Helper instruction functions, begin allowing the execution of instructions, start writing info statements for operations
This commit is contained in:
parent
385278d8e9
commit
e410fe0069
9 changed files with 282 additions and 39 deletions
83
Cargo.lock
generated
83
Cargo.lock
generated
|
@ -18,6 +18,16 @@ dependencies = [
|
|||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.5"
|
||||
|
@ -58,6 +68,12 @@ dependencies = [
|
|||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.8.1"
|
||||
|
@ -84,6 +100,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"codespan-reporting",
|
||||
"colored",
|
||||
"itertools",
|
||||
"rayon",
|
||||
]
|
||||
|
@ -133,3 +150,69 @@ name = "winapi-x86_64-pc-windows-gnu"
|
|||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
|
|
@ -6,5 +6,6 @@ edition = "2021"
|
|||
[dependencies]
|
||||
anyhow = "1.0.79"
|
||||
codespan-reporting = "0.11.1"
|
||||
colored = "2.1.0"
|
||||
itertools = "0.12.0"
|
||||
rayon = "1.8.1"
|
||||
|
|
25
src/env.rs
25
src/env.rs
|
@ -16,7 +16,7 @@ pub enum Variables {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Env {
|
||||
register_alias: HashMap<String, u32>,
|
||||
register_alias: HashMap<String, usize>,
|
||||
labels: HashMap<String, u32>,
|
||||
registers: [u32; 32],
|
||||
/// EQ, LT, GT
|
||||
|
@ -79,19 +79,20 @@ impl Env {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_register(&mut self, reg: u32, value: u32) {
|
||||
self.registers[reg as usize] = value;
|
||||
pub fn set_register(&mut self, reg: usize, value: u32) {
|
||||
if reg == 0 {
|
||||
return;
|
||||
}
|
||||
self.registers[reg] = value;
|
||||
}
|
||||
|
||||
pub fn get_register(&self, reg: u32) -> u32 {
|
||||
self.registers[reg as usize]
|
||||
pub fn get_register(&self, reg: usize) -> u32 {
|
||||
self.registers[reg]
|
||||
}
|
||||
|
||||
pub fn str_to_register(&self, reg: &str) -> Option<u32> {
|
||||
pub fn str_to_register(&self, reg: &str) -> Option<usize> {
|
||||
if reg == "x0" {
|
||||
Some(0)
|
||||
} else if reg.starts_with("x") && !reg[1..].starts_with("0") {
|
||||
match reg[1..].parse::<u32>() {
|
||||
match reg[1..].parse::<usize>() {
|
||||
Ok(n) if n < 32 => Some(n),
|
||||
_ => None,
|
||||
}
|
||||
|
@ -103,7 +104,6 @@ impl Env {
|
|||
pub fn add_label(&mut self, label: &str, value: u32) {
|
||||
self.labels.insert(label.to_string(), value);
|
||||
}
|
||||
|
||||
pub fn get_label(&self, label: &str) -> Option<u32> {
|
||||
self.labels.get(label).copied()
|
||||
}
|
||||
|
@ -273,7 +273,10 @@ impl Env {
|
|||
}
|
||||
|
||||
/// Assume memory offsets have been handled
|
||||
pub fn exec_op(&mut self, (op, loc): (Token, Loc)) -> Result<(), (RuntimeErr, Loc, Option<String>)> {
|
||||
pub fn exec_op(
|
||||
&mut self,
|
||||
(op, loc): (Token, Loc),
|
||||
) -> Result<(), (RuntimeErr, Loc, Option<String>)> {
|
||||
let (i, args) = if let Token::Op(name, args) = op {
|
||||
if let Some(i) = instruction(&name) {
|
||||
(i, args.clone())
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
use crate::{env::Env, instructions::kind::Kind};
|
||||
|
||||
/// lui rd, imm
|
||||
fn lui(env: &mut Env, rd: usize, imm: u32) {
|
||||
env.set_register(rd, imm);
|
||||
}
|
||||
|
||||
/// jal rd, imm
|
||||
fn jal(env: &mut Env, rd: usize, imm: u32) {
|
||||
env.set_register(rd, env.pc);
|
||||
env.pc += imm;
|
||||
}
|
||||
|
||||
const fn to_u32<const N: usize>(bits: &[bool; N]) -> u32 {
|
||||
let mut val = 0;
|
||||
for i in 0..N {
|
||||
if bits[i] {
|
||||
val |= 1 << i;
|
||||
}
|
||||
}
|
||||
val
|
||||
}
|
||||
|
||||
pub fn run_instruction(env: &mut Env, kind: Kind) {
|
||||
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, _rc) = (regs[0], regs[1], regs[2], regs[3]);
|
||||
let imm = kind.get_imm().unwrap();
|
||||
let opcode = kind.get_opcode().unwrap();
|
||||
|
||||
match to_u32(opcode) {
|
||||
0b0110111 => {
|
||||
lui(env, rd, imm)
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
30
src/info.rs
Normal file
30
src/info.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use colored::Colorize;
|
||||
|
||||
use crate::env::Env;
|
||||
|
||||
pub fn info(env: &Env, op: &str, args: Vec<String>) -> Vec<String> {
|
||||
match op {
|
||||
"nop" => vec!["Do nothing - wait 1 cycle".to_string()],
|
||||
"li" => vec![format!("load {} into the register {}", args[1], args[0])],
|
||||
"lui" => {
|
||||
let imm = format!("{:032b}", args[1].parse::<i32>().unwrap() as u32)
|
||||
.chars()
|
||||
.rev()
|
||||
.collect::<String>();
|
||||
vec![
|
||||
format!(
|
||||
"load the upper 20 bits of {} into the register {}",
|
||||
args[1], args[0]
|
||||
),
|
||||
format!(
|
||||
"{} = {}{}",
|
||||
args[1],
|
||||
imm[12..32].to_string().red(),
|
||||
imm[0..12].to_string()
|
||||
),
|
||||
format!("{:>1$} = {2}{3:0>12}", args[0], args[1].to_string().len(), imm[12..32].to_string(), "0".to_string().bold()),
|
||||
]
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
|
@ -3,6 +3,8 @@ pub mod kind {
|
|||
|
||||
use crate::instructions::to_u32;
|
||||
|
||||
use super::to_reg;
|
||||
|
||||
/// will be converted by the engine to a real instruction
|
||||
pub struct Pseudo(pub &'static str);
|
||||
|
||||
|
@ -108,6 +110,74 @@ pub mod kind {
|
|||
}
|
||||
}
|
||||
|
||||
impl Kind {
|
||||
pub fn get_opcode(&self) -> Option<&[bool; 7]> {
|
||||
match self {
|
||||
Kind::Pseudo(_) => None,
|
||||
Kind::R(r) => Some(&r.opcode),
|
||||
Kind::R4(r4) => Some(&r4.opcode),
|
||||
Kind::I(i) => Some(&i.opcode),
|
||||
Kind::I2(i2) => Some(&i2.opcode),
|
||||
Kind::S(s) => Some(&s.opcode),
|
||||
Kind::B(b) => Some(&b.opcode),
|
||||
Kind::U(u) => Some(&u.opcode),
|
||||
Kind::J(j) => Some(&j.opcode),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_imm(&self) -> Option<u32> {
|
||||
match self {
|
||||
Kind::Pseudo(_) => None,
|
||||
Kind::R(_) => None,
|
||||
Kind::R4(_) => None,
|
||||
Kind::I(i) => Some(to_u32(&i.imm)),
|
||||
Kind::I2(i2) => Some(to_u32(&i2.imm)),
|
||||
Kind::S(s) => {
|
||||
let mut imm = [false; 12];
|
||||
imm[0..=4].copy_from_slice(&s.imm2);
|
||||
imm[5..=11].copy_from_slice(&s.imm);
|
||||
Some(to_u32(&imm))
|
||||
}
|
||||
Kind::B(b) => {
|
||||
let mut imm = [false; 13];
|
||||
imm[1..=4].copy_from_slice(&b.imm2[1..=4]);
|
||||
imm[5..=10].copy_from_slice(&b.imm[0..=5]);
|
||||
imm[11] = b.imm2[0];
|
||||
imm[12] = b.imm[6];
|
||||
Some(to_u32(&imm))
|
||||
}
|
||||
Kind::U(u) => Some(to_u32(&u.imm) << 12),
|
||||
Kind::J(j) => {
|
||||
let mut imm = [false; 21];
|
||||
imm[1..=10].copy_from_slice(&j.imm[9..=18]);
|
||||
imm[11] = j.imm[8];
|
||||
imm[12..=19].copy_from_slice(&j.imm[0..=7]);
|
||||
imm[20] = j.imm[19];
|
||||
Some(to_u32(&imm))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_regs(&self) -> Option<Vec<usize>> {
|
||||
match self {
|
||||
Kind::Pseudo(_) => None,
|
||||
Kind::R(r) => Some(vec![to_reg(&r.rd), to_reg(&r.ra), to_reg(&r.rb)]),
|
||||
Kind::R4(r4) => Some(vec![
|
||||
to_reg(&r4.rd),
|
||||
to_reg(&r4.ra),
|
||||
to_reg(&r4.rb),
|
||||
to_reg(&r4.rc),
|
||||
]),
|
||||
Kind::I(i) => Some(vec![to_reg(&i.rd), to_reg(&i.ra)]),
|
||||
Kind::I2(i2) => Some(vec![to_reg(&i2.rd), to_reg(&i2.ra)]),
|
||||
Kind::S(s) => Some(vec![0, to_reg(&s.ra), to_reg(&s.rb)]),
|
||||
Kind::B(b) => Some(vec![0, to_reg(&b.ra), to_reg(&b.rb)]),
|
||||
Kind::U(u) => Some(vec![to_reg(&u.rd)]),
|
||||
Kind::J(j) => Some(vec![to_reg(&j.rd)]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Pseudo {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:0^32}", 0)
|
||||
|
@ -391,28 +461,28 @@ pub fn get_instruction(op: &str) -> (Kind, Vec<Arg>) {
|
|||
}
|
||||
|
||||
/// regs order: rd, ra, rb, rc
|
||||
pub fn with((kind, args): (Kind, Vec<Arg>), imm: u32, regs: Vec<u32>) -> (Kind, Vec<Arg>) {
|
||||
pub fn with((kind, args): (Kind, Vec<Arg>), imm: u32, regs: Vec<usize>) -> (Kind, Vec<Arg>) {
|
||||
match kind {
|
||||
Kind::Pseudo(_) => (kind, args),
|
||||
Kind::R(r) => (
|
||||
Kind::R(R {
|
||||
funct7: r.funct7,
|
||||
rb: to_bits(regs[2]),
|
||||
ra: to_bits(regs[1]),
|
||||
rb: reg_bits(regs[2]),
|
||||
ra: reg_bits(regs[1]),
|
||||
funct3: r.funct3,
|
||||
rd: to_bits(regs[0]),
|
||||
rd: reg_bits(regs[0]),
|
||||
opcode: r.opcode,
|
||||
}),
|
||||
args,
|
||||
),
|
||||
Kind::R4(r4) => (
|
||||
Kind::R4(R4 {
|
||||
rc: to_bits(regs[3]),
|
||||
rc: reg_bits(regs[3]),
|
||||
funct2: r4.funct2,
|
||||
rb: to_bits(regs[2]),
|
||||
ra: to_bits(regs[1]),
|
||||
rb: reg_bits(regs[2]),
|
||||
ra: reg_bits(regs[1]),
|
||||
funct3: r4.funct3,
|
||||
rd: to_bits(regs[0]),
|
||||
rd: reg_bits(regs[0]),
|
||||
opcode: r4.opcode,
|
||||
}),
|
||||
args,
|
||||
|
@ -420,9 +490,9 @@ pub fn with((kind, args): (Kind, Vec<Arg>), imm: u32, regs: Vec<u32>) -> (Kind,
|
|||
Kind::I(i) => (
|
||||
Kind::I(I {
|
||||
imm: to_bits(imm),
|
||||
ra: to_bits(regs[1]),
|
||||
ra: reg_bits(regs[1]),
|
||||
funct3: i.funct3,
|
||||
rd: to_bits(regs[0]),
|
||||
rd: reg_bits(regs[0]),
|
||||
opcode: i.opcode,
|
||||
}),
|
||||
args,
|
||||
|
@ -431,9 +501,9 @@ pub fn with((kind, args): (Kind, Vec<Arg>), imm: u32, regs: Vec<u32>) -> (Kind,
|
|||
Kind::I2(I2 {
|
||||
funct6: i2.funct6,
|
||||
imm: to_bits(imm),
|
||||
ra: to_bits(regs[1]),
|
||||
ra: reg_bits(regs[1]),
|
||||
funct3: i2.funct3,
|
||||
rd: to_bits(regs[0]),
|
||||
rd: reg_bits(regs[0]),
|
||||
opcode: i2.opcode,
|
||||
}),
|
||||
args,
|
||||
|
@ -447,8 +517,8 @@ pub fn with((kind, args): (Kind, Vec<Arg>), imm: u32, regs: Vec<u32>) -> (Kind,
|
|||
imm.copy_from_slice(&bits[5..=11]);
|
||||
imm
|
||||
},
|
||||
rb: to_bits(regs[2]),
|
||||
ra: to_bits(regs[1]),
|
||||
rb: reg_bits(regs[2]),
|
||||
ra: reg_bits(regs[1]),
|
||||
funct3: s.funct3,
|
||||
imm2: {
|
||||
let mut imm2 = [false; 5];
|
||||
|
@ -470,8 +540,8 @@ pub fn with((kind, args): (Kind, Vec<Arg>), imm: u32, regs: Vec<u32>) -> (Kind,
|
|||
imm[0..=5].copy_from_slice(&bits[5..=10]);
|
||||
imm
|
||||
},
|
||||
rb: to_bits(regs[2]),
|
||||
ra: to_bits(regs[1]),
|
||||
rb: reg_bits(regs[2]),
|
||||
ra: reg_bits(regs[1]),
|
||||
funct3: b.funct3,
|
||||
imm2: {
|
||||
let mut imm2 = [false; 5];
|
||||
|
@ -487,7 +557,7 @@ pub fn with((kind, args): (Kind, Vec<Arg>), imm: u32, regs: Vec<u32>) -> (Kind,
|
|||
Kind::U(u) => (
|
||||
Kind::U(U {
|
||||
imm: to_bits(imm >> 12), // 31:12
|
||||
rd: to_bits(regs[0]),
|
||||
rd: reg_bits(regs[0]),
|
||||
opcode: u.opcode,
|
||||
}),
|
||||
args,
|
||||
|
@ -503,7 +573,7 @@ pub fn with((kind, args): (Kind, Vec<Arg>), imm: u32, regs: Vec<u32>) -> (Kind,
|
|||
imm[0..=7].copy_from_slice(&bits[12..=19]);
|
||||
imm
|
||||
},
|
||||
rd: to_bits(regs[0]),
|
||||
rd: reg_bits(regs[0]),
|
||||
opcode: j.opcode,
|
||||
}),
|
||||
args,
|
||||
|
@ -515,7 +585,7 @@ pub fn with((kind, args): (Kind, Vec<Arg>), imm: u32, regs: Vec<u32>) -> (Kind,
|
|||
pub fn handle_pseudo(
|
||||
(kind, args): (Kind, Vec<Arg>),
|
||||
imm: u32,
|
||||
regs: Vec<u32>,
|
||||
regs: Vec<usize>,
|
||||
) -> Vec<(Kind, Vec<Arg>)> {
|
||||
let op = if let Kind::Pseudo(Pseudo(op)) = kind {
|
||||
op
|
||||
|
@ -532,16 +602,24 @@ pub fn handle_pseudo(
|
|||
match imm {
|
||||
// if the immediate is small enough (12 bits), 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 => {
|
||||
// lui rd, imm
|
||||
vec![with(get_instruction("lui"), imm, regs)]
|
||||
}
|
||||
// otherwise, use lui and addi
|
||||
_ => vec![
|
||||
// lui rd, imm
|
||||
with(get_instruction("lui"), imm & 0xfffff000, regs.clone()),
|
||||
with(get_instruction("addi"), imm & 0x00000fff, regs),
|
||||
// addi rd, rd, imm
|
||||
with(
|
||||
get_instruction("addi"),
|
||||
imm & 0x00000fff,
|
||||
vec![regs[0], regs[0]],
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
@ -572,6 +650,10 @@ const fn to_bits<const N: usize>(val: u32) -> [bool; N] {
|
|||
bits
|
||||
}
|
||||
|
||||
const fn reg_bits<const N: usize>(reg: usize) -> [bool; N] {
|
||||
to_bits(reg as u32)
|
||||
}
|
||||
|
||||
const fn to_u32<const N: usize>(bits: &[bool; N]) -> u32 {
|
||||
let mut val = 0;
|
||||
for i in 0..N {
|
||||
|
@ -581,3 +663,7 @@ const fn to_u32<const N: usize>(bits: &[bool; N]) -> u32 {
|
|||
}
|
||||
val
|
||||
}
|
||||
|
||||
const fn to_reg<const N: usize>(bits: &[bool; N]) -> usize {
|
||||
to_u32(bits) as usize
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
pub mod env;
|
||||
pub mod err;
|
||||
pub mod execution;
|
||||
pub mod info;
|
||||
pub mod instructions;
|
||||
pub mod parser;
|
||||
pub mod tests;
|
||||
|
|
|
@ -8,8 +8,7 @@ use codespan_reporting::{
|
|||
},
|
||||
};
|
||||
use riscv_interpreter::{
|
||||
env::Env,
|
||||
parser::{parse, Token},
|
||||
env::Env, info::info, parser::{parse, Token}
|
||||
};
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
|
@ -105,5 +104,7 @@ fn main() -> anyhow::Result<()> {
|
|||
}
|
||||
};
|
||||
|
||||
println!("{}", info(&env, "lui", vec!["a0".to_string(), "573498".to_string()]).join("\n"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
12
test.s
12
test.s
|
@ -1,12 +1,12 @@
|
|||
li a0 55743235
|
||||
# li a0 55743235
|
||||
li a1 1
|
||||
|
||||
# 5!
|
||||
factorial:
|
||||
beqz a0 end
|
||||
mul a1 a1 a0
|
||||
addi a0 a0 -1
|
||||
j factorial
|
||||
# beqz a0 end
|
||||
# mul a1 a1 a0
|
||||
# addi a0 a0 -1
|
||||
# j factorial
|
||||
|
||||
end:
|
||||
nop
|
||||
# nop
|
||||
|
|
Loading…
Reference in a new issue