2020-02-17 16:15:06 -05:00
|
|
|
use crate::vm::{common::Addr, reg::Reg};
|
|
|
|
|
|
2020-02-03 17:56:32 -05:00
|
|
|
macro_rules! instructions {
|
|
|
|
|
{
|
|
|
|
|
$($variant:ident = $value:expr),* $(,)?
|
|
|
|
|
} => {
|
2020-01-25 19:17:39 -05:00
|
|
|
|
2020-02-03 17:56:32 -05:00
|
|
|
$(
|
|
|
|
|
pub const $variant: InstOp = $value;
|
|
|
|
|
)*
|
2020-02-09 15:43:07 -05:00
|
|
|
|
|
|
|
|
pub fn inst_name(op: InstOp) -> Option<&'static str> {
|
|
|
|
|
match op {
|
|
|
|
|
$(
|
|
|
|
|
$value => Some(stringify!($variant)),
|
|
|
|
|
)*
|
|
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-03 17:56:32 -05:00
|
|
|
};
|
2020-01-25 19:17:39 -05:00
|
|
|
}
|
2020-02-09 13:04:56 -05:00
|
|
|
pub type InstOp = u16;
|
|
|
|
|
|
2020-02-03 17:56:32 -05:00
|
|
|
instructions! {
|
2020-02-17 16:15:06 -05:00
|
|
|
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,
|
2020-02-03 17:56:32 -05:00
|
|
|
}
|
2020-02-09 13:04:56 -05:00
|
|
|
|
2020-02-17 16:15:06 -05:00
|
|
|
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,
|
|
|
|
|
}
|
2020-02-09 13:04:56 -05:00
|
|
|
}
|
|
|
|
|
}
|
2020-02-17 16:15:06 -05:00
|
|
|
|
|
|
|
|
#[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;
|