impl sub
This commit is contained in:
@@ -172,9 +172,35 @@ impl Code {
|
||||
self.bytes.push(0xc3);
|
||||
}
|
||||
|
||||
pub fn sub(&mut self) {
|
||||
// sub esp 40 iirc
|
||||
self.bytes.extend([0x48, 0x83, 0xec, 0x28]);
|
||||
pub fn sub(&mut self, mut dst: Reg, src: impl Into<Imm>) -> ERes {
|
||||
let mut src = src.into();
|
||||
let mut 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 {
|
||||
return Err("immediate overflow".into());
|
||||
}
|
||||
src = src.reinterpret(dst_width);
|
||||
width = src.width_signed()?;
|
||||
}
|
||||
if dst.width() == Width::B8 {
|
||||
self.bytes.push(0x80);
|
||||
} else {
|
||||
if width == Width::B8 {
|
||||
self.bytes.push(0x83);
|
||||
} else {
|
||||
self.bytes.push(0x81);
|
||||
width = dst_width;
|
||||
}
|
||||
}
|
||||
self.bytes.push(modrm(0b11, 0b101, dst.base()));
|
||||
self.imm(src, width);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prefix16(&mut self, width: impl Into<Width>) {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
mod setup;
|
||||
use setup::*;
|
||||
|
||||
#[test]
|
||||
fn mov() {
|
||||
let c = &mut TestCtx::new("mov");
|
||||
|
||||
for dst in regs() {
|
||||
for src in regs() {
|
||||
eq(c, format!("mov {dst}, {src}"), |c| c.mov(dst, src));
|
||||
}
|
||||
}
|
||||
|
||||
for dst in regs() {
|
||||
for src in mems() {
|
||||
eq(c, format!("mov {dst}, {src}"), |c| c.mov(dst, src));
|
||||
}
|
||||
}
|
||||
|
||||
for dst in regs() {
|
||||
for src in imms() {
|
||||
eq(c, format!("mov {dst}, {src}"), |c| c.mov(dst, src));
|
||||
}
|
||||
}
|
||||
|
||||
for dst in mems() {
|
||||
for src in regs() {
|
||||
eq(c, format!("mov {dst}, {src}"), |c| c.mov(dst, src));
|
||||
}
|
||||
}
|
||||
|
||||
for dst in mems() {
|
||||
for src in imms() {
|
||||
eq(c, format!("mov {dst}, {src}"), |c| c.mov(dst, src));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sub() {
|
||||
let c = &mut TestCtx::new("mov");
|
||||
|
||||
for dst in regs() {
|
||||
for src in imms() {
|
||||
eq(c, format!("sub {dst}, {src}"), |c| c.sub(dst, src))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,50 +32,15 @@ const IMMS: &[i128] = &[
|
||||
|
||||
const WIDTHS: &[Width] = &[Width::B8, Width::B16, Width::B32, Width::B64];
|
||||
|
||||
#[test]
|
||||
fn mov() {
|
||||
let c = &mut TestCtx::new("mov");
|
||||
|
||||
for dst in regs() {
|
||||
for src in regs() {
|
||||
eq(c, format!("mov {dst}, {src}"), |c| c.mov(dst, src));
|
||||
}
|
||||
}
|
||||
|
||||
for dst in regs() {
|
||||
for src in mems() {
|
||||
eq(c, format!("mov {dst}, {src}"), |c| c.mov(dst, src));
|
||||
}
|
||||
}
|
||||
|
||||
for dst in regs() {
|
||||
for src in imms() {
|
||||
eq(c, format!("mov {dst}, {src}"), |c| c.mov(dst, src));
|
||||
}
|
||||
}
|
||||
|
||||
for dst in mems() {
|
||||
for src in regs() {
|
||||
eq(c, format!("mov {dst}, {src}"), |c| c.mov(dst, src));
|
||||
}
|
||||
}
|
||||
|
||||
for dst in mems() {
|
||||
for src in imms() {
|
||||
eq(c, format!("mov {dst}, {src}"), |c| c.mov(dst, src));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn imms() -> impl Iterator<Item = i128> {
|
||||
pub fn imms() -> impl Iterator<Item = i128> {
|
||||
IMMS.iter().cloned()
|
||||
}
|
||||
|
||||
fn regs() -> impl Iterator<Item = Reg> {
|
||||
pub fn regs() -> impl Iterator<Item = Reg> {
|
||||
Reg::IMPORTANT.iter().cloned()
|
||||
}
|
||||
|
||||
fn mems() -> impl Iterator<Item = Mem> {
|
||||
pub fn mems() -> impl Iterator<Item = Mem> {
|
||||
gen move {
|
||||
for ® in Reg::IMPORTANT {
|
||||
for &disp in DISPS {
|
||||
@@ -87,14 +52,14 @@ fn mems() -> impl Iterator<Item = Mem> {
|
||||
}
|
||||
}
|
||||
|
||||
struct TestCtx {
|
||||
pub struct TestCtx {
|
||||
path: String,
|
||||
code: Code,
|
||||
cache: HashMap<String, Result<Vec<u8>, String>>,
|
||||
changed: bool,
|
||||
}
|
||||
|
||||
fn eq(
|
||||
pub fn eq(
|
||||
ctx: &mut TestCtx,
|
||||
asm: impl AsRef<str>,
|
||||
instr: impl FnOnce(&mut Code) -> Result<(), CompilerMsg>,
|
||||
@@ -176,7 +141,7 @@ fn write(path: &str, binary: &[u8]) {
|
||||
const CACHE_PATH: &str = "test/nasm_cache";
|
||||
|
||||
impl TestCtx {
|
||||
fn new(name: &str) -> Self {
|
||||
pub fn new(name: &str) -> Self {
|
||||
let path = CACHE_PATH.to_string() + "/" + name;
|
||||
let cache = match std::fs::read(&path) {
|
||||
Ok(bytes) => bitcode::decode(&bytes).unwrap_or_default(),
|
||||
@@ -11,7 +11,7 @@ fn hello() -> Result<(), CompilerMsg> {
|
||||
let entry = program.func(
|
||||
"main",
|
||||
[Instr::Asm(encode(|c| {
|
||||
c.sub();
|
||||
c.sub(esp, 0x28)?;
|
||||
// stdout
|
||||
c.mov(ecx, -11)?;
|
||||
c.call_mem(get_std_handle);
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
mod full;
|
||||
mod nasm;
|
||||
mod asm;
|
||||
|
||||
@@ -53,6 +53,15 @@ impl Imm {
|
||||
_ => return Err(Self::overflow_msg()),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn reinterpret(&self, width: Width) -> Self {
|
||||
Self(match width {
|
||||
Width::B8 => self.0 as i8 as i128,
|
||||
Width::B16 => self.0 as i16 as i128,
|
||||
Width::B32 => self.0 as i32 as i128,
|
||||
Width::B64 => self.0 as i64 as i128,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Imm> for u8 {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user