Update/add instructions in parser

* StoreImm just uses a u64 instead of u32 - we'll figure out the layout
  later
* Jmp implementation added (can't believe I forgot this)
* Add Inst AST item, whose immediates don't have to be a u64 right away

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-01-28 13:51:25 -05:00
parent 7e6c621c2b
commit f98a53654e
6 changed files with 63 additions and 29 deletions

View File

@@ -25,6 +25,6 @@ fn main() -> Result<()> {
process::exit(1);
},
};
println!("{:?}", ast);
println!("{:#?}", ast);
Ok(())
}

View File

@@ -16,12 +16,13 @@ pub enum Inst {
CmpEq(Reg, Reg),
CmpLt(Reg, Reg),
Jmp(Reg),
Jz(Reg),
Jnz(Reg),
Load(Reg, Reg),
Store(Reg, Reg),
StoreImm(Reg, u32),
StoreImm(Reg, u64),
MemCopy(Reg, Reg),
RegCopy(Reg, Reg),

View File

@@ -1,4 +1,4 @@
use crate::vm::inst::Inst;
use crate::vm::reg::Reg;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Line {
@@ -18,3 +18,32 @@ pub enum Value {
Number(u64),
Label(String),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Inst {
Add(Reg, Reg),
Mul(Reg, Reg),
Div(Reg, Reg),
Mod(Reg, Reg),
INeg(Reg),
And(Reg, Reg),
Or(Reg, Reg),
Xor(Reg, Reg),
Shl(Reg, Reg),
Shr(Reg, Reg),
CmpEq(Reg, Reg),
CmpLt(Reg, Reg),
Jmp(Reg),
Jz(Reg),
Jnz(Reg),
Load(Reg, Reg),
Store(Reg, Reg),
StoreImm(Reg, Value),
MemCopy(Reg, Reg),
RegCopy(Reg, Reg),
Nop,
Halt,
}

View File

@@ -2,7 +2,6 @@ use std::str::FromStr;
use crate::vm::{
syn::ast::*,
reg::*,
inst::Inst,
};
grammar;
@@ -21,17 +20,17 @@ Label: String = {
}
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()
<s:r"\$[0-9]+"> => u64::from_str(&s[1..]).unwrap(),
<s:r"\$0x[0-9a-fA-F]+"> => u64::from_str_radix(&s[3..], 16).unwrap()
}
Reg: Reg = {
"%ip" => IP,
"%sp" => SP,
"%fp" => FP,
"%flags" => FLAGS,
"%status" => STATUS,
"%r[0-9]{2}" => {
r"%ip" => IP,
r"%sp" => SP,
r"%fp" => FP,
r"%flags" => FLAGS,
r"%status" => STATUS,
r"%r[0-9]{2}" => {
let offset = (&<>[2..]).parse::<u8>().unwrap();
let reg = R00 + offset;
assert!(reg < LAST_REG, "invalid register");
@@ -52,16 +51,12 @@ Inst: Inst = {
"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),
"jmp" <d:Reg> => Inst::Jmp(d),
"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)
},
"storeimm" <d:Reg> "," <s:Value> => Inst::StoreImm(d, s),
"memcopy" <d:Reg> "," <s:Reg> => Inst::MemCopy(d, s),
"regcopy" <d:Reg> "," <s:Reg> => Inst::RegCopy(d, s),
"nop" => Inst::Nop,

View File

@@ -190,6 +190,10 @@ impl Vm {
self.remove_flags(Flags::COMPARE);
}
}
Inst::Jmp(r1) => {
let w1 = self.get_reg(r1);
self.set_reg(IP, w1);
}
Inst::Jz(r1) => {
if !self.flags().contains(Flags::COMPARE) {
let w1 = self.get_reg(r1);