void
noops(void)
{
- Prog *p, *q, *q1, *q2, orig;
+ Prog *p, *q, *q1, *q2;
int o;
Sym *tlsfallback, *gmsym;
break;
if(p->to.type != D_REG)
break;
-
- orig = *p;
+ q1 = p;
- /* MOV a,4(M) */
+ /* MOV a,4(SP) */
+ p = appendp(p);
p->as = AMOVW;
- p->line = orig.line;
+ p->line = q1->line;
p->from.type = D_REG;
- p->from.reg = orig.from.reg;
- p->reg = NREG;
+ p->from.reg = q1->from.reg;
p->to.type = D_OREG;
- p->to.reg = REGM;
+ p->to.reg = REGSP;
p->to.offset = 4;
/* MOV b,REGTMP */
p = appendp(p);
p->as = AMOVW;
- p->line = orig.line;
+ p->line = q1->line;
p->from.type = D_REG;
- p->from.reg = orig.reg;
- if(orig.reg == NREG)
- p->from.reg = orig.to.reg;
+ p->from.reg = q1->reg;
+ if(q1->reg == NREG)
+ p->from.reg = q1->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 = orig.line;
+ p->line = q1->line;
p->to.type = D_BRANCH;
p->cond = p;
switch(o) {
/* MOV REGTMP, b */
p = appendp(p);
p->as = AMOVW;
- p->line = orig.line;
+ p->line = q1->line;
p->from.type = D_REG;
p->from.reg = REGTMP;
p->from.offset = 0;
p->to.type = D_REG;
- p->to.reg = orig.to.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;
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-0
+TEXT udiv<>(SB),NOSPLIT,$-4
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:
- MOVW $runtime·panicdivide(SB),R11
- B (R11)
+ // 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)
TEXT fast_udiv_tab<>(SB),NOSPLIT,$-4
// var tab [64]byte
// expects the result in R(TMP)
TMP = 11
-TEXT _divu(SB), NOSPLIT, $16-0
+TEXT _divu(SB), NOSPLIT, $16
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 m_divmod(m), R(q) /* denominator */
- MOVW $0, R(s)
- MOVW R(s), m_divmod(m)
+ MOVW 0(FP), R(q) /* denominator */
BL udiv<>(SB)
MOVW R(q), R(TMP)
MOVW 4(R13), R(q)
MOVW 16(R13), R(M)
RET
-TEXT _modu(SB), NOSPLIT, $16-0
+TEXT _modu(SB), NOSPLIT, $16
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 m_divmod(m), R(q) /* denominator */
- MOVW $0, R(s)
- MOVW R(s), m_divmod(m)
+ MOVW 0(FP), R(q) /* denominator */
BL udiv<>(SB)
MOVW R(r), R(TMP)
MOVW 4(R13), R(q)
MOVW 16(R13), R(M)
RET
-TEXT _div(SB),NOSPLIT,$16-0
+TEXT _div(SB),NOSPLIT,$16
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 m_divmod(m), R(q) /* denominator */
- MOVW $0, R(s)
- MOVW R(s), m_divmod(m)
+ MOVW 0(FP), R(q) /* denominator */
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-0
+TEXT _mod(SB),NOSPLIT,$16
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 m_divmod(m), R(q) /* denominator */
- MOVW $0, R(s)
- MOVW R(s), m_divmod(m)
+ MOVW 0(FP), R(q) /* denominator */
CMP $0, R(q)
RSB.LT $0, R(q), R(q)
CMP $0, R(r)