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),
|
CALL(RegisterMem, Const),
|
||||||
|
|
||||||
// J Type
|
// 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};
|
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);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)?));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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) => {
|
||||||
|
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::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
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