aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJohannes Stoelp <johannes.stoelp@gmail.com>2023-03-05 22:20:48 +0100
committerJohannes Stoelp <johannes.stoelp@gmail.com>2023-03-05 22:20:48 +0100
commit8316b628bbc9945fd1d08305317cf49a6482801f (patch)
treeffc730d9ad9a131a2dbe54d41a4ab026e06f1ff3
parent005fca316085c3a2ce3e43b92531f006a15fbdd2 (diff)
downloadjuicebox-asm-8316b628bbc9945fd1d08305317cf49a6482801f.tar.gz
juicebox-asm-8316b628bbc9945fd1d08305317cf49a6482801f.zip
Added CALL and call extern fn example
-rw-r--r--examples/add.rs30
-rw-r--r--src/insn.rs6
-rw-r--r--src/insn/call.rs7
-rw-r--r--src/prelude.rs2
-rw-r--r--src/rt.rs3
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};
diff --git a/src/rt.rs b/src/rt.rs
index 1e9289e..7b5f74b 100644
--- a/src/rt.rs
+++ b/src/rt.rs
@@ -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()) };
}