fixed BEQ, BGT, JAL, loops works. Fixed the encoder adress calculation for JAL's.

This commit is contained in:
raphy 2023-05-02 16:26:04 +02:00
parent 8513b62222
commit 3023e578b4
8 changed files with 102 additions and 22 deletions

View File

@ -31,5 +31,5 @@ pub enum Operation {
CALL(RegisterMem, Const), CALL(RegisterMem, Const),
// J Type // J Type
JAL(RegisterMem, RegisterMem, Word), JAL(RegisterMem, RegisterMem, Const),
} }

View File

@ -1,17 +1,18 @@
use super::{SymbolTable, AST::*}; use super::{AST::*};
use crate::cpu::{get_num, OP::*, get_memo}; use crate::cpu::{get_num, OP::*, get_memo};
pub trait CodeFormat { pub trait CodeFormat {
fn encode_op(op: &Operation, sy: &SymbolTable) -> Option<Self> fn encode_op(op: &Operation, sy: &SymbolTable, current_pc: u16) -> Option<Self>
where where
Self: Sized; Self: Sized;
} }
struct SyWrap<'a>(&'a SymbolTable); #[derive(Debug)]
pub struct SymbolTable(pub Vec<(String, u16)>);
impl SyWrap<'_> { impl SymbolTable {
pub fn lookup(&self, query: &str) -> u16 { pub fn lookup(&self, query: &str) -> u16 {
let SyWrap(sy) = self; let SymbolTable(sy) = self;
for (name, loc) in sy.into_iter() { for (name, loc) in sy.into_iter() {
if query == (*name) { if query == (*name) {
@ -26,8 +27,8 @@ impl SyWrap<'_> {
} }
impl CodeFormat for u16 { impl CodeFormat for u16 {
fn encode_op(op: &Operation, sy: &SymbolTable) -> Option<Self> { fn encode_op(op: &Operation, sy: &SymbolTable, current_pc: u16) -> Option<Self> {
let sy = SyWrap(sy); println!("encoding {:?}", op);
match op { match op {
Operation::NOP => Some(0b0000000000000000), Operation::NOP => Some(0b0000000000000000),
Operation::HALT => Some(0b1111111111111111), Operation::HALT => Some(0b1111111111111111),
@ -131,7 +132,10 @@ impl CodeFormat for u16 {
Operation::JAL(r1, r2, c) => { Operation::JAL(r1, r2, c) => {
let r1b = get_num(&r1)? as u16; let r1b = get_num(&r1)? as u16;
let r2b = get_num(&r2)? as u16; let r2b = get_num(&r2)? as u16;
let cb = (*c) as u16; let cb = match c {
Const::CS(label) => current_pc - sy.lookup(&label),
Const::C(n) => (*n) as u16,
};
return Some((0b1010 << 12) + (r1b << 8) + (r2b << 4) + cb); return Some((0b1010 << 12) + (r1b << 8) + (r2b << 4) + cb);
}, },
} }

View File

@ -4,6 +4,7 @@ pub mod parser;
mod tests; mod tests;
use encoder::{SymbolTable};
use encoder::CodeFormat; use encoder::CodeFormat;
use parser::Section; use parser::Section;
@ -13,7 +14,6 @@ use crate::loader::unloader::make_string;
use self::parser::SectionContent; use self::parser::SectionContent;
type SymbolTable = Vec<(String, u16)>;
impl Section { impl Section {
fn get_size(&self) -> usize { fn get_size(&self) -> usize {
@ -30,11 +30,15 @@ impl Section {
} }
fn to_binary(&self, sy: &SymbolTable) -> Option<Vec<u16>> { fn to_binary(&self, sy: &SymbolTable) -> Option<Vec<u16>> {
let own_address = sy.lookup(&self.name);
match &self.content { match &self.content {
SectionContent::Code(c) => { SectionContent::Code(c) => {
let mut res = vec![]; let mut res = vec![];
let mut pc = own_address;
for op in c.iter() { for op in c.iter() {
res.push(CodeFormat::encode_op(op, sy)?); println!("converting {:?}", op);
res.push(CodeFormat::encode_op(op, sy, pc)?);
pc += 1;
} }
return Some(res); return Some(res);
@ -75,7 +79,7 @@ fn sort_sections(sections: Vec<Section>) -> Option<Vec<Section>> {
return Some(res); return Some(res);
} }
fn make_symbol_table(sections: &Vec<Section>) -> Option<SymbolTable> { fn make_symbol_table<'a>(sections: &'a Vec<Section>) -> Option<SymbolTable> {
let mut res = vec![]; let mut res = vec![];
let mut pos : u16 = 0; let mut pos : u16 = 0;
@ -86,7 +90,7 @@ fn make_symbol_table(sections: &Vec<Section>) -> Option<SymbolTable> {
} }
return Some(res); return Some(SymbolTable(res));
} }

View File

@ -191,7 +191,7 @@ fn parse_code_line(i: &str) -> Result<Operation, ParseError> {
// every operation has at most 3 arguments // every operation has at most 3 arguments
let mut bits = i.split_whitespace(); let mut bits = i.split_whitespace();
println!("current parse code line: {}", i); println!("current parse code line: {}", i);
let Some(op) = bits.next() else {return Err(ParseError::BadSectionContent)}; let Some(op) = bits.next() else {return Err(ParseError::BadInstruction)};
// no type // no type
match op { match op {
@ -205,8 +205,8 @@ fn parse_code_line(i: &str) -> Result<Operation, ParseError> {
}; };
// I-type // I-type
let Some(r1) = bits.next() else {return Err(ParseError::BadSectionHeader)}; let Some(r1) = bits.next() else {return Err(ParseError::BadInstruction)};
let Some(r2) = bits.next() else {return Err(ParseError::BadSectionHeader)}; let Some(r2) = bits.next() else {return Err(ParseError::BadInstruction)};
match op { match op {
"addi" => { "addi" => {
@ -218,8 +218,43 @@ fn parse_code_line(i: &str) -> Result<Operation, ParseError> {
"call" => { "call" => {
return Ok(CALL(r1.to_owned(), parse_const(r2)?)); return Ok(CALL(r1.to_owned(), parse_const(r2)?));
} }
"halt" => { _ => {}
return Ok(HALT); }
let Some(r3) = bits.next() else {return Err(ParseError::BadInstruction)};
// R-type
match op {
"add" => {
return Ok(ADD(r1.to_owned(), r2.to_owned(), r3.to_owned()));
}
"sub" => {
return Ok(SUB(r1.to_owned(), r2.to_owned(), r3.to_owned()));
}
"and" => {
return Ok(AND(r1.to_owned(), r2.to_owned(), r3.to_owned()));
}
"xor" => {
return Ok(XOR(r1.to_owned(), r2.to_owned(), r3.to_owned()));
}
"sll" => {
return Ok(SLL(r1.to_owned(), r2.to_owned(), r3.to_owned()));
}
"beq" => {
return Ok(BEQ(r1.to_owned(), r2.to_owned(), r3.to_owned()));
}
"bgt" => {
return Ok(BGT(r1.to_owned(), r2.to_owned(), r3.to_owned()));
}
_ => {}
}
// J-type
match op {
"jal" => {
return Ok(JAL(r1.to_owned(), r2.to_owned(), parse_const(&r3)?));
} }
_ => {} _ => {}
} }

View File

@ -35,7 +35,7 @@ pub fn decode(op: u16) -> OP {
let c = Constant::from_be_bytes([(op & 0x00FF) as u8]); let c = Constant::from_be_bytes([(op & 0x00FF) as u8]);
let c4 = Constant::from_be_bytes([(op & 0x000F) as u8]); let c4 = Constant::from_be_bytes([(op & 0x000F) as u8]);
println!("opcode: {}", opcode); // println!("opcode: {}", opcode);
return match opcode { return match opcode {
// todo: write a macro for every type (I-type, R-type) // todo: write a macro for every type (I-type, R-type)

View File

@ -102,15 +102,23 @@ where
self.regs.pc += 1; self.regs.pc += 1;
} }
OP::BEQ(d, x0, x1) => { OP::BEQ(d, x0, x1) => {
if x0 == x1 { let v0 = self.regs.get(x0).ok_or(InvalidRegister)?;
let v1 = self.regs.get(x1).ok_or(InvalidRegister)?;
if v0 == v1 {
let v = self.regs.get(d).ok_or(InvalidRegister)?; let v = self.regs.get(d).ok_or(InvalidRegister)?;
self.regs.pc = v; self.regs.pc = v;
} else {
self.regs.pc += 1;
} }
} }
OP::BGT(d, x0, x1) => { OP::BGT(d, x0, x1) => {
if x0 > x1 { let v0 = self.regs.get(x0).ok_or(InvalidRegister)?;
let v1 = self.regs.get(x1).ok_or(InvalidRegister)?;
if v0 > v1 {
let v = self.regs.get(d).ok_or(InvalidRegister)?; let v = self.regs.get(d).ok_or(InvalidRegister)?;
self.regs.pc = v; self.regs.pc = v;
} else {
self.regs.pc += 1;
} }
} }
OP::JAL(s0, s1, c) => { OP::JAL(s0, s1, c) => {

View File

@ -1,3 +1,6 @@
use std::env::Args;
use std::env::args;
use dekejit::assembler::parser; use dekejit::assembler::parser;
use dekejit::assembler::to_binary; use dekejit::assembler::to_binary;
use dekejit::cpu::IOBuffer; use dekejit::cpu::IOBuffer;
@ -7,8 +10,18 @@ use dekejit::loader::unloader::*;
fn main() { fn main() {
let args : Vec<String> = args().collect();
let code = std::fs::read_to_string("./tests/assembly/hello_world.grasm").unwrap(); if args.len() < 2 {
println!("Scialla");
return;
}
// let code = std::fs::read_to_string("./tests/assembly/hello_world.grasm").unwrap();
let code = match std::fs::read_to_string(&args[1]) {
Ok(p) => p,
Err(_) => {println!("Could not open file '{}'", &args[1]); return;}
};
let mut parser = parser::Parser::new(code); let mut parser = parser::Parser::new(code);

16
tests/assembly/loop.grasm Normal file
View File

@ -0,0 +1,16 @@
.text main
addi t1 10
sub t0 t0 t0 ; set t0 = 0
addi t2 loop ; set t2 to loop's addr.
addi t3 end ; set t3 to end's addr
.text loop
call t0 0 ; print t0
addi t0 1 ; t0 = t0 + 1;
beq t3 t1 t0
beq t2 zero zero
.text end
halt