| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | package arm |
| |
|
| | import ( |
| | "cmd/internal/obj" |
| | "cmd/internal/objabi" |
| | "cmd/internal/sys" |
| | "internal/abi" |
| | "internal/buildcfg" |
| | "log" |
| | ) |
| |
|
| | var progedit_tlsfallback *obj.LSym |
| |
|
| | func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { |
| | p.From.Class = 0 |
| | p.To.Class = 0 |
| |
|
| | c := ctxt5{ctxt: ctxt, newprog: newprog} |
| |
|
| | |
| | switch p.As { |
| | case AB, ABL, obj.ADUFFZERO, obj.ADUFFCOPY: |
| | if p.To.Type == obj.TYPE_MEM && (p.To.Name == obj.NAME_EXTERN || p.To.Name == obj.NAME_STATIC) && p.To.Sym != nil { |
| | p.To.Type = obj.TYPE_BRANCH |
| | } |
| | } |
| |
|
| | |
| | switch p.As { |
| | |
| | case AMRC: |
| | if p.To.Offset&0xffff0fff == 0xee1d0f70 { |
| | |
| | |
| | if p.To.Offset&0xf000 != 0 { |
| | ctxt.Diag("%v: TLS MRC instruction must write to R0 as it might get translated into a BL instruction", p.Line()) |
| | } |
| |
|
| | if buildcfg.GOARM.Version < 7 { |
| | |
| | if progedit_tlsfallback == nil { |
| | progedit_tlsfallback = ctxt.Lookup("runtime.read_tls_fallback") |
| | } |
| |
|
| | |
| | p.As = AMOVW |
| |
|
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGLINK |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGTMP |
| |
|
| | |
| | p = obj.Appendp(p, newprog) |
| |
|
| | p.As = ABL |
| | p.To.Type = obj.TYPE_BRANCH |
| | p.To.Sym = progedit_tlsfallback |
| | p.To.Offset = 0 |
| |
|
| | |
| | p = obj.Appendp(p, newprog) |
| |
|
| | p.As = AMOVW |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGTMP |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGLINK |
| | break |
| | } |
| | } |
| |
|
| | |
| | p.As = AWORD |
| | } |
| |
|
| | |
| | switch p.As { |
| | case AMOVF: |
| | if p.From.Type == obj.TYPE_FCONST && c.chipfloat5(p.From.Val.(float64)) < 0 && (c.chipzero5(p.From.Val.(float64)) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) { |
| | f32 := float32(p.From.Val.(float64)) |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Sym = ctxt.Float32Sym(f32) |
| | p.From.Name = obj.NAME_EXTERN |
| | p.From.Offset = 0 |
| | } |
| |
|
| | case AMOVD: |
| | if p.From.Type == obj.TYPE_FCONST && c.chipfloat5(p.From.Val.(float64)) < 0 && (c.chipzero5(p.From.Val.(float64)) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) { |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Sym = ctxt.Float64Sym(p.From.Val.(float64)) |
| | p.From.Name = obj.NAME_EXTERN |
| | p.From.Offset = 0 |
| | } |
| | } |
| |
|
| | if ctxt.Flag_dynlink { |
| | c.rewriteToUseGot(p) |
| | } |
| | } |
| |
|
| | |
| | func (c *ctxt5) rewriteToUseGot(p *obj.Prog) { |
| | if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO { |
| | |
| | |
| | |
| | |
| | |
| | var sym *obj.LSym |
| | if p.As == obj.ADUFFZERO { |
| | sym = c.ctxt.Lookup("runtime.duffzero") |
| | } else { |
| | sym = c.ctxt.Lookup("runtime.duffcopy") |
| | } |
| | offset := p.To.Offset |
| | p.As = AMOVW |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Name = obj.NAME_GOTREF |
| | p.From.Sym = sym |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REG_R9 |
| | p.To.Name = obj.NAME_NONE |
| | p.To.Offset = 0 |
| | p.To.Sym = nil |
| | p1 := obj.Appendp(p, c.newprog) |
| | p1.As = AADD |
| | p1.From.Type = obj.TYPE_CONST |
| | p1.From.Offset = offset |
| | p1.To.Type = obj.TYPE_REG |
| | p1.To.Reg = REG_R9 |
| | p2 := obj.Appendp(p1, c.newprog) |
| | p2.As = obj.ACALL |
| | p2.To.Type = obj.TYPE_MEM |
| | p2.To.Reg = REG_R9 |
| | return |
| | } |
| |
|
| | |
| | |
| | |
| | if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() { |
| | |
| | |
| | if p.As != AMOVW { |
| | 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 = AMOVW |
| | 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 = REG_R9 |
| |
|
| | p2.As = p.As |
| | p2.From = p.From |
| | p2.To = p.To |
| | if p.From.Name == obj.NAME_EXTERN { |
| | p2.From.Reg = REG_R9 |
| | p2.From.Name = obj.NAME_NONE |
| | p2.From.Sym = nil |
| | } else if p.To.Name == obj.NAME_EXTERN { |
| | p2.To.Reg = REG_R9 |
| | p2.To.Name = obj.NAME_NONE |
| | p2.To.Sym = nil |
| | } else { |
| | return |
| | } |
| | obj.Nopout(p) |
| | } |
| |
|
| | |
| | const ( |
| | FOLL = 1 << 0 |
| | LABEL = 1 << 1 |
| | LEAF = 1 << 2 |
| | ) |
| |
|
| | func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { |
| | autosize := int32(0) |
| |
|
| | if cursym.Func().Text == nil || cursym.Func().Text.Link == nil { |
| | return |
| | } |
| |
|
| | c := ctxt5{ctxt: ctxt, cursym: cursym, newprog: newprog} |
| |
|
| | p := c.cursym.Func().Text |
| | autoffset := int32(p.To.Offset) |
| | if autoffset == -4 { |
| | |
| | p.From.Sym.Set(obj.AttrNoFrame, true) |
| | autoffset = 0 |
| | } |
| | if autoffset < 0 || autoffset%4 != 0 { |
| | c.ctxt.Diag("frame size %d not 0 or a positive multiple of 4", autoffset) |
| | } |
| | if p.From.Sym.NoFrame() { |
| | if autoffset != 0 { |
| | c.ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", autoffset) |
| | } |
| | } |
| |
|
| | cursym.Func().Locals = autoffset |
| | cursym.Func().Args = p.To.Val.(int32) |
| |
|
| | |
| | |
| | |
| | for p := cursym.Func().Text; p != nil; p = p.Link { |
| | switch p.As { |
| | case obj.ATEXT: |
| | p.Mark |= LEAF |
| |
|
| | case ADIV, ADIVU, AMOD, AMODU: |
| | cursym.Func().Text.Mark &^= LEAF |
| |
|
| | case ABL, |
| | ABX, |
| | obj.ADUFFZERO, |
| | obj.ADUFFCOPY: |
| | cursym.Func().Text.Mark &^= LEAF |
| | } |
| | } |
| |
|
| | var q2 *obj.Prog |
| | for p := cursym.Func().Text; p != nil; p = p.Link { |
| | o := p.As |
| | switch o { |
| | case obj.ATEXT: |
| | autosize = autoffset |
| |
|
| | if p.Mark&LEAF != 0 && autosize == 0 { |
| | |
| | p.From.Sym.Set(obj.AttrNoFrame, true) |
| | } |
| |
|
| | if !p.From.Sym.NoFrame() { |
| | |
| | |
| | autosize += 4 |
| | } |
| |
|
| | if autosize == 0 && cursym.Func().Text.Mark&LEAF == 0 { |
| | |
| | |
| | if ctxt.Debugvlog { |
| | ctxt.Logf("save suppressed in: %s\n", cursym.Name) |
| | } |
| |
|
| | cursym.Func().Text.Mark |= LEAF |
| | } |
| |
|
| | |
| | p.To.Offset = int64(autosize) - 4 |
| |
|
| | if cursym.Func().Text.Mark&LEAF != 0 { |
| | cursym.Set(obj.AttrLeaf, true) |
| | if p.From.Sym.NoFrame() { |
| | break |
| | } |
| | } |
| |
|
| | if !p.From.Sym.NoSplit() { |
| | p = c.stacksplit(p, autosize) |
| | } |
| |
|
| | |
| | p = obj.Appendp(p, c.newprog) |
| |
|
| | p.As = AMOVW |
| | p.Scond |= C_WBIT |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGLINK |
| | p.To.Type = obj.TYPE_MEM |
| | p.To.Offset = int64(-autosize) |
| | p.To.Reg = REGSP |
| | p.Spadj = autosize |
| |
|
| | case obj.ARET: |
| | nocache(p) |
| | if cursym.Func().Text.Mark&LEAF != 0 { |
| | if autosize == 0 { |
| | p.As = AB |
| | p.From = obj.Addr{} |
| | if p.To.Sym != nil { |
| | p.To.Type = obj.TYPE_BRANCH |
| | } else { |
| | p.To.Type = obj.TYPE_MEM |
| | p.To.Offset = 0 |
| | p.To.Reg = REGLINK |
| | } |
| |
|
| | break |
| | } |
| | } |
| |
|
| | p.As = AMOVW |
| | p.Scond |= C_PBIT |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Offset = int64(autosize) |
| | p.From.Reg = REGSP |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGPC |
| |
|
| | |
| | |
| | |
| |
|
| | if p.To.Sym != nil { |
| | p.To.Reg = REGLINK |
| | q2 = obj.Appendp(p, newprog) |
| | q2.As = AB |
| | q2.To.Type = obj.TYPE_BRANCH |
| | q2.To.Sym = p.To.Sym |
| | p.To.Sym = nil |
| | p.To.Name = obj.NAME_NONE |
| | p = q2 |
| | } |
| |
|
| | case AADD: |
| | if p.From.Type == obj.TYPE_CONST && p.From.Reg == 0 && p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP { |
| | p.Spadj = int32(-p.From.Offset) |
| | } |
| |
|
| | case ASUB: |
| | if p.From.Type == obj.TYPE_CONST && p.From.Reg == 0 && p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP { |
| | p.Spadj = int32(p.From.Offset) |
| | } |
| |
|
| | case ADIV, ADIVU, AMOD, AMODU: |
| | if cursym.Func().Text.From.Sym.NoSplit() { |
| | ctxt.Diag("cannot divide in NOSPLIT function") |
| | } |
| | const debugdivmod = false |
| | if debugdivmod { |
| | break |
| | } |
| | if p.From.Type != obj.TYPE_REG { |
| | break |
| | } |
| | if p.To.Type != obj.TYPE_REG { |
| | break |
| | } |
| |
|
| | |
| | q1 := *p |
| | if q1.Reg == REGTMP || q1.Reg == 0 && q1.To.Reg == REGTMP { |
| | ctxt.Diag("div already using REGTMP: %v", p) |
| | } |
| |
|
| | |
| | p.As = AMOVW |
| | p.Pos = q1.Pos |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Reg = REGG |
| | p.From.Offset = 6 * 4 |
| | p.Reg = 0 |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGTMP |
| |
|
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = AMOVW |
| | p.Pos = q1.Pos |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = q1.From.Reg |
| | p.To.Type = obj.TYPE_MEM |
| | p.To.Reg = REGTMP |
| | p.To.Offset = 7 * 4 |
| |
|
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = AMOVW |
| | p.Pos = q1.Pos |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = q1.Reg |
| | if q1.Reg == 0 { |
| | p.From.Reg = q1.To.Reg |
| | } |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REG_R8 |
| | p.To.Offset = 0 |
| |
|
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = ABL |
| | p.Pos = q1.Pos |
| | p.To.Type = obj.TYPE_BRANCH |
| | switch o { |
| | case ADIV: |
| | p.To.Sym = symdiv |
| | case ADIVU: |
| | p.To.Sym = symdivu |
| | case AMOD: |
| | p.To.Sym = symmod |
| | case AMODU: |
| | p.To.Sym = symmodu |
| | } |
| |
|
| | |
| | p = obj.Appendp(p, newprog) |
| | p.As = AMOVW |
| | p.Pos = q1.Pos |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGTMP |
| | p.From.Offset = 0 |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = q1.To.Reg |
| |
|
| | case AMOVW: |
| | if (p.Scond&C_WBIT != 0) && p.To.Type == obj.TYPE_MEM && p.To.Reg == REGSP { |
| | p.Spadj = int32(-p.To.Offset) |
| | } |
| | if (p.Scond&C_PBIT != 0) && p.From.Type == obj.TYPE_MEM && p.From.Reg == REGSP && p.To.Reg != REGPC { |
| | p.Spadj = int32(-p.From.Offset) |
| | } |
| | if p.From.Type == obj.TYPE_ADDR && p.From.Reg == REGSP && p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP { |
| | p.Spadj = int32(-p.From.Offset) |
| | } |
| |
|
| | case obj.AGETCALLERPC: |
| | if cursym.Leaf() { |
| | |
| | p.As = AMOVW |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGLINK |
| | } else { |
| | |
| | p.As = AMOVW |
| | 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") |
| | } |
| | } |
| | } |
| | } |
| | } |
| | } |
| |
|
| | func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { |
| | if c.ctxt.Flag_maymorestack != "" { |
| | |
| | const frameSize = 8 |
| | |
| | p = obj.Appendp(p, c.newprog) |
| | p.As = AMOVW |
| | p.Scond |= C_WBIT |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGLINK |
| | p.To.Type = obj.TYPE_MEM |
| | p.To.Offset = -frameSize |
| | p.To.Reg = REGSP |
| | p.Spadj = frameSize |
| |
|
| | |
| | p = obj.Appendp(p, c.newprog) |
| | p.As = AMOVW |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REGCTXT |
| | p.To.Type = obj.TYPE_MEM |
| | p.To.Offset = 4 |
| | p.To.Reg = REGSP |
| |
|
| | |
| | p = obj.Appendp(p, c.newprog) |
| | p.As = obj.ACALL |
| | 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 = AMOVW |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Offset = 4 |
| | p.From.Reg = REGSP |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGCTXT |
| |
|
| | |
| | p.As = AMOVW |
| | p.Scond |= C_PBIT |
| | p.From.Type = obj.TYPE_MEM |
| | p.From.Offset = frameSize |
| | p.From.Reg = REGSP |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REGLINK |
| | p.Spadj = -frameSize |
| | } |
| |
|
| | |
| | startPred := p |
| |
|
| | |
| | p = obj.Appendp(p, c.newprog) |
| |
|
| | p.As = AMOVW |
| | 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 = REG_R1 |
| |
|
| | |
| | |
| | |
| | |
| | p = c.ctxt.StartUnsafePoint(p, c.newprog) |
| |
|
| | if framesize <= abi.StackSmall { |
| | |
| | |
| | p = obj.Appendp(p, c.newprog) |
| |
|
| | p.As = ACMP |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REG_R1 |
| | p.Reg = REGSP |
| | } else if framesize <= abi.StackBig { |
| | |
| | |
| | |
| | p = obj.Appendp(p, c.newprog) |
| |
|
| | p.As = AMOVW |
| | p.From.Type = obj.TYPE_ADDR |
| | p.From.Reg = REGSP |
| | p.From.Offset = -(int64(framesize) - abi.StackSmall) |
| | p.To.Type = obj.TYPE_REG |
| | p.To.Reg = REG_R2 |
| |
|
| | p = obj.Appendp(p, c.newprog) |
| | p.As = ACMP |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REG_R1 |
| | p.Reg = REG_R2 |
| | } else { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | p = obj.Appendp(p, c.newprog) |
| | p.As = ASUB |
| | p.Scond = C_SBIT |
| | 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 = REG_R2 |
| |
|
| | p = obj.Appendp(p, c.newprog) |
| | p.As = ACMP |
| | p.Scond = C_SCOND_HS |
| | p.From.Type = obj.TYPE_REG |
| | p.From.Reg = REG_R1 |
| | p.Reg = REG_R2 |
| | } |
| |
|
| | |
| | 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) |
| |
|
| | |
| | movw := obj.Appendp(pcdata, c.newprog) |
| | movw.As = AMOVW |
| | movw.From.Type = obj.TYPE_REG |
| | movw.From.Reg = REGLINK |
| | movw.To.Type = obj.TYPE_REG |
| | movw.To.Reg = REG_R3 |
| |
|
| | bls.To.SetTarget(movw) |
| |
|
| | |
| | call := obj.Appendp(movw, c.newprog) |
| | call.As = obj.ACALL |
| | 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) |
| |
|
| | |
| | b := obj.Appendp(pcdata, c.newprog) |
| | b.As = obj.AJMP |
| | b.To.Type = obj.TYPE_BRANCH |
| | b.To.SetTarget(startPred.Link) |
| | b.Spadj = +framesize |
| |
|
| | return end |
| | } |
| |
|
| | var unaryDst = map[obj.As]bool{ |
| | ASWI: true, |
| | AWORD: true, |
| | } |
| |
|
| | var Linkarm = obj.LinkArch{ |
| | Arch: sys.ArchARM, |
| | Init: buildop, |
| | Preprocess: preprocess, |
| | Assemble: span5, |
| | Progedit: progedit, |
| | UnaryDst: unaryDst, |
| | DWARFRegisters: ARMDWARFRegisters, |
| | } |
| |
|