refactor
This commit is contained in:
+33
-28
@@ -23,10 +23,9 @@ impl Code {
|
||||
if dst.incompatible(&src) {
|
||||
return Err("incompatible registers due to rex".into());
|
||||
}
|
||||
let width = dst.width();
|
||||
self.prefix16(width);
|
||||
self.rex(width, src, 0, dst);
|
||||
self.bytes.push(0x88 | width.not8());
|
||||
self.prefix16(dst);
|
||||
self.rex(dst, src, 0, dst);
|
||||
self.bytes.push(0x88 | dst.not8());
|
||||
self.modrm(src, dst);
|
||||
}
|
||||
RegImmMem::Imm(src) => {
|
||||
@@ -56,7 +55,7 @@ impl Code {
|
||||
if dst.high() && src.reg.gt8() {
|
||||
return Err("registers incompatible (REX)".into());
|
||||
}
|
||||
self.prefix32(&src)?;
|
||||
self.prefix32(src)?;
|
||||
self.prefix16(dst);
|
||||
self.rex(dst, dst, 0, src);
|
||||
self.bytes.push(0x8a | dst.not8());
|
||||
@@ -71,7 +70,7 @@ impl Code {
|
||||
if src.high() && dst.reg.gt8() {
|
||||
return Err("registers incompatible (REX)".into());
|
||||
}
|
||||
self.prefix32(&dst)?;
|
||||
self.prefix32(dst)?;
|
||||
self.prefix16(src);
|
||||
self.rex(dst, src, 0, dst);
|
||||
self.bytes.push(0x88 | src.not8());
|
||||
@@ -90,7 +89,7 @@ impl Code {
|
||||
if src_width > dst.width {
|
||||
return Err("source cannot fit in destination".into());
|
||||
}
|
||||
self.prefix32(&dst)?;
|
||||
self.prefix32(dst)?;
|
||||
self.prefix16(encode_width);
|
||||
self.rex(dst, 0, 0, dst);
|
||||
self.bytes.push(0xc6 | encode_width.not8());
|
||||
@@ -172,39 +171,42 @@ impl Code {
|
||||
self.bytes.push(0xc3);
|
||||
}
|
||||
|
||||
fn add_sub(&mut self, dst: Reg, src: impl Into<Imm>, ext: u8) -> ERes {
|
||||
fn add_sub(&mut self, dst: impl RegMem_, src: impl Into<Imm>, ext: u8) -> ERes {
|
||||
let mut src = src.into();
|
||||
let mut width = src.width_signed()?;
|
||||
let mut imm_width = src.width_signed()?;
|
||||
let dst_width = dst.width().min(Width::B32);
|
||||
|
||||
self.prefix16(dst_width);
|
||||
self.rex(dst, 0, 0, dst);
|
||||
|
||||
if width > dst_width {
|
||||
width = src.width_unsigned()?;
|
||||
if dst.width() == Width::B64 || width > dst_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);
|
||||
width = src.width_signed()?;
|
||||
imm_width = src.width_signed()?;
|
||||
}
|
||||
|
||||
if dst.width() == Width::B8 {
|
||||
self.bytes.push(0x80);
|
||||
} else if width == Width::B8 {
|
||||
self.bytes.push(0x83);
|
||||
let code = if dst.width() == Width::B8 {
|
||||
0x80
|
||||
} else if imm_width == Width::B8 {
|
||||
0x83
|
||||
} else {
|
||||
self.bytes.push(0x81);
|
||||
width = dst_width;
|
||||
}
|
||||
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, width);
|
||||
self.imm(src, imm_width);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add(&mut self, dst: Reg, src: impl Into<Imm>) -> ERes {
|
||||
self.add_sub(dst, src, 0)
|
||||
pub fn add(&mut self, dst: impl Into<RegMem>, src: impl Into<Imm>) -> ERes {
|
||||
match dst.into() {
|
||||
RegMem::Reg(dst) => self.add_sub(dst, src, 0),
|
||||
RegMem::Mem(dst) => self.add_sub(dst, src, 0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sub(&mut self, dst: Reg, src: impl Into<Imm>) -> ERes {
|
||||
@@ -217,7 +219,10 @@ impl Code {
|
||||
}
|
||||
}
|
||||
|
||||
fn prefix32(&mut self, mem: &Mem) -> Result<(), CompilerMsg> {
|
||||
fn prefix32(&mut self, mem: impl MaybeMem) -> Result<(), CompilerMsg> {
|
||||
let Some(mem) = mem.mem() else {
|
||||
return Ok(());
|
||||
};
|
||||
match mem.reg.width() {
|
||||
Width::B8 | Width::B16 => return Err("invalid register width".into()),
|
||||
Width::B32 => self.bytes.push(0x67),
|
||||
|
||||
Reference in New Issue
Block a user