Files
rasp/src/vm/inst.rs

209 lines
5.3 KiB
Rust
Raw Normal View History

use crate::vm::{addr::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,
IDIV = 0x0004,
MOD = 0x0005,
AND = 0x0006,
OR = 0x0007,
XOR = 0x0008,
SHL = 0x0009,
SHR = 0x000a,
INEG = 0x000b,
INV = 0x000c,
NOT = 0x000d,
CMPEQ = 0x1000,
CMPLT = 0x1001,
JMP = 0x1002,
JZ = 0x1003,
JNZ = 0x1004,
MOV = 0x2000,
HALT = 0xF000,
NOP = 0xF001,
DUMP = 0xF002,
}
#[derive(Debug, Clone, Copy)]
pub enum Inst {
Add(Dest, Source),
Sub(Dest, Source),
Mul(Dest, Source),
Div(Dest, Source),
IDiv(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::IDiv(_, _) => IDIV,
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,
}
}
pub fn len(&self) -> usize {
match self {
Inst::Add(dest, source)
| Inst::Sub(dest, source)
| Inst::Mul(dest, source)
| Inst::Div(dest, source)
| Inst::IDiv(dest, source)
| Inst::Mod(dest, source)
| Inst::And(dest, source)
| Inst::Or(dest, source)
| Inst::Xor(dest, source)
| Inst::Shl(dest, source)
| Inst::Shr(dest, source)
| Inst::INeg(dest, source)
| Inst::Inv(dest, source)
| Inst::Not(dest, source)
| Inst::Mov(dest, source) => { 3 + dest.len() + source.len() }
Inst::CmpEq(s1, s2)
| Inst::CmpLt(s1, s2) => { 3 + s1.len() + s2.len() }
Inst::Jmp(v)
| Inst::Jz(v)
| Inst::Jnz(v) => { 3 + v.len() }
Inst::Halt
| Inst::Nop
| Inst::Dump => { 2 }
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Source {
Addr64(Addr),
Addr32(Addr),
Addr16(Addr),
Addr8(Addr),
RegAddr64(Reg),
RegAddr32(Reg),
RegAddr16(Reg),
RegAddr8(Reg),
Reg(Reg),
Imm(u64),
}
impl Source {
pub fn len(&self) -> usize {
match self {
Source::Addr64(_) | Source::Addr32(_) | Source::Addr16(_) | Source::Addr8(_) => 8,
Source::RegAddr64(_) | Source::RegAddr32(_) | Source::RegAddr16(_) | Source::RegAddr8(_) => 1,
Source::Reg(_) => 1,
Source::Imm(_) => 8,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Dest {
Addr64(Addr),
Addr32(Addr),
Addr16(Addr),
Addr8(Addr),
RegAddr64(Reg),
RegAddr32(Reg),
RegAddr16(Reg),
RegAddr8(Reg),
Reg(Reg),
}
impl Dest {
pub fn len(&self) -> usize {
match self {
Dest::Addr64(_) | Dest::Addr32(_) | Dest::Addr16(_) | Dest::Addr8(_) => 8,
Dest::RegAddr64(_) | Dest::RegAddr32(_) | Dest::RegAddr16(_) | Dest::RegAddr8(_) => 1,
Dest::Reg(_) => 1,
}
}
}
// TODO : make this an enum
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_ADDR64: u8 = 0b0100;
pub const DEST_REG_ADDR32: u8 = 0b0101;
pub const DEST_REG_ADDR16: u8 = 0b0110;
pub const DEST_REG_ADDR8: u8 = 0b0111;
/* immediates - not used, invalid */
pub const DEST_REG: u8 = 0b1100;
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_ADDR64: u8 = 0b0100;
pub const SOURCE_REG_ADDR32: u8 = 0b0101;
pub const SOURCE_REG_ADDR16: u8 = 0b0110;
pub const SOURCE_REG_ADDR8: u8 = 0b0111;
pub const SOURCE_IMM64: u8 = 0b1000;
pub const SOURCE_IMM32: u8 = 0b1001;
pub const SOURCE_IMM16: u8 = 0b1010;
pub const SOURCE_IMM8: u8 = 0b1011;
pub const SOURCE_REG: u8 = 0b1100;