initial commit
This commit is contained in:
commit
92fc7ff44b
8 changed files with 335 additions and 0 deletions
src
152
src/vm.rs
Normal file
152
src/vm.rs
Normal file
|
@ -0,0 +1,152 @@
|
|||
pub type VM_Word = i64;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(u64)]
|
||||
pub enum VM_Instruction {
|
||||
Nop, Jmp, Call, Branch, Ret,
|
||||
Lit, Dup, Drop, Swap, Rot,
|
||||
Fetch, Store,
|
||||
Accept, Emit,
|
||||
Add, //Sub, Mul, Div, Rem,
|
||||
Addf,//Subf, Mulf, Divf
|
||||
BitwiseNot,
|
||||
}
|
||||
|
||||
pub struct VM {
|
||||
pub data_stack: Vec< VM_Word >,
|
||||
pub call_stack: Vec< VM_Word >,
|
||||
|
||||
pub inst_ptr: VM_Word,
|
||||
pub memory: Vec< VM_Word >,
|
||||
}
|
||||
|
||||
impl VM {
|
||||
pub fn new(memsize: usize) -> Self {
|
||||
VM {
|
||||
data_stack: Vec::new(),
|
||||
call_stack: Vec::new(),
|
||||
|
||||
inst_ptr: 0,
|
||||
memory: vec![0; memsize]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute(&mut self, entry: VM_Word) {
|
||||
self.inst_ptr = entry;
|
||||
while self.execute_step() {}
|
||||
}
|
||||
|
||||
pub fn execute_step(&mut self) -> bool {
|
||||
// fetch instruction from memory
|
||||
let inst = unsafe { std::mem::transmute(self.memory[ self.inst_ptr as usize ]) };
|
||||
self.inst_ptr += 1;
|
||||
|
||||
// decode instruction & load immediate if neccesary
|
||||
let mut imm : VM_Word = 0;
|
||||
match inst {
|
||||
VM_Instruction::Jmp |
|
||||
VM_Instruction::Call |
|
||||
VM_Instruction::Branch |
|
||||
VM_Instruction::Lit => {
|
||||
imm = self.memory[ self.inst_ptr as usize ];
|
||||
self.inst_ptr += 1;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// execute instruction
|
||||
self.execute_instruction( inst, imm )
|
||||
}
|
||||
|
||||
pub fn execute_instruction(&mut self, inst: VM_Instruction, imm: VM_Word) -> bool {
|
||||
// eprintln!("execute {:?}, {}", inst, imm);
|
||||
match inst {
|
||||
VM_Instruction::Nop => {}
|
||||
VM_Instruction::Lit => {
|
||||
self.data_stack.push( imm );
|
||||
}
|
||||
VM_Instruction::Jmp => {
|
||||
self.inst_ptr += imm;
|
||||
}
|
||||
VM_Instruction::Call => {
|
||||
self.call_stack.push( self.inst_ptr );
|
||||
self.inst_ptr = imm;
|
||||
}
|
||||
VM_Instruction::Branch => {
|
||||
if self.data_stack.pop().expect("branch expects val") == 0 {
|
||||
//self.call_stack.push( self.inst_ptr );
|
||||
self.inst_ptr += imm;
|
||||
}
|
||||
}
|
||||
VM_Instruction::Ret => {
|
||||
if let Some(target) = self.call_stack.pop() {
|
||||
self.inst_ptr = target;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
VM_Instruction::Fetch => {
|
||||
let addr = self.data_stack.pop().expect("fetch requries addr");
|
||||
let val = self.memory[ addr as usize ];
|
||||
self.data_stack.push(val);
|
||||
}
|
||||
VM_Instruction::Store => {
|
||||
let addr = self.data_stack.pop().expect("store requires addr");
|
||||
let val = self.data_stack.pop().expect("store requires val");
|
||||
self.memory[ addr as usize ] = val;
|
||||
}
|
||||
VM_Instruction::Accept => {
|
||||
// todo: read word from stdin
|
||||
self.data_stack.push(0);
|
||||
}
|
||||
VM_Instruction::Emit => {
|
||||
let val = char::from(self.data_stack.pop().expect("emit expects value") as u8);
|
||||
print!("{}", val);
|
||||
}
|
||||
VM_Instruction::Dup => {
|
||||
self.data_stack.push( *self.data_stack.last().expect("dup expect val") );
|
||||
}
|
||||
VM_Instruction::Drop => {
|
||||
self.data_stack.pop().expect("drop expects value");
|
||||
}
|
||||
VM_Instruction::Swap => {
|
||||
let a = self.data_stack.pop().expect("swap expects value");
|
||||
let b = self.data_stack.pop().expect("swap expects value");
|
||||
self.data_stack.push(a);
|
||||
self.data_stack.push(b);
|
||||
}
|
||||
VM_Instruction::Rot => {
|
||||
let a = self.data_stack.pop().expect("rot expects value");
|
||||
let b = self.data_stack.pop().expect("rot expects value");
|
||||
let c = self.data_stack.pop().expect("rot expects value");
|
||||
self.data_stack.push(a);
|
||||
self.data_stack.push(c);
|
||||
self.data_stack.push(b);
|
||||
}
|
||||
VM_Instruction::Add => {
|
||||
let a = self.data_stack.pop().expect("add expects value");
|
||||
let b = self.data_stack.pop().expect("add expects value");
|
||||
self.data_stack.push( a + b );
|
||||
}
|
||||
VM_Instruction::Addf => {
|
||||
let a = self.data_stack.pop().expect("addf expects value");
|
||||
let af : f64 = unsafe{ std::mem::transmute(a) };
|
||||
|
||||
let b = self.data_stack.pop().expect("addf expects value");
|
||||
let bf : f64 = unsafe{ std::mem::transmute(a) };
|
||||
|
||||
let cf = af + bf;
|
||||
let c : i64 = unsafe{ std::mem::transmute(cf) };
|
||||
|
||||
self.data_stack.push(c);
|
||||
}
|
||||
VM_Instruction::BitwiseNot => {
|
||||
let a = self.data_stack.pop().expect("bitwise not expects value");
|
||||
self.data_stack.push( !a );
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue