aboutsummaryrefslogtreecommitdiffhomepage
path: root/examples
diff options
context:
space:
mode:
authorJohannes Stoelp <johannes.stoelp@gmail.com>2023-02-27 22:41:39 +0100
committerJohannes Stoelp <johannes.stoelp@gmail.com>2023-02-27 22:41:39 +0100
commit23f5da9983036cf37dedc0511a930fcbc7a8bc0e (patch)
treeab663fb8452ef081f635a0e5fc085bbf874a9e5e /examples
parent24c9507c2d6529699edca9b2479d7e4f1a3415e6 (diff)
downloadjuicebox-asm-23f5da9983036cf37dedc0511a930fcbc7a8bc0e.tar.gz
juicebox-asm-23f5da9983036cf37dedc0511a930fcbc7a8bc0e.zip
Add fibonacci example
Diffstat (limited to 'examples')
-rw-r--r--examples/fib.rs73
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));
+ }
+}