From: Josh Bleecher Snyder Date: Thu, 6 Apr 2017 19:51:55 +0000 (-0700) Subject: cmd/internal/obj/arm: make assembler concurrency-safe X-Git-Tag: go1.9beta1~765 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=dcf643f1fd39f98baa4686c1b3baf5691e5773d3;p=gostls13.git cmd/internal/obj/arm: make assembler concurrency-safe Move global state from obj.Link to a new function-local state struct arm.ctxt5. This ends up being cleaner than threading all the state through as parameters; there's a lot of it. While we're here, move newprog from a parameter to ctxt5. We reserve the variable name c for ctxt5, so a few local variables named c have been renamed. Instead of lazily initializing deferreturn and Sym_div and friends, initialize them up front. Passes toolstash-check -all. Updates #15756 Change-Id: Ifb4e4b9879e4e1f25e6168d8b7b2a25a3390dc11 Reviewed-on: https://go-review.googlesource.com/39922 Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang --- diff --git a/src/cmd/internal/obj/arm/asm5.go b/src/cmd/internal/obj/arm/asm5.go index 43b82deddb..0636193cc8 100644 --- a/src/cmd/internal/obj/arm/asm5.go +++ b/src/cmd/internal/obj/arm/asm5.go @@ -38,6 +38,26 @@ import ( "sort" ) +// ctxt5 holds state while assembling a single function. +// Each function gets a fresh ctxt5. +// This allows for multiple functions to be safely concurrently assembled. +type ctxt5 struct { + ctxt *obj.Link + newprog obj.ProgAlloc + cursym *obj.LSym + printp *obj.Prog + blitrl *obj.Prog + elitrl *obj.Prog + autosize int64 + instoffset int64 + pc int64 + pool struct { + start uint32 + size uint32 + extra uint32 + } +} + type Optab struct { as obj.As a1 uint8 @@ -257,17 +277,17 @@ var optab = []Optab{ {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0}, } -var pool struct { - start uint32 - size uint32 - extra uint32 -} - var oprange [ALAST & obj.AMask][]Optab var xcmp [C_GOK + 1][C_GOK + 1]bool -var deferreturn *obj.LSym +var ( + deferreturn *obj.LSym + symdiv *obj.LSym + symdivu *obj.LSym + symmod *obj.LSym + symmodu *obj.LSym +) // Note about encoding: Prog.scond holds the condition encoding, // but XOR'ed with C_SCOND_XOR, so that C_SCOND_NONE == 0. @@ -279,14 +299,14 @@ var deferreturn *obj.LSym // p->pc if extra padding is necessary. // In rare cases, asmoutnacl might split p into two instructions. // origPC is the PC for this Prog (no padding is taken into account). -func asmoutnacl(ctxt *obj.Link, newprog obj.ProgAlloc, origPC int32, p *obj.Prog, o *Optab, out []uint32) int { +func (c *ctxt5) asmoutnacl(origPC int32, p *obj.Prog, o *Optab, out []uint32) int { size := int(o.size) // instruction specific switch p.As { default: if out != nil { - asmout(ctxt, p, o, out) + c.asmout(p, o, out) } case ADATABUNDLE, // align to 16-byte boundary @@ -294,7 +314,7 @@ func asmoutnacl(ctxt *obj.Link, newprog obj.ProgAlloc, origPC int32, p *obj.Prog p.Pc = (p.Pc + 15) &^ 15 if out != nil { - asmout(ctxt, p, o, out) + c.asmout(p, o, out) } case obj.AUNDEF, @@ -313,11 +333,11 @@ func asmoutnacl(ctxt *obj.Link, newprog obj.ProgAlloc, origPC int32, p *obj.Prog case AB, ABL: if p.To.Type != obj.TYPE_MEM { if out != nil { - asmout(ctxt, p, o, out) + c.asmout(p, o, out) } } else { if p.To.Offset != 0 || size != 4 || p.To.Reg > REG_R15 || p.To.Reg < REG_R0 { - ctxt.Diag("unsupported instruction: %v", p) + c.ctxt.Diag("unsupported instruction: %v", p) } if p.Pc&15 == 12 { p.Pc += 4 @@ -336,9 +356,6 @@ func asmoutnacl(ctxt *obj.Link, newprog obj.ProgAlloc, origPC int32, p *obj.Prog // align the last instruction (the actual BL) to the last instruction in a bundle if p.As == ABL { - if deferreturn == nil { - deferreturn = ctxt.Lookup("runtime.deferreturn", 0) - } if p.To.Sym == deferreturn { p.Pc = ((int64(origPC) + 15) &^ 15) + 16 - int64(size) } else { @@ -362,7 +379,7 @@ func asmoutnacl(ctxt *obj.Link, newprog obj.ProgAlloc, origPC int32, p *obj.Prog ASTREXD: if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_R15 && p.From.Reg == REG_R13 { // MOVW.W x(R13), PC if out != nil { - asmout(ctxt, p, o, out) + c.asmout(p, o, out) } if size == 4 { if out != nil { @@ -398,7 +415,7 @@ func asmoutnacl(ctxt *obj.Link, newprog obj.ProgAlloc, origPC int32, p *obj.Prog } if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_R15 { - ctxt.Diag("unsupported instruction (move to another register and use indirect jump instead): %v", p) + c.ctxt.Diag("unsupported instruction (move to another register and use indirect jump instead): %v", p) } if p.To.Type == obj.TYPE_MEM && p.To.Reg == REG_R13 && (p.Scond&C_WBIT != 0) && size > 4 { @@ -406,7 +423,7 @@ func asmoutnacl(ctxt *obj.Link, newprog obj.ProgAlloc, origPC int32, p *obj.Prog // split it into two instructions: // ADD $-100004, R13 // MOVW R14, 0(R13) - q := newprog() + q := c.newprog() p.Scond &^= C_WBIT *q = *p @@ -444,7 +461,7 @@ func asmoutnacl(ctxt *obj.Link, newprog obj.ProgAlloc, origPC int32, p *obj.Prog a2.Reg = REG_R13 a2.Sym = nil a2.Offset = 0 - size = int(oplook(ctxt, p).size) + size = int(c.oplook(p).size) break } @@ -461,7 +478,7 @@ func asmoutnacl(ctxt *obj.Link, newprog obj.ProgAlloc, origPC int32, p *obj.Prog // if addr.reg == 0, then it is probably load from x(FP) with small x, no need to modify. if reg == 0 { if out != nil { - asmout(ctxt, p, o, out) + c.asmout(p, o, out) } } else { if out != nil { @@ -472,7 +489,7 @@ func asmoutnacl(ctxt *obj.Link, newprog obj.ProgAlloc, origPC int32, p *obj.Prog } size += 4 if out != nil { - asmout(ctxt, p, o, out[1:]) + c.asmout(p, o, out[1:]) } } @@ -484,9 +501,9 @@ func asmoutnacl(ctxt *obj.Link, newprog obj.ProgAlloc, origPC int32, p *obj.Prog // 2. load/store from R11. // This won't handle .W/.P, so we should reject such code. if p.Scond&(C_PBIT|C_WBIT) != 0 { - ctxt.Diag("unsupported instruction (.P/.W): %v", p) + c.ctxt.Diag("unsupported instruction (.P/.W): %v", p) } - q := newprog() + q := c.newprog() *q = *p var a2 *obj.Addr if p.To.Type == obj.TYPE_MEM { @@ -519,11 +536,11 @@ func asmoutnacl(ctxt *obj.Link, newprog obj.ProgAlloc, origPC int32, p *obj.Prog a2.Reg = REG_R11 a2.Sym = nil a2.Offset = 0 - size = int(oplook(ctxt, p).size) + size = int(c.oplook(p).size) break } } else if out != nil { - asmout(ctxt, p, o, out) + c.asmout(p, o, out) } } @@ -531,7 +548,7 @@ func asmoutnacl(ctxt *obj.Link, newprog obj.ProgAlloc, origPC int32, p *obj.Prog if p.To.Type == obj.TYPE_REG { switch p.To.Reg { case REG_R9: - ctxt.Diag("invalid instruction, cannot write to R9: %v", p) + c.ctxt.Diag("invalid instruction, cannot write to R9: %v", p) case REG_R13: if out != nil { @@ -560,19 +577,17 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ctxt.Diag("arm ops not initialized, call arm.buildop first") } - ctxt.Cursym = cursym - - ctxt.Autosize = int32(p.To.Offset + 4) - c := int32(0) + c := ctxt5{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: p.To.Offset + 4} + pc := int32(0) op = p p = p.Link var i int var m int var o *Optab - for ; p != nil || ctxt.Blitrl != nil; op, p = p, p.Link { + for ; p != nil || c.blitrl != nil; op, p = p, p.Link { if p == nil { - if checkpool(ctxt, newprog, op, 0) { + if c.checkpool(op, 0) { p = op continue } @@ -583,14 +598,14 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { break } - p.Pc = int64(c) - o = oplook(ctxt, p) + p.Pc = int64(pc) + o = c.oplook(p) if ctxt.Headtype != obj.Hnacl { m = int(o.size) } else { - m = asmoutnacl(ctxt, newprog, c, p, o, nil) - c = int32(p.Pc) // asmoutnacl might change pc for alignment - o = oplook(ctxt, p) // asmoutnacl might change p in rare cases + m = c.asmoutnacl(pc, p, o, nil) + pc = int32(p.Pc) // asmoutnacl might change pc for alignment + o = c.oplook(p) // asmoutnacl might change p in rare cases } if m%4 != 0 || p.Pc%4 != 0 { @@ -598,9 +613,9 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } // must check literal pool here in case p generates many instructions - if ctxt.Blitrl != nil { + if c.blitrl != nil { i = m - if checkpool(ctxt, newprog, op, i) { + if c.checkpool(op, i) { p = op continue } @@ -613,24 +628,24 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { switch o.flag & (LFROM | LTO | LPOOL) { case LFROM: - addpool(ctxt, newprog, p, &p.From) + c.addpool(p, &p.From) case LTO: - addpool(ctxt, newprog, p, &p.To) + c.addpool(p, &p.To) case LPOOL: if p.Scond&C_SCOND == C_SCOND_NONE { - flushpool(ctxt, newprog, p, 0, 0) + c.flushpool(p, 0, 0) } } if p.As == AMOVW && p.To.Type == obj.TYPE_REG && p.To.Reg == REGPC && p.Scond&C_SCOND == C_SCOND_NONE { - flushpool(ctxt, newprog, p, 0, 0) + c.flushpool(p, 0, 0) } - c += int32(m) + pc += int32(m) } - cursym.Size = int64(c) + c.cursym.Size = int64(pc) /* * if any procedure is large enough to @@ -645,13 +660,13 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { var out [6 + 3]uint32 for { bflag = 0 - c = 0 + pc = 0 times++ - cursym.Text.Pc = 0 // force re-layout the code. - for p = cursym.Text; p != nil; p = p.Link { - o = oplook(ctxt, p) - if int64(c) > p.Pc { - p.Pc = int64(c) + c.cursym.Text.Pc = 0 // force re-layout the code. + for p = c.cursym.Text; p != nil; p = p.Link { + o = c.oplook(p) + if int64(pc) > p.Pc { + p.Pc = int64(pc) } /* very large branches @@ -682,14 +697,14 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { if ctxt.Headtype != obj.Hnacl { m = int(o.size) } else { - m = asmoutnacl(ctxt, newprog, c, p, o, nil) + m = c.asmoutnacl(pc, p, o, nil) } if p.Pc != int64(opc) { bflag = 1 } //print("%v pc changed %d to %d in iter. %d\n", p, opc, (int32)p->pc, times); - c = int32(p.Pc + int64(m)) + pc = int32(p.Pc + int64(m)) if m%4 != 0 || p.Pc%4 != 0 { ctxt.Diag("pc invalid: %v size=%d", p, m) @@ -700,7 +715,7 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != ADATABUNDLEEND && p.As != obj.ANOP) { if p.As == obj.ATEXT { - ctxt.Autosize = int32(p.To.Offset + 4) + c.autosize = p.To.Offset + 4 continue } @@ -709,14 +724,14 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } } - cursym.Size = int64(c) + c.cursym.Size = int64(pc) if bflag == 0 { break } } - if c%4 != 0 { - ctxt.Diag("sym->size=%d, invalid", c) + if pc%4 != 0 { + ctxt.Diag("sym->size=%d, invalid", pc) } /* @@ -728,22 +743,22 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { * perhaps we'd be able to parallelize the span loop above. */ - p = cursym.Text - ctxt.Autosize = int32(p.To.Offset + 4) - cursym.Grow(cursym.Size) + p = c.cursym.Text + c.autosize = p.To.Offset + 4 + c.cursym.Grow(c.cursym.Size) - bp := cursym.P - c = int32(p.Pc) // even p->link might need extra padding + bp := c.cursym.P + pc = int32(p.Pc) // even p->link might need extra padding var v int for p = p.Link; p != nil; p = p.Link { - ctxt.Pc = p.Pc - o = oplook(ctxt, p) + c.pc = p.Pc + o = c.oplook(p) opc = int32(p.Pc) if ctxt.Headtype != obj.Hnacl { - asmout(ctxt, p, o, out[:]) + c.asmout(p, o, out[:]) m = int(o.size) } else { - m = asmoutnacl(ctxt, newprog, c, p, o, out[:]) + m = c.asmoutnacl(pc, p, o, out[:]) if int64(opc) != p.Pc { ctxt.Diag("asmoutnacl broken: pc changed (%d->%d) in last stage: %v", opc, int32(p.Pc), p) } @@ -753,10 +768,10 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ctxt.Diag("final stage: pc invalid: %v size=%d", p, m) } - if int64(c) > p.Pc { - ctxt.Diag("PC padding invalid: want %#d, has %#d: %v", p.Pc, c, p) + if int64(pc) > p.Pc { + ctxt.Diag("PC padding invalid: want %#d, has %#d: %v", p.Pc, pc, p) } - for int64(c) != p.Pc { + for int64(pc) != p.Pc { // emit 0xe1a00000 (MOVW R0, R0) bp[0] = 0x00 bp = bp[1:] @@ -767,7 +782,7 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { bp = bp[1:] bp[0] = 0xe1 bp = bp[1:] - c += 4 + pc += 4 } for i = 0; i < m/4; i++ { @@ -782,7 +797,7 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { bp = bp[1:] } - c += int32(m) + pc += int32(m) } } @@ -792,77 +807,73 @@ func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { * drop the pool now, and branch round it. * this happens only in extended basic blocks that exceed 4k. */ -func checkpool(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog, sz int) bool { - if pool.size >= 0xff0 || immaddr(int32((p.Pc+int64(sz)+4)+4+int64(12+pool.size)-int64(pool.start+8))) == 0 { - return flushpool(ctxt, newprog, p, 1, 0) +func (c *ctxt5) checkpool(p *obj.Prog, sz int) bool { + if c.pool.size >= 0xff0 || immaddr(int32((p.Pc+int64(sz)+4)+4+int64(12+c.pool.size)-int64(c.pool.start+8))) == 0 { + return c.flushpool(p, 1, 0) } else if p.Link == nil { - return flushpool(ctxt, newprog, p, 2, 0) + return c.flushpool(p, 2, 0) } return false } -func flushpool(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog, skip int, force int) bool { - if ctxt.Blitrl != nil { +func (c *ctxt5) flushpool(p *obj.Prog, skip int, force int) bool { + if c.blitrl != nil { if skip != 0 { if false && skip == 1 { - fmt.Printf("note: flush literal pool at %x: len=%d ref=%x\n", uint64(p.Pc+4), pool.size, pool.start) + fmt.Printf("note: flush literal pool at %x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start) } - q := newprog() + q := c.newprog() q.As = AB q.To.Type = obj.TYPE_BRANCH q.Pcond = p.Link - q.Link = ctxt.Blitrl + q.Link = c.blitrl q.Pos = p.Pos - ctxt.Blitrl = q - } else if force == 0 && (p.Pc+int64(12+pool.size)-int64(pool.start) < 2048) { // 12 take into account the maximum nacl literal pool alignment padding size + c.blitrl = q + } else if force == 0 && (p.Pc+int64(12+c.pool.size)-int64(c.pool.start) < 2048) { // 12 take into account the maximum nacl literal pool alignment padding size return false } - if ctxt.Headtype == obj.Hnacl && pool.size%16 != 0 { + if c.ctxt.Headtype == obj.Hnacl && c.pool.size%16 != 0 { // if pool is not multiple of 16 bytes, add an alignment marker - q := newprog() + q := c.newprog() q.As = ADATABUNDLEEND - ctxt.Elitrl.Link = q - ctxt.Elitrl = q + c.elitrl.Link = q + c.elitrl = q } // The line number for constant pool entries doesn't really matter. // We set it to the line number of the preceding instruction so that // there are no deltas to encode in the pc-line tables. - for q := ctxt.Blitrl; q != nil; q = q.Link { + for q := c.blitrl; q != nil; q = q.Link { q.Pos = p.Pos } - ctxt.Elitrl.Link = p.Link - p.Link = ctxt.Blitrl + c.elitrl.Link = p.Link + p.Link = c.blitrl - ctxt.Blitrl = nil /* BUG: should refer back to values until out-of-range */ - ctxt.Elitrl = nil - pool.size = 0 - pool.start = 0 - pool.extra = 0 + c.blitrl = nil /* BUG: should refer back to values until out-of-range */ + c.elitrl = nil + c.pool.size = 0 + c.pool.start = 0 + c.pool.extra = 0 return true } return false } -func addpool(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog, a *obj.Addr) { - var t obj.Prog - - c := aclass(ctxt, a) - - t.Ctxt = ctxt +func (c *ctxt5) addpool(p *obj.Prog, a *obj.Addr) { + t := c.newprog() t.As = AWORD - switch c { + switch c.aclass(a) { default: t.To.Offset = a.Offset t.To.Sym = a.Sym t.To.Type = a.Type t.To.Name = a.Name - if ctxt.Flag_shared && t.To.Sym != nil { + if c.ctxt.Flag_shared && t.To.Sym != nil { t.Rel = p } @@ -877,11 +888,11 @@ func addpool(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog, a *obj.Addr) { C_LAUTO, C_LACON: t.To.Type = obj.TYPE_CONST - t.To.Offset = ctxt.Instoffset + t.To.Offset = c.instoffset } if t.Rel == nil { - for q := ctxt.Blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */ + for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */ if q.Rel == nil && q.To == t.To { p.Pcond = q return @@ -889,42 +900,42 @@ func addpool(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog, a *obj.Addr) { } } - if ctxt.Headtype == obj.Hnacl && pool.size%16 == 0 { + if c.ctxt.Headtype == obj.Hnacl && c.pool.size%16 == 0 { // start a new data bundle - q := newprog() + q := c.newprog() q.As = ADATABUNDLE - q.Pc = int64(pool.size) - pool.size += 4 - if ctxt.Blitrl == nil { - ctxt.Blitrl = q - pool.start = uint32(p.Pc) + q.Pc = int64(c.pool.size) + c.pool.size += 4 + if c.blitrl == nil { + c.blitrl = q + c.pool.start = uint32(p.Pc) } else { - ctxt.Elitrl.Link = q + c.elitrl.Link = q } - ctxt.Elitrl = q + c.elitrl = q } - q := newprog() - *q = t - q.Pc = int64(pool.size) + q := c.newprog() + *q = *t + q.Pc = int64(c.pool.size) - if ctxt.Blitrl == nil { - ctxt.Blitrl = q - pool.start = uint32(p.Pc) + if c.blitrl == nil { + c.blitrl = q + c.pool.start = uint32(p.Pc) } else { - ctxt.Elitrl.Link = q + c.elitrl.Link = q } - ctxt.Elitrl = q - pool.size += 4 + c.elitrl = q + c.pool.size += 4 p.Pcond = q } -func regoff(ctxt *obj.Link, a *obj.Addr) int32 { - ctxt.Instoffset = 0 - aclass(ctxt, a) - return int32(ctxt.Instoffset) +func (c *ctxt5) regoff(a *obj.Addr) int32 { + c.instoffset = 0 + c.aclass(a) + return int32(c.instoffset) } func immrot(v uint32) int32 { @@ -962,13 +973,13 @@ func immhalf(v int32) bool { return false } -func aclass(ctxt *obj.Link, a *obj.Addr) int { +func (c *ctxt5) aclass(a *obj.Addr) int { switch a.Type { case obj.TYPE_NONE: return C_NONE case obj.TYPE_REG: - ctxt.Instoffset = 0 + c.instoffset = 0 if REG_R0 <= a.Reg && a.Reg <= REG_R15 { return C_REG } @@ -1005,9 +1016,9 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { return C_GOK } - ctxt.Instoffset = 0 // s.b. unused but just in case + c.instoffset = 0 // s.b. unused but just in case if a.Sym.Type == obj.STLSBSS { - if ctxt.Flag_shared { + if c.ctxt.Flag_shared { return C_TLS_IE } else { return C_TLS_LE @@ -1017,9 +1028,9 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { return C_ADDR case obj.NAME_AUTO: - ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset - if t := immaddr(int32(ctxt.Instoffset)); t != 0 { - if immhalf(int32(ctxt.Instoffset)) { + c.instoffset = c.autosize + a.Offset + if t := immaddr(int32(c.instoffset)); t != 0 { + if immhalf(int32(c.instoffset)) { if immfloat(t) { return C_HFAUTO } @@ -1035,9 +1046,9 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { return C_LAUTO case obj.NAME_PARAM: - ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 4 - if t := immaddr(int32(ctxt.Instoffset)); t != 0 { - if immhalf(int32(ctxt.Instoffset)) { + c.instoffset = c.autosize + a.Offset + 4 + if t := immaddr(int32(c.instoffset)); t != 0 { + if immhalf(int32(c.instoffset)) { if immfloat(t) { return C_HFAUTO } @@ -1053,9 +1064,9 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { return C_LAUTO case obj.NAME_NONE: - ctxt.Instoffset = a.Offset - if t := immaddr(int32(ctxt.Instoffset)); t != 0 { - if immhalf(int32(ctxt.Instoffset)) { /* n.b. that it will also satisfy immrot */ + c.instoffset = a.Offset + if t := immaddr(int32(c.instoffset)); t != 0 { + if immhalf(int32(c.instoffset)) { /* n.b. that it will also satisfy immrot */ if immfloat(t) { return C_HFOREG } @@ -1065,16 +1076,16 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { if immfloat(t) { return C_FOREG /* n.b. that it will also satisfy immrot */ } - if immrot(uint32(ctxt.Instoffset)) != 0 { + if immrot(uint32(c.instoffset)) != 0 { return C_SROREG } - if immhalf(int32(ctxt.Instoffset)) { + if immhalf(int32(c.instoffset)) { return C_HOREG } return C_SOREG } - if immrot(uint32(ctxt.Instoffset)) != 0 { + if immrot(uint32(c.instoffset)) != 0 { return C_ROREG } return C_LOREG @@ -1083,10 +1094,10 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { return C_GOK case obj.TYPE_FCONST: - if chipzero5(ctxt, a.Val.(float64)) >= 0 { + if c.chipzero5(a.Val.(float64)) >= 0 { return C_ZFCON } - if chipfloat5(ctxt, a.Val.(float64)) >= 0 { + if c.chipfloat5(a.Val.(float64)) >= 0 { return C_SFCON } return C_LFCON @@ -1098,15 +1109,15 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { obj.TYPE_ADDR: switch a.Name { case obj.NAME_NONE: - ctxt.Instoffset = a.Offset + c.instoffset = a.Offset if a.Reg != 0 { - return aconsize(ctxt) + return c.aconsize() } - if immrot(uint32(ctxt.Instoffset)) != 0 { + if immrot(uint32(c.instoffset)) != 0 { return C_RCON } - if immrot(^uint32(ctxt.Instoffset)) != 0 { + if immrot(^uint32(c.instoffset)) != 0 { return C_NCON } return C_LCON @@ -1118,16 +1129,16 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { if s == nil { break } - ctxt.Instoffset = 0 // s.b. unused but just in case + c.instoffset = 0 // s.b. unused but just in case return C_LCONADDR case obj.NAME_AUTO: - ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset - return aconsize(ctxt) + c.instoffset = c.autosize + a.Offset + return c.aconsize() case obj.NAME_PARAM: - ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 4 - return aconsize(ctxt) + c.instoffset = c.autosize + a.Offset + 4 + return c.aconsize() } return C_GOK @@ -1139,31 +1150,31 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { return C_GOK } -func aconsize(ctxt *obj.Link) int { - if immrot(uint32(ctxt.Instoffset)) != 0 { +func (c *ctxt5) aconsize() int { + if immrot(uint32(c.instoffset)) != 0 { return C_RACON } - if immrot(uint32(-ctxt.Instoffset)) != 0 { + if immrot(uint32(-c.instoffset)) != 0 { return C_RACON } return C_LACON } -func oplook(ctxt *obj.Link, p *obj.Prog) *Optab { +func (c *ctxt5) oplook(p *obj.Prog) *Optab { a1 := int(p.Optab) if a1 != 0 { return &optab[a1-1] } a1 = int(p.From.Class) if a1 == 0 { - a1 = aclass(ctxt, &p.From) + 1 + a1 = c.aclass(&p.From) + 1 p.From.Class = int8(a1) } a1-- a3 := int(p.To.Class) if a3 == 0 { - a3 = aclass(ctxt, &p.To) + 1 + a3 = c.aclass(&p.To) + 1 p.To.Class = int8(a3) } @@ -1189,8 +1200,8 @@ func oplook(ctxt *obj.Link, p *obj.Prog) *Optab { } } - ctxt.Diag("illegal combination %v; %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.To.Type) - ctxt.Diag("from %d %d to %d %d\n", p.From.Type, p.From.Name, p.To.Type, p.To.Name) + c.ctxt.Diag("illegal combination %v; %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.To.Type) + c.ctxt.Diag("from %d %d to %d %d\n", p.From.Type, p.From.Name, p.To.Type, p.To.Name) if ops == nil { ops = optab } @@ -1300,6 +1311,13 @@ func buildop(ctxt *obj.Link) { return } + deferreturn = ctxt.Lookup("runtime.deferreturn", 0) + + symdiv = ctxt.Lookup("_div", 0) + symdivu = ctxt.Lookup("_divu", 0) + symmod = ctxt.Lookup("_mod", 0) + symmodu = ctxt.Lookup("_modu", 0) + var n int for i := 0; i < C_GOK; i++ { @@ -1478,21 +1496,20 @@ func buildop(ctxt *obj.Link) { } } -func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { - ctxt.Printp = p +func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) { + c.printp = p o1 := uint32(0) o2 := uint32(0) o3 := uint32(0) o4 := uint32(0) o5 := uint32(0) o6 := uint32(0) - ctxt.Armsize += int32(o.size) if false { /*debug['P']*/ fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_) } switch o.type_ { default: - ctxt.Diag("%v: unknown asm %d", p, o.type_) + c.ctxt.Diag("%v: unknown asm %d", p, o.type_) case 0: /* pseudo ops */ if false { /*debug['G']*/ @@ -1500,7 +1517,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { } case 1: /* op R,[R],R */ - o1 = oprrr(ctxt, p, p.As, int(p.Scond)) + o1 = c.oprrr(p, p.As, int(p.Scond)) rf := int(p.From.Reg) rt := int(p.To.Reg) @@ -1516,10 +1533,10 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 case 2: /* movbu $I,[R],R */ - aclass(ctxt, &p.From) + c.aclass(&p.From) - o1 = oprrr(ctxt, p, p.As, int(p.Scond)) - o1 |= uint32(immrot(uint32(ctxt.Instoffset))) + o1 = c.oprrr(p, p.As, int(p.Scond)) + o1 |= uint32(immrot(uint32(c.instoffset))) rt := int(p.To.Reg) r := int(p.Reg) if p.To.Type == obj.TYPE_NONE { @@ -1533,16 +1550,16 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 case 3: /* add R<<[IR],[R],R */ - o1 = mov(ctxt, p) + o1 = c.mov(p) case 4: /* MOVW $off(R), R -> add $off,[R],R */ - aclass(ctxt, &p.From) - if ctxt.Instoffset < 0 { - o1 = oprrr(ctxt, p, ASUB, int(p.Scond)) - o1 |= uint32(immrot(uint32(-ctxt.Instoffset))) + c.aclass(&p.From) + if c.instoffset < 0 { + o1 = c.oprrr(p, ASUB, int(p.Scond)) + o1 |= uint32(immrot(uint32(-c.instoffset))) } else { - o1 = oprrr(ctxt, p, AADD, int(p.Scond)) - o1 |= uint32(immrot(uint32(ctxt.Instoffset))) + o1 = c.oprrr(p, AADD, int(p.Scond)) + o1 |= uint32(immrot(uint32(c.instoffset))) } r := int(p.From.Reg) if r == 0 { @@ -1552,12 +1569,12 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { o1 |= (uint32(p.To.Reg) & 15) << 12 case 5: /* bra s */ - o1 = opbra(ctxt, p, p.As, int(p.Scond)) + o1 = c.opbra(p, p.As, int(p.Scond)) v := int32(-8) if p.To.Sym != nil { - rel := obj.Addrel(ctxt.Cursym) - rel.Off = int32(ctxt.Pc) + rel := obj.Addrel(c.cursym) + rel.Off = int32(c.pc) rel.Siz = 4 rel.Sym = p.To.Sym v += int32(p.To.Offset) @@ -1567,45 +1584,45 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { } if p.Pcond != nil { - v = int32((p.Pcond.Pc - ctxt.Pc) - 8) + v = int32((p.Pcond.Pc - c.pc) - 8) } o1 |= (uint32(v) >> 2) & 0xffffff case 6: /* b ,O(R) -> add $O,R,PC */ - aclass(ctxt, &p.To) + c.aclass(&p.To) - o1 = oprrr(ctxt, p, AADD, int(p.Scond)) - o1 |= uint32(immrot(uint32(ctxt.Instoffset))) + o1 = c.oprrr(p, AADD, int(p.Scond)) + o1 |= uint32(immrot(uint32(c.instoffset))) o1 |= (uint32(p.To.Reg) & 15) << 16 o1 |= (REGPC & 15) << 12 case 7: /* bl (R) -> blx R */ - aclass(ctxt, &p.To) + c.aclass(&p.To) - if ctxt.Instoffset != 0 { - ctxt.Diag("%v: doesn't support BL offset(REG) with non-zero offset %d", p, ctxt.Instoffset) + if c.instoffset != 0 { + c.ctxt.Diag("%v: doesn't support BL offset(REG) with non-zero offset %d", p, c.instoffset) } - o1 = oprrr(ctxt, p, ABL, int(p.Scond)) + o1 = c.oprrr(p, ABL, int(p.Scond)) o1 |= (uint32(p.To.Reg) & 15) << 0 - rel := obj.Addrel(ctxt.Cursym) - rel.Off = int32(ctxt.Pc) + rel := obj.Addrel(c.cursym) + rel.Off = int32(c.pc) rel.Siz = 0 rel.Type = obj.R_CALLIND case 8: /* sll $c,[R],R -> mov (R<<$c),R */ - aclass(ctxt, &p.From) + c.aclass(&p.From) - o1 = oprrr(ctxt, p, p.As, int(p.Scond)) + o1 = c.oprrr(p, p.As, int(p.Scond)) r := int(p.Reg) if r == 0 { r = int(p.To.Reg) } o1 |= (uint32(r) & 15) << 0 - o1 |= uint32((ctxt.Instoffset & 31) << 7) + o1 |= uint32((c.instoffset & 31) << 7) o1 |= (uint32(p.To.Reg) & 15) << 12 case 9: /* sll R,[R],R -> mov (R< lr */ - aclass(ctxt, &p.From) + c.aclass(&p.From) r := int(p.From.Reg) if r == 0 { r = int(o.param) } - o1 = olr(ctxt, int32(ctxt.Instoffset), r, int(p.To.Reg), int(p.Scond)) + o1 = c.olr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond)) if p.As != AMOVW { o1 |= 1 << 22 } case 30: /* mov/movb/movbu R,L(R) */ - o1 = omvl(ctxt, p, &p.To, REGTMP) + o1 = c.omvl(p, &p.To, REGTMP) if o1 == 0 { break @@ -1762,13 +1779,13 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { if r == 0 { r = int(o.param) } - o2 = osrr(ctxt, int(p.From.Reg), REGTMP&15, r, int(p.Scond)) + o2 = c.osrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond)) if p.As != AMOVW { o2 |= 1 << 22 } case 31: /* mov/movbu L(R),R -> lr[b] */ - o1 = omvl(ctxt, p, &p.From, REGTMP) + o1 = c.omvl(p, &p.From, REGTMP) if o1 == 0 { break @@ -1777,19 +1794,19 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { if r == 0 { r = int(o.param) } - o2 = olrr(ctxt, REGTMP&15, r, int(p.To.Reg), int(p.Scond)) + o2 = c.olrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond)) if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB { o2 |= 1 << 22 } case 34: /* mov $lacon,R */ - o1 = omvl(ctxt, p, &p.From, REGTMP) + o1 = c.omvl(p, &p.From, REGTMP) if o1 == 0 { break } - o2 = oprrr(ctxt, p, AADD, int(p.Scond)) + o2 = c.oprrr(p, AADD, int(p.Scond)) o2 |= REGTMP & 15 r := int(p.From.Reg) if r == 0 { @@ -1818,14 +1835,14 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { o1 |= (uint32(p.From.Reg) & 15) << 0 case 37: /* mov $con,PSR */ - aclass(ctxt, &p.From) + c.aclass(&p.From) o1 = 2<<23 | 0x29f<<12 | 0<<4 if p.Scond&C_FBIT != 0 { o1 ^= 0x010 << 12 } o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 - o1 |= uint32(immrot(uint32(ctxt.Instoffset))) + o1 |= uint32(immrot(uint32(c.instoffset))) o1 |= (uint32(p.To.Reg) & 1) << 22 o1 |= (uint32(p.From.Reg) & 15) << 0 @@ -1836,18 +1853,18 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { o1 |= uint32(p.From.Offset & 0xffff) o1 |= (uint32(p.To.Reg) & 15) << 16 - aclass(ctxt, &p.To) + c.aclass(&p.To) case 39: /* movm oreg,$con -> ldm */ o1 = 0x4<<25 | 1<<20 o1 |= uint32(p.To.Offset & 0xffff) o1 |= (uint32(p.From.Reg) & 15) << 16 - aclass(ctxt, &p.From) + c.aclass(&p.From) } - if ctxt.Instoffset != 0 { - ctxt.Diag("offset must be zero in MOVM; %v", p) + if c.instoffset != 0 { + c.ctxt.Diag("offset must be zero in MOVM; %v", p) } o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 if p.Scond&C_PBIT != 0 { @@ -1864,10 +1881,10 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { } case 40: /* swp oreg,reg,reg */ - aclass(ctxt, &p.From) + c.aclass(&p.From) - if ctxt.Instoffset != 0 { - ctxt.Diag("offset must be zero in SWP") + if c.instoffset != 0 { + c.ctxt.Diag("offset must be zero in SWP") } o1 = 0x2<<23 | 0x9<<4 if p.As != ASWPW { @@ -1882,25 +1899,25 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { o1 = 0xe8fd8000 case 50: /* floating point store */ - v := regoff(ctxt, &p.To) + v := c.regoff(&p.To) r := int(p.To.Reg) if r == 0 { r = int(o.param) } - o1 = ofsr(ctxt, p.As, int(p.From.Reg), v, r, int(p.Scond), p) + o1 = c.ofsr(p.As, int(p.From.Reg), v, r, int(p.Scond), p) case 51: /* floating point load */ - v := regoff(ctxt, &p.From) + v := c.regoff(&p.From) r := int(p.From.Reg) if r == 0 { r = int(o.param) } - o1 = ofsr(ctxt, p.As, int(p.To.Reg), v, r, int(p.Scond), p) | 1<<20 + o1 = c.ofsr(p.As, int(p.To.Reg), v, r, int(p.Scond), p) | 1<<20 case 52: /* floating point store, int32 offset UGLY */ - o1 = omvl(ctxt, p, &p.To, REGTMP) + o1 = c.omvl(p, &p.To, REGTMP) if o1 == 0 { break @@ -1909,11 +1926,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { if r == 0 { r = int(o.param) } - o2 = oprrr(ctxt, p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0 - o3 = ofsr(ctxt, p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p) + o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0 + o3 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p) case 53: /* floating point load, int32 offset UGLY */ - o1 = omvl(ctxt, p, &p.From, REGTMP) + o1 = c.omvl(p, &p.From, REGTMP) if o1 == 0 { break @@ -1922,11 +1939,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { if r == 0 { r = int(o.param) } - o2 = oprrr(ctxt, p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0 - o3 = ofsr(ctxt, p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20 + o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0 + o3 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20 case 54: /* floating point arith */ - o1 = oprrr(ctxt, p, p.As, int(p.Scond)) + o1 = c.oprrr(p, p.As, int(p.Scond)) rf := int(p.From.Reg) rt := int(p.To.Reg) @@ -1951,7 +1968,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { o1 |= ((uint32(p.From.Reg)&1)+1)<<21 | (uint32(p.To.Reg)&15)<<12 | 1<<20 case 58: /* movbu R,R */ - o1 = oprrr(ctxt, p, AAND, int(p.Scond)) + o1 = c.oprrr(p, AAND, int(p.Scond)) o1 |= uint32(immrot(0xff)) rt := int(p.To.Reg) @@ -1967,95 +1984,95 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { case 59: /* movw/bu R< ldr indexed */ if p.From.Reg == 0 { if p.As != AMOVW { - ctxt.Diag("byte MOV from shifter operand") + c.ctxt.Diag("byte MOV from shifter operand") } - o1 = mov(ctxt, p) + o1 = c.mov(p) break } if p.From.Offset&(1<<4) != 0 { - ctxt.Diag("bad shift in LDR") + c.ctxt.Diag("bad shift in LDR") } - o1 = olrr(ctxt, int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond)) + o1 = c.olrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond)) if p.As == AMOVBU { o1 |= 1 << 22 } case 60: /* movb R(R),R -> ldrsb indexed */ if p.From.Reg == 0 { - ctxt.Diag("byte MOV from shifter operand") - o1 = mov(ctxt, p) + c.ctxt.Diag("byte MOV from shifter operand") + o1 = c.mov(p) break } if p.From.Offset&(^0xf) != 0 { - ctxt.Diag("bad shift in LDRSB") + c.ctxt.Diag("bad shift in LDRSB") } - o1 = olhrr(ctxt, int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond)) + o1 = c.olhrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond)) o1 ^= 1<<5 | 1<<6 case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */ if p.To.Reg == 0 { - ctxt.Diag("MOV to shifter operand") + c.ctxt.Diag("MOV to shifter operand") } - o1 = osrr(ctxt, int(p.From.Reg), int(p.To.Offset), int(p.To.Reg), int(p.Scond)) + o1 = c.osrr(int(p.From.Reg), int(p.To.Offset), int(p.To.Reg), int(p.Scond)) if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU { o1 |= 1 << 22 } /* reloc ops */ case 64: /* mov/movb/movbu R,addr */ - o1 = omvl(ctxt, p, &p.To, REGTMP) + o1 = c.omvl(p, &p.To, REGTMP) if o1 == 0 { break } - o2 = osr(ctxt, p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond)) + o2 = c.osr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond)) if o.flag&LPCREL != 0 { o3 = o2 - o2 = oprrr(ctxt, p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 + o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 } case 65: /* mov/movbu addr,R */ - o1 = omvl(ctxt, p, &p.From, REGTMP) + o1 = c.omvl(p, &p.From, REGTMP) if o1 == 0 { break } - o2 = olr(ctxt, 0, REGTMP, int(p.To.Reg), int(p.Scond)) + o2 = c.olr(0, REGTMP, int(p.To.Reg), int(p.Scond)) if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB { o2 |= 1 << 22 } if o.flag&LPCREL != 0 { o3 = o2 - o2 = oprrr(ctxt, p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 + o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 } case 101: /* movw tlsvar,R, local exec*/ if p.Scond&C_SCOND != C_SCOND_NONE { - ctxt.Diag("conditional tls") + c.ctxt.Diag("conditional tls") } - o1 = omvl(ctxt, p, &p.From, int(p.To.Reg)) + o1 = c.omvl(p, &p.From, int(p.To.Reg)) case 102: /* movw tlsvar,R, initial exec*/ if p.Scond&C_SCOND != C_SCOND_NONE { - ctxt.Diag("conditional tls") + c.ctxt.Diag("conditional tls") } - o1 = omvl(ctxt, p, &p.From, int(p.To.Reg)) - o2 = olrr(ctxt, int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond)) + o1 = c.omvl(p, &p.From, int(p.To.Reg)) + o2 = c.olrr(int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond)) case 103: /* word tlsvar, local exec */ if p.To.Sym == nil { - ctxt.Diag("nil sym in tls %v", p) + c.ctxt.Diag("nil sym in tls %v", p) } if p.To.Offset != 0 { - ctxt.Diag("offset against tls var in %v", p) + c.ctxt.Diag("offset against tls var in %v", p) } // This case happens with words generated in the PC stream as part of - // the literal pool. - rel := obj.Addrel(ctxt.Cursym) + // the literal c.pool. + rel := obj.Addrel(c.cursym) - rel.Off = int32(ctxt.Pc) + rel.Off = int32(c.pc) rel.Siz = 4 rel.Sym = p.To.Sym rel.Type = obj.R_TLS_LE @@ -2063,60 +2080,60 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { case 104: /* word tlsvar, initial exec */ if p.To.Sym == nil { - ctxt.Diag("nil sym in tls %v", p) + c.ctxt.Diag("nil sym in tls %v", p) } if p.To.Offset != 0 { - ctxt.Diag("offset against tls var in %v", p) + c.ctxt.Diag("offset against tls var in %v", p) } - rel := obj.Addrel(ctxt.Cursym) - rel.Off = int32(ctxt.Pc) + rel := obj.Addrel(c.cursym) + rel.Off = int32(c.pc) rel.Siz = 4 rel.Sym = p.To.Sym rel.Type = obj.R_TLS_IE - rel.Add = ctxt.Pc - p.Rel.Pc - 8 - int64(rel.Siz) + rel.Add = c.pc - p.Rel.Pc - 8 - int64(rel.Siz) case 68: /* floating point store -> ADDR */ - o1 = omvl(ctxt, p, &p.To, REGTMP) + o1 = c.omvl(p, &p.To, REGTMP) if o1 == 0 { break } - o2 = ofsr(ctxt, p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p) + o2 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p) if o.flag&LPCREL != 0 { o3 = o2 - o2 = oprrr(ctxt, p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 + o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 } case 69: /* floating point load <- ADDR */ - o1 = omvl(ctxt, p, &p.From, REGTMP) + o1 = c.omvl(p, &p.From, REGTMP) if o1 == 0 { break } - o2 = ofsr(ctxt, p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20 + o2 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20 if o.flag&LPCREL != 0 { o3 = o2 - o2 = oprrr(ctxt, p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 + o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 } /* ArmV4 ops: */ case 70: /* movh/movhu R,O(R) -> strh */ - aclass(ctxt, &p.To) + c.aclass(&p.To) r := int(p.To.Reg) if r == 0 { r = int(o.param) } - o1 = oshr(ctxt, int(p.From.Reg), int32(ctxt.Instoffset), r, int(p.Scond)) + o1 = c.oshr(int(p.From.Reg), int32(c.instoffset), r, int(p.Scond)) case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */ - aclass(ctxt, &p.From) + c.aclass(&p.From) r := int(p.From.Reg) if r == 0 { r = int(o.param) } - o1 = olhr(ctxt, int32(ctxt.Instoffset), r, int(p.To.Reg), int(p.Scond)) + o1 = c.olhr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond)) if p.As == AMOVB || p.As == AMOVBS { o1 ^= 1<<5 | 1<<6 } else if p.As == AMOVH || p.As == AMOVHS { @@ -2124,7 +2141,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { } case 72: /* movh/movhu R,L(R) -> strh */ - o1 = omvl(ctxt, p, &p.To, REGTMP) + o1 = c.omvl(p, &p.To, REGTMP) if o1 == 0 { break @@ -2133,10 +2150,10 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { if r == 0 { r = int(o.param) } - o2 = oshrr(ctxt, int(p.From.Reg), REGTMP&15, r, int(p.Scond)) + o2 = c.oshrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond)) case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */ - o1 = omvl(ctxt, p, &p.From, REGTMP) + o1 = c.omvl(p, &p.From, REGTMP) if o1 == 0 { break @@ -2145,7 +2162,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { if r == 0 { r = int(o.param) } - o2 = olhrr(ctxt, REGTMP&15, r, int(p.To.Reg), int(p.Scond)) + o2 = c.olhrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond)) if p.As == AMOVB || p.As == AMOVBS { o2 ^= 1<<5 | 1<<6 } else if p.As == AMOVH || p.As == AMOVHS { @@ -2153,36 +2170,36 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { } case 74: /* bx $I */ - ctxt.Diag("ABX $I") + c.ctxt.Diag("ABX $I") case 75: /* bx O(R) */ - aclass(ctxt, &p.To) + c.aclass(&p.To) - if ctxt.Instoffset != 0 { - ctxt.Diag("non-zero offset in ABX") + if c.instoffset != 0 { + c.ctxt.Diag("non-zero offset in ABX") } /* - o1 = oprrr(ctxt, p, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12); // mov PC, LR + o1 = c.oprrr(p, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12); // mov PC, LR o2 = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | (0x12fff<<8) | (1<<4) | ((p->to.reg&15) << 0); // BX R */ // p->to.reg may be REGLINK - o1 = oprrr(ctxt, p, AADD, int(p.Scond)) + o1 = c.oprrr(p, AADD, int(p.Scond)) - o1 |= uint32(immrot(uint32(ctxt.Instoffset))) + o1 |= uint32(immrot(uint32(c.instoffset))) o1 |= (uint32(p.To.Reg) & 15) << 16 o1 |= (REGTMP & 15) << 12 - o2 = oprrr(ctxt, p, AADD, int(p.Scond)) | uint32(immrot(0)) | (REGPC&15)<<16 | (REGLINK&15)<<12 // mov PC, LR - o3 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x12fff<<8 | 1<<4 | REGTMP&15 // BX Rtmp + o2 = c.oprrr(p, AADD, int(p.Scond)) | uint32(immrot(0)) | (REGPC&15)<<16 | (REGLINK&15)<<12 // mov PC, LR + o3 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x12fff<<8 | 1<<4 | REGTMP&15 // BX Rtmp case 76: /* bx O(R) when returning from fn*/ - ctxt.Diag("ABXRET") + c.ctxt.Diag("ABXRET") case 77: /* ldrex oreg,reg */ - aclass(ctxt, &p.From) + c.aclass(&p.From) - if ctxt.Instoffset != 0 { - ctxt.Diag("offset must be zero in LDREX") + if c.instoffset != 0 { + c.ctxt.Diag("offset must be zero in LDREX") } o1 = 0x19<<20 | 0xf9f o1 |= (uint32(p.From.Reg) & 15) << 16 @@ -2190,10 +2207,10 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 case 78: /* strex reg,oreg,reg */ - aclass(ctxt, &p.From) + c.aclass(&p.From) - if ctxt.Instoffset != 0 { - ctxt.Diag("offset must be zero in STREX") + if c.instoffset != 0 { + c.ctxt.Diag("offset must be zero in STREX") } o1 = 0x18<<20 | 0xf90 o1 |= (uint32(p.From.Reg) & 15) << 16 @@ -2204,10 +2221,10 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { case 80: /* fmov zfcon,freg */ if p.As == AMOVD { o1 = 0xeeb00b00 // VMOV imm 64 - o2 = oprrr(ctxt, p, ASUBD, int(p.Scond)) + o2 = c.oprrr(p, ASUBD, int(p.Scond)) } else { o1 = 0x0eb00a00 // VMOV imm 32 - o2 = oprrr(ctxt, p, ASUBF, int(p.Scond)) + o2 = c.oprrr(p, ASUBF, int(p.Scond)) } v := int32(0x70) // 1.0 @@ -2230,73 +2247,73 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { } o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 o1 |= (uint32(p.To.Reg) & 15) << 12 - v := int32(chipfloat5(ctxt, p.From.Val.(float64))) + v := int32(c.chipfloat5(p.From.Val.(float64))) o1 |= (uint32(v) & 0xf) << 0 o1 |= (uint32(v) & 0xf0) << 12 case 82: /* fcmp freg,freg, */ - o1 = oprrr(ctxt, p, p.As, int(p.Scond)) + o1 = c.oprrr(p, p.As, int(p.Scond)) o1 |= (uint32(p.Reg)&15)<<12 | (uint32(p.From.Reg)&15)<<0 o2 = 0x0ef1fa10 // VMRS R15 o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 case 83: /* fcmp freg,, */ - o1 = oprrr(ctxt, p, p.As, int(p.Scond)) + o1 = c.oprrr(p, p.As, int(p.Scond)) o1 |= (uint32(p.From.Reg)&15)<<12 | 1<<16 o2 = 0x0ef1fa10 // VMRS R15 o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 case 84: /* movfw freg,freg - truncate float-to-fix */ - o1 = oprrr(ctxt, p, p.As, int(p.Scond)) + o1 = c.oprrr(p, p.As, int(p.Scond)) o1 |= (uint32(p.From.Reg) & 15) << 0 o1 |= (uint32(p.To.Reg) & 15) << 12 case 85: /* movwf freg,freg - fix-to-float */ - o1 = oprrr(ctxt, p, p.As, int(p.Scond)) + o1 = c.oprrr(p, p.As, int(p.Scond)) o1 |= (uint32(p.From.Reg) & 15) << 0 o1 |= (uint32(p.To.Reg) & 15) << 12 // macro for movfw freg,FTMP; movw FTMP,reg case 86: /* movfw freg,reg - truncate float-to-fix */ - o1 = oprrr(ctxt, p, p.As, int(p.Scond)) + o1 = c.oprrr(p, p.As, int(p.Scond)) o1 |= (uint32(p.From.Reg) & 15) << 0 o1 |= (FREGTMP & 15) << 12 - o2 = oprrr(ctxt, p, -AMOVFW, int(p.Scond)) + o2 = c.oprrr(p, -AMOVFW, int(p.Scond)) o2 |= (FREGTMP & 15) << 16 o2 |= (uint32(p.To.Reg) & 15) << 12 // macro for movw reg,FTMP; movwf FTMP,freg case 87: /* movwf reg,freg - fix-to-float */ - o1 = oprrr(ctxt, p, -AMOVWF, int(p.Scond)) + o1 = c.oprrr(p, -AMOVWF, int(p.Scond)) o1 |= (uint32(p.From.Reg) & 15) << 12 o1 |= (FREGTMP & 15) << 16 - o2 = oprrr(ctxt, p, p.As, int(p.Scond)) + o2 = c.oprrr(p, p.As, int(p.Scond)) o2 |= (FREGTMP & 15) << 0 o2 |= (uint32(p.To.Reg) & 15) << 12 case 88: /* movw reg,freg */ - o1 = oprrr(ctxt, p, -AMOVWF, int(p.Scond)) + o1 = c.oprrr(p, -AMOVWF, int(p.Scond)) o1 |= (uint32(p.From.Reg) & 15) << 12 o1 |= (uint32(p.To.Reg) & 15) << 16 case 89: /* movw freg,reg */ - o1 = oprrr(ctxt, p, -AMOVFW, int(p.Scond)) + o1 = c.oprrr(p, -AMOVFW, int(p.Scond)) o1 |= (uint32(p.From.Reg) & 15) << 16 o1 |= (uint32(p.To.Reg) & 15) << 12 case 91: /* ldrexd oreg,reg */ - aclass(ctxt, &p.From) + c.aclass(&p.From) - if ctxt.Instoffset != 0 { - ctxt.Diag("offset must be zero in LDREX") + if c.instoffset != 0 { + c.ctxt.Diag("offset must be zero in LDREX") } o1 = 0x1b<<20 | 0xf9f o1 |= (uint32(p.From.Reg) & 15) << 16 @@ -2304,10 +2321,10 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 case 92: /* strexd reg,oreg,reg */ - aclass(ctxt, &p.From) + c.aclass(&p.From) - if ctxt.Instoffset != 0 { - ctxt.Diag("offset must be zero in STREX") + if c.instoffset != 0 { + c.ctxt.Diag("offset must be zero in STREX") } o1 = 0x1a<<20 | 0xf90 o1 |= (uint32(p.From.Reg) & 15) << 16 @@ -2316,12 +2333,12 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */ - o1 = omvl(ctxt, p, &p.From, REGTMP) + o1 = c.omvl(p, &p.From, REGTMP) if o1 == 0 { break } - o2 = olhr(ctxt, 0, REGTMP, int(p.To.Reg), int(p.Scond)) + o2 = c.olhr(0, REGTMP, int(p.To.Reg), int(p.Scond)) if p.As == AMOVB || p.As == AMOVBS { o2 ^= 1<<5 | 1<<6 } else if p.As == AMOVH || p.As == AMOVHS { @@ -2329,19 +2346,19 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { } if o.flag&LPCREL != 0 { o3 = o2 - o2 = oprrr(ctxt, p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 + o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 } case 94: /* movh/movhu R,addr -> strh */ - o1 = omvl(ctxt, p, &p.To, REGTMP) + o1 = c.omvl(p, &p.To, REGTMP) if o1 == 0 { break } - o2 = oshr(ctxt, int(p.From.Reg), 0, REGTMP, int(p.Scond)) + o2 = c.oshr(int(p.From.Reg), 0, REGTMP, int(p.Scond)) if o.flag&LPCREL != 0 { o3 = o2 - o2 = oprrr(ctxt, p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 + o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 } case 95: /* PLD off(reg) */ @@ -2364,20 +2381,20 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { o1 = 0xf7fabcfd case 97: /* CLZ Rm, Rd */ - o1 = oprrr(ctxt, p, p.As, int(p.Scond)) + o1 = c.oprrr(p, p.As, int(p.Scond)) o1 |= (uint32(p.To.Reg) & 15) << 12 o1 |= (uint32(p.From.Reg) & 15) << 0 case 98: /* MULW{T,B} Rs, Rm, Rd */ - o1 = oprrr(ctxt, p, p.As, int(p.Scond)) + o1 = c.oprrr(p, p.As, int(p.Scond)) o1 |= (uint32(p.To.Reg) & 15) << 16 o1 |= (uint32(p.From.Reg) & 15) << 8 o1 |= (uint32(p.Reg) & 15) << 0 case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */ - o1 = oprrr(ctxt, p, p.As, int(p.Scond)) + o1 = c.oprrr(p, p.As, int(p.Scond)) o1 |= (uint32(p.To.Reg) & 15) << 12 o1 |= (uint32(p.From.Reg) & 15) << 8 @@ -2401,9 +2418,9 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { return } -func mov(ctxt *obj.Link, p *obj.Prog) uint32 { - aclass(ctxt, &p.From) - o1 := oprrr(ctxt, p, p.As, int(p.Scond)) +func (c *ctxt5) mov(p *obj.Prog) uint32 { + c.aclass(&p.From) + o1 := c.oprrr(p, p.As, int(p.Scond)) o1 |= uint32(p.From.Offset) rt := int(p.To.Reg) if p.To.Type == obj.TYPE_NONE { @@ -2419,13 +2436,13 @@ func mov(ctxt *obj.Link, p *obj.Prog) uint32 { return o1 } -func oprrr(ctxt *obj.Link, p *obj.Prog, a obj.As, sc int) uint32 { +func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 { o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 if sc&C_SBIT != 0 { o |= 1 << 20 } if sc&(C_PBIT|C_WBIT) != 0 { - ctxt.Diag(".nil/.W on dp instruction") + c.ctxt.Diag(".nil/.W on dp instruction") } switch a { case AMMUL: @@ -2604,13 +2621,13 @@ func oprrr(ctxt *obj.Link, p *obj.Prog, a obj.As, sc int) uint32 { return o&(0xf<<28) | 0x12fff3<<4 } - ctxt.Diag("%v: bad rrr %d", p, a) + c.ctxt.Diag("%v: bad rrr %d", p, a) return 0 } -func opbra(ctxt *obj.Link, p *obj.Prog, a obj.As, sc int) uint32 { +func (c *ctxt5) opbra(p *obj.Prog, a obj.As, sc int) uint32 { if sc&(C_SBIT|C_PBIT|C_WBIT) != 0 { - ctxt.Diag("%v: .nil/.nil/.W on bra instruction", p) + c.ctxt.Diag("%v: .nil/.nil/.W on bra instruction", p) } sc &= C_SCOND sc ^= C_SCOND_XOR @@ -2618,7 +2635,7 @@ func opbra(ctxt *obj.Link, p *obj.Prog, a obj.As, sc int) uint32 { return uint32(sc)<<28 | 0x5<<25 | 0x1<<24 } if sc != 0xe { - ctxt.Diag("%v: .COND on bcond instruction", p) + c.ctxt.Diag("%v: .COND on bcond instruction", p) } switch a { case ABEQ: @@ -2657,13 +2674,13 @@ func opbra(ctxt *obj.Link, p *obj.Prog, a obj.As, sc int) uint32 { return 0xe<<28 | 0x5<<25 } - ctxt.Diag("%v: bad bra %v", p, a) + c.ctxt.Diag("%v: bad bra %v", p, a) return 0 } -func olr(ctxt *obj.Link, v int32, b int, r int, sc int) uint32 { +func (c *ctxt5) olr(v int32, b int, r int, sc int) uint32 { if sc&C_SBIT != 0 { - ctxt.Diag(".nil on LDR/STR instruction") + c.ctxt.Diag(".nil on LDR/STR instruction") } o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 if sc&C_PBIT == 0 { @@ -2678,14 +2695,14 @@ func olr(ctxt *obj.Link, v int32, b int, r int, sc int) uint32 { o |= 1<<26 | 1<<20 if v < 0 { if sc&C_UBIT != 0 { - ctxt.Diag(".U on neg offset") + c.ctxt.Diag(".U on neg offset") } v = -v o ^= 1 << 23 } if v >= 1<<12 || v < 0 { - ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, ctxt.Printp) + c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp) } o |= uint32(v) o |= (uint32(b) & 15) << 16 @@ -2693,9 +2710,9 @@ func olr(ctxt *obj.Link, v int32, b int, r int, sc int) uint32 { return o } -func olhr(ctxt *obj.Link, v int32, b int, r int, sc int) uint32 { +func (c *ctxt5) olhr(v int32, b int, r int, sc int) uint32 { if sc&C_SBIT != 0 { - ctxt.Diag(".nil on LDRH/STRH instruction") + c.ctxt.Diag(".nil on LDRH/STRH instruction") } o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 if sc&C_PBIT == 0 { @@ -2711,7 +2728,7 @@ func olhr(ctxt *obj.Link, v int32, b int, r int, sc int) uint32 { } if v >= 1<<8 || v < 0 { - ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, ctxt.Printp) + c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp) } o |= uint32(v)&0xf | (uint32(v)>>4)<<8 | 1<<22 o |= (uint32(b) & 15) << 16 @@ -2719,38 +2736,38 @@ func olhr(ctxt *obj.Link, v int32, b int, r int, sc int) uint32 { return o } -func osr(ctxt *obj.Link, a obj.As, r int, v int32, b int, sc int) uint32 { - o := olr(ctxt, v, b, r, sc) ^ (1 << 20) +func (c *ctxt5) osr(a obj.As, r int, v int32, b int, sc int) uint32 { + o := c.olr(v, b, r, sc) ^ (1 << 20) if a != AMOVW { o |= 1 << 22 } return o } -func oshr(ctxt *obj.Link, r int, v int32, b int, sc int) uint32 { - o := olhr(ctxt, v, b, r, sc) ^ (1 << 20) +func (c *ctxt5) oshr(r int, v int32, b int, sc int) uint32 { + o := c.olhr(v, b, r, sc) ^ (1 << 20) return o } -func osrr(ctxt *obj.Link, r int, i int, b int, sc int) uint32 { - return olr(ctxt, int32(i), b, r, sc) ^ (1<<25 | 1<<20) +func (c *ctxt5) osrr(r int, i int, b int, sc int) uint32 { + return c.olr(int32(i), b, r, sc) ^ (1<<25 | 1<<20) } -func oshrr(ctxt *obj.Link, r int, i int, b int, sc int) uint32 { - return olhr(ctxt, int32(i), b, r, sc) ^ (1<<22 | 1<<20) +func (c *ctxt5) oshrr(r int, i int, b int, sc int) uint32 { + return c.olhr(int32(i), b, r, sc) ^ (1<<22 | 1<<20) } -func olrr(ctxt *obj.Link, i int, b int, r int, sc int) uint32 { - return olr(ctxt, int32(i), b, r, sc) ^ (1 << 25) +func (c *ctxt5) olrr(i int, b int, r int, sc int) uint32 { + return c.olr(int32(i), b, r, sc) ^ (1 << 25) } -func olhrr(ctxt *obj.Link, i int, b int, r int, sc int) uint32 { - return olhr(ctxt, int32(i), b, r, sc) ^ (1 << 22) +func (c *ctxt5) olhrr(i int, b int, r int, sc int) uint32 { + return c.olhr(int32(i), b, r, sc) ^ (1 << 22) } -func ofsr(ctxt *obj.Link, a obj.As, r int, v int32, b int, sc int, p *obj.Prog) uint32 { +func (c *ctxt5) ofsr(a obj.As, r int, v int32, b int, sc int, p *obj.Prog) uint32 { if sc&C_SBIT != 0 { - ctxt.Diag(".nil on FLDR/FSTR instruction: %v", p) + c.ctxt.Diag(".nil on FLDR/FSTR instruction: %v", p) } o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 if sc&C_PBIT == 0 { @@ -2766,9 +2783,9 @@ func ofsr(ctxt *obj.Link, a obj.As, r int, v int32, b int, sc int, p *obj.Prog) } if v&3 != 0 { - ctxt.Diag("odd offset for floating point op: %d\n%v", v, p) + c.ctxt.Diag("odd offset for floating point op: %d\n%v", v, p) } else if v >= 1<<10 || v < 0 { - ctxt.Diag("literal span too large: %d\n%v", v, p) + c.ctxt.Diag("literal span too large: %d\n%v", v, p) } o |= (uint32(v) >> 2) & 0xFF o |= (uint32(b) & 15) << 16 @@ -2776,7 +2793,7 @@ func ofsr(ctxt *obj.Link, a obj.As, r int, v int32, b int, sc int, p *obj.Prog) switch a { default: - ctxt.Diag("bad fst %v", a) + c.ctxt.Diag("bad fst %v", a) fallthrough case AMOVD: @@ -2790,28 +2807,28 @@ func ofsr(ctxt *obj.Link, a obj.As, r int, v int32, b int, sc int, p *obj.Prog) return o } -func omvl(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, dr int) uint32 { +func (c *ctxt5) omvl(p *obj.Prog, a *obj.Addr, dr int) uint32 { var o1 uint32 if p.Pcond == nil { - aclass(ctxt, a) - v := immrot(^uint32(ctxt.Instoffset)) + c.aclass(a) + v := immrot(^uint32(c.instoffset)) if v == 0 { - ctxt.Diag("%v: missing literal", p) + c.ctxt.Diag("%v: missing literal", p) return 0 } - o1 = oprrr(ctxt, p, AMVN, int(p.Scond)&C_SCOND) + o1 = c.oprrr(p, AMVN, int(p.Scond)&C_SCOND) o1 |= uint32(v) o1 |= (uint32(dr) & 15) << 12 } else { v := int32(p.Pcond.Pc - p.Pc - 8) - o1 = olr(ctxt, v, REGPC, dr, int(p.Scond)&C_SCOND) + o1 = c.olr(v, REGPC, dr, int(p.Scond)&C_SCOND) } return o1 } -func chipzero5(ctxt *obj.Link, e float64) int { +func (c *ctxt5) chipzero5(e float64) int { // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions. if obj.GOARM < 7 || e != 0 { return -1 @@ -2819,7 +2836,7 @@ func chipzero5(ctxt *obj.Link, e float64) int { return 0 } -func chipfloat5(ctxt *obj.Link, e float64) int { +func (c *ctxt5) chipfloat5(e float64) int { // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions. if obj.GOARM < 7 { return -1 diff --git a/src/cmd/internal/obj/arm/obj5.go b/src/cmd/internal/obj/arm/obj5.go index 89cf299bef..bf4ad0a69b 100644 --- a/src/cmd/internal/obj/arm/obj5.go +++ b/src/cmd/internal/obj/arm/obj5.go @@ -41,12 +41,11 @@ 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} + // Rewrite B/BL to symbol as TYPE_BRANCH. switch p.As { - case AB, - ABL, - obj.ADUFFZERO, - obj.ADUFFCOPY: + 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 } @@ -104,7 +103,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { // Rewrite float constants to values stored in memory. switch p.As { case AMOVF: - if p.From.Type == obj.TYPE_FCONST && chipfloat5(ctxt, p.From.Val.(float64)) < 0 && (chipzero5(ctxt, p.From.Val.(float64)) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) { + 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) @@ -113,7 +112,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { } case AMOVD: - if p.From.Type == obj.TYPE_FCONST && chipfloat5(ctxt, p.From.Val.(float64)) < 0 && (chipzero5(ctxt, p.From.Val.(float64)) < 0 || p.Scond&C_SCOND != C_SCOND_NONE) { + 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 @@ -122,12 +121,12 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { } if ctxt.Flag_dynlink { - rewriteToUseGot(ctxt, p, newprog) + c.rewriteToUseGot(p) } } // Rewrite p, if necessary, to access global data via the global offset table. -func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { +func (c *ctxt5) rewriteToUseGot(p *obj.Prog) { if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO { // ADUFFxxx $offset // becomes @@ -136,9 +135,9 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { // CALL (R9) var sym *obj.LSym if p.As == obj.ADUFFZERO { - sym = ctxt.Lookup("runtime.duffzero", 0) + sym = c.ctxt.Lookup("runtime.duffzero", 0) } else { - sym = ctxt.Lookup("runtime.duffcopy", 0) + sym = c.ctxt.Lookup("runtime.duffcopy", 0) } offset := p.To.Offset p.As = AMOVW @@ -150,13 +149,13 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { p.To.Name = obj.NAME_NONE p.To.Offset = 0 p.To.Sym = nil - p1 := obj.Appendp(p, newprog) + 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, newprog) + p2 := obj.Appendp(p1, c.newprog) p2.As = obj.ACALL p2.To.Type = obj.TYPE_MEM p2.To.Reg = REG_R9 @@ -170,15 +169,15 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { // MOVW $sym, Rx becomes MOVW sym@GOT, Rx // MOVW $sym+, Rx becomes MOVW sym@GOT, Rx; ADD , Rx if p.As != AMOVW { - ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p) + c.ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p) } if p.To.Type != obj.TYPE_REG { - ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p) + 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, newprog) + q := obj.Appendp(p, c.newprog) q.As = AADD q.From.Type = obj.TYPE_CONST q.From.Offset = p.From.Offset @@ -187,7 +186,7 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { } } if p.From3 != nil && p.From3.Name == obj.NAME_EXTERN { - ctxt.Diag("don't know how to handle %v with -dynlink", p) + c.ctxt.Diag("don't know how to handle %v with -dynlink", p) } var source *obj.Addr // MOVx sym, Ry becomes MOVW sym@GOT, R9; MOVx (R9), Ry @@ -195,7 +194,7 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { // An addition may be inserted between the two MOVs if there is an offset. if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() { if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() { - ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p) + 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() { @@ -210,10 +209,10 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { return } if source.Type != obj.TYPE_MEM { - ctxt.Diag("don't know how to handle %v with -dynlink", p) + c.ctxt.Diag("don't know how to handle %v with -dynlink", p) } - p1 := obj.Appendp(p, newprog) - p2 := obj.Appendp(p1, newprog) + p1 := obj.Appendp(p, c.newprog) + p2 := obj.Appendp(p1, c.newprog) p1.As = AMOVW p1.From.Type = obj.TYPE_MEM @@ -249,15 +248,15 @@ const ( func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { autosize := int32(0) - ctxt.Cursym = cursym - if cursym.Text == nil || cursym.Text.Link == nil { return } - softfloat(ctxt, newprog, cursym) + c := ctxt5{ctxt: ctxt, cursym: cursym, newprog: newprog} - p := cursym.Text + c.softfloat() + + p := c.cursym.Text autoffset := int32(p.To.Offset) if autoffset < 0 { autoffset = 0 @@ -283,9 +282,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { case ADIV, ADIVU, AMOD, AMODU: q = p - if ctxt.Sym_div == nil { - initdiv(ctxt) - } cursym.Text.Mark &^= LEAF continue @@ -362,11 +358,11 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { } if p.From3.Offset&obj.NOSPLIT == 0 { - p = stacksplit(ctxt, p, newprog, autosize) // emit split check + p = c.stacksplit(p, autosize) // emit split check } // MOVW.W R14,$-autosize(SP) - p = obj.Appendp(p, newprog) + p = obj.Appendp(p, c.newprog) p.As = AMOVW p.Scond |= C_WBIT @@ -597,16 +593,13 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { p.To.Type = obj.TYPE_BRANCH switch o { case ADIV: - p.To.Sym = ctxt.Sym_div - + p.To.Sym = symdiv case ADIVU: - p.To.Sym = ctxt.Sym_divu - + p.To.Sym = symdivu case AMOD: - p.To.Sym = ctxt.Sym_mod - + p.To.Sym = symmod case AMODU: - p.To.Sym = ctxt.Sym_modu + p.To.Sym = symmodu } /* MOV REGTMP, b */ @@ -637,21 +630,21 @@ func isfloatreg(a *obj.Addr) bool { return a.Type == obj.TYPE_REG && REG_F0 <= a.Reg && a.Reg <= REG_F15 } -func softfloat(ctxt *obj.Link, newprog obj.ProgAlloc, cursym *obj.LSym) { +func (c *ctxt5) softfloat() { if obj.GOARM > 5 { return } - symsfloat := ctxt.Lookup("_sfloat", 0) + symsfloat := c.ctxt.Lookup("_sfloat", 0) wasfloat := 0 - for p := cursym.Text; p != nil; p = p.Link { + for p := c.cursym.Text; p != nil; p = p.Link { if p.Pcond != nil { p.Pcond.Mark |= LABEL } } var next *obj.Prog - for p := cursym.Text; p != nil; p = p.Link { + for p := c.cursym.Text; p != nil; p = p.Link { switch p.As { case AMOVW: if isfloatreg(&p.To) || isfloatreg(&p.From) { @@ -691,12 +684,12 @@ func softfloat(ctxt *obj.Link, newprog obj.ProgAlloc, cursym *obj.LSym) { soft: if wasfloat == 0 || (p.Mark&LABEL != 0) { - next = newprog() + next = c.newprog() *next = *p // BL _sfloat(SB) *p = obj.Prog{} - p.Ctxt = ctxt + p.Ctxt = c.ctxt p.Link = next p.As = ABL p.To.Type = obj.TYPE_BRANCH @@ -714,16 +707,16 @@ func softfloat(ctxt *obj.Link, newprog obj.ProgAlloc, cursym *obj.LSym) { } } -func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize int32) *obj.Prog { +func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog { // MOVW g_stackguard(g), R1 - p = obj.Appendp(p, newprog) + p = obj.Appendp(p, c.newprog) p.As = AMOVW p.From.Type = obj.TYPE_MEM p.From.Reg = REGG - p.From.Offset = 2 * int64(ctxt.Arch.PtrSize) // G.stackguard0 - if ctxt.Cursym.CFunc() { - p.From.Offset = 3 * int64(ctxt.Arch.PtrSize) // G.stackguard1 + p.From.Offset = 2 * int64(c.ctxt.Arch.PtrSize) // G.stackguard0 + if c.cursym.CFunc() { + p.From.Offset = 3 * int64(c.ctxt.Arch.PtrSize) // G.stackguard1 } p.To.Type = obj.TYPE_REG p.To.Reg = REG_R1 @@ -731,7 +724,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in if framesize <= obj.StackSmall { // small stack: SP < stackguard // CMP stackguard, SP - p = obj.Appendp(p, newprog) + p = obj.Appendp(p, c.newprog) p.As = ACMP p.From.Type = obj.TYPE_REG @@ -741,7 +734,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in // large stack: SP-framesize < stackguard-StackSmall // MOVW $-(framesize-StackSmall)(SP), R2 // CMP stackguard, R2 - p = obj.Appendp(p, newprog) + p = obj.Appendp(p, c.newprog) p.As = AMOVW p.From.Type = obj.TYPE_ADDR @@ -750,7 +743,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in p.To.Type = obj.TYPE_REG p.To.Reg = REG_R2 - p = obj.Appendp(p, newprog) + p = obj.Appendp(p, c.newprog) p.As = ACMP p.From.Type = obj.TYPE_REG p.From.Reg = REG_R1 @@ -766,14 +759,14 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in // SUB.NE R1, R2 // MOVW.NE $(framesize+(StackGuard-StackSmall)), R3 // CMP.NE R3, R2 - p = obj.Appendp(p, newprog) + p = obj.Appendp(p, c.newprog) p.As = ACMP p.From.Type = obj.TYPE_CONST p.From.Offset = int64(uint32(obj.StackPreempt & (1<<32 - 1))) p.Reg = REG_R1 - p = obj.Appendp(p, newprog) + p = obj.Appendp(p, c.newprog) p.As = AMOVW p.From.Type = obj.TYPE_ADDR p.From.Reg = REGSP @@ -782,7 +775,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in p.To.Reg = REG_R2 p.Scond = C_SCOND_NE - p = obj.Appendp(p, newprog) + p = obj.Appendp(p, c.newprog) p.As = ASUB p.From.Type = obj.TYPE_REG p.From.Reg = REG_R1 @@ -790,7 +783,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in p.To.Reg = REG_R2 p.Scond = C_SCOND_NE - p = obj.Appendp(p, newprog) + p = obj.Appendp(p, c.newprog) p.As = AMOVW p.From.Type = obj.TYPE_ADDR p.From.Offset = int64(framesize) + (obj.StackGuard - obj.StackSmall) @@ -798,7 +791,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in p.To.Reg = REG_R3 p.Scond = C_SCOND_NE - p = obj.Appendp(p, newprog) + p = obj.Appendp(p, c.newprog) p.As = ACMP p.From.Type = obj.TYPE_REG p.From.Reg = REG_R3 @@ -807,23 +800,23 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in } // BLS call-to-morestack - bls := obj.Appendp(p, newprog) + bls := obj.Appendp(p, c.newprog) bls.As = ABLS bls.To.Type = obj.TYPE_BRANCH var last *obj.Prog - for last = ctxt.Cursym.Text; last.Link != nil; last = last.Link { + for last = c.cursym.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, newprog) + spfix := obj.Appendp(last, c.newprog) spfix.As = obj.ANOP spfix.Spadj = -framesize - pcdata := obj.Appendp(spfix, newprog) - pcdata.Pos = ctxt.Cursym.Text.Pos + pcdata := obj.Appendp(spfix, c.newprog) + pcdata.Pos = c.cursym.Text.Pos pcdata.As = obj.APCDATA pcdata.From.Type = obj.TYPE_CONST pcdata.From.Offset = obj.PCDATA_StackMapIndex @@ -831,7 +824,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in pcdata.To.Offset = -1 // pcdata starts at -1 at function entry // MOVW LR, R3 - movw := obj.Appendp(pcdata, newprog) + movw := obj.Appendp(pcdata, c.newprog) movw.As = AMOVW movw.From.Type = obj.TYPE_REG movw.From.Reg = REGLINK @@ -841,38 +834,28 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in bls.Pcond = movw // BL runtime.morestack - call := obj.Appendp(movw, newprog) + call := obj.Appendp(movw, c.newprog) call.As = obj.ACALL call.To.Type = obj.TYPE_BRANCH morestack := "runtime.morestack" switch { - case ctxt.Cursym.CFunc(): + case c.cursym.CFunc(): morestack = "runtime.morestackc" - case ctxt.Cursym.Text.From3.Offset&obj.NEEDCTXT == 0: + case c.cursym.Text.From3.Offset&obj.NEEDCTXT == 0: morestack = "runtime.morestack_noctxt" } - call.To.Sym = ctxt.Lookup(morestack, 0) + call.To.Sym = c.ctxt.Lookup(morestack, 0) // B start - b := obj.Appendp(call, newprog) + b := obj.Appendp(call, c.newprog) b.As = obj.AJMP b.To.Type = obj.TYPE_BRANCH - b.Pcond = ctxt.Cursym.Text.Link + b.Pcond = c.cursym.Text.Link b.Spadj = +framesize return bls } -func initdiv(ctxt *obj.Link) { - if ctxt.Sym_div != nil { - return - } - ctxt.Sym_div = ctxt.Lookup("_div", 0) - ctxt.Sym_divu = ctxt.Lookup("_divu", 0) - ctxt.Sym_mod = ctxt.Lookup("_mod", 0) - ctxt.Sym_modu = ctxt.Lookup("_modu", 0) -} - var unaryDst = map[obj.As]bool{ ASWI: true, AWORD: true, diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index fd07851f3b..0c0a9f5bbf 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -726,17 +726,12 @@ type Link struct { PosTable src.PosTable InlTree InlTree // global inlining tree used by gc/inl.go Imports []string - Sym_div *LSym - Sym_divu *LSym - Sym_mod *LSym - Sym_modu *LSym Plan9privates *LSym Printp *Prog Blitrl *Prog Elitrl *Prog Instoffset int64 Autosize int32 - Armsize int32 Pc int64 DiagFunc func(string, ...interface{}) DebugInfo func(fn *LSym, curfn interface{}) []*dwarf.Var // if non-nil, curfn is a *gc.Node