Fix some assembling bugs
This commit is contained in:
parent
78165b9b4e
commit
385278d8e9
6 changed files with 83 additions and 36 deletions
49
src/env.rs
49
src/env.rs
|
@ -6,7 +6,7 @@ use crate::{
|
|||
parser::{Loc, Token},
|
||||
};
|
||||
|
||||
pub enum SymbolValue {
|
||||
pub enum Variables {
|
||||
Byte(u8),
|
||||
Half(u16),
|
||||
Word(u32),
|
||||
|
@ -16,12 +16,14 @@ pub enum SymbolValue {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Env {
|
||||
pub register_alias: HashMap<String, u32>,
|
||||
register_alias: HashMap<String, u32>,
|
||||
labels: HashMap<String, u32>,
|
||||
registers: [u32; 32],
|
||||
pub stack: Vec<u32>, // TODO: Find the size of the stack
|
||||
/// EQ, LT, GT
|
||||
pub cmp_flags: [bool; 3],
|
||||
pub stack: Vec<u32>, // TODO: Find the actual size of the stack
|
||||
pub instructions: Vec<u32>,
|
||||
pc: u32,
|
||||
pub pc: u32,
|
||||
}
|
||||
|
||||
impl Env {
|
||||
|
@ -70,6 +72,7 @@ impl Env {
|
|||
register_alias,
|
||||
labels: HashMap::new(),
|
||||
registers: [0; 32],
|
||||
cmp_flags: [false; 3],
|
||||
stack: Vec::from([0; 1024]), // 1024 * 64 = 64 KiB stack
|
||||
instructions: Vec::new(),
|
||||
pc: 0,
|
||||
|
@ -197,7 +200,7 @@ impl Env {
|
|||
Arg::Symbol => {
|
||||
if let Token::Symbol(s) = &args[k].0 {
|
||||
if let Some(v) = self.get_label(&s) {
|
||||
imm = v;
|
||||
imm = (v).wrapping_sub(loc.mem_offset as u32);
|
||||
Ok(())
|
||||
} else {
|
||||
Err((
|
||||
|
@ -236,29 +239,55 @@ impl Env {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn handle_labels(&mut self, tokens: Vec<(Token, Loc)>) {
|
||||
pub fn handle_mem_offsets(&mut self, mut tokens: Vec<(Token, Loc)>) -> Vec<(Token, Loc)> {
|
||||
let mut i = 0;
|
||||
// Calculate the instruction position for all opcodes to
|
||||
// allow for labels to be used before they are defined
|
||||
tokens.into_iter().for_each(|(token, _)| match token {
|
||||
tokens
|
||||
.clone()
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.for_each(|(id, (token, _))| match token {
|
||||
Token::Op(name, _) => {
|
||||
if let Some((kind, args)) = instruction(&name) {
|
||||
if let Kind::Pseudo(_) = kind {
|
||||
tokens[id].1.mem_offset = i + 4;
|
||||
handle_pseudo((kind, args), 0, vec![0; 4])
|
||||
.into_iter()
|
||||
.for_each(|_| i += 1);
|
||||
.for_each(|_| i += 4);
|
||||
} else {
|
||||
i += 1;
|
||||
i += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
Token::Label(name) => {
|
||||
self.add_label(&name, (i + 1) * 4);
|
||||
self.add_label(&name, (i + 4) as u32);
|
||||
}
|
||||
other => {
|
||||
dbg!(other);
|
||||
unreachable!()
|
||||
}
|
||||
});
|
||||
|
||||
tokens
|
||||
}
|
||||
|
||||
/// Assume memory offsets have been handled
|
||||
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())
|
||||
} else {
|
||||
return Err((
|
||||
RuntimeErr::InvalidOp,
|
||||
loc,
|
||||
Some("no implementation exists".to_string()),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
0
src/execution.rs
Normal file
0
src/execution.rs
Normal file
|
@ -444,7 +444,7 @@ pub fn with((kind, args): (Kind, Vec<Arg>), imm: u32, regs: Vec<u32>) -> (Kind,
|
|||
Kind::S(S {
|
||||
imm: {
|
||||
let mut imm = [false; 7];
|
||||
imm.copy_from_slice(&bits[5..=11]); //.into_iter().rev().map(|&b| b).collect::<Vec<_>>()[..]);
|
||||
imm.copy_from_slice(&bits[5..=11]);
|
||||
imm
|
||||
},
|
||||
rb: to_bits(regs[2]),
|
||||
|
@ -452,7 +452,7 @@ pub fn with((kind, args): (Kind, Vec<Arg>), imm: u32, regs: Vec<u32>) -> (Kind,
|
|||
funct3: s.funct3,
|
||||
imm2: {
|
||||
let mut imm2 = [false; 5];
|
||||
imm2.copy_from_slice(&bits[0..=4]); //.into_iter().rev().map(|&b| b).collect::<Vec<_>>()[..]);
|
||||
imm2.copy_from_slice(&bits[0..=4]);
|
||||
imm2
|
||||
},
|
||||
opcode: s.opcode,
|
||||
|
@ -547,15 +547,15 @@ pub fn handle_pseudo(
|
|||
}
|
||||
"beqz" => vec![
|
||||
// beq ra, x0, imm
|
||||
with(get_instruction("beq"), imm, vec![0, regs[0], 0]),
|
||||
with(get_instruction("beq"), imm, regs),
|
||||
],
|
||||
"bnez" => vec![
|
||||
// bne ra, x0, imm
|
||||
with(get_instruction("bne"), imm, vec![0, regs[0], 0]),
|
||||
with(get_instruction("bne"), imm, regs),
|
||||
],
|
||||
"j" => vec![
|
||||
// jal x0, imm
|
||||
with(get_instruction("jal"), imm, vec![0]),
|
||||
with(get_instruction("jal"), imm, regs),
|
||||
],
|
||||
other => {
|
||||
dbg!(other);
|
||||
|
@ -564,7 +564,7 @@ pub fn handle_pseudo(
|
|||
}
|
||||
}
|
||||
|
||||
fn to_bits<const N: usize>(val: u32) -> [bool; N] {
|
||||
const fn to_bits<const N: usize>(val: u32) -> [bool; N] {
|
||||
let mut bits = [false; N];
|
||||
for i in 0..N {
|
||||
bits[i] = (val >> i) & 1 == 1;
|
||||
|
@ -572,7 +572,7 @@ fn to_bits<const N: usize>(val: u32) -> [bool; N] {
|
|||
bits
|
||||
}
|
||||
|
||||
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;
|
||||
for i in 0..N {
|
||||
if bits[i] {
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
#![feature(const_for)]
|
||||
#![feature(const_mut_refs)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(effects)]
|
||||
|
||||
pub mod env;
|
||||
pub mod err;
|
||||
pub mod execution;
|
||||
pub mod instructions;
|
||||
pub mod parser;
|
||||
pub mod tests;
|
||||
|
|
|
@ -27,14 +27,12 @@ fn main() -> anyhow::Result<()> {
|
|||
let size = lines.iter().map(|l| l.len()).max().unwrap();
|
||||
let mut i = 0;
|
||||
|
||||
tokens.iter().for_each(|(token, loc)| {
|
||||
env.handle_mem_offsets(tokens).iter().for_each(|(token, loc)| {
|
||||
let token = token.clone();
|
||||
env.handle_labels(tokens.clone());
|
||||
|
||||
match token.clone() {
|
||||
Token::Op(..) => match env.assemble_op((token, loc.clone())) {
|
||||
Ok(op) => {
|
||||
let addr = (loc.line - 1) * 4;
|
||||
let mut formatted = format!(
|
||||
"{:<1$} {3:02x}: {2:032b}",
|
||||
lines[loc.line - 1],
|
||||
|
@ -46,7 +44,8 @@ fn main() -> anyhow::Result<()> {
|
|||
|
||||
if op.len() > 1 {
|
||||
for op in op[1..].iter() {
|
||||
formatted += &format!("\n{:<1$} {3:02x}: {2:032b}", "", size + 3, op, i);
|
||||
formatted +=
|
||||
&format!("\n{:<1$} {3:02x}: {2:032b}", "", size + 3, op, i);
|
||||
i += 4;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,18 @@ pub struct Loc {
|
|||
pub line: usize,
|
||||
pub start: usize,
|
||||
pub end: usize,
|
||||
pub mem_offset: usize,
|
||||
}
|
||||
|
||||
impl Default for Loc {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
line: 0,
|
||||
start: 0,
|
||||
end: 0,
|
||||
mem_offset: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_line(env: &Env, input: &str, loc: &mut Loc) -> Result<Vec<(Token, Loc)>, ParseErr> {
|
||||
|
@ -83,9 +95,9 @@ fn parse_line(env: &Env, input: &str, loc: &mut Loc) -> Result<Vec<(Token, Loc)>
|
|||
let err = Err((
|
||||
SyntaxErr::UnexpectedChar,
|
||||
Loc {
|
||||
line: loc.line,
|
||||
start: loc.end + 1,
|
||||
end: loc.end + 1,
|
||||
..*loc
|
||||
},
|
||||
tokens.clone(),
|
||||
None,
|
||||
|
@ -134,9 +146,9 @@ fn parse_line(env: &Env, input: &str, loc: &mut Loc) -> Result<Vec<(Token, Loc)>
|
|||
let err = Err((
|
||||
SyntaxErr::InvalidRegister,
|
||||
Loc {
|
||||
line: loc.line,
|
||||
start,
|
||||
end,
|
||||
..*loc
|
||||
},
|
||||
tokens.clone(),
|
||||
None,
|
||||
|
@ -282,6 +294,7 @@ pub fn parse(env: &Env, input: &str) -> Result<Vec<(Token, Loc)>, Vec<ParseErr>>
|
|||
line: 0,
|
||||
start: 0,
|
||||
end: 0,
|
||||
mem_offset: 0,
|
||||
};
|
||||
|
||||
let parsed_lines = input
|
||||
|
|
Loading…
Reference in a new issue