juicebox_asm/lib.rs
1// SPDX-License-Identifier: MIT
2//
3// Copyright (c) 2023, Johannes Stoelp <dev@memzero.de>
4
5//! A simple `x64` jit assembler with a minimal runtime to execute emitted code for fun.
6//!
7//! The following is an fibonacci example implementation.
8//! ```rust
9//! use juicebox_asm::{Asm, Reg64, Imm64, Label};
10//! use juicebox_asm::insn::*;
11//! use juicebox_asm::Runtime;
12//!
13//! const fn fib_rs(n: u64) -> u64 {
14//! match n {
15//! 0 => 0,
16//! 1 => 1,
17//! _ => fib_rs(n - 2) + fib_rs(n - 1),
18//! }
19//! }
20//!
21//! fn main() {
22//! let mut asm = Asm::new();
23//!
24//! let mut lp = Label::new();
25//! let mut end = Label::new();
26//!
27//! // Reference implementation:
28//! //
29//! // int fib(int n) {
30//! // int tmp = 0;
31//! // int prv = 1;
32//! // int sum = 0;
33//! // loop:
34//! // if (n == 0) goto end;
35//! // tmp = sum;
36//! // sum += prv;
37//! // prv = tmp;
38//! // --n;
39//! // goto loop;
40//! // end:
41//! // return sum;
42//! // }
43//!
44//! // SystemV abi:
45//! // rdi -> first argument
46//! // rax -> return value
47//! let n = Reg64::rdi;
48//! let sum = Reg64::rax;
49//!
50//! let tmp = Reg64::rcx;
51//! let prv = Reg64::rbx;
52//!
53//! asm.mov(tmp, Imm64::from(0));
54//! asm.mov(prv, Imm64::from(1));
55//! asm.mov(sum, Imm64::from(0));
56//!
57//! asm.bind(&mut lp);
58//! asm.test(n, n);
59//! asm.jz(&mut end);
60//! asm.mov(tmp, sum);
61//! asm.add(sum, prv);
62//! asm.mov(prv, tmp);
63//! asm.dec(n);
64//! asm.jmp(&mut lp);
65//! asm.bind(&mut end);
66//! asm.ret();
67//!
68//! // Move code into executable page and get function pointer to it.
69//! let mut rt = Runtime::new();
70//! let fib = unsafe { rt.add_code::<extern "C" fn(u64) -> u64>(&asm.into_code()) };
71//!
72//! for n in 0..15 {
73//! let fib_jit = fib(n);
74//! println!("fib({}) = {}", n, fib_jit);
75//! assert_eq!(fib_jit, fib_rs(n));
76//! }
77//! }
78//! ```
79
80mod asm;
81mod disasm;
82mod imm;
83mod label;
84mod mem;
85mod reg;
86mod rt;
87
88pub mod insn;
89
90pub use asm::Asm;
91pub use imm::{Imm16, Imm32, Imm64, Imm8};
92pub use label::Label;
93pub use mem::{Mem16, Mem32, Mem64, Mem8};
94pub use reg::{Reg16, Reg32, Reg64, Reg8};
95pub use rt::Runtime;