From bfc0c294d0fd3ba498f286300ccadcea8b81c46c Mon Sep 17 00:00:00 2001 From: mii Date: Fri, 30 Jun 2023 13:30:40 +0000 Subject: [PATCH] rv wrapper --- .gitignore | 1 + Cargo.lock | 7 +++ Cargo.toml | 3 ++ examples/simple.rs | 13 +++++ src/lib.rs | 2 + src/main.rs | 3 -- src/rv.rs | 122 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 examples/simple.rs create mode 100644 src/lib.rs delete mode 100644 src/main.rs create mode 100644 src/rv.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock index 0a2d094..9286b62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,9 +8,16 @@ version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + [[package]] name = "rsrv" version = "0.1.0" dependencies = [ "cc", + "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 651006e..d503587 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,5 +5,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +libc = "0.2" + [build-dependencies] cc = "1.0" diff --git a/examples/simple.rs b/examples/simple.rs new file mode 100644 index 0000000..60b4fe5 --- /dev/null +++ b/examples/simple.rs @@ -0,0 +1,13 @@ +use rsrv::rv::*; + +fn main() { + let cpu = RV::new(0x10000, vec![0x02A88893, 0x00000073]); + + while RV::step(cpu) != RV_EECALL {} + + println!( + "Environment call @ {:08x}: {}", + RV::get_pc(cpu), + RV::get_r(cpu)[17] + ); +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..0dc72d9 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,2 @@ +#[allow(dead_code)] +pub mod rv; diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/src/rv.rs b/src/rv.rs new file mode 100644 index 0000000..e4573fd --- /dev/null +++ b/src/rv.rs @@ -0,0 +1,122 @@ +use std::{ffi::c_void, slice}; + +pub const RV_EIALIGN: u32 = 1; +pub const RV_EIFAULT: u32 = 2; +pub const RV_EILL: u32 = 3; +pub const RV_EBP: u32 = 4; +pub const RV_ELALIGN: u32 = 5; +pub const RV_ELFAULT: u32 = 6; +pub const RV_ESALIGN: u32 = 7; +pub const RV_ESFAULT: u32 = 8; +pub const RV_EECALL: u32 = 9; + +pub const RV_OK: u32 = 0; +pub const RV_BAD: u32 = 1; + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct CSRS { + pub mhartid: u32, + pub mstatus: u32, + pub mstatush: u32, + pub mscratch: u32, + pub mepc: u32, + pub mcause: u32, + pub mtval: u32, + pub mip: u32, + pub mtinst: u32, + pub mtval2: u32, + pub mtvec: u32, + pub mie: u32, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct RV { + rv_load_cb: extern "C" fn(*mut c_void, u32, u8) -> u32, + rv_store_cb: extern "C" fn(*mut c_void, u32, *const u8) -> u32, + r: [u32; 32], + pc: u32, + next_pc: u32, + user: *mut c_void, + csrs: CSRS, +} + +extern "C" fn rv_load_cb(user: *mut c_void, addr: u32, data: *mut u8) -> u32 { + if (addr - 0x80000000) > 0x10000 { + return RV_BAD; + } + + unsafe { + *data = *(user.offset((addr - 0x80000000) as isize) as *mut u8); + } + + RV_OK +} + +extern "C" fn rv_store_cb(user: *mut c_void, addr: u32, data: u8) -> u32 { + if (addr - 0x80000000) > 0x10000 { + return RV_BAD; + } + + unsafe { + *(user.offset((addr - 0x80000000) as isize) as *mut u8) = data; + } + + RV_OK +} + +extern "C" { + fn rv_init( + cpu: *mut RV, + user: *mut c_void, + rv_load_cb: extern "C" fn(*mut c_void, u32, *mut u8) -> u32, + rv_store_cb: extern "C" fn(*mut c_void, u32, u8) -> u32, + ); + + fn rv_step(cpu: *mut RV) -> u32; +} + +impl RV { + pub fn new(mem_size: usize, program: Vec) -> *mut RV { + unsafe { + let mem = libc::malloc(mem_size as libc::size_t) as *mut c_void; + + libc::memcpy( + mem, + program.as_ptr() as *mut c_void, + std::mem::size_of_val(&program) as libc::size_t, + ); + + let rv = libc::malloc(std::mem::size_of::() as libc::size_t) as *mut RV; + + rv_init(rv, mem, rv_load_cb, rv_store_cb); + + rv + } + } + + pub fn step(cpu: *mut RV) -> u32 { + unsafe { rv_step(cpu) } + } + + pub fn get_r(cpu: *mut RV) -> [u32; 32] { + let cpu = unsafe { *cpu }; + cpu.r + } + + pub fn get_pc(cpu: *mut RV) -> u32 { + let cpu = unsafe { *cpu }; + cpu.pc + } + + pub fn get_next_pc(cpu: *mut RV) -> u32 { + let cpu = unsafe { *cpu }; + cpu.next_pc + } + + pub fn get_csrs(cpu: *mut RV) -> CSRS { + let cpu = unsafe { *cpu }; + cpu.csrs + } +}