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",
|
"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]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
|
@ -58,6 +68,12 @@ dependencies = [
|
||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon"
|
name = "rayon"
|
||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
|
@ -84,6 +100,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"codespan-reporting",
|
"codespan-reporting",
|
||||||
|
"colored",
|
||||||
"itertools",
|
"itertools",
|
||||||
"rayon",
|
"rayon",
|
||||||
]
|
]
|
||||||
|
@ -133,3 +150,69 @@ name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
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]
|
[dependencies]
|
||||||
anyhow = "1.0.79"
|
anyhow = "1.0.79"
|
||||||
codespan-reporting = "0.11.1"
|
codespan-reporting = "0.11.1"
|
||||||
|
colored = "2.1.0"
|
||||||
itertools = "0.12.0"
|
itertools = "0.12.0"
|
||||||
rayon = "1.8.1"
|
rayon = "1.8.1"
|
||||||
|
|
25
src/env.rs
25
src/env.rs
|
@ -16,7 +16,7 @@ pub enum Variables {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Env {
|
pub struct Env {
|
||||||
register_alias: HashMap<String, u32>,
|
register_alias: HashMap<String, usize>,
|
||||||
labels: HashMap<String, u32>,
|
labels: HashMap<String, u32>,
|
||||||
registers: [u32; 32],
|
registers: [u32; 32],
|
||||||
/// EQ, LT, GT
|
/// EQ, LT, GT
|
||||||
|
@ -79,19 +79,20 @@ impl Env {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_register(&mut self, reg: u32, value: u32) {
|
pub fn set_register(&mut self, reg: usize, value: u32) {
|
||||||
self.registers[reg as usize] = value;
|
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 {
|
||||||
pub fn str_to_register(&self, reg: &str) -> Option<u32> {
|
self.registers[reg]
|
||||||
|
}
|
||||||
|
pub fn str_to_register(&self, reg: &str) -> Option<usize> {
|
||||||
if reg == "x0" {
|
if reg == "x0" {
|
||||||
Some(0)
|
Some(0)
|
||||||
} else if reg.starts_with("x") && !reg[1..].starts_with("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),
|
Ok(n) if n < 32 => Some(n),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -103,7 +104,6 @@ impl Env {
|
||||||
pub fn add_label(&mut self, label: &str, value: u32) {
|
pub fn add_label(&mut self, label: &str, value: u32) {
|
||||||
self.labels.insert(label.to_string(), value);
|
self.labels.insert(label.to_string(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_label(&self, label: &str) -> Option<u32> {
|
pub fn get_label(&self, label: &str) -> Option<u32> {
|
||||||
self.labels.get(label).copied()
|
self.labels.get(label).copied()
|
||||||
}
|
}
|
||||||
|
@ -273,7 +273,10 @@ impl Env {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assume memory offsets have been handled
|
/// 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 {
|
let (i, args) = if let Token::Op(name, args) = op {
|
||||||
if let Some(i) = instruction(&name) {
|
if let Some(i) = instruction(&name) {
|
||||||
(i, args.clone())
|
(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 crate::instructions::to_u32;
|
||||||
|
|
||||||
|
use super::to_reg;
|
||||||
|
|
||||||
/// will be converted by the engine to a real instruction
|
/// will be converted by the engine to a real instruction
|
||||||
pub struct Pseudo(pub &'static str);
|
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 {
|
impl Display for Pseudo {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{:0^32}", 0)
|
write!(f, "{:0^32}", 0)
|
||||||
|
@ -391,28 +461,28 @@ pub fn get_instruction(op: &str) -> (Kind, Vec<Arg>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// regs order: rd, ra, rb, rc
|
/// 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 {
|
match kind {
|
||||||
Kind::Pseudo(_) => (kind, args),
|
Kind::Pseudo(_) => (kind, args),
|
||||||
Kind::R(r) => (
|
Kind::R(r) => (
|
||||||
Kind::R(R {
|
Kind::R(R {
|
||||||
funct7: r.funct7,
|
funct7: r.funct7,
|
||||||
rb: to_bits(regs[2]),
|
rb: reg_bits(regs[2]),
|
||||||
ra: to_bits(regs[1]),
|
ra: reg_bits(regs[1]),
|
||||||
funct3: r.funct3,
|
funct3: r.funct3,
|
||||||
rd: to_bits(regs[0]),
|
rd: reg_bits(regs[0]),
|
||||||
opcode: r.opcode,
|
opcode: r.opcode,
|
||||||
}),
|
}),
|
||||||
args,
|
args,
|
||||||
),
|
),
|
||||||
Kind::R4(r4) => (
|
Kind::R4(r4) => (
|
||||||
Kind::R4(R4 {
|
Kind::R4(R4 {
|
||||||
rc: to_bits(regs[3]),
|
rc: reg_bits(regs[3]),
|
||||||
funct2: r4.funct2,
|
funct2: r4.funct2,
|
||||||
rb: to_bits(regs[2]),
|
rb: reg_bits(regs[2]),
|
||||||
ra: to_bits(regs[1]),
|
ra: reg_bits(regs[1]),
|
||||||
funct3: r4.funct3,
|
funct3: r4.funct3,
|
||||||
rd: to_bits(regs[0]),
|
rd: reg_bits(regs[0]),
|
||||||
opcode: r4.opcode,
|
opcode: r4.opcode,
|
||||||
}),
|
}),
|
||||||
args,
|
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) => (
|
||||||
Kind::I(I {
|
Kind::I(I {
|
||||||
imm: to_bits(imm),
|
imm: to_bits(imm),
|
||||||
ra: to_bits(regs[1]),
|
ra: reg_bits(regs[1]),
|
||||||
funct3: i.funct3,
|
funct3: i.funct3,
|
||||||
rd: to_bits(regs[0]),
|
rd: reg_bits(regs[0]),
|
||||||
opcode: i.opcode,
|
opcode: i.opcode,
|
||||||
}),
|
}),
|
||||||
args,
|
args,
|
||||||
|
@ -431,9 +501,9 @@ pub fn with((kind, args): (Kind, Vec<Arg>), imm: u32, regs: Vec<u32>) -> (Kind,
|
||||||
Kind::I2(I2 {
|
Kind::I2(I2 {
|
||||||
funct6: i2.funct6,
|
funct6: i2.funct6,
|
||||||
imm: to_bits(imm),
|
imm: to_bits(imm),
|
||||||
ra: to_bits(regs[1]),
|
ra: reg_bits(regs[1]),
|
||||||
funct3: i2.funct3,
|
funct3: i2.funct3,
|
||||||
rd: to_bits(regs[0]),
|
rd: reg_bits(regs[0]),
|
||||||
opcode: i2.opcode,
|
opcode: i2.opcode,
|
||||||
}),
|
}),
|
||||||
args,
|
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.copy_from_slice(&bits[5..=11]);
|
||||||
imm
|
imm
|
||||||
},
|
},
|
||||||
rb: to_bits(regs[2]),
|
rb: reg_bits(regs[2]),
|
||||||
ra: to_bits(regs[1]),
|
ra: reg_bits(regs[1]),
|
||||||
funct3: s.funct3,
|
funct3: s.funct3,
|
||||||
imm2: {
|
imm2: {
|
||||||
let mut imm2 = [false; 5];
|
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[0..=5].copy_from_slice(&bits[5..=10]);
|
||||||
imm
|
imm
|
||||||
},
|
},
|
||||||
rb: to_bits(regs[2]),
|
rb: reg_bits(regs[2]),
|
||||||
ra: to_bits(regs[1]),
|
ra: reg_bits(regs[1]),
|
||||||
funct3: b.funct3,
|
funct3: b.funct3,
|
||||||
imm2: {
|
imm2: {
|
||||||
let mut imm2 = [false; 5];
|
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) => (
|
||||||
Kind::U(U {
|
Kind::U(U {
|
||||||
imm: to_bits(imm >> 12), // 31:12
|
imm: to_bits(imm >> 12), // 31:12
|
||||||
rd: to_bits(regs[0]),
|
rd: reg_bits(regs[0]),
|
||||||
opcode: u.opcode,
|
opcode: u.opcode,
|
||||||
}),
|
}),
|
||||||
args,
|
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[0..=7].copy_from_slice(&bits[12..=19]);
|
||||||
imm
|
imm
|
||||||
},
|
},
|
||||||
rd: to_bits(regs[0]),
|
rd: reg_bits(regs[0]),
|
||||||
opcode: j.opcode,
|
opcode: j.opcode,
|
||||||
}),
|
}),
|
||||||
args,
|
args,
|
||||||
|
@ -515,7 +585,7 @@ pub fn with((kind, args): (Kind, Vec<Arg>), imm: u32, regs: Vec<u32>) -> (Kind,
|
||||||
pub fn handle_pseudo(
|
pub fn handle_pseudo(
|
||||||
(kind, args): (Kind, Vec<Arg>),
|
(kind, args): (Kind, Vec<Arg>),
|
||||||
imm: u32,
|
imm: u32,
|
||||||
regs: Vec<u32>,
|
regs: Vec<usize>,
|
||||||
) -> Vec<(Kind, Vec<Arg>)> {
|
) -> Vec<(Kind, Vec<Arg>)> {
|
||||||
let op = if let Kind::Pseudo(Pseudo(op)) = kind {
|
let op = if let Kind::Pseudo(Pseudo(op)) = kind {
|
||||||
op
|
op
|
||||||
|
@ -532,16 +602,24 @@ pub fn handle_pseudo(
|
||||||
match imm {
|
match imm {
|
||||||
// if the immediate is small enough (12 bits), use addi
|
// if the immediate is small enough (12 bits), use addi
|
||||||
_ if imm >> 12 == 0 => {
|
_ if imm >> 12 == 0 => {
|
||||||
|
// addi rd, x0, imm
|
||||||
vec![with(get_instruction("addi"), imm, regs)]
|
vec![with(get_instruction("addi"), imm, regs)]
|
||||||
}
|
}
|
||||||
// if the immediate is a multiple of 0x1000, use lui
|
// if the immediate is a multiple of 0x1000, use lui
|
||||||
_ if imm & 0xfff == 0 => {
|
_ if imm & 0xfff == 0 => {
|
||||||
|
// lui rd, imm
|
||||||
vec![with(get_instruction("lui"), imm, regs)]
|
vec![with(get_instruction("lui"), imm, regs)]
|
||||||
}
|
}
|
||||||
// otherwise, use lui and addi
|
// otherwise, use lui and addi
|
||||||
_ => vec![
|
_ => vec![
|
||||||
|
// lui rd, imm
|
||||||
with(get_instruction("lui"), imm & 0xfffff000, regs.clone()),
|
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
|
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 {
|
const fn to_u32<const N: usize>(bits: &[bool; N]) -> u32 {
|
||||||
let mut val = 0;
|
let mut val = 0;
|
||||||
for i in 0..N {
|
for i in 0..N {
|
||||||
|
@ -581,3 +663,7 @@ const fn to_u32<const N: usize>(bits: &[bool; N]) -> u32 {
|
||||||
}
|
}
|
||||||
val
|
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 env;
|
||||||
pub mod err;
|
pub mod err;
|
||||||
pub mod execution;
|
pub mod execution;
|
||||||
|
pub mod info;
|
||||||
pub mod instructions;
|
pub mod instructions;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod tests;
|
pub mod tests;
|
||||||
|
|
|
@ -8,8 +8,7 @@ use codespan_reporting::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use riscv_interpreter::{
|
use riscv_interpreter::{
|
||||||
env::Env,
|
env::Env, info::info, parser::{parse, Token}
|
||||||
parser::{parse, Token},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
12
test.s
12
test.s
|
@ -1,12 +1,12 @@
|
||||||
li a0 55743235
|
# li a0 55743235
|
||||||
li a1 1
|
li a1 1
|
||||||
|
|
||||||
# 5!
|
# 5!
|
||||||
factorial:
|
factorial:
|
||||||
beqz a0 end
|
# beqz a0 end
|
||||||
mul a1 a1 a0
|
# mul a1 a1 a0
|
||||||
addi a0 a0 -1
|
# addi a0 a0 -1
|
||||||
j factorial
|
# j factorial
|
||||||
|
|
||||||
end:
|
end:
|
||||||
nop
|
# nop
|
||||||
|
|
Loading…
Reference in a new issue