Update registers to be constants, add instructions to parser
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -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(<>),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user