80 lines
2.1 KiB
Plaintext
80 lines
2.1 KiB
Plaintext
use std::str::FromStr;
|
|
use crate::vm::{
|
|
syn::ast::*,
|
|
reg::*,
|
|
inst::Inst,
|
|
};
|
|
|
|
grammar;
|
|
|
|
LabelDef: String = {
|
|
<Label> ":" => <>
|
|
}
|
|
|
|
Value: Value = {
|
|
<Label> => Value::Label(<>),
|
|
<Number> => Value::Number(<>),
|
|
}
|
|
|
|
Label: String = {
|
|
"[a-zA-Z]+" => String::from(<>),
|
|
}
|
|
|
|
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()
|
|
}
|
|
|
|
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)
|
|
},
|
|
"memcopy" <d:Reg> "," <s:Reg> => Inst::MemCopy(d, s),
|
|
"regcopy" <d:Reg> "," <s:Reg> => Inst::RegCopy(d, s),
|
|
"nop" => Inst::Nop,
|
|
"halt" => Inst::Halt,
|
|
}
|
|
|
|
Directive: Directive = {
|
|
".section" <s:Label> => Directive::Section(s.to_string()),
|
|
}
|
|
|
|
pub Line: Line = {
|
|
<Directive> => Line::Directive(<>),
|
|
<Inst> => Line::Inst(<>),
|
|
<LabelDef> => Line::LabelDef(<>),
|
|
}
|