diff --git a/src/arch/x86_64/encode.rs b/src/arch/x86_64/encode.rs index ccf2678..456abf2 100644 --- a/src/arch/x86_64/encode.rs +++ b/src/arch/x86_64/encode.rs @@ -25,9 +25,7 @@ impl Code { } let width = dst.width(); self.prefix16(width); - if src.requires_rex() || dst.requires_rex() { - self.bytes.push(rex(width, src, 0, dst)); - } + self.rex(width, src, 0, dst); self.bytes.push(0x88 | width.not8()); self.bytes.push(modrm_regs(src, dst)); } @@ -46,9 +44,7 @@ impl Code { if src_width <= Width::B32 { dst = dst.lower64(); } - if dst.requires_rex() { - self.bytes.push(rex(dst, 0, 0, dst)); - } + self.rex(dst, 0, 0, dst); self.bytes.push(0xb0 | (dst.not8() << 3) | dst.base()); self.imm(src, dst.width()); } @@ -62,9 +58,7 @@ impl Code { } self.prefix32(&src)?; self.prefix16(dst); - if dst.requires_rex() | src.reg.gt8() { - self.bytes.push(rex(dst, dst, 0, src)); - } + self.rex(dst, dst, 0, src); self.bytes.push(0x8a | dst.not8()); self.modrm_regdisp(dst, src); } @@ -79,9 +73,7 @@ impl Code { } self.prefix32(&dst)?; self.prefix16(src); - if src.requires_rex() | dst.reg.gt8() { - self.bytes.push(rex(src, src, 0, dst)); - } + self.rex(src, src, 0, dst); self.bytes.push(0x88 | src.not8()); self.modrm_regdisp(src, dst); } @@ -100,9 +92,7 @@ impl Code { } self.prefix32(&dst)?; self.prefix16(encode_width); - if dst.reg.gt8() || dst.width == Width::B64 { - self.bytes.push(rex(dst, 0, 0, dst)); - } + self.rex(dst, 0, 0, dst); self.bytes.push(0xc6 | encode_width.not8()); self.modrm_regdisp(None, dst); self.imm(src, encode_width); @@ -202,6 +192,12 @@ impl Code { Ok(()) } + fn rex(&mut self, w: impl RexW, r: impl RexBit, x: u8, b: impl RexBit) { + if w.rexw() || r.rex() || x.rex() || b.rex() | r.req() | b.req() { + self.bytes.push(rex(w, r, x, b)); + } + } + fn modrm_regdisp(&mut self, reg: impl Into>, mem: Mem) { const I8_MIN: i32 = i8::MIN as i32; const I8_MAX: i32 = i8::MAX as i32; diff --git a/src/arch/x86_64/util.rs b/src/arch/x86_64/util.rs index 5796def..ed6fa87 100644 --- a/src/arch/x86_64/util.rs +++ b/src/arch/x86_64/util.rs @@ -25,52 +25,58 @@ fn bit(val: bool, pos: u8) -> u8 { (val as u8) << pos } -pub trait RexBit { - fn rex(self) -> bool; +pub trait RexBit: Sized { + fn rex(&self) -> bool; + fn req(&self) -> bool { + false + } } impl RexBit for u8 { - fn rex(self) -> bool { - self != 0 + fn rex(&self) -> bool { + *self != 0 } } impl RexBit for Reg { - fn rex(self) -> bool { + fn rex(&self) -> bool { self.gt8() } + fn req(&self) -> bool { + self.gt4() && (self.width() == Width::B8) && !self.high() + } } impl RexBit for Mem { - fn rex(self) -> bool { + fn rex(&self) -> bool { self.reg.rex() } } pub trait RexW { - fn rexw(self) -> bool; + fn rexw(&self) -> bool; } impl RexW for Width { - fn rexw(self) -> bool { - self == Width::B64 + fn rexw(&self) -> bool { + *self == Width::B64 } } impl RexW for Reg { - fn rexw(self) -> bool { + fn rexw(&self) -> bool { self.width().rexw() } } impl RexW for u8 { - fn rexw(self) -> bool { - self == 1 + fn rexw(&self) -> bool { + *self == 1 } } impl RexW for Mem { - fn rexw(self) -> bool { + fn rexw(&self) -> bool { self.width.rexw() } }