found a cause of a memory bug in emulator - fix is TODO (#6) - continued working on brainf interpreter. we really need better debugging tools tbh.
This commit is contained in:
@@ -183,7 +183,7 @@ fn expand_stx(current: Node, nodes: &mut Vec<Node>) -> Result<(), AssembleError>
|
|||||||
let base = expect_type!(current.arg(0).unwrap(), Register)?;
|
let base = expect_type!(current.arg(0).unwrap(), Register)?;
|
||||||
let dest = expect_type!(current.arg(1).unwrap(), Symbol)?;
|
let dest = expect_type!(current.arg(1).unwrap(), Symbol)?;
|
||||||
let offset = expect_type!(current.arg(2).unwrap(), Immediate)?;
|
let offset = expect_type!(current.arg(2).unwrap(), Immediate)?;
|
||||||
let temp = Token::Register(Register::Rgf);
|
let temp = Token::Register(Register::Acc);
|
||||||
|
|
||||||
nodes.extend(vec![
|
nodes.extend(vec![
|
||||||
node!(current.label(), Opcode::Lli, dest, temp),
|
node!(current.label(), Opcode::Lli, dest, temp),
|
||||||
|
|||||||
@@ -326,8 +326,8 @@ impl FromStr for Opcode {
|
|||||||
"include" => Ok(Self::Include),
|
"include" => Ok(Self::Include),
|
||||||
"call" => Ok(Self::Call),
|
"call" => Ok(Self::Call),
|
||||||
"return" => Ok(Self::Return),
|
"return" => Ok(Self::Return),
|
||||||
"pusha" => Ok(Self::Push),
|
"pusha" => Ok(Self::Pusha),
|
||||||
"popa" => Ok(Self::Pop),
|
"popa" => Ok(Self::Popa),
|
||||||
_ => Err(OpcodeFromStrError::InvalidRegister("unknown opcode")),
|
_ => Err(OpcodeFromStrError::InvalidRegister("unknown opcode")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ impl MemoryUnit for MainStore {
|
|||||||
|
|
||||||
fn read_word(&mut self, addr: u32) -> u32 {
|
fn read_word(&mut self, addr: u32) -> u32 {
|
||||||
let (block_addr, offset) = Self::segment_addr(addr);
|
let (block_addr, offset) = Self::segment_addr(addr);
|
||||||
|
|
||||||
|
println!("reading word from {block_addr:x?} + {offset}");
|
||||||
|
|
||||||
let block = self.mut_block(block_addr);
|
let block = self.mut_block(block_addr);
|
||||||
let mut bytes = [0; 4];
|
let mut bytes = [0; 4];
|
||||||
bytes[0] = block.data[offset as usize];
|
bytes[0] = block.data[offset as usize];
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ pub struct Processor {
|
|||||||
pub dustbin: u32,
|
pub dustbin: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn log(message: &str) {
|
||||||
|
println!("\x1b[32mINFO:\x1b[0m {message}");
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::needless_pass_by_ref_mut)]
|
#[allow(clippy::needless_pass_by_ref_mut)]
|
||||||
impl Processor {
|
impl Processor {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@@ -62,12 +66,10 @@ impl Processor {
|
|||||||
// Decode and execute the instruction.
|
// Decode and execute the instruction.
|
||||||
let instruction = Instruction::decode(val)?;
|
let instruction = Instruction::decode(val)?;
|
||||||
|
|
||||||
println!("Executing instruction: {instruction}");
|
log(&instruction.to_string());
|
||||||
|
|
||||||
instruction.execute(self);
|
instruction.execute(self);
|
||||||
|
|
||||||
println!("ok!");
|
|
||||||
|
|
||||||
Ok((addr, instruction))
|
Ok((addr, instruction))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+114
-56
@@ -1,10 +1,12 @@
|
|||||||
|
|
||||||
// a simple brainf##k interpreter, because I already wrote a compiler lol.
|
// a simple brainf##k interpreter,
|
||||||
|
// because I already wrote a compiler lol.
|
||||||
|
|
||||||
include print "./lib/print.dsa"
|
include print "./lib/print.dsa"
|
||||||
|
|
||||||
// "print hello world"
|
// "print hello world"
|
||||||
db program: "++++++[>++++++++++++<-]>.>++++++++++[>++++++++++<-]>+.+++++++..+++.>++++[>+++++++++++<-]>.<+++[>----<-]>.<<<<<+++[>+++++<-]>.>>.+++.------.--------.>>+."
|
db program: "++++++[>++++++++++++<-]>.>++++++++++[>++++++++++<-]>+.+++++++..+++.>++++[>+++++++++++<-]>.<+++[>----<-]>.<<<<<+++[>+++++<-]>.>>.+++.------.--------.>>+."
|
||||||
|
|
||||||
db error: "Invalid Instruction!"
|
db error: "Invalid Instruction!"
|
||||||
dw stack: 0x10000
|
dw stack: 0x10000
|
||||||
dw input: 0x30000
|
dw input: 0x30000
|
||||||
@@ -21,25 +23,32 @@ start:
|
|||||||
|
|
||||||
// rg0 is our instruction pointer
|
// rg0 is our instruction pointer
|
||||||
// rg1 is our data pointer
|
// rg1 is our data pointer
|
||||||
// acc is the value at the data pointer
|
// rg2 is the value at the data pointer
|
||||||
// rg3 stores the current instruction
|
// rg3 stores the current instruction
|
||||||
// rg4 is the expression nesting level.
|
// rg4 is the expression nesting level.
|
||||||
|
|
||||||
lui rg8, 43 // + = 43 increment
|
lli 43, rg8 // + = 43 increment
|
||||||
lui rg9, 45 // - = 45 decrement
|
lli 45, rg9 // - = 45 decrement
|
||||||
lui rga, 62 // > = 62 increment pointer
|
lli 62, rga // > = 62 increment pointer
|
||||||
lui rgb, 60 // < = 60 decrement pointer
|
lli 60, rgb // < = 60 decrement pointer
|
||||||
lui rgc, 46 // . = 46 output
|
lli 46, rgc // . = 46 output
|
||||||
lui rgd, 44 // , = 44 input
|
lli 44, rgd // , = 44 input
|
||||||
lui rge, 91 // [ = 91 loop start
|
lli 91, rge // [ = 91 loop start
|
||||||
lui rgf, 93 // ] = 93 loop end
|
lli 93, rgf // ] = 93 loop end
|
||||||
|
|
||||||
loop:
|
loop_start:
|
||||||
// load the current instruction into rg3
|
// load the current instruction into rg3
|
||||||
ldb rg0, rg3
|
ldb rg0, rg3
|
||||||
inc rg0
|
|
||||||
|
|
||||||
|
// pusha 2
|
||||||
|
// push rg3
|
||||||
|
// call print::print_byte
|
||||||
|
// pop zero
|
||||||
|
// popa 2
|
||||||
|
|
||||||
// switch on the instruction
|
// switch on the instruction
|
||||||
|
// all cases will return to either loop_start or loop_end
|
||||||
cmp rg3, rg8
|
cmp rg3, rg8
|
||||||
jeq increment
|
jeq increment
|
||||||
cmp rg3, rg9
|
cmp rg3, rg9
|
||||||
@@ -56,93 +65,142 @@ loop:
|
|||||||
jeq expr_start
|
jeq expr_start
|
||||||
cmp rg3, rgf
|
cmp rg3, rgf
|
||||||
jeq expr_end
|
jeq expr_end
|
||||||
|
cmp rg3, zero
|
||||||
|
jeq end
|
||||||
|
|
||||||
// if we get here, we don't know what the instruction is
|
// if we get here, we don't know what the instruction is
|
||||||
lwi error, rg0
|
lwi error, rg0
|
||||||
push rg0
|
push rg0
|
||||||
call print::print
|
call print::print
|
||||||
pop zero
|
pop zero
|
||||||
|
|
||||||
|
end:
|
||||||
|
lwi error, rg2
|
||||||
|
pusha 2
|
||||||
|
push rg2
|
||||||
|
call print::print
|
||||||
|
pop zero
|
||||||
|
popa 2
|
||||||
hlt
|
hlt
|
||||||
|
|
||||||
|
loop_end:
|
||||||
|
inc rg0
|
||||||
|
jmp loop_start
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
// increment the current cell
|
// increment the current cell
|
||||||
increment:
|
increment:
|
||||||
inc acc
|
inc rg2
|
||||||
jmp loop
|
jmp loop_end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
// decrement the current cell
|
// decrement the current cell
|
||||||
decrement:
|
decrement:
|
||||||
dec acc
|
dec rg2
|
||||||
jmp loop
|
jmp loop_end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
// increment the pointer
|
// increment the pointer
|
||||||
inc_ptr:
|
inc_ptr:
|
||||||
stw acc, rg1
|
stw rg2, rg1
|
||||||
addi rg1, 4
|
addi rg1, 4
|
||||||
ldw rg1, acc
|
ldw rg1, rg2
|
||||||
jmp loop
|
jmp loop_end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
// decrement the pointer
|
// decrement the pointer
|
||||||
dec_ptr:
|
dec_ptr:
|
||||||
stw rg1, acc
|
stw rg1, rg2
|
||||||
subi rg1, 4
|
subi rg1, 4
|
||||||
ldw rg1, acc
|
ldw rg1, rg2
|
||||||
jmp loop
|
jmp loop_end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
// print the byte in the current cell
|
// print the byte in the current cell
|
||||||
output:
|
output:
|
||||||
push acc
|
pusha 2
|
||||||
|
push rg2
|
||||||
call print::print_byte
|
call print::print_byte
|
||||||
pop zero
|
pop zero
|
||||||
jmp loop
|
popa 2
|
||||||
|
jmp loop_end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
// read a byte into the current cell
|
// read a byte into the current cell
|
||||||
input:
|
input:
|
||||||
ldw input, acc
|
ldw input, rg2
|
||||||
jmp loop
|
jmp loop_end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// handle an open bracket instruction
|
||||||
expr_start:
|
expr_start:
|
||||||
cmp acc, zero
|
cmp rg2, zero
|
||||||
jeq _traverse_right
|
jne loop_end
|
||||||
inc rg4
|
|
||||||
jmp loop
|
|
||||||
|
|
||||||
expr_end:
|
_traverse_right_start:
|
||||||
cmp acc, zero
|
// push a register that definitely has a nonzero value
|
||||||
jne _traverse_left
|
// when we pop this value from the stack
|
||||||
dec rg4
|
// we know we've finished traversing.
|
||||||
jmp loop
|
push rg8
|
||||||
|
|
||||||
traverse_right_start:
|
_traverse_right:
|
||||||
// we need to traverse to the right until we find the closing bracket.
|
|
||||||
// for each open bracket, we push to the stack
|
|
||||||
// for each close bracket, we pop from the stack
|
|
||||||
_traverse_right_loop:
|
|
||||||
inc rg0
|
inc rg0
|
||||||
ldb rg0, rg3
|
ldb rg0, rg3
|
||||||
|
|
||||||
cmp rg3, rge
|
cmp rg3, rge
|
||||||
jeq _open
|
jeq open_right
|
||||||
|
|
||||||
cmp rg3, rgf
|
cmp rg3, rgf
|
||||||
jeq _close
|
jeq close_right
|
||||||
|
cmp rg3, zero
|
||||||
|
jeq end
|
||||||
jmp _traverse_right
|
jmp _traverse_right
|
||||||
|
|
||||||
|
open_right:
|
||||||
|
// push zero to the stack
|
||||||
|
push zero
|
||||||
|
|
||||||
|
|
||||||
_open:
|
|
||||||
push rg4
|
|
||||||
inc rg4
|
|
||||||
jmp _traverse_right
|
jmp _traverse_right
|
||||||
|
|
||||||
_close:
|
close_right:
|
||||||
pop rg5
|
// check if we've reached the bottom of the stack
|
||||||
cmp rg4,
|
pop rg4
|
||||||
jmp _traverse_right
|
cmp rg4, zero
|
||||||
|
jeq _traverse_right
|
||||||
|
|
||||||
|
// go to next instruction after closing bracket
|
||||||
|
inc rg0
|
||||||
|
jmp loop_start
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// handle the close bracket instruction
|
||||||
|
expr_end:
|
||||||
|
cmp rg2, zero
|
||||||
|
jeq loop_end
|
||||||
|
|
||||||
|
_traverse_left_start:
|
||||||
|
push rg8
|
||||||
_traverse_left:
|
_traverse_left:
|
||||||
|
dec rg0
|
||||||
|
ldb rg0, rg3
|
||||||
|
|
||||||
|
cmp rg3, rge
|
||||||
|
jeq open_left
|
||||||
|
cmp rg3, rgf
|
||||||
|
jeq close_left
|
||||||
|
cmp rg3, zero
|
||||||
|
jeq end
|
||||||
|
jmp _traverse_left
|
||||||
|
|
||||||
|
open_left:
|
||||||
|
// check if we've reached the bottom of the stack
|
||||||
|
pop rg4
|
||||||
|
cmp rg4, zero
|
||||||
|
jeq _traverse_left
|
||||||
|
|
||||||
|
// go to next instruction after open bracket
|
||||||
|
inc rg0
|
||||||
|
jmp loop_start
|
||||||
|
|
||||||
|
close_left:
|
||||||
|
// push zero to the stack
|
||||||
|
push zero
|
||||||
|
jmp _traverse_left
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user