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:
@@ -25,6 +25,6 @@ fn main() -> Result<()> {
|
|||||||
process::exit(1);
|
process::exit(1);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
println!("{:?}", ast);
|
println!("{:#?}", ast);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,13 @@ pub enum Inst {
|
|||||||
|
|
||||||
CmpEq(Reg, Reg),
|
CmpEq(Reg, Reg),
|
||||||
CmpLt(Reg, Reg),
|
CmpLt(Reg, Reg),
|
||||||
|
Jmp(Reg),
|
||||||
Jz(Reg),
|
Jz(Reg),
|
||||||
Jnz(Reg),
|
Jnz(Reg),
|
||||||
|
|
||||||
Load(Reg, Reg),
|
Load(Reg, Reg),
|
||||||
Store(Reg, Reg),
|
Store(Reg, Reg),
|
||||||
StoreImm(Reg, u32),
|
StoreImm(Reg, u64),
|
||||||
MemCopy(Reg, Reg),
|
MemCopy(Reg, Reg),
|
||||||
RegCopy(Reg, Reg),
|
RegCopy(Reg, Reg),
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::vm::inst::Inst;
|
use crate::vm::reg::Reg;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Line {
|
pub enum Line {
|
||||||
@@ -18,3 +18,32 @@ pub enum Value {
|
|||||||
Number(u64),
|
Number(u64),
|
||||||
Label(String),
|
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,
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ use std::str::FromStr;
|
|||||||
use crate::vm::{
|
use crate::vm::{
|
||||||
syn::ast::*,
|
syn::ast::*,
|
||||||
reg::*,
|
reg::*,
|
||||||
inst::Inst,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
grammar;
|
grammar;
|
||||||
@@ -21,17 +20,17 @@ Label: String = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Number: u64 = {
|
Number: u64 = {
|
||||||
<s:r"\$[0-9]+"> => u64::from_str(s).unwrap(),
|
<s:r"\$[0-9]+"> => u64::from_str(&s[1..]).unwrap(),
|
||||||
<s:r"\$0x[0-9a-fA-F]+"> => u64::from_str_radix(s, 16).unwrap()
|
<s:r"\$0x[0-9a-fA-F]+"> => u64::from_str_radix(&s[3..], 16).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
Reg: Reg = {
|
Reg: Reg = {
|
||||||
"%ip" => IP,
|
r"%ip" => IP,
|
||||||
"%sp" => SP,
|
r"%sp" => SP,
|
||||||
"%fp" => FP,
|
r"%fp" => FP,
|
||||||
"%flags" => FLAGS,
|
r"%flags" => FLAGS,
|
||||||
"%status" => STATUS,
|
r"%status" => STATUS,
|
||||||
"%r[0-9]{2}" => {
|
r"%r[0-9]{2}" => {
|
||||||
let offset = (&<>[2..]).parse::<u8>().unwrap();
|
let offset = (&<>[2..]).parse::<u8>().unwrap();
|
||||||
let reg = R00 + offset;
|
let reg = R00 + offset;
|
||||||
assert!(reg < LAST_REG, "invalid register");
|
assert!(reg < LAST_REG, "invalid register");
|
||||||
@@ -52,16 +51,12 @@ Inst: Inst = {
|
|||||||
"shr" <d:Reg> "," <s:Reg> => Inst::Shr(d, s),
|
"shr" <d:Reg> "," <s:Reg> => Inst::Shr(d, s),
|
||||||
"cmpeq" <d:Reg> "," <s:Reg> => Inst::CmpEq(d, s),
|
"cmpeq" <d:Reg> "," <s:Reg> => Inst::CmpEq(d, s),
|
||||||
"cmplt" <d:Reg> "," <s:Reg> => Inst::CmpLt(d, s),
|
"cmplt" <d:Reg> "," <s:Reg> => Inst::CmpLt(d, s),
|
||||||
|
"jmp" <d:Reg> => Inst::Jmp(d),
|
||||||
"jz" <d:Reg> => Inst::Jz(d),
|
"jz" <d:Reg> => Inst::Jz(d),
|
||||||
"jnz" <d:Reg> => Inst::Jnz(d),
|
"jnz" <d:Reg> => Inst::Jnz(d),
|
||||||
"load" <d:Reg> "," <s:Reg> => Inst::Load(d, s),
|
"load" <d:Reg> "," <s:Reg> => Inst::Load(d, s),
|
||||||
"store" <d:Reg> "," <s:Reg> => Inst::Store(d, s),
|
"store" <d:Reg> "," <s:Reg> => Inst::Store(d, s),
|
||||||
"storeimm" <d:Reg> "," <s:Number> => {
|
"storeimm" <d:Reg> "," <s:Value> => Inst::StoreImm(d, s),
|
||||||
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),
|
"memcopy" <d:Reg> "," <s:Reg> => Inst::MemCopy(d, s),
|
||||||
"regcopy" <d:Reg> "," <s:Reg> => Inst::RegCopy(d, s),
|
"regcopy" <d:Reg> "," <s:Reg> => Inst::RegCopy(d, s),
|
||||||
"nop" => Inst::Nop,
|
"nop" => Inst::Nop,
|
||||||
|
|||||||
@@ -190,6 +190,10 @@ impl Vm {
|
|||||||
self.remove_flags(Flags::COMPARE);
|
self.remove_flags(Flags::COMPARE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Inst::Jmp(r1) => {
|
||||||
|
let w1 = self.get_reg(r1);
|
||||||
|
self.set_reg(IP, w1);
|
||||||
|
}
|
||||||
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);
|
||||||
|
|||||||
23
test.asm
23
test.asm
@@ -2,19 +2,24 @@
|
|||||||
|
|
||||||
.section code
|
.section code
|
||||||
|
|
||||||
storeimm %r0, $0xDEAD
|
main:
|
||||||
storeimm %r1, $16
|
storeimm %r00, $0xDEAD
|
||||||
|
storeimm %r01, $16
|
||||||
|
|
||||||
shl %r0, %r1
|
shl %r00, %r01
|
||||||
|
|
||||||
storeimm %r1, $0xBEEF
|
storeimm %r01, $0xBEEF
|
||||||
or %r0, %r1
|
or %r00, %r01
|
||||||
|
|
||||||
storeimm %r1, $0xDEADBEEF
|
storeimm %r01, $0xDEADBEEF
|
||||||
cmpeq %r0, %r1
|
|
||||||
jz failure
|
|
||||||
|
|
||||||
jmp ok
|
storeimm %r00, failure
|
||||||
|
storeimm %r01, ok
|
||||||
|
cmpeq %r00, %r01
|
||||||
|
|
||||||
|
jz %r00
|
||||||
|
|
||||||
|
jmp %r01
|
||||||
|
|
||||||
failure:
|
failure:
|
||||||
storeimm %status, $1
|
storeimm %status, $1
|
||||||
|
|||||||
Reference in New Issue
Block a user