return Yxxx
}
-// AsmBuf is a simple buffer to assemble variable-length x86 instructions into.
+// AsmBuf is a simple buffer to assemble variable-length x86 instructions into
+// and hold assembly state.
type AsmBuf struct {
- buf [100]byte
- off int
+ buf [100]byte
+ off int
+ rexflag int
+ vexflag int
+ rep int
+ repn int
+ lock int
}
// Put1 appends one byte to the end of the buffer.
switch {
case int64(int32(a.Offset)) == a.Offset:
// Offset fits in sign-extended 32 bits.
- case int64(uint32(a.Offset)) == a.Offset && ctxt.Rexflag&Rxw == 0:
+ case int64(uint32(a.Offset)) == a.Offset && asmbuf.rexflag&Rxw == 0:
// Offset fits in zero-extended 32 bits in a 32-bit instruction.
// This is allowed for assembly that wants to use 32-bit hex
// constants, e.g. LEAL 0x99999999(AX), AX.
goto bad
}
asmbuf.Put1(byte(3<<6 | reg[a.Reg]<<0 | r<<3))
- ctxt.Rexflag |= regrex[a.Reg]&(0x40|Rxb) | rex
+ asmbuf.rexflag |= regrex[a.Reg]&(0x40|Rxb) | rex
return
}
base = REG_SP
}
- ctxt.Rexflag |= regrex[int(a.Index)]&Rxx | regrex[base]&Rxb | rex
+ asmbuf.rexflag |= regrex[int(a.Index)]&Rxx | regrex[base]&Rxb | rex
if base == REG_NONE {
asmbuf.Put1(byte(0<<6 | 4<<0 | r<<3))
asmbuf.asmidx(ctxt, int(a.Scale), int(a.Index), base)
v = int32(vaddr(ctxt, p, a, &rel))
}
- ctxt.Rexflag |= regrex[base]&Rxb | rex
+ asmbuf.rexflag |= regrex[base]&Rxb | rex
if base == REG_NONE || (REG_CS <= base && base <= REG_GS) || base == REG_TLS {
if (a.Sym == nil || !isextern(a.Sym)) && base == REG_NONE && (a.Name == obj.NAME_STATIC || a.Name == obj.NAME_EXTERN || a.Name == obj.NAME_GOTREF) || p.Mode != 64 {
if a.Name == obj.NAME_GOTREF && (a.Offset != 0 || a.Index != 0 || a.Scale != 0) {
// For details about vex prefix see:
// https://en.wikipedia.org/wiki/VEX_prefix#Technical_description
func (asmbuf *AsmBuf) asmvex(ctxt *obj.Link, rm, v, r *obj.Addr, vex, opcode uint8) {
- ctxt.Vexflag = 1
+ asmbuf.vexflag = 1
rexR := 0
if r != nil {
rexR = regrex[r.Reg] & Rxr
asmbuf.Put2(Pe, Pm)
case Pq3: /* 16 bit escape and opcode escape + REX.W */
- ctxt.Rexflag |= Pw
+ asmbuf.rexflag |= Pw
asmbuf.Put2(Pe, Pm)
case Pq4: /* 66 0F 38 */
asmbuf.Put3(Pe, Pf3, Pm)
case Pfw: /* xmm opcode escape + REX.W */
- ctxt.Rexflag |= Pw
+ asmbuf.rexflag |= Pw
asmbuf.Put2(Pf3, Pm)
case Pm: /* opcode escape */
if p.Mode != 64 {
ctxt.Diag("asmins: illegal 64: %v", p)
}
- ctxt.Rexflag |= Pw
+ asmbuf.rexflag |= Pw
case Pw8: /* 64-bit escape if z >= 8 */
if z >= 8 {
if p.Mode != 64 {
ctxt.Diag("asmins: illegal 64: %v", p)
}
- ctxt.Rexflag |= Pw
+ asmbuf.rexflag |= Pw
}
case Pb: /* botch */
asmbuf.asmand(ctxt, cursym, p, &p.From, &p.To)
case Zm_r_xm_nr:
- ctxt.Rexflag = 0
+ asmbuf.rexflag = 0
asmbuf.mediaop(ctxt, o, op, int(yt.zoffset), z)
asmbuf.asmand(ctxt, cursym, p, &p.From, &p.To)
asmbuf.asmand(ctxt, cursym, p, &p.To, &p.From)
case Zr_m_xm_nr:
- ctxt.Rexflag = 0
+ asmbuf.rexflag = 0
asmbuf.mediaop(ctxt, o, op, int(yt.zoffset), z)
asmbuf.asmand(ctxt, cursym, p, &p.To, &p.From)
asmbuf.Put1(byte(vaddr(ctxt, p, a, nil)))
case Zib_rp:
- ctxt.Rexflag |= regrex[p.To.Reg] & (Rxb | 0x40)
+ asmbuf.rexflag |= regrex[p.To.Reg] & (Rxb | 0x40)
asmbuf.Put2(byte(op+reg[p.To.Reg]), byte(vaddr(ctxt, p, &p.From, nil)))
case Zil_rp:
- ctxt.Rexflag |= regrex[p.To.Reg] & Rxb
+ asmbuf.rexflag |= regrex[p.To.Reg] & Rxb
asmbuf.Put1(byte(op + reg[p.To.Reg]))
if o.prefix == Pe {
v = vaddr(ctxt, p, &p.From, nil)
if l == 0 && rel.Siz != 8 {
//p->mark |= 0100;
//print("zero: %llux %v\n", v, p);
- ctxt.Rexflag &^= (0x40 | Rxw)
+ asmbuf.rexflag &^= (0x40 | Rxw)
- ctxt.Rexflag |= regrex[p.To.Reg] & Rxb
+ asmbuf.rexflag |= regrex[p.To.Reg] & Rxb
asmbuf.Put1(byte(0xb8 + reg[p.To.Reg]))
if rel.Type != 0 {
r = obj.Addrel(cursym)
asmbuf.PutInt32(int32(v)) // need all 8
} else {
//print("all: %llux %v\n", v, p);
- ctxt.Rexflag |= regrex[p.To.Reg] & Rxb
+ asmbuf.rexflag |= regrex[p.To.Reg] & Rxb
asmbuf.Put1(byte(op + reg[p.To.Reg]))
if rel.Type != 0 {
r = obj.Addrel(cursym)
}
case Z_rp:
- ctxt.Rexflag |= regrex[p.To.Reg] & (Rxb | 0x40)
+ asmbuf.rexflag |= regrex[p.To.Reg] & (Rxb | 0x40)
asmbuf.Put1(byte(op + reg[p.To.Reg]))
case Zrp_:
- ctxt.Rexflag |= regrex[p.From.Reg] & (Rxb | 0x40)
+ asmbuf.rexflag |= regrex[p.From.Reg] & (Rxb | 0x40)
asmbuf.Put1(byte(op + reg[p.From.Reg]))
case Zclr:
- ctxt.Rexflag &^= Pw
+ asmbuf.rexflag &^= Pw
asmbuf.Put1(byte(op))
asmbuf.asmand(ctxt, cursym, p, &p.To, &p.To)
case 3: /* r,m - 2op */
asmbuf.Put2(t[0], t[1])
asmbuf.asmando(ctxt, cursym, p, &p.To, int(t[2]))
- ctxt.Rexflag |= regrex[p.From.Reg] & (Rxr | 0x40)
+ asmbuf.rexflag |= regrex[p.From.Reg] & (Rxr | 0x40)
case 4: /* m,r - 2op */
asmbuf.Put2(t[0], t[1])
asmbuf.asmando(ctxt, cursym, p, &p.From, int(t[2]))
- ctxt.Rexflag |= regrex[p.To.Reg] & (Rxr | 0x40)
+ asmbuf.rexflag |= regrex[p.To.Reg] & (Rxr | 0x40)
case 5: /* load full pointer, trash heap */
if t[0] != 0 {
if p.Mode != 64 {
ctxt.Diag("asmins: illegal 64: %v", p)
}
- ctxt.Rexflag |= Pw
+ asmbuf.rexflag |= Pw
t = t[1:]
} else if t[0] == Pe {
asmbuf.Put1(Pe)
// and a R_TLS_IE reloc. This all assumes the only tls variable we access
// is g, which we can't check here, but will when we assemble the second
// instruction.
- ctxt.Rexflag = Pw | (regrex[p.To.Reg] & Rxr)
+ asmbuf.rexflag = Pw | (regrex[p.To.Reg] & Rxr)
asmbuf.Put2(0x8B, byte(0x05|(reg[p.To.Reg]<<3)))
r = obj.Addrel(cursym)
pp.From.Sym = ctxt.Plan9privates
pp.From.Offset = 0
pp.From.Index = REG_NONE
- ctxt.Rexflag |= Pw
+ asmbuf.rexflag |= Pw
asmbuf.Put1(0x8B)
asmbuf.asmand(ctxt, cursym, p, &pp.From, &p.To)
pp.From.Offset = 0
pp.From.Index = REG_NONE
pp.From.Scale = 0
- ctxt.Rexflag |= Pw
+ asmbuf.rexflag |= Pw
asmbuf.Put2(0x64, // FS
0x8B)
asmbuf.asmand(ctxt, cursym, p, &pp.From, &p.To)
pp.From.Offset = 0x28
pp.From.Index = REG_NONE
pp.From.Scale = 0
- ctxt.Rexflag |= Pw
+ asmbuf.rexflag |= Pw
asmbuf.Put2(0x65, // GS
0x8B)
asmbuf.asmand(ctxt, cursym, p, &pp.From, &p.To)
if ctxt.Headtype == obj.Hnacl && p.Mode == 64 {
if p.As == AREP {
- ctxt.Rep++
+ asmbuf.rep++
return
}
if p.As == AREPN {
- ctxt.Repn++
+ asmbuf.repn++
return
}
if p.As == ALOCK {
- ctxt.Lock++
+ asmbuf.lock++
return
}
asmbuf.Put(naclmovs)
}
- if ctxt.Rep != 0 {
+ if asmbuf.rep != 0 {
asmbuf.Put1(0xf3)
- ctxt.Rep = 0
+ asmbuf.rep = 0
}
- if ctxt.Repn != 0 {
+ if asmbuf.repn != 0 {
asmbuf.Put1(0xf2)
- ctxt.Repn = 0
+ asmbuf.repn = 0
}
- if ctxt.Lock != 0 {
+ if asmbuf.lock != 0 {
asmbuf.Put1(0xf0)
- ctxt.Lock = 0
+ asmbuf.lock = 0
}
}
- ctxt.Rexflag = 0
- ctxt.Vexflag = 0
+ asmbuf.rexflag = 0
+ asmbuf.vexflag = 0
mark := asmbuf.Len()
asmbuf.doasm(ctxt, cursym, p)
- if ctxt.Rexflag != 0 && ctxt.Vexflag == 0 {
+ if asmbuf.rexflag != 0 && asmbuf.vexflag == 0 {
/*
* as befits the whole approach of the architecture,
* the rex prefix must appear before the first opcode byte
break
}
}
- asmbuf.Insert(np, byte(0x40|ctxt.Rexflag))
+ asmbuf.Insert(np, byte(0x40|asmbuf.rexflag))
}
n := asmbuf.Len()
if int64(r.Off) < p.Pc {
break
}
- if ctxt.Rexflag != 0 {
+ if asmbuf.rexflag != 0 {
r.Off++
}
if r.Type == obj.R_PCREL {