use crate::vm::{common::Addr, reg::Reg}; macro_rules! instructions { { $($variant:ident = $value:expr),* $(,)? } => { $( pub const $variant: InstOp = $value; )* pub fn inst_name(op: InstOp) -> Option<&'static str> { match op { $( $value => Some(stringify!($variant)), )* _ => None, } } }; } pub type InstOp = u16; instructions! { ADD = 0x0000, SUB = 0x0001, MUL = 0x0002, DIV = 0x0003, MOD = 0x0004, AND = 0x0005, OR = 0x0006, XOR = 0x0007, SHL = 0x0008, SHR = 0x0009, INEG = 0x000a, INV = 0x000b, NOT = 0x000c, CMPEQ = 0x1000, CMPLT = 0x1001, JMP = 0x1002, JZ = 0x1003, JNZ = 0x1004, MOV = 0x2000, HALT = 0xF000, NOP = 0xF001, DUMP = 0xF002, } pub enum Inst { Add(Dest, Source), Sub(Dest, Source), Mul(Dest, Source), Div(Dest, Source), Mod(Dest, Source), And(Dest, Source), Or(Dest, Source), Xor(Dest, Source), Shl(Dest, Source), Shr(Dest, Source), INeg(Dest, Source), Inv(Dest, Source), Not(Dest, Source), CmpEq(Source, Source), CmpLt(Source, Source), Jmp(Source), Jz(Source), Jnz(Source), Mov(Dest, Source), Halt, Nop, Dump, } impl Inst { pub fn op(&self) -> InstOp { match self { Inst::Add(_, _) => ADD, Inst::Sub(_, _) => SUB, Inst::Mul(_, _) => MUL, Inst::Div(_, _) => DIV, Inst::Mod(_, _) => MOD, Inst::And(_, _) => AND, Inst::Or(_, _) => OR, Inst::Xor(_, _) => XOR, Inst::Shl(_, _) => SHL, Inst::Shr(_, _) => SHL, Inst::INeg(_, _) => INEG, Inst::Inv(_, _) => INV, Inst::Not(_, _) => NOT, Inst::CmpEq(_, _) => CMPEQ, Inst::CmpLt(_, _) => CMPLT, Inst::Jmp(_) => JMP, Inst::Jz(_) => JZ, Inst::Jnz(_) => JNZ, Inst::Mov(_, _) => MOV, Inst::Halt => HALT, Inst::Nop => NOP, Inst::Dump => DUMP, } } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Source { Addr64(Addr), Addr32(Addr), Addr16(Addr), Addr8(Addr), Reg(Reg), Imm(u64), } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Dest { Addr64(Addr), Addr32(Addr), Addr16(Addr), Addr8(Addr), Reg(Reg), } pub const DEST_ADDR64: u8 = 0b0000; pub const DEST_ADDR32: u8 = 0b0001; pub const DEST_ADDR16: u8 = 0b0010; pub const DEST_ADDR8: u8 = 0b0011; pub const DEST_REG: u8 = 0b0100; pub const SOURCE_ADDR64: u8 = 0b0000; pub const SOURCE_ADDR32: u8 = 0b0001; pub const SOURCE_ADDR16: u8 = 0b0010; pub const SOURCE_ADDR8: u8 = 0b0011; pub const SOURCE_REG: u8 = 0b0100; pub const SOURCE_IMM64: u8 = 0b0101; pub const SOURCE_IMM32: u8 = 0b0110; pub const SOURCE_IMM16: u8 = 0b0111; pub const SOURCE_IMM8: u8 = 0b1000;