fixed BEQ, BGT, JAL, loops works. Fixed the encoder adress calculation for JAL's.
This commit is contained in:
parent
8513b62222
commit
3023e578b4
@ -31,5 +31,5 @@ pub enum Operation {
|
||||
CALL(RegisterMem, Const),
|
||||
|
||||
// J Type
|
||||
JAL(RegisterMem, RegisterMem, Word),
|
||||
JAL(RegisterMem, RegisterMem, Const),
|
||||
}
|
||||
|
@ -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);
|
||||
},
|
||||
}
|
||||
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
@ -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)?));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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) => {
|
||||
|
15
src/main.rs
15
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<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
16
tests/assembly/loop.grasm
Normal 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
|
||||
|
Loading…
Reference in New Issue
Block a user