2026-03-24 13:40:11 +00:00

157 lines
4.2 KiB
Rust

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
pub enum OpCode {
// 6.1 Controle de Execução
Nop = 0x00,
Halt = 0x01,
Jmp = 0x02,
JmpIfFalse = 0x03,
// 6.2 Pilha
PushConst = 0x10,
Pop = 0x11,
Dup = 0x12,
Swap = 0x13,
// 6.3 Aritmética
Add = 0x20,
Sub = 0x21,
Mul = 0x22,
Div = 0x23,
// 6.4 Comparação e Lógica
Eq = 0x30,
Neq = 0x31,
Lt = 0x32,
Gt = 0x33,
And = 0x34,
Or = 0x35,
Not = 0x36,
// 6.5 Variáveis
GetGlobal = 0x40,
SetGlobal = 0x41,
GetLocal = 0x42,
SetLocal = 0x43,
// 6.6 Funções
Call = 0x50,
Ret = 0x51,
PushScope = 0x52,
PopScope = 0x53,
// 6.7 Heap
Alloc = 0x60,
LoadRef = 0x61,
StoreRef = 0x62,
// 6.8 Periféricos e Sistema
Syscall = 0x70,
FrameSync = 0x80,
}
impl TryFrom<u16> for OpCode {
type Error = String;
fn try_from(value: u16) -> Result<Self, Self::Error> {
match value {
0x00 => Ok(OpCode::Nop),
0x01 => Ok(OpCode::Halt),
0x02 => Ok(OpCode::Jmp),
0x03 => Ok(OpCode::JmpIfFalse),
0x10 => Ok(OpCode::PushConst),
0x11 => Ok(OpCode::Pop),
0x12 => Ok(OpCode::Dup),
0x13 => Ok(OpCode::Swap),
0x20 => Ok(OpCode::Add),
0x21 => Ok(OpCode::Sub),
0x22 => Ok(OpCode::Mul),
0x23 => Ok(OpCode::Div),
0x30 => Ok(OpCode::Eq),
0x31 => Ok(OpCode::Neq),
0x32 => Ok(OpCode::Lt),
0x33 => Ok(OpCode::Gt),
0x34 => Ok(OpCode::And),
0x35 => Ok(OpCode::Or),
0x36 => Ok(OpCode::Not),
0x40 => Ok(OpCode::GetGlobal),
0x41 => Ok(OpCode::SetGlobal),
0x42 => Ok(OpCode::GetLocal),
0x43 => Ok(OpCode::SetLocal),
0x50 => Ok(OpCode::Call),
0x51 => Ok(OpCode::Ret),
0x52 => Ok(OpCode::PushScope),
0x53 => Ok(OpCode::PopScope),
0x60 => Ok(OpCode::Alloc),
0x61 => Ok(OpCode::LoadRef),
0x62 => Ok(OpCode::StoreRef),
0x70 => Ok(OpCode::Syscall),
0x80 => Ok(OpCode::FrameSync),
_ => Err(format!("Invalid OpCode: 0x{:04X}", value)),
}
}
}
impl OpCode {
pub fn cycles(&self) -> u64 {
match self {
OpCode::Nop => 1,
OpCode::Halt => 1,
OpCode::Jmp => 2,
OpCode::JmpIfFalse => 3,
OpCode::PushConst => 2,
OpCode::Pop => 1,
OpCode::Dup => 1,
OpCode::Swap => 1,
OpCode::Add => 2,
OpCode::Sub => 2,
OpCode::Mul => 4,
OpCode::Div => 6,
OpCode::Eq => 2,
OpCode::Neq => 2,
OpCode::Lt => 2,
OpCode::Gt => 2,
OpCode::And => 2,
OpCode::Or => 2,
OpCode::Not => 1,
OpCode::GetGlobal => 3,
OpCode::SetGlobal => 3,
OpCode::GetLocal => 2,
OpCode::SetLocal => 2,
OpCode::Call => 5,
OpCode::Ret => 4,
OpCode::PushScope => 3,
OpCode::PopScope => 3,
OpCode::Alloc => 10,
OpCode::LoadRef => 3,
OpCode::StoreRef => 3,
OpCode::Syscall => 1, // Variável, mas vamos usar 1 como base ou definir via ID
OpCode::FrameSync => 1,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_opcode_decoding() {
assert_eq!(OpCode::try_from(0x00).unwrap(), OpCode::Nop);
assert_eq!(OpCode::try_from(0x10).unwrap(), OpCode::PushConst);
assert_eq!(OpCode::try_from(0x20).unwrap(), OpCode::Add);
assert_eq!(OpCode::try_from(0x70).unwrap(), OpCode::Syscall);
assert_eq!(OpCode::try_from(0x80).unwrap(), OpCode::FrameSync);
assert!(OpCode::try_from(0xFFFF).is_err());
}
#[test]
fn test_opcode_cycles() {
assert_eq!(OpCode::Nop.cycles(), 1);
assert_eq!(OpCode::Add.cycles(), 2);
assert_eq!(OpCode::Mul.cycles(), 4);
assert_eq!(OpCode::Div.cycles(), 6);
assert_eq!(OpCode::Alloc.cycles(), 10);
}
}