use embassy_executor::Spawner;
use embassy_futures::yield_now;
use log::info;
use core::num::NonZeroI32;
use embive::{
interpreter::{
memory::{Memory, MemoryType, SliceMemory},
registers::CPURegister,
Interpreter, State, SYSCALL_ARGS,
},
transpiler::transpile_elf,
};
const ELF_FILE: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/app.elf"));
async fn syscall<M: Memory>(
nr: i32,
args: &[i32; SYSCALL_ARGS],
memory: &mut M,
) -> Result<Result<i32, NonZeroI32>, ()> {
info!("Entering syscall: {nr}");
yield_now().await; info!("Args: {args:?}");
Ok(match nr {
1 => Ok(args[0] + args[1]),
2 => match i32::load(memory, args[0] as u32) {
Ok(val) => Ok(val),
Err(_) => Err(1.try_into().unwrap()), },
_ => Err(2.try_into().unwrap()), })
}
#[embassy_executor::task]
async fn run() {
loop {
info!("tick");
yield_now().await;
}
}
#[embassy_executor::main]
async fn main(spawner: Spawner) {
env_logger::builder()
.filter_level(log::LevelFilter::Debug)
.format_timestamp_nanos()
.init();
spawner.spawn(run()).unwrap();
let mut code = [0; 16384];
transpile_elf(ELF_FILE, &mut code).unwrap();
let mut ram = [0; 4096];
let mut memory = SliceMemory::new(&code, &mut ram);
let mut interpreter = Interpreter::new(&mut memory, 10);
loop {
match interpreter.run().unwrap() {
State::Running => {
info!("Yielding...");
yield_now().await;
}
State::Called => interpreter.syscall_async(&mut syscall).await.unwrap(),
State::Waiting => interpreter.interrupt(10).unwrap(),
State::Halted => break,
}
}
assert_eq!(
interpreter
.registers
.cpu
.get(CPURegister::A0 as u8)
.unwrap(),
0
);
assert_eq!(
interpreter
.registers
.cpu
.get(CPURegister::A1 as u8)
.unwrap(),
30
);
info!("Interpreter halted!");
std::process::exit(0);
}