add more adds

This commit is contained in:
2026-06-17 01:34:25 -04:00
parent 4fe4b50c8b
commit 85eacd783d
7 changed files with 168 additions and 48 deletions
+68 -46
View File
@@ -19,11 +19,8 @@ impl Code {
if dst.width() != src.width() {
return Err("src and dst are not same width".into());
}
if dst.incompatible(&src) {
return Err("incompatible registers due to rex".into());
}
self.prefix16(dst);
self.rex(dst, src, 0, dst);
self.rex(dst, src, 0, dst)?;
self.bytes.push(0x88 | dst.not8());
self.modrm(src, dst);
}
@@ -42,7 +39,7 @@ impl Code {
if src_width <= Width::B32 {
dst = dst.lower64();
}
self.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());
}
@@ -51,12 +48,9 @@ impl Code {
if src.width != dst.width() {
return Err("register & memory sizes don't match".into());
}
if dst.high() && src.reg.gt8() {
return Err("registers incompatible (REX)".into());
}
self.prefix32(src)?;
self.prefix16(dst);
self.rex(dst, dst, 0, src);
self.rex(dst, dst, 0, src)?;
self.bytes.push(0x8a | dst.not8());
self.modrm(dst, src);
}
@@ -66,12 +60,9 @@ impl Code {
if src.width() != dst.width {
return Err("register & memory sizes don't match".into());
}
if src.high() && dst.reg.gt8() {
return Err("registers incompatible (REX)".into());
}
self.prefix32(dst)?;
self.prefix16(src);
self.rex(dst, src, 0, dst);
self.rex(dst, src, 0, dst)?;
self.bytes.push(0x88 | src.not8());
self.modrm(src, dst);
}
@@ -90,7 +81,7 @@ impl Code {
}
self.prefix32(dst)?;
self.prefix16(encode_width);
self.rex(dst, 0, 0, dst);
self.rex(dst, 0, 0, dst)?;
self.bytes.push(0xc6 | encode_width.not8());
self.modrm(0, dst);
self.imm(src, encode_width);
@@ -142,10 +133,11 @@ impl Code {
Ok(())
}
pub fn lea(&mut self, dst: Reg, sym: Symbol) {
self.rex(1, dst, 0, 0);
pub fn lea(&mut self, dst: Reg, sym: Symbol) -> ERes {
self.rex(1, dst, 0, 0)?;
self.bytes.push(0x8d);
self.modrm(dst, sym);
Ok(())
}
pub fn int(&mut self, code: u8) {
@@ -170,42 +162,68 @@ impl Code {
self.bytes.push(0xc3);
}
fn add_sub(&mut self, dst: impl RegMem, src: impl Into<Imm>, ext: u8) -> ERes {
let mut src = src.into();
let mut imm_width = src.width_signed()?;
let dst_width = dst.width().min(Width::B32);
if imm_width > dst_width {
imm_width = src.width_unsigned()?;
if dst.width() == Width::B64 || imm_width > dst_width {
return Err("immediate overflow".into());
fn add_sub(&mut self, dst: impl RegMem, src: impl Into<RegMemImm>, ext: u8) -> ERes {
match src.into() {
RegMemImm::Reg(src) => {
if src.width() != dst.width() {
return Err("incompatible widths".into());
}
self.prefix32(dst)?;
self.prefix16(src);
self.rex(dst, src, 0, dst)?;
self.bytes.push(src.not8());
self.modrm(src, dst);
}
src = src.reinterpret(dst_width);
imm_width = src.width_signed()?;
}
let code = if dst.width() == Width::B8 {
0x80
} else if imm_width == Width::B8 {
0x83
} else {
imm_width = dst_width;
0x81
};
RegMemImm::Imm(mut src) => {
let mut imm_width = src.width_signed()?;
let dst_width = dst.width().min(Width::B32);
self.prefix32(dst)?;
self.prefix16(dst_width);
self.rex(dst, 0, 0, dst);
self.bytes.push(code);
self.modrm(ext, dst);
self.imm(src, imm_width);
if imm_width > dst_width {
imm_width = src.width_unsigned()?;
if dst.width() == Width::B64 || imm_width > dst_width {
return Err("immediate overflow".into());
}
src = src.reinterpret(dst_width);
imm_width = src.width_signed()?;
}
let code = if dst.width() == Width::B8 {
0x80
} else if imm_width == Width::B8 {
0x83
} else {
imm_width = dst_width;
0x81
};
self.prefix32(dst)?;
self.prefix16(dst_width);
self.rex(dst, 0, 0, dst)?;
self.bytes.push(code);
self.modrm(ext, dst);
self.imm(src, imm_width);
}
RegMemImm::Mem(src) => {
let RegMemKind::Reg(dst) = dst.kind() else {
return Err("cannot add memory to memory".into());
};
if src.width() != dst.width() {
return Err("incompatible widths".into());
}
self.prefix32(src)?;
self.prefix16(dst);
self.rex(dst, dst, 0, src)?;
self.bytes.push(0x2 | dst.not8());
self.modrm(dst, src);
}
}
Ok(())
}
pub fn add(&mut self, dst: impl RegMem, src: impl Into<Imm>) -> ERes {
pub fn add(&mut self, dst: impl RegMem, src: impl Into<RegMemImm>) -> ERes {
self.add_sub(dst, src, 0)
}
pub fn sub(&mut self, dst: impl RegMem, src: impl Into<Imm>) -> ERes {
pub fn sub(&mut self, dst: impl RegMem, src: impl Into<RegMemImm>) -> ERes {
self.add_sub(dst, src, 5)
}
@@ -227,10 +245,14 @@ 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() {
fn rex(&mut self, w: impl RexW, r: impl RexBit, x: u8, b: impl RexBit) -> ERes {
if r.req() && b.req_no() || r.req_no() && b.req() {
return Err("registers incompatible (REX)".into());
}
if w.rexw() || r.rex() || x.rex() || b.rex() || r.req() || b.req() {
self.bytes.push(rex(w, r, x, b));
}
Ok(())
}
fn modrm(&mut self, reg: impl ModRMReg, rm: impl ModRMRM) {