diff --git a/src/assembler/AST.rs b/src/assembler/AST.rs index 57e4efc..8d1e15c 100644 --- a/src/assembler/AST.rs +++ b/src/assembler/AST.rs @@ -31,5 +31,5 @@ pub enum Operation { CALL(RegisterMem, Const), // J Type - JAL(RegisterMem, RegisterMem, Word), + JAL(RegisterMem, RegisterMem, Const), } diff --git a/src/assembler/encoder.rs b/src/assembler/encoder.rs index 02108fd..7b949e8 100644 --- a/src/assembler/encoder.rs +++ b/src/assembler/encoder.rs @@ -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 + fn encode_op(op: &Operation, sy: &SymbolTable, current_pc: u16) -> Option 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 { - let sy = SyWrap(sy); + fn encode_op(op: &Operation, sy: &SymbolTable, current_pc: u16) -> Option { + 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); }, } diff --git a/src/assembler/mod.rs b/src/assembler/mod.rs index df8d06c..535d247 100644 --- a/src/assembler/mod.rs +++ b/src/assembler/mod.rs @@ -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> { + 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
) -> Option> { return Some(res); } -fn make_symbol_table(sections: &Vec
) -> Option { +fn make_symbol_table<'a>(sections: &'a Vec
) -> Option { let mut res = vec![]; let mut pos : u16 = 0; @@ -86,7 +90,7 @@ fn make_symbol_table(sections: &Vec
) -> Option { } - return Some(res); + return Some(SymbolTable(res)); } diff --git a/src/assembler/parser.rs b/src/assembler/parser.rs index 28a27bb..86a885e 100644 --- a/src/assembler/parser.rs +++ b/src/assembler/parser.rs @@ -191,7 +191,7 @@ fn parse_code_line(i: &str) -> Result { // 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 { }; // 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 { "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)?)); } _ => {} } diff --git a/src/cpu/decoder.rs b/src/cpu/decoder.rs index e7269e9..9ce7741 100644 --- a/src/cpu/decoder.rs +++ b/src/cpu/decoder.rs @@ -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) diff --git a/src/cpu/mod.rs b/src/cpu/mod.rs index 61d76ac..368bc6f 100644 --- a/src/cpu/mod.rs +++ b/src/cpu/mod.rs @@ -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) => { diff --git a/src/main.rs b/src/main.rs index 4b20198..37fd70e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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 = 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); diff --git a/tests/assembly/loop.grasm b/tests/assembly/loop.grasm new file mode 100644 index 0000000..6cd8ebb --- /dev/null +++ b/tests/assembly/loop.grasm @@ -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 +