diff --git a/src/arch/x86_64/asm.rs b/src/arch/x86_64/asm.rs index 976a4b6..7c1b19d 100644 --- a/src/arch/x86_64/asm.rs +++ b/src/arch/x86_64/asm.rs @@ -1,4 +1,7 @@ -use crate::{arch::x86_64::RegMode, backend::Symbol}; +use crate::{ + arch::x86_64::{BitWidth, Reg, RegMode}, + backend::Symbol, +}; pub struct Asm { pub instrs: Vec, @@ -7,11 +10,13 @@ pub struct Asm { #[derive(Clone, Copy)] pub enum Instr { Mov { dst: RegMode, src: RegImm }, - Int { code: u8 }, + Int(u8), Call(Symbol), Ret, Syscall, Lea { dst: RegMode, sym: Symbol }, + Push(Reg), + Pop(Reg), } #[derive(Clone, Copy)] @@ -32,17 +37,28 @@ impl From for RegImm { } } -pub fn mov(dst: RegMode, src: impl Into) -> Instr { - Instr::Mov { - dst, - src: src.into(), +mod fns { + use super::*; + pub fn mov(dst: RegMode, src: impl Into) -> Instr { + Instr::Mov { + dst, + src: src.into(), + } + } + + pub fn lea(dst: RegMode, sym: Symbol) -> Instr { + Instr::Lea { dst, sym } + } + + pub fn push(reg: RegMode) -> Instr { + assert!(reg.width == BitWidth::B64); + Instr::Push(reg.reg) + } + + pub fn pop(reg: RegMode) -> Instr { + assert!(reg.width == BitWidth::B64); + Instr::Pop(reg.reg) } } -pub fn lea(dst: RegMode, sym: Symbol) -> Instr { - Instr::Lea { dst, sym } -} - -pub fn int(code: u8) -> Instr { - Instr::Int { code } -} +pub use fns::*; diff --git a/src/arch/x86_64/encode.rs b/src/arch/x86_64/encode.rs index 67af13f..cd4af33 100644 --- a/src/arch/x86_64/encode.rs +++ b/src/arch/x86_64/encode.rs @@ -115,6 +115,20 @@ impl Encoder { self.data.push(0xc3); } + pub fn push(&mut self, reg: Reg) { + if reg.gt8() { + self.data.push(0x41); + } + self.data.push(0x50 | reg.base()); + } + + pub fn pop(&mut self, reg: Reg) { + if reg.gt8() { + self.data.push(0x41); + } + self.data.push(0x58 | reg.base()); + } + /// inserts a 32 bit offset from a symbol pub fn sym_offset4(&mut self, sym: Symbol) { let Some(addr) = self.sym_tab.get(sym) else { @@ -129,11 +143,13 @@ impl Encoder { pub fn asm(&mut self, instr: Instr) -> Result<(), CompilerMsg> { match instr { Instr::Mov { dst, src } => self.mov(dst, src)?, - Instr::Int { code } => self.int(code), + Instr::Int(code) => self.int(code), Instr::Syscall => self.syscall(), Instr::Lea { dst, sym } => self.lea(dst, sym), Instr::Call(sym) => self.call(sym), Instr::Ret => self.ret(), + Instr::Push(reg) => self.push(reg), + Instr::Pop(reg) => self.pop(reg), } Ok(()) } diff --git a/src/arch/x86_64/reg.rs b/src/arch/x86_64/reg.rs index 7a6882f..d772ea3 100644 --- a/src/arch/x86_64/reg.rs +++ b/src/arch/x86_64/reg.rs @@ -16,16 +16,29 @@ pub enum BitWidth { B8, } -impl RegMode { +impl Reg { pub fn base(&self) -> u8 { - self.reg.0 & 0b111 + self.0 & 0b111 } /// checks if register is not one of the first 8 (0-7) pub fn gt8(&self) -> bool { - self.reg.0 >= 0b1000 + self.0 >= 0b1000 } pub fn gt4(&self) -> bool { - self.reg.0 >= 0b0100 + self.0 >= 0b0100 + } +} + +impl RegMode { + pub fn base(&self) -> u8 { + self.reg.base() + } + /// checks if register is not one of the first 8 (0-7) + pub fn gt8(&self) -> bool { + self.reg.gt8() + } + pub fn gt4(&self) -> bool { + self.reg.gt4() } } diff --git a/src/arch/x86_64/test/bin.rs b/src/arch/x86_64/test/bin.rs index bfc5000..dfaea9b 100644 --- a/src/arch/x86_64/test/bin.rs +++ b/src/arch/x86_64/test/bin.rs @@ -22,6 +22,8 @@ pub fn run() { })]); let entry = program.func([BInstr::Asm(Asm { instrs: vec![ + mov(di, 39), + push(rdi), mov(ax, 1), mov(di, 1), lea(rsi, text_sym), @@ -29,7 +31,7 @@ pub fn run() { Instr::Syscall, Instr::Call(hello2), mov(ax, 0x3c), - mov(di, 39), + pop(rdi), Instr::Syscall, ], })]); diff --git a/src/parser/nodes/asm/x86_64.rs b/src/parser/nodes/asm/x86_64.rs index b162646..8361c6f 100644 --- a/src/parser/nodes/asm/x86_64.rs +++ b/src/parser/nodes/asm/x86_64.rs @@ -27,7 +27,7 @@ impl Node for Asm { let code = parse_imm(&num, ctx.span)? .try_into() .map_err(|_| CompilerMsg::from("Immediate must be a u8"))?; - instrs.push(Instr::Int { code }); + instrs.push(Instr::Int(code)); } _ => { let msg = format!("Unknown instruction {next}"); diff --git a/x86_64_test b/x86_64_test index 92c5c41..ae8f616 100755 Binary files a/x86_64_test and b/x86_64_test differ