Update registers to be constants, add instructions to parser
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
157
src/vm/reg.rs
157
src/vm/reg.rs
@@ -1,83 +1,94 @@
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[allow(dead_code)]
|
||||
pub enum Reg {
|
||||
macro_rules! registers {
|
||||
{
|
||||
$($variant:ident = $value:expr),* $(,)?
|
||||
} => {
|
||||
pub type Reg = u8;
|
||||
|
||||
$(
|
||||
#[allow(dead_code)]
|
||||
pub const $variant: Reg = $value;
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
registers! {
|
||||
// https://crates.io/crates/packed_struct
|
||||
// TODO : check this muffugin shit out!!
|
||||
|
||||
/// Instruction pointer
|
||||
Ip = 0,
|
||||
// Instruction pointer
|
||||
IP = 0,
|
||||
|
||||
/// Stack pointer
|
||||
Sp,
|
||||
// Stack pointer
|
||||
SP = 1,
|
||||
|
||||
/// Frame pointer
|
||||
Fp,
|
||||
// Frame pointer
|
||||
FP = 2,
|
||||
|
||||
/// Flags
|
||||
Flags,
|
||||
// Flags
|
||||
FLAGS = 3,
|
||||
|
||||
Unused00,
|
||||
Unused01,
|
||||
Unused02,
|
||||
Unused03,
|
||||
Unused04,
|
||||
Unused05,
|
||||
Unused06,
|
||||
Unused07,
|
||||
Unused08,
|
||||
UNUSED00 = 4,
|
||||
UNUSED01 = 5,
|
||||
UNUSED02 = 6,
|
||||
UNUSED03 = 7,
|
||||
UNUSED04 = 8,
|
||||
UNUSED05 = 9,
|
||||
UNUSED06 = 10,
|
||||
UNUSED07 = 11,
|
||||
UNUSED08 = 12,
|
||||
|
||||
/// General status code
|
||||
Status,
|
||||
// General status code
|
||||
STATUS = 13,
|
||||
|
||||
R00,
|
||||
R01,
|
||||
R02,
|
||||
R03,
|
||||
R04,
|
||||
R05,
|
||||
R06,
|
||||
R07,
|
||||
R08,
|
||||
R09,
|
||||
R10,
|
||||
R11,
|
||||
R12,
|
||||
R13,
|
||||
R14,
|
||||
R15,
|
||||
R16,
|
||||
R17,
|
||||
R18,
|
||||
R19,
|
||||
R20,
|
||||
R21,
|
||||
R22,
|
||||
R23,
|
||||
R24,
|
||||
R25,
|
||||
R26,
|
||||
R27,
|
||||
R28,
|
||||
R29,
|
||||
R30,
|
||||
R31,
|
||||
R32,
|
||||
R33,
|
||||
R34,
|
||||
R35,
|
||||
R36,
|
||||
R37,
|
||||
R38,
|
||||
R39,
|
||||
R40,
|
||||
R41,
|
||||
R42,
|
||||
R43,
|
||||
R44,
|
||||
R45,
|
||||
R46,
|
||||
R47,
|
||||
R48,
|
||||
R49,
|
||||
R00 = 14,
|
||||
R01 = 15,
|
||||
R02 = 16,
|
||||
R03 = 17,
|
||||
R04 = 18,
|
||||
R05 = 19,
|
||||
R06 = 20,
|
||||
R07 = 21,
|
||||
R08 = 22,
|
||||
R09 = 23,
|
||||
R10 = 24,
|
||||
R11 = 25,
|
||||
R12 = 26,
|
||||
R13 = 27,
|
||||
R14 = 28,
|
||||
R15 = 29,
|
||||
R16 = 30,
|
||||
R17 = 31,
|
||||
R18 = 32,
|
||||
R19 = 33,
|
||||
R20 = 34,
|
||||
R21 = 35,
|
||||
R22 = 36,
|
||||
R23 = 37,
|
||||
R24 = 38,
|
||||
R25 = 39,
|
||||
R26 = 40,
|
||||
R27 = 41,
|
||||
R28 = 42,
|
||||
R29 = 43,
|
||||
R30 = 44,
|
||||
R31 = 45,
|
||||
R32 = 46,
|
||||
R33 = 47,
|
||||
R34 = 48,
|
||||
R35 = 49,
|
||||
R36 = 50,
|
||||
R37 = 51,
|
||||
R38 = 52,
|
||||
R39 = 53,
|
||||
R40 = 54,
|
||||
R41 = 55,
|
||||
R42 = 56,
|
||||
R43 = 57,
|
||||
R44 = 58,
|
||||
R45 = 59,
|
||||
R46 = 60,
|
||||
R47 = 61,
|
||||
R48 = 62,
|
||||
R49 = 63,
|
||||
LAST_REG = R49,
|
||||
}
|
||||
|
||||
@@ -1,42 +1,15 @@
|
||||
use crate::vm::{inst::Inst, reg::Reg};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Line {
|
||||
Section(Section),
|
||||
Directive(Directive),
|
||||
Inst(Inst),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Section {
|
||||
Code,
|
||||
Data,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum InstOp {
|
||||
Add,
|
||||
Mul,
|
||||
Div,
|
||||
Neg,
|
||||
And,
|
||||
Or,
|
||||
Xor,
|
||||
Shl,
|
||||
Shr,
|
||||
CmpEq,
|
||||
CmpLt,
|
||||
Jz,
|
||||
Jnz,
|
||||
Load,
|
||||
Store,
|
||||
StoreImm,
|
||||
Copy,
|
||||
Nop,
|
||||
Halt,
|
||||
LabelDef(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Inst {
|
||||
pub op: InstOp,
|
||||
pub args: Vec<Value>,
|
||||
pub enum Directive {
|
||||
Section(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
||||
@@ -1,73 +1,79 @@
|
||||
use std::str::FromStr;
|
||||
use crate::vm::{
|
||||
syn::ast::*,
|
||||
reg::*,
|
||||
inst::Inst,
|
||||
};
|
||||
|
||||
grammar;
|
||||
|
||||
// TODO : instkind
|
||||
InstOp: InstOp = {
|
||||
"add" => InstOp::Add,
|
||||
"mul" => InstOp::Mul,
|
||||
"div" => InstOp::Div,
|
||||
"neg" => InstOp::Neg,
|
||||
"and" => InstOp::And,
|
||||
"or" => InstOp::Or,
|
||||
"xor" => InstOp::Xor,
|
||||
"shl" => InstOp::Shl,
|
||||
"shr" => InstOp::Shr,
|
||||
"cmpeq" => InstOp::CmpEq,
|
||||
"cmplt" => InstOp::CmpLt,
|
||||
"jz" => InstOp::Jz,
|
||||
"jnz" => InstOp::Jnz,
|
||||
"load" => InstOp::Load,
|
||||
"store" => InstOp::Store,
|
||||
"storeimm" => InstOp::StoreImm,
|
||||
"copy" => InstOp::Copy,
|
||||
"nop" => InstOp::Nop,
|
||||
"halt" => InstOp::Halt,
|
||||
}
|
||||
|
||||
LabelDef: String = {
|
||||
<Label> ":" => <>
|
||||
}
|
||||
|
||||
pub Label: String = {
|
||||
Value: Value = {
|
||||
<Label> => Value::Label(<>),
|
||||
<Number> => Value::Number(<>),
|
||||
}
|
||||
|
||||
Label: String = {
|
||||
"[a-zA-Z]+" => String::from(<>),
|
||||
}
|
||||
|
||||
pub Section: Section = {
|
||||
".code" => Section::Code,
|
||||
".data" => Section::Data,
|
||||
Number: u64 = {
|
||||
<s:r"\$[0-9]+"> => u64::from_str(s).unwrap(),
|
||||
<s:r"\$0x[0-9a-fA-F]+"> => u64::from_str_radix(s, 16).unwrap()
|
||||
}
|
||||
|
||||
pub Inst: Inst = {
|
||||
<op:InstOp> <head:Value> <tail:("," <Value>)+> => {
|
||||
Inst {
|
||||
op,
|
||||
args: {
|
||||
let mut tail = tail;
|
||||
tail.insert(0, head);
|
||||
tail
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
<op:InstOp> <head:Value?> => {
|
||||
Inst { op, args: if let Some(head) = head { vec![head] } else { vec![] } }
|
||||
Reg: Reg = {
|
||||
"%ip" => IP,
|
||||
"%sp" => SP,
|
||||
"%fp" => FP,
|
||||
"%flags" => FLAGS,
|
||||
"%status" => STATUS,
|
||||
"%r[0-9]{2}" => {
|
||||
let offset = (&<>[2..]).parse::<u8>().unwrap();
|
||||
let reg = R00 + offset;
|
||||
assert!(reg < LAST_REG, "invalid register");
|
||||
reg
|
||||
}
|
||||
}
|
||||
|
||||
pub Value: Value = {
|
||||
<Number> => Value::Number(<>),
|
||||
<Label> => Value::Label(<>),
|
||||
Inst: Inst = {
|
||||
"add" <d:Reg> "," <s:Reg> => Inst::Add(d, s),
|
||||
"mul" <d:Reg> "," <s:Reg> => Inst::Mul(d, s),
|
||||
"div" <d:Reg> "," <s:Reg> =>Inst::Div(d, s),
|
||||
"mod" <d:Reg> "," <s:Reg> => Inst::Mod(d, s),
|
||||
"ineg" <d:Reg> => Inst::INeg(d),
|
||||
"and" <d:Reg> "," <s:Reg> => Inst::And(d, s),
|
||||
"or" <d:Reg> "," <s:Reg> => Inst::Or(d, s),
|
||||
"xor" <d:Reg> "," <s:Reg> => Inst::Xor(d, s),
|
||||
"shl" <d:Reg> "," <s:Reg> => Inst::Shl(d, s),
|
||||
"shr" <d:Reg> "," <s:Reg> => Inst::Shr(d, s),
|
||||
"cmpeq" <d:Reg> "," <s:Reg> => Inst::CmpEq(d, s),
|
||||
"cmplt" <d:Reg> "," <s:Reg> => Inst::CmpLt(d, s),
|
||||
"jz" <d:Reg> => Inst::Jz(d),
|
||||
"jnz" <d:Reg> => Inst::Jnz(d),
|
||||
"load" <d:Reg> "," <s:Reg> => Inst::Load(d, s),
|
||||
"store" <d:Reg> "," <s:Reg> => Inst::Store(d, s),
|
||||
"storeimm" <d:Reg> "," <s:Number> => {
|
||||
if s > u32::max_value() as u64 {
|
||||
eprintln!("WARNING: number {} is too large. It will be truncated to 32 bits.", s);
|
||||
}
|
||||
Inst::StoreImm(d, (s & 0xFFFF_FFFF) as u32)
|
||||
},
|
||||
"memcopy" <d:Reg> "," <s:Reg> => Inst::MemCopy(d, s),
|
||||
"regcopy" <d:Reg> "," <s:Reg> => Inst::RegCopy(d, s),
|
||||
"nop" => Inst::Nop,
|
||||
"halt" => Inst::Halt,
|
||||
}
|
||||
|
||||
pub Number: u64 = {
|
||||
<s:r"[0-9]+"> => u64::from_str(s).unwrap()
|
||||
Directive: Directive = {
|
||||
".section" <s:Label> => Directive::Section(s.to_string()),
|
||||
}
|
||||
|
||||
pub Line: Line = {
|
||||
<Section> => Line::Section(<>),
|
||||
<Directive> => Line::Directive(<>),
|
||||
<Inst> => Line::Inst(<>),
|
||||
<LabelDef> => Line::LabelDef(<>),
|
||||
}
|
||||
|
||||
12
src/vm/vm.rs
12
src/vm/vm.rs
@@ -34,7 +34,7 @@ impl Vm {
|
||||
pub fn tick(&mut self) {
|
||||
let inst = self.decode();
|
||||
let ip = self.ip();
|
||||
self.set_reg(Reg::Ip, ip + 1);
|
||||
self.set_reg(IP, ip + 1);
|
||||
self.execute(inst);
|
||||
}
|
||||
|
||||
@@ -100,13 +100,13 @@ impl Vm {
|
||||
}
|
||||
|
||||
pub fn ip(&self) -> Word {
|
||||
self.get_reg(Reg::Ip)
|
||||
self.get_reg(IP)
|
||||
}
|
||||
|
||||
pub fn flags(&self) -> Flags {
|
||||
// this is safe because it's OK if there are random bits flipped - this shouldn't happen
|
||||
// anyway, but if it does, they're ignored
|
||||
unsafe { Flags::from_bits_unchecked(self.get_reg(Reg::Flags)) }
|
||||
unsafe { Flags::from_bits_unchecked(self.get_reg(FLAGS)) }
|
||||
}
|
||||
|
||||
pub fn insert_flags(&mut self, flags: Flags) {
|
||||
@@ -122,7 +122,7 @@ impl Vm {
|
||||
}
|
||||
|
||||
pub fn set_flags(&mut self, flags: Flags) {
|
||||
self.set_reg(Reg::Flags, flags.bits());
|
||||
self.set_reg(FLAGS, flags.bits());
|
||||
}
|
||||
|
||||
pub fn map_flags<F>(&mut self, mapping: F)
|
||||
@@ -193,13 +193,13 @@ impl Vm {
|
||||
Inst::Jz(r1) => {
|
||||
if !self.flags().contains(Flags::COMPARE) {
|
||||
let w1 = self.get_reg(r1);
|
||||
self.set_reg(Reg::Ip, w1);
|
||||
self.set_reg(IP, w1);
|
||||
}
|
||||
}
|
||||
Inst::Jnz(r1) => {
|
||||
if self.flags().contains(Flags::COMPARE) {
|
||||
let w1 = self.get_reg(r1);
|
||||
self.set_reg(Reg::Ip, w1);
|
||||
self.set_reg(IP, w1);
|
||||
}
|
||||
}
|
||||
Inst::Load(r1, r2) => {
|
||||
|
||||
Reference in New Issue
Block a user