Fix some assembling bugs

This commit is contained in:
Lumi Kalt 2024-01-23 15:46:30 +00:00
parent 78165b9b4e
commit 385278d8e9
6 changed files with 83 additions and 36 deletions

View file

@ -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 {
Token::Op(name, _) => {
if let Some((kind, args)) = instruction(&name) {
if let Kind::Pseudo(_) = kind {
handle_pseudo((kind, args), 0, vec![0; 4])
.into_iter()
.for_each(|_| i += 1);
} else {
i += 1;
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 += 4);
} else {
i += 4;
}
}
}
Token::Label(name) => {
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()),
));
}
Token::Label(name) => {
self.add_label(&name, (i + 1) * 4);
}
other => {
dbg!(other);
unreachable!()
}
});
} else {
unreachable!()
};
todo!()
}
}

0
src/execution.rs Normal file
View file

View 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] {

View file

@ -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;

View file

@ -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;
}
}

View file

@ -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