progress: new assembler works, instruction set fully implemented with call/ret and push/pop, bf.dsa works which means the dsa assembly language works reliably. still a few bugs to fix. might be able to squeeze out a tiny bit more performance
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
include print: "./print.dsa"
|
||||
db msg: "hello world"
|
||||
dw stack: 0x1000
|
||||
_init:
|
||||
ldw stack, bpr
|
||||
mov bpr, spr
|
||||
lwi 1000000, rg5
|
||||
|
||||
_loop:
|
||||
call print::reset
|
||||
lwi msg, rg0
|
||||
push rg0
|
||||
call print::print
|
||||
pop zero
|
||||
subi rg5, 1, rg5
|
||||
igt rg5, zero, rg4
|
||||
jnz rg4, _loop
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,227 @@
|
||||
// a simple brainf##k interpreter,
|
||||
// because I already wrote a compiler lol.
|
||||
|
||||
include print "./print.dsa"
|
||||
|
||||
// "print hello world"
|
||||
db program: "++++++++++++++++++++++++++++++++++++++++++++
|
||||
>++++++++++++++++++++++++++++++++
|
||||
>++++++++++++++++
|
||||
>
|
||||
>+
|
||||
<<
|
||||
[
|
||||
>>
|
||||
>
|
||||
>++++++++++
|
||||
<<
|
||||
[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]
|
||||
>[<+>-]
|
||||
>[-]
|
||||
>>
|
||||
>++++++++++
|
||||
<
|
||||
[->-[>+>>]>[+[-<+>]>+>>]<<<<<]
|
||||
>[-]
|
||||
>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]
|
||||
<[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]
|
||||
<<<++++++++++++++++++++++++++++++++++++++++++++++++.[-]
|
||||
<<<<<<<.>.
|
||||
>>[>>+<<-]
|
||||
>[>+<<+>-]
|
||||
>[<+>-]
|
||||
<<<-
|
||||
]
|
||||
<<++..."
|
||||
|
||||
db error: "Invalid Instruction!"
|
||||
dw stack: 0x10000
|
||||
dw input: 0x30000
|
||||
resb data: 1024
|
||||
|
||||
// set up a stack so we can call functions
|
||||
_init_stack:
|
||||
ldw stack, bpr
|
||||
mov bpr, spr
|
||||
|
||||
start:
|
||||
// load the start of the program into rg0
|
||||
lwi program, rg0
|
||||
lwi data, rg1
|
||||
|
||||
// rg0 is our instruction pointer
|
||||
// rg1 is our data pointer
|
||||
// rg2 is the value at the data pointer
|
||||
// rg3 stores the current instruction
|
||||
// rg4 is the expression nesting level.
|
||||
|
||||
lli 43, rg8 // + = 43 increment
|
||||
lli 45, rg9 // - = 45 decrement
|
||||
lli 62, rga // > = 62 increment pointer
|
||||
lli 60, rgb // < = 60 decrement pointer
|
||||
lli 46, rgc // . = 46 output
|
||||
lli 44, rgd // , = 44 input
|
||||
lli 91, rge // [ = 91 loop start
|
||||
lli 93, rgf // ] = 93 loop end
|
||||
|
||||
loop_start:
|
||||
// load the current instruction into rg3
|
||||
ldb rg0, rg3
|
||||
|
||||
// switch on the instruction
|
||||
ieq rg3, rg8, rg4
|
||||
jnz rg4, increment
|
||||
ieq rg3, rg9, rg4
|
||||
jnz rg4, decrement
|
||||
ieq rg3, rga, rg4
|
||||
jnz rg4, inc_ptr
|
||||
ieq rg3, rgb, rg4
|
||||
jnz rg4, dec_ptr
|
||||
ieq rg3, rgc, rg4
|
||||
jnz rg4, output
|
||||
ieq rg3, rgd, rg4
|
||||
jnz rg4, input
|
||||
ieq rg3, rge, rg4
|
||||
jnz rg4, expr_start
|
||||
ieq rg3, rgf, rg4
|
||||
jnz rg4, expr_end
|
||||
ieq rg3, zero, rg4
|
||||
jnz rg4, end
|
||||
|
||||
// if we get here, we don't know what the instruction is
|
||||
lwi error, rg2
|
||||
push rg0
|
||||
push rg1
|
||||
push rg2
|
||||
call print::print
|
||||
pop zero
|
||||
pop rg1
|
||||
pop rg0
|
||||
|
||||
end:
|
||||
hlt
|
||||
|
||||
loop_end:
|
||||
addi rg0, 1, rg0
|
||||
jmp loop_start
|
||||
|
||||
// ------------------------------------------
|
||||
// increment the current cell
|
||||
increment:
|
||||
addi rg2, 1, rg2
|
||||
jmp loop_end
|
||||
|
||||
// ------------------------------------------
|
||||
// decrement the current cell
|
||||
decrement:
|
||||
subi rg2, 1, rg2
|
||||
jmp loop_end
|
||||
|
||||
// ------------------------------------------
|
||||
// increment the pointer
|
||||
inc_ptr:
|
||||
stw rg2, rg1
|
||||
addi rg1, 4
|
||||
ldw rg1, rg2
|
||||
jmp loop_end
|
||||
|
||||
// ------------------------------------------
|
||||
// decrement the pointer
|
||||
dec_ptr:
|
||||
stw rg2, rg1
|
||||
subi rg1, 4
|
||||
ldw rg1, rg2
|
||||
jmp loop_end
|
||||
|
||||
// ------------------------------------------
|
||||
// print the byte in the current cell
|
||||
output:
|
||||
push rg0
|
||||
push rg1
|
||||
push rg2
|
||||
call print::print_byte
|
||||
pop zero
|
||||
pop rg1
|
||||
pop rg0
|
||||
jmp loop_end
|
||||
|
||||
// ------------------------------------------
|
||||
// read a byte into the current cell
|
||||
input:
|
||||
ldw input, rg2
|
||||
jmp loop_end
|
||||
|
||||
// ------------------------------------------
|
||||
// handle an open bracket instruction
|
||||
expr_start:
|
||||
ieq rg2, zero, rg4
|
||||
jez rg4, loop_end
|
||||
|
||||
_traverse_right_start:
|
||||
// push a register that definitely has a nonzero value
|
||||
// when we pop this value from the stack
|
||||
// we know we've finished traversing.
|
||||
push rg8
|
||||
|
||||
_traverse_right:
|
||||
addi rg0, 1, rg0
|
||||
ldb rg0, rg3
|
||||
|
||||
ieq rg3, rge, rg4
|
||||
jnz rg4, open_right
|
||||
ieq rg3, rgf, rg4
|
||||
jnz rg4, close_right
|
||||
ieq rg3, zero, rg4
|
||||
jnz rg4, end
|
||||
jmp _traverse_right
|
||||
|
||||
open_right:
|
||||
// push zero to the stack
|
||||
push zero
|
||||
jmp _traverse_right
|
||||
|
||||
close_right:
|
||||
// check if we've reached the bottom of the stack
|
||||
pop rg4
|
||||
ieq rg4, zero, rg5
|
||||
jnz rg5, _traverse_right
|
||||
|
||||
// go to next instruction after closing bracket
|
||||
addi rg0, 1, rg0
|
||||
jmp loop_start
|
||||
|
||||
// ------------------------------------------
|
||||
// handle the close bracket instruction
|
||||
expr_end:
|
||||
ieq rg2, zero, rg4
|
||||
jnz rg4, loop_end
|
||||
|
||||
_traverse_left_start:
|
||||
push rg8
|
||||
|
||||
_traverse_left:
|
||||
subi rg0, 1, rg0
|
||||
ldb rg0, rg3
|
||||
|
||||
ieq rg3, rge, rg4
|
||||
jnz rg4, open_left
|
||||
ieq rg3, rgf, rg4
|
||||
jnz rg4, close_left
|
||||
ieq rg3, zero, rg4
|
||||
jnz rg4, end
|
||||
jmp _traverse_left
|
||||
|
||||
open_left:
|
||||
// check if we've reached the bottom of the stack
|
||||
pop rg4
|
||||
ieq rg4, zero, rg5
|
||||
jnz rg5, _traverse_left
|
||||
|
||||
// go to next instruction after open bracket
|
||||
addi rg0, 1, rg0
|
||||
jmp loop_start
|
||||
|
||||
close_left:
|
||||
// push zero to the stack
|
||||
push zero
|
||||
jmp _traverse_left
|
||||
Binary file not shown.
@@ -0,0 +1,292 @@
|
||||
// lib:
|
||||
// print.dsa
|
||||
|
||||
// usage:
|
||||
//
|
||||
// include print "<relative path>"
|
||||
//
|
||||
// usage for print:
|
||||
// push (register containing address of string)
|
||||
// call print::print
|
||||
//
|
||||
// usage for reset:
|
||||
// call print::reset
|
||||
//
|
||||
// usage for clear:
|
||||
// call print::clear
|
||||
//
|
||||
// usage for print_byte:
|
||||
// push (register containing byte)
|
||||
// call print::print_byte
|
||||
//
|
||||
// usage for print_word:
|
||||
// push (register containing word)
|
||||
// call print::print_word
|
||||
//
|
||||
// usage for print_num:
|
||||
// push (register containing number to print in decimal)
|
||||
// call print::print_num
|
||||
//
|
||||
|
||||
dw display: 0x20000
|
||||
dw current: 0x20000
|
||||
|
||||
// ------------------------------------------
|
||||
// prints the string at addr(arg[0]) to the screen.
|
||||
print: func
|
||||
|
||||
ldw bpr, rg0, 8
|
||||
ldw current, rg1
|
||||
|
||||
_print_loop:
|
||||
ldb rg0, rg2
|
||||
ieq rg2, zero, rg4
|
||||
jnz rg4, _end
|
||||
stb rg2, rg1
|
||||
|
||||
addi rg0, 1
|
||||
addi rg1, 1
|
||||
|
||||
jmp _print_loop
|
||||
// ------------------------------------------
|
||||
// println:
|
||||
// push bpr
|
||||
// mov spr, bpr
|
||||
|
||||
// ldw bpr, rg0, 8
|
||||
// ldw current, rg1
|
||||
|
||||
// _println_loop:
|
||||
// ldb rg0, acc
|
||||
// ieq acc, zero, rg4
|
||||
// jnz rg4, _println_end
|
||||
// stb acc, rg1
|
||||
|
||||
// addi rg0, 1
|
||||
// addi rg1, 1
|
||||
|
||||
// jmp _println_loop
|
||||
|
||||
// _println_end:
|
||||
// call print_newline
|
||||
// jmp _end
|
||||
|
||||
// ------------------------------------------
|
||||
// prints the value of arg[0] to the screen.
|
||||
// print_word:
|
||||
// push bpr
|
||||
// mov spr, bpr
|
||||
|
||||
// ldw bpr, rg0, 8
|
||||
// ldw current, rg1
|
||||
|
||||
// addi rg1, 3
|
||||
|
||||
// stb rg0, rg1
|
||||
// subi rg1, 1
|
||||
// shr rg0, 8
|
||||
// stb rg0, rg1
|
||||
// subi rg1, 1
|
||||
// shr rg0, 8
|
||||
// stb rg0, rg1
|
||||
// subi rg1, 1
|
||||
// shr rg0, 8
|
||||
// stb rg0, rg1
|
||||
|
||||
// addi rg1, 4
|
||||
// jmp _end
|
||||
|
||||
// ------------------------------------------
|
||||
// prints the last byte of arg[0] to the screen.
|
||||
print_byte: func
|
||||
ldw bpr, rg0, 8
|
||||
ldw current, rg1
|
||||
|
||||
stb rg0, rg1
|
||||
addi rg1, 1
|
||||
jmp _end
|
||||
|
||||
// ------------------------------------------
|
||||
// prints the value of arg[0] to the screen in hex.
|
||||
// print_hex_word:
|
||||
// push bpr
|
||||
// mov spr, bpr
|
||||
|
||||
// ldw current, rg1
|
||||
|
||||
// ldb bpr, rg0, 8
|
||||
// push rg0
|
||||
// call _print_hex_byte
|
||||
// addi spr, 4
|
||||
|
||||
// ldb bpr, rg0, 9
|
||||
// push rg0
|
||||
// call _print_hex_byte
|
||||
// addi spr, 4
|
||||
|
||||
// ldb bpr, rg0, 10
|
||||
// push rg0
|
||||
// call _print_hex_byte
|
||||
// addi spr, 4
|
||||
|
||||
// ldb bpr, rg0, 11
|
||||
// push rg0
|
||||
// call _print_hex_byte
|
||||
// addi spr, 4
|
||||
|
||||
// jmp _end
|
||||
|
||||
// ------------------------------------------
|
||||
// prints the last byte of arg[0] to the screen in hex.
|
||||
print_hex_byte: func
|
||||
ldw bpr, rg0, 8
|
||||
ldw current, rg1
|
||||
|
||||
call _print_hex_byte
|
||||
jmp _end
|
||||
|
||||
// function body
|
||||
_print_hex_byte:
|
||||
lli 0xF, rg2
|
||||
push rg0
|
||||
|
||||
shr rg0, 4
|
||||
and rg0, rg2, rg0
|
||||
call _print_hex_nibble
|
||||
pop rg0
|
||||
|
||||
and rg0, rg2, rg0
|
||||
call _print_hex_nibble
|
||||
ret
|
||||
|
||||
// print a hex digit
|
||||
_print_hex_nibble:
|
||||
lli 10, rg3
|
||||
ilt rg0, rg3, rg4
|
||||
jnz rg4, _print_hex_nibble_number
|
||||
addi rg0, 0x37, rg0
|
||||
stb rg0, rg1
|
||||
addi rg1, 1
|
||||
ret
|
||||
|
||||
// helper function.
|
||||
_print_hex_nibble_number:
|
||||
addi rg0, 0x30, rg0
|
||||
stb rg0, rg1
|
||||
addi rg1, 1
|
||||
ret
|
||||
|
||||
// ------------------------------------------
|
||||
// print whitespace
|
||||
print_whitespace: func
|
||||
ldw current, rg1
|
||||
lli 0x20, rg0
|
||||
stb rg0, rg1
|
||||
addi rg1, 1
|
||||
jmp _end
|
||||
|
||||
// // ------------------------------------------
|
||||
// // print newline
|
||||
// print_newline:
|
||||
// push bpr
|
||||
// mov spr, bpr
|
||||
|
||||
// ldw display, rg0
|
||||
// ldw current, rg1
|
||||
|
||||
// sub rg1, rg0, rg0
|
||||
|
||||
// lwi 80, rg2
|
||||
// push rg0
|
||||
// push rg1
|
||||
// push rg2
|
||||
// push rg0
|
||||
// push rg2
|
||||
// call maths::divmod
|
||||
// pop zero // result
|
||||
// pop rg3 // remainder
|
||||
// pop rg0
|
||||
// pop rg1
|
||||
// pop rg2
|
||||
|
||||
// sub rg1, rg3, rg2
|
||||
// addi rg2, 80, rg1
|
||||
|
||||
// jmp _end
|
||||
|
||||
// ------------------------------------------
|
||||
// prints arg[0] as a decimal number to the screen.
|
||||
// print_num:
|
||||
// push bpr
|
||||
// mov spr, bpr
|
||||
|
||||
// ldw bpr, rg0, 8
|
||||
// lli 0, rg5
|
||||
|
||||
// ieq rg0, zero, rg4
|
||||
// jez rg4, _print_num_extract_digits
|
||||
|
||||
// lli 0x30, rg6
|
||||
// push rg6
|
||||
// lli 1, rg5
|
||||
// jmp _print_num_output
|
||||
|
||||
// _print_num_extract_digits:
|
||||
// ieq rg0, zero, rg4
|
||||
// jnz rg4, _print_num_output
|
||||
|
||||
// push rg0
|
||||
// lli 10, rg1
|
||||
// push rg1
|
||||
// call maths::divmod
|
||||
// pop rg0 // quotient
|
||||
// pop rg1 // remainder
|
||||
|
||||
// addi rg1, 0x30, rg6
|
||||
// push rg6
|
||||
// inc rg5
|
||||
|
||||
// jmp _print_num_extract_digits
|
||||
|
||||
// _print_num_output:
|
||||
// ldw current, rg1
|
||||
|
||||
// _print_num_output_loop:
|
||||
// ieq rg5, zero, rg4
|
||||
// jnz rg4, _print_num_done
|
||||
|
||||
// pop rg6
|
||||
// stb rg6, rg1
|
||||
// addi rg1, 1
|
||||
// dec rg5
|
||||
|
||||
// jmp _print_num_output_loop
|
||||
|
||||
// _print_num_done:
|
||||
// jmp _end
|
||||
|
||||
// ------------------------------------------
|
||||
// resets the cursor position to 0x20000 (0,0)
|
||||
reset: func
|
||||
ldw display, rg1
|
||||
jmp _end
|
||||
|
||||
// ------------------------------------------
|
||||
// clears the screen
|
||||
clear: func
|
||||
lli 500, rg0
|
||||
ldw display, rg1
|
||||
|
||||
_clear_loop:
|
||||
subi rg0, 1, rg0
|
||||
stw zero, rg1
|
||||
addi rg1, 4
|
||||
igt rg0, zero, rg4
|
||||
jnz rg4, _clear_loop
|
||||
jmp _end
|
||||
|
||||
// ------------------------------------------
|
||||
// return — saves current, restores frame, returns
|
||||
_end:
|
||||
stw rg1, current
|
||||
return
|
||||
Reference in New Issue
Block a user