add inline opcodes

This commit is contained in:
Nilton Constantino 2026-01-20 08:37:47 +00:00
parent 7e99eed6b4
commit 0ea26f4efd
No known key found for this signature in database
3 changed files with 144 additions and 0 deletions

View File

@ -13,6 +13,9 @@ pub enum OpCode {
Pop = 0x11, Pop = 0x11,
Dup = 0x12, Dup = 0x12,
Swap = 0x13, Swap = 0x13,
PushI64 = 0x14,
PushF64 = 0x15,
PushBool = 0x16,
// 6.3 Arithmetic // 6.3 Arithmetic
Add = 0x20, Add = 0x20,
@ -64,6 +67,9 @@ impl TryFrom<u16> for OpCode {
0x11 => Ok(OpCode::Pop), 0x11 => Ok(OpCode::Pop),
0x12 => Ok(OpCode::Dup), 0x12 => Ok(OpCode::Dup),
0x13 => Ok(OpCode::Swap), 0x13 => Ok(OpCode::Swap),
0x14 => Ok(OpCode::PushI64),
0x15 => Ok(OpCode::PushF64),
0x16 => Ok(OpCode::PushBool),
0x20 => Ok(OpCode::Add), 0x20 => Ok(OpCode::Add),
0x21 => Ok(OpCode::Sub), 0x21 => Ok(OpCode::Sub),
0x22 => Ok(OpCode::Mul), 0x22 => Ok(OpCode::Mul),
@ -104,6 +110,9 @@ impl OpCode {
OpCode::Pop => 1, OpCode::Pop => 1,
OpCode::Dup => 1, OpCode::Dup => 1,
OpCode::Swap => 1, OpCode::Swap => 1,
OpCode::PushI64 => 2,
OpCode::PushF64 => 2,
OpCode::PushBool => 2,
OpCode::Add => 2, OpCode::Add => 2,
OpCode::Sub => 2, OpCode::Sub => 2,
OpCode::Mul => 4, OpCode::Mul => 4,

View File

@ -312,6 +312,18 @@ impl VirtualMachine {
let val = self.program.constant_pool.get(idx).cloned().ok_or("Invalid constant index")?; let val = self.program.constant_pool.get(idx).cloned().ok_or("Invalid constant index")?;
self.push(val); 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 => { OpCode::Pop => {
self.pop()?; self.pop()?;
} }
@ -534,6 +546,26 @@ impl VirtualMachine {
Ok(u32::from_le_bytes(bytes)) 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> { fn read_u16(&mut self) -> Result<u16, String> {
if self.pc + 2 > self.program.rom.len() { if self.pc + 2 > self.program.rom.len() {
return Err("Unexpected end of ROM".into()); return Err("Unexpected end of ROM".into());
@ -546,6 +578,15 @@ impl VirtualMachine {
Ok(u16::from_le_bytes(bytes)) 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) { pub fn push(&mut self, val: Value) {
self.operand_stack.push(val); self.operand_stack.push(val);
} }
@ -579,3 +620,97 @@ impl VirtualMachine {
Ok(()) 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()));
}
}