add inline opcodes
This commit is contained in:
parent
7e99eed6b4
commit
0ea26f4efd
@ -13,6 +13,9 @@ pub enum OpCode {
|
||||
Pop = 0x11,
|
||||
Dup = 0x12,
|
||||
Swap = 0x13,
|
||||
PushI64 = 0x14,
|
||||
PushF64 = 0x15,
|
||||
PushBool = 0x16,
|
||||
|
||||
// 6.3 Arithmetic
|
||||
Add = 0x20,
|
||||
@ -64,6 +67,9 @@ impl TryFrom<u16> for OpCode {
|
||||
0x11 => Ok(OpCode::Pop),
|
||||
0x12 => Ok(OpCode::Dup),
|
||||
0x13 => Ok(OpCode::Swap),
|
||||
0x14 => Ok(OpCode::PushI64),
|
||||
0x15 => Ok(OpCode::PushF64),
|
||||
0x16 => Ok(OpCode::PushBool),
|
||||
0x20 => Ok(OpCode::Add),
|
||||
0x21 => Ok(OpCode::Sub),
|
||||
0x22 => Ok(OpCode::Mul),
|
||||
@ -104,6 +110,9 @@ impl OpCode {
|
||||
OpCode::Pop => 1,
|
||||
OpCode::Dup => 1,
|
||||
OpCode::Swap => 1,
|
||||
OpCode::PushI64 => 2,
|
||||
OpCode::PushF64 => 2,
|
||||
OpCode::PushBool => 2,
|
||||
OpCode::Add => 2,
|
||||
OpCode::Sub => 2,
|
||||
OpCode::Mul => 4,
|
||||
|
||||
@ -312,6 +312,18 @@ impl VirtualMachine {
|
||||
let val = self.program.constant_pool.get(idx).cloned().ok_or("Invalid constant index")?;
|
||||
self.push(val);
|
||||
}
|
||||
OpCode::PushI64 => {
|
||||
let val = self.read_i64()?;
|
||||
self.push(Value::Integer(val));
|
||||
}
|
||||
OpCode::PushF64 => {
|
||||
let val = self.read_f64()?;
|
||||
self.push(Value::Float(val));
|
||||
}
|
||||
OpCode::PushBool => {
|
||||
let val = self.read_u8()?;
|
||||
self.push(Value::Boolean(val != 0));
|
||||
}
|
||||
OpCode::Pop => {
|
||||
self.pop()?;
|
||||
}
|
||||
@ -534,6 +546,26 @@ impl VirtualMachine {
|
||||
Ok(u32::from_le_bytes(bytes))
|
||||
}
|
||||
|
||||
fn read_i64(&mut self) -> Result<i64, String> {
|
||||
if self.pc + 8 > self.program.rom.len() {
|
||||
return Err("Unexpected end of ROM".into());
|
||||
}
|
||||
let mut bytes = [0u8; 8];
|
||||
bytes.copy_from_slice(&self.program.rom[self.pc..self.pc + 8]);
|
||||
self.pc += 8;
|
||||
Ok(i64::from_le_bytes(bytes))
|
||||
}
|
||||
|
||||
fn read_f64(&mut self) -> Result<f64, String> {
|
||||
if self.pc + 8 > self.program.rom.len() {
|
||||
return Err("Unexpected end of ROM".into());
|
||||
}
|
||||
let mut bytes = [0u8; 8];
|
||||
bytes.copy_from_slice(&self.program.rom[self.pc..self.pc + 8]);
|
||||
self.pc += 8;
|
||||
Ok(f64::from_le_bytes(bytes))
|
||||
}
|
||||
|
||||
fn read_u16(&mut self) -> Result<u16, String> {
|
||||
if self.pc + 2 > self.program.rom.len() {
|
||||
return Err("Unexpected end of ROM".into());
|
||||
@ -546,6 +578,15 @@ impl VirtualMachine {
|
||||
Ok(u16::from_le_bytes(bytes))
|
||||
}
|
||||
|
||||
fn read_u8(&mut self) -> Result<u8, String> {
|
||||
if self.pc + 1 > self.program.rom.len() {
|
||||
return Err("Unexpected end of ROM".into());
|
||||
}
|
||||
let val = self.program.rom[self.pc];
|
||||
self.pc += 1;
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
pub fn push(&mut self, val: Value) {
|
||||
self.operand_stack.push(val);
|
||||
}
|
||||
@ -579,3 +620,97 @@ impl VirtualMachine {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::virtual_machine::Value;
|
||||
use crate::prometeu_os::NativeInterface;
|
||||
use crate::hardware::HardwareBridge;
|
||||
|
||||
struct MockNative;
|
||||
impl NativeInterface for MockNative {
|
||||
fn syscall(&mut self, _id: u32, _vm: &mut VirtualMachine, _hw: &mut dyn HardwareBridge) -> Result<u64, String> {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
struct MockHardware;
|
||||
impl HardwareBridge for MockHardware {
|
||||
fn gfx(&self) -> &crate::hardware::Gfx { todo!() }
|
||||
fn gfx_mut(&mut self) -> &mut crate::hardware::Gfx { todo!() }
|
||||
fn audio(&self) -> &crate::hardware::Audio { todo!() }
|
||||
fn audio_mut(&mut self) -> &mut crate::hardware::Audio { todo!() }
|
||||
fn pad(&self) -> &crate::hardware::Pad { todo!() }
|
||||
fn pad_mut(&mut self) -> &mut crate::hardware::Pad { todo!() }
|
||||
fn touch(&self) -> &crate::hardware::Touch { todo!() }
|
||||
fn touch_mut(&mut self) -> &mut crate::hardware::Touch { todo!() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_push_i64_immediate() {
|
||||
let mut rom = Vec::new();
|
||||
rom.extend_from_slice(&(OpCode::PushI64 as u16).to_le_bytes());
|
||||
rom.extend_from_slice(&42i64.to_le_bytes());
|
||||
rom.extend_from_slice(&(OpCode::Halt as u16).to_le_bytes());
|
||||
|
||||
let mut vm = VirtualMachine::new(rom, vec![]);
|
||||
let mut native = MockNative;
|
||||
let mut hw = MockHardware;
|
||||
|
||||
vm.step(&mut native, &mut hw).unwrap();
|
||||
assert_eq!(vm.peek().unwrap(), &Value::Integer(42));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_push_f64_immediate() {
|
||||
let mut rom = Vec::new();
|
||||
rom.extend_from_slice(&(OpCode::PushF64 as u16).to_le_bytes());
|
||||
rom.extend_from_slice(&3.14f64.to_le_bytes());
|
||||
rom.extend_from_slice(&(OpCode::Halt as u16).to_le_bytes());
|
||||
|
||||
let mut vm = VirtualMachine::new(rom, vec![]);
|
||||
let mut native = MockNative;
|
||||
let mut hw = MockHardware;
|
||||
|
||||
vm.step(&mut native, &mut hw).unwrap();
|
||||
assert_eq!(vm.peek().unwrap(), &Value::Float(3.14));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_push_bool_immediate() {
|
||||
let mut rom = Vec::new();
|
||||
// True
|
||||
rom.extend_from_slice(&(OpCode::PushBool as u16).to_le_bytes());
|
||||
rom.push(1);
|
||||
// False
|
||||
rom.extend_from_slice(&(OpCode::PushBool as u16).to_le_bytes());
|
||||
rom.push(0);
|
||||
rom.extend_from_slice(&(OpCode::Halt as u16).to_le_bytes());
|
||||
|
||||
let mut vm = VirtualMachine::new(rom, vec![]);
|
||||
let mut native = MockNative;
|
||||
let mut hw = MockHardware;
|
||||
|
||||
vm.step(&mut native, &mut hw).unwrap(); // Push true
|
||||
assert_eq!(vm.peek().unwrap(), &Value::Boolean(true));
|
||||
vm.step(&mut native, &mut hw).unwrap(); // Push false
|
||||
assert_eq!(vm.peek().unwrap(), &Value::Boolean(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_push_const_string() {
|
||||
let mut rom = Vec::new();
|
||||
rom.extend_from_slice(&(OpCode::PushConst as u16).to_le_bytes());
|
||||
rom.extend_from_slice(&0u32.to_le_bytes());
|
||||
rom.extend_from_slice(&(OpCode::Halt as u16).to_le_bytes());
|
||||
|
||||
let cp = vec![Value::String("hello".into())];
|
||||
let mut vm = VirtualMachine::new(rom, cp);
|
||||
let mut native = MockNative;
|
||||
let mut hw = MockHardware;
|
||||
|
||||
vm.step(&mut native, &mut hw).unwrap();
|
||||
assert_eq!(vm.peek().unwrap(), &Value::String("hello".into()));
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user