void
noops(void)
{
- Prog *p, *q, *q1, *q2;
+ Prog *p, *q, *q1, *q2, orig;
int o;
Sym *tlsfallback, *gmsym;
break;
if(p->to.type != D_REG)
break;
- q1 = p;
+
+ orig = *p;
- /* MOV a,4(SP) */
- p = appendp(p);
+ /* MOV a,4(M) */
p->as = AMOVW;
- p->line = q1->line;
+ p->line = orig.line;
p->from.type = D_REG;
- p->from.reg = q1->from.reg;
+ p->from.reg = orig.from.reg;
+ p->reg = NREG;
p->to.type = D_OREG;
- p->to.reg = REGSP;
+ p->to.reg = REGM;
p->to.offset = 4;
/* MOV b,REGTMP */
p = appendp(p);
p->as = AMOVW;
- p->line = q1->line;
+ p->line = orig.line;
p->from.type = D_REG;
- p->from.reg = q1->reg;
- if(q1->reg == NREG)
- p->from.reg = q1->to.reg;
+ p->from.reg = orig.reg;
+ if(orig.reg == NREG)
+ p->from.reg = orig.to.reg;
p->to.type = D_REG;
p->to.reg = REGTMP;
p->to.offset = 0;
/* CALL appropriate */
p = appendp(p);
p->as = ABL;
- p->line = q1->line;
+ p->line = orig.line;
p->to.type = D_BRANCH;
p->cond = p;
switch(o) {
/* MOV REGTMP, b */
p = appendp(p);
p->as = AMOVW;
- p->line = q1->line;
+ p->line = orig.line;
p->from.type = D_REG;
p->from.reg = REGTMP;
p->from.offset = 0;
p->to.type = D_REG;
- p->to.reg = q1->to.reg;
-
- /* ADD $8,SP */
- p = appendp(p);
- p->as = AADD;
- p->line = q1->line;
- p->from.type = D_CONST;
- p->from.reg = NREG;
- p->from.offset = 8;
- p->reg = NREG;
- p->to.type = D_REG;
- p->to.reg = REGSP;
- p->spadj = -8;
-
- /* SUB $8,SP */
- q1->as = ASUB;
- q1->from.type = D_CONST;
- q1->from.offset = 8;
- q1->from.reg = NREG;
- q1->reg = NREG;
- q1->to.type = D_REG;
- q1->to.reg = REGSP;
- q1->spadj = 8;
+ p->to.reg = orig.to.reg;
break;
case AMOVW:
"bytes"
"fmt"
"hash/crc32"
+ "math/big"
"os/exec"
"regexp"
"runtime"
}
})
+ if len(need) == 0 {
+ return
+ }
+
var total uintptr
for i, name := range need {
total += have[i]
}
}
+// Test that profiling of division operations is okay, especially on ARM. See issue 6681.
+func TestMathBigDivide(t *testing.T) {
+ testCPUProfile(t, nil, func() {
+ t := time.After(5 * time.Second)
+ pi := new(big.Int)
+ for {
+ for i := 0; i < 100; i++ {
+ n := big.NewInt(2646693125139304345)
+ d := big.NewInt(842468587426513207)
+ pi.Div(n, d)
+ }
+ select {
+ case <-t:
+ return
+ default:
+ }
+ }
+ })
+}
+
// Operating systems that are expected to fail the tests. See issue 6047.
var badOS = map[string]bool{
"darwin": true,
M = 3
a = 11
// Be careful: R(a) == R11 will be used by the linker for synthesized instructions.
-TEXT udiv<>(SB),NOSPLIT,$-4
+TEXT udiv<>(SB),NOSPLIT,$-4-0
CLZ R(q), R(s) // find normalizing shift
MOVW.S R(q)<<R(s), R(a)
MOVW $fast_udiv_tab<>-64(SB), R(M)
RET
udiv_by_0:
- // The ARM toolchain expects it can emit references to DIV and MOD
- // instructions. The linker rewrites each pseudo-instruction into
- // a sequence that pushes two values onto the stack and then calls
- // _divu, _modu, _div, or _mod (below), all of which have a 16-byte
- // frame plus the saved LR. The traceback routine knows the expanded
- // stack frame size at the pseudo-instruction call site, but it
- // doesn't know that the frame has a non-standard layout. In particular,
- // it expects to find a saved LR in the bottom word of the frame.
- // Unwind the stack back to the pseudo-instruction call site, copy the
- // saved LR where the traceback routine will look for it, and make it
- // appear that panicdivide was called from that PC.
- MOVW 0(R13), LR
- ADD $20, R13
- MOVW 8(R13), R1 // actual saved LR
- MOVW R1, 0(R13) // expected here for traceback
- B runtime·panicdivide(SB)
+ MOVW $runtime·panicdivide(SB),R11
+ B (R11)
TEXT fast_udiv_tab<>(SB),NOSPLIT,$-4
// var tab [64]byte
// expects the result in R(TMP)
TMP = 11
-TEXT _divu(SB), NOSPLIT, $16
+TEXT _divu(SB), NOSPLIT, $16-0
MOVW R(q), 4(R13)
MOVW R(r), 8(R13)
MOVW R(s), 12(R13)
MOVW R(M), 16(R13)
MOVW R(TMP), R(r) /* numerator */
- MOVW 0(FP), R(q) /* denominator */
+ MOVW m_divmod(m), R(q) /* denominator */
+ MOVW $0, R(s)
+ MOVW R(s), m_divmod(m)
BL udiv<>(SB)
MOVW R(q), R(TMP)
MOVW 4(R13), R(q)
MOVW 16(R13), R(M)
RET
-TEXT _modu(SB), NOSPLIT, $16
+TEXT _modu(SB), NOSPLIT, $16-0
MOVW R(q), 4(R13)
MOVW R(r), 8(R13)
MOVW R(s), 12(R13)
MOVW R(M), 16(R13)
MOVW R(TMP), R(r) /* numerator */
- MOVW 0(FP), R(q) /* denominator */
+ MOVW m_divmod(m), R(q) /* denominator */
+ MOVW $0, R(s)
+ MOVW R(s), m_divmod(m)
BL udiv<>(SB)
MOVW R(r), R(TMP)
MOVW 4(R13), R(q)
MOVW 16(R13), R(M)
RET
-TEXT _div(SB),NOSPLIT,$16
+TEXT _div(SB),NOSPLIT,$16-0
MOVW R(q), 4(R13)
MOVW R(r), 8(R13)
MOVW R(s), 12(R13)
MOVW R(M), 16(R13)
MOVW R(TMP), R(r) /* numerator */
- MOVW 0(FP), R(q) /* denominator */
+ MOVW m_divmod(m), R(q) /* denominator */
+ MOVW $0, R(s)
+ MOVW R(s), m_divmod(m)
CMP $0, R(r)
BGE d1
RSB $0, R(r), R(r)
RSB $0, R(q), R(TMP)
B out
-TEXT _mod(SB),NOSPLIT,$16
+TEXT _mod(SB),NOSPLIT,$16-0
MOVW R(q), 4(R13)
MOVW R(r), 8(R13)
MOVW R(s), 12(R13)
MOVW R(M), 16(R13)
MOVW R(TMP), R(r) /* numerator */
- MOVW 0(FP), R(q) /* denominator */
+ MOVW m_divmod(m), R(q) /* denominator */
+ MOVW $0, R(s)
+ MOVW R(s), m_divmod(m)
CMP $0, R(q)
RSB.LT $0, R(q), R(q)
CMP $0, R(r)