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),
// 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};
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
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 {
let SyWrap(sy) = self;
let SymbolTable(sy) = self;
for (name, loc) in sy.into_iter() {
if query == (*name) {
@ -26,8 +27,8 @@ impl SyWrap<'_> {
}
impl CodeFormat for u16 {
fn encode_op(op: &Operation, sy: &SymbolTable) -> Option<Self> {
let sy = SyWrap(sy);
fn encode_op(op: &Operation, sy: &SymbolTable, current_pc: u16) -> Option<Self> {
println!("encoding {:?}", op);
match op {
Operation::NOP => Some(0b0000000000000000),
Operation::HALT => Some(0b1111111111111111),
@ -131,7 +132,10 @@ impl CodeFormat for u16 {
Operation::JAL(r1, r2, c) => {
let r1b = get_num(&r1)? 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);
},
}

View File

@ -4,6 +4,7 @@ pub mod parser;
mod tests;
use encoder::{SymbolTable};
use encoder::CodeFormat;
use parser::Section;
@ -13,7 +14,6 @@ use crate::loader::unloader::make_string;
use self::parser::SectionContent;
type SymbolTable = Vec<(String, u16)>;
impl Section {
fn get_size(&self) -> usize {
@ -30,11 +30,15 @@ impl Section {
}
fn to_binary(&self, sy: &SymbolTable) -> Option<Vec<u16>> {
let own_address = sy.lookup(&self.name);
match &self.content {
SectionContent::Code(c) => {
let mut res = vec![];
let mut pc = own_address;
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);
@ -75,7 +79,7 @@ fn sort_sections(sections: Vec<Section>) -> Option<Vec<Section>> {
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 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
let mut bits = i.split_whitespace();
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
match op {
@ -205,8 +205,8 @@ fn parse_code_line(i: &str) -> Result<Operation, ParseError> {
};
// I-type
let Some(r1) = bits.next() else {return Err(ParseError::BadSectionHeader)};
let Some(r2) = 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::BadInstruction)};
match op {
"addi" => {
@ -218,8 +218,43 @@ fn parse_code_line(i: &str) -> Result<Operation, ParseError> {
"call" => {
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 c4 = Constant::from_be_bytes([(op & 0x000F) as u8]);
println!("opcode: {}", opcode);
// println!("opcode: {}", opcode);
return match opcode {
// todo: write a macro for every type (I-type, R-type)

View File

@ -102,15 +102,23 @@ where
self.regs.pc += 1;
}
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)?;
self.regs.pc = v;
} else {
self.regs.pc += 1;
}
}
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)?;
self.regs.pc = v;
} else {
self.regs.pc += 1;
}
}
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::to_binary;
use dekejit::cpu::IOBuffer;
@ -7,8 +10,18 @@ use dekejit::loader::unloader::*;
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);

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