| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | package arm64 |
| |
|
| | import ( |
| | "cmd/internal/obj" |
| | "cmd/internal/objabi" |
| | "cmd/internal/src" |
| | "cmd/internal/sys" |
| | "internal/abi" |
| | "internal/buildcfg" |
| | "log" |
| | "math" |
| | ) |
| |
|
| | |
| | |
| | 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 { |
| | if c.ctxt.Flag_maymorestack != "" { |
| | p = c.cursym.Func().SpillRegisterArgs(p, c.newprog) |
| |
|
| | |
| | |
| | const frameSize = 32 |
| | p = obj.Appendp(p, c.newprog) |
| | p.As = AMOVD |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGLINK |
| | p.To.Type = obj.TYPE_MEM |
| | p.Scond = C_XPRE |
| | p.To.Offset = -frameSize |
| | p.To.Reg = REGSP |
| | p.Spadj = frameSize |
| |
|
| | |
| | p = obj.Appendp(p, c.newprog) |
| | p.As = AMOVD |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGFP |
| | p.To.Type = obj.TYPE_MEM |
| | p.To.Reg = REGSP |
| | p.To.Offset = -8 |
| |
|
| | p = obj.Appendp(p, c.newprog) |
| | p.As = ASUB |
| | p.From.Type = obj.TYPE_CONST |
| | p.From.Offset = 8 |
| | p.Reg = REGSP |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGFP |
| |
|
| | |
| | |
| | p = obj.Appendp(p, c.newprog) |
| | p.As = AMOVD |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGCTXT |
| | p.To.Type = obj.TYPE_MEM |
| | p.To.Reg = REGSP |
| | p.To.Offset = 8 |
| |
|
| | |
| | p = obj.Appendp(p, c.newprog) |
| | p.As = ABL |
| | p.To.Type = obj.TYPE_BRANCH |
| | |
| | p.To.Sym = c.ctxt.LookupABI(c.ctxt.Flag_maymorestack, c.cursym.ABI()) |
| |
|
| | |
| | p = obj.Appendp(p, c.newprog) |
| | p.As = AMOVD |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Reg = REGSP |
| | p.From.Offset = 8 |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGCTXT |
| |
|
| | |
| | p = obj.Appendp(p, c.newprog) |
| | p.As = AMOVD |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Reg = REGSP |
| | p.From.Offset = -8 |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGFP |
| |
|
| | |
| | p = obj.Appendp(p, c.newprog) |
| | p.As = AMOVD |
| | p.From.Type = obj.TYPE_MEM |
| | p.Scond = C_XPOST |
| | p.From.Offset = frameSize |
| | p.From.Reg = REGSP |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGLINK |
| | p.Spadj = -frameSize |
| |
|
| | p = c.cursym.Func().UnspillRegisterArgs(p, c.newprog) |
| | } |
| |
|
| | |
| | startPred := p |
| |
|
| | |
| | p = obj.Appendp(p, c.newprog) |
| |
|
| | p.As = AMOVD |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Reg = REGG |
| | p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize) |
| | if c.cursym.CFunc() { |
| | p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize) |
| | } |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGRT1 |
| |
|
| | |
| | |
| | |
| | |
| | p = c.ctxt.StartUnsafePoint(p, c.newprog) |
| |
|
| | q := (*obj.Prog)(nil) |
| | if framesize <= abi.StackSmall { |
| | |
| | |
| |
|
| | p = obj.Appendp(p, c.newprog) |
| | p.As = ACMP |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGRT1 |
| | p.Reg = REGSP |
| | } else if framesize <= abi.StackBig { |
| | |
| | |
| | |
| | p = obj.Appendp(p, c.newprog) |
| |
|
| | p.As = ASUB |
| | p.From.Type = obj.TYPE_CONST |
| | 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 = ACMP |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGRT1 |
| | p.Reg = REGRT2 |
| | } else { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | p = obj.Appendp(p, c.newprog) |
| | p.As = ASUBS |
| | p.From.Type = obj.TYPE_CONST |
| | 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) |
| | q = p |
| | p.As = ABLO |
| | p.To.Type = obj.TYPE_BRANCH |
| |
|
| | p = obj.Appendp(p, c.newprog) |
| | p.As = ACMP |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGRT1 |
| | p.Reg = REGRT2 |
| | } |
| |
|
| | |
| | bls := obj.Appendp(p, c.newprog) |
| | bls.As = ABLS |
| | bls.To.Type = obj.TYPE_BRANCH |
| |
|
| | end := c.ctxt.EndUnsafePoint(bls, c.newprog, -1) |
| |
|
| | var last *obj.Prog |
| | for last = c.cursym.Func().Text; last.Link != nil; last = last.Link { |
| | } |
| |
|
| | |
| | |
| | |
| | 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) |
| | } |
| | bls.To.SetTarget(pcdata) |
| |
|
| | spill := c.cursym.Func().SpillRegisterArgs(pcdata, c.newprog) |
| |
|
| | |
| | movlr := obj.Appendp(spill, c.newprog) |
| | movlr.As = AMOVD |
| | movlr.From.Type = obj.TYPE_REG |
| | movlr.From.Reg = REGLINK |
| | movlr.To.Type = obj.TYPE_REG |
| | movlr.To.Reg = REG_R3 |
| |
|
| | debug := movlr |
| | if false { |
| | debug = obj.Appendp(debug, c.newprog) |
| | debug.As = AMOVD |
| | debug.From.Type = obj.TYPE_CONST |
| | debug.From.Offset = int64(framesize) |
| | debug.To.Type = obj.TYPE_REG |
| | debug.To.Reg = REGTMP |
| | } |
| |
|
| | |
| | call := obj.Appendp(debug, c.newprog) |
| | call.As = ABL |
| | call.To.Type = obj.TYPE_BRANCH |
| | morestack := "runtime.morestack" |
| | switch { |
| | case c.cursym.CFunc(): |
| | morestack = "runtime.morestackc" |
| | case !c.cursym.Func().Text.From.Sym.NeedCtxt(): |
| | morestack = "runtime.morestack_noctxt" |
| | } |
| | call.To.Sym = c.ctxt.Lookup(morestack) |
| |
|
| | |
| | pcdata = c.ctxt.EndUnsafePoint(call, c.newprog, -1) |
| | unspill := c.cursym.Func().UnspillRegisterArgs(pcdata, c.newprog) |
| |
|
| | |
| | jmp := obj.Appendp(unspill, c.newprog) |
| | jmp.As = AB |
| | jmp.To.Type = obj.TYPE_BRANCH |
| | jmp.To.SetTarget(startPred.Link) |
| | jmp.Spadj = +framesize |
| |
|
| | return end |
| | } |
| |
|
| | func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { |
| | c := ctxt7{ctxt: ctxt, newprog: newprog} |
| |
|
| | p.From.Class = 0 |
| | p.To.Class = 0 |
| |
|
| | |
| | |
| | |
| | if p.From.Type == obj.TYPE_CONST && p.From.Offset == 0 && zrReplace[p.As] { |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGZERO |
| | } |
| |
|
| | |
| | switch p.As { |
| | case AB, ABL, obj.ARET: |
| | if p.To.Sym != nil { |
| | p.To.Type = obj.TYPE_BRANCH |
| | } |
| | break |
| | } |
| |
|
| | |
| | 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) |
| | f32 := float32(f64) |
| | if c.chipfloat7(f64) > 0 { |
| | break |
| | } |
| | if math.Float32bits(f32) == 0 { |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGZERO |
| | break |
| | } |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Sym = c.ctxt.Float32Sym(f32) |
| | p.From.Name = obj.NAME_EXTERN |
| | p.From.Offset = 0 |
| | } |
| |
|
| | case AFMOVD: |
| | if p.From.Type == obj.TYPE_FCONST { |
| | f64 := p.From.Val.(float64) |
| | if c.chipfloat7(f64) > 0 { |
| | break |
| | } |
| | if math.Float64bits(f64) == 0 { |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGZERO |
| | break |
| | } |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Sym = c.ctxt.Float64Sym(f64) |
| | p.From.Name = obj.NAME_EXTERN |
| | p.From.Offset = 0 |
| | } |
| | } |
| |
|
| | if c.ctxt.Flag_dynlink { |
| | c.rewriteToUseGot(p) |
| | } |
| | } |
| |
|
| | |
| | func (c *ctxt7) rewriteToUseGot(p *obj.Prog) { |
| |
|
| | |
| | |
| | |
| | if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() { |
| | |
| | |
| | if p.As != AMOVD { |
| | c.ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p) |
| | } |
| | if p.To.Type != obj.TYPE_REG { |
| | c.ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p) |
| | } |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Name = obj.NAME_GOTREF |
| | if p.From.Offset != 0 { |
| | q := obj.Appendp(p, c.newprog) |
| | q.As = AADD |
| | q.From.Type = obj.TYPE_CONST |
| | q.From.Offset = p.From.Offset |
| | q.To = p.To |
| | p.From.Offset = 0 |
| | } |
| | } |
| | if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN { |
| | c.ctxt.Diag("don't know how to handle %v with -dynlink", p) |
| | } |
| | var source *obj.Addr |
| | |
| | |
| | |
| | if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() { |
| | if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { |
| | c.ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p) |
| | } |
| | source = &p.From |
| | } else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { |
| | source = &p.To |
| | } else { |
| | return |
| | } |
| | if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP { |
| | return |
| | } |
| | if source.Sym.Type == objabi.STLSBSS { |
| | return |
| | } |
| | if source.Type != obj.TYPE_MEM { |
| | c.ctxt.Diag("don't know how to handle %v with -dynlink", p) |
| | } |
| | p1 := obj.Appendp(p, c.newprog) |
| | p2 := obj.Appendp(p1, c.newprog) |
| | p1.As = AMOVD |
| | p1.From.Type = obj.TYPE_MEM |
| | p1.From.Sym = source.Sym |
| | p1.From.Name = obj.NAME_GOTREF |
| | p1.To.Type = obj.TYPE_REG |
| | p1.To.Reg = REGTMP |
| |
|
| | p2.As = p.As |
| | p2.From = p.From |
| | p2.To = p.To |
| | if p.From.Name == obj.NAME_EXTERN { |
| | p2.From.Reg = REGTMP |
| | p2.From.Name = obj.NAME_NONE |
| | p2.From.Sym = nil |
| | } else if p.To.Name == obj.NAME_EXTERN { |
| | p2.To.Reg = REGTMP |
| | p2.To.Name = obj.NAME_NONE |
| | p2.To.Sym = nil |
| | } else { |
| | return |
| | } |
| | obj.Nopout(p) |
| | } |
| |
|
| | func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { |
| | if cursym.Func().Text == nil || cursym.Func().Text.Link == nil { |
| | return |
| | } |
| |
|
| | c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym} |
| |
|
| | p := c.cursym.Func().Text |
| | textstksiz := p.To.Offset |
| | if textstksiz == -8 { |
| | |
| | p.From.Sym.Set(obj.AttrNoFrame, true) |
| | textstksiz = 0 |
| | } |
| | if textstksiz < 0 { |
| | c.ctxt.Diag("negative frame size %d - did you mean NOFRAME?", textstksiz) |
| | } |
| | if p.From.Sym.NoFrame() { |
| | if textstksiz != 0 { |
| | c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz) |
| | } |
| | } |
| |
|
| | c.cursym.Func().Args = p.To.Val.(int32) |
| | c.cursym.Func().Locals = int32(textstksiz) |
| |
|
| | |
| | |
| | |
| | for p := c.cursym.Func().Text; p != nil; p = p.Link { |
| | switch p.As { |
| | case obj.ATEXT: |
| | p.Mark |= LEAF |
| |
|
| | case ABL: |
| | c.cursym.Func().Text.Mark &^= LEAF |
| | } |
| | } |
| |
|
| | var q *obj.Prog |
| | var q1 *obj.Prog |
| | for p := c.cursym.Func().Text; p != nil; p = p.Link { |
| | o := p.As |
| | switch o { |
| | case obj.ATEXT: |
| | c.cursym.Func().Text = p |
| | c.autosize = int32(textstksiz) |
| |
|
| | if p.Mark&LEAF != 0 && c.autosize == 0 { |
| | |
| | p.From.Sym.Set(obj.AttrNoFrame, true) |
| | } |
| |
|
| | if !p.From.Sym.NoFrame() { |
| | |
| | |
| | c.autosize += 8 |
| | } |
| |
|
| | if c.autosize != 0 { |
| | extrasize := int32(0) |
| | if c.autosize%16 == 8 { |
| | |
| | extrasize = 8 |
| | } else if c.autosize&(16-1) == 0 { |
| | |
| | extrasize = 16 |
| | } else { |
| | c.ctxt.Diag("%v: unaligned frame size %d - must be 16 aligned", p, c.autosize-8) |
| | } |
| | c.autosize += extrasize |
| | c.cursym.Func().Locals += extrasize |
| |
|
| | |
| | |
| | p.To.Offset = int64(c.autosize) | int64(extrasize)<<32 |
| | } else { |
| | |
| | p.To.Offset = 0 |
| | } |
| |
|
| | if c.autosize == 0 && c.cursym.Func().Text.Mark&LEAF == 0 { |
| | if c.ctxt.Debugvlog { |
| | c.ctxt.Logf("save suppressed in: %s\n", c.cursym.Func().Text.From.Sym.Name) |
| | } |
| | c.cursym.Func().Text.Mark |= LEAF |
| | } |
| |
|
| | if cursym.Func().Text.Mark&LEAF != 0 { |
| | cursym.Set(obj.AttrLeaf, true) |
| | if p.From.Sym.NoFrame() { |
| | break |
| | } |
| | } |
| |
|
| | if p.Mark&LEAF != 0 && c.autosize < abi.StackSmall { |
| | |
| | |
| | p.From.Sym.Set(obj.AttrNoSplit, true) |
| | } |
| |
|
| | if !p.From.Sym.NoSplit() { |
| | p = c.stacksplit(p, c.autosize) |
| | } |
| |
|
| | var prologueEnd *obj.Prog |
| |
|
| | aoffset := c.autosize |
| | if aoffset > 0xf0 { |
| | |
| | |
| | aoffset = 0xf0 |
| | } |
| |
|
| | |
| | |
| | q = p |
| | if c.autosize > aoffset { |
| | |
| | |
| | |
| | |
| |
|
| | |
| | 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 = q1 |
| |
|
| | |
| | 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 = c.ctxt.StartUnsafePoint(q1, c.newprog) |
| |
|
| | |
| | q1 = obj.Appendp(q1, c.newprog) |
| | q1.Pos = p.Pos |
| | q1.As = AMOVD |
| | q1.From.Type = obj.TYPE_REG |
| | 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" { |
| | |
| | |
| | |
| | |
| | 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 = REGSP |
| | q1.To.Offset = -8 |
| | } |
| | } else { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | q1 = obj.Appendp(q, c.newprog) |
| | q1.As = AMOVD |
| | q1.Pos = p.Pos |
| | q1.From.Type = obj.TYPE_REG |
| | q1.From.Reg = REGLINK |
| | q1.To.Type = obj.TYPE_MEM |
| | q1.Scond = C_XPRE |
| | q1.To.Offset = int64(-aoffset) |
| | q1.To.Reg = REGSP |
| | q1.Spadj = aoffset |
| |
|
| | prologueEnd = q1 |
| |
|
| | |
| | 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 |
| | } |
| |
|
| | prologueEnd.Pos = prologueEnd.Pos.WithXlogue(src.PosPrologueEnd) |
| |
|
| | q1 = obj.Appendp(q1, c.newprog) |
| | q1.Pos = p.Pos |
| | q1.As = ASUB |
| | q1.From.Type = obj.TYPE_CONST |
| | q1.From.Offset = 8 |
| | q1.Reg = REGSP |
| | q1.To.Type = obj.TYPE_REG |
| | q1.To.Reg = REGFP |
| |
|
| | case obj.ARET: |
| | nocache(p) |
| | if p.From.Type == obj.TYPE_CONST { |
| | c.ctxt.Diag("using BECOME (%v) is not supported!", p) |
| | break |
| | } |
| |
|
| | retJMP, retReg := p.To.Sym, p.To.Reg |
| | if retReg == 0 { |
| | retReg = REGLINK |
| | } |
| | p.To = obj.Addr{} |
| | aoffset := c.autosize |
| | if c.cursym.Func().Text.Mark&LEAF != 0 { |
| | if aoffset != 0 { |
| | |
| | |
| | p.As = AADD |
| | p.From.Type = obj.TYPE_CONST |
| | p.From.Offset = int64(c.autosize) - 8 |
| | p.Reg = REGSP |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGFP |
| |
|
| | |
| | |
| | p = obj.Appendp(p, c.newprog) |
| | p.As = AADD |
| | p.From.Type = obj.TYPE_CONST |
| | p.From.Offset = int64(c.autosize) |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGSP |
| | p.Spadj = -c.autosize |
| | } |
| | } else if aoffset <= 0xF0 { |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | p.As = AMOVD |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Reg = REGSP |
| | p.From.Offset = -8 |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGFP |
| | p = obj.Appendp(p, c.newprog) |
| |
|
| | |
| | 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 = ALDP |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Offset = -8 |
| | p.From.Reg = REGSP |
| | p.To.Type = obj.TYPE_REGREG |
| | p.To.Reg = REGFP |
| | p.To.Offset = REGLINK |
| |
|
| | if aoffset < 1<<12 { |
| | |
| | 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 |
| | } else { |
| | |
| | |
| | |
| | |
| |
|
| | |
| | q = newprog() |
| | q.As = AMOVD |
| | q.From.Type = obj.TYPE_CONST |
| | q.From.Offset = int64(aoffset) |
| | q.To.Type = obj.TYPE_REG |
| | q.To.Reg = REGTMP |
| | q.Pos = p.Pos |
| | q.Link = p.Link |
| | p.Link = q |
| | p = q |
| | |
| | q = newprog() |
| | q.As = AADD |
| | q.From.Type = obj.TYPE_REG |
| | q.From.Reg = REGTMP |
| | 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 |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | const debugRETZERO = false |
| | if debugRETZERO { |
| | if p.As != obj.ARET { |
| | q = newprog() |
| | q.Pos = p.Pos |
| | q.Link = p.Link |
| | p.Link = q |
| | p = q |
| | } |
| | p.As = AADR |
| | p.From.Type = obj.TYPE_BRANCH |
| | p.From.Offset = 0 |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGTMP |
| |
|
| | } |
| |
|
| | if p.As != obj.ARET { |
| | q = newprog() |
| | q.Pos = p.Pos |
| | q.Link = p.Link |
| | p.Link = q |
| | p = q |
| | } |
| |
|
| | if retJMP != nil { |
| | p.As = AB |
| | p.To.Type = obj.TYPE_BRANCH |
| | p.To.Sym = retJMP |
| | p.Spadj = +c.autosize |
| | break |
| | } |
| |
|
| | p.As = obj.ARET |
| | p.To.Type = obj.TYPE_MEM |
| | p.To.Offset = 0 |
| | p.To.Reg = retReg |
| | p.Spadj = +c.autosize |
| |
|
| | case AADD, ASUB: |
| | if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST { |
| | if p.As == AADD { |
| | p.Spadj = int32(-p.From.Offset) |
| | } else { |
| | p.Spadj = int32(+p.From.Offset) |
| | } |
| | } |
| |
|
| | case obj.AGETCALLERPC: |
| | if cursym.Leaf() { |
| | |
| | p.As = AMOVD |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGLINK |
| | } else { |
| | |
| | p.As = AMOVD |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Reg = REGSP |
| | } |
| | } |
| | if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 { |
| | f := c.cursym.Func() |
| | 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 { |
| | ctxt.Diag("invalid auto-SPWRITE in non-assembly") |
| | ctxt.DiagFlush() |
| | log.Fatalf("bad SPWRITE") |
| | } |
| | } |
| | } |
| | } |
| | if p.From.Type == obj.TYPE_SHIFT && (p.To.Reg == REG_RSP || p.Reg == REG_RSP) { |
| | offset := p.From.Offset |
| | op := offset & (3 << 22) |
| | if op != SHIFT_LL { |
| | ctxt.Diag("illegal combination: %v", p) |
| | } |
| | r := (offset >> 16) & 31 |
| | shift := (offset >> 10) & 63 |
| | if shift > 4 { |
| | |
| | |
| | |
| | shift = 7 |
| | } |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = int16(REG_LSL + r + (shift&7)<<5) |
| | p.From.Offset = 0 |
| | } |
| | } |
| | } |
| |
|
| | func nocache(p *obj.Prog) { |
| | p.Optab = 0 |
| | p.From.Class = 0 |
| | p.To.Class = 0 |
| | } |
| |
|
| | var unaryDst = map[obj.As]bool{ |
| | AWORD: true, |
| | ADWORD: true, |
| | ABL: true, |
| | AB: true, |
| | ACLREX: true, |
| | } |
| |
|
| | var Linkarm64 = obj.LinkArch{ |
| | Arch: sys.ArchARM64, |
| | Init: buildop, |
| | Preprocess: preprocess, |
| | Assemble: span7, |
| | Progedit: progedit, |
| | UnaryDst: unaryDst, |
| | DWARFRegisters: ARM64DWARFRegisters, |
| | } |
| |
|