Full encoding supported, add tests, start encoding the parsed code
This commit is contained in:
parent
4509218b49
commit
f0b5be8c63
8 changed files with 342 additions and 173 deletions
95
src/env.rs
95
src/env.rs
|
@ -1,13 +1,33 @@
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, env::Args};
|
||||||
|
|
||||||
use crate::{err::RuntimeErr, parser::{Loc, Token}};
|
use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
err::RuntimeErr,
|
||||||
|
instructions::{instruction, with, Arg},
|
||||||
|
parser::{Loc, Token},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub enum SymbolValue {
|
||||||
|
Byte(u8),
|
||||||
|
Half(u16),
|
||||||
|
Word(u32),
|
||||||
|
DWord(u64),
|
||||||
|
String(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Value {
|
||||||
|
Immediate(i64),
|
||||||
|
Register(u32),
|
||||||
|
Symbol(String, SymbolValue),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Env {
|
pub struct Env {
|
||||||
pub register_alias: HashMap<String, u32>,
|
pub register_alias: HashMap<String, u32>,
|
||||||
labels: HashMap<String, u32>,
|
labels: HashMap<String, u32>,
|
||||||
registers: [i64; 32],
|
registers: [u64; 32],
|
||||||
pub stack: Vec<i64>, // TODO: Find the size of the stack
|
pub stack: Vec<u64>, // TODO: Find the size of the stack
|
||||||
pub instructions: Vec<u32>,
|
pub instructions: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +44,7 @@ impl Env {
|
||||||
("t1", 6),
|
("t1", 6),
|
||||||
("t2", 7),
|
("t2", 7),
|
||||||
("s0", 8),
|
("s0", 8),
|
||||||
|
("fp", 8),
|
||||||
("s1", 9),
|
("s1", 9),
|
||||||
("a0", 10),
|
("a0", 10),
|
||||||
("a1", 11),
|
("a1", 11),
|
||||||
|
@ -56,16 +77,16 @@ impl Env {
|
||||||
register_alias,
|
register_alias,
|
||||||
labels: HashMap::new(),
|
labels: HashMap::new(),
|
||||||
registers: [0; 32],
|
registers: [0; 32],
|
||||||
stack: Vec::new(),
|
stack: Vec::from([0; 1024]),
|
||||||
instructions: Vec::new(),
|
instructions: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_register(&mut self, reg: u32, value: i64) {
|
pub fn set_register(&mut self, reg: u32, value: u64) {
|
||||||
self.registers[reg as usize] = value;
|
self.registers[reg as usize] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_register(&self, reg: u32) -> i64 {
|
pub fn get_register(&self, reg: u32) -> u64 {
|
||||||
self.registers[reg as usize]
|
self.registers[reg as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +105,13 @@ impl Env {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn reg_to_register(&self, reg: &str) -> Option<u32> {
|
||||||
|
if reg.starts_with("x") {
|
||||||
|
self.xn_to_register(reg)
|
||||||
|
} else {
|
||||||
|
self.alias_to_register(reg)
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn is_valid_register(&self, reg: &str) -> bool {
|
pub fn is_valid_register(&self, reg: &str) -> bool {
|
||||||
self.alias_to_register(reg)
|
self.alias_to_register(reg)
|
||||||
.or_else(|| self.xn_to_register(reg))
|
.or_else(|| self.xn_to_register(reg))
|
||||||
|
@ -98,12 +126,53 @@ impl Env {
|
||||||
self.labels.get(label).copied()
|
self.labels.get(label).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_instruction(&self, tokens: Vec<(Token, Loc)>) -> Result<u32, RuntimeErr> {
|
pub fn assemble_op(&mut self, op: (Token, Loc)) -> Result<u32, RuntimeErr> {
|
||||||
let (op, args) = match &tokens[0].0 {
|
if let (Token::Op(name, args), loc) = op {
|
||||||
Token::Op(op, args) => (op, args),
|
let i = instruction(&name);
|
||||||
_ => unreachable!(),
|
let mut imm = 0u32;
|
||||||
};
|
let mut regs = vec![0; 4];
|
||||||
|
if args.len() != i.1.len() {
|
||||||
|
return Err(RuntimeErr::InvalidOpArity(
|
||||||
|
name,
|
||||||
|
args.len(),
|
||||||
|
i.1.len(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
todo!()
|
let _ = i.1.into_par_iter()
|
||||||
|
.enumerate()
|
||||||
|
.try_for_each(|(k, v)| match v {
|
||||||
|
Arg::Immediate => {
|
||||||
|
if let Token::Immediate(i) = args[k].0 {
|
||||||
|
imm = i as u32;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(RuntimeErr::InvalidType("Immediate".to_string(), v.kind()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Arg::Register => {
|
||||||
|
if let Token::Register(r) = args[k].0 {
|
||||||
|
regs[k] = self.reg_to_register(&r).unwrap();
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(RuntimeErr::InvalidType("Register".to_string(), v.kind()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Arg::Memory => {
|
||||||
|
if let Token::Memory(i, r) = args[k].0 {
|
||||||
|
if r.is_some() {
|
||||||
|
regs[k] = self.reg_to_register(&r.unwrap()).unwrap();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(RuntimeErr::InvalidType("Memory".to_string(), v.kind()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unimplemented!()
|
||||||
|
})?;
|
||||||
|
Ok(u32::from_str_radix(&with(i, imm, regs).0.to_string(), 2).unwrap())
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
src/err.rs
11
src/err.rs
|
@ -30,7 +30,10 @@ impl SyntaxErr {
|
||||||
SyntaxErr::UnmatchedParen(true) => "add '(' before the register name".to_string(),
|
SyntaxErr::UnmatchedParen(true) => "add '(' before the register name".to_string(),
|
||||||
SyntaxErr::UnexpectedChar => "ensure the input is well-formed".to_string(),
|
SyntaxErr::UnexpectedChar => "ensure the input is well-formed".to_string(),
|
||||||
SyntaxErr::OutsideOp(_) => format!("add arguments after the opcode"),
|
SyntaxErr::OutsideOp(_) => format!("add arguments after the opcode"),
|
||||||
SyntaxErr::MemoryInvalidRegister => "registers are either xN (N < 32 with no leading 0) or the standard aliases".to_string(),
|
SyntaxErr::MemoryInvalidRegister => {
|
||||||
|
"registers are either xN (N < 32 with no leading 0) or the standard aliases"
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +45,7 @@ pub enum RuntimeErr {
|
||||||
UnexpectedRegister,
|
UnexpectedRegister,
|
||||||
InvalidOp(String),
|
InvalidOp(String),
|
||||||
InvalidOpArity(String, usize, usize),
|
InvalidOpArity(String, usize, usize),
|
||||||
|
InvalidType(String, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for RuntimeErr {
|
impl Display for RuntimeErr {
|
||||||
|
@ -51,11 +55,14 @@ impl Display for RuntimeErr {
|
||||||
RuntimeErr::UnexpectedImmediate => write!(f, "unexpected immediate"),
|
RuntimeErr::UnexpectedImmediate => write!(f, "unexpected immediate"),
|
||||||
RuntimeErr::UnexpectedRegister => write!(f, "unexpected register"),
|
RuntimeErr::UnexpectedRegister => write!(f, "unexpected register"),
|
||||||
RuntimeErr::InvalidOp(op) => write!(f, "invalid operation {}", op),
|
RuntimeErr::InvalidOp(op) => write!(f, "invalid operation {}", op),
|
||||||
RuntimeErr::InvalidOpArity(op, expected, actual) => write!(
|
RuntimeErr::InvalidOpArity(op, actual, expected) => write!(
|
||||||
f,
|
f,
|
||||||
"invalid operation arity {} expected {} got {}",
|
"invalid operation arity {} expected {} got {}",
|
||||||
op, expected, actual
|
op, expected, actual
|
||||||
),
|
),
|
||||||
|
RuntimeErr::InvalidType(actual, expected) => {
|
||||||
|
write!(f, "expected {}, got {}", expected, actual)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,36 +222,56 @@ pub mod kind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Value {
|
pub enum Arg {
|
||||||
Register,
|
Register,
|
||||||
Immediate,
|
Immediate,
|
||||||
Memory,
|
Memory,
|
||||||
Symbol,
|
Symbol,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Arg {
|
||||||
|
pub fn kind(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Arg::Register => "register",
|
||||||
|
Arg::Immediate => "immediate",
|
||||||
|
Arg::Memory => "memory",
|
||||||
|
Arg::Symbol => "symbol",
|
||||||
|
}
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
use kind::*;
|
use kind::*;
|
||||||
|
|
||||||
/// (kind, (arity, Vec<token kind>))
|
/// (kind, (arity, Vec<token kind>))
|
||||||
pub fn instruction(op: &str) -> (Kind, Vec<Value>) {
|
pub fn instruction(op: &str) -> (Kind, Vec<Arg>) {
|
||||||
match op {
|
match op {
|
||||||
// -
|
// -
|
||||||
"nop" => (Kind::Pseudo(Pseudo {}), vec![]),
|
"nop" => (Kind::Pseudo(Pseudo {}), vec![]),
|
||||||
|
|
||||||
// Move
|
// Move
|
||||||
"li" => (
|
"li" => (Kind::Pseudo(Pseudo {}), vec![Arg::Register, Arg::Immediate]),
|
||||||
Kind::Pseudo(Pseudo {}),
|
|
||||||
vec![Value::Register, Value::Immediate],
|
|
||||||
),
|
|
||||||
"lui" => (
|
"lui" => (
|
||||||
Kind::U(U {
|
Kind::U(U {
|
||||||
imm: to_bits(0),
|
imm: to_bits(0),
|
||||||
rd: to_bits(0),
|
rd: to_bits(0),
|
||||||
opcode: to_bits(0b0110111),
|
opcode: to_bits(0b0110111),
|
||||||
}),
|
}),
|
||||||
vec![Value::Register, Value::Immediate],
|
vec![Arg::Register, Arg::Immediate],
|
||||||
),
|
),
|
||||||
|
|
||||||
// Memory
|
// Memory
|
||||||
|
"sb" => (
|
||||||
|
Kind::S(S {
|
||||||
|
imm: to_bits(0),
|
||||||
|
rb: to_bits(0),
|
||||||
|
ra: to_bits(0),
|
||||||
|
funct3: to_bits(0b000),
|
||||||
|
imm2: to_bits(0),
|
||||||
|
opcode: to_bits(0b0100011),
|
||||||
|
}),
|
||||||
|
vec![Arg::Register, Arg::Memory],
|
||||||
|
),
|
||||||
|
|
||||||
// Arithmetic, Logic, Shift
|
// Arithmetic, Logic, Shift
|
||||||
"add" => (
|
"add" => (
|
||||||
|
@ -263,7 +283,7 @@ pub fn instruction(op: &str) -> (Kind, Vec<Value>) {
|
||||||
rd: to_bits(0),
|
rd: to_bits(0),
|
||||||
opcode: to_bits(0b0110011),
|
opcode: to_bits(0b0110011),
|
||||||
}),
|
}),
|
||||||
vec![Value::Register, Value::Register, Value::Register],
|
vec![Arg::Register, Arg::Register, Arg::Register],
|
||||||
),
|
),
|
||||||
"addi" => (
|
"addi" => (
|
||||||
Kind::I(I {
|
Kind::I(I {
|
||||||
|
@ -273,14 +293,30 @@ pub fn instruction(op: &str) -> (Kind, Vec<Value>) {
|
||||||
rd: to_bits(0),
|
rd: to_bits(0),
|
||||||
opcode: to_bits(0b0010011),
|
opcode: to_bits(0b0010011),
|
||||||
}),
|
}),
|
||||||
vec![Value::Register, Value::Register, Value::Immediate],
|
vec![Arg::Register, Arg::Register, Arg::Immediate],
|
||||||
|
),
|
||||||
|
// Multiply, Divide
|
||||||
|
|
||||||
|
// Compare
|
||||||
|
|
||||||
|
// Flow control (branch, jump, call, ret)
|
||||||
|
"beq" => (
|
||||||
|
Kind::B(B {
|
||||||
|
imm: to_bits(0),
|
||||||
|
rb: to_bits(0),
|
||||||
|
ra: to_bits(0),
|
||||||
|
funct3: to_bits(0b000),
|
||||||
|
imm2: to_bits(0),
|
||||||
|
opcode: to_bits(0b1100011),
|
||||||
|
}),
|
||||||
|
vec![Arg::Register, Arg::Register, Arg::Immediate],
|
||||||
),
|
),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Order: rd, ra, rb, rc
|
/// regs order: rd, ra, rb, rc
|
||||||
pub fn with_reg_args((kind, args): (Kind, Vec<Value>), regs: Vec<u32>) -> (Kind, Vec<Value>) {
|
pub fn with((kind, args): (Kind, Vec<Arg>), imm: u32, regs: Vec<u32>) -> (Kind, Vec<Arg>) {
|
||||||
match kind {
|
match kind {
|
||||||
Kind::Pseudo(_) => (kind, args),
|
Kind::Pseudo(_) => (kind, args),
|
||||||
Kind::R(r) => (
|
Kind::R(r) => (
|
||||||
|
@ -308,7 +344,7 @@ pub fn with_reg_args((kind, args): (Kind, Vec<Value>), regs: Vec<u32>) -> (Kind,
|
||||||
),
|
),
|
||||||
Kind::I(i) => (
|
Kind::I(i) => (
|
||||||
Kind::I(I {
|
Kind::I(I {
|
||||||
imm: i.imm,
|
imm: to_bits(imm),
|
||||||
ra: to_bits(regs[1]),
|
ra: to_bits(regs[1]),
|
||||||
funct3: i.funct3,
|
funct3: i.funct3,
|
||||||
rd: to_bits(regs[0]),
|
rd: to_bits(regs[0]),
|
||||||
|
@ -319,7 +355,7 @@ pub fn with_reg_args((kind, args): (Kind, Vec<Value>), regs: Vec<u32>) -> (Kind,
|
||||||
Kind::I2(i2) => (
|
Kind::I2(i2) => (
|
||||||
Kind::I2(I2 {
|
Kind::I2(I2 {
|
||||||
funct6: i2.funct6,
|
funct6: i2.funct6,
|
||||||
imm: i2.imm,
|
imm: to_bits(imm),
|
||||||
ra: to_bits(regs[1]),
|
ra: to_bits(regs[1]),
|
||||||
funct3: i2.funct3,
|
funct3: i2.funct3,
|
||||||
rd: to_bits(regs[0]),
|
rd: to_bits(regs[0]),
|
||||||
|
@ -327,88 +363,21 @@ pub fn with_reg_args((kind, args): (Kind, Vec<Value>), regs: Vec<u32>) -> (Kind,
|
||||||
}),
|
}),
|
||||||
args,
|
args,
|
||||||
),
|
),
|
||||||
Kind::S(s) => (
|
|
||||||
Kind::S(S {
|
|
||||||
imm: s.imm,
|
|
||||||
rb: to_bits(regs[2]),
|
|
||||||
ra: to_bits(regs[1]),
|
|
||||||
funct3: s.funct3,
|
|
||||||
imm2: s.imm2,
|
|
||||||
opcode: s.opcode,
|
|
||||||
}),
|
|
||||||
args,
|
|
||||||
),
|
|
||||||
Kind::B(b) => (
|
|
||||||
Kind::B(B {
|
|
||||||
imm: b.imm,
|
|
||||||
rb: to_bits(regs[2]),
|
|
||||||
ra: to_bits(regs[1]),
|
|
||||||
funct3: b.funct3,
|
|
||||||
imm2: b.imm2,
|
|
||||||
opcode: b.opcode,
|
|
||||||
}),
|
|
||||||
args,
|
|
||||||
),
|
|
||||||
Kind::U(u) => (
|
|
||||||
Kind::U(U {
|
|
||||||
imm: u.imm,
|
|
||||||
rd: to_bits(regs[0]),
|
|
||||||
opcode: u.opcode,
|
|
||||||
}),
|
|
||||||
args,
|
|
||||||
),
|
|
||||||
Kind::J(j) => (
|
|
||||||
Kind::J(J {
|
|
||||||
imm: j.imm,
|
|
||||||
rd: to_bits(regs[0]),
|
|
||||||
opcode: j.opcode,
|
|
||||||
}),
|
|
||||||
args,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_imm((kind, args): (Kind, Vec<Value>), imm: u32) -> (Kind, Vec<Value>) {
|
|
||||||
match kind {
|
|
||||||
Kind::Pseudo(_) => (kind, args),
|
|
||||||
Kind::R(r) => (Kind::R(r), args),
|
|
||||||
Kind::R4(r4) => (Kind::R4(r4), args),
|
|
||||||
Kind::I(i) => (
|
|
||||||
Kind::I(I {
|
|
||||||
imm: to_bits(imm),
|
|
||||||
ra: i.ra,
|
|
||||||
funct3: i.funct3,
|
|
||||||
rd: i.rd,
|
|
||||||
opcode: i.opcode,
|
|
||||||
}),
|
|
||||||
args,
|
|
||||||
),
|
|
||||||
Kind::I2(i2) => (
|
|
||||||
Kind::I2(I2 {
|
|
||||||
funct6: i2.funct6,
|
|
||||||
imm: to_bits(imm),
|
|
||||||
ra: i2.ra,
|
|
||||||
funct3: i2.funct3,
|
|
||||||
rd: i2.rd,
|
|
||||||
opcode: i2.opcode,
|
|
||||||
}),
|
|
||||||
args,
|
|
||||||
),
|
|
||||||
Kind::S(s) => {
|
Kind::S(s) => {
|
||||||
let bits = to_bits::<32>(imm);
|
let bits = to_bits::<32>(imm);
|
||||||
(
|
(
|
||||||
Kind::S(S {
|
Kind::S(S {
|
||||||
imm: {
|
imm: {
|
||||||
let mut imm = [false; 7];
|
let mut imm = [false; 7];
|
||||||
imm.copy_from_slice(&bits[11..=5]);
|
imm.copy_from_slice(&bits[5..=11]); //.into_iter().rev().map(|&b| b).collect::<Vec<_>>()[..]);
|
||||||
imm
|
imm
|
||||||
},
|
},
|
||||||
rb: s.rb,
|
rb: to_bits(regs[2]),
|
||||||
ra: s.ra,
|
ra: to_bits(regs[1]),
|
||||||
funct3: s.funct3,
|
funct3: s.funct3,
|
||||||
imm2: {
|
imm2: {
|
||||||
let mut imm2 = [false; 5];
|
let mut imm2 = [false; 5];
|
||||||
imm2.copy_from_slice(&bits[4..=0]);
|
imm2.copy_from_slice(&bits[0..=4]); //.into_iter().rev().map(|&b| b).collect::<Vec<_>>()[..]);
|
||||||
imm2
|
imm2
|
||||||
},
|
},
|
||||||
opcode: s.opcode,
|
opcode: s.opcode,
|
||||||
|
@ -423,15 +392,15 @@ pub fn with_imm((kind, args): (Kind, Vec<Value>), imm: u32) -> (Kind, Vec<Value>
|
||||||
imm: {
|
imm: {
|
||||||
let mut imm = [false; 7];
|
let mut imm = [false; 7];
|
||||||
imm[6] = bits[12];
|
imm[6] = bits[12];
|
||||||
imm[5..=0].copy_from_slice(&bits[10..=5]);
|
imm[0..=5].copy_from_slice(&bits[5..=10]);
|
||||||
imm
|
imm
|
||||||
},
|
},
|
||||||
rb: b.rb,
|
rb: to_bits(regs[2]),
|
||||||
ra: b.ra,
|
ra: to_bits(regs[1]),
|
||||||
funct3: b.funct3,
|
funct3: b.funct3,
|
||||||
imm2: {
|
imm2: {
|
||||||
let mut imm2 = [false; 5];
|
let mut imm2 = [false; 5];
|
||||||
imm2[4..=1].copy_from_slice(&bits[4..=1]);
|
imm2[1..=4].copy_from_slice(&bits[1..=4]);
|
||||||
imm2[0] = bits[11];
|
imm2[0] = bits[11];
|
||||||
imm2
|
imm2
|
||||||
},
|
},
|
||||||
|
@ -448,7 +417,7 @@ pub fn with_imm((kind, args): (Kind, Vec<Value>), imm: u32) -> (Kind, Vec<Value>
|
||||||
imm.copy_from_slice(&bits[31..=12]);
|
imm.copy_from_slice(&bits[31..=12]);
|
||||||
imm
|
imm
|
||||||
},
|
},
|
||||||
rd: u.rd,
|
rd: to_bits(regs[0]),
|
||||||
opcode: u.opcode,
|
opcode: u.opcode,
|
||||||
}),
|
}),
|
||||||
args,
|
args,
|
||||||
|
@ -464,7 +433,7 @@ pub fn with_imm((kind, args): (Kind, Vec<Value>), imm: u32) -> (Kind, Vec<Value>
|
||||||
imm[7..=0].copy_from_slice(&bits[19..=12]);
|
imm[7..=0].copy_from_slice(&bits[19..=12]);
|
||||||
imm
|
imm
|
||||||
},
|
},
|
||||||
rd: j.rd,
|
rd: to_bits(regs[0]),
|
||||||
opcode: j.opcode,
|
opcode: j.opcode,
|
||||||
}),
|
}),
|
||||||
args,
|
args,
|
||||||
|
|
|
@ -2,3 +2,4 @@ pub mod env;
|
||||||
pub mod err;
|
pub mod err;
|
||||||
pub mod instructions;
|
pub mod instructions;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
pub mod tests;
|
||||||
|
|
93
src/main.rs
93
src/main.rs
|
@ -9,7 +9,7 @@ use codespan_reporting::{
|
||||||
};
|
};
|
||||||
use riscv_interpreter::{
|
use riscv_interpreter::{
|
||||||
env::Env,
|
env::Env,
|
||||||
instructions::{instruction, with_imm, with_reg_args},
|
instructions::{instruction, with},
|
||||||
parser::parse,
|
parser::parse,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,74 +22,35 @@ fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
let env = Env::new();
|
let env = Env::new();
|
||||||
|
|
||||||
// match parse(&env, &input) {
|
match parse(&env, &input) {
|
||||||
// Ok(tokens) => {
|
Ok(tokens) => {
|
||||||
// println!("{:#?} -> {:#?}", input, tokens);
|
println!("{:#?} -> {:#?}", input, tokens);
|
||||||
// }
|
}
|
||||||
// Err(errs) => {
|
Err(errs) => {
|
||||||
// for err in errs {
|
for err in errs {
|
||||||
// let start = err.1.start;
|
let start = err.1.start;
|
||||||
// let end = err.1.end + 1;
|
let end = err.1.end + 1;
|
||||||
|
|
||||||
// let diagnostic = Diagnostic::error()
|
let diagnostic = Diagnostic::error()
|
||||||
// .with_message("Syntax Error")
|
.with_message("Syntax Error")
|
||||||
// .with_labels(vec![
|
.with_labels(vec![
|
||||||
// Label::primary((), start..end).with_message(err.0.to_string())
|
Label::primary((), start..end).with_message(err.0.to_string())
|
||||||
// ])
|
])
|
||||||
// .with_notes({
|
.with_notes({
|
||||||
// let mut notes = Vec::new();
|
let mut notes = Vec::new();
|
||||||
// if let Some(note) = err.3 {
|
if let Some(note) = err.3 {
|
||||||
// notes.push(note);
|
notes.push(note);
|
||||||
// }
|
}
|
||||||
// notes.push(err.0.note());
|
notes.push(err.0.note());
|
||||||
// notes
|
notes
|
||||||
// });
|
});
|
||||||
|
|
||||||
// term::emit(&mut writer.lock(), &config, &file, &diagnostic).unwrap();
|
term::emit(&mut writer.lock(), &config, &file, &diagnostic).unwrap();
|
||||||
// }
|
}
|
||||||
// }
|
return Ok(());
|
||||||
// };
|
}
|
||||||
|
};
|
||||||
|
|
||||||
println!("nop: {}", instruction("nop").0);
|
|
||||||
println!(
|
|
||||||
"add a0 a0 a1: {}",
|
|
||||||
with_reg_args(
|
|
||||||
instruction("add"),
|
|
||||||
vec![
|
|
||||||
env.alias_to_register("a0").unwrap() as u32,
|
|
||||||
env.alias_to_register("a0").unwrap() as u32,
|
|
||||||
env.alias_to_register("a1").unwrap() as u32
|
|
||||||
]
|
|
||||||
)
|
|
||||||
.0 // 011001101010000001010010110000000
|
|
||||||
// Ripes: 011001101010000001010010110000000
|
|
||||||
);
|
|
||||||
println!(
|
|
||||||
"addi a0 a0 1: {}",
|
|
||||||
with_imm(
|
|
||||||
with_reg_args(
|
|
||||||
instruction("addi"),
|
|
||||||
vec![
|
|
||||||
env.alias_to_register("a0").unwrap(),
|
|
||||||
env.alias_to_register("a0").unwrap()
|
|
||||||
]
|
|
||||||
),
|
|
||||||
1
|
|
||||||
)
|
|
||||||
.0 // 00000000000101010000010100010011
|
|
||||||
// Ripes: 00000000000101010000010100010011
|
|
||||||
);
|
|
||||||
println!(
|
|
||||||
"lui a0 1: {}",
|
|
||||||
with_imm(
|
|
||||||
with_reg_args(
|
|
||||||
instruction("lui"),
|
|
||||||
vec![env.alias_to_register("a0").unwrap()]
|
|
||||||
),
|
|
||||||
1
|
|
||||||
)
|
|
||||||
.0
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ pub enum Token {
|
||||||
/// \# blablabla,
|
/// \# blablabla,
|
||||||
Comment,
|
Comment,
|
||||||
/// 1, 2, -1
|
/// 1, 2, -1
|
||||||
Immediate(i64),
|
Immediate(u32),
|
||||||
/// zero, r1, pc
|
/// zero, r1, pc
|
||||||
///
|
///
|
||||||
/// Technically also label references and symbols, but we'll handle those later
|
/// Technically also label references and symbols, but we'll handle those later
|
||||||
|
|
159
src/tests.rs
Normal file
159
src/tests.rs
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
#[cfg(test)]
|
||||||
|
/// Test values come from Ripes
|
||||||
|
use crate::{
|
||||||
|
env::Env,
|
||||||
|
instructions::{instruction, with},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[ignore = "TODO"]
|
||||||
|
fn nop() {
|
||||||
|
#[rustfmt::skip]
|
||||||
|
{
|
||||||
|
// nop (pseudo) -> addi x0, x0, 0
|
||||||
|
// I-Type
|
||||||
|
// | imm12 | ra |f3 | rd | opcode
|
||||||
|
// 000000000000 00000 000 00000 0010011
|
||||||
|
};
|
||||||
|
// nop
|
||||||
|
assert_eq!(
|
||||||
|
u32::from_str_radix(
|
||||||
|
&with(
|
||||||
|
instruction("nop"),
|
||||||
|
0, // imm
|
||||||
|
vec![]
|
||||||
|
)
|
||||||
|
.0
|
||||||
|
.to_string(),
|
||||||
|
2
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
0b00000000000000000000000000010011u32
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sb() {
|
||||||
|
let env = Env::new();
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
{
|
||||||
|
// S-Type
|
||||||
|
// | imm | rb | ra |f3 | rd | opcode
|
||||||
|
// 1111111 11110 00010 000 11100 0100011
|
||||||
|
};
|
||||||
|
// sb t5 -4(sp)
|
||||||
|
assert_eq!(
|
||||||
|
u32::from_str_radix(
|
||||||
|
&with(
|
||||||
|
instruction("sb"),
|
||||||
|
-4i32 as u32, // imm
|
||||||
|
vec![
|
||||||
|
0, // rd
|
||||||
|
env.alias_to_register("sp").unwrap(), // ra
|
||||||
|
env.alias_to_register("t5").unwrap() // rb
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.0
|
||||||
|
.to_string(),
|
||||||
|
2
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
0b11111111111000010000111000100011u32
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn add() {
|
||||||
|
let env = Env::new();
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
{
|
||||||
|
// R-Type
|
||||||
|
// | f7 | rb | ra |f3 | rd | opcode
|
||||||
|
// 0000000 01011 01010 000 01010 0110011
|
||||||
|
};
|
||||||
|
// add a0 a0 a1
|
||||||
|
assert_eq!(
|
||||||
|
u32::from_str_radix(
|
||||||
|
&with(
|
||||||
|
instruction("add"),
|
||||||
|
0, // imm
|
||||||
|
vec![
|
||||||
|
env.alias_to_register("a0").unwrap(), // rd
|
||||||
|
env.alias_to_register("a0").unwrap(), // ra
|
||||||
|
env.alias_to_register("a1").unwrap() // rb
|
||||||
|
]
|
||||||
|
)
|
||||||
|
.0
|
||||||
|
.to_string(),
|
||||||
|
2
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
0b00000000101101010000010100110011u32
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn addi() {
|
||||||
|
let env = Env::new();
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
{
|
||||||
|
// I-Type
|
||||||
|
// | imm12 | ra |f3 | rd | opcode
|
||||||
|
// 000000000001 01010 000 01010 0010011
|
||||||
|
// 000000000001 01010 000 01010 0010011 (Ripes)
|
||||||
|
};
|
||||||
|
// addi a0 a0 1
|
||||||
|
assert_eq!(
|
||||||
|
u32::from_str_radix(
|
||||||
|
with(
|
||||||
|
instruction("addi"),
|
||||||
|
1,
|
||||||
|
vec![
|
||||||
|
env.alias_to_register("a0").unwrap(),
|
||||||
|
env.alias_to_register("a0").unwrap()
|
||||||
|
],
|
||||||
|
)
|
||||||
|
.0
|
||||||
|
.to_string()
|
||||||
|
.as_str(),
|
||||||
|
2
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
0b00000000000101010000010100010011u32
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn beq() {
|
||||||
|
let env = Env::new();
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
{
|
||||||
|
// B-Type
|
||||||
|
// | imm7 | rb | ra |f3 |imm5 | opcode
|
||||||
|
// 0000000 01011 01010 000 00100 1100011
|
||||||
|
// 0000000 01011 01010 000 00100 1100011 (Ripes)
|
||||||
|
};
|
||||||
|
// beq a0 a1 4
|
||||||
|
assert_eq!(
|
||||||
|
u32::from_str_radix(
|
||||||
|
&with(
|
||||||
|
instruction("beq"),
|
||||||
|
4,
|
||||||
|
vec![
|
||||||
|
0, // no rd
|
||||||
|
env.alias_to_register("a0").unwrap(),
|
||||||
|
env.alias_to_register("a1").unwrap()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
.0
|
||||||
|
.to_string(),
|
||||||
|
2
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
0b00000000101101010000001001100011u32
|
||||||
|
);
|
||||||
|
}
|
5
test.s
5
test.s
|
@ -1 +1,4 @@
|
||||||
x0 li 8(x0)
|
a:
|
||||||
|
addi a0 zero 1
|
||||||
|
addi a1 zero 2
|
||||||
|
add a2 a1 a0
|
||||||
|
|
Loading…
Reference in a new issue