diff options
author | Johannes Stoelp <johannes.stoelp@gmail.com> | 2023-02-27 22:41:39 +0100 |
---|---|---|
committer | Johannes Stoelp <johannes.stoelp@gmail.com> | 2023-02-27 22:41:39 +0100 |
commit | 23f5da9983036cf37dedc0511a930fcbc7a8bc0e (patch) | |
tree | ab663fb8452ef081f635a0e5fc085bbf874a9e5e /examples | |
parent | 24c9507c2d6529699edca9b2479d7e4f1a3415e6 (diff) | |
download | juicebox-asm-23f5da9983036cf37dedc0511a930fcbc7a8bc0e.tar.gz juicebox-asm-23f5da9983036cf37dedc0511a930fcbc7a8bc0e.zip |
Add fibonacci example
Diffstat (limited to 'examples')
-rw-r--r-- | examples/fib.rs | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/examples/fib.rs b/examples/fib.rs new file mode 100644 index 0000000..c4233da --- /dev/null +++ b/examples/fib.rs @@ -0,0 +1,73 @@ +use juicebox_asm::prelude::*; +use juicebox_asm::rt::Runtime; + +const fn fib_rs(n: u64) -> u64 { + match n { + 0 => 0, + 1 => 1, + _ => fib_rs(n - 2) + fib_rs(n - 1), + } +} + +fn main() { + let mut asm = Asm::new(); + + let mut lp = Label::new(); + let mut end = Label::new(); + + // Reference implementation: + // + // int fib(int n) { + // int tmp = 0; + // int prv = 1; + // int sum = 0; + // loop: + // if (n == 0) goto end; + // tmp = sum; + // sum += prv; + // prv = tmp; + // --n; + // goto loop; + // end: + // return sum; + // } + + // SystemV abi: + // rdi -> first argument + // rax -> return value + let n = Reg64::rdi; + let sum = Reg64::rax; + + let tmp = Reg64::rcx; + let prv = Reg64::rbx; + + asm.mov(tmp, Imm64::from(0)); + asm.mov(prv, Imm64::from(1)); + asm.mov(sum, Imm64::from(0)); + + asm.bind(&mut lp); + asm.test(n, n); + asm.jz(&mut end); + asm.mov(tmp, sum); + asm.add(sum, prv); + asm.mov(prv, tmp); + asm.dec(n); + asm.jmp(&mut lp); + asm.bind(&mut end); + asm.ret(); + + // Write out JIT code for visualization. + // Disassemble for example with `ndisasm -b 64 jit.asm`. + let code = asm.into_code(); + std::fs::write("jit.asm", &code).unwrap(); + + // Move code into executable page and get function pointer to it. + let rt = Runtime::new(&code); + let fib = unsafe { rt.as_fn::<extern "C" fn(u64) -> u64>() }; + + for n in 0..15 { + let fib_jit = fib(n); + println!("fib({}) = {}", n, fib_jit); + assert_eq!(fib_jit, fib_rs(n)); + } +} |