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

cmd/internal/obj/arm64: make assembler almost concurrency-safe

CL 39922 made the arm assembler concurrency-safe.
This CL does the same, but for arm64.
The approach is similar: introduce ctxt7 to hold
function-local state and thread it through
the assembler as necessary.

One race remains after this CL, deep in aclass,
in the check that a Prog does not take the address
of a TLS variable.

That race is conceptually unrelated to this refactoring,
and will be addressed in a separate CL.

Passes toolstash-check -all.

Updates #15756

Change-Id: Icab1ef70008468f9a5b8bf728a77c4520bbcb67d
Reviewed-on: https://go-review.googlesource.com/40252
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarCherry Zhang <cherryyz@google.com>
parent c4135d61
...@@ -38,6 +38,24 @@ import ( ...@@ -38,6 +38,24 @@ import (
"sort" "sort"
) )
// ctxt7 holds state while assembling a single function.
// Each function gets a fresh ctxt7.
// This allows for multiple functions to be safely concurrently assembled.
type ctxt7 struct {
ctxt *obj.Link
newprog obj.ProgAlloc
cursym *obj.LSym
blitrl *obj.Prog
elitrl *obj.Prog
autosize int32
instoffset int64
pc int64
pool struct {
start uint32
size uint32
}
}
const ( const (
funcAlign = 16 funcAlign = 16
) )
...@@ -523,23 +541,18 @@ var pstatefield = []struct { ...@@ -523,23 +541,18 @@ var pstatefield = []struct {
{REG_DAIFClr, 3<<16 | 4<<12 | 7<<5}, {REG_DAIFClr, 3<<16 | 4<<12 | 7<<5},
} }
var pool struct {
start uint32
size uint32
}
func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p := cursym.Text p := cursym.Text
if p == nil || p.Link == nil { // handle external functions and ELF section symbols if p == nil || p.Link == nil { // handle external functions and ELF section symbols
return return
} }
ctxt.Cursym = cursym
ctxt.Autosize = int32(p.To.Offset&0xffffffff) + 8
if oprange[AAND&obj.AMask] == nil { if oprange[AAND&obj.AMask] == nil {
ctxt.Diag("arm64 ops not initialized, call arm64.buildop first") ctxt.Diag("arm64 ops not initialized, call arm64.buildop first")
} }
c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset&0xffffffff) + 8}
bflag := 1 bflag := 1
pc := int64(0) pc := int64(0)
p.Pc = pc p.Pc = pc
...@@ -550,34 +563,34 @@ func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -550,34 +563,34 @@ func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
pc += 4 pc += 4
} }
p.Pc = pc p.Pc = pc
o = oplook(ctxt, p) o = c.oplook(p)
m = int(o.size) m = int(o.size)
if m == 0 { if m == 0 {
if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA { if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
ctxt.Diag("zero-width instruction\n%v", p) c.ctxt.Diag("zero-width instruction\n%v", p)
} }
continue continue
} }
switch o.flag & (LFROM | LTO) { switch o.flag & (LFROM | LTO) {
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)
break break
} }
if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */ if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */
checkpool(ctxt, newprog, p, 0) c.checkpool(p, 0)
} }
pc += int64(m) pc += int64(m)
if ctxt.Blitrl != nil { if c.blitrl != nil {
checkpool(ctxt, newprog, p, 1) c.checkpool(p, 1)
} }
} }
cursym.Size = pc c.cursym.Size = pc
/* /*
* if any procedure is large enough to * if any procedure is large enough to
...@@ -588,25 +601,25 @@ func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -588,25 +601,25 @@ func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
for bflag != 0 { for bflag != 0 {
bflag = 0 bflag = 0
pc = 0 pc = 0
for p = cursym.Text.Link; p != nil; p = p.Link { for p = c.cursym.Text.Link; p != nil; p = p.Link {
if p.As == ADWORD && (pc&7) != 0 { if p.As == ADWORD && (pc&7) != 0 {
pc += 4 pc += 4
} }
p.Pc = pc p.Pc = pc
o = oplook(ctxt, p) o = c.oplook(p)
/* very large branches */ /* very large branches */
if (o.type_ == 7 || o.type_ == 39) && p.Pcond != nil { // 7: BEQ and like, 39: CBZ and like if (o.type_ == 7 || o.type_ == 39) && p.Pcond != nil { // 7: BEQ and like, 39: CBZ and like
otxt := p.Pcond.Pc - pc otxt := p.Pcond.Pc - pc
if otxt <= -(1<<18)+10 || otxt >= (1<<18)-10 { if otxt <= -(1<<18)+10 || otxt >= (1<<18)-10 {
q := newprog() q := c.newprog()
q.Link = p.Link q.Link = p.Link
p.Link = q p.Link = q
q.As = AB q.As = AB
q.To.Type = obj.TYPE_BRANCH q.To.Type = obj.TYPE_BRANCH
q.Pcond = p.Pcond q.Pcond = p.Pcond
p.Pcond = q p.Pcond = q
q = newprog() q = c.newprog()
q.Link = p.Link q.Link = p.Link
p.Link = q p.Link = q
q.As = AB q.As = AB
...@@ -619,7 +632,7 @@ func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -619,7 +632,7 @@ func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
if m == 0 { if m == 0 {
if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA { if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
ctxt.Diag("zero-width instruction\n%v", p) c.ctxt.Diag("zero-width instruction\n%v", p)
} }
continue continue
} }
...@@ -629,19 +642,19 @@ func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -629,19 +642,19 @@ func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
} }
pc += -pc & (funcAlign - 1) pc += -pc & (funcAlign - 1)
cursym.Size = pc c.cursym.Size = pc
/* /*
* lay out the code, emitting code and data relocations. * lay out the code, emitting code and data relocations.
*/ */
cursym.Grow(cursym.Size) c.cursym.Grow(c.cursym.Size)
bp := cursym.P bp := c.cursym.P
psz := int32(0) psz := int32(0)
var i int var i int
var out [6]uint32 var out [6]uint32
for p := cursym.Text.Link; p != nil; p = p.Link { for p := c.cursym.Text.Link; p != nil; p = p.Link {
ctxt.Pc = p.Pc c.pc = p.Pc
o = oplook(ctxt, p) o = c.oplook(p)
// need to align DWORDs on 8-byte boundary. The ISA doesn't // need to align DWORDs on 8-byte boundary. The ISA doesn't
// require it, but the various 64-bit loads we generate assume it. // require it, but the various 64-bit loads we generate assume it.
...@@ -657,9 +670,9 @@ func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -657,9 +670,9 @@ func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
if int(o.size) > 4*len(out) { if int(o.size) > 4*len(out) {
log.Fatalf("out array in span7 is too small, need at least %d for %v", o.size/4, p) log.Fatalf("out array in span7 is too small, need at least %d for %v", o.size/4, p)
} }
asmout(ctxt, p, o, out[:]) c.asmout(p, o, out[:])
for i = 0; i < int(o.size/4); i++ { for i = 0; i < int(o.size/4); i++ {
ctxt.Arch.ByteOrder.PutUint32(bp, out[i]) c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
bp = bp[4:] bp = bp[4:]
psz += 4 psz += 4
} }
...@@ -671,55 +684,55 @@ func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -671,55 +684,55 @@ func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
* to go out of range of a 1Mb PC-relative offset * to go out of range of a 1Mb PC-relative offset
* drop the pool now, and branch round it. * drop the pool now, and branch round it.
*/ */
func checkpool(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog, skip int) { func (c *ctxt7) checkpool(p *obj.Prog, skip int) {
if pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(pool.size)-int64(pool.start)+8)) { if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) {
flushpool(ctxt, newprog, p, skip) c.flushpool(p, skip)
} else if p.Link == nil { } else if p.Link == nil {
flushpool(ctxt, newprog, p, 2) c.flushpool(p, 2)
} }
} }
func flushpool(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog, skip int) { func (c *ctxt7) flushpool(p *obj.Prog, skip int) {
if ctxt.Blitrl != nil { if c.blitrl != nil {
if skip != 0 { if skip != 0 {
if ctxt.Debugvlog && skip == 1 { if c.ctxt.Debugvlog && 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 p.Pc+int64(pool.size)-int64(pool.start) < maxPCDisp { } else if p.Pc+int64(c.pool.size)-int64(c.pool.start) < maxPCDisp {
return return
} }
// 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
} }
} }
/* /*
* TODO: hash * TODO: hash
*/ */
func addpool(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog, a *obj.Addr) { func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) {
cls := aclass(ctxt, a) cls := c.aclass(a)
lit := ctxt.Instoffset lit := c.instoffset
t := *newprog() t := *c.newprog()
t.As = AWORD t.As = AWORD
sz := 4 sz := 4
...@@ -783,32 +796,32 @@ func addpool(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog, a *obj.Addr) { ...@@ -783,32 +796,32 @@ func addpool(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog, a *obj.Addr) {
break break
} }
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.To == t.To { if q.To == t.To {
p.Pcond = q p.Pcond = q
return return
} }
} }
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 = -pool.size & (funcAlign - 1) c.pool.size = -c.pool.size & (funcAlign - 1)
pool.size += uint32(sz) c.pool.size += uint32(sz)
p.Pcond = q p.Pcond = q
} }
func regoff(ctxt *obj.Link, a *obj.Addr) uint32 { func (c *ctxt7) regoff(a *obj.Addr) uint32 {
ctxt.Instoffset = 0 c.instoffset = 0
aclass(ctxt, a) c.aclass(a)
return uint32(ctxt.Instoffset) return uint32(c.instoffset)
} }
// Maximum PC-relative displacement. // Maximum PC-relative displacement.
...@@ -1013,7 +1026,7 @@ func oregclass(l int64) int { ...@@ -1013,7 +1026,7 @@ func oregclass(l int64) int {
* return the offset value to use in the instruction, * return the offset value to use in the instruction,
* scaled if necessary * scaled if necessary
*/ */
func offsetshift(ctxt *obj.Link, p *obj.Prog, v int64, cls int) int64 { func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 {
s := 0 s := 0
if cls >= C_SEXT1 && cls <= C_SEXT16 { if cls >= C_SEXT1 && cls <= C_SEXT16 {
s = cls - C_SEXT1 s = cls - C_SEXT1
...@@ -1024,7 +1037,7 @@ func offsetshift(ctxt *obj.Link, p *obj.Prog, v int64, cls int) int64 { ...@@ -1024,7 +1037,7 @@ func offsetshift(ctxt *obj.Link, p *obj.Prog, v int64, cls int) int64 {
} }
vs := v >> uint(s) vs := v >> uint(s)
if vs<<uint(s) != v { if vs<<uint(s) != v {
ctxt.Diag("odd offset: %d\n%v", v, p) c.ctxt.Diag("odd offset: %d\n%v", v, p)
} }
return vs return vs
} }
...@@ -1065,7 +1078,7 @@ func rclass(r int16) int { ...@@ -1065,7 +1078,7 @@ func rclass(r int16) int {
return C_GOK return C_GOK
} }
func aclass(ctxt *obj.Link, a *obj.Addr) int { func (c *ctxt7) 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
...@@ -1085,10 +1098,10 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { ...@@ -1085,10 +1098,10 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
if a.Sym == nil { if a.Sym == nil {
break break
} }
ctxt.Instoffset = a.Offset c.instoffset = a.Offset
if a.Sym != nil { // use relocation if a.Sym != nil { // use relocation
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
...@@ -1102,16 +1115,16 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { ...@@ -1102,16 +1115,16 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
return C_GOTADDR return C_GOTADDR
case obj.NAME_AUTO: case obj.NAME_AUTO:
ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset c.instoffset = int64(c.autosize) + a.Offset
return autoclass(ctxt.Instoffset) return autoclass(c.instoffset)
case obj.NAME_PARAM: case obj.NAME_PARAM:
ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8 c.instoffset = int64(c.autosize) + a.Offset + 8
return autoclass(ctxt.Instoffset) return autoclass(c.instoffset)
case obj.NAME_NONE: case obj.NAME_NONE:
ctxt.Instoffset = a.Offset c.instoffset = a.Offset
return oregclass(ctxt.Instoffset) return oregclass(c.instoffset)
} }
return C_GOK return C_GOK
...@@ -1124,11 +1137,11 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { ...@@ -1124,11 +1137,11 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
case obj.TYPE_CONST, obj.TYPE_ADDR: case obj.TYPE_CONST, 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 && a.Reg != REGZERO { if a.Reg != 0 && a.Reg != REGZERO {
goto aconsize goto aconsize
} }
v := ctxt.Instoffset v := c.instoffset
if v == 0 { if v == 0 {
return C_ZCON return C_ZCON
} }
...@@ -1175,23 +1188,23 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int { ...@@ -1175,23 +1188,23 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
break break
} }
if a.Sym.Type == obj.STLSBSS { if a.Sym.Type == obj.STLSBSS {
ctxt.Diag("taking address of TLS variable is not supported") c.ctxt.Diag("taking address of TLS variable is not supported")
} }
ctxt.Instoffset = a.Offset c.instoffset = a.Offset
return C_VCONADDR return C_VCONADDR
case obj.NAME_AUTO: case obj.NAME_AUTO:
ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset c.instoffset = int64(c.autosize) + a.Offset
goto aconsize goto aconsize
case obj.NAME_PARAM: case obj.NAME_PARAM:
ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8 c.instoffset = int64(c.autosize) + a.Offset + 8
goto aconsize goto aconsize
} }
return C_GOK return C_GOK
aconsize: aconsize:
if isaddcon(ctxt.Instoffset) { if isaddcon(c.instoffset) {
return C_AACON return C_AACON
} }
return C_LACON return C_LACON
...@@ -1207,21 +1220,21 @@ func oclass(a *obj.Addr) int { ...@@ -1207,21 +1220,21 @@ func oclass(a *obj.Addr) int {
return int(a.Class) - 1 return int(a.Class) - 1
} }
func oplook(ctxt *obj.Link, p *obj.Prog) *Optab { func (c *ctxt7) 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)
} }
...@@ -1249,7 +1262,7 @@ func oplook(ctxt *obj.Link, p *obj.Prog) *Optab { ...@@ -1249,7 +1262,7 @@ 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)
if ops == nil { if ops == nil {
ops = optab ops = optab
} }
...@@ -1884,7 +1897,7 @@ func buildop(ctxt *obj.Link) { ...@@ -1884,7 +1897,7 @@ func buildop(ctxt *obj.Link) {
} }
} }
func chipfloat7(ctxt *obj.Link, e float64) int { func (c *ctxt7) chipfloat7(e float64) int {
ei := math.Float64bits(e) ei := math.Float64bits(e)
l := uint32(int32(ei)) l := uint32(int32(ei))
h := uint32(int32(ei >> 32)) h := uint32(int32(ei >> 32))
...@@ -1924,7 +1937,7 @@ func SYSARG4(op1 int, Cn int, Cm int, op2 int) int { ...@@ -1924,7 +1937,7 @@ func SYSARG4(op1 int, Cn int, Cm int, op2 int) int {
return SYSARG5(0, op1, Cn, Cm, op2) return SYSARG5(0, op1, Cn, Cm, op2)
} }
func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 := uint32(0) o1 := uint32(0)
o2 := uint32(0) o2 := uint32(0)
o3 := uint32(0) o3 := uint32(0)
...@@ -1935,13 +1948,13 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -1935,13 +1948,13 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
} }
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 */
break break
case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */ case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
rf := int(p.From.Reg) rf := int(p.From.Reg)
rt := int(p.To.Reg) rt := int(p.To.Reg)
...@@ -1955,12 +1968,12 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -1955,12 +1968,12 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */ case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */
o1 = opirr(ctxt, p, p.As) o1 = c.opirr(p, p.As)
rt := int(p.To.Reg) rt := int(p.To.Reg)
if p.To.Type == obj.TYPE_NONE { if p.To.Type == obj.TYPE_NONE {
if (o1 & Sbit) == 0 { if (o1 & Sbit) == 0 {
ctxt.Diag("ineffective ZR destination\n%v", p) c.ctxt.Diag("ineffective ZR destination\n%v", p)
} }
rt = REGZERO rt = REGZERO
} }
...@@ -1969,11 +1982,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -1969,11 +1982,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
if r == 0 { if r == 0 {
r = rt r = rt
} }
v := int32(regoff(ctxt, &p.From)) v := int32(c.regoff(&p.From))
o1 = oaddi(ctxt, p, int32(o1), v, r, rt) o1 = c.oaddi(p, int32(o1), v, r, rt)
case 3: /* op R<<n[,R],R (shifted register) */ case 3: /* op R<<n[,R],R (shifted register) */
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
rt := int(p.To.Reg) rt := int(p.To.Reg)
...@@ -1989,7 +2002,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -1989,7 +2002,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= (uint32(r&31) << 5) | uint32(rt&31) o1 |= (uint32(r&31) << 5) | uint32(rt&31)
case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R */ case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R */
o1 = opirr(ctxt, p, p.As) o1 = c.opirr(p, p.As)
rt := int(p.To.Reg) rt := int(p.To.Reg)
r := int(o.param) r := int(o.param)
...@@ -2001,7 +2014,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2001,7 +2014,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
if r == 0 { if r == 0 {
r = REGSP r = REGSP
} }
v := int32(regoff(ctxt, &p.From)) v := int32(c.regoff(&p.From))
if (v & 0xFFF000) != 0 { if (v & 0xFFF000) != 0 {
v >>= 12 v >>= 12
o1 |= 1 << 22 /* shift, by 12 */ o1 |= 1 << 22 /* shift, by 12 */
...@@ -2010,33 +2023,33 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2010,33 +2023,33 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= ((uint32(v) & 0xFFF) << 10) | (uint32(r&31) << 5) | uint32(rt&31) o1 |= ((uint32(v) & 0xFFF) << 10) | (uint32(r&31) << 5) | uint32(rt&31)
case 5: /* b s; bl s */ case 5: /* b s; bl s */
o1 = opbra(ctxt, p, p.As) o1 = c.opbra(p, p.As)
if p.To.Sym == nil { if p.To.Sym == nil {
o1 |= uint32(brdist(ctxt, p, 0, 26, 2)) o1 |= uint32(c.brdist(p, 0, 26, 2))
break break
} }
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
rel.Type = obj.R_CALLARM64 rel.Type = obj.R_CALLARM64
case 6: /* b ,O(R); bl ,O(R) */ case 6: /* b ,O(R); bl ,O(R) */
o1 = opbrr(ctxt, p, p.As) o1 = c.opbrr(p, p.As)
o1 |= uint32(p.To.Reg&31) << 5 o1 |= uint32(p.To.Reg&31) << 5
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 7: /* beq s */ case 7: /* beq s */
o1 = opbra(ctxt, p, p.As) o1 = c.opbra(p, p.As)
o1 |= uint32(brdist(ctxt, p, 0, 19, 2) << 5) o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */ case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */
rt := int(p.To.Reg) rt := int(p.To.Reg)
...@@ -2048,36 +2061,36 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2048,36 +2061,36 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
v := int32(p.From.Offset) v := int32(p.From.Offset)
switch p.As { switch p.As {
case AASR: case AASR:
o1 = opbfm(ctxt, p, ASBFM, int(v), 63, rf, rt) o1 = c.opbfm(p, ASBFM, int(v), 63, rf, rt)
case AASRW: case AASRW:
o1 = opbfm(ctxt, p, ASBFMW, int(v), 31, rf, rt) o1 = c.opbfm(p, ASBFMW, int(v), 31, rf, rt)
case ALSL: case ALSL:
o1 = opbfm(ctxt, p, AUBFM, int((64-v)&63), int(63-v), rf, rt) o1 = c.opbfm(p, AUBFM, int((64-v)&63), int(63-v), rf, rt)
case ALSLW: case ALSLW:
o1 = opbfm(ctxt, p, AUBFMW, int((32-v)&31), int(31-v), rf, rt) o1 = c.opbfm(p, AUBFMW, int((32-v)&31), int(31-v), rf, rt)
case ALSR: case ALSR:
o1 = opbfm(ctxt, p, AUBFM, int(v), 63, rf, rt) o1 = c.opbfm(p, AUBFM, int(v), 63, rf, rt)
case ALSRW: case ALSRW:
o1 = opbfm(ctxt, p, AUBFMW, int(v), 31, rf, rt) o1 = c.opbfm(p, AUBFMW, int(v), 31, rf, rt)
case AROR: case AROR:
o1 = opextr(ctxt, p, AEXTR, v, rf, rf, rt) o1 = c.opextr(p, AEXTR, v, rf, rf, rt)
case ARORW: case ARORW:
o1 = opextr(ctxt, p, AEXTRW, v, rf, rf, rt) o1 = c.opextr(p, AEXTRW, v, rf, rf, rt)
default: default:
ctxt.Diag("bad shift $con\n%v", p) c.ctxt.Diag("bad shift $con\n%v", p)
break break
} }
case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */ case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
r := int(p.Reg) r := int(p.Reg)
if r == 0 { if r == 0 {
...@@ -2086,20 +2099,20 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2086,20 +2099,20 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31) o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31)
case 10: /* brk/hvc/.../svc [$con] */ case 10: /* brk/hvc/.../svc [$con] */
o1 = opimm(ctxt, p, p.As) o1 = c.opimm(p, p.As)
if p.To.Type != obj.TYPE_NONE { if p.To.Type != obj.TYPE_NONE {
o1 |= uint32((p.To.Offset & 0xffff) << 5) o1 |= uint32((p.To.Offset & 0xffff) << 5)
} }
case 11: /* dword */ case 11: /* dword */
aclass(ctxt, &p.To) c.aclass(&p.To)
o1 = uint32(ctxt.Instoffset) o1 = uint32(c.instoffset)
o2 = uint32(ctxt.Instoffset >> 32) o2 = uint32(c.instoffset >> 32)
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 = 8 rel.Siz = 8
rel.Sym = p.To.Sym rel.Sym = p.To.Sym
rel.Add = p.To.Offset rel.Add = p.To.Offset
...@@ -2109,10 +2122,10 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2109,10 +2122,10 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
} }
case 12: /* movT $vcon, reg */ case 12: /* movT $vcon, reg */
o1 = omovlit(ctxt, p.As, p, &p.From, int(p.To.Reg)) o1 = c.omovlit(p.As, p, &p.From, int(p.To.Reg))
case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */ case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
o1 = omovlit(ctxt, AMOVD, p, &p.From, REGTMP) o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
if !(o1 != 0) { if !(o1 != 0) {
break break
...@@ -2126,11 +2139,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2126,11 +2139,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
r = rt r = rt
} }
if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) { if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
o2 = opxrrr(ctxt, p, p.As) o2 = c.opxrrr(p, p.As)
o2 |= REGTMP & 31 << 16 o2 |= REGTMP & 31 << 16
o2 |= LSL0_64 o2 |= LSL0_64
} else { } else {
o2 = oprrr(ctxt, p, p.As) o2 = c.oprrr(p, p.As)
o2 |= REGTMP & 31 << 16 /* shift is 0 */ o2 |= REGTMP & 31 << 16 /* shift is 0 */
} }
...@@ -2138,16 +2151,16 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2138,16 +2151,16 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o2 |= uint32(rt & 31) o2 |= uint32(rt & 31)
case 14: /* word */ case 14: /* word */
if aclass(ctxt, &p.To) == C_ADDR { if c.aclass(&p.To) == C_ADDR {
ctxt.Diag("address constant needs DWORD\n%v", p) c.ctxt.Diag("address constant needs DWORD\n%v", p)
} }
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.
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
...@@ -2156,7 +2169,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2156,7 +2169,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
} }
case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub Rm,Rn,Ra,Rd */ case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub Rm,Rn,Ra,Rd */
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
rf := int(p.From.Reg) rf := int(p.From.Reg)
rt := int(p.To.Reg) rt := int(p.To.Reg)
...@@ -2179,7 +2192,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2179,7 +2192,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31) o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31)
case 16: /* XremY R[,R],R -> XdivY; XmsubY */ case 16: /* XremY R[,R],R -> XdivY; XmsubY */
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
rf := int(p.From.Reg) rf := int(p.From.Reg)
rt := int(p.To.Reg) rt := int(p.To.Reg)
...@@ -2188,12 +2201,12 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2188,12 +2201,12 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
r = rt r = rt
} }
o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31
o2 = oprrr(ctxt, p, AMSUBW) o2 = c.oprrr(p, AMSUBW)
o2 |= o1 & (1 << 31) /* same size */ o2 |= o1 & (1 << 31) /* same size */
o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31) o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31)
case 17: /* op Rm,[Rn],Rd; default Rn=ZR */ case 17: /* op Rm,[Rn],Rd; default Rn=ZR */
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
rf := int(p.From.Reg) rf := int(p.From.Reg)
rt := int(p.To.Reg) rt := int(p.To.Reg)
...@@ -2207,7 +2220,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2207,7 +2220,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */ case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
cond := int(p.From.Reg) cond := int(p.From.Reg)
r := int(p.Reg) r := int(p.Reg)
...@@ -2224,7 +2237,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2224,7 +2237,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
} else { } else {
/* CSET */ /* CSET */
if p.From3Type() != obj.TYPE_NONE { if p.From3Type() != obj.TYPE_NONE {
ctxt.Diag("invalid combination\n%v", p) c.ctxt.Diag("invalid combination\n%v", p)
} }
rf = REGZERO rf = REGZERO
r = rf r = rf
...@@ -2240,17 +2253,17 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2240,17 +2253,17 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
cond := int(p.From.Reg) cond := int(p.From.Reg)
var rf int var rf int
if p.From3.Type == obj.TYPE_REG { if p.From3.Type == obj.TYPE_REG {
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
rf = int(p.From3.Reg) /* Rm */ rf = int(p.From3.Reg) /* Rm */
} else { } else {
o1 = opirr(ctxt, p, p.As) o1 = c.opirr(p, p.As)
rf = int(p.From3.Offset & 0x1F) rf = int(p.From3.Offset & 0x1F)
} }
o1 |= (uint32(rf&31) << 16) | (uint32(cond) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv) o1 |= (uint32(rf&31) << 16) | (uint32(cond) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv)
case 20: /* movT R,O(R) -> strT */ case 20: /* movT R,O(R) -> strT */
v := int32(regoff(ctxt, &p.To)) v := int32(c.regoff(&p.To))
sz := int32(1 << uint(movesize(p.As))) sz := int32(1 << uint(movesize(p.As)))
r := int(p.To.Reg) r := int(p.To.Reg)
...@@ -2258,14 +2271,14 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2258,14 +2271,14 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
r = int(o.param) r = int(o.param)
} }
if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
o1 = olsr9s(ctxt, p, int32(opstr9(ctxt, p, p.As)), v, r, int(p.From.Reg)) o1 = c.olsr9s(p, int32(c.opstr9(p, p.As)), v, r, int(p.From.Reg))
} else { } else {
v = int32(offsetshift(ctxt, p, int64(v), int(o.a3))) v = int32(c.offsetshift(p, int64(v), int(o.a3)))
o1 = olsr12u(ctxt, p, int32(opstr12(ctxt, p, p.As)), v, r, int(p.From.Reg)) o1 = c.olsr12u(p, int32(c.opstr12(p, p.As)), v, r, int(p.From.Reg))
} }
case 21: /* movT O(R),R -> ldrT */ case 21: /* movT O(R),R -> ldrT */
v := int32(regoff(ctxt, &p.From)) v := int32(c.regoff(&p.From))
sz := int32(1 << uint(movesize(p.As))) sz := int32(1 << uint(movesize(p.As)))
r := int(p.From.Reg) r := int(p.From.Reg)
...@@ -2273,20 +2286,20 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2273,20 +2286,20 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
r = int(o.param) r = int(o.param)
} }
if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */ if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
o1 = olsr9s(ctxt, p, int32(opldr9(ctxt, p, p.As)), v, r, int(p.To.Reg)) o1 = c.olsr9s(p, int32(c.opldr9(p, p.As)), v, r, int(p.To.Reg))
} else { } else {
v = int32(offsetshift(ctxt, p, int64(v), int(o.a1))) v = int32(c.offsetshift(p, int64(v), int(o.a1)))
//print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1); //print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1);
o1 = olsr12u(ctxt, p, int32(opldr12(ctxt, p, p.As)), v, r, int(p.To.Reg)) o1 = c.olsr12u(p, int32(c.opldr12(p, p.As)), v, r, int(p.To.Reg))
} }
case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */ case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */
v := int32(p.From.Offset) v := int32(p.From.Offset)
if v < -256 || v > 255 { if v < -256 || v > 255 {
ctxt.Diag("offset out of range\n%v", p) c.ctxt.Diag("offset out of range\n%v", p)
} }
o1 = opldrpp(ctxt, p, p.As) o1 = c.opldrpp(p, p.As)
if o.scond == C_XPOST { if o.scond == C_XPOST {
o1 |= 1 << 10 o1 |= 1 << 10
} else { } else {
...@@ -2298,9 +2311,9 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2298,9 +2311,9 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
v := int32(p.To.Offset) v := int32(p.To.Offset)
if v < -256 || v > 255 { if v < -256 || v > 255 {
ctxt.Diag("offset out of range\n%v", p) c.ctxt.Diag("offset out of range\n%v", p)
} }
o1 = LD2STR(opldrpp(ctxt, p, p.As)) o1 = LD2STR(c.opldrpp(p, p.As))
if o.scond == C_XPOST { if o.scond == C_XPOST {
o1 |= 1 << 10 o1 |= 1 << 10
} else { } else {
...@@ -2314,20 +2327,20 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2314,20 +2327,20 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
s := rf == REGSP || rt == REGSP s := rf == REGSP || rt == REGSP
if p.As == AMVN || p.As == AMVNW { if p.As == AMVN || p.As == AMVNW {
if s { if s {
ctxt.Diag("illegal SP reference\n%v", p) c.ctxt.Diag("illegal SP reference\n%v", p)
} }
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
} else if s { } else if s {
o1 = opirr(ctxt, p, p.As) o1 = c.opirr(p, p.As)
o1 |= (uint32(rf&31) << 5) | uint32(rt&31) o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
} else { } else {
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
} }
case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */ case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
rf := int(p.From.Reg) rf := int(p.From.Reg)
if rf == C_NONE { if rf == C_NONE {
...@@ -2337,17 +2350,17 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2337,17 +2350,17 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
case 26: /* negX Rm<<s, Rd -> subX Rm<<s, ZR, Rd */ case 26: /* negX Rm<<s, Rd -> subX Rm<<s, ZR, Rd */
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
rt := int(p.To.Reg) rt := int(p.To.Reg)
o1 |= (REGZERO & 31 << 5) | uint32(rt&31) o1 |= (REGZERO & 31 << 5) | uint32(rt&31)
case 27: /* op Rm<<n[,Rn],Rd (extended register) */ case 27: /* op Rm<<n[,Rn],Rd (extended register) */
o1 = opxrrr(ctxt, p, p.As) o1 = c.opxrrr(p, p.As)
if (p.From.Reg-obj.RBaseARM64)&REG_EXT != 0 { if (p.From.Reg-obj.RBaseARM64)&REG_EXT != 0 {
ctxt.Diag("extended register not implemented\n%v", p) c.ctxt.Diag("extended register not implemented\n%v", p)
// o1 |= uint32(p.From.Offset) /* includes reg, op, etc */ // o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
} else { } else {
o1 |= uint32(p.From.Reg&31) << 16 o1 |= uint32(p.From.Reg&31) << 16
...@@ -2363,7 +2376,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2363,7 +2376,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= (uint32(r&31) << 5) | uint32(rt&31) o1 |= (uint32(r&31) << 5) | uint32(rt&31)
case 28: /* logop $vcon, [R], R (64 bit literal) */ case 28: /* logop $vcon, [R], R (64 bit literal) */
o1 = omovlit(ctxt, AMOVD, p, &p.From, REGTMP) o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
if !(o1 != 0) { if !(o1 != 0) {
break break
...@@ -2372,14 +2385,14 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2372,14 +2385,14 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
if r == 0 { if r == 0 {
r = int(p.To.Reg) r = int(p.To.Reg)
} }
o2 = oprrr(ctxt, p, p.As) o2 = c.oprrr(p, p.As)
o2 |= REGTMP & 31 << 16 /* shift is 0 */ o2 |= REGTMP & 31 << 16 /* shift is 0 */
o2 |= uint32(r&31) << 5 o2 |= uint32(r&31) << 5
o2 |= uint32(p.To.Reg & 31) o2 |= uint32(p.To.Reg & 31)
case 29: /* op Rn, Rd */ case 29: /* op Rn, Rd */
fc := aclass(ctxt, &p.From) fc := c.aclass(&p.From)
tc := aclass(ctxt, &p.To) tc := c.aclass(&p.To)
if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZCON || tc == C_REG || tc == C_ZCON) { if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZCON || tc == C_REG || tc == C_ZCON) {
// FMOV Rx, Fy or FMOV Fy, Rx // FMOV Rx, Fy or FMOV Fy, Rx
o1 = FPCVTI(0, 0, 0, 0, 6) o1 = FPCVTI(0, 0, 0, 0, 6)
...@@ -2390,7 +2403,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2390,7 +2403,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= 1 << 16 // FMOV Rx, Fy o1 |= 1 << 16 // FMOV Rx, Fy
} }
} else { } else {
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
} }
o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31) o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31)
...@@ -2398,18 +2411,18 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2398,18 +2411,18 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
s := movesize(o.as) s := movesize(o.as)
if s < 0 { if s < 0 {
ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p) c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
} }
v := int32(regoff(ctxt, &p.To)) v := int32(c.regoff(&p.To))
if v < 0 { if v < 0 {
ctxt.Diag("negative large offset\n%v", p) c.ctxt.Diag("negative large offset\n%v", p)
} }
if (v & ((1 << uint(s)) - 1)) != 0 { if (v & ((1 << uint(s)) - 1)) != 0 {
ctxt.Diag("misaligned offset\n%v", p) c.ctxt.Diag("misaligned offset\n%v", p)
} }
hi := v - (v & (0xFFF << uint(s))) hi := v - (v & (0xFFF << uint(s)))
if (hi & 0xFFF) != 0 { if (hi & 0xFFF) != 0 {
ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p) c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
} }
//fprint(2, "v=%ld (%#lux) s=%d hi=%ld (%#lux) v'=%ld (%#lux)\n", v, v, s, hi, hi, ((v-hi)>>s)&0xFFF, ((v-hi)>>s)&0xFFF); //fprint(2, "v=%ld (%#lux) s=%d hi=%ld (%#lux) v'=%ld (%#lux)\n", v, v, s, hi, hi, ((v-hi)>>s)&0xFFF, ((v-hi)>>s)&0xFFF);
...@@ -2418,25 +2431,25 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2418,25 +2431,25 @@ 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)
} }
o1 = oaddi(ctxt, p, int32(opirr(ctxt, p, AADD)), hi, r, REGTMP) o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
o2 = olsr12u(ctxt, p, int32(opstr12(ctxt, p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg)) o2 = c.olsr12u(p, int32(c.opstr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg))
case 31: /* movT L(R), R -> ldrT */ case 31: /* movT L(R), R -> ldrT */
s := movesize(o.as) s := movesize(o.as)
if s < 0 { if s < 0 {
ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p) c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
} }
v := int32(regoff(ctxt, &p.From)) v := int32(c.regoff(&p.From))
if v < 0 { if v < 0 {
ctxt.Diag("negative large offset\n%v", p) c.ctxt.Diag("negative large offset\n%v", p)
} }
if (v & ((1 << uint(s)) - 1)) != 0 { if (v & ((1 << uint(s)) - 1)) != 0 {
ctxt.Diag("misaligned offset\n%v", p) c.ctxt.Diag("misaligned offset\n%v", p)
} }
hi := v - (v & (0xFFF << uint(s))) hi := v - (v & (0xFFF << uint(s)))
if (hi & 0xFFF) != 0 { if (hi & 0xFFF) != 0 {
ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p) c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
} }
//fprint(2, "v=%ld (%#lux) s=%d hi=%ld (%#lux) v'=%ld (%#lux)\n", v, v, s, hi, hi, ((v-hi)>>s)&0xFFF, ((v-hi)>>s)&0xFFF); //fprint(2, "v=%ld (%#lux) s=%d hi=%ld (%#lux) v'=%ld (%#lux)\n", v, v, s, hi, hi, ((v-hi)>>s)&0xFFF, ((v-hi)>>s)&0xFFF);
...@@ -2445,27 +2458,27 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2445,27 +2458,27 @@ 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)
} }
o1 = oaddi(ctxt, p, int32(opirr(ctxt, p, AADD)), hi, r, REGTMP) o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
o2 = olsr12u(ctxt, p, int32(opldr12(ctxt, p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg)) o2 = c.olsr12u(p, int32(c.opldr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg))
case 32: /* mov $con, R -> movz/movn */ case 32: /* mov $con, R -> movz/movn */
o1 = omovconst(ctxt, p.As, p, &p.From, int(p.To.Reg)) o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg))
case 33: /* movk $uimm16 << pos */ case 33: /* movk $uimm16 << pos */
o1 = opirr(ctxt, p, p.As) o1 = c.opirr(p, p.As)
d := p.From.Offset d := p.From.Offset
if (d >> 16) != 0 { if (d >> 16) != 0 {
ctxt.Diag("requires uimm16\n%v", p) c.ctxt.Diag("requires uimm16\n%v", p)
} }
s := 0 s := 0
if p.From3Type() != obj.TYPE_NONE { if p.From3Type() != obj.TYPE_NONE {
if p.From3.Type != obj.TYPE_CONST { if p.From3.Type != obj.TYPE_CONST {
ctxt.Diag("missing bit position\n%v", p) c.ctxt.Diag("missing bit position\n%v", p)
} }
s = int(p.From3.Offset / 16) s = int(p.From3.Offset / 16)
if (s*16&0xF) != 0 || s >= 4 || (o1&S64) == 0 && s >= 2 { if (s*16&0xF) != 0 || s >= 4 || (o1&S64) == 0 && s >= 2 {
ctxt.Diag("illegal bit position\n%v", p) c.ctxt.Diag("illegal bit position\n%v", p)
} }
} }
...@@ -2473,12 +2486,12 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2473,12 +2486,12 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= uint32(((d & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31)) o1 |= uint32(((d & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31))
case 34: /* mov $lacon,R */ case 34: /* mov $lacon,R */
o1 = omovlit(ctxt, AMOVD, p, &p.From, REGTMP) o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
if !(o1 != 0) { if !(o1 != 0) {
break break
} }
o2 = opxrrr(ctxt, p, AADD) o2 = c.opxrrr(p, AADD)
o2 |= REGTMP & 31 << 16 o2 |= REGTMP & 31 << 16
o2 |= LSL0_64 o2 |= LSL0_64
r := int(p.From.Reg) r := int(p.From.Reg)
...@@ -2489,30 +2502,30 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2489,30 +2502,30 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o2 |= uint32(p.To.Reg & 31) o2 |= uint32(p.To.Reg & 31)
case 35: /* mov SPR,R -> mrs */ case 35: /* mov SPR,R -> mrs */
o1 = oprrr(ctxt, p, AMRS) o1 = c.oprrr(p, AMRS)
v := int32(p.From.Offset) v := int32(p.From.Offset)
if (o1 & uint32(v&^(3<<19))) != 0 { if (o1 & uint32(v&^(3<<19))) != 0 {
ctxt.Diag("MRS register value overlap\n%v", p) c.ctxt.Diag("MRS register value overlap\n%v", p)
} }
o1 |= uint32(v) o1 |= uint32(v)
o1 |= uint32(p.To.Reg & 31) o1 |= uint32(p.To.Reg & 31)
case 36: /* mov R,SPR */ case 36: /* mov R,SPR */
o1 = oprrr(ctxt, p, AMSR) o1 = c.oprrr(p, AMSR)
v := int32(p.To.Offset) v := int32(p.To.Offset)
if (o1 & uint32(v&^(3<<19))) != 0 { if (o1 & uint32(v&^(3<<19))) != 0 {
ctxt.Diag("MSR register value overlap\n%v", p) c.ctxt.Diag("MSR register value overlap\n%v", p)
} }
o1 |= uint32(v) o1 |= uint32(v)
o1 |= uint32(p.From.Reg & 31) o1 |= uint32(p.From.Reg & 31)
case 37: /* mov $con,PSTATEfield -> MSR [immediate] */ case 37: /* mov $con,PSTATEfield -> MSR [immediate] */
if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 { if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 {
ctxt.Diag("illegal immediate for PSTATE field\n%v", p) c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p)
} }
o1 = opirr(ctxt, p, AMSR) o1 = c.opirr(p, AMSR)
o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */ o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */
v := int32(0) v := int32(0)
for i := 0; i < len(pstatefield); i++ { for i := 0; i < len(pstatefield); i++ {
...@@ -2523,12 +2536,12 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2523,12 +2536,12 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
} }
if v == 0 { if v == 0 {
ctxt.Diag("illegal PSTATE field for immediate move\n%v", p) c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p)
} }
o1 |= uint32(v) o1 |= uint32(v)
case 38: /* clrex [$imm] */ case 38: /* clrex [$imm] */
o1 = opimm(ctxt, p, p.As) o1 = c.opimm(p, p.As)
if p.To.Type == obj.TYPE_NONE { if p.To.Type == obj.TYPE_NONE {
o1 |= 0xF << 8 o1 |= 0xF << 8
...@@ -2537,27 +2550,27 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2537,27 +2550,27 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
} }
case 39: /* cbz R, rel */ case 39: /* cbz R, rel */
o1 = opirr(ctxt, p, p.As) o1 = c.opirr(p, p.As)
o1 |= uint32(p.From.Reg & 31) o1 |= uint32(p.From.Reg & 31)
o1 |= uint32(brdist(ctxt, p, 0, 19, 2) << 5) o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
case 40: /* tbz */ case 40: /* tbz */
o1 = opirr(ctxt, p, p.As) o1 = c.opirr(p, p.As)
v := int32(p.From.Offset) v := int32(p.From.Offset)
if v < 0 || v > 63 { if v < 0 || v > 63 {
ctxt.Diag("illegal bit number\n%v", p) c.ctxt.Diag("illegal bit number\n%v", p)
} }
o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19) o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19)
o1 |= uint32(brdist(ctxt, p, 0, 14, 2) << 5) o1 |= uint32(c.brdist(p, 0, 14, 2) << 5)
o1 |= uint32(p.Reg) o1 |= uint32(p.Reg)
case 41: /* eret, nop, others with no operands */ case 41: /* eret, nop, others with no operands */
o1 = op0(ctxt, p, p.As) o1 = c.op0(p, p.As)
case 42: /* bfm R,r,s,R */ case 42: /* bfm R,r,s,R */
o1 = opbfm(ctxt, p, p.As, int(p.From.Offset), int(p.From3.Offset), int(p.Reg), int(p.To.Reg)) o1 = c.opbfm(p, p.As, int(p.From.Offset), int(p.From3.Offset), int(p.Reg), int(p.To.Reg))
case 43: /* bfm aliases */ case 43: /* bfm aliases */
r := int(p.From.Offset) r := int(p.From.Offset)
...@@ -2570,48 +2583,48 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2570,48 +2583,48 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
} }
switch p.As { switch p.As {
case ABFI: case ABFI:
o1 = opbfm(ctxt, p, ABFM, 64-r, s-1, rf, rt) o1 = c.opbfm(p, ABFM, 64-r, s-1, rf, rt)
case ABFIW: case ABFIW:
o1 = opbfm(ctxt, p, ABFMW, 32-r, s-1, rf, rt) o1 = c.opbfm(p, ABFMW, 32-r, s-1, rf, rt)
case ABFXIL: case ABFXIL:
o1 = opbfm(ctxt, p, ABFM, r, r+s-1, rf, rt) o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt)
case ABFXILW: case ABFXILW:
o1 = opbfm(ctxt, p, ABFMW, r, r+s-1, rf, rt) o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt)
case ASBFIZ: case ASBFIZ:
o1 = opbfm(ctxt, p, ASBFM, 64-r, s-1, rf, rt) o1 = c.opbfm(p, ASBFM, 64-r, s-1, rf, rt)
case ASBFIZW: case ASBFIZW:
o1 = opbfm(ctxt, p, ASBFMW, 32-r, s-1, rf, rt) o1 = c.opbfm(p, ASBFMW, 32-r, s-1, rf, rt)
case ASBFX: case ASBFX:
o1 = opbfm(ctxt, p, ASBFM, r, r+s-1, rf, rt) o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt)
case ASBFXW: case ASBFXW:
o1 = opbfm(ctxt, p, ASBFMW, r, r+s-1, rf, rt) o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt)
case AUBFIZ: case AUBFIZ:
o1 = opbfm(ctxt, p, AUBFM, 64-r, s-1, rf, rt) o1 = c.opbfm(p, AUBFM, 64-r, s-1, rf, rt)
case AUBFIZW: case AUBFIZW:
o1 = opbfm(ctxt, p, AUBFMW, 32-r, s-1, rf, rt) o1 = c.opbfm(p, AUBFMW, 32-r, s-1, rf, rt)
case AUBFX: case AUBFX:
o1 = opbfm(ctxt, p, AUBFM, r, r+s-1, rf, rt) o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt)
case AUBFXW: case AUBFXW:
o1 = opbfm(ctxt, p, AUBFMW, r, r+s-1, rf, rt) o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt)
default: default:
ctxt.Diag("bad bfm alias\n%v", p) c.ctxt.Diag("bad bfm alias\n%v", p)
break break
} }
case 44: /* extr $b, Rn, Rm, Rd */ case 44: /* extr $b, Rn, Rm, Rd */
o1 = opextr(ctxt, p, p.As, int32(p.From.Offset), int(p.From3.Reg), int(p.Reg), int(p.To.Reg)) o1 = c.opextr(p, p.As, int32(p.From.Offset), int(p.From3.Reg), int(p.Reg), int(p.To.Reg))
case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */ case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */
rf := int(p.From.Reg) rf := int(p.From.Reg)
...@@ -2623,51 +2636,51 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2623,51 +2636,51 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
} }
switch as { switch as {
case AMOVB, ASXTB: case AMOVB, ASXTB:
o1 = opbfm(ctxt, p, ASBFM, 0, 7, rf, rt) o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt)
case AMOVH, ASXTH: case AMOVH, ASXTH:
o1 = opbfm(ctxt, p, ASBFM, 0, 15, rf, rt) o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt)
case AMOVW, ASXTW: case AMOVW, ASXTW:
o1 = opbfm(ctxt, p, ASBFM, 0, 31, rf, rt) o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt)
case AMOVBU, AUXTB: case AMOVBU, AUXTB:
o1 = opbfm(ctxt, p, AUBFM, 0, 7, rf, rt) o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt)
case AMOVHU, AUXTH: case AMOVHU, AUXTH:
o1 = opbfm(ctxt, p, AUBFM, 0, 15, rf, rt) o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt)
case AMOVWU: case AMOVWU:
o1 = oprrr(ctxt, p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31) o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
case AUXTW: case AUXTW:
o1 = opbfm(ctxt, p, AUBFM, 0, 31, rf, rt) o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt)
case ASXTBW: case ASXTBW:
o1 = opbfm(ctxt, p, ASBFMW, 0, 7, rf, rt) o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt)
case ASXTHW: case ASXTHW:
o1 = opbfm(ctxt, p, ASBFMW, 0, 15, rf, rt) o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt)
case AUXTBW: case AUXTBW:
o1 = opbfm(ctxt, p, AUBFMW, 0, 7, rf, rt) o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt)
case AUXTHW: case AUXTHW:
o1 = opbfm(ctxt, p, AUBFMW, 0, 15, rf, rt) o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt)
default: default:
ctxt.Diag("bad sxt %v", as) c.ctxt.Diag("bad sxt %v", as)
break break
} }
case 46: /* cls */ case 46: /* cls */
o1 = opbit(ctxt, p, p.As) o1 = c.opbit(p, p.As)
o1 |= uint32(p.From.Reg&31) << 5 o1 |= uint32(p.From.Reg&31) << 5
o1 |= uint32(p.To.Reg & 31) o1 |= uint32(p.To.Reg & 31)
case 47: /* movT R,V(R) -> strT (huge offset) */ case 47: /* movT R,V(R) -> strT (huge offset) */
o1 = omovlit(ctxt, AMOVW, p, &p.To, REGTMP) o1 = c.omovlit(AMOVW, p, &p.To, REGTMP)
if !(o1 != 0) { if !(o1 != 0) {
break break
...@@ -2676,10 +2689,10 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2676,10 +2689,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 = olsxrr(ctxt, p, p.As, REGTMP, r, int(p.From.Reg)) o2 = c.olsxrr(p, p.As, REGTMP, r, int(p.From.Reg))
case 48: /* movT V(R), R -> ldrT (huge offset) */ case 48: /* movT V(R), R -> ldrT (huge offset) */
o1 = omovlit(ctxt, AMOVW, p, &p.From, REGTMP) o1 = c.omovlit(AMOVW, p, &p.From, REGTMP)
if !(o1 != 0) { if !(o1 != 0) {
break break
...@@ -2688,13 +2701,13 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2688,13 +2701,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 = olsxrr(ctxt, p, p.As, REGTMP, r, int(p.To.Reg)) o2 = c.olsxrr(p, p.As, REGTMP, r, int(p.To.Reg))
case 50: /* sys/sysl */ case 50: /* sys/sysl */
o1 = opirr(ctxt, p, p.As) o1 = c.opirr(p, p.As)
if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 { if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 {
ctxt.Diag("illegal SYS argument\n%v", p) c.ctxt.Diag("illegal SYS argument\n%v", p)
} }
o1 |= uint32(p.From.Offset) o1 |= uint32(p.From.Offset)
if p.To.Type == obj.TYPE_REG { if p.To.Type == obj.TYPE_REG {
...@@ -2706,14 +2719,14 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2706,14 +2719,14 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
} }
case 51: /* dmb */ case 51: /* dmb */
o1 = opirr(ctxt, p, p.As) o1 = c.opirr(p, p.As)
if p.From.Type == obj.TYPE_CONST { if p.From.Type == obj.TYPE_CONST {
o1 |= uint32((p.From.Offset & 0xF) << 8) o1 |= uint32((p.From.Offset & 0xF) << 8)
} }
case 52: /* hint */ case 52: /* hint */
o1 = opirr(ctxt, p, p.As) o1 = c.opirr(p, p.As)
o1 |= uint32((p.From.Offset & 0x7F) << 5) o1 |= uint32((p.From.Offset & 0x7F) << 5)
...@@ -2735,17 +2748,17 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2735,17 +2748,17 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
v = ^v v = ^v
mode = 32 mode = 32
} }
o1 = opirr(ctxt, p, a) o1 = c.opirr(p, a)
o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31) o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31)
case 54: /* floating point arith */ case 54: /* floating point arith */
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
var rf int var rf int
if p.From.Type == obj.TYPE_CONST { if p.From.Type == obj.TYPE_CONST {
rf = chipfloat7(ctxt, p.From.Val.(float64)) rf = c.chipfloat7(p.From.Val.(float64))
if rf < 0 || true { if rf < 0 || true {
ctxt.Diag("invalid floating-point immediate\n%v", p) c.ctxt.Diag("invalid floating-point immediate\n%v", p)
rf = 0 rf = 0
} }
...@@ -2764,7 +2777,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2764,7 +2777,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31) o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
case 56: /* floating point compare */ case 56: /* floating point compare */
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
var rf int var rf int
if p.From.Type == obj.TYPE_CONST { if p.From.Type == obj.TYPE_CONST {
...@@ -2777,23 +2790,23 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2777,23 +2790,23 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5 o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5
case 57: /* floating point conditional compare */ case 57: /* floating point conditional compare */
o1 = oprrr(ctxt, p, p.As) o1 = c.oprrr(p, p.As)
cond := int(p.From.Reg) cond := int(p.From.Reg)
nzcv := int(p.To.Offset) nzcv := int(p.To.Offset)
if nzcv&^0xF != 0 { if nzcv&^0xF != 0 {
ctxt.Diag("implausible condition\n%v", p) c.ctxt.Diag("implausible condition\n%v", p)
} }
rf := int(p.Reg) rf := int(p.Reg)
if p.From3 == nil || p.From3.Reg < REG_F0 || p.From3.Reg > REG_F31 { if p.From3 == nil || p.From3.Reg < REG_F0 || p.From3.Reg > REG_F31 {
ctxt.Diag("illegal FCCMP\n%v", p) c.ctxt.Diag("illegal FCCMP\n%v", p)
break break
} }
rt := int(p.From3.Reg) rt := int(p.From3.Reg)
o1 |= uint32(rf&31)<<16 | uint32(cond)<<12 | uint32(rt&31)<<5 | uint32(nzcv) o1 |= uint32(rf&31)<<16 | uint32(cond)<<12 | uint32(rt&31)<<5 | uint32(nzcv)
case 58: /* ldar/ldxr/ldaxr */ case 58: /* ldar/ldxr/ldaxr */
o1 = opload(ctxt, p, p.As) o1 = c.opload(p, p.As)
o1 |= 0x1F << 16 o1 |= 0x1F << 16
o1 |= uint32(p.From.Reg) << 5 o1 |= uint32(p.From.Reg) << 5
...@@ -2805,7 +2818,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2805,7 +2818,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= uint32(p.To.Reg & 31) o1 |= uint32(p.To.Reg & 31)
case 59: /* stxr/stlxr */ case 59: /* stxr/stlxr */
o1 = opstore(ctxt, p, p.As) o1 = c.opstore(p, p.As)
if p.RegTo2 != obj.REG_NONE { if p.RegTo2 != obj.REG_NONE {
o1 |= uint32(p.RegTo2&31) << 16 o1 |= uint32(p.RegTo2&31) << 16
...@@ -2819,20 +2832,20 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2819,20 +2832,20 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
o1 |= uint32(p.From.Reg & 31) o1 |= uint32(p.From.Reg & 31)
case 60: /* adrp label,r */ case 60: /* adrp label,r */
d := brdist(ctxt, p, 12, 21, 0) d := c.brdist(p, 12, 21, 0)
o1 = ADR(1, uint32(d), uint32(p.To.Reg)) o1 = ADR(1, uint32(d), uint32(p.To.Reg))
case 61: /* adr label, r */ case 61: /* adr label, r */
d := brdist(ctxt, p, 0, 21, 0) d := c.brdist(p, 0, 21, 0)
o1 = ADR(0, uint32(d), uint32(p.To.Reg)) o1 = ADR(0, uint32(d), uint32(p.To.Reg))
case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */ case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */
if p.Reg == REGTMP { if p.Reg == REGTMP {
ctxt.Diag("cannot use REGTMP as source: %v\n", p) c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
} }
o1 = omovconst(ctxt, AMOVD, p, &p.From, REGTMP) o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
rt := int(p.To.Reg) rt := int(p.To.Reg)
if p.To.Type == obj.TYPE_NONE { if p.To.Type == obj.TYPE_NONE {
...@@ -2843,11 +2856,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2843,11 +2856,11 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
r = rt r = rt
} }
if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) { if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
o2 = opxrrr(ctxt, p, p.As) o2 = c.opxrrr(p, p.As)
o2 |= REGTMP & 31 << 16 o2 |= REGTMP & 31 << 16
o2 |= LSL0_64 o2 |= LSL0_64
} else { } else {
o2 = oprrr(ctxt, p, p.As) o2 = c.oprrr(p, p.As)
o2 |= REGTMP & 31 << 16 /* shift is 0 */ o2 |= REGTMP & 31 << 16 /* shift is 0 */
} }
o2 |= uint32(r&31) << 5 o2 |= uint32(r&31) << 5
...@@ -2856,31 +2869,31 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2856,31 +2869,31 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
/* reloc ops */ /* reloc ops */
case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */ case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */
o1 = ADR(1, 0, REGTMP) o1 = ADR(1, 0, REGTMP)
o2 = opirr(ctxt, p, AADD) | REGTMP&31<<5 | REGTMP&31 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
rel := obj.Addrel(ctxt.Cursym) rel := obj.Addrel(c.cursym)
rel.Off = int32(ctxt.Pc) rel.Off = int32(c.pc)
rel.Siz = 8 rel.Siz = 8
rel.Sym = p.To.Sym rel.Sym = p.To.Sym
rel.Add = p.To.Offset rel.Add = p.To.Offset
rel.Type = obj.R_ADDRARM64 rel.Type = obj.R_ADDRARM64
o3 = olsr12u(ctxt, p, int32(opstr12(ctxt, p, p.As)), 0, REGTMP, int(p.From.Reg)) o3 = c.olsr12u(p, int32(c.opstr12(p, p.As)), 0, REGTMP, int(p.From.Reg))
case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */ case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */
o1 = ADR(1, 0, REGTMP) o1 = ADR(1, 0, REGTMP)
o2 = opirr(ctxt, p, AADD) | REGTMP&31<<5 | REGTMP&31 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
rel := obj.Addrel(ctxt.Cursym) rel := obj.Addrel(c.cursym)
rel.Off = int32(ctxt.Pc) rel.Off = int32(c.pc)
rel.Siz = 8 rel.Siz = 8
rel.Sym = p.From.Sym rel.Sym = p.From.Sym
rel.Add = p.From.Offset rel.Add = p.From.Offset
rel.Type = obj.R_ADDRARM64 rel.Type = obj.R_ADDRARM64
o3 = olsr12u(ctxt, p, int32(opldr12(ctxt, p, p.As)), 0, REGTMP, int(p.To.Reg)) o3 = c.olsr12u(p, int32(c.opldr12(p, p.As)), 0, REGTMP, int(p.To.Reg))
case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */ case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */
v := int32(p.From.Offset) v := int32(p.From.Offset)
if v < -512 || v > 504 { if v < -512 || v > 504 {
ctxt.Diag("offset out of range\n%v", p) c.ctxt.Diag("offset out of range\n%v", p)
} }
if o.scond == C_XPOST { if o.scond == C_XPOST {
o1 |= 1 << 23 o1 |= 1 << 23
...@@ -2894,7 +2907,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2894,7 +2907,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
v := int32(p.To.Offset) v := int32(p.To.Offset)
if v < -512 || v > 504 { if v < -512 || v > 504 {
ctxt.Diag("offset out of range\n%v", p) c.ctxt.Diag("offset out of range\n%v", p)
} }
if o.scond == C_XPOST { if o.scond == C_XPOST {
o1 |= 1 << 23 o1 |= 1 << 23
...@@ -2905,47 +2918,47 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2905,47 +2918,47 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */ case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */
if p.As == AMOVW { if p.As == AMOVW {
ctxt.Diag("invalid load of 32-bit address: %v", p) c.ctxt.Diag("invalid load of 32-bit address: %v", p)
} }
o1 = ADR(1, 0, uint32(p.To.Reg)) o1 = ADR(1, 0, uint32(p.To.Reg))
o2 = opirr(ctxt, p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31) o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31)
rel := obj.Addrel(ctxt.Cursym) rel := obj.Addrel(c.cursym)
rel.Off = int32(ctxt.Pc) rel.Off = int32(c.pc)
rel.Siz = 8 rel.Siz = 8
rel.Sym = p.From.Sym rel.Sym = p.From.Sym
rel.Add = p.From.Offset rel.Add = p.From.Offset
rel.Type = obj.R_ADDRARM64 rel.Type = obj.R_ADDRARM64
case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */ case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */
o1 = opirr(ctxt, p, AMOVZ) o1 = c.opirr(p, AMOVZ)
o1 |= uint32(p.To.Reg & 31) o1 |= uint32(p.To.Reg & 31)
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.From.Sym rel.Sym = p.From.Sym
rel.Type = obj.R_ARM64_TLS_LE rel.Type = obj.R_ARM64_TLS_LE
if p.From.Offset != 0 { if p.From.Offset != 0 {
ctxt.Diag("invalid offset on MOVW $tlsvar") c.ctxt.Diag("invalid offset on MOVW $tlsvar")
} }
case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */ case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
o1 = ADR(1, 0, REGTMP) o1 = ADR(1, 0, REGTMP)
o2 = olsr12u(ctxt, p, int32(opldr12(ctxt, p, AMOVD)), 0, REGTMP, int(p.To.Reg)) o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
rel := obj.Addrel(ctxt.Cursym) rel := obj.Addrel(c.cursym)
rel.Off = int32(ctxt.Pc) rel.Off = int32(c.pc)
rel.Siz = 8 rel.Siz = 8
rel.Sym = p.From.Sym rel.Sym = p.From.Sym
rel.Add = 0 rel.Add = 0
rel.Type = obj.R_ARM64_TLS_IE rel.Type = obj.R_ARM64_TLS_IE
if p.From.Offset != 0 { if p.From.Offset != 0 {
ctxt.Diag("invalid offset on MOVW $tlsvar") c.ctxt.Diag("invalid offset on MOVW $tlsvar")
} }
case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */ case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */
o1 = ADR(1, 0, REGTMP) o1 = ADR(1, 0, REGTMP)
o2 = olsr12u(ctxt, p, int32(opldr12(ctxt, p, AMOVD)), 0, REGTMP, int(p.To.Reg)) o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
rel := obj.Addrel(ctxt.Cursym) rel := obj.Addrel(c.cursym)
rel.Off = int32(ctxt.Pc) rel.Off = int32(c.pc)
rel.Siz = 8 rel.Siz = 8
rel.Sym = p.From.Sym rel.Sym = p.From.Sym
rel.Add = 0 rel.Add = 0
...@@ -2975,7 +2988,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2975,7 +2988,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
* also op Rn -> Rt * also op Rn -> Rt
* also Rm*Rn op Ra -> Rd * also Rm*Rn op Ra -> Rd
*/ */
func oprrr(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 {
switch a { switch a {
case AADC: case AADC:
return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10 return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
...@@ -3489,7 +3502,7 @@ func oprrr(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -3489,7 +3502,7 @@ func oprrr(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
return FPOP1S(0, 0, 3, 5) return FPOP1S(0, 0, 3, 5)
} }
ctxt.Diag("%v: bad rrr %d %v", p, a, a) c.ctxt.Diag("%v: bad rrr %d %v", p, a, a)
return 0 return 0
} }
...@@ -3497,7 +3510,7 @@ func oprrr(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -3497,7 +3510,7 @@ func oprrr(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
* imm -> Rd * imm -> Rd
* imm op Rn -> Rd * imm op Rn -> Rd
*/ */
func opirr(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 {
switch a { switch a {
/* op $addcon, Rn, Rd */ /* op $addcon, Rn, Rd */
case AMOVD, AADD: case AMOVD, AADD:
...@@ -3675,11 +3688,11 @@ func opirr(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -3675,11 +3688,11 @@ func opirr(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
return SYSOP(0, 0, 3, 2, 0, 0, 0x1F) return SYSOP(0, 0, 3, 2, 0, 0, 0x1F)
} }
ctxt.Diag("%v: bad irr %v", p, a) c.ctxt.Diag("%v: bad irr %v", p, a)
return 0 return 0
} }
func opbit(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 {
switch a { switch a {
case ACLS: case ACLS:
return S64 | OPBIT(5) return S64 | OPBIT(5)
...@@ -3715,7 +3728,7 @@ func opbit(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -3715,7 +3728,7 @@ func opbit(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
return S64 | OPBIT(2) return S64 | OPBIT(2)
default: default:
ctxt.Diag("bad bit op\n%v", p) c.ctxt.Diag("bad bit op\n%v", p)
return 0 return 0
} }
} }
...@@ -3723,7 +3736,7 @@ func opbit(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -3723,7 +3736,7 @@ func opbit(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
/* /*
* add/subtract extended register * add/subtract extended register
*/ */
func opxrrr(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As) uint32 {
switch a { switch a {
case AADD: case AADD:
return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_64
...@@ -3750,11 +3763,11 @@ func opxrrr(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -3750,11 +3763,11 @@ func opxrrr(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | LSL0_32
} }
ctxt.Diag("bad opxrrr %v\n%v", a, p) c.ctxt.Diag("bad opxrrr %v\n%v", a, p)
return 0 return 0
} }
func opimm(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 {
switch a { switch a {
case ASVC: case ASVC:
return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */ return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */
...@@ -3784,22 +3797,22 @@ func opimm(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -3784,22 +3797,22 @@ func opimm(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
return SYSOP(0, 0, 3, 3, 0, 2, 0x1F) return SYSOP(0, 0, 3, 3, 0, 2, 0x1F)
} }
ctxt.Diag("%v: bad imm %v", p, a) c.ctxt.Diag("%v: bad imm %v", p, a)
return 0 return 0
} }
func brdist(ctxt *obj.Link, p *obj.Prog, preshift int, flen int, shift int) int64 { func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 {
v := int64(0) v := int64(0)
t := int64(0) t := int64(0)
if p.Pcond != nil { if p.Pcond != nil {
v = (p.Pcond.Pc >> uint(preshift)) - (ctxt.Pc >> uint(preshift)) v = (p.Pcond.Pc >> uint(preshift)) - (c.pc >> uint(preshift))
if (v & ((1 << uint(shift)) - 1)) != 0 { if (v & ((1 << uint(shift)) - 1)) != 0 {
ctxt.Diag("misaligned label\n%v", p) c.ctxt.Diag("misaligned label\n%v", p)
} }
v >>= uint(shift) v >>= uint(shift)
t = int64(1) << uint(flen-1) t = int64(1) << uint(flen-1)
if v < -t || v >= t { if v < -t || v >= t {
ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, ctxt.Blitrl, p, p.Pcond) c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, p.Pcond)
panic("branch too far") panic("branch too far")
} }
} }
...@@ -3810,7 +3823,7 @@ func brdist(ctxt *obj.Link, p *obj.Prog, preshift int, flen int, shift int) int6 ...@@ -3810,7 +3823,7 @@ func brdist(ctxt *obj.Link, p *obj.Prog, preshift int, flen int, shift int) int6
/* /*
* pc-relative branches * pc-relative branches
*/ */
func opbra(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 {
switch a { switch a {
case ABEQ: case ABEQ:
return OPBcc(0x0) return OPBcc(0x0)
...@@ -3867,11 +3880,11 @@ func opbra(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -3867,11 +3880,11 @@ func opbra(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
return 1<<31 | 5<<26 return 1<<31 | 5<<26
} }
ctxt.Diag("%v: bad bra %v", p, a) c.ctxt.Diag("%v: bad bra %v", p, a)
return 0 return 0
} }
func opbrr(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 {
switch a { switch a {
case ABL: case ABL:
return OPBLR(1) /* BLR */ return OPBLR(1) /* BLR */
...@@ -3883,11 +3896,11 @@ func opbrr(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -3883,11 +3896,11 @@ func opbrr(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
return OPBLR(2) /* RET */ return OPBLR(2) /* RET */
} }
ctxt.Diag("%v: bad brr %v", p, a) c.ctxt.Diag("%v: bad brr %v", p, a)
return 0 return 0
} }
func op0(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 {
switch a { switch a {
case ADRPS: case ADRPS:
return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5 return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5
...@@ -3914,14 +3927,14 @@ func op0(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -3914,14 +3927,14 @@ func op0(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
return SYSHINT(5) return SYSHINT(5)
} }
ctxt.Diag("%v: bad op0 %v", p, a) c.ctxt.Diag("%v: bad op0 %v", p, a)
return 0 return 0
} }
/* /*
* register offset * register offset
*/ */
func opload(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 {
switch a { switch a {
case ALDAR: case ALDAR:
return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10 return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10
...@@ -3978,11 +3991,11 @@ func opload(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -3978,11 +3991,11 @@ func opload(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
} }
ctxt.Diag("bad opload %v\n%v", a, p) c.ctxt.Diag("bad opload %v\n%v", a, p)
return 0 return 0
} }
func opstore(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 {
switch a { switch a {
case ASTLR: case ASTLR:
return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10 return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10
...@@ -4045,7 +4058,7 @@ func opstore(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -4045,7 +4058,7 @@ func opstore(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
} }
ctxt.Diag("bad opstore %v\n%v", a, p) c.ctxt.Diag("bad opstore %v\n%v", a, p)
return 0 return 0
} }
...@@ -4053,9 +4066,9 @@ func opstore(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -4053,9 +4066,9 @@ func opstore(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
* load/store register (unsigned immediate) C3.3.13 * load/store register (unsigned immediate) C3.3.13
* these produce 64-bit values (when there's an option) * these produce 64-bit values (when there's an option)
*/ */
func olsr12u(ctxt *obj.Link, p *obj.Prog, o int32, v int32, b int, r int) uint32 { func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
if v < 0 || v >= (1<<12) { if v < 0 || v >= (1<<12) {
ctxt.Diag("offset out of range: %d\n%v", v, p) c.ctxt.Diag("offset out of range: %d\n%v", v, p)
} }
o |= (v & 0xFFF) << 10 o |= (v & 0xFFF) << 10
o |= int32(b&31) << 5 o |= int32(b&31) << 5
...@@ -4063,7 +4076,7 @@ func olsr12u(ctxt *obj.Link, p *obj.Prog, o int32, v int32, b int, r int) uint32 ...@@ -4063,7 +4076,7 @@ func olsr12u(ctxt *obj.Link, p *obj.Prog, o int32, v int32, b int, r int) uint32
return uint32(o) return uint32(o)
} }
func opldr12(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) opldr12(p *obj.Prog, a obj.As) uint32 {
switch a { switch a {
case AMOVD: case AMOVD:
return LDSTR12U(3, 0, 1) /* imm12<<10 | Rn<<5 | Rt */ return LDSTR12U(3, 0, 1) /* imm12<<10 | Rn<<5 | Rt */
...@@ -4093,20 +4106,20 @@ func opldr12(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -4093,20 +4106,20 @@ func opldr12(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
return LDSTR12U(3, 1, 1) return LDSTR12U(3, 1, 1)
} }
ctxt.Diag("bad opldr12 %v\n%v", a, p) c.ctxt.Diag("bad opldr12 %v\n%v", a, p)
return 0 return 0
} }
func opstr12(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) opstr12(p *obj.Prog, a obj.As) uint32 {
return LD2STR(opldr12(ctxt, p, a)) return LD2STR(c.opldr12(p, a))
} }
/* /*
* load/store register (unscaled immediate) C3.3.12 * load/store register (unscaled immediate) C3.3.12
*/ */
func olsr9s(ctxt *obj.Link, p *obj.Prog, o int32, v int32, b int, r int) uint32 { func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
if v < -256 || v > 255 { if v < -256 || v > 255 {
ctxt.Diag("offset out of range: %d\n%v", v, p) c.ctxt.Diag("offset out of range: %d\n%v", v, p)
} }
o |= (v & 0x1FF) << 12 o |= (v & 0x1FF) << 12
o |= int32(b&31) << 5 o |= int32(b&31) << 5
...@@ -4114,7 +4127,7 @@ func olsr9s(ctxt *obj.Link, p *obj.Prog, o int32, v int32, b int, r int) uint32 ...@@ -4114,7 +4127,7 @@ func olsr9s(ctxt *obj.Link, p *obj.Prog, o int32, v int32, b int, r int) uint32
return uint32(o) return uint32(o)
} }
func opldr9(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) opldr9(p *obj.Prog, a obj.As) uint32 {
switch a { switch a {
case AMOVD: case AMOVD:
return LDSTR9S(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */ return LDSTR9S(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */
...@@ -4144,15 +4157,15 @@ func opldr9(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -4144,15 +4157,15 @@ func opldr9(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
return LDSTR9S(3, 1, 1) return LDSTR9S(3, 1, 1)
} }
ctxt.Diag("bad opldr9 %v\n%v", a, p) c.ctxt.Diag("bad opldr9 %v\n%v", a, p)
return 0 return 0
} }
func opstr9(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) opstr9(p *obj.Prog, a obj.As) uint32 {
return LD2STR(opldr9(ctxt, p, a)) return LD2STR(c.opldr9(p, a))
} }
func opldrpp(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { func (c *ctxt7) opldrpp(p *obj.Prog, a obj.As) uint32 {
switch a { switch a {
case AMOVD: case AMOVD:
return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 /* simm9<<12 | Rn<<5 | Rt */ return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 /* simm9<<12 | Rn<<5 | Rt */
...@@ -4176,22 +4189,22 @@ func opldrpp(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 { ...@@ -4176,22 +4189,22 @@ func opldrpp(ctxt *obj.Link, p *obj.Prog, a obj.As) uint32 {
return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
} }
ctxt.Diag("bad opldr %v\n%v", a, p) c.ctxt.Diag("bad opldr %v\n%v", a, p)
return 0 return 0
} }
/* /*
* load/store register (extended register) * load/store register (extended register)
*/ */
func olsxrr(ctxt *obj.Link, p *obj.Prog, as obj.As, rt int, r1 int, r2 int) uint32 { func (c *ctxt7) olsxrr(p *obj.Prog, as obj.As, rt int, r1 int, r2 int) uint32 {
ctxt.Diag("need load/store extended register\n%v", p) c.ctxt.Diag("need load/store extended register\n%v", p)
return 0xffffffff return 0xffffffff
} }
func oaddi(ctxt *obj.Link, p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 { func (c *ctxt7) oaddi(p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 {
if (v & 0xFFF000) != 0 { if (v & 0xFFF000) != 0 {
if v&0xFFF != 0 { if v&0xFFF != 0 {
ctxt.Diag("%v misuses oaddi", p) c.ctxt.Diag("%v misuses oaddi", p)
} }
v >>= 12 v >>= 12
o1 |= 1 << 22 o1 |= 1 << 22
...@@ -4204,16 +4217,16 @@ func oaddi(ctxt *obj.Link, p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 ...@@ -4204,16 +4217,16 @@ func oaddi(ctxt *obj.Link, p *obj.Prog, o1 int32, v int32, r int, rt int) uint32
/* /*
* load a a literal value into dr * load a a literal value into dr
*/ */
func omovlit(ctxt *obj.Link, as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 { func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 {
var o1 int32 var o1 int32
if p.Pcond == nil { /* not in literal pool */ if p.Pcond == nil { /* not in literal pool */
aclass(ctxt, a) c.aclass(a)
ctxt.Logf("omovlit add %d (%#x)\n", ctxt.Instoffset, uint64(ctxt.Instoffset)) c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset))
/* TODO: could be clever, and use general constant builder */ /* TODO: could be clever, and use general constant builder */
o1 = int32(opirr(ctxt, p, AADD)) o1 = int32(c.opirr(p, AADD))
v := int32(ctxt.Instoffset) v := int32(c.instoffset)
if v != 0 && (v&0xFFF) == 0 { if v != 0 && (v&0xFFF) == 0 {
v >>= 12 v >>= 12
o1 |= 1 << 22 /* shift, by 12 */ o1 |= 1 << 22 /* shift, by 12 */
...@@ -4243,7 +4256,7 @@ func omovlit(ctxt *obj.Link, as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 ...@@ -4243,7 +4256,7 @@ func omovlit(ctxt *obj.Link, as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32
break break
} }
v := int32(brdist(ctxt, p, 0, 19, 2)) v := int32(c.brdist(p, 0, 19, 2))
o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27) o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27)
o1 |= (v & 0x7FFFF) << 5 o1 |= (v & 0x7FFFF) << 5
o1 |= int32(dr & 31) o1 |= int32(dr & 31)
...@@ -4253,7 +4266,7 @@ func omovlit(ctxt *obj.Link, as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 ...@@ -4253,7 +4266,7 @@ func omovlit(ctxt *obj.Link, as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32
} }
// load a constant (MOVCON or BITCON) in a into rt // load a constant (MOVCON or BITCON) in a into rt
func omovconst(ctxt *obj.Link, as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) { func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) {
if cls := oclass(a); cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0 { if cls := oclass(a); cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0 {
// or $bitcon, REGZERO, rt // or $bitcon, REGZERO, rt
mode := 64 mode := 64
...@@ -4265,7 +4278,7 @@ func omovconst(ctxt *obj.Link, as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 ...@@ -4265,7 +4278,7 @@ func omovconst(ctxt *obj.Link, as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1
case AMOVD: case AMOVD:
as1 = AORR as1 = AORR
} }
o1 = opirr(ctxt, p, as1) o1 = c.opirr(p, as1)
o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31) o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31)
return o1 return o1
} }
...@@ -4280,54 +4293,54 @@ func omovconst(ctxt *obj.Link, as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 ...@@ -4280,54 +4293,54 @@ func omovconst(ctxt *obj.Link, as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1
d = ^d d = ^d
s = movcon(d) s = movcon(d)
if s < 0 || s >= r { if s < 0 || s >= r {
ctxt.Diag("impossible move wide: %#x\n%v", uint64(a.Offset), p) c.ctxt.Diag("impossible move wide: %#x\n%v", uint64(a.Offset), p)
} }
if as == AMOVD { if as == AMOVD {
o1 = opirr(ctxt, p, AMOVN) o1 = c.opirr(p, AMOVN)
} else { } else {
o1 = opirr(ctxt, p, AMOVNW) o1 = c.opirr(p, AMOVNW)
} }
} else { } else {
if as == AMOVD { if as == AMOVD {
o1 = opirr(ctxt, p, AMOVZ) o1 = c.opirr(p, AMOVZ)
} else { } else {
o1 = opirr(ctxt, p, AMOVZW) o1 = c.opirr(p, AMOVZW)
} }
} }
o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31)) o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31))
return o1 return o1
} }
func opbfm(ctxt *obj.Link, p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 { func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 {
var b uint32 var b uint32
o := opirr(ctxt, p, a) o := c.opirr(p, a)
if (o & (1 << 31)) == 0 { if (o & (1 << 31)) == 0 {
b = 32 b = 32
} else { } else {
b = 64 b = 64
} }
if r < 0 || uint32(r) >= b { if r < 0 || uint32(r) >= b {
ctxt.Diag("illegal bit number\n%v", p) c.ctxt.Diag("illegal bit number\n%v", p)
} }
o |= (uint32(r) & 0x3F) << 16 o |= (uint32(r) & 0x3F) << 16
if s < 0 || uint32(s) >= b { if s < 0 || uint32(s) >= b {
ctxt.Diag("illegal bit number\n%v", p) c.ctxt.Diag("illegal bit number\n%v", p)
} }
o |= (uint32(s) & 0x3F) << 10 o |= (uint32(s) & 0x3F) << 10
o |= (uint32(rf&31) << 5) | uint32(rt&31) o |= (uint32(rf&31) << 5) | uint32(rt&31)
return o return o
} }
func opextr(ctxt *obj.Link, p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 { func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 {
var b uint32 var b uint32
o := opirr(ctxt, p, a) o := c.opirr(p, a)
if (o & (1 << 31)) != 0 { if (o & (1 << 31)) != 0 {
b = 63 b = 63
} else { } else {
b = 31 b = 31
} }
if v < 0 || uint32(v) > b { if v < 0 || uint32(v) > b {
ctxt.Diag("illegal bit number\n%v", p) c.ctxt.Diag("illegal bit number\n%v", p)
} }
o |= uint32(v) << 10 o |= uint32(v) << 10
o |= uint32(rn&31) << 5 o |= uint32(rn&31) << 5
......
...@@ -47,16 +47,16 @@ var complements = []obj.As{ ...@@ -47,16 +47,16 @@ var complements = []obj.As{
ACMNW: ACMPW, ACMNW: ACMPW,
} }
func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize int32) *obj.Prog { func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
// MOV g_stackguard(g), R1 // MOV g_stackguard(g), R1
p = obj.Appendp(p, newprog) p = obj.Appendp(p, c.newprog)
p.As = AMOVD p.As = AMOVD
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
...@@ -66,7 +66,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in ...@@ -66,7 +66,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in
// small stack: SP < stackguard // small stack: SP < stackguard
// MOV SP, R2 // MOV SP, R2
// CMP stackguard, R2 // CMP stackguard, R2
p = obj.Appendp(p, newprog) p = obj.Appendp(p, c.newprog)
p.As = AMOVD p.As = AMOVD
p.From.Type = obj.TYPE_REG p.From.Type = obj.TYPE_REG
...@@ -74,7 +74,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in ...@@ -74,7 +74,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
...@@ -83,7 +83,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in ...@@ -83,7 +83,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
// SUB $(framesize-StackSmall), SP, R2 // SUB $(framesize-StackSmall), SP, R2
// CMP stackguard, R2 // CMP stackguard, R2
p = obj.Appendp(p, newprog) p = obj.Appendp(p, c.newprog)
p.As = ASUB p.As = ASUB
p.From.Type = obj.TYPE_CONST p.From.Type = obj.TYPE_CONST
...@@ -92,7 +92,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in ...@@ -92,7 +92,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
...@@ -109,19 +109,19 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in ...@@ -109,19 +109,19 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in
// SUB R1, R2 // SUB R1, R2
// MOV $(framesize+(StackGuard-StackSmall)), R3 // MOV $(framesize+(StackGuard-StackSmall)), R3
// CMP R3, R2 // CMP 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 = obj.StackPreempt p.From.Offset = obj.StackPreempt
p.Reg = REG_R1 p.Reg = REG_R1
p = obj.Appendp(p, newprog) p = obj.Appendp(p, c.newprog)
q = p q = p
p.As = ABEQ p.As = ABEQ
p.To.Type = obj.TYPE_BRANCH p.To.Type = obj.TYPE_BRANCH
p = obj.Appendp(p, newprog) p = obj.Appendp(p, c.newprog)
p.As = AADD p.As = AADD
p.From.Type = obj.TYPE_CONST p.From.Type = obj.TYPE_CONST
p.From.Offset = obj.StackGuard p.From.Offset = obj.StackGuard
...@@ -129,21 +129,21 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in ...@@ -129,21 +129,21 @@ 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 = 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
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 = AMOVD p.As = AMOVD
p.From.Type = obj.TYPE_CONST p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(framesize) + (obj.StackGuard - obj.StackSmall) p.From.Offset = int64(framesize) + (obj.StackGuard - obj.StackSmall)
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R3 p.To.Reg = REG_R3
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
...@@ -151,23 +151,23 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in ...@@ -151,23 +151,23 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in
} }
// BLS do-morestack // BLS do-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
...@@ -175,7 +175,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in ...@@ -175,7 +175,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
// MOV LR, R3 // MOV LR, R3
movlr := obj.Appendp(pcdata, newprog) movlr := obj.Appendp(pcdata, c.newprog)
movlr.As = AMOVD movlr.As = AMOVD
movlr.From.Type = obj.TYPE_REG movlr.From.Type = obj.TYPE_REG
movlr.From.Reg = REGLINK movlr.From.Reg = REGLINK
...@@ -188,7 +188,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in ...@@ -188,7 +188,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in
debug := movlr debug := movlr
if false { if false {
debug = obj.Appendp(debug, newprog) debug = obj.Appendp(debug, c.newprog)
debug.As = AMOVD debug.As = AMOVD
debug.From.Type = obj.TYPE_CONST debug.From.Type = obj.TYPE_CONST
debug.From.Offset = int64(framesize) debug.From.Offset = int64(framesize)
...@@ -197,23 +197,23 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in ...@@ -197,23 +197,23 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in
} }
// BL runtime.morestack(SB) // BL runtime.morestack(SB)
call := obj.Appendp(debug, newprog) call := obj.Appendp(debug, c.newprog)
call.As = ABL call.As = ABL
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
jmp := obj.Appendp(call, newprog) jmp := obj.Appendp(call, c.newprog)
jmp.As = AB jmp.As = AB
jmp.To.Type = obj.TYPE_BRANCH jmp.To.Type = obj.TYPE_BRANCH
jmp.Pcond = ctxt.Cursym.Text.Link jmp.Pcond = c.cursym.Text.Link
jmp.Spadj = +framesize jmp.Spadj = +framesize
// placeholder for bls's jump target // placeholder for bls's jump target
...@@ -224,6 +224,8 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in ...@@ -224,6 +224,8 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc, framesize in
} }
func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
c := ctxt7{ctxt: ctxt, newprog: newprog}
p.From.Class = 0 p.From.Class = 0
p.To.Class = 0 p.To.Class = 0
...@@ -264,7 +266,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { ...@@ -264,7 +266,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
break break
} }
p.From.Type = obj.TYPE_MEM p.From.Type = obj.TYPE_MEM
p.From.Sym = ctxt.Float32Sym(f32) p.From.Sym = c.ctxt.Float32Sym(f32)
p.From.Name = obj.NAME_EXTERN p.From.Name = obj.NAME_EXTERN
p.From.Offset = 0 p.From.Offset = 0
} }
...@@ -278,7 +280,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { ...@@ -278,7 +280,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
break break
} }
p.From.Type = obj.TYPE_MEM p.From.Type = obj.TYPE_MEM
p.From.Sym = ctxt.Float64Sym(f64) p.From.Sym = c.ctxt.Float64Sym(f64)
p.From.Name = obj.NAME_EXTERN p.From.Name = obj.NAME_EXTERN
p.From.Offset = 0 p.From.Offset = 0
} }
...@@ -315,13 +317,13 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { ...@@ -315,13 +317,13 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
} }
} }
if ctxt.Flag_dynlink { if c.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 *ctxt7) 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
...@@ -330,9 +332,9 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { ...@@ -330,9 +332,9 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
// CALL REGTMP // CALL REGTMP
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 = AMOVD p.As = AMOVD
...@@ -344,13 +346,13 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { ...@@ -344,13 +346,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 = REGTMP p1.To.Reg = REGTMP
p2 := obj.Appendp(p1, newprog) p2 := obj.Appendp(p1, c.newprog)
p2.As = obj.ACALL p2.As = obj.ACALL
p2.To.Type = obj.TYPE_REG p2.To.Type = obj.TYPE_REG
p2.To.Reg = REGTMP p2.To.Reg = REGTMP
...@@ -363,15 +365,15 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { ...@@ -363,15 +365,15 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
// MOVD $sym, Rx becomes MOVD sym@GOT, Rx // MOVD $sym, Rx becomes MOVD sym@GOT, Rx
// MOVD $sym+<off>, Rx becomes MOVD sym@GOT, Rx; ADD <off>, Rx // MOVD $sym+<off>, Rx becomes MOVD sym@GOT, Rx; ADD <off>, Rx
if p.As != AMOVD { if p.As != AMOVD {
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
...@@ -380,7 +382,7 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { ...@@ -380,7 +382,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 MOVD sym@GOT, REGTMP; MOVx (REGTMP), Ry // MOVx sym, Ry becomes MOVD sym@GOT, REGTMP; MOVx (REGTMP), Ry
...@@ -388,7 +390,7 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { ...@@ -388,7 +390,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() {
...@@ -403,10 +405,10 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { ...@@ -403,10 +405,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 = AMOVD p1.As = AMOVD
p1.From.Type = obj.TYPE_MEM p1.From.Type = obj.TYPE_MEM
p1.From.Sym = source.Sym p1.From.Sym = source.Sym
...@@ -432,18 +434,18 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { ...@@ -432,18 +434,18 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
} }
func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
ctxt.Cursym = cursym
if cursym.Text == nil || cursym.Text.Link == nil { if cursym.Text == nil || cursym.Text.Link == nil {
return return
} }
p := cursym.Text c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym}
p := c.cursym.Text
textstksiz := p.To.Offset textstksiz := p.To.Offset
aoffset := int32(textstksiz) aoffset := int32(textstksiz)
cursym.Args = p.To.Val.(int32) c.cursym.Args = p.To.Val.(int32)
cursym.Locals = int32(textstksiz) c.cursym.Locals = int32(textstksiz)
/* /*
* find leaf subroutines * find leaf subroutines
...@@ -452,7 +454,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -452,7 +454,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
*/ */
q := (*obj.Prog)(nil) q := (*obj.Prog)(nil)
var q1 *obj.Prog var q1 *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 obj.ATEXT: case obj.ATEXT:
p.Mark |= LEAF p.Mark |= LEAF
...@@ -469,7 +471,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -469,7 +471,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
case ABL, case ABL,
obj.ADUFFZERO, obj.ADUFFZERO,
obj.ADUFFCOPY: obj.ADUFFCOPY:
cursym.Text.Mark &^= LEAF c.cursym.Text.Mark &^= LEAF
fallthrough fallthrough
case ACBNZ, case ACBNZ,
...@@ -514,19 +516,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -514,19 +516,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
var q2 *obj.Prog var q2 *obj.Prog
var retjmp *obj.LSym var retjmp *obj.LSym
for p := cursym.Text; p != nil; p = p.Link { for p := c.cursym.Text; p != nil; p = p.Link {
o := p.As o := p.As
switch o { switch o {
case obj.ATEXT: case obj.ATEXT:
cursym.Text = p c.cursym.Text = p
if textstksiz < 0 { if textstksiz < 0 {
ctxt.Autosize = 0 c.autosize = 0
} else { } else {
ctxt.Autosize = int32(textstksiz + 8) c.autosize = int32(textstksiz + 8)
} }
if (cursym.Text.Mark&LEAF != 0) && ctxt.Autosize <= 8 { if (c.cursym.Text.Mark&LEAF != 0) && c.autosize <= 8 {
ctxt.Autosize = 0 c.autosize = 0
} else if ctxt.Autosize&(16-1) != 0 { } else if c.autosize&(16-1) != 0 {
// The frame includes an LR. // The frame includes an LR.
// If the frame size is 8, it's only an LR, // If the frame size is 8, it's only an LR,
// so there's no potential for breaking references to // so there's no potential for breaking references to
...@@ -535,32 +537,32 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -535,32 +537,32 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
// But otherwise, if there is a non-empty locals section, // But otherwise, if there is a non-empty locals section,
// the author of the code is responsible for making sure // the author of the code is responsible for making sure
// that the frame size is 8 mod 16. // that the frame size is 8 mod 16.
if ctxt.Autosize == 8 { if c.autosize == 8 {
ctxt.Autosize += 8 c.autosize += 8
cursym.Locals += 8 c.cursym.Locals += 8
} else { } else {
ctxt.Diag("%v: unaligned frame size %d - must be 8 mod 16 (or 0)", p, ctxt.Autosize-8) c.ctxt.Diag("%v: unaligned frame size %d - must be 8 mod 16 (or 0)", p, c.autosize-8)
} }
} }
p.To.Offset = int64(ctxt.Autosize) - 8 p.To.Offset = int64(c.autosize) - 8
if ctxt.Autosize == 0 && !(cursym.Text.Mark&LEAF != 0) { if c.autosize == 0 && !(c.cursym.Text.Mark&LEAF != 0) {
if ctxt.Debugvlog { if c.ctxt.Debugvlog {
ctxt.Logf("save suppressed in: %s\n", cursym.Text.From.Sym.Name) c.ctxt.Logf("save suppressed in: %s\n", c.cursym.Text.From.Sym.Name)
} }
cursym.Text.Mark |= LEAF c.cursym.Text.Mark |= LEAF
} }
if !(p.From3.Offset&obj.NOSPLIT != 0) { if !(p.From3.Offset&obj.NOSPLIT != 0) {
p = stacksplit(ctxt, p, newprog, ctxt.Autosize) // emit split check p = c.stacksplit(p, c.autosize) // emit split check
} }
aoffset = ctxt.Autosize aoffset = c.autosize
if aoffset > 0xF0 { if aoffset > 0xF0 {
aoffset = 0xF0 aoffset = 0xF0
} }
if cursym.Text.Mark&LEAF != 0 { if c.cursym.Text.Mark&LEAF != 0 {
cursym.Set(obj.AttrLeaf, true) c.cursym.Set(obj.AttrLeaf, true)
if ctxt.Autosize == 0 { if c.autosize == 0 {
break break
} }
} }
...@@ -568,21 +570,21 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -568,21 +570,21 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
// Frame is non-empty. Make sure to save link register, even if // Frame is non-empty. Make sure to save link register, even if
// it is a leaf function, so that traceback works. // it is a leaf function, so that traceback works.
q = p q = p
if ctxt.Autosize > aoffset { if c.autosize > aoffset {
// Frame size is too large for a MOVD.W instruction. // Frame size is too large for a MOVD.W instruction.
// Store link register before decrementing SP, so if a signal comes // Store link register before decrementing SP, so if a signal comes
// during the execution of the function prologue, the traceback // during the execution of the function prologue, the traceback
// code will not see a half-updated stack frame. // code will not see a half-updated stack frame.
q = obj.Appendp(q, newprog) q = obj.Appendp(q, c.newprog)
q.Pos = p.Pos q.Pos = p.Pos
q.As = ASUB q.As = ASUB
q.From.Type = obj.TYPE_CONST q.From.Type = obj.TYPE_CONST
q.From.Offset = int64(ctxt.Autosize) q.From.Offset = int64(c.autosize)
q.Reg = REGSP q.Reg = REGSP
q.To.Type = obj.TYPE_REG q.To.Type = obj.TYPE_REG
q.To.Reg = REGTMP q.To.Reg = REGTMP
q = obj.Appendp(q, newprog) q = obj.Appendp(q, c.newprog)
q.Pos = p.Pos q.Pos = p.Pos
q.As = AMOVD q.As = AMOVD
q.From.Type = obj.TYPE_REG q.From.Type = obj.TYPE_REG
...@@ -590,17 +592,17 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -590,17 +592,17 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q.To.Type = obj.TYPE_MEM q.To.Type = obj.TYPE_MEM
q.To.Reg = REGTMP q.To.Reg = REGTMP
q1 = obj.Appendp(q, newprog) q1 = obj.Appendp(q, c.newprog)
q1.Pos = p.Pos q1.Pos = p.Pos
q1.As = AMOVD q1.As = AMOVD
q1.From.Type = obj.TYPE_REG q1.From.Type = obj.TYPE_REG
q1.From.Reg = REGTMP q1.From.Reg = REGTMP
q1.To.Type = obj.TYPE_REG q1.To.Type = obj.TYPE_REG
q1.To.Reg = REGSP q1.To.Reg = REGSP
q1.Spadj = ctxt.Autosize q1.Spadj = c.autosize
} else { } else {
// small frame, update SP and save LR in a single MOVD.W instruction // small frame, update SP and save LR in a single MOVD.W instruction
q1 = obj.Appendp(q, newprog) q1 = obj.Appendp(q, c.newprog)
q1.As = AMOVD q1.As = AMOVD
q1.Pos = p.Pos q1.Pos = p.Pos
q1.From.Type = obj.TYPE_REG q1.From.Type = obj.TYPE_REG
...@@ -612,7 +614,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -612,7 +614,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q1.Spadj = aoffset q1.Spadj = aoffset
} }
if cursym.Text.From3.Offset&obj.WRAPPER != 0 { if c.cursym.Text.From3.Offset&obj.WRAPPER != 0 {
// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame // if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
// //
// MOV g_panic(g), R1 // MOV g_panic(g), R1
...@@ -631,26 +633,26 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -631,26 +633,26 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
// It is a liblink NOP, not a ARM64 NOP: it encodes to 0 instruction bytes. // It is a liblink NOP, not a ARM64 NOP: it encodes to 0 instruction bytes.
q = q1 q = q1
q = obj.Appendp(q, newprog) q = obj.Appendp(q, c.newprog)
q.As = AMOVD q.As = AMOVD
q.From.Type = obj.TYPE_MEM q.From.Type = obj.TYPE_MEM
q.From.Reg = REGG q.From.Reg = REGG
q.From.Offset = 4 * int64(ctxt.Arch.PtrSize) // G.panic q.From.Offset = 4 * int64(c.ctxt.Arch.PtrSize) // G.panic
q.To.Type = obj.TYPE_REG q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R1 q.To.Reg = REG_R1
q = obj.Appendp(q, newprog) q = obj.Appendp(q, c.newprog)
q.As = ACMP q.As = ACMP
q.From.Type = obj.TYPE_REG q.From.Type = obj.TYPE_REG
q.From.Reg = REGZERO q.From.Reg = REGZERO
q.Reg = REG_R1 q.Reg = REG_R1
q = obj.Appendp(q, newprog) q = obj.Appendp(q, c.newprog)
q.As = ABEQ q.As = ABEQ
q.To.Type = obj.TYPE_BRANCH q.To.Type = obj.TYPE_BRANCH
q1 = q q1 = q
q = obj.Appendp(q, newprog) q = obj.Appendp(q, c.newprog)
q.As = AMOVD q.As = AMOVD
q.From.Type = obj.TYPE_MEM q.From.Type = obj.TYPE_MEM
q.From.Reg = REG_R1 q.From.Reg = REG_R1
...@@ -658,26 +660,26 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -658,26 +660,26 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q.To.Type = obj.TYPE_REG q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R2 q.To.Reg = REG_R2
q = obj.Appendp(q, newprog) q = obj.Appendp(q, c.newprog)
q.As = AADD q.As = AADD
q.From.Type = obj.TYPE_CONST q.From.Type = obj.TYPE_CONST
q.From.Offset = int64(ctxt.Autosize) + 8 q.From.Offset = int64(c.autosize) + 8
q.Reg = REGSP q.Reg = REGSP
q.To.Type = obj.TYPE_REG q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R3 q.To.Reg = REG_R3
q = obj.Appendp(q, newprog) q = obj.Appendp(q, c.newprog)
q.As = ACMP q.As = ACMP
q.From.Type = obj.TYPE_REG q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R2 q.From.Reg = REG_R2
q.Reg = REG_R3 q.Reg = REG_R3
q = obj.Appendp(q, newprog) q = obj.Appendp(q, c.newprog)
q.As = ABNE q.As = ABNE
q.To.Type = obj.TYPE_BRANCH q.To.Type = obj.TYPE_BRANCH
q2 = q q2 = q
q = obj.Appendp(q, newprog) q = obj.Appendp(q, c.newprog)
q.As = AADD q.As = AADD
q.From.Type = obj.TYPE_CONST q.From.Type = obj.TYPE_CONST
q.From.Offset = 8 q.From.Offset = 8
...@@ -685,7 +687,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -685,7 +687,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q.To.Type = obj.TYPE_REG q.To.Type = obj.TYPE_REG
q.To.Reg = REG_R4 q.To.Reg = REG_R4
q = obj.Appendp(q, newprog) q = obj.Appendp(q, c.newprog)
q.As = AMOVD q.As = AMOVD
q.From.Type = obj.TYPE_REG q.From.Type = obj.TYPE_REG
q.From.Reg = REG_R4 q.From.Reg = REG_R4
...@@ -693,7 +695,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -693,7 +695,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
q.To.Reg = REG_R1 q.To.Reg = REG_R1
q.To.Offset = 0 // Panic.argp q.To.Offset = 0 // Panic.argp
q = obj.Appendp(q, newprog) q = obj.Appendp(q, c.newprog)
q.As = obj.ANOP q.As = obj.ANOP
q1.Pcond = q q1.Pcond = q
...@@ -703,24 +705,24 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -703,24 +705,24 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
case obj.ARET: case obj.ARET:
nocache(p) nocache(p)
if p.From.Type == obj.TYPE_CONST { if p.From.Type == obj.TYPE_CONST {
ctxt.Diag("using BECOME (%v) is not supported!", p) c.ctxt.Diag("using BECOME (%v) is not supported!", p)
break break
} }
retjmp = p.To.Sym retjmp = p.To.Sym
p.To = obj.Addr{} p.To = obj.Addr{}
if cursym.Text.Mark&LEAF != 0 { if c.cursym.Text.Mark&LEAF != 0 {
if ctxt.Autosize != 0 { if c.autosize != 0 {
p.As = AADD p.As = AADD
p.From.Type = obj.TYPE_CONST p.From.Type = obj.TYPE_CONST
p.From.Offset = int64(ctxt.Autosize) p.From.Offset = int64(c.autosize)
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = REGSP p.To.Reg = REGSP
p.Spadj = -ctxt.Autosize p.Spadj = -c.autosize
} }
} else { } else {
/* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/ /* want write-back pre-indexed SP+autosize -> SP, loading REGLINK*/
aoffset = ctxt.Autosize aoffset = c.autosize
if aoffset > 0xF0 { if aoffset > 0xF0 {
aoffset = 0xF0 aoffset = 0xF0
...@@ -733,11 +735,11 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -733,11 +735,11 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = REGLINK p.To.Reg = REGLINK
p.Spadj = -aoffset p.Spadj = -aoffset
if ctxt.Autosize > aoffset { if c.autosize > aoffset {
q = newprog() q = newprog()
q.As = AADD q.As = AADD
q.From.Type = obj.TYPE_CONST q.From.Type = obj.TYPE_CONST
q.From.Offset = int64(ctxt.Autosize) - int64(aoffset) q.From.Offset = int64(c.autosize) - int64(aoffset)
q.To.Type = obj.TYPE_REG q.To.Type = obj.TYPE_REG
q.To.Reg = REGSP q.To.Reg = REGSP
q.Link = p.Link q.Link = p.Link
...@@ -760,7 +762,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -760,7 +762,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p.As = AB p.As = AB
p.To.Type = obj.TYPE_BRANCH p.To.Type = obj.TYPE_BRANCH
p.To.Sym = retjmp p.To.Sym = retjmp
p.Spadj = +ctxt.Autosize p.Spadj = +c.autosize
break break
} }
...@@ -768,7 +770,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { ...@@ -768,7 +770,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
p.To.Type = obj.TYPE_MEM p.To.Type = obj.TYPE_MEM
p.To.Offset = 0 p.To.Offset = 0
p.To.Reg = REGLINK p.To.Reg = REGLINK
p.Spadj = +ctxt.Autosize p.Spadj = +c.autosize
case AADD, ASUB: case AADD, ASUB:
if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST { if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
......
...@@ -728,8 +728,6 @@ type Link struct { ...@@ -728,8 +728,6 @@ type Link struct {
Imports []string Imports []string
Plan9privates *LSym Plan9privates *LSym
Printp *Prog Printp *Prog
Blitrl *Prog
Elitrl *Prog
Instoffset int64 Instoffset int64
Autosize int32 Autosize int32
Pc int64 Pc int64
......
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