Commit 2ebe1bdd authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/internal/obj: make x86's asmbuf a local variable

The x86 assembler requires a buffer to build
variable-length instructions.
It used to be an obj.Link field.
That doesn't play nicely with concurrent assembly.
Move the AsmBuf type to the x86 package,
where it belongs anyway,
and make it a local variable.

Passes toolstash-check -all.
No compiler performance impact.

Updates #15756

Change-Id: I8014e52145380bfd378ee374a0c971ee5bada917
Reviewed-on: https://go-review.googlesource.com/38663
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 3b251e60
...@@ -740,7 +740,6 @@ type Link struct { ...@@ -740,7 +740,6 @@ type Link struct {
Rep int Rep int
Repn int Repn int
Lock int Lock int
AsmBuf AsmBuf // instruction buffer for x86
Instoffset int64 Instoffset int64
Autosize int32 Autosize int32
Armsize int32 Armsize int32
...@@ -878,96 +877,3 @@ func (h *HeadType) String() string { ...@@ -878,96 +877,3 @@ func (h *HeadType) String() string {
} }
return fmt.Sprintf("HeadType(%d)", *h) return fmt.Sprintf("HeadType(%d)", *h)
} }
// AsmBuf is a simple buffer to assemble variable-length x86 instructions into.
type AsmBuf struct {
buf [100]byte
off int
}
// Put1 appends one byte to the end of the buffer.
func (a *AsmBuf) Put1(x byte) {
a.buf[a.off] = x
a.off++
}
// Put2 appends two bytes to the end of the buffer.
func (a *AsmBuf) Put2(x, y byte) {
a.buf[a.off+0] = x
a.buf[a.off+1] = y
a.off += 2
}
// Put3 appends three bytes to the end of the buffer.
func (a *AsmBuf) Put3(x, y, z byte) {
a.buf[a.off+0] = x
a.buf[a.off+1] = y
a.buf[a.off+2] = z
a.off += 3
}
// Put4 appends four bytes to the end of the buffer.
func (a *AsmBuf) Put4(x, y, z, w byte) {
a.buf[a.off+0] = x
a.buf[a.off+1] = y
a.buf[a.off+2] = z
a.buf[a.off+3] = w
a.off += 4
}
// PutInt16 writes v into the buffer using little-endian encoding.
func (a *AsmBuf) PutInt16(v int16) {
a.buf[a.off+0] = byte(v)
a.buf[a.off+1] = byte(v >> 8)
a.off += 2
}
// PutInt32 writes v into the buffer using little-endian encoding.
func (a *AsmBuf) PutInt32(v int32) {
a.buf[a.off+0] = byte(v)
a.buf[a.off+1] = byte(v >> 8)
a.buf[a.off+2] = byte(v >> 16)
a.buf[a.off+3] = byte(v >> 24)
a.off += 4
}
// PutInt64 writes v into the buffer using little-endian encoding.
func (a *AsmBuf) PutInt64(v int64) {
a.buf[a.off+0] = byte(v)
a.buf[a.off+1] = byte(v >> 8)
a.buf[a.off+2] = byte(v >> 16)
a.buf[a.off+3] = byte(v >> 24)
a.buf[a.off+4] = byte(v >> 32)
a.buf[a.off+5] = byte(v >> 40)
a.buf[a.off+6] = byte(v >> 48)
a.buf[a.off+7] = byte(v >> 56)
a.off += 8
}
// Put copies b into the buffer.
func (a *AsmBuf) Put(b []byte) {
copy(a.buf[a.off:], b)
a.off += len(b)
}
// Insert inserts b at offset i.
func (a *AsmBuf) Insert(i int, b byte) {
a.off++
copy(a.buf[i+1:a.off], a.buf[i:a.off-1])
a.buf[i] = b
}
// Last returns the byte at the end of the buffer.
func (a *AsmBuf) Last() byte { return a.buf[a.off-1] }
// Len returns the length of the buffer.
func (a *AsmBuf) Len() int { return a.off }
// Bytes returns the contents of the buffer.
func (a *AsmBuf) Bytes() []byte { return a.buf[:a.off] }
// Reset empties the buffer.
func (a *AsmBuf) Reset() { a.off = 0 }
// Peek returns the byte at offset i.
func (a *AsmBuf) Peek(i int) byte { return a.buf[i] }
...@@ -1773,6 +1773,8 @@ func span6(ctxt *obj.Link, s *obj.LSym) { ...@@ -1773,6 +1773,8 @@ func span6(ctxt *obj.Link, s *obj.LSym) {
ctxt.Diag("x86 tables not initialized, call x86.InstInit first") ctxt.Diag("x86 tables not initialized, call x86.InstInit first")
} }
var asmbuf AsmBuf
for p := ctxt.Cursym.Text; p != nil; p = p.Link { for p := ctxt.Cursym.Text; p != nil; p = p.Link {
if p.To.Type == obj.TYPE_BRANCH { if p.To.Type == obj.TYPE_BRANCH {
if p.Pcond == nil { if p.Pcond == nil {
...@@ -1913,15 +1915,15 @@ func span6(ctxt *obj.Link, s *obj.LSym) { ...@@ -1913,15 +1915,15 @@ func span6(ctxt *obj.Link, s *obj.LSym) {
p.Rel = nil p.Rel = nil
p.Pc = int64(c) p.Pc = int64(c)
asmins(ctxt, p) asmbuf.asmins(ctxt, p)
m := ctxt.AsmBuf.Len() m := asmbuf.Len()
if int(p.Isize) != m { if int(p.Isize) != m {
p.Isize = uint8(m) p.Isize = uint8(m)
loop++ loop++
} }
s.Grow(p.Pc + int64(m)) s.Grow(p.Pc + int64(m))
copy(s.P[p.Pc:], ctxt.AsmBuf.Bytes()) copy(s.P[p.Pc:], asmbuf.Bytes())
c += int32(m) c += int32(m)
} }
...@@ -2568,7 +2570,100 @@ func oclass(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int { ...@@ -2568,7 +2570,100 @@ func oclass(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int {
return Yxxx return Yxxx
} }
func asmidx(ctxt *obj.Link, scale int, index int, base int) { // AsmBuf is a simple buffer to assemble variable-length x86 instructions into.
type AsmBuf struct {
buf [100]byte
off int
}
// Put1 appends one byte to the end of the buffer.
func (a *AsmBuf) Put1(x byte) {
a.buf[a.off] = x
a.off++
}
// Put2 appends two bytes to the end of the buffer.
func (a *AsmBuf) Put2(x, y byte) {
a.buf[a.off+0] = x
a.buf[a.off+1] = y
a.off += 2
}
// Put3 appends three bytes to the end of the buffer.
func (a *AsmBuf) Put3(x, y, z byte) {
a.buf[a.off+0] = x
a.buf[a.off+1] = y
a.buf[a.off+2] = z
a.off += 3
}
// Put4 appends four bytes to the end of the buffer.
func (a *AsmBuf) Put4(x, y, z, w byte) {
a.buf[a.off+0] = x
a.buf[a.off+1] = y
a.buf[a.off+2] = z
a.buf[a.off+3] = w
a.off += 4
}
// PutInt16 writes v into the buffer using little-endian encoding.
func (a *AsmBuf) PutInt16(v int16) {
a.buf[a.off+0] = byte(v)
a.buf[a.off+1] = byte(v >> 8)
a.off += 2
}
// PutInt32 writes v into the buffer using little-endian encoding.
func (a *AsmBuf) PutInt32(v int32) {
a.buf[a.off+0] = byte(v)
a.buf[a.off+1] = byte(v >> 8)
a.buf[a.off+2] = byte(v >> 16)
a.buf[a.off+3] = byte(v >> 24)
a.off += 4
}
// PutInt64 writes v into the buffer using little-endian encoding.
func (a *AsmBuf) PutInt64(v int64) {
a.buf[a.off+0] = byte(v)
a.buf[a.off+1] = byte(v >> 8)
a.buf[a.off+2] = byte(v >> 16)
a.buf[a.off+3] = byte(v >> 24)
a.buf[a.off+4] = byte(v >> 32)
a.buf[a.off+5] = byte(v >> 40)
a.buf[a.off+6] = byte(v >> 48)
a.buf[a.off+7] = byte(v >> 56)
a.off += 8
}
// Put copies b into the buffer.
func (a *AsmBuf) Put(b []byte) {
copy(a.buf[a.off:], b)
a.off += len(b)
}
// Insert inserts b at offset i.
func (a *AsmBuf) Insert(i int, b byte) {
a.off++
copy(a.buf[i+1:a.off], a.buf[i:a.off-1])
a.buf[i] = b
}
// Last returns the byte at the end of the buffer.
func (a *AsmBuf) Last() byte { return a.buf[a.off-1] }
// Len returns the length of the buffer.
func (a *AsmBuf) Len() int { return a.off }
// Bytes returns the contents of the buffer.
func (a *AsmBuf) Bytes() []byte { return a.buf[:a.off] }
// Reset empties the buffer.
func (a *AsmBuf) Reset() { a.off = 0 }
// At returns the byte at offset i.
func (a *AsmBuf) At(i int) byte { return a.buf[i] }
func (asmbuf *AsmBuf) asmidx(ctxt *obj.Link, scale int, index int, base int) {
var i int var i int
switch index { switch index {
...@@ -2651,16 +2746,16 @@ bas: ...@@ -2651,16 +2746,16 @@ bas:
i |= reg[base] i |= reg[base]
} }
ctxt.AsmBuf.Put1(byte(i)) asmbuf.Put1(byte(i))
return return
bad: bad:
ctxt.Diag("asmidx: bad address %d/%d/%d", scale, index, base) ctxt.Diag("asmidx: bad address %d/%d/%d", scale, index, base)
ctxt.AsmBuf.Put1(0) asmbuf.Put1(0)
return return
} }
func relput4(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) { func (asmbuf *AsmBuf) relput4(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
var rel obj.Reloc var rel obj.Reloc
v := vaddr(ctxt, p, a, &rel) v := vaddr(ctxt, p, a, &rel)
...@@ -2670,10 +2765,10 @@ func relput4(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) { ...@@ -2670,10 +2765,10 @@ func relput4(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
} }
r := obj.Addrel(ctxt.Cursym) r := obj.Addrel(ctxt.Cursym)
*r = rel *r = rel
r.Off = int32(p.Pc + int64(ctxt.AsmBuf.Len())) r.Off = int32(p.Pc + int64(asmbuf.Len()))
} }
ctxt.AsmBuf.PutInt32(int32(v)) asmbuf.PutInt32(int32(v))
} }
/* /*
...@@ -2744,7 +2839,7 @@ func vaddr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r *obj.Reloc) int64 { ...@@ -2744,7 +2839,7 @@ func vaddr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r *obj.Reloc) int64 {
return a.Offset return a.Offset
} }
func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int) { func (asmbuf *AsmBuf) asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int) {
var base int var base int
var rel obj.Reloc var rel obj.Reloc
...@@ -2779,7 +2874,7 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int) ...@@ -2779,7 +2874,7 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int)
if v != 0 { if v != 0 {
goto bad goto bad
} }
ctxt.AsmBuf.Put1(byte(3<<6 | reg[a.Reg]<<0 | r<<3)) asmbuf.Put1(byte(3<<6 | reg[a.Reg]<<0 | r<<3))
ctxt.Rexflag |= regrex[a.Reg]&(0x40|Rxb) | rex ctxt.Rexflag |= regrex[a.Reg]&(0x40|Rxb) | rex
return return
} }
...@@ -2813,26 +2908,26 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int) ...@@ -2813,26 +2908,26 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int)
ctxt.Rexflag |= regrex[int(a.Index)]&Rxx | regrex[base]&Rxb | rex ctxt.Rexflag |= regrex[int(a.Index)]&Rxx | regrex[base]&Rxb | rex
if base == REG_NONE { if base == REG_NONE {
ctxt.AsmBuf.Put1(byte(0<<6 | 4<<0 | r<<3)) asmbuf.Put1(byte(0<<6 | 4<<0 | r<<3))
asmidx(ctxt, int(a.Scale), int(a.Index), base) asmbuf.asmidx(ctxt, int(a.Scale), int(a.Index), base)
goto putrelv goto putrelv
} }
if v == 0 && rel.Siz == 0 && base != REG_BP && base != REG_R13 { if v == 0 && rel.Siz == 0 && base != REG_BP && base != REG_R13 {
ctxt.AsmBuf.Put1(byte(0<<6 | 4<<0 | r<<3)) asmbuf.Put1(byte(0<<6 | 4<<0 | r<<3))
asmidx(ctxt, int(a.Scale), int(a.Index), base) asmbuf.asmidx(ctxt, int(a.Scale), int(a.Index), base)
return return
} }
if v >= -128 && v < 128 && rel.Siz == 0 { if v >= -128 && v < 128 && rel.Siz == 0 {
ctxt.AsmBuf.Put1(byte(1<<6 | 4<<0 | r<<3)) asmbuf.Put1(byte(1<<6 | 4<<0 | r<<3))
asmidx(ctxt, int(a.Scale), int(a.Index), base) asmbuf.asmidx(ctxt, int(a.Scale), int(a.Index), base)
ctxt.AsmBuf.Put1(byte(v)) asmbuf.Put1(byte(v))
return return
} }
ctxt.AsmBuf.Put1(byte(2<<6 | 4<<0 | r<<3)) asmbuf.Put1(byte(2<<6 | 4<<0 | r<<3))
asmidx(ctxt, int(a.Scale), int(a.Index), base) asmbuf.asmidx(ctxt, int(a.Scale), int(a.Index), base)
goto putrelv goto putrelv
} }
...@@ -2868,12 +2963,12 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int) ...@@ -2868,12 +2963,12 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int)
if a.Name == obj.NAME_GOTREF && (a.Offset != 0 || a.Index != 0 || a.Scale != 0) { if a.Name == obj.NAME_GOTREF && (a.Offset != 0 || a.Index != 0 || a.Scale != 0) {
ctxt.Diag("%v has offset against gotref", p) ctxt.Diag("%v has offset against gotref", p)
} }
ctxt.AsmBuf.Put1(byte(0<<6 | 5<<0 | r<<3)) asmbuf.Put1(byte(0<<6 | 5<<0 | r<<3))
goto putrelv goto putrelv
} }
// temporary // temporary
ctxt.AsmBuf.Put2( asmbuf.Put2(
byte(0<<6|4<<0|r<<3), // sib present byte(0<<6|4<<0|r<<3), // sib present
0<<6|4<<3|5<<0, // DS:d32 0<<6|4<<3|5<<0, // DS:d32
) )
...@@ -2882,20 +2977,20 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int) ...@@ -2882,20 +2977,20 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int)
if base == REG_SP || base == REG_R12 { if base == REG_SP || base == REG_R12 {
if v == 0 { if v == 0 {
ctxt.AsmBuf.Put1(byte(0<<6 | reg[base]<<0 | r<<3)) asmbuf.Put1(byte(0<<6 | reg[base]<<0 | r<<3))
asmidx(ctxt, int(a.Scale), REG_NONE, base) asmbuf.asmidx(ctxt, int(a.Scale), REG_NONE, base)
return return
} }
if v >= -128 && v < 128 { if v >= -128 && v < 128 {
ctxt.AsmBuf.Put1(byte(1<<6 | reg[base]<<0 | r<<3)) asmbuf.Put1(byte(1<<6 | reg[base]<<0 | r<<3))
asmidx(ctxt, int(a.Scale), REG_NONE, base) asmbuf.asmidx(ctxt, int(a.Scale), REG_NONE, base)
ctxt.AsmBuf.Put1(byte(v)) asmbuf.Put1(byte(v))
return return
} }
ctxt.AsmBuf.Put1(byte(2<<6 | reg[base]<<0 | r<<3)) asmbuf.Put1(byte(2<<6 | reg[base]<<0 | r<<3))
asmidx(ctxt, int(a.Scale), REG_NONE, base) asmbuf.asmidx(ctxt, int(a.Scale), REG_NONE, base)
goto putrelv goto putrelv
} }
...@@ -2910,16 +3005,16 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int) ...@@ -2910,16 +3005,16 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int)
} }
if v == 0 && rel.Siz == 0 && base != REG_BP && base != REG_R13 { if v == 0 && rel.Siz == 0 && base != REG_BP && base != REG_R13 {
ctxt.AsmBuf.Put1(byte(0<<6 | reg[base]<<0 | r<<3)) asmbuf.Put1(byte(0<<6 | reg[base]<<0 | r<<3))
return return
} }
if v >= -128 && v < 128 && rel.Siz == 0 { if v >= -128 && v < 128 && rel.Siz == 0 {
ctxt.AsmBuf.Put2(byte(1<<6|reg[base]<<0|r<<3), byte(v)) asmbuf.Put2(byte(1<<6|reg[base]<<0|r<<3), byte(v))
return return
} }
ctxt.AsmBuf.Put1(byte(2<<6 | reg[base]<<0 | r<<3)) asmbuf.Put1(byte(2<<6 | reg[base]<<0 | r<<3))
goto putrelv goto putrelv
} }
...@@ -2934,10 +3029,10 @@ putrelv: ...@@ -2934,10 +3029,10 @@ putrelv:
r := obj.Addrel(ctxt.Cursym) r := obj.Addrel(ctxt.Cursym)
*r = rel *r = rel
r.Off = int32(ctxt.Curp.Pc + int64(ctxt.AsmBuf.Len())) r.Off = int32(ctxt.Curp.Pc + int64(asmbuf.Len()))
} }
ctxt.AsmBuf.PutInt32(v) asmbuf.PutInt32(v)
return return
bad: bad:
...@@ -2945,12 +3040,12 @@ bad: ...@@ -2945,12 +3040,12 @@ bad:
return return
} }
func asmand(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, ra *obj.Addr) { func (asmbuf *AsmBuf) asmand(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, ra *obj.Addr) {
asmandsz(ctxt, p, a, reg[ra.Reg], regrex[ra.Reg], 0) asmbuf.asmandsz(ctxt, p, a, reg[ra.Reg], regrex[ra.Reg], 0)
} }
func asmando(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, o int) { func (asmbuf *AsmBuf) asmando(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, o int) {
asmandsz(ctxt, p, a, o, 0, 0) asmbuf.asmandsz(ctxt, p, a, o, 0, 0)
} }
func bytereg(a *obj.Addr, t *uint8) { func bytereg(a *obj.Addr, t *uint8) {
...@@ -3153,14 +3248,14 @@ func subreg(p *obj.Prog, from int, to int) { ...@@ -3153,14 +3248,14 @@ func subreg(p *obj.Prog, from int, to int) {
} }
} }
func mediaop(ctxt *obj.Link, o *Optab, op int, osize int, z int) int { func (asmbuf *AsmBuf) mediaop(ctxt *obj.Link, o *Optab, op int, osize int, z int) int {
switch op { switch op {
case Pm, Pe, Pf2, Pf3: case Pm, Pe, Pf2, Pf3:
if osize != 1 { if osize != 1 {
if op != Pm { if op != Pm {
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
} }
ctxt.AsmBuf.Put1(Pm) asmbuf.Put1(Pm)
z++ z++
op = int(o.op[z]) op = int(o.op[z])
break break
...@@ -3168,12 +3263,12 @@ func mediaop(ctxt *obj.Link, o *Optab, op int, osize int, z int) int { ...@@ -3168,12 +3263,12 @@ func mediaop(ctxt *obj.Link, o *Optab, op int, osize int, z int) int {
fallthrough fallthrough
default: default:
if ctxt.AsmBuf.Len() == 0 || ctxt.AsmBuf.Last() != Pm { if asmbuf.Len() == 0 || asmbuf.Last() != Pm {
ctxt.AsmBuf.Put1(Pm) asmbuf.Put1(Pm)
} }
} }
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
return z return z
} }
...@@ -3194,7 +3289,7 @@ var bpduff2 = []byte{ ...@@ -3194,7 +3289,7 @@ var bpduff2 = []byte{
// and the opcode byte. // and the opcode byte.
// For details about vex prefix see: // For details about vex prefix see:
// https://en.wikipedia.org/wiki/VEX_prefix#Technical_description // https://en.wikipedia.org/wiki/VEX_prefix#Technical_description
func asmvex(ctxt *obj.Link, rm, v, r *obj.Addr, vex, opcode uint8) { func (asmbuf *AsmBuf) asmvex(ctxt *obj.Link, rm, v, r *obj.Addr, vex, opcode uint8) {
ctxt.Vexflag = 1 ctxt.Vexflag = 1
rexR := 0 rexR := 0
if r != nil { if r != nil {
...@@ -3215,18 +3310,18 @@ func asmvex(ctxt *obj.Link, rm, v, r *obj.Addr, vex, opcode uint8) { ...@@ -3215,18 +3310,18 @@ func asmvex(ctxt *obj.Link, rm, v, r *obj.Addr, vex, opcode uint8) {
vexV ^= 0xF vexV ^= 0xF
if vexM == 1 && (rexX|rexB) == 0 && vex&vexW1 == 0 { if vexM == 1 && (rexX|rexB) == 0 && vex&vexW1 == 0 {
// Can use 2-byte encoding. // Can use 2-byte encoding.
ctxt.AsmBuf.Put2(0xc5, byte(rexR<<5)^0x80|vexV<<3|vexWLP) asmbuf.Put2(0xc5, byte(rexR<<5)^0x80|vexV<<3|vexWLP)
} else { } else {
// Must use 3-byte encoding. // Must use 3-byte encoding.
ctxt.AsmBuf.Put3(0xc4, asmbuf.Put3(0xc4,
(byte(rexR|rexX|rexB)<<5)^0xE0|vexM, (byte(rexR|rexX|rexB)<<5)^0xE0|vexM,
vexV<<3|vexWLP, vexV<<3|vexWLP,
) )
} }
ctxt.AsmBuf.Put1(opcode) asmbuf.Put1(opcode)
} }
func doasm(ctxt *obj.Link, p *obj.Prog) { func (asmbuf *AsmBuf) doasm(ctxt *obj.Link, p *obj.Prog) {
ctxt.Curp = p // TODO ctxt.Curp = p // TODO
o := opindex[p.As&obj.AMask] o := opindex[p.As&obj.AMask]
...@@ -3238,11 +3333,11 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3238,11 +3333,11 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
pre := prefixof(ctxt, p, &p.From) pre := prefixof(ctxt, p, &p.From)
if pre != 0 { if pre != 0 {
ctxt.AsmBuf.Put1(byte(pre)) asmbuf.Put1(byte(pre))
} }
pre = prefixof(ctxt, p, &p.To) pre = prefixof(ctxt, p, &p.To)
if pre != 0 { if pre != 0 {
ctxt.AsmBuf.Put1(byte(pre)) asmbuf.Put1(byte(pre))
} }
// TODO(rsc): This special case is for SHRQ $3, AX:DX, // TODO(rsc): This special case is for SHRQ $3, AX:DX,
...@@ -3312,31 +3407,31 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3312,31 +3407,31 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
continue continue
} }
case Pq: /* 16 bit escape and opcode escape */ case Pq: /* 16 bit escape and opcode escape */
ctxt.AsmBuf.Put2(Pe, Pm) asmbuf.Put2(Pe, Pm)
case Pq3: /* 16 bit escape and opcode escape + REX.W */ case Pq3: /* 16 bit escape and opcode escape + REX.W */
ctxt.Rexflag |= Pw ctxt.Rexflag |= Pw
ctxt.AsmBuf.Put2(Pe, Pm) asmbuf.Put2(Pe, Pm)
case Pq4: /* 66 0F 38 */ case Pq4: /* 66 0F 38 */
ctxt.AsmBuf.Put3(0x66, 0x0F, 0x38) asmbuf.Put3(0x66, 0x0F, 0x38)
case Pf2, /* xmm opcode escape */ case Pf2, /* xmm opcode escape */
Pf3: Pf3:
ctxt.AsmBuf.Put2(o.prefix, Pm) asmbuf.Put2(o.prefix, Pm)
case Pef3: case Pef3:
ctxt.AsmBuf.Put3(Pe, Pf3, Pm) asmbuf.Put3(Pe, Pf3, Pm)
case Pfw: /* xmm opcode escape + REX.W */ case Pfw: /* xmm opcode escape + REX.W */
ctxt.Rexflag |= Pw ctxt.Rexflag |= Pw
ctxt.AsmBuf.Put2(Pf3, Pm) asmbuf.Put2(Pf3, Pm)
case Pm: /* opcode escape */ case Pm: /* opcode escape */
ctxt.AsmBuf.Put1(Pm) asmbuf.Put1(Pm)
case Pe: /* 16 bit escape */ case Pe: /* 16 bit escape */
ctxt.AsmBuf.Put1(Pe) asmbuf.Put1(Pe)
case Pw: /* 64-bit escape */ case Pw: /* 64-bit escape */
if p.Mode != 64 { if p.Mode != 64 {
...@@ -3396,7 +3491,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3396,7 +3491,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
op = int(o.op[z]) op = int(o.op[z])
// In vex case 0x0f is actually VEX_256_F2_0F_WIG // In vex case 0x0f is actually VEX_256_F2_0F_WIG
if op == 0x0f && o.prefix != Pvex { if op == 0x0f && o.prefix != Pvex {
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
z++ z++
op = int(o.op[z]) op = int(o.op[z])
} }
...@@ -3415,7 +3510,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3415,7 +3510,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
if op == 0 { if op == 0 {
break break
} }
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
} }
case Zlitm_r: case Zlitm_r:
...@@ -3424,35 +3519,35 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3424,35 +3519,35 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
if op == 0 { if op == 0 {
break break
} }
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
} }
asmand(ctxt, p, &p.From, &p.To) asmbuf.asmand(ctxt, p, &p.From, &p.To)
case Zmb_r: case Zmb_r:
bytereg(&p.From, &p.Ft) bytereg(&p.From, &p.Ft)
fallthrough fallthrough
case Zm_r: case Zm_r:
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
asmand(ctxt, p, &p.From, &p.To) asmbuf.asmand(ctxt, p, &p.From, &p.To)
case Zm2_r: case Zm2_r:
ctxt.AsmBuf.Put2(byte(op), o.op[z+1]) asmbuf.Put2(byte(op), o.op[z+1])
asmand(ctxt, p, &p.From, &p.To) asmbuf.asmand(ctxt, p, &p.From, &p.To)
case Zm_r_xm: case Zm_r_xm:
mediaop(ctxt, o, op, int(yt.zoffset), z) asmbuf.mediaop(ctxt, o, op, int(yt.zoffset), z)
asmand(ctxt, p, &p.From, &p.To) asmbuf.asmand(ctxt, p, &p.From, &p.To)
case Zm_r_xm_nr: case Zm_r_xm_nr:
ctxt.Rexflag = 0 ctxt.Rexflag = 0
mediaop(ctxt, o, op, int(yt.zoffset), z) asmbuf.mediaop(ctxt, o, op, int(yt.zoffset), z)
asmand(ctxt, p, &p.From, &p.To) asmbuf.asmand(ctxt, p, &p.From, &p.To)
case Zm_r_i_xm: case Zm_r_i_xm:
mediaop(ctxt, o, op, int(yt.zoffset), z) asmbuf.mediaop(ctxt, o, op, int(yt.zoffset), z)
asmand(ctxt, p, &p.From, p.From3) asmbuf.asmand(ctxt, p, &p.From, p.From3)
ctxt.AsmBuf.Put1(byte(p.To.Offset)) asmbuf.Put1(byte(p.To.Offset))
case Zibm_r, Zibr_m: case Zibm_r, Zibr_m:
for { for {
...@@ -3462,77 +3557,77 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3462,77 +3557,77 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
if op == 0 { if op == 0 {
break break
} }
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
} }
if yt.zcase == Zibr_m { if yt.zcase == Zibr_m {
asmand(ctxt, p, &p.To, p.From3) asmbuf.asmand(ctxt, p, &p.To, p.From3)
} else { } else {
asmand(ctxt, p, p.From3, &p.To) asmbuf.asmand(ctxt, p, p.From3, &p.To)
} }
ctxt.AsmBuf.Put1(byte(p.From.Offset)) asmbuf.Put1(byte(p.From.Offset))
case Zaut_r: case Zaut_r:
ctxt.AsmBuf.Put1(0x8d) // leal asmbuf.Put1(0x8d) // leal
if p.From.Type != obj.TYPE_ADDR { if p.From.Type != obj.TYPE_ADDR {
ctxt.Diag("asmins: Zaut sb type ADDR") ctxt.Diag("asmins: Zaut sb type ADDR")
} }
p.From.Type = obj.TYPE_MEM p.From.Type = obj.TYPE_MEM
asmand(ctxt, p, &p.From, &p.To) asmbuf.asmand(ctxt, p, &p.From, &p.To)
p.From.Type = obj.TYPE_ADDR p.From.Type = obj.TYPE_ADDR
case Zm_o: case Zm_o:
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
asmando(ctxt, p, &p.From, int(o.op[z+1])) asmbuf.asmando(ctxt, p, &p.From, int(o.op[z+1]))
case Zr_m: case Zr_m:
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
asmand(ctxt, p, &p.To, &p.From) asmbuf.asmand(ctxt, p, &p.To, &p.From)
case Zvex_rm_v_r: case Zvex_rm_v_r:
asmvex(ctxt, &p.From, p.From3, &p.To, o.op[z], o.op[z+1]) asmbuf.asmvex(ctxt, &p.From, p.From3, &p.To, o.op[z], o.op[z+1])
asmand(ctxt, p, &p.From, &p.To) asmbuf.asmand(ctxt, p, &p.From, &p.To)
case Zvex_i_r_v: case Zvex_i_r_v:
asmvex(ctxt, p.From3, &p.To, nil, o.op[z], o.op[z+1]) asmbuf.asmvex(ctxt, p.From3, &p.To, nil, o.op[z], o.op[z+1])
regnum := byte(0x7) regnum := byte(0x7)
if p.From3.Reg >= REG_X0 && p.From3.Reg <= REG_X15 { if p.From3.Reg >= REG_X0 && p.From3.Reg <= REG_X15 {
regnum &= byte(p.From3.Reg - REG_X0) regnum &= byte(p.From3.Reg - REG_X0)
} else { } else {
regnum &= byte(p.From3.Reg - REG_Y0) regnum &= byte(p.From3.Reg - REG_Y0)
} }
ctxt.AsmBuf.Put1(byte(o.op[z+2]) | regnum) asmbuf.Put1(byte(o.op[z+2]) | regnum)
ctxt.AsmBuf.Put1(byte(p.From.Offset)) asmbuf.Put1(byte(p.From.Offset))
case Zvex_i_rm_v_r: case Zvex_i_rm_v_r:
asmvex(ctxt, &p.From, p.From3, &p.To, o.op[z], o.op[z+1]) asmbuf.asmvex(ctxt, &p.From, p.From3, &p.To, o.op[z], o.op[z+1])
asmand(ctxt, p, &p.From, &p.To) asmbuf.asmand(ctxt, p, &p.From, &p.To)
ctxt.AsmBuf.Put1(byte(p.From3.Offset)) asmbuf.Put1(byte(p.From3.Offset))
case Zvex_i_rm_r: case Zvex_i_rm_r:
asmvex(ctxt, p.From3, nil, &p.To, o.op[z], o.op[z+1]) asmbuf.asmvex(ctxt, p.From3, nil, &p.To, o.op[z], o.op[z+1])
asmand(ctxt, p, p.From3, &p.To) asmbuf.asmand(ctxt, p, p.From3, &p.To)
ctxt.AsmBuf.Put1(byte(p.From.Offset)) asmbuf.Put1(byte(p.From.Offset))
case Zvex_v_rm_r: case Zvex_v_rm_r:
asmvex(ctxt, p.From3, &p.From, &p.To, o.op[z], o.op[z+1]) asmbuf.asmvex(ctxt, p.From3, &p.From, &p.To, o.op[z], o.op[z+1])
asmand(ctxt, p, p.From3, &p.To) asmbuf.asmand(ctxt, p, p.From3, &p.To)
case Zvex_r_v_rm: case Zvex_r_v_rm:
asmvex(ctxt, &p.To, p.From3, &p.From, o.op[z], o.op[z+1]) asmbuf.asmvex(ctxt, &p.To, p.From3, &p.From, o.op[z], o.op[z+1])
asmand(ctxt, p, &p.To, &p.From) asmbuf.asmand(ctxt, p, &p.To, &p.From)
case Zr_m_xm: case Zr_m_xm:
mediaop(ctxt, o, op, int(yt.zoffset), z) asmbuf.mediaop(ctxt, o, op, int(yt.zoffset), z)
asmand(ctxt, p, &p.To, &p.From) asmbuf.asmand(ctxt, p, &p.To, &p.From)
case Zr_m_xm_nr: case Zr_m_xm_nr:
ctxt.Rexflag = 0 ctxt.Rexflag = 0
mediaop(ctxt, o, op, int(yt.zoffset), z) asmbuf.mediaop(ctxt, o, op, int(yt.zoffset), z)
asmand(ctxt, p, &p.To, &p.From) asmbuf.asmand(ctxt, p, &p.To, &p.From)
case Zo_m: case Zo_m:
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
asmando(ctxt, p, &p.To, int(o.op[z+1])) asmbuf.asmando(ctxt, p, &p.To, int(o.op[z+1]))
case Zcallindreg: case Zcallindreg:
r = obj.Addrel(ctxt.Cursym) r = obj.Addrel(ctxt.Cursym)
...@@ -3542,23 +3637,23 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3542,23 +3637,23 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
fallthrough fallthrough
case Zo_m64: case Zo_m64:
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
asmandsz(ctxt, p, &p.To, int(o.op[z+1]), 0, 1) asmbuf.asmandsz(ctxt, p, &p.To, int(o.op[z+1]), 0, 1)
case Zm_ibo: case Zm_ibo:
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
asmando(ctxt, p, &p.From, int(o.op[z+1])) asmbuf.asmando(ctxt, p, &p.From, int(o.op[z+1]))
ctxt.AsmBuf.Put1(byte(vaddr(ctxt, p, &p.To, nil))) asmbuf.Put1(byte(vaddr(ctxt, p, &p.To, nil)))
case Zibo_m: case Zibo_m:
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
asmando(ctxt, p, &p.To, int(o.op[z+1])) asmbuf.asmando(ctxt, p, &p.To, int(o.op[z+1]))
ctxt.AsmBuf.Put1(byte(vaddr(ctxt, p, &p.From, nil))) asmbuf.Put1(byte(vaddr(ctxt, p, &p.From, nil)))
case Zibo_m_xm: case Zibo_m_xm:
z = mediaop(ctxt, o, op, int(yt.zoffset), z) z = asmbuf.mediaop(ctxt, o, op, int(yt.zoffset), z)
asmando(ctxt, p, &p.To, int(o.op[z+1])) asmbuf.asmando(ctxt, p, &p.To, int(o.op[z+1]))
ctxt.AsmBuf.Put1(byte(vaddr(ctxt, p, &p.From, nil))) asmbuf.Put1(byte(vaddr(ctxt, p, &p.From, nil)))
case Z_ib, Zib_: case Z_ib, Zib_:
if yt.zcase == Zib_ { if yt.zcase == Zib_ {
...@@ -3566,31 +3661,31 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3566,31 +3661,31 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
} else { } else {
a = &p.To a = &p.To
} }
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
if p.As == AXABORT { if p.As == AXABORT {
ctxt.AsmBuf.Put1(o.op[z+1]) asmbuf.Put1(o.op[z+1])
} }
ctxt.AsmBuf.Put1(byte(vaddr(ctxt, p, a, nil))) asmbuf.Put1(byte(vaddr(ctxt, p, a, nil)))
case Zib_rp: case Zib_rp:
ctxt.Rexflag |= regrex[p.To.Reg] & (Rxb | 0x40) ctxt.Rexflag |= regrex[p.To.Reg] & (Rxb | 0x40)
ctxt.AsmBuf.Put2(byte(op+reg[p.To.Reg]), byte(vaddr(ctxt, p, &p.From, nil))) asmbuf.Put2(byte(op+reg[p.To.Reg]), byte(vaddr(ctxt, p, &p.From, nil)))
case Zil_rp: case Zil_rp:
ctxt.Rexflag |= regrex[p.To.Reg] & Rxb ctxt.Rexflag |= regrex[p.To.Reg] & Rxb
ctxt.AsmBuf.Put1(byte(op + reg[p.To.Reg])) asmbuf.Put1(byte(op + reg[p.To.Reg]))
if o.prefix == Pe { if o.prefix == Pe {
v = vaddr(ctxt, p, &p.From, nil) v = vaddr(ctxt, p, &p.From, nil)
ctxt.AsmBuf.PutInt16(int16(v)) asmbuf.PutInt16(int16(v))
} else { } else {
relput4(ctxt, p, &p.From) asmbuf.relput4(ctxt, p, &p.From)
} }
case Zo_iw: case Zo_iw:
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
if p.From.Type != obj.TYPE_NONE { if p.From.Type != obj.TYPE_NONE {
v = vaddr(ctxt, p, &p.From, nil) v = vaddr(ctxt, p, &p.From, nil)
ctxt.AsmBuf.PutInt16(int16(v)) asmbuf.PutInt16(int16(v))
} }
case Ziq_rp: case Ziq_rp:
...@@ -3602,39 +3697,39 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3602,39 +3697,39 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
ctxt.Rexflag &^= (0x40 | Rxw) ctxt.Rexflag &^= (0x40 | Rxw)
ctxt.Rexflag |= regrex[p.To.Reg] & Rxb ctxt.Rexflag |= regrex[p.To.Reg] & Rxb
ctxt.AsmBuf.Put1(byte(0xb8 + reg[p.To.Reg])) asmbuf.Put1(byte(0xb8 + reg[p.To.Reg]))
if rel.Type != 0 { if rel.Type != 0 {
r = obj.Addrel(ctxt.Cursym) r = obj.Addrel(ctxt.Cursym)
*r = rel *r = rel
r.Off = int32(p.Pc + int64(ctxt.AsmBuf.Len())) r.Off = int32(p.Pc + int64(asmbuf.Len()))
} }
ctxt.AsmBuf.PutInt32(int32(v)) asmbuf.PutInt32(int32(v))
} else if l == -1 && uint64(v)&(uint64(1)<<31) != 0 { /* sign extend */ } else if l == -1 && uint64(v)&(uint64(1)<<31) != 0 { /* sign extend */
//p->mark |= 0100; //p->mark |= 0100;
//print("sign: %llux %v\n", v, p); //print("sign: %llux %v\n", v, p);
ctxt.AsmBuf.Put1(0xc7) asmbuf.Put1(0xc7)
asmando(ctxt, p, &p.To, 0) asmbuf.asmando(ctxt, p, &p.To, 0)
ctxt.AsmBuf.PutInt32(int32(v)) // need all 8 asmbuf.PutInt32(int32(v)) // need all 8
} else { } else {
//print("all: %llux %v\n", v, p); //print("all: %llux %v\n", v, p);
ctxt.Rexflag |= regrex[p.To.Reg] & Rxb ctxt.Rexflag |= regrex[p.To.Reg] & Rxb
ctxt.AsmBuf.Put1(byte(op + reg[p.To.Reg])) asmbuf.Put1(byte(op + reg[p.To.Reg]))
if rel.Type != 0 { if rel.Type != 0 {
r = obj.Addrel(ctxt.Cursym) r = obj.Addrel(ctxt.Cursym)
*r = rel *r = rel
r.Off = int32(p.Pc + int64(ctxt.AsmBuf.Len())) r.Off = int32(p.Pc + int64(asmbuf.Len()))
} }
ctxt.AsmBuf.PutInt64(v) asmbuf.PutInt64(v)
} }
case Zib_rr: case Zib_rr:
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
asmand(ctxt, p, &p.To, &p.To) asmbuf.asmand(ctxt, p, &p.To, &p.To)
ctxt.AsmBuf.Put1(byte(vaddr(ctxt, p, &p.From, nil))) asmbuf.Put1(byte(vaddr(ctxt, p, &p.From, nil)))
case Z_il, Zil_: case Z_il, Zil_:
if yt.zcase == Zil_ { if yt.zcase == Zil_ {
...@@ -3642,71 +3737,71 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3642,71 +3737,71 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
} else { } else {
a = &p.To a = &p.To
} }
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
if o.prefix == Pe { if o.prefix == Pe {
v = vaddr(ctxt, p, a, nil) v = vaddr(ctxt, p, a, nil)
ctxt.AsmBuf.PutInt16(int16(v)) asmbuf.PutInt16(int16(v))
} else { } else {
relput4(ctxt, p, a) asmbuf.relput4(ctxt, p, a)
} }
case Zm_ilo, Zilo_m: case Zm_ilo, Zilo_m:
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
if yt.zcase == Zilo_m { if yt.zcase == Zilo_m {
a = &p.From a = &p.From
asmando(ctxt, p, &p.To, int(o.op[z+1])) asmbuf.asmando(ctxt, p, &p.To, int(o.op[z+1]))
} else { } else {
a = &p.To a = &p.To
asmando(ctxt, p, &p.From, int(o.op[z+1])) asmbuf.asmando(ctxt, p, &p.From, int(o.op[z+1]))
} }
if o.prefix == Pe { if o.prefix == Pe {
v = vaddr(ctxt, p, a, nil) v = vaddr(ctxt, p, a, nil)
ctxt.AsmBuf.PutInt16(int16(v)) asmbuf.PutInt16(int16(v))
} else { } else {
relput4(ctxt, p, a) asmbuf.relput4(ctxt, p, a)
} }
case Zil_rr: case Zil_rr:
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
asmand(ctxt, p, &p.To, &p.To) asmbuf.asmand(ctxt, p, &p.To, &p.To)
if o.prefix == Pe { if o.prefix == Pe {
v = vaddr(ctxt, p, &p.From, nil) v = vaddr(ctxt, p, &p.From, nil)
ctxt.AsmBuf.PutInt16(int16(v)) asmbuf.PutInt16(int16(v))
} else { } else {
relput4(ctxt, p, &p.From) asmbuf.relput4(ctxt, p, &p.From)
} }
case Z_rp: case Z_rp:
ctxt.Rexflag |= regrex[p.To.Reg] & (Rxb | 0x40) ctxt.Rexflag |= regrex[p.To.Reg] & (Rxb | 0x40)
ctxt.AsmBuf.Put1(byte(op + reg[p.To.Reg])) asmbuf.Put1(byte(op + reg[p.To.Reg]))
case Zrp_: case Zrp_:
ctxt.Rexflag |= regrex[p.From.Reg] & (Rxb | 0x40) ctxt.Rexflag |= regrex[p.From.Reg] & (Rxb | 0x40)
ctxt.AsmBuf.Put1(byte(op + reg[p.From.Reg])) asmbuf.Put1(byte(op + reg[p.From.Reg]))
case Zclr: case Zclr:
ctxt.Rexflag &^= Pw ctxt.Rexflag &^= Pw
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
asmand(ctxt, p, &p.To, &p.To) asmbuf.asmand(ctxt, p, &p.To, &p.To)
case Zcallcon, Zjmpcon: case Zcallcon, Zjmpcon:
if yt.zcase == Zcallcon { if yt.zcase == Zcallcon {
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
} else { } else {
ctxt.AsmBuf.Put1(o.op[z+1]) asmbuf.Put1(o.op[z+1])
} }
r = obj.Addrel(ctxt.Cursym) r = obj.Addrel(ctxt.Cursym)
r.Off = int32(p.Pc + int64(ctxt.AsmBuf.Len())) r.Off = int32(p.Pc + int64(asmbuf.Len()))
r.Type = obj.R_PCREL r.Type = obj.R_PCREL
r.Siz = 4 r.Siz = 4
r.Add = p.To.Offset r.Add = p.To.Offset
ctxt.AsmBuf.PutInt32(0) asmbuf.PutInt32(0)
case Zcallind: case Zcallind:
ctxt.AsmBuf.Put2(byte(op), o.op[z+1]) asmbuf.Put2(byte(op), o.op[z+1])
r = obj.Addrel(ctxt.Cursym) r = obj.Addrel(ctxt.Cursym)
r.Off = int32(p.Pc + int64(ctxt.AsmBuf.Len())) r.Off = int32(p.Pc + int64(asmbuf.Len()))
if p.Mode == 64 { if p.Mode == 64 {
r.Type = obj.R_PCREL r.Type = obj.R_PCREL
} else { } else {
...@@ -3715,7 +3810,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3715,7 +3810,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
r.Siz = 4 r.Siz = 4
r.Add = p.To.Offset r.Add = p.To.Offset
r.Sym = p.To.Sym r.Sym = p.To.Sym
ctxt.AsmBuf.PutInt32(0) asmbuf.PutInt32(0)
case Zcall, Zcallduff: case Zcall, Zcallduff:
if p.To.Sym == nil { if p.To.Sym == nil {
...@@ -3735,27 +3830,27 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3735,27 +3830,27 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
// whole point of obj.Framepointer_enabled). // whole point of obj.Framepointer_enabled).
// MOVQ BP, -16(SP) // MOVQ BP, -16(SP)
// LEAQ -16(SP), BP // LEAQ -16(SP), BP
ctxt.AsmBuf.Put(bpduff1) asmbuf.Put(bpduff1)
} }
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
r = obj.Addrel(ctxt.Cursym) r = obj.Addrel(ctxt.Cursym)
r.Off = int32(p.Pc + int64(ctxt.AsmBuf.Len())) r.Off = int32(p.Pc + int64(asmbuf.Len()))
r.Sym = p.To.Sym r.Sym = p.To.Sym
r.Add = p.To.Offset r.Add = p.To.Offset
r.Type = obj.R_CALL r.Type = obj.R_CALL
r.Siz = 4 r.Siz = 4
ctxt.AsmBuf.PutInt32(0) asmbuf.PutInt32(0)
if ctxt.Framepointer_enabled && yt.zcase == Zcallduff && p.Mode == 64 { if ctxt.Framepointer_enabled && yt.zcase == Zcallduff && p.Mode == 64 {
// Pop BP pushed above. // Pop BP pushed above.
// MOVQ 0(BP), BP // MOVQ 0(BP), BP
ctxt.AsmBuf.Put(bpduff2) asmbuf.Put(bpduff2)
} }
// TODO: jump across functions needs reloc // TODO: jump across functions needs reloc
case Zbr, Zjmp, Zloop: case Zbr, Zjmp, Zloop:
if p.As == AXBEGIN { if p.As == AXBEGIN {
ctxt.AsmBuf.Put1(byte(op)) asmbuf.Put1(byte(op))
} }
if p.To.Sym != nil { if p.To.Sym != nil {
if yt.zcase != Zjmp { if yt.zcase != Zjmp {
...@@ -3763,13 +3858,13 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3763,13 +3858,13 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
log.Fatalf("bad code") log.Fatalf("bad code")
} }
ctxt.AsmBuf.Put1(o.op[z+1]) asmbuf.Put1(o.op[z+1])
r = obj.Addrel(ctxt.Cursym) r = obj.Addrel(ctxt.Cursym)
r.Off = int32(p.Pc + int64(ctxt.AsmBuf.Len())) r.Off = int32(p.Pc + int64(asmbuf.Len()))
r.Sym = p.To.Sym r.Sym = p.To.Sym
r.Type = obj.R_PCREL r.Type = obj.R_PCREL
r.Siz = 4 r.Siz = 4
ctxt.AsmBuf.PutInt32(0) asmbuf.PutInt32(0)
break break
} }
...@@ -3788,9 +3883,9 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3788,9 +3883,9 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
v = q.Pc - (p.Pc + 2) v = q.Pc - (p.Pc + 2)
if v >= -128 && p.As != AXBEGIN { if v >= -128 && p.As != AXBEGIN {
if p.As == AJCXZL { if p.As == AJCXZL {
ctxt.AsmBuf.Put1(0x67) asmbuf.Put1(0x67)
} }
ctxt.AsmBuf.Put2(byte(op), byte(v)) asmbuf.Put2(byte(op), byte(v))
} else if yt.zcase == Zloop { } else if yt.zcase == Zloop {
ctxt.Diag("loop too far: %v", p) ctxt.Diag("loop too far: %v", p)
} else { } else {
...@@ -3799,12 +3894,12 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3799,12 +3894,12 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
v-- v--
} }
if yt.zcase == Zbr { if yt.zcase == Zbr {
ctxt.AsmBuf.Put1(0x0f) asmbuf.Put1(0x0f)
v-- v--
} }
ctxt.AsmBuf.Put1(o.op[z+1]) asmbuf.Put1(o.op[z+1])
ctxt.AsmBuf.PutInt32(int32(v)) asmbuf.PutInt32(int32(v))
} }
break break
...@@ -3816,17 +3911,17 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3816,17 +3911,17 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
q.Rel = p q.Rel = p
if p.Back&2 != 0 && p.As != AXBEGIN { // short if p.Back&2 != 0 && p.As != AXBEGIN { // short
if p.As == AJCXZL { if p.As == AJCXZL {
ctxt.AsmBuf.Put1(0x67) asmbuf.Put1(0x67)
} }
ctxt.AsmBuf.Put2(byte(op), 0) asmbuf.Put2(byte(op), 0)
} else if yt.zcase == Zloop { } else if yt.zcase == Zloop {
ctxt.Diag("loop too far: %v", p) ctxt.Diag("loop too far: %v", p)
} else { } else {
if yt.zcase == Zbr { if yt.zcase == Zbr {
ctxt.AsmBuf.Put1(0x0f) asmbuf.Put1(0x0f)
} }
ctxt.AsmBuf.Put1(o.op[z+1]) asmbuf.Put1(o.op[z+1])
ctxt.AsmBuf.PutInt32(0) asmbuf.PutInt32(0)
} }
break break
...@@ -3856,16 +3951,16 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3856,16 +3951,16 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
rel.Siz = uint8(op) rel.Siz = uint8(op)
r = obj.Addrel(ctxt.Cursym) r = obj.Addrel(ctxt.Cursym)
*r = rel *r = rel
r.Off = int32(p.Pc + int64(ctxt.AsmBuf.Len())) r.Off = int32(p.Pc + int64(asmbuf.Len()))
} }
ctxt.AsmBuf.Put1(byte(v)) asmbuf.Put1(byte(v))
if op > 1 { if op > 1 {
ctxt.AsmBuf.Put1(byte(v >> 8)) asmbuf.Put1(byte(v >> 8))
if op > 2 { if op > 2 {
ctxt.AsmBuf.PutInt16(int16(v >> 16)) asmbuf.PutInt16(int16(v >> 16))
if op > 4 { if op > 4 {
ctxt.AsmBuf.PutInt32(int32(v >> 32)) asmbuf.PutInt32(int32(v >> 32))
} }
} }
} }
...@@ -3887,52 +3982,52 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3887,52 +3982,52 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
case 0: /* lit */ case 0: /* lit */
for z = 0; t[z] != E; z++ { for z = 0; t[z] != E; z++ {
ctxt.AsmBuf.Put1(t[z]) asmbuf.Put1(t[z])
} }
case 1: /* r,m */ case 1: /* r,m */
ctxt.AsmBuf.Put1(t[0]) asmbuf.Put1(t[0])
asmando(ctxt, p, &p.To, int(t[1])) asmbuf.asmando(ctxt, p, &p.To, int(t[1]))
case 2: /* m,r */ case 2: /* m,r */
ctxt.AsmBuf.Put1(t[0]) asmbuf.Put1(t[0])
asmando(ctxt, p, &p.From, int(t[1])) asmbuf.asmando(ctxt, p, &p.From, int(t[1]))
case 3: /* r,m - 2op */ case 3: /* r,m - 2op */
ctxt.AsmBuf.Put2(t[0], t[1]) asmbuf.Put2(t[0], t[1])
asmando(ctxt, p, &p.To, int(t[2])) asmbuf.asmando(ctxt, p, &p.To, int(t[2]))
ctxt.Rexflag |= regrex[p.From.Reg] & (Rxr | 0x40) ctxt.Rexflag |= regrex[p.From.Reg] & (Rxr | 0x40)
case 4: /* m,r - 2op */ case 4: /* m,r - 2op */
ctxt.AsmBuf.Put2(t[0], t[1]) asmbuf.Put2(t[0], t[1])
asmando(ctxt, p, &p.From, int(t[2])) asmbuf.asmando(ctxt, p, &p.From, int(t[2]))
ctxt.Rexflag |= regrex[p.To.Reg] & (Rxr | 0x40) ctxt.Rexflag |= regrex[p.To.Reg] & (Rxr | 0x40)
case 5: /* load full pointer, trash heap */ case 5: /* load full pointer, trash heap */
if t[0] != 0 { if t[0] != 0 {
ctxt.AsmBuf.Put1(t[0]) asmbuf.Put1(t[0])
} }
switch p.To.Index { switch p.To.Index {
default: default:
goto bad goto bad
case REG_DS: case REG_DS:
ctxt.AsmBuf.Put1(0xc5) asmbuf.Put1(0xc5)
case REG_SS: case REG_SS:
ctxt.AsmBuf.Put2(0x0f, 0xb2) asmbuf.Put2(0x0f, 0xb2)
case REG_ES: case REG_ES:
ctxt.AsmBuf.Put1(0xc4) asmbuf.Put1(0xc4)
case REG_FS: case REG_FS:
ctxt.AsmBuf.Put2(0x0f, 0xb4) asmbuf.Put2(0x0f, 0xb4)
case REG_GS: case REG_GS:
ctxt.AsmBuf.Put2(0x0f, 0xb5) asmbuf.Put2(0x0f, 0xb5)
} }
asmand(ctxt, p, &p.From, &p.To) asmbuf.asmand(ctxt, p, &p.From, &p.To)
case 6: /* double shift */ case 6: /* double shift */
if t[0] == Pw { if t[0] == Pw {
...@@ -3942,7 +4037,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3942,7 +4037,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
ctxt.Rexflag |= Pw ctxt.Rexflag |= Pw
t = t[1:] t = t[1:]
} else if t[0] == Pe { } else if t[0] == Pe {
ctxt.AsmBuf.Put1(Pe) asmbuf.Put1(Pe)
t = t[1:] t = t[1:]
} }
...@@ -3951,9 +4046,9 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3951,9 +4046,9 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
goto bad goto bad
case obj.TYPE_CONST: case obj.TYPE_CONST:
ctxt.AsmBuf.Put2(0x0f, t[0]) asmbuf.Put2(0x0f, t[0])
asmandsz(ctxt, p, &p.To, reg[p.From3.Reg], regrex[p.From3.Reg], 0) asmbuf.asmandsz(ctxt, p, &p.To, reg[p.From3.Reg], regrex[p.From3.Reg], 0)
ctxt.AsmBuf.Put1(byte(p.From.Offset)) asmbuf.Put1(byte(p.From.Offset))
case obj.TYPE_REG: case obj.TYPE_REG:
switch p.From.Reg { switch p.From.Reg {
...@@ -3961,8 +4056,8 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3961,8 +4056,8 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
goto bad goto bad
case REG_CL, REG_CX: case REG_CL, REG_CX:
ctxt.AsmBuf.Put2(0x0f, t[1]) asmbuf.Put2(0x0f, t[1])
asmandsz(ctxt, p, &p.To, reg[p.From3.Reg], regrex[p.From3.Reg], 0) asmbuf.asmandsz(ctxt, p, &p.To, reg[p.From3.Reg], regrex[p.From3.Reg], 0)
} }
} }
...@@ -3999,21 +4094,21 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -3999,21 +4094,21 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
// is g, which we can't check here, but will when we assemble the second // is g, which we can't check here, but will when we assemble the second
// instruction. // instruction.
dst := p.To.Reg dst := p.To.Reg
ctxt.AsmBuf.Put1(0xe8) asmbuf.Put1(0xe8)
r = obj.Addrel(ctxt.Cursym) r = obj.Addrel(ctxt.Cursym)
r.Off = int32(p.Pc + int64(ctxt.AsmBuf.Len())) r.Off = int32(p.Pc + int64(asmbuf.Len()))
r.Type = obj.R_CALL r.Type = obj.R_CALL
r.Siz = 4 r.Siz = 4
r.Sym = obj.Linklookup(ctxt, "__x86.get_pc_thunk."+strings.ToLower(Rconv(int(dst))), 0) r.Sym = obj.Linklookup(ctxt, "__x86.get_pc_thunk."+strings.ToLower(Rconv(int(dst))), 0)
ctxt.AsmBuf.PutInt32(0) asmbuf.PutInt32(0)
ctxt.AsmBuf.Put2(0x8B, byte(2<<6|reg[dst]|(reg[dst]<<3))) asmbuf.Put2(0x8B, byte(2<<6|reg[dst]|(reg[dst]<<3)))
r = obj.Addrel(ctxt.Cursym) r = obj.Addrel(ctxt.Cursym)
r.Off = int32(p.Pc + int64(ctxt.AsmBuf.Len())) r.Off = int32(p.Pc + int64(asmbuf.Len()))
r.Type = obj.R_TLS_IE r.Type = obj.R_TLS_IE
r.Siz = 4 r.Siz = 4
r.Add = 2 r.Add = 2
ctxt.AsmBuf.PutInt32(0) asmbuf.PutInt32(0)
} else { } else {
// ELF TLS base is 0(GS). // ELF TLS base is 0(GS).
pp.From = p.From pp.From = p.From
...@@ -4023,9 +4118,9 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -4023,9 +4118,9 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
pp.From.Offset = 0 pp.From.Offset = 0
pp.From.Index = REG_NONE pp.From.Index = REG_NONE
pp.From.Scale = 0 pp.From.Scale = 0
ctxt.AsmBuf.Put2(0x65, // GS asmbuf.Put2(0x65, // GS
0x8B) 0x8B)
asmand(ctxt, p, &pp.From, &p.To) asmbuf.asmand(ctxt, p, &pp.From, &p.To)
} }
case obj.Hplan9: case obj.Hplan9:
if ctxt.Plan9privates == nil { if ctxt.Plan9privates == nil {
...@@ -4037,8 +4132,8 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -4037,8 +4132,8 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
pp.From.Sym = ctxt.Plan9privates pp.From.Sym = ctxt.Plan9privates
pp.From.Offset = 0 pp.From.Offset = 0
pp.From.Index = REG_NONE pp.From.Index = REG_NONE
ctxt.AsmBuf.Put1(0x8B) asmbuf.Put1(0x8B)
asmand(ctxt, p, &pp.From, &p.To) asmbuf.asmand(ctxt, p, &pp.From, &p.To)
case obj.Hwindows, obj.Hwindowsgui: case obj.Hwindows, obj.Hwindowsgui:
// Windows TLS base is always 0x14(FS). // Windows TLS base is always 0x14(FS).
...@@ -4049,9 +4144,9 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -4049,9 +4144,9 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
pp.From.Offset = 0x14 pp.From.Offset = 0x14
pp.From.Index = REG_NONE pp.From.Index = REG_NONE
pp.From.Scale = 0 pp.From.Scale = 0
ctxt.AsmBuf.Put2(0x64, // FS asmbuf.Put2(0x64, // FS
0x8B) 0x8B)
asmand(ctxt, p, &pp.From, &p.To) asmbuf.asmand(ctxt, p, &pp.From, &p.To)
} }
break break
} }
...@@ -4075,13 +4170,13 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -4075,13 +4170,13 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
// instruction. // instruction.
ctxt.Rexflag = Pw | (regrex[p.To.Reg] & Rxr) ctxt.Rexflag = Pw | (regrex[p.To.Reg] & Rxr)
ctxt.AsmBuf.Put2(0x8B, byte(0x05|(reg[p.To.Reg]<<3))) asmbuf.Put2(0x8B, byte(0x05|(reg[p.To.Reg]<<3)))
r = obj.Addrel(ctxt.Cursym) r = obj.Addrel(ctxt.Cursym)
r.Off = int32(p.Pc + int64(ctxt.AsmBuf.Len())) r.Off = int32(p.Pc + int64(asmbuf.Len()))
r.Type = obj.R_TLS_IE r.Type = obj.R_TLS_IE
r.Siz = 4 r.Siz = 4
r.Add = -4 r.Add = -4
ctxt.AsmBuf.PutInt32(0) asmbuf.PutInt32(0)
case obj.Hplan9: case obj.Hplan9:
if ctxt.Plan9privates == nil { if ctxt.Plan9privates == nil {
...@@ -4094,8 +4189,8 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -4094,8 +4189,8 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
pp.From.Offset = 0 pp.From.Offset = 0
pp.From.Index = REG_NONE pp.From.Index = REG_NONE
ctxt.Rexflag |= Pw ctxt.Rexflag |= Pw
ctxt.AsmBuf.Put1(0x8B) asmbuf.Put1(0x8B)
asmand(ctxt, p, &pp.From, &p.To) asmbuf.asmand(ctxt, p, &pp.From, &p.To)
case obj.Hsolaris: // TODO(rsc): Delete Hsolaris from list. Should not use this code. See progedit in obj6.c. case obj.Hsolaris: // TODO(rsc): Delete Hsolaris from list. Should not use this code. See progedit in obj6.c.
// TLS base is 0(FS). // TLS base is 0(FS).
...@@ -4108,9 +4203,9 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -4108,9 +4203,9 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
pp.From.Index = REG_NONE pp.From.Index = REG_NONE
pp.From.Scale = 0 pp.From.Scale = 0
ctxt.Rexflag |= Pw ctxt.Rexflag |= Pw
ctxt.AsmBuf.Put2(0x64, // FS asmbuf.Put2(0x64, // FS
0x8B) 0x8B)
asmand(ctxt, p, &pp.From, &p.To) asmbuf.asmand(ctxt, p, &pp.From, &p.To)
case obj.Hwindows, obj.Hwindowsgui: case obj.Hwindows, obj.Hwindowsgui:
// Windows TLS base is always 0x28(GS). // Windows TLS base is always 0x28(GS).
...@@ -4123,9 +4218,9 @@ func doasm(ctxt *obj.Link, p *obj.Prog) { ...@@ -4123,9 +4218,9 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
pp.From.Index = REG_NONE pp.From.Index = REG_NONE
pp.From.Scale = 0 pp.From.Scale = 0
ctxt.Rexflag |= Pw ctxt.Rexflag |= Pw
ctxt.AsmBuf.Put2(0x65, // GS asmbuf.Put2(0x65, // GS
0x8B) 0x8B)
asmand(ctxt, p, &pp.From, &p.To) asmbuf.asmand(ctxt, p, &pp.From, &p.To)
} }
} }
return return
...@@ -4155,17 +4250,17 @@ bad: ...@@ -4155,17 +4250,17 @@ bad:
if p.Mode == 32 { if p.Mode == 32 {
breg := byteswapreg(ctxt, &p.To) breg := byteswapreg(ctxt, &p.To)
if breg != REG_AX { if breg != REG_AX {
ctxt.AsmBuf.Put1(0x87) // xchg lhs,bx asmbuf.Put1(0x87) // xchg lhs,bx
asmando(ctxt, p, &p.From, reg[breg]) asmbuf.asmando(ctxt, p, &p.From, reg[breg])
subreg(&pp, z, breg) subreg(&pp, z, breg)
doasm(ctxt, &pp) asmbuf.doasm(ctxt, &pp)
ctxt.AsmBuf.Put1(0x87) // xchg lhs,bx asmbuf.Put1(0x87) // xchg lhs,bx
asmando(ctxt, p, &p.From, reg[breg]) asmbuf.asmando(ctxt, p, &p.From, reg[breg])
} else { } else {
ctxt.AsmBuf.Put1(byte(0x90 + reg[z])) // xchg lsh,ax asmbuf.Put1(byte(0x90 + reg[z])) // xchg lsh,ax
subreg(&pp, z, REG_AX) subreg(&pp, z, REG_AX)
doasm(ctxt, &pp) asmbuf.doasm(ctxt, &pp)
ctxt.AsmBuf.Put1(byte(0x90 + reg[z])) // xchg lsh,ax asmbuf.Put1(byte(0x90 + reg[z])) // xchg lsh,ax
} }
return return
} }
...@@ -4173,17 +4268,17 @@ bad: ...@@ -4173,17 +4268,17 @@ bad:
if isax(&p.To) || p.To.Type == obj.TYPE_NONE { if isax(&p.To) || p.To.Type == obj.TYPE_NONE {
// We certainly don't want to exchange // We certainly don't want to exchange
// with AX if the op is MUL or DIV. // with AX if the op is MUL or DIV.
ctxt.AsmBuf.Put1(0x87) // xchg lhs,bx asmbuf.Put1(0x87) // xchg lhs,bx
asmando(ctxt, p, &p.From, reg[REG_BX]) asmbuf.asmando(ctxt, p, &p.From, reg[REG_BX])
subreg(&pp, z, REG_BX) subreg(&pp, z, REG_BX)
doasm(ctxt, &pp) asmbuf.doasm(ctxt, &pp)
ctxt.AsmBuf.Put1(0x87) // xchg lhs,bx asmbuf.Put1(0x87) // xchg lhs,bx
asmando(ctxt, p, &p.From, reg[REG_BX]) asmbuf.asmando(ctxt, p, &p.From, reg[REG_BX])
} else { } else {
ctxt.AsmBuf.Put1(byte(0x90 + reg[z])) // xchg lsh,ax asmbuf.Put1(byte(0x90 + reg[z])) // xchg lsh,ax
subreg(&pp, z, REG_AX) subreg(&pp, z, REG_AX)
doasm(ctxt, &pp) asmbuf.doasm(ctxt, &pp)
ctxt.AsmBuf.Put1(byte(0x90 + reg[z])) // xchg lsh,ax asmbuf.Put1(byte(0x90 + reg[z])) // xchg lsh,ax
} }
return return
} }
...@@ -4195,33 +4290,33 @@ bad: ...@@ -4195,33 +4290,33 @@ bad:
if p.Mode == 32 { if p.Mode == 32 {
breg := byteswapreg(ctxt, &p.From) breg := byteswapreg(ctxt, &p.From)
if breg != REG_AX { if breg != REG_AX {
ctxt.AsmBuf.Put1(0x87) //xchg rhs,bx asmbuf.Put1(0x87) //xchg rhs,bx
asmando(ctxt, p, &p.To, reg[breg]) asmbuf.asmando(ctxt, p, &p.To, reg[breg])
subreg(&pp, z, breg) subreg(&pp, z, breg)
doasm(ctxt, &pp) asmbuf.doasm(ctxt, &pp)
ctxt.AsmBuf.Put1(0x87) // xchg rhs,bx asmbuf.Put1(0x87) // xchg rhs,bx
asmando(ctxt, p, &p.To, reg[breg]) asmbuf.asmando(ctxt, p, &p.To, reg[breg])
} else { } else {
ctxt.AsmBuf.Put1(byte(0x90 + reg[z])) // xchg rsh,ax asmbuf.Put1(byte(0x90 + reg[z])) // xchg rsh,ax
subreg(&pp, z, REG_AX) subreg(&pp, z, REG_AX)
doasm(ctxt, &pp) asmbuf.doasm(ctxt, &pp)
ctxt.AsmBuf.Put1(byte(0x90 + reg[z])) // xchg rsh,ax asmbuf.Put1(byte(0x90 + reg[z])) // xchg rsh,ax
} }
return return
} }
if isax(&p.From) { if isax(&p.From) {
ctxt.AsmBuf.Put1(0x87) // xchg rhs,bx asmbuf.Put1(0x87) // xchg rhs,bx
asmando(ctxt, p, &p.To, reg[REG_BX]) asmbuf.asmando(ctxt, p, &p.To, reg[REG_BX])
subreg(&pp, z, REG_BX) subreg(&pp, z, REG_BX)
doasm(ctxt, &pp) asmbuf.doasm(ctxt, &pp)
ctxt.AsmBuf.Put1(0x87) // xchg rhs,bx asmbuf.Put1(0x87) // xchg rhs,bx
asmando(ctxt, p, &p.To, reg[REG_BX]) asmbuf.asmando(ctxt, p, &p.To, reg[REG_BX])
} else { } else {
ctxt.AsmBuf.Put1(byte(0x90 + reg[z])) // xchg rsh,ax asmbuf.Put1(byte(0x90 + reg[z])) // xchg rsh,ax
subreg(&pp, z, REG_AX) subreg(&pp, z, REG_AX)
doasm(ctxt, &pp) asmbuf.doasm(ctxt, &pp)
ctxt.AsmBuf.Put1(byte(0x90 + reg[z])) // xchg rsh,ax asmbuf.Put1(byte(0x90 + reg[z])) // xchg rsh,ax
} }
return return
} }
...@@ -4356,31 +4451,31 @@ var naclstos = []uint8{ ...@@ -4356,31 +4451,31 @@ var naclstos = []uint8{
0x3f, // LEAQ (R15)(DI*1), DI 0x3f, // LEAQ (R15)(DI*1), DI
} }
func nacltrunc(ctxt *obj.Link, reg int) { func (asmbuf *AsmBuf) nacltrunc(ctxt *obj.Link, reg int) {
if reg >= REG_R8 { if reg >= REG_R8 {
ctxt.AsmBuf.Put1(0x45) asmbuf.Put1(0x45)
} }
reg = (reg - REG_AX) & 7 reg = (reg - REG_AX) & 7
ctxt.AsmBuf.Put2(0x89, byte(3<<6|reg<<3|reg)) asmbuf.Put2(0x89, byte(3<<6|reg<<3|reg))
} }
func asmins(ctxt *obj.Link, p *obj.Prog) { func (asmbuf *AsmBuf) asmins(ctxt *obj.Link, p *obj.Prog) {
ctxt.AsmBuf.Reset() asmbuf.Reset()
if ctxt.Headtype == obj.Hnacl && p.Mode == 32 { if ctxt.Headtype == obj.Hnacl && p.Mode == 32 {
switch p.As { switch p.As {
case obj.ARET: case obj.ARET:
ctxt.AsmBuf.Put(naclret8) asmbuf.Put(naclret8)
return return
case obj.ACALL, case obj.ACALL,
obj.AJMP: obj.AJMP:
if p.To.Type == obj.TYPE_REG && REG_AX <= p.To.Reg && p.To.Reg <= REG_DI { if p.To.Type == obj.TYPE_REG && REG_AX <= p.To.Reg && p.To.Reg <= REG_DI {
ctxt.AsmBuf.Put3(0x83, byte(0xe0|(p.To.Reg-REG_AX)), 0xe0) asmbuf.Put3(0x83, byte(0xe0|(p.To.Reg-REG_AX)), 0xe0)
} }
case AINT: case AINT:
ctxt.AsmBuf.Put1(0xf4) asmbuf.Put1(0xf4)
return return
} }
} }
...@@ -4403,36 +4498,36 @@ func asmins(ctxt *obj.Link, p *obj.Prog) { ...@@ -4403,36 +4498,36 @@ func asmins(ctxt *obj.Link, p *obj.Prog) {
if p.As != ALEAQ && p.As != ALEAL { if p.As != ALEAQ && p.As != ALEAL {
if p.From.Index != REG_NONE && p.From.Scale > 0 { if p.From.Index != REG_NONE && p.From.Scale > 0 {
nacltrunc(ctxt, int(p.From.Index)) asmbuf.nacltrunc(ctxt, int(p.From.Index))
} }
if p.To.Index != REG_NONE && p.To.Scale > 0 { if p.To.Index != REG_NONE && p.To.Scale > 0 {
nacltrunc(ctxt, int(p.To.Index)) asmbuf.nacltrunc(ctxt, int(p.To.Index))
} }
} }
switch p.As { switch p.As {
case obj.ARET: case obj.ARET:
ctxt.AsmBuf.Put(naclret) asmbuf.Put(naclret)
return return
case obj.ACALL, case obj.ACALL,
obj.AJMP: obj.AJMP:
if p.To.Type == obj.TYPE_REG && REG_AX <= p.To.Reg && p.To.Reg <= REG_DI { if p.To.Type == obj.TYPE_REG && REG_AX <= p.To.Reg && p.To.Reg <= REG_DI {
// ANDL $~31, reg // ANDL $~31, reg
ctxt.AsmBuf.Put3(0x83, byte(0xe0|(p.To.Reg-REG_AX)), 0xe0) asmbuf.Put3(0x83, byte(0xe0|(p.To.Reg-REG_AX)), 0xe0)
// ADDQ R15, reg // ADDQ R15, reg
ctxt.AsmBuf.Put3(0x4c, 0x01, byte(0xf8|(p.To.Reg-REG_AX))) asmbuf.Put3(0x4c, 0x01, byte(0xf8|(p.To.Reg-REG_AX)))
} }
if p.To.Type == obj.TYPE_REG && REG_R8 <= p.To.Reg && p.To.Reg <= REG_R15 { if p.To.Type == obj.TYPE_REG && REG_R8 <= p.To.Reg && p.To.Reg <= REG_R15 {
// ANDL $~31, reg // ANDL $~31, reg
ctxt.AsmBuf.Put4(0x41, 0x83, byte(0xe0|(p.To.Reg-REG_R8)), 0xe0) asmbuf.Put4(0x41, 0x83, byte(0xe0|(p.To.Reg-REG_R8)), 0xe0)
// ADDQ R15, reg // ADDQ R15, reg
ctxt.AsmBuf.Put3(0x4d, 0x01, byte(0xf8|(p.To.Reg-REG_R8))) asmbuf.Put3(0x4d, 0x01, byte(0xf8|(p.To.Reg-REG_R8)))
} }
case AINT: case AINT:
ctxt.AsmBuf.Put1(0xf4) asmbuf.Put1(0xf4)
return return
case ASCASB, case ASCASB,
...@@ -4443,32 +4538,32 @@ func asmins(ctxt *obj.Link, p *obj.Prog) { ...@@ -4443,32 +4538,32 @@ func asmins(ctxt *obj.Link, p *obj.Prog) {
ASTOSW, ASTOSW,
ASTOSL, ASTOSL,
ASTOSQ: ASTOSQ:
ctxt.AsmBuf.Put(naclstos) asmbuf.Put(naclstos)
case AMOVSB, AMOVSW, AMOVSL, AMOVSQ: case AMOVSB, AMOVSW, AMOVSL, AMOVSQ:
ctxt.AsmBuf.Put(naclmovs) asmbuf.Put(naclmovs)
} }
if ctxt.Rep != 0 { if ctxt.Rep != 0 {
ctxt.AsmBuf.Put1(0xf3) asmbuf.Put1(0xf3)
ctxt.Rep = 0 ctxt.Rep = 0
} }
if ctxt.Repn != 0 { if ctxt.Repn != 0 {
ctxt.AsmBuf.Put1(0xf2) asmbuf.Put1(0xf2)
ctxt.Repn = 0 ctxt.Repn = 0
} }
if ctxt.Lock != 0 { if ctxt.Lock != 0 {
ctxt.AsmBuf.Put1(0xf0) asmbuf.Put1(0xf0)
ctxt.Lock = 0 ctxt.Lock = 0
} }
} }
ctxt.Rexflag = 0 ctxt.Rexflag = 0
ctxt.Vexflag = 0 ctxt.Vexflag = 0
mark := ctxt.AsmBuf.Len() mark := asmbuf.Len()
doasm(ctxt, p) asmbuf.doasm(ctxt, p)
if ctxt.Rexflag != 0 && ctxt.Vexflag == 0 { if ctxt.Rexflag != 0 && ctxt.Vexflag == 0 {
/* /*
* as befits the whole approach of the architecture, * as befits the whole approach of the architecture,
...@@ -4480,18 +4575,18 @@ func asmins(ctxt *obj.Link, p *obj.Prog) { ...@@ -4480,18 +4575,18 @@ func asmins(ctxt *obj.Link, p *obj.Prog) {
if p.Mode != 64 { if p.Mode != 64 {
ctxt.Diag("asmins: illegal in mode %d: %v (%d %d)", p.Mode, p, p.Ft, p.Tt) ctxt.Diag("asmins: illegal in mode %d: %v (%d %d)", p.Mode, p, p.Ft, p.Tt)
} }
n := ctxt.AsmBuf.Len() n := asmbuf.Len()
var np int var np int
for np = mark; np < n; np++ { for np = mark; np < n; np++ {
c := ctxt.AsmBuf.Peek(np) c := asmbuf.At(np)
if c != 0xf2 && c != 0xf3 && (c < 0x64 || c > 0x67) && c != 0x2e && c != 0x3e && c != 0x26 { if c != 0xf2 && c != 0xf3 && (c < 0x64 || c > 0x67) && c != 0x2e && c != 0x3e && c != 0x26 {
break break
} }
} }
ctxt.AsmBuf.Insert(np, byte(0x40|ctxt.Rexflag)) asmbuf.Insert(np, byte(0x40|ctxt.Rexflag))
} }
n := ctxt.AsmBuf.Len() n := asmbuf.Len()
for i := len(ctxt.Cursym.R) - 1; i >= 0; i-- { for i := len(ctxt.Cursym.R) - 1; i >= 0; i-- {
r := &ctxt.Cursym.R[i] r := &ctxt.Cursym.R[i]
if int64(r.Off) < p.Pc { if int64(r.Off) < p.Pc {
...@@ -4528,9 +4623,9 @@ func asmins(ctxt *obj.Link, p *obj.Prog) { ...@@ -4528,9 +4623,9 @@ func asmins(ctxt *obj.Link, p *obj.Prog) {
if p.Mode == 64 && ctxt.Headtype == obj.Hnacl && p.As != ACMPL && p.As != ACMPQ && p.To.Type == obj.TYPE_REG { if p.Mode == 64 && ctxt.Headtype == obj.Hnacl && p.As != ACMPL && p.As != ACMPQ && p.To.Type == obj.TYPE_REG {
switch p.To.Reg { switch p.To.Reg {
case REG_SP: case REG_SP:
ctxt.AsmBuf.Put(naclspfix) asmbuf.Put(naclspfix)
case REG_BP: case REG_BP:
ctxt.AsmBuf.Put(naclbpfix) asmbuf.Put(naclbpfix)
} }
} }
} }
...@@ -38,7 +38,6 @@ sync/cond_test.go: assignment copies lock value to c2: sync.Cond contains sync.n ...@@ -38,7 +38,6 @@ sync/cond_test.go: assignment copies lock value to c2: sync.Cond contains sync.n
// Except for the runtime/pprof case, the API is not exported. // Except for the runtime/pprof case, the API is not exported.
cmd/internal/bio/buf.go: method Seek(offset int64, whence int) int64 should have signature Seek(int64, int) (int64, error) cmd/internal/bio/buf.go: method Seek(offset int64, whence int) int64 should have signature Seek(int64, int) (int64, error)
cmd/internal/bio/buf.go: method Seek(offset int64, whence int) int64 should have signature Seek(int64, int) (int64, error) cmd/internal/bio/buf.go: method Seek(offset int64, whence int) int64 should have signature Seek(int64, int) (int64, error)
cmd/internal/obj/link.go: method Peek(i int) byte should have signature Peek(int) ([]byte, error)
fmt/print.go: method WriteByte(c byte) should have signature WriteByte(byte) error fmt/print.go: method WriteByte(c byte) should have signature WriteByte(byte) error
runtime/pprof/pprof.go: method WriteTo(w io.Writer, debug int) error should have signature WriteTo(io.Writer) (int64, error) runtime/pprof/pprof.go: method WriteTo(w io.Writer, debug int) error should have signature WriteTo(io.Writer) (int64, error)
......
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