Update registers to be constants, add instructions to parser

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-01-27 18:41:33 -05:00
parent abf32665e2
commit b16974c7c4
4 changed files with 149 additions and 159 deletions

View File

@@ -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,
}

View File

@@ -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)]

View File

@@ -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
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
}
}
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)
},
<op:InstOp> <head:Value?> => {
Inst { op, args: if let Some(head) = head { vec![head] } else { vec![] } }
}
"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 Value: Value = {
<Number> => Value::Number(<>),
<Label> => Value::Label(<>),
}
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(<>),
}

View File

@@ -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) => {