}
case ADIV, ADIVU, AMOD, AMODU:
+ if cursym.Text.From3.Offset&obj.NOSPLIT != 0 {
+ ctxt.Diag("cannot divide in NOSPLIT function")
+ }
if ctxt.Debugdivmod != 0 {
break
}
if p.To.Type != obj.TYPE_REG {
break
}
- q1 = p
- /* MOV a,4(SP) */
- p = obj.Appendp(ctxt, p)
+ // Make copy because we overwrite p below.
+ q1 := *p
+ if q1.Reg == REGTMP || q1.Reg == 0 && q1.To.Reg == REGTMP {
+ ctxt.Diag("div already using REGTMP: %v", p)
+ }
+ /* MOV m(g),REGTMP */
+ p.As = AMOVW
+ p.Lineno = q1.Lineno
+ p.From.Type = obj.TYPE_MEM
+ p.From.Reg = REGG
+ p.From.Offset = 6 * 4 // offset of g.m
+ p.Reg = 0
+ p.To.Type = obj.TYPE_REG
+ p.To.Reg = REGTMP
+
+ /* MOV a,m_divmod(REGTMP) */
+ p = obj.Appendp(ctxt, p)
p.As = AMOVW
p.Lineno = q1.Lineno
p.From.Type = obj.TYPE_REG
p.From.Reg = q1.From.Reg
p.To.Type = obj.TYPE_MEM
- p.To.Reg = REGSP
- p.To.Offset = 4
+ p.To.Reg = REGTMP
+ p.To.Offset = 8 * 4 // offset of m.divmod
/* MOV b,REGTMP */
p = obj.Appendp(ctxt, p)
-
p.As = AMOVW
p.Lineno = q1.Lineno
p.From.Type = obj.TYPE_REG
/* CALL appropriate */
p = obj.Appendp(ctxt, p)
-
p.As = ABL
p.Lineno = q1.Lineno
p.To.Type = obj.TYPE_BRANCH
/* MOV REGTMP, b */
p = obj.Appendp(ctxt, p)
-
p.As = AMOVW
p.Lineno = q1.Lineno
p.From.Type = obj.TYPE_REG
p.To.Type = obj.TYPE_REG
p.To.Reg = q1.To.Reg
- /* ADD $8,SP */
- p = obj.Appendp(ctxt, p)
-
- p.As = AADD
- p.Lineno = q1.Lineno
- p.From.Type = obj.TYPE_CONST
- p.From.Reg = 0
- p.From.Offset = 8
- p.Reg = 0
- p.To.Type = obj.TYPE_REG
- p.To.Reg = REGSP
- p.Spadj = -8
-
- /* Keep saved LR at 0(SP) after SP change. */
- /* MOVW 0(SP), REGTMP; MOVW REGTMP, -8!(SP) */
- /* TODO: Remove SP adjustments; see issue 6699. */
- q1.As = AMOVW
-
- q1.From.Type = obj.TYPE_MEM
- q1.From.Reg = REGSP
- q1.From.Offset = 0
- q1.Reg = 0
- q1.To.Type = obj.TYPE_REG
- q1.To.Reg = REGTMP
-
- /* SUB $8,SP */
- q1 = obj.Appendp(ctxt, q1)
-
- q1.As = AMOVW
- q1.From.Type = obj.TYPE_REG
- q1.From.Reg = REGTMP
- q1.Reg = 0
- q1.To.Type = obj.TYPE_MEM
- q1.To.Reg = REGSP
- q1.To.Offset = -8
- q1.Scond |= C_WBIT
- q1.Spadj = 8
-
case AMOVW:
if (p.Scond&C_WBIT != 0) && p.To.Type == obj.TYPE_MEM && p.To.Reg == REGSP {
p.Spadj = int32(-p.To.Offset)
_panic *_panic // innermost panic - offset known to liblink
_defer *_defer // innermost defer
+ m *m // current m; offset known to arm liblink
stackAlloc uintptr // stack allocation is [stack.lo,stack.lo+stackAlloc)
sched gobuf
syscallsp uintptr // if status==Gsyscall, syscallsp = sched.sp to use during gc
sysblocktraced bool // StartTrace has emitted EvGoInSyscall about this goroutine
sysexitticks int64 // cputicks when syscall has returned (for tracing)
sysexitseq uint64 // trace seq when syscall has returned (for tracing)
- m *m // for debuggers, but offset not hard-coded
lockedm *m
sig uint32
writebuf []byte
}
type m struct {
- g0 *g // goroutine with scheduling stack
- morebuf gobuf // gobuf arg to morestack
+ g0 *g // goroutine with scheduling stack
+ morebuf gobuf // gobuf arg to morestack
+ divmod uint32 // div/mod denominator for arm - known to liblink
// Fields not known to debuggers.
procid uint64 // for debuggers, but offset not hard-coded
#include "go_asm.h"
#include "go_tls.h"
+#include "funcdata.h"
#include "textflag.h"
/* replaced use of R10 by R11 because the former can be the data segment base register */
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)
// var tab [64]byte
// tab[0] = 255; for i := 1; i <= 63; i++ { tab[i] = (1<<14)/(64+i) }
// expects the result in RTMP
#define RTMP R11
-TEXT _divu(SB), NOSPLIT, $16
+TEXT _divu(SB), NOSPLIT, $16-0
+ // It's not strictly true that there are no local pointers.
+ // It could be that the saved registers Rq, Rr, Rs, and Rm
+ // contain pointers. However, the only way this can matter
+ // is if the stack grows (which it can't, udiv is nosplit)
+ // or if a fault happens and more frames are added to
+ // the stack due to deferred functions.
+ // In the latter case, the stack can grow arbitrarily,
+ // and garbage collection can happen, and those
+ // operations care about pointers, but in that case
+ // the calling frame is dead, and so are the saved
+ // registers. So we can claim there are no pointers here.
+ NO_LOCAL_POINTERS
MOVW Rq, 4(R13)
MOVW Rr, 8(R13)
MOVW Rs, 12(R13)
MOVW RM, 16(R13)
MOVW RTMP, Rr /* numerator */
- MOVW den+0(FP), Rq /* denominator */
+ MOVW g_m(g), Rq
+ MOVW m_divmod(Rq), Rq /* denominator */
BL udiv<>(SB)
MOVW Rq, RTMP
MOVW 4(R13), Rq
MOVW 16(R13), RM
RET
-TEXT _modu(SB), NOSPLIT, $16
+TEXT _modu(SB), NOSPLIT, $16-0
+ NO_LOCAL_POINTERS
MOVW Rq, 4(R13)
MOVW Rr, 8(R13)
MOVW Rs, 12(R13)
MOVW RM, 16(R13)
MOVW RTMP, Rr /* numerator */
- MOVW den+0(FP), Rq /* denominator */
+ MOVW g_m(g), Rq
+ MOVW m_divmod(Rq), Rq /* denominator */
BL udiv<>(SB)
MOVW Rr, RTMP
MOVW 4(R13), Rq
MOVW 16(R13), RM
RET
-TEXT _div(SB),NOSPLIT,$16
+TEXT _div(SB),NOSPLIT,$16-0
+ NO_LOCAL_POINTERS
MOVW Rq, 4(R13)
MOVW Rr, 8(R13)
MOVW Rs, 12(R13)
MOVW RM, 16(R13)
MOVW RTMP, Rr /* numerator */
- MOVW den+0(FP), Rq /* denominator */
+ MOVW g_m(g), Rq
+ MOVW m_divmod(Rq), Rq /* denominator */
CMP $0, Rr
BGE d1
RSB $0, Rr, Rr
MOVW 16(R13), RM
RET
-TEXT _mod(SB),NOSPLIT,$16
+TEXT _mod(SB),NOSPLIT,$16-0
+ NO_LOCAL_POINTERS
MOVW Rq, 4(R13)
MOVW Rr, 8(R13)
MOVW Rs, 12(R13)
MOVW RM, 16(R13)
MOVW RTMP, Rr /* numerator */
- MOVW den+0(FP), Rq /* denominator */
+ MOVW g_m(g), Rq
+ MOVW m_divmod(Rq), Rq /* denominator */
CMP $0, Rq
RSB.LT $0, Rq, Rq
CMP $0, Rr