diff options
-rw-r--r-- | examples/add.rs | 30 | ||||
-rw-r--r-- | src/insn.rs | 6 | ||||
-rw-r--r-- | src/insn/call.rs | 7 | ||||
-rw-r--r-- | src/prelude.rs | 2 | ||||
-rw-r--r-- | src/rt.rs | 3 |
5 files changed, 46 insertions, 2 deletions
diff --git a/examples/add.rs b/examples/add.rs new file mode 100644 index 0000000..ef010b6 --- /dev/null +++ b/examples/add.rs @@ -0,0 +1,30 @@ +use juicebox_asm::prelude::*; +use juicebox_asm::Runtime; +use Reg64::*; + +extern "C" fn add(a: u32, b: u32) -> u32 { + a + b +} + +fn main() { + let mut asm = Asm::new(); + + // SystemV abi: + // rdi -> first argument + // rsi -> second argument + // rax -> return value + // + asm.mov(rsi, Imm64::from(42)); + asm.mov(rax, Imm64::from(add as u64)); + asm.call(rax); + asm.ret(); + + let code = asm.into_code(); + std::fs::write("jit.asm", &code).unwrap(); + + let rt = Runtime::new(&code); + let add42 = unsafe { rt.as_fn::<extern "C" fn(u32) -> u32>() }; + + let res = add42(5); + assert_eq!(res, 47); +} diff --git a/src/insn.rs b/src/insn.rs index 2a6ca42..8810085 100644 --- a/src/insn.rs +++ b/src/insn.rs @@ -1,6 +1,7 @@ //! Trait definitions of various instructions. mod add; +mod call; mod dec; mod jmp; mod jnz; @@ -15,6 +16,11 @@ pub trait Add<T, U> { fn add(&mut self, op1: T, op2: U); } +pub trait Call<T> { + /// Emit a call instruction. + fn call(&mut self, op1: T); +} + pub trait Dec<T> { /// Emit a decrement instruction. fn dec(&mut self, op1: T); diff --git a/src/insn/call.rs b/src/insn/call.rs new file mode 100644 index 0000000..8a71db8 --- /dev/null +++ b/src/insn/call.rs @@ -0,0 +1,7 @@ +use crate::prelude::*; + +impl Call<Reg64> for Asm { + fn call(&mut self, op1: Reg64) { + self.encode_r(0xff, 0x2, op1); + } +} diff --git a/src/prelude.rs b/src/prelude.rs index 0093240..b21d67c 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -7,4 +7,4 @@ pub use crate::imm::{Imm16, Imm32, Imm64, Imm8}; pub use crate::label::Label; pub use crate::reg::{Reg16, Reg32, Reg64, Reg8}; -pub use crate::insn::{Add, Dec, Jmp, Jnz, Jz, Mov, Test}; +pub use crate::insn::{Add, Call, Dec, Jmp, Jnz, Jz, Mov, Test}; @@ -11,7 +11,7 @@ pub struct Runtime { impl Runtime { /// Create a new [Runtime]. - pub fn new(code: &[u8]) -> Runtime { + pub fn new(code: impl AsRef<[u8]>) -> Runtime { // Allocate a single page. let len = core::num::NonZeroUsize::new(4096).unwrap(); let buf = unsafe { @@ -27,6 +27,7 @@ impl Runtime { }; { // Copy over code. + let code = code.as_ref(); assert!(code.len() < len.get()); unsafe { std::ptr::copy_nonoverlapping(code.as_ptr(), buf.cast(), len.get()) }; } |