Commit dcf643f1 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

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