var prologueEnd *obj.Prog
aoffset := c.autosize
- if aoffset > 0xF0 {
- aoffset = 0xF0
+ if aoffset > 0x1f0 {
+ // LDP offset variant range is -512 to 504, SP should be 16-byte aligned,
+ // so the maximum aoffset value is 496.
+ aoffset = 0x1f0
}
// Frame is non-empty. Make sure to save link register, even if
// it is a leaf function, so that traceback works.
q = p
if c.autosize > aoffset {
- // Frame size is too large for a MOVD.W instruction.
- // Store link register before decrementing SP, so if a signal comes
- // during the execution of the function prologue, the traceback
- // code will not see a half-updated stack frame.
- // This sequence is not async preemptible, as if we open a frame
- // at the current SP, it will clobber the saved LR.
- q = c.ctxt.StartUnsafePoint(q, c.newprog)
+ // Frame size is too large for a STP instruction. Store the frame pointer
+ // register and link register before decrementing SP, so if a signal comes
+ // during the execution of the function prologue, the traceback code will
+ // not see a half-updated stack frame.
- q = obj.Appendp(q, c.newprog)
- q.Pos = p.Pos
- q.As = ASUB
- q.From.Type = obj.TYPE_CONST
- q.From.Offset = int64(c.autosize)
- q.Reg = REGSP
- q.To.Type = obj.TYPE_REG
- q.To.Reg = REGTMP
+ // SUB $autosize, RSP, R20
+ q1 = obj.Appendp(q, c.newprog)
+ q1.Pos = p.Pos
+ q1.As = ASUB
+ q1.From.Type = obj.TYPE_CONST
+ q1.From.Offset = int64(c.autosize)
+ q1.Reg = REGSP
+ q1.To.Type = obj.TYPE_REG
+ q1.To.Reg = REG_R20
- prologueEnd = q
+ prologueEnd = q1
- q = obj.Appendp(q, c.newprog)
- q.Pos = p.Pos
- q.As = AMOVD
- q.From.Type = obj.TYPE_REG
- q.From.Reg = REGLINK
- q.To.Type = obj.TYPE_MEM
- q.To.Reg = REGTMP
+ // STP (R29, R30), -8(R20)
+ q1 = obj.Appendp(q1, c.newprog)
+ q1.Pos = p.Pos
+ q1.As = ASTP
+ q1.From.Type = obj.TYPE_REGREG
+ q1.From.Reg = REGFP
+ q1.From.Offset = REGLINK
+ q1.To.Type = obj.TYPE_MEM
+ q1.To.Reg = REG_R20
+ q1.To.Offset = -8
- q1 = obj.Appendp(q, c.newprog)
+ // This is not async preemptible, as if we open a frame
+ // at the current SP, it will clobber the saved LR.
+ q1 = c.ctxt.StartUnsafePoint(q1, c.newprog)
+
+ // MOVD R20, RSP
+ q1 = obj.Appendp(q1, c.newprog)
q1.Pos = p.Pos
q1.As = AMOVD
q1.From.Type = obj.TYPE_REG
- q1.From.Reg = REGTMP
+ q1.From.Reg = REG_R20
q1.To.Type = obj.TYPE_REG
q1.To.Reg = REGSP
q1.Spadj = c.autosize
+ q1 = c.ctxt.EndUnsafePoint(q1, c.newprog, -1)
+
if buildcfg.GOOS == "ios" {
// iOS does not support SA_ONSTACK. We will run the signal handler
// on the G stack. If we write below SP, it may be clobbered by
- // the signal handler. So we save LR after decrementing SP.
+ // the signal handler. So we save FP and LR after decrementing SP.
+ // STP (R29, R30), -8(RSP)
q1 = obj.Appendp(q1, c.newprog)
q1.Pos = p.Pos
- q1.As = AMOVD
- q1.From.Type = obj.TYPE_REG
- q1.From.Reg = REGLINK
+ q1.As = ASTP
+ q1.From.Type = obj.TYPE_REGREG
+ q1.From.Reg = REGFP
+ q1.From.Offset = REGLINK
q1.To.Type = obj.TYPE_MEM
q1.To.Reg = REGSP
+ q1.To.Offset = -8
}
-
- q1 = c.ctxt.EndUnsafePoint(q1, c.newprog, -1)
} else {
- // small frame, update SP and save LR in a single MOVD.W instruction
+ // small frame, save FP and LR with one STP instruction, then update SP.
+ // Store first, so if a signal comes during the execution of the function
+ // prologue, the traceback code will not see a half-updated stack frame.
+ // STP (R29, R30), -aoffset-8(RSP)
q1 = obj.Appendp(q, c.newprog)
- q1.As = AMOVD
+ q1.As = ASTP
q1.Pos = p.Pos
- q1.From.Type = obj.TYPE_REG
- q1.From.Reg = REGLINK
+ q1.From.Type = obj.TYPE_REGREG
+ q1.From.Reg = REGFP
+ q1.From.Offset = REGLINK
q1.To.Type = obj.TYPE_MEM
- q1.Scond = C_XPRE
- q1.To.Offset = int64(-aoffset)
+ q1.To.Offset = int64(-aoffset - 8)
q1.To.Reg = REGSP
- q1.Spadj = aoffset
prologueEnd = q1
+
+ q1 = c.ctxt.StartUnsafePoint(q1, c.newprog)
+ // This instruction is not async preemptible, see the above comment.
+ // SUB $aoffset, RSP, RSP
+ q1 = obj.Appendp(q1, c.newprog)
+ q1.Pos = p.Pos
+ q1.As = ASUB
+ q1.From.Type = obj.TYPE_CONST
+ q1.From.Offset = int64(aoffset)
+ q1.Reg = REGSP
+ q1.To.Type = obj.TYPE_REG
+ q1.To.Reg = REGSP
+ q1.Spadj = aoffset
+
+ q1 = c.ctxt.EndUnsafePoint(q1, c.newprog, -1)
+
+ if buildcfg.GOOS == "ios" {
+ // See the above comment.
+ // STP (R29, R30), -8(RSP)
+ q1 = obj.Appendp(q1, c.newprog)
+ q1.As = ASTP
+ q1.Pos = p.Pos
+ q1.From.Type = obj.TYPE_REGREG
+ q1.From.Reg = REGFP
+ q1.From.Offset = REGLINK
+ q1.To.Type = obj.TYPE_MEM
+ q1.To.Offset = int64(-8)
+ q1.To.Reg = REGSP
+ }
}
prologueEnd.Pos = prologueEnd.Pos.WithXlogue(src.PosPrologueEnd)
- // Frame pointer.
- q1 = obj.Appendp(q1, c.newprog)
- q1.Pos = p.Pos
- q1.As = AMOVD
- q1.From.Type = obj.TYPE_REG
- q1.From.Reg = REGFP
- q1.To.Type = obj.TYPE_MEM
- q1.To.Reg = REGSP
- q1.To.Offset = -8
-
q1 = obj.Appendp(q1, c.newprog)
q1.Pos = p.Pos
q1.As = ASUB
p.To.Reg = REGFP
}
} else {
- /* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/
-
- // Frame pointer.
- p.As = AMOVD
+ aoffset := c.autosize
+ // LDP -8(RSP), (R29, R30)
+ p.As = ALDP
p.From.Type = obj.TYPE_MEM
- p.From.Reg = REGSP
p.From.Offset = -8
- p.To.Type = obj.TYPE_REG
+ p.From.Reg = REGSP
+ p.To.Type = obj.TYPE_REGREG
p.To.Reg = REGFP
- p = obj.Appendp(p, c.newprog)
-
- aoffset := c.autosize
+ p.To.Offset = REGLINK
- if aoffset <= 0xF0 {
- p.As = AMOVD
- p.From.Type = obj.TYPE_MEM
- p.Scond = C_XPOST
- p.From.Offset = int64(aoffset)
- p.From.Reg = REGSP
- p.To.Type = obj.TYPE_REG
- p.To.Reg = REGLINK
- p.Spadj = -aoffset
- } else {
- p.As = AMOVD
- p.From.Type = obj.TYPE_MEM
- p.From.Offset = 0
- p.From.Reg = REGSP
- p.To.Type = obj.TYPE_REG
- p.To.Reg = REGLINK
-
- q = newprog()
- q.As = AADD
- q.From.Type = obj.TYPE_CONST
- q.From.Offset = int64(aoffset)
- q.To.Type = obj.TYPE_REG
- q.To.Reg = REGSP
- q.Link = p.Link
- q.Spadj = int32(-q.From.Offset)
- q.Pos = p.Pos
- p.Link = q
- p = q
- }
+ // ADD $aoffset, RSP, RSP
+ q = newprog()
+ q.As = AADD
+ q.From.Type = obj.TYPE_CONST
+ q.From.Offset = int64(aoffset)
+ q.To.Type = obj.TYPE_REG
+ q.To.Reg = REGSP
+ q.Spadj = -aoffset
+ q.Pos = p.Pos
+ q.Link = p.Link
+ p.Link = q
+ p = q
}
// If enabled, this code emits 'MOV PC, R27' before every 'MOV LR, PC',