Make output box modular, fix bug in the expansion of li

This commit is contained in:
Lumi Kalt 2024-01-26 01:41:50 +00:00
parent 6d81417701
commit 3ee54491be
10 changed files with 544 additions and 234 deletions

88
Cargo.lock generated
View file

@ -14,6 +14,18 @@ version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
name = "codespan-reporting"
version = "0.11.1"
@ -74,6 +86,16 @@ dependencies = [
"either",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
dependencies = [
"winapi 0.2.8",
"winapi-build",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
@ -86,6 +108,23 @@ version = "0.2.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
[[package]]
name = "libredox"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607"
dependencies = [
"bitflags 2.4.2",
"libc",
"redox_syscall",
]
[[package]]
name = "numtoa"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
[[package]]
name = "rayon"
version = "1.8.1"
@ -106,6 +145,21 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_termios"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb"
[[package]]
name = "riscv_interpreter"
version = "0.1.0"
@ -117,16 +171,18 @@ dependencies = [
"itertools",
"rayon",
"term_size",
"termion",
]
[[package]]
name = "term_size"
version = "0.3.2"
version = "1.0.0-beta1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
checksum = "a8a17d8699e154863becdf18e4fd28bd0be27ca72856f54daf75c00f2566898f"
dependencies = [
"kernel32-sys",
"libc",
"winapi",
"winapi 0.2.8",
]
[[package]]
@ -138,12 +194,30 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "termion"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "417813675a504dfbbf21bfde32c03e5bf9f2413999962b479023c02848c1c7a5"
dependencies = [
"libc",
"libredox",
"numtoa",
"redox_termios",
]
[[package]]
name = "unicode-width"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
[[package]]
name = "winapi"
version = "0.3.9"
@ -154,6 +228,12 @@ dependencies = [
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
@ -166,7 +246,7 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
"winapi 0.3.9",
]
[[package]]

View file

@ -10,4 +10,5 @@ codespan-reporting = "0.11.1"
colored = "2.1.0"
itertools = "0.12.0"
rayon = "1.8.1"
term_size = "0.3.2"
term_size = "1.0.0-beta1"
termion = "3.0.0"

View file

@ -160,7 +160,7 @@ impl Env {
}
pub fn assemble_op(
&self,
&mut self,
op: (Token, Loc),
) -> Result<Vec<u32>, (RuntimeErr, Loc, Option<String>)> {
if let (Token::Op(name, args), loc) = op {
@ -183,26 +183,35 @@ impl Env {
));
}
let _ =
i.1.clone()
let _ = i
.1
.clone()
.into_iter()
.enumerate()
.try_for_each(|(k, v)| match v {
Arg::Immediate => {
if let Token::Immediate(i) = args[k].0 {
Arg::Immediate => match args[k].0.clone() {
Token::Immediate(i) => {
imm = i as u32;
Ok(())
}
Token::Symbol(s) => {
if let Some(v) = self.get_label(&s) {
imm = v - loc.mem_offset as u32;
Ok(())
} else {
Err((
RuntimeErr::InvalidType(
Arg::from(args[k].0.clone()).kind(),
v.kind(),
),
RuntimeErr::LabelNotFound,
args[k].1,
None,
))
}
}
_ => Err((
RuntimeErr::InvalidType(Arg::from(args[k].0.clone()).kind(), v.kind()),
args[k].1,
None,
)),
},
Arg::Register(id) => {
if let Token::Register(r) = &args[k].0 {
regs[id] = self.str_to_register(&r).unwrap();
@ -255,14 +264,14 @@ impl Env {
Ok(())
} else {
Err((
RuntimeErr::InvalidType(
Arg::from(args[k].0.clone()).kind(),
v.kind(),
),
RuntimeErr::LabelNotFound,
args[k].1,
None,
))
}
} else if let Token::Immediate(i) = &args[k].0 {
imm = *i as u32;
Ok(())
} else {
Err((
RuntimeErr::InvalidType(
@ -312,7 +321,7 @@ impl Env {
}
}
Token::Label(name) => {
self.add_label(&name, (i + 4) as u32);
self.add_label(&name, i as u32);
}
other => {
dbg!(other);

View file

@ -21,7 +21,7 @@ impl Display for SyntaxErr {
match self {
SyntaxErr::UnmatchedParen(_) => write!(f, "unmatched parenthesis"),
SyntaxErr::UnexpectedChar => write!(f, "unexpected character"),
SyntaxErr::OutsideOp(kind) => write!(f, "`{kind}` before opcode"),
SyntaxErr::OutsideOp(kind) => write!(f, "'{kind}' before opcode"),
SyntaxErr::InvalidRegister => write!(f, "invalid register"),
}
}
@ -49,18 +49,20 @@ pub enum RuntimeErr {
InvalidOpArity(String, usize, usize),
/// actual, expected
InvalidType(String, String),
LabelNotFound,
}
impl Display for RuntimeErr {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
RuntimeErr::InvalidOp => write!(f, "invalid opcode"),
RuntimeErr::InvalidOpArity(op, actual, expected) => {
write!(f, "`{}` expected {} args, got {}", op, expected, actual)
RuntimeErr::InvalidOpArity(_, actual, expected) => {
write!(f, "expected {} args, got {}", expected, actual)
}
RuntimeErr::InvalidType(actual, expected) => {
write!(f, "expected `{}`, got `{}`", expected, actual)
write!(f, "expected '{}', got '{}'", expected, actual)
}
RuntimeErr::LabelNotFound => write!(f, "label not found"),
}
}
}
@ -78,7 +80,7 @@ impl RuntimeErr {
}
Ordering::Greater => "remove the extra arguments".to_string(),
Ordering::Less if expected - actual == 1 => {
format!("add the extra `{}` argument", args.last().unwrap().kind())
format!("add the extra '{}' argument", args.last().unwrap().kind())
}
Ordering::Less => format!(
"add the extra `{}` arguments",
@ -86,11 +88,12 @@ impl RuntimeErr {
.unwrap()
.iter()
.map(|arg| arg.kind())
.join("`, `")
.join("', '")
),
}
}
RuntimeErr::InvalidType(_, _) => "ensure the operation is valid".to_string(),
RuntimeErr::LabelNotFound => "ensure the label is spelled correctly".to_string(),
}
}
}

View file

@ -5,9 +5,14 @@ fn lui(env: &mut Env, rd: usize, imm: u32) {
env.set_register(rd, imm);
}
/// add rd, ra, rb
fn add(env: &mut Env, rd: usize, ra: usize, rb: usize) {
env.set_register(rd, env.get_register(ra).wrapping_add(env.get_register(rb)));
}
/// addi rd, ra, imm
fn addi(env: &mut Env, rd: usize, ra: usize, imm: u32) {
env.set_register(rd, env.get_register(ra) + imm);
env.set_register(rd, env.get_register(ra).wrapping_add(imm));
}
/// xor rd, ra, rb
@ -15,41 +20,75 @@ fn xor(env: &mut Env, rd: usize, ra: usize, rb: usize) {
env.set_register(rd, env.get_register(ra) ^ env.get_register(rb));
}
/// mul rd, ra, rb
fn mul(env: &mut Env, rd: usize, ra: usize, rb: usize) {
env.set_register(rd, env.get_register(ra).wrapping_mul(env.get_register(rb)));
}
/// beq ra, rb, imm
fn beq(env: &mut Env, ra: usize, rb: usize, imm: u32) -> bool {
if env.get_register(ra) == env.get_register(rb) {
env.pc = env.pc.wrapping_add(imm);
return true;
}
false
}
/// jal rd, imm
fn jal(env: &mut Env, rd: usize, imm: u32) {
env.set_register(rd, env.pc);
env.pc += imm;
env.set_register(rd, env.pc + 4);
env.pc = env.pc.wrapping_add(imm);
}
/// fmadd.s fd, fa, fb, fc
fn fmadd_s(env: &mut Env, fd: usize, fa: usize, fb: usize, fc: usize) {
env.set_fregister(fd, env.get_fregister(fa) * env.get_fregister(fb) + env.get_fregister(fc));
env.set_fregister(
fd,
env.get_fregister(fa) * env.get_fregister(fb) + env.get_fregister(fc),
);
}
pub fn run_instruction(env: &mut Env, kind: Kind) {
pub fn run_instruction(env: &mut Env, instruction: u32) -> bool {
let (kind, _) = Kind::to_op(instruction);
let mut regs = kind.get_regs().unwrap();
// Ensure all four registers have a value
regs.extend([0].repeat(4 - regs.len()));
let (rd, ra, rb) = (regs[0], regs[1], regs[2]);
let (fd, fa, fb, fc) = (regs[0], regs[1], regs[2], regs[3]);
let imm = kind.get_imm().unwrap();
let imm = kind.get_imm();
let opcode = kind.get_opcode().unwrap();
let funct3 = instruction >> 12 & 0b111;
let funct7 = instruction >> 25 & 0b1111111;
match opcode {
0b0110111 => {
lui(env, rd, imm)
lui(env, rd, imm.unwrap());
false
}
0b0110011 if funct3 == 0b000 && funct7 == 0b0000000 => {
add(env, rd, ra, rb);
false
}
0b0010011 => {
addi(env, rd, ra, imm)
addi(env, rd, ra, imm.unwrap());
false
}
0b0110011 => {
xor(env, rd, ra, rb)
0b0110011 if funct3 == 0b100 && funct7 == 0b0000000 => {
xor(env, rd, ra, rb);
false
}
0b0110011 if funct3 == 0b000 && funct7 == 0b0000001 => {
mul(env, rd, ra, rb);
false
}
0b1100011 => beq(env, ra, rb, imm.unwrap()),
0b1101111 => {
jal(env, rd, imm)
jal(env, rd, imm.unwrap());
true
}
0b1000011 => {
fmadd_s(env, fd, fa, fb, fc)
fmadd_s(env, fd, fa, fb, fc);
false
}
_ => todo!(),
}

View file

@ -1,8 +1,5 @@
pub mod kind {
use std::{
fmt::{self, Display, Formatter},
mem,
};
use std::fmt::{self, Display, Formatter};
use bitfield::bitfield;
@ -154,21 +151,31 @@ pub mod kind {
Kind::Pseudo(_) => None,
Kind::R(_) => None,
Kind::R4(_) => None,
Kind::I(i) => Some(i.imm()),
Kind::I2(i2) => Some(i2.imm() >> 20),
Kind::I(i) => Some(if i.imm() >> 11 == 1 {
i.imm() | 0xFFFFF000
} else {
i.imm()
}),
Kind::I2(i2) => Some(if i2.imm() >> 5 == 1 {
i2.imm() | 0xFFFFFFE0
} else {
i2.imm()
}),
Kind::S(s) => Some(s.imm_11_5() | s.imm_4_0()),
Kind::B(b) => Some(
((b.imm_12() as u32) << 12)
| ((b.imm_11() as u32) << 11)
| (b.imm_10_5() << 5)
| (b.imm_4_1() << 1),
| (b.imm_4_1() << 1)
| if b.imm_12() == true { 0xFFFFE000 } else { 0 },
),
Kind::U(u) => Some(u.imm31_12() << 12),
Kind::J(j) => Some(
((j.imm_20() as u32) << 20)
| ((j.imm_19_12() as u32) << 12)
| ((j.imm_11() as u32) << 11)
| (j.imm_10_1() << 1),
| (j.imm_10_1() << 1)
| if j.imm_20() == true { 0xFFE00000 } else { 0 },
),
}
}
@ -194,17 +201,41 @@ pub mod kind {
pub fn to_op(instruction: u32) -> (Kind, String) {
let opcode = instruction & 0b00000000000000000000000001111111;
let funct3 = (instruction & 0b00000000000000000111000000000000) >> 12;
let funct7 = (instruction & 0b11111110000000000000000000000000) >> 25;
match opcode {
0b0110111 => (
Kind::U(unsafe { mem::transmute_copy(&instruction) }),
"lui".into(),
),
0b0010011 => (
Kind::I(unsafe { mem::transmute_copy(&instruction) }),
"addi".into(),
),
_ => todo!(),
0b0110111 => (Kind::U(U(instruction)), "lui".into()),
0b0010011 => (Kind::I(I(instruction)), "addi".into()),
0b0110011 if funct3 == 0b000 && funct7 == 0b0000000 => {
(Kind::R(R(instruction)), "add".into())
}
0b0110011 if funct3 == 0b000 && funct7 == 0b0100000 => {
(Kind::R(R(instruction)), "sub".into())
}
0b0110011 if funct3 == 0b000 && funct7 == 0b0000001 => {
(Kind::R(R(instruction)), "mul".into())
}
0b1100011 => (Kind::B(B(instruction)), "beq".into()),
0b1101111 => (Kind::J(J(instruction)), "jal".into()),
other => {
println!("{:07b}", other);
todo!()
}
}
}
pub fn to_u32(&self) -> u32 {
match self {
Kind::Pseudo(_) => unreachable!(),
Kind::R(r) => r.0,
Kind::R4(r4) => r4.0,
Kind::I(i) => i.0,
Kind::I2(i2) => i2.0,
Kind::S(s) => s.0,
Kind::B(b) => b.0,
Kind::U(u) => u.0,
Kind::J(j) => j.0,
}
}
}
@ -565,28 +596,32 @@ pub fn handle_pseudo(
with(get_instruction("addi"), 0, vec![0, 0]),
],
"li" => {
match imm {
// if the immediate is small enough (12 bits), use addi
_ if imm >> 12 == 0 => {
// if the immediate only has the lower 12 bits set, use addi
if imm >> 12 == 0 {
// addi rd, x0, imm
vec![with(get_instruction("addi"), imm, regs)]
}
// if the immediate is a multiple of 0x1000, use lui
_ if imm & 0xfff == 0 => {
else if imm & 0xfff == 0 {
// lui rd, imm
vec![with(get_instruction("lui"), imm, regs)]
}
// otherwise, use lui and addi
_ => vec![
else {
vec![
// lui rd, imm
with(get_instruction("lui"), imm & 0xfffff000, regs.clone()),
with(
get_instruction("lui"),
(imm & 0xFFFF000) | ((imm >> 11) & 0x1) << 12,
regs.clone(),
),
// addi rd, rd, imm
with(
get_instruction("addi"),
imm & 0x00000fff,
vec![regs[0], regs[0]],
),
],
]
}
}
"beqz" => vec![

View file

@ -7,11 +7,11 @@ use codespan_reporting::{
Config,
},
};
use colored::Colorize;
use itertools::Itertools;
use riscv_interpreter::{
env::Env,
execution::run_instruction,
instructions::kind::Kind,
parser::{parse, Token},
};
@ -19,12 +19,13 @@ fn main() -> anyhow::Result<()> {
let writer = StandardStream::stderr(ColorChoice::Always);
let config = Config::default();
let input = std::fs::read_to_string("test.s").unwrap();
let term_width = term_size::dimensions().map(|(w, _)| w).unwrap_or(80);
let file = SimpleFile::new("test.s", input.clone());
let mut env = Env::new();
let mut ops: Vec<(Kind, String)> = Vec::new();
let mut ops: Vec<u32> = Vec::new();
match parse(&env, &input) {
Ok(tokens) => {
@ -46,7 +47,7 @@ fn main() -> anyhow::Result<()> {
op[0],
loc.mem_offset
);
ops.push(Kind::to_op(op[0].clone()));
ops.push(op[0]);
if op.len() > 1 {
for op in op[1..].iter() {
@ -57,14 +58,14 @@ fn main() -> anyhow::Result<()> {
op,
loc.mem_offset
);
ops.push(Kind::to_op(op.clone()));
ops.push(*op);
}
}
println!("{}", formatted);
}
Err(err) => {
let diagnostic = Diagnostic::error()
.with_message("Runtime Error")
.with_message("Engine Error")
.with_labels(vec![Label::primary(
(),
err.1.start..(err.1.end + 1),
@ -120,11 +121,115 @@ fn main() -> anyhow::Result<()> {
}
};
for op in ops {
run_instruction(&mut env, op.0);
// Print the register values
println!("{}\n{}", op.1, env.registers.iter().enumerate().map(|(i, r)| format!("x{:<1$} {2:032b}", i.to_string() + ":", 3, r)).join("\n"));
while env.pc / 4 < ops.clone().len() as u32 {
let pc = env.pc.clone();
let prev_regs = env.registers.clone();
env.pc += 4 * !run_instruction(&mut env, ops[pc as usize >> 2]) as u32;
let mut changed = Vec::new();
for (i, _) in prev_regs
.iter()
.zip(env.registers.iter())
.enumerate()
.filter(|(_, (prev, curr))| prev != curr)
{
changed.push(i);
}
println!(
"{}",
make_box(
term_width as u32,
pc as usize,
env.registers.clone().into_iter().collect(),
changed,
's'
)
);
}
Ok(())
}
fn round_down_to_power_of_two(n: u32) -> u32 {
1 << (32 - n.leading_zeros() - 1)
}
/// Assuming the terminal is at least 80 characters wide
/// Display Mode:
/// - b: binary
/// - u: unsigned decimal
/// - h: hex
/// - s: signed decimal
/// - f: float
fn make_box(
width: u32,
pc: usize,
regs: Vec<u32>,
changed: Vec<usize>,
display_mode: char,
) -> String {
let cell_inner_width: u32 = match display_mode {
'b' => 32,
'u' => 10,
'h' => 8,
's' => 11,
'f' => todo!("float display mode"),
_ => unreachable!(),
} + 7;
// Nnumber of boxes that fit horizontally
let num_boxes = round_down_to_power_of_two((width / (cell_inner_width + 2)) as u32);
let mut boxed = String::new();
boxed += &format!(
"┌─╢ pc = {pc:04x} ╟{:─<1$}┬",
"",
cell_inner_width.saturating_sub(14) as usize
);
for _ in 1..(num_boxes - 1) {
boxed += &format!("{:─<1$}", "", cell_inner_width as usize);
}
boxed += &format!("{:─<1$}\n", "", cell_inner_width as usize);
for chunk in &regs.iter().enumerate().chunks(num_boxes as usize) {
let chunk = chunk.collect::<Vec<_>>();
let mut formatted = String::from("");
for (i, reg) in chunk {
let reg = match display_mode {
'b' => format!("x{:<3} {1:0>32b}", i.to_string() + ":", reg),
'u' => format!("x{:<3} {1:0>10}", i.to_string() + ":", reg),
'h' => format!("x{:<3} {1:0>8x}", i.to_string() + ":", reg),
's' => {
let signed = *reg as i32;
let sign = if signed < 0 { "-" } else { "+" };
format!("x{:<3} {}{:0>10}", i.to_string() + ":", sign, signed)
}
'f' => todo!("float display mode"),
_ => unreachable!(),
};
let reg = if changed.contains(&i) {
reg.bright_green()
} else {
reg.normal()
};
formatted += &format!("{}", reg);
}
boxed += &format!("{}\n", formatted);
}
boxed += &format!("{:─<1$}", "", cell_inner_width as usize);
for _ in 1..(num_boxes - 1) {
boxed += &format!("{:─<1$}", "", cell_inner_width as usize);
}
boxed += &format!("{:─<1$}", "", cell_inner_width as usize);
boxed
}

View file

@ -83,6 +83,81 @@ fn parse_line(env: &Env, input: &str, loc: &mut Loc) -> Result<Vec<(Token, Loc)>
Spacing
}
'0' if chars.peek() == Some(&'x') => {
chars.next();
loc.end += 1;
let mut num = std::string::String::new();
while let Some('0'..='9') | Some('a'..='f') | Some('A'..='F') = chars.peek() {
num.push(chars.next().unwrap());
loc.end += 1;
}
if let Some('(') | Some(' ') | None = chars.peek() {
Immediate(u32::from_str_radix(&num, 16).unwrap())
} else {
let err = Err((
SyntaxErr::UnexpectedChar,
Loc {
start: loc.end + 1,
end: loc.end + 1,
..*loc
},
tokens.clone(),
None,
));
advance_to_next_line(&mut chars, loc);
return err;
}
}
'0' if chars.peek() == Some(&'b') => {
chars.next();
loc.end += 1;
let mut num = std::string::String::new();
while let Some('0'..='1') = chars.peek() {
num.push(chars.next().unwrap());
loc.end += 1;
}
if let Some('(') | Some(' ') | None = chars.peek() {
Immediate(u32::from_str_radix(&num, 2).unwrap())
} else {
let err = Err((
SyntaxErr::UnexpectedChar,
Loc {
start: loc.end + 1,
end: loc.end + 1,
..*loc
},
tokens.clone(),
None,
));
advance_to_next_line(&mut chars, loc);
return err;
}
}
'0' if chars.peek() == Some(&'o') => {
chars.next();
loc.end += 1;
let mut num = std::string::String::new();
while let Some('0'..='7') = chars.peek() {
num.push(chars.next().unwrap());
loc.end += 1;
}
if let Some('(') | Some(' ') | None = chars.peek() {
Immediate(u32::from_str_radix(&num, 8).unwrap())
} else {
let err = Err((
SyntaxErr::UnexpectedChar,
Loc {
start: loc.end + 1,
end: loc.end + 1,
..*loc
},
tokens.clone(),
None,
));
advance_to_next_line(&mut chars, loc);
return err;
}
}
'0'..='9' => {
let mut num = c.to_string();
while let Some('0'..='9') = chars.peek() {

View file

@ -16,17 +16,13 @@ fn nop() {
};
// nop
assert_eq!(
u32::from_str_radix(
&handle_pseudo(
handle_pseudo(
get_instruction("nop"),
0, // imm
vec![]
)[0]
.0
.to_string(),
2
)
.unwrap(),
.to_u32(),
0b00000000000000000000000000010011
);
}
@ -42,12 +38,10 @@ fn li() {
// U-Type
// | imm20 | rd | opcode
// 00000000000000001101 01010 0110111
// 00000000000000001101 01010 0110111
// 2 -> addi
// I-Type
// | imm12 | ra |f3 | rd | opcode
// 000000101001 01010 000 01010 0010011
// 000000101001 01010 000 01010 0010011
};
// li a0 53289
assert!(handle_pseudo(
@ -56,7 +50,7 @@ fn li() {
vec![env.str_to_register("a0").unwrap()]
)
.into_iter()
.map(|i| u32::from_str_radix(dbg!(&i.0.to_string()), 2).unwrap())
.map(|i| i.0.to_u32())
.eq([
0b00000000000000001101010100110111,
0b00000010100101010000010100010011
@ -72,22 +66,19 @@ fn lui() {
{
// U-Type
// | imm20 | rd | opcode
// 00000000000000000011 01010 0110111
// 00000011010100101001 01010 0110111
// 11111111111101111011 01010 0110111
// 00001111111101111011 01010 0110111
};
// lui a0 13609
assert_eq!(
u32::from_str_radix(
&with(
with(
get_instruction("lui"),
13609 << 12,
vec![env.str_to_register("a0").unwrap()]
)
.0
.to_string(),
2
)
.unwrap(),
.to_u32(),
0b00000011010100101001010100110111
);
}
@ -104,8 +95,7 @@ fn sb() {
};
// sb t5 -4(sp)
assert_eq!(
u32::from_str_radix(
&with(
with(
get_instruction("sb"),
-4i32 as u32, // imm
vec![
@ -115,10 +105,7 @@ fn sb() {
],
)
.0
.to_string(),
2
)
.unwrap(),
.to_u32(),
0b11111111111000010000111000100011
);
}
@ -135,8 +122,7 @@ fn add() {
};
// add a0 a0 a1
assert_eq!(
u32::from_str_radix(
&with(
with(
get_instruction("add"),
0, // imm
vec![
@ -146,10 +132,7 @@ fn add() {
]
)
.0
.to_string(),
2
)
.unwrap(),
.to_u32(),
0b00000000101101010000010100110011
);
}
@ -167,7 +150,6 @@ fn addi() {
};
// addi a0 a0 1
assert_eq!(
u32::from_str_radix(
with(
get_instruction("addi"),
1,
@ -177,11 +159,7 @@ fn addi() {
],
)
.0
.to_string()
.as_str(),
2
)
.unwrap(),
.to_u32(),
0b00000000000101010000010100010011
);
}
@ -200,8 +178,7 @@ fn beq() {
};
// beq a0 a1 4
assert_eq!(
u32::from_str_radix(
&with(
with(
get_instruction("beq"),
4,
vec![
@ -211,10 +188,7 @@ fn beq() {
]
)
.0
.to_string(),
2
)
.unwrap(),
.to_u32(),
0b00000000101101010000001001100011
);
}

13
test.s
View file

@ -1,12 +1 @@
# li a0 55743235
li a1 1
# 5!
factorial:
# beqz a0 end
# mul a1 a1 a0
# addi a0 a0 -1
# j factorial
end:
# nop
li a0 -543643