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, MUL = 0x0001, DIV = 0x0002, MOD = 0x0003, INEG = 0x0004, AND = 0x0005, OR = 0x0006, INV = 0x0007, NOT = 0x0008, XOR = 0x0009, SHL = 0x000a, SHR = 0x000b, CMPEQ = 0x1000, CMPLT = 0x1001, JMP = 0x1100, JZ = 0x1101, JNZ = 0x1102, LOAD = 0x2000, REGCOPY = 0x2001, STOREIMM64 = 0x2100, STOREIMM32 = 0x2101, MEMCOPY = 0x2200, STORE = 0x2201, HALT = 0xF000, NOP = 0xF001, } pub fn inst_len(op: InstOp) -> usize { match op { // 2 bytes HALT | NOP => 2, // 4 bytes ADD | MUL | DIV | INEG | INV | NOT | MOD | AND | OR | XOR | SHL | SHR | CMPEQ | CMPLT | JMP | JZ | JNZ | LOAD | REGCOPY | MEMCOPY | STORE => 4, // Immediates - 4+ bytes STOREIMM64 => 16, STOREIMM32 => 8, _ => panic!("unknown instruction op 0x{:04x}", op), } }