2020-02-17 16:22:15 -05:00
|
|
|
use crate::vm::{addr::Addr, reg::Reg};
|
2020-02-17 16:15:06 -05:00
|
|
|
|
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
|
|
|
$(
|
2020-02-25 13:46:38 -05:00
|
|
|
#[allow(dead_code)]
|
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,
|
2020-02-25 13:44:03 -05:00
|
|
|
IDIV = 0x0004,
|
|
|
|
|
MOD = 0x0005,
|
|
|
|
|
AND = 0x0006,
|
|
|
|
|
OR = 0x0007,
|
|
|
|
|
XOR = 0x0008,
|
|
|
|
|
SHL = 0x0009,
|
|
|
|
|
SHR = 0x000a,
|
|
|
|
|
INEG = 0x000b,
|
|
|
|
|
INV = 0x000c,
|
|
|
|
|
NOT = 0x000d,
|
2020-02-17 16:15:06 -05:00
|
|
|
CMPEQ = 0x1000,
|
|
|
|
|
CMPLT = 0x1001,
|
|
|
|
|
JMP = 0x1002,
|
|
|
|
|
JZ = 0x1003,
|
|
|
|
|
JNZ = 0x1004,
|
|
|
|
|
MOV = 0x2000,
|
|
|
|
|
HALT = 0xF000,
|
|
|
|
|
NOP = 0xF001,
|
|
|
|
|
DUMP = 0xF002,
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-18 17:44:41 -05:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
2020-02-17 16:15:06 -05:00
|
|
|
pub enum Inst {
|
|
|
|
|
Add(Dest, Source),
|
|
|
|
|
Sub(Dest, Source),
|
|
|
|
|
Mul(Dest, Source),
|
|
|
|
|
Div(Dest, Source),
|
2020-02-25 13:44:03 -05:00
|
|
|
IDiv(Dest, Source),
|
2020-02-17 16:15:06 -05:00
|
|
|
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,
|
2020-02-25 13:44:03 -05:00
|
|
|
Inst::IDiv(_, _) => IDIV,
|
2020-02-17 16:15:06 -05:00
|
|
|
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-18 17:44:41 -05:00
|
|
|
|
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
|
match self {
|
|
|
|
|
Inst::Add(dest, source)
|
|
|
|
|
| Inst::Sub(dest, source)
|
|
|
|
|
| Inst::Mul(dest, source)
|
|
|
|
|
| Inst::Div(dest, source)
|
2020-02-25 13:44:03 -05:00
|
|
|
| Inst::IDiv(dest, source)
|
2020-02-18 17:44:41 -05:00
|
|
|
| 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 }
|
|
|
|
|
}
|
|
|
|
|
}
|
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),
|
2020-02-25 12:07:24 -05:00
|
|
|
RegAddr64(Reg),
|
|
|
|
|
RegAddr32(Reg),
|
|
|
|
|
RegAddr16(Reg),
|
|
|
|
|
RegAddr8(Reg),
|
2020-02-17 16:15:06 -05:00
|
|
|
Reg(Reg),
|
|
|
|
|
Imm(u64),
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-18 17:44:41 -05:00
|
|
|
impl Source {
|
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
|
match self {
|
|
|
|
|
Source::Addr64(_) | Source::Addr32(_) | Source::Addr16(_) | Source::Addr8(_) => 8,
|
2020-02-25 12:07:24 -05:00
|
|
|
Source::RegAddr64(_) | Source::RegAddr32(_) | Source::RegAddr16(_) | Source::RegAddr8(_) => 1,
|
2020-02-18 17:44:41 -05:00
|
|
|
Source::Reg(_) => 1,
|
|
|
|
|
Source::Imm(_) => 8,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-17 16:15:06 -05:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
|
pub enum Dest {
|
|
|
|
|
Addr64(Addr),
|
|
|
|
|
Addr32(Addr),
|
|
|
|
|
Addr16(Addr),
|
|
|
|
|
Addr8(Addr),
|
2020-02-25 12:07:24 -05:00
|
|
|
RegAddr64(Reg),
|
|
|
|
|
RegAddr32(Reg),
|
|
|
|
|
RegAddr16(Reg),
|
|
|
|
|
RegAddr8(Reg),
|
2020-02-17 16:15:06 -05:00
|
|
|
Reg(Reg),
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-18 17:44:41 -05:00
|
|
|
impl Dest {
|
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
|
match self {
|
|
|
|
|
Dest::Addr64(_) | Dest::Addr32(_) | Dest::Addr16(_) | Dest::Addr8(_) => 8,
|
2020-02-25 12:07:24 -05:00
|
|
|
Dest::RegAddr64(_) | Dest::RegAddr32(_) | Dest::RegAddr16(_) | Dest::RegAddr8(_) => 1,
|
2020-02-18 17:44:41 -05:00
|
|
|
Dest::Reg(_) => 1,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-25 12:07:24 -05:00
|
|
|
// TODO : make this an enum
|
|
|
|
|
|
2020-02-17 16:15:06 -05:00
|
|
|
pub const DEST_ADDR64: u8 = 0b0000;
|
|
|
|
|
pub const DEST_ADDR32: u8 = 0b0001;
|
|
|
|
|
pub const DEST_ADDR16: u8 = 0b0010;
|
|
|
|
|
pub const DEST_ADDR8: u8 = 0b0011;
|
2020-02-25 12:07:24 -05:00
|
|
|
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;
|
2020-02-17 16:15:06 -05:00
|
|
|
|
|
|
|
|
pub const SOURCE_ADDR64: u8 = 0b0000;
|
|
|
|
|
pub const SOURCE_ADDR32: u8 = 0b0001;
|
|
|
|
|
pub const SOURCE_ADDR16: u8 = 0b0010;
|
|
|
|
|
pub const SOURCE_ADDR8: u8 = 0b0011;
|
2020-02-25 12:07:24 -05:00
|
|
|
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;
|