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:
2025-06-23 00:31:09 +01:00
parent b8091222a4
commit ddd0c27893
6 changed files with 125 additions and 62 deletions
+1 -1
View File
@@ -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),
+2 -2
View File
@@ -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")),
} }
} }
+3
View File
@@ -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
View File
@@ -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.