// cmd/7l/noop.c, cmd/7l/obj.c, cmd/ld/pass.c from Vita Nuova.
-// https://code.google.com/p/ken-cc/source/browse/
+// https://bitbucket.org/plan9-from-bell-labs/9-cc/src/master/
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
"cmd/internal/objabi"
"cmd/internal/src"
"cmd/internal/sys"
+ "internal/abi"
"internal/buildcfg"
"log"
"math"
)
-var complements = []obj.As{
- AADD: ASUB,
- AADDW: ASUBW,
- ASUB: AADD,
- ASUBW: AADDW,
- ACMP: ACMN,
- ACMPW: ACMNW,
- ACMN: ACMP,
- ACMNW: ACMPW,
-}
-
-// noZRreplace is the set of instructions for which $0 in the To operand
-// should NOT be replaced with REGZERO.
-var noZRreplace = map[obj.As]bool{
- APRFM: true,
+// zrReplace is the set of instructions for which $0 in the From operand
+// should be replaced with REGZERO.
+var zrReplace = map[obj.As]bool{
+ AMOVD: true,
+ AMOVW: true,
+ AMOVWU: true,
+ AMOVH: true,
+ AMOVHU: true,
+ AMOVB: true,
+ AMOVBU: true,
+ ASBC: true,
+ ASBCW: true,
+ ASBCS: true,
+ ASBCSW: true,
+ AADC: true,
+ AADCW: true,
+ AADCS: true,
+ AADCSW: true,
+ AFMOVD: true,
+ AFMOVS: true,
+ AMSR: true,
}
func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
p = c.ctxt.StartUnsafePoint(p, c.newprog)
q := (*obj.Prog)(nil)
- if framesize <= objabi.StackSmall {
+ if framesize <= abi.StackSmall {
// small stack: SP < stackguard
// CMP stackguard, SP
p.From.Type = obj.TYPE_REG
p.From.Reg = REGRT1
p.Reg = REGSP
- } else if framesize <= objabi.StackBig {
+ } else if framesize <= abi.StackBig {
// large stack: SP-framesize < stackguard-StackSmall
// SUB $(framesize-StackSmall), SP, RT2
// CMP stackguard, RT2
p.As = ASUB
p.From.Type = obj.TYPE_CONST
- p.From.Offset = int64(framesize) - objabi.StackSmall
+ p.From.Offset = int64(framesize) - abi.StackSmall
p.Reg = REGSP
p.To.Type = obj.TYPE_REG
p.To.Reg = REGRT2
p = obj.Appendp(p, c.newprog)
p.As = ASUBS
p.From.Type = obj.TYPE_CONST
- p.From.Offset = int64(framesize) - objabi.StackSmall
+ p.From.Offset = int64(framesize) - abi.StackSmall
p.Reg = REGSP
p.To.Type = obj.TYPE_REG
p.To.Reg = REGRT2
}
call.To.Sym = c.ctxt.Lookup(morestack)
- unspill := c.cursym.Func().UnspillRegisterArgs(call, c.newprog)
- pcdata = c.ctxt.EndUnsafePoint(unspill, c.newprog, -1)
+ // The instructions which unspill regs should be preemptible.
+ pcdata = c.ctxt.EndUnsafePoint(call, c.newprog, -1)
+ unspill := c.cursym.Func().UnspillRegisterArgs(pcdata, c.newprog)
// B start
- jmp := obj.Appendp(pcdata, c.newprog)
+ jmp := obj.Appendp(unspill, c.newprog)
jmp.As = AB
jmp.To.Type = obj.TYPE_BRANCH
jmp.To.SetTarget(startPred.Link)
p.From.Class = 0
p.To.Class = 0
- // $0 results in C_ZCON, which matches both C_REG and various
- // C_xCON, however the C_REG cases in asmout don't expect a
- // constant, so they will use the register fields and assemble
- // a R0. To prevent that, rewrite $0 as ZR.
- if p.From.Type == obj.TYPE_CONST && p.From.Offset == 0 {
+ // Previously we rewrote $0 to ZR, but we have now removed this change.
+ // In order to be compatible with some previous legal instruction formats,
+ // reserve the previous conversion for some specific instructions.
+ if p.From.Type == obj.TYPE_CONST && p.From.Offset == 0 && zrReplace[p.As] {
p.From.Type = obj.TYPE_REG
p.From.Reg = REGZERO
}
- if p.To.Type == obj.TYPE_CONST && p.To.Offset == 0 && !noZRreplace[p.As] {
- p.To.Type = obj.TYPE_REG
- p.To.Reg = REGZERO
- }
// Rewrite BR/BL to symbol as TYPE_BRANCH.
switch p.As {
break
}
- // Rewrite float constants to values stored in memory.
+ // Rewrite float and vector constants to values stored in memory.
switch p.As {
+ case AVMOVS:
+ if p.From.Type == obj.TYPE_CONST {
+ p.From.Type = obj.TYPE_MEM
+ p.From.Sym = c.ctxt.Int32Sym(p.From.Offset)
+ p.From.Name = obj.NAME_EXTERN
+ p.From.Offset = 0
+ }
+
+ case AVMOVD:
+ if p.From.Type == obj.TYPE_CONST {
+ p.From.Type = obj.TYPE_MEM
+ p.From.Sym = c.ctxt.Int64Sym(p.From.Offset)
+ p.From.Name = obj.NAME_EXTERN
+ p.From.Offset = 0
+ }
+
+ case AVMOVQ:
+ if p.From.Type == obj.TYPE_CONST {
+ p.From.Type = obj.TYPE_MEM
+ p.From.Sym = c.ctxt.Int128Sym(p.GetFrom3().Offset, p.From.Offset)
+ p.From.Name = obj.NAME_EXTERN
+ p.From.Offset = 0
+ p.RestArgs = nil
+ }
+
case AFMOVS:
if p.From.Type == obj.TYPE_FCONST {
f64 := p.From.Val.(float64)
p.From.Name = obj.NAME_EXTERN
p.From.Offset = 0
}
-
- break
- }
-
- // Rewrite negative immediates as positive immediates with
- // complementary instruction.
- switch p.As {
- case AADD, ASUB, ACMP, ACMN:
- if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && p.From.Offset != -1<<63 {
- p.From.Offset = -p.From.Offset
- p.As = complements[p.As]
- }
- case AADDW, ASUBW, ACMPW, ACMNW:
- if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && int32(p.From.Offset) != -1<<31 {
- p.From.Offset = -p.From.Offset
- p.As = complements[p.As]
- }
}
if c.ctxt.Flag_dynlink {
}
}
- if p.Mark&LEAF != 0 && c.autosize < objabi.StackSmall {
+ if p.Mark&LEAF != 0 && c.autosize < abi.StackSmall {
// A leaf function with a small stack can be marked
// NOSPLIT, avoiding a stack check.
p.From.Sym.Set(obj.AttrNoSplit, true)
p.To = obj.Addr{}
if c.cursym.Func().Text.Mark&LEAF != 0 {
if c.autosize != 0 {
+ // Restore frame pointer.
+ // ADD $framesize-8, RSP, R29
p.As = AADD
p.From.Type = obj.TYPE_CONST
- p.From.Offset = int64(c.autosize)
+ p.From.Offset = int64(c.autosize) - 8
+ p.Reg = REGSP
p.To.Type = obj.TYPE_REG
- p.To.Reg = REGSP
- p.Spadj = -c.autosize
+ p.To.Reg = REGFP
- // Frame pointer.
+ // Pop stack frame.
+ // ADD $framesize, RSP, RSP
p = obj.Appendp(p, c.newprog)
- p.As = ASUB
+ p.As = AADD
p.From.Type = obj.TYPE_CONST
- p.From.Offset = 8
- p.Reg = REGSP
+ p.From.Offset = int64(c.autosize)
p.To.Type = obj.TYPE_REG
- p.To.Reg = REGFP
+ p.To.Reg = REGSP
+ p.Spadj = -c.autosize
}
} else {
aoffset := c.autosize
if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 {
f := c.cursym.Func()
- if f.FuncFlag&objabi.FuncFlag_SPWRITE == 0 {
- c.cursym.Func().FuncFlag |= objabi.FuncFlag_SPWRITE
+ if f.FuncFlag&abi.FuncFlagSPWrite == 0 {
+ c.cursym.Func().FuncFlag |= abi.FuncFlagSPWrite
if ctxt.Debugvlog || !ctxt.IsAsm {
ctxt.Logf("auto-SPWRITE: %s %v\n", c.cursym.Name, p)
if !ctxt.IsAsm {