var q *obj.Prog
if framesize <= abi.StackSmall {
// small stack: SP < stackguard
- // AGTU SP, stackguard, R20
+ // SGTU SP, stackguard, R20
p = obj.Appendp(p, c.newprog)
p.As = ASGTU
p.To.Reg = REG_R20
}
- // q1: BNE R20, done
+ // q1: BEQ R20, morestack
p = obj.Appendp(p, c.newprog)
q1 := p
- p.As = ABNE
+ p.As = ABEQ
p.From.Type = obj.TYPE_REG
p.From.Reg = REG_R20
p.To.Type = obj.TYPE_BRANCH
p.Mark |= BRANCH
- // MOV LINK, R31
- p = obj.Appendp(p, c.newprog)
+ end := c.ctxt.EndUnsafePoint(p, c.newprog, -1)
+
+ var last *obj.Prog
+ for last = c.cursym.Func().Text; last.Link != nil; last = last.Link {
+ }
+ // Now we are at the end of the function, but logically
+ // we are still in function prologue. We need to fix the
+ // SP data and PCDATA.
+ spfix := obj.Appendp(last, c.newprog)
+ spfix.As = obj.ANOP
+ spfix.Spadj = -framesize
+
+ pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog)
+ pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog)
+
+ if q != nil {
+ q.To.SetTarget(pcdata)
+ }
+ q1.To.SetTarget(pcdata)
+
+ p = c.cursym.Func().SpillRegisterArgs(pcdata, c.newprog)
+
+ // MOV LINK, R31
+ p = obj.Appendp(p, c.newprog)
p.As = mov
p.From.Type = obj.TYPE_REG
p.From.Reg = REGLINK
p.Mark |= LABEL
}
- p = c.ctxt.EmitEntryStackMap(c.cursym, p, c.newprog)
-
- // Spill the register args that could be clobbered by the
- // morestack code
- p = c.cursym.Func().SpillRegisterArgs(p, c.newprog)
+ // JAL runtime.morestack(SB)
+ call := obj.Appendp(p, c.newprog)
+ call.As = AJAL
+ call.To.Type = obj.TYPE_BRANCH
- // JAL runtime.morestack(SB)
- p = obj.Appendp(p, c.newprog)
-
- p.As = AJAL
- p.To.Type = obj.TYPE_BRANCH
if c.cursym.CFunc() {
- p.To.Sym = c.ctxt.Lookup("runtime.morestackc")
+ call.To.Sym = c.ctxt.Lookup("runtime.morestackc")
} else if !c.cursym.Func().Text.From.Sym.NeedCtxt() {
- p.To.Sym = c.ctxt.Lookup("runtime.morestack_noctxt")
+ call.To.Sym = c.ctxt.Lookup("runtime.morestack_noctxt")
} else {
- p.To.Sym = c.ctxt.Lookup("runtime.morestack")
+ call.To.Sym = c.ctxt.Lookup("runtime.morestack")
}
- p.Mark |= BRANCH
-
- p = c.cursym.Func().UnspillRegisterArgs(p, c.newprog)
- p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
+ call.Mark |= BRANCH
- // JMP start
- p = obj.Appendp(p, c.newprog)
-
- p.As = AJMP
- p.To.Type = obj.TYPE_BRANCH
- p.To.SetTarget(startPred.Link)
- startPred.Link.Mark |= LABEL
- p.Mark |= BRANCH
-
- // placeholder for q1's jump target
- p = obj.Appendp(p, c.newprog)
+ // The instructions which unspill regs should be preemptible.
+ pcdata = c.ctxt.EndUnsafePoint(call, c.newprog, -1)
+ unspill := c.cursym.Func().UnspillRegisterArgs(pcdata, c.newprog)
- p.As = obj.ANOP // zero-width place holder
- q1.To.SetTarget(p)
+ // JMP start
+ jmp := obj.Appendp(unspill, c.newprog)
+ jmp.As = AJMP
+ jmp.To.Type = obj.TYPE_BRANCH
+ jmp.To.SetTarget(startPred.Link)
+ jmp.Spadj = +framesize
- return p
+ return end
}
func (c *ctxt0) addnop(p *obj.Prog) {