push and pop

This commit is contained in:
2026-06-06 23:47:38 -04:00
parent 66710370bf
commit a086fa6590
6 changed files with 67 additions and 20 deletions
+29 -13
View File
@@ -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<Instr>,
@@ -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<u64> for RegImm {
}
}
pub fn mov(dst: RegMode, src: impl Into<RegImm>) -> Instr {
Instr::Mov {
dst,
src: src.into(),
mod fns {
use super::*;
pub fn mov(dst: RegMode, src: impl Into<RegImm>) -> 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::*;
+17 -1
View File
@@ -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(())
}
+17 -4
View File
@@ -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()
}
}
+3 -1
View File
@@ -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,
],
})]);
+1 -1
View File
@@ -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}");
BIN
View File
Binary file not shown.