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)]
|
macro_rules! registers {
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
{
|
||||||
#[allow(dead_code)]
|
$($variant:ident = $value:expr),* $(,)?
|
||||||
pub enum Reg {
|
} => {
|
||||||
|
pub type Reg = u8;
|
||||||
|
|
||||||
|
$(
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub const $variant: Reg = $value;
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
registers! {
|
||||||
// https://crates.io/crates/packed_struct
|
// https://crates.io/crates/packed_struct
|
||||||
// TODO : check this muffugin shit out!!
|
// TODO : check this muffugin shit out!!
|
||||||
|
|
||||||
/// Instruction pointer
|
// Instruction pointer
|
||||||
Ip = 0,
|
IP = 0,
|
||||||
|
|
||||||
/// Stack pointer
|
// Stack pointer
|
||||||
Sp,
|
SP = 1,
|
||||||
|
|
||||||
/// Frame pointer
|
// Frame pointer
|
||||||
Fp,
|
FP = 2,
|
||||||
|
|
||||||
/// Flags
|
// Flags
|
||||||
Flags,
|
FLAGS = 3,
|
||||||
|
|
||||||
Unused00,
|
UNUSED00 = 4,
|
||||||
Unused01,
|
UNUSED01 = 5,
|
||||||
Unused02,
|
UNUSED02 = 6,
|
||||||
Unused03,
|
UNUSED03 = 7,
|
||||||
Unused04,
|
UNUSED04 = 8,
|
||||||
Unused05,
|
UNUSED05 = 9,
|
||||||
Unused06,
|
UNUSED06 = 10,
|
||||||
Unused07,
|
UNUSED07 = 11,
|
||||||
Unused08,
|
UNUSED08 = 12,
|
||||||
|
|
||||||
/// General status code
|
// General status code
|
||||||
Status,
|
STATUS = 13,
|
||||||
|
|
||||||
R00,
|
R00 = 14,
|
||||||
R01,
|
R01 = 15,
|
||||||
R02,
|
R02 = 16,
|
||||||
R03,
|
R03 = 17,
|
||||||
R04,
|
R04 = 18,
|
||||||
R05,
|
R05 = 19,
|
||||||
R06,
|
R06 = 20,
|
||||||
R07,
|
R07 = 21,
|
||||||
R08,
|
R08 = 22,
|
||||||
R09,
|
R09 = 23,
|
||||||
R10,
|
R10 = 24,
|
||||||
R11,
|
R11 = 25,
|
||||||
R12,
|
R12 = 26,
|
||||||
R13,
|
R13 = 27,
|
||||||
R14,
|
R14 = 28,
|
||||||
R15,
|
R15 = 29,
|
||||||
R16,
|
R16 = 30,
|
||||||
R17,
|
R17 = 31,
|
||||||
R18,
|
R18 = 32,
|
||||||
R19,
|
R19 = 33,
|
||||||
R20,
|
R20 = 34,
|
||||||
R21,
|
R21 = 35,
|
||||||
R22,
|
R22 = 36,
|
||||||
R23,
|
R23 = 37,
|
||||||
R24,
|
R24 = 38,
|
||||||
R25,
|
R25 = 39,
|
||||||
R26,
|
R26 = 40,
|
||||||
R27,
|
R27 = 41,
|
||||||
R28,
|
R28 = 42,
|
||||||
R29,
|
R29 = 43,
|
||||||
R30,
|
R30 = 44,
|
||||||
R31,
|
R31 = 45,
|
||||||
R32,
|
R32 = 46,
|
||||||
R33,
|
R33 = 47,
|
||||||
R34,
|
R34 = 48,
|
||||||
R35,
|
R35 = 49,
|
||||||
R36,
|
R36 = 50,
|
||||||
R37,
|
R37 = 51,
|
||||||
R38,
|
R38 = 52,
|
||||||
R39,
|
R39 = 53,
|
||||||
R40,
|
R40 = 54,
|
||||||
R41,
|
R41 = 55,
|
||||||
R42,
|
R42 = 56,
|
||||||
R43,
|
R43 = 57,
|
||||||
R44,
|
R44 = 58,
|
||||||
R45,
|
R45 = 59,
|
||||||
R46,
|
R46 = 60,
|
||||||
R47,
|
R47 = 61,
|
||||||
R48,
|
R48 = 62,
|
||||||
R49,
|
R49 = 63,
|
||||||
|
LAST_REG = R49,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,42 +1,15 @@
|
|||||||
|
use crate::vm::{inst::Inst, reg::Reg};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Line {
|
pub enum Line {
|
||||||
Section(Section),
|
Directive(Directive),
|
||||||
Inst(Inst),
|
Inst(Inst),
|
||||||
}
|
LabelDef(String),
|
||||||
|
|
||||||
#[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,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Inst {
|
pub enum Directive {
|
||||||
pub op: InstOp,
|
Section(String),
|
||||||
pub args: Vec<Value>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
|||||||
@@ -1,73 +1,79 @@
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use crate::vm::{
|
use crate::vm::{
|
||||||
syn::ast::*,
|
syn::ast::*,
|
||||||
|
reg::*,
|
||||||
|
inst::Inst,
|
||||||
};
|
};
|
||||||
|
|
||||||
grammar;
|
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 = {
|
LabelDef: String = {
|
||||||
<Label> ":" => <>
|
<Label> ":" => <>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub Label: String = {
|
Value: Value = {
|
||||||
|
<Label> => Value::Label(<>),
|
||||||
|
<Number> => Value::Number(<>),
|
||||||
|
}
|
||||||
|
|
||||||
|
Label: String = {
|
||||||
"[a-zA-Z]+" => String::from(<>),
|
"[a-zA-Z]+" => String::from(<>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub Section: Section = {
|
Number: u64 = {
|
||||||
".code" => Section::Code,
|
<s:r"\$[0-9]+"> => u64::from_str(s).unwrap(),
|
||||||
".data" => Section::Data,
|
<s:r"\$0x[0-9a-fA-F]+"> => u64::from_str_radix(s, 16).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub Inst: Inst = {
|
Reg: Reg = {
|
||||||
<op:InstOp> <head:Value> <tail:("," <Value>)+> => {
|
"%ip" => IP,
|
||||||
Inst {
|
"%sp" => SP,
|
||||||
op,
|
"%fp" => FP,
|
||||||
args: {
|
"%flags" => FLAGS,
|
||||||
let mut tail = tail;
|
"%status" => STATUS,
|
||||||
tail.insert(0, head);
|
"%r[0-9]{2}" => {
|
||||||
tail
|
let offset = (&<>[2..]).parse::<u8>().unwrap();
|
||||||
}
|
let reg = R00 + offset;
|
||||||
}
|
assert!(reg < LAST_REG, "invalid register");
|
||||||
},
|
reg
|
||||||
|
|
||||||
<op:InstOp> <head:Value?> => {
|
|
||||||
Inst { op, args: if let Some(head) = head { vec![head] } else { vec![] } }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub Value: Value = {
|
Inst: Inst = {
|
||||||
<Number> => Value::Number(<>),
|
"add" <d:Reg> "," <s:Reg> => Inst::Add(d, s),
|
||||||
<Label> => Value::Label(<>),
|
"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 = {
|
Directive: Directive = {
|
||||||
<s:r"[0-9]+"> => u64::from_str(s).unwrap()
|
".section" <s:Label> => Directive::Section(s.to_string()),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub Line: Line = {
|
pub Line: Line = {
|
||||||
<Section> => Line::Section(<>),
|
<Directive> => Line::Directive(<>),
|
||||||
<Inst> => Line::Inst(<>),
|
<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) {
|
pub fn tick(&mut self) {
|
||||||
let inst = self.decode();
|
let inst = self.decode();
|
||||||
let ip = self.ip();
|
let ip = self.ip();
|
||||||
self.set_reg(Reg::Ip, ip + 1);
|
self.set_reg(IP, ip + 1);
|
||||||
self.execute(inst);
|
self.execute(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,13 +100,13 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn ip(&self) -> Word {
|
pub fn ip(&self) -> Word {
|
||||||
self.get_reg(Reg::Ip)
|
self.get_reg(IP)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flags(&self) -> Flags {
|
pub fn flags(&self) -> Flags {
|
||||||
// this is safe because it's OK if there are random bits flipped - this shouldn't happen
|
// 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
|
// 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) {
|
pub fn insert_flags(&mut self, flags: Flags) {
|
||||||
@@ -122,7 +122,7 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_flags(&mut self, flags: Flags) {
|
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)
|
pub fn map_flags<F>(&mut self, mapping: F)
|
||||||
@@ -193,13 +193,13 @@ impl Vm {
|
|||||||
Inst::Jz(r1) => {
|
Inst::Jz(r1) => {
|
||||||
if !self.flags().contains(Flags::COMPARE) {
|
if !self.flags().contains(Flags::COMPARE) {
|
||||||
let w1 = self.get_reg(r1);
|
let w1 = self.get_reg(r1);
|
||||||
self.set_reg(Reg::Ip, w1);
|
self.set_reg(IP, w1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Inst::Jnz(r1) => {
|
Inst::Jnz(r1) => {
|
||||||
if self.flags().contains(Flags::COMPARE) {
|
if self.flags().contains(Flags::COMPARE) {
|
||||||
let w1 = self.get_reg(r1);
|
let w1 = self.get_reg(r1);
|
||||||
self.set_reg(Reg::Ip, w1);
|
self.set_reg(IP, w1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Inst::Load(r1, r2) => {
|
Inst::Load(r1, r2) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user