mega refactor:

essentially completely reorganised the project.
previous contents of the dsa folder have now been split into emulator/ tooling/ and libraries/
libraries is for common functionality across crates, tooling is for core binaries needed for building and debugging DSA projects, including dsx client/server/build
emulator contains the dsa_emulator crate that implements the core DSA emulator, the dsa_gui crate that implements the graphical user interface for the emulator & all future tooling under a unified application, and finally the dsa_cli crate which will eventually provide lightweight wrapper for the core emulator, simply providing a tool for running DSA binaries without the overhead of a heavy GUI.
This commit is contained in:
2026-08-01 01:28:11 +01:00
parent 8c19497bc7
commit 27d38eaf89
120 changed files with 84 additions and 90 deletions
+173
View File
@@ -0,0 +1,173 @@
include print: "./print.dsa"
dw DISPLAY: 0x30000
dw stack: 0x10000
// colour table — AABBGGRR format
dw COL0: 0xFFFFFFFF // white
dw COL1: 0xFF0000FF // red
dw COL2: 0xFF00FF00 // green
dw COL3: 0xFFFF0000 // blue
dw COL4: 0xFF00FFFF // yellow
dw COL_IDX: 0
// registers:
// rg0 = x position
// rg1 = y position
// rg2 = x direction (1 = right, 0 = left)
// rg3 = y direction (1 = down, 0 = up)
// rg5 = current colour
db startup: "Starting animation..."
_init:
ldw stack, bpr
mov bpr, spr
start:
lwi startup, rg0
push rg0
call print::print
pop zero
lli 0, rg0
lli 0, rg1
lli 1, rg2
lli 1, rg3
lli 0, rg8
stw rg8, COL_IDX
ldw COL0, rg5
frame_loop:
// --- clear display ---
ldw DISPLAY, rg4
lwi 76800, rga
clear_loop:
stw zero, rg4
addi rg4, 4, rg4
subi rga, 1, rga
jnz rga, clear_loop
// --- draw square ---
mov rg1, rg6
draw_y_loop:
lli 20, rg8
add rg1, rg8, rg8
ilt rg6, rg8, rg9
jez rg9, draw_done
mov rg0, rg7
draw_x_loop:
lli 20, rg8
add rg0, rg8, rg8
ilt rg7, rg8, rg9
jez rg9, draw_x_done
shl rg6, 8, rg8
shl rg6, 6, rg9
add rg8, rg9, rg8
add rg8, rg7, rg8
shl rg8, 2, rg8
ldw DISPLAY, rg9
add rg9, rg8, rg8
stw rg5, rg8
addi rg7, 1, rg7
jmp draw_x_loop
draw_x_done:
addi rg6, 1, rg6
jmp draw_y_loop
draw_done:
// --- track bounces this frame ---
lli 0, rgb
lli 0, rgc
// --- check x walls ---
lli 1, rg8
ieq rg2, rg8, rg9
jez rg9, check_x_left_wall
check_x_right_wall:
lli 300, rg8
ige rg0, rg8, rg9
jez rg9, move_x
lli 0, rg2
lli 1, rgb
jmp move_x
check_x_left_wall:
ieq rg0, zero, rg9
jez rg9, move_x
lli 1, rg2
lli 1, rgb
move_x:
lli 1, rg8
ieq rg2, rg8, rg9
jez rg9, do_x_left
addi rg0, 1, rg0
jmp check_y_walls
do_x_left:
subi rg0, 1, rg0
check_y_walls:
lli 1, rg8
ieq rg3, rg8, rg9
jez rg9, check_y_up_wall
check_y_down_wall:
lli 220, rg8
ige rg1, rg8, rg9
jez rg9, move_y
lli 0, rg3
lli 1, rgc
jmp move_y
check_y_up_wall:
ieq rg1, zero, rg9
jez rg9, move_y
lli 1, rg3
lli 1, rgc
move_y:
lli 1, rg8
ieq rg3, rg8, rg9
jez rg9, do_y_up
addi rg1, 1, rg1
jmp check_corner
do_y_up:
subi rg1, 1, rg1
check_corner:
and rgb, rgc, rg8
jez rg8, delay
// advance colour index
ldw COL_IDX, rg8
addi rg8, 1, rg8
lli 5, rg9
ige rg8, rg9, rg9
jez rg9, store_col_idx
lli 0, rg8
store_col_idx:
stw rg8, COL_IDX
// load colour from table: address = COL0 + idx * 4
shl rg8, 2, rg8
lwi COL0, rg9
add rg9, rg8, rg8
ldw rg8, rg5
delay:
lwi 2000000, rg8
delay_loop:
subi rg8, 1, rg8
jnz rg8, delay_loop
jmp frame_loop
hlt
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
include print: "./print.dsa"
db msg: "hello world"
dw stack: 0x10000
_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
Binary file not shown.
+161
View File
@@ -0,0 +1,161 @@
; ==== symbols ====
; clear 0x000001d0 TEXT global
; _loop 0x00000018 TEXT global
; print_whitespace 0x00000150 TEXT global
; _print_hex_nibble_number 0x00000140 TEXT global
; _init 0x00000000 TEXT global
; _print_loop 0x00000068 TEXT global
; print_hex_byte 0x000000e0 TEXT global
; _print_hex_byte 0x00000100 TEXT global
; _end 0x00000200 TEXT global
; print_byte 0x000000ac TEXT global
; _newline_mod 0x0000019c TEXT global
; reset 0x000001b8 TEXT global
; _newline_done 0x000001ac TEXT global
; msg 0x00000218 DATA global
; display 0x00000228 DATA global
; current 0x0000022c DATA global
; _clear_loop 0x000001e8 TEXT global
; _print_hex_nibble 0x00000124 TEXT global
; print 0x00000040 TEXT global
; stack 0x00000224 DATA global
; _print_end 0x00000084 TEXT global
; newline 0x00000174 TEXT global
; ==== data ====
db "hello world"
dw 0x00000000
dw 0x00000010
dw 0x00000000
dw 0x00000002
dw 0x00000002
; ==== text ====
_init:
ldw stack, Bpr, 0x0000
mov Bpr, Spr
lwi 0x000f4240, Rg5
_loop:
call reset
lwi msg, Rg0
push Rg0
call print
pop Zero
subi Rg5, Rg5, 0x0001
igt Rg5, Zero, Rg4
jnz Rg4, _loop
hlt
print:
push Bpr
mov Spr, Bpr
push Rg0
push Rg1
push Rg2
push Rg3
ldw Bpr, Rg0, 0x0008
ldw current, Rg1, 0x0000
_print_loop:
ldb Rg0, Rg2, 0x0000
ieq Rg2, Zero, Rg3
jnz Rg3, _print_end
stb Rg2, Rg1, 0x0000
addi Rg0, Rg0, 0x0001
addi Rg1, Rg1, 0x0001
jmp _print_loop
_print_end:
stw current, Rg1, 0x0000
pop Rg3
pop Rg2
pop Rg1
pop Rg0
mov Bpr, Spr
pop Bpr
ret
print_byte:
push Bpr
mov Spr, Bpr
push Rg0
push Rg1
ldw Bpr, Rg0, 0x0008
ldw current, Rg1, 0x0000
stb Rg0, Rg1, 0x0000
addi Rg1, Rg1, 0x0001
pop Rg1
pop Rg0
jmp _end
print_hex_byte:
push Bpr
mov Spr, Bpr
ldw Bpr, Rg0, 0x0008
ldw current, Rg1, 0x0000
call _print_hex_byte
jmp _end
_print_hex_byte:
lli Rg2, 0x000f
push Rg0
shr Rg0, Rg0, Zero, 4
and Rg0, Rg2, Rg0
call _print_hex_nibble
pop Rg0
and Rg0, Rg2, Rg0
call _print_hex_nibble
ret
_print_hex_nibble:
lli Rg3, 0x000a
ilt Rg0, Rg3, Rg4
jnz Rg4, _print_hex_nibble_number
addi Rg0, Rg0, 0x0037
stb Rg0, Rg1, 0x0000
addi Rg1, Rg1, 0x0001
ret
_print_hex_nibble_number:
addi Rg0, Rg0, 0x0030
stb Rg0, Rg1, 0x0000
addi Rg1, Rg1, 0x0001
ret
print_whitespace:
push Bpr
mov Spr, Bpr
ldw current, Rg1, 0x0000
lli Rg0, 0x0020
stb Rg0, Rg1, 0x0000
addi Rg1, Rg1, 0x0001
jmp _end
newline:
push Bpr
mov Spr, Bpr
ldw display, Rg0, 0x0000
ldw current, Rg1, 0x0000
sub Rg1, Rg0, Rg2
lli Rg3, 0x0050
_newline_mod:
ilt Rg2, Rg3, Rg4
jnz Rg4, _newline_done
sub Rg2, Rg3, Rg2
jmp _newline_mod
_newline_done:
sub Rg1, Rg2, Rg1
addi Rg1, Rg1, 0x0050
jmp _end
reset:
push Bpr
mov Spr, Bpr
ldw display, Rg1, 0x0000
jmp _end
clear:
push Bpr
mov Spr, Bpr
lli Rg0, 0x01f4
ldw display, Rg1, 0x0000
_clear_loop:
subi Rg0, Rg0, 0x0001
stw Zero, Rg1, 0x0000
addi Rg1, Rg1, 0x0004
igt Rg0, Zero, Rg4
jnz Rg4, _clear_loop
jmp _end
_end:
stw current, Rg1, 0x0000
mov Bpr, Spr
pop Bpr
ret
+272
View File
@@ -0,0 +1,272 @@
// a simple brainf##k interpreter,
// because I already wrote a compiler lol.
include print "./print.dsa"
// "prints first 16 fibonacci numbers"
db program: "++++++++++++++++++++++++++++++++++++++++++++
>++++++++++++++++++++++++++++++++
>++++++++++++++++
>
>+
<<
[
>>
>
>++++++++++
<<
[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]
>[<+>-]
>[-]
>>
>++++++++++
<
[->-[>+>>]>[+[-<+>]>+>>]<<<<<]
>[-]
>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]
<[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]
<<<++++++++++++++++++++++++++++++++++++++++++++++++.[-]
<<<<<<<.>.
>>[>>+<<-]
>[>+<<+>-]
>[<+>-]
<<<-
]
<<++..."
db error: "Invalid Instruction!"
dh counter: 0xFF
dw stack: 0x10000
dw input_addr: 0x30000
resb data: 1024
// set up a stack so we can call functions
_init:
ldw stack, bpr
mov bpr, spr
init:
ldw counter, rg7
start:
call bf_reset
// 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
db success: "Success!"
end:
call print::newline
lwi success, rg0
push rg0
call print::print
pop zero
subi rg7, 1
jnz rg7, start
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_addr, 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
// ------------------------------------------
// reset interpreter
// clears screen, resets cursor and clears data buffer.
bf_reset: func
push rg0
push rg1
// clear screen and reset cursor
call print::clear
call print::reset
// clear data buffer (resb data: 1024 = 256 words)
lli 256, rg0
lwi data, rg1
_bf_reset_clear_data:
subi rg0, 1, rg0
stw zero, rg1
addi rg1, 4, rg1
igt rg0, zero, rg4
jnz rg4, _bf_reset_clear_data
pop rg1
pop rg0
// reload interpreter state
lwi program, rg0
lwi data, rg1
lli 0, rg2
return
BIN
View File
Binary file not shown.
Binary file not shown.
+592
View File
@@ -0,0 +1,592 @@
; ==== symbols ====
; _print_hex_nibble 0x00000328 TEXT global
; increment 0x000000ec TEXT global
; _clear_loop 0x000003ec TEXT global
; end 0x000000c0 TEXT global
; reset 0x000003bc TEXT global
; _print_end 0x00000288 TEXT global
; decrement 0x000000f4 TEXT global
; open_left 0x000001c8 TEXT global
; open_right 0x0000017c TEXT global
; expr_end 0x00000198 TEXT global
; newline 0x00000378 TEXT global
; input 0x0000013c TEXT global
; loop_start 0x00000050 TEXT global
; loop_end 0x000000e4 TEXT global
; _traverse_right 0x00000158 TEXT global
; dec_ptr 0x0000010c TEXT global
; expr_start 0x0000014c TEXT global
; print_hex_byte 0x000002e4 TEXT global
; print_byte 0x000002b0 TEXT global
; success 0x000009e8 DATA global
; data 0x000005e8 DATA global
; error 0x000005c4 DATA global
; clear 0x000003d4 TEXT global
; _print_hex_byte 0x00000304 TEXT global
; _bf_reset_clear_data 0x00000208 TEXT global
; bf_reset 0x000001e4 TEXT global
; _end 0x00000404 TEXT global
; _traverse_left_start 0x000001a0 TEXT global
; _init 0x00000000 TEXT global
; counter 0x000005dc DATA global
; _print_loop 0x0000026c TEXT global
; print_whitespace 0x00000354 TEXT global
; inc_ptr 0x000000fc TEXT global
; current 0x000009f8 DATA global
; _traverse_right_start 0x00000154 TEXT global
; print 0x00000244 TEXT global
; init 0x00000010 TEXT global
; stack 0x000005e0 DATA global
; _traverse_left 0x000001a4 TEXT global
; start 0x0000001c TEXT global
; close_left 0x000001dc TEXT global
; input_addr 0x000005e4 DATA global
; close_right 0x00000184 TEXT global
; display 0x000009f4 DATA global
; _newline_done 0x000003b0 TEXT global
; program 0x0000041c DATA global
; _newline_mod 0x000003a0 TEXT global
; _print_hex_nibble_number 0x00000344 TEXT global
; output 0x0000011c TEXT global
; ==== data ====
db "++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++>++++++++++++++++>>+<<[>>>>++++++++++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>[<+>-]>[-]>>>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]>[-]>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]<[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]<<<++++++++++++++++++++++++++++++++++++++++++++++++.[-]<<<<<<<.>.>>[>>+<<-]>[>+<<+>-]>[<+>-]<<<-]<<++..."
db "Invalid Instruction!"
dw 0x00000000
dw 0x000000ff
dw 0x00000000
dw 0x00000001
dw 0x00000003
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
dw 0x00000000
db "Success!"
dw 0x00000000
dw 0x00000000
dw 0x00000002
dw 0x00000002
; ==== text ====
_init:
ldw stack, Bpr, 0x0000
mov Bpr, Spr
init:
ldw counter, Rg7, 0x0000
start:
call bf_reset
lwi program, Rg0
lwi data, Rg1
lli Rg8, 0x002b
lli Rg9, 0x002d
lli Rga, 0x003e
lli Rgb, 0x003c
lli Rgc, 0x002e
lli Rgd, 0x002c
lli Rge, 0x005b
lli Rgf, 0x005d
loop_start:
ldb Rg0, Rg3, 0x0000
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
lwi error, Rg2
push Rg0
push Rg1
push Rg2
call print
pop Zero
pop Rg1
pop Rg0
end:
call newline
lwi success, Rg0
push Rg0
call print
pop Zero
subi Rg7, Rg7, 0x0001
jnz Rg7, start
hlt
loop_end:
addi Rg0, Rg0, 0x0001
jmp loop_start
increment:
addi Rg2, Rg2, 0x0001
jmp loop_end
decrement:
subi Rg2, Rg2, 0x0001
jmp loop_end
inc_ptr:
stw Rg2, Rg1, 0x0000
addi Rg1, Rg1, 0x0004
ldw Rg1, Rg2, 0x0000
jmp loop_end
dec_ptr:
stw Rg2, Rg1, 0x0000
subi Rg1, Rg1, 0x0004
ldw Rg1, Rg2, 0x0000
jmp loop_end
output:
push Rg0
push Rg1
push Rg2
call print_byte
pop Zero
pop Rg1
pop Rg0
jmp loop_end
input:
ldw input_addr, Rg2, 0x0000
jmp loop_end
expr_start:
ieq Rg2, Zero, Rg4
jez Rg4, loop_end
_traverse_right_start:
push Rg8
_traverse_right:
addi Rg0, Rg0, 0x0001
ldb Rg0, Rg3, 0x0000
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
jmp _traverse_right
close_right:
pop Rg4
ieq Rg4, Zero, Rg5
jnz Rg5, _traverse_right
addi Rg0, Rg0, 0x0001
jmp loop_start
expr_end:
ieq Rg2, Zero, Rg4
jnz Rg4, loop_end
_traverse_left_start:
push Rg8
_traverse_left:
subi Rg0, Rg0, 0x0001
ldb Rg0, Rg3, 0x0000
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:
pop Rg4
ieq Rg4, Zero, Rg5
jnz Rg5, _traverse_left
addi Rg0, Rg0, 0x0001
jmp loop_start
close_left:
push Zero
jmp _traverse_left
bf_reset:
push Bpr
mov Spr, Bpr
push Rg0
push Rg1
call clear
call reset
lli Rg0, 0x0100
lwi data, Rg1
_bf_reset_clear_data:
subi Rg0, Rg0, 0x0001
stw Zero, Rg1, 0x0000
addi Rg1, Rg1, 0x0004
igt Rg0, Zero, Rg4
jnz Rg4, _bf_reset_clear_data
pop Rg1
pop Rg0
lwi program, Rg0
lwi data, Rg1
lli Rg2, 0x0000
mov Bpr, Spr
pop Bpr
ret
print:
push Bpr
mov Spr, Bpr
push Rg0
push Rg1
push Rg2
push Rg3
ldw Bpr, Rg0, 0x0008
ldw current, Rg1, 0x0000
_print_loop:
ldb Rg0, Rg2, 0x0000
ieq Rg2, Zero, Rg3
jnz Rg3, _print_end
stb Rg2, Rg1, 0x0000
addi Rg0, Rg0, 0x0001
addi Rg1, Rg1, 0x0001
jmp _print_loop
_print_end:
stw current, Rg1, 0x0000
pop Rg3
pop Rg2
pop Rg1
pop Rg0
mov Bpr, Spr
pop Bpr
ret
print_byte:
push Bpr
mov Spr, Bpr
push Rg0
push Rg1
ldw Bpr, Rg0, 0x0008
ldw current, Rg1, 0x0000
stb Rg0, Rg1, 0x0000
addi Rg1, Rg1, 0x0001
pop Rg1
pop Rg0
jmp _end
print_hex_byte:
push Bpr
mov Spr, Bpr
ldw Bpr, Rg0, 0x0008
ldw current, Rg1, 0x0000
call _print_hex_byte
jmp _end
_print_hex_byte:
lli Rg2, 0x000f
push Rg0
shr Rg0, Rg0, Zero, 4
and Rg0, Rg2, Rg0
call _print_hex_nibble
pop Rg0
and Rg0, Rg2, Rg0
call _print_hex_nibble
ret
_print_hex_nibble:
lli Rg3, 0x000a
ilt Rg0, Rg3, Rg4
jnz Rg4, _print_hex_nibble_number
addi Rg0, Rg0, 0x0037
stb Rg0, Rg1, 0x0000
addi Rg1, Rg1, 0x0001
ret
_print_hex_nibble_number:
addi Rg0, Rg0, 0x0030
stb Rg0, Rg1, 0x0000
addi Rg1, Rg1, 0x0001
ret
print_whitespace:
push Bpr
mov Spr, Bpr
ldw current, Rg1, 0x0000
lli Rg0, 0x0020
stb Rg0, Rg1, 0x0000
addi Rg1, Rg1, 0x0001
jmp _end
newline:
push Bpr
mov Spr, Bpr
ldw display, Rg0, 0x0000
ldw current, Rg1, 0x0000
sub Rg1, Rg0, Rg2
lli Rg3, 0x0050
_newline_mod:
ilt Rg2, Rg3, Rg4
jnz Rg4, _newline_done
sub Rg2, Rg3, Rg2
jmp _newline_mod
_newline_done:
sub Rg1, Rg2, Rg1
addi Rg1, Rg1, 0x0050
jmp _end
reset:
push Bpr
mov Spr, Bpr
ldw display, Rg1, 0x0000
jmp _end
clear:
push Bpr
mov Spr, Bpr
lli Rg0, 0x01f4
ldw display, Rg1, 0x0000
_clear_loop:
subi Rg0, Rg0, 0x0001
stw Zero, Rg1, 0x0000
addi Rg1, Rg1, 0x0004
igt Rg0, Zero, Rg4
jnz Rg4, _clear_loop
jmp _end
_end:
stw current, Rg1, 0x0000
mov Bpr, Spr
pop Bpr
ret
+65
View File
@@ -0,0 +1,65 @@
include print: "./print.dsa"
db success: "Success!"
dw framebuffer: 0x30000
dw stack: 0x10000
_init:
ldw stack, bpr
mov bpr, spr
start:
ldw framebuffer, rg0 // rg0 = display base address
lli 0, rg1 // rg1 = y (0..240)
y_loop:
lli 0, rg2 // rg2 = x (0..320)
x_loop:
// red = x >> 1 (0..159, left to right gradient)
shr rg2, zero, 1, rg4
// green = y (0..239, top to bottom gradient)
mov rg1, rg5
// blue = constant 128
lli 0x80, rg6
// pack as 0xAABBGGRR (LE reads as RGBA)
// start with red in bits 0-7
mov rg4, rg7
// green into bits 8-15
shl rg5, zero, 8, rg5
or rg7, rg5, rg7
// blue into bits 16-23
shl rg6, zero, 16, rg6
or rg7, rg6, rg7
// alpha into bits 24-31
lli 0xFF, rg6
shl rg6, zero, 24, rg6
or rg7, rg6, rg7
stw rg7, rg0 // write pixel
addi rg0, 4, rg0 // next pixel
addi rg2, 1, rg2
lli 320, rg6
ilt rg2, rg6, rg6
jnz rg6, x_loop
addi rg1, 1, rg1
lli 240, rg6
ilt rg1, rg6, rg6
jnz rg6, y_loop
_end:
lwi success: rg0
push rg0
call print::print
pop zero
hlt
Binary file not shown.
+58
View File
@@ -0,0 +1,58 @@
include print: "./print.dsa"
include serial: "./serial.dsa"
dw idt: 0xFFFF0000
setup_base: func
push rg0
push rg1
push rg2
push rg3
ldw idt, idr // load the IDT into the IDR
// set all 256 interrupt addresses to point to guard
lwi _guard, rg1 // load address of guard handler
addi idr, 1024, rg2 // counter for 256 entries
_loop_start:
stw rg1, rg2 // store guard into current IDT entry
subi rg2, 4, rg2 // decrement counter
ieq rg2, idr, rg3 // check if we've reached the base address
jez rg3, _loop_start // repeat until all entries set
// make sure we can handle an invalid interrupt
lwi _handle_invalid_interrupt, rg0
stw rg0, idr, 0
pop rg3
pop rg2
pop rg1
pop rg0
return
setup_io: func
push rg0
lwi serial::isr, rg0
stw rg0, idr, 128 // 32*4, interrupt idx 32
pop rg0
return
db _invalid_int: "FATAL: Invalid Interrupt!"
_handle_invalid_interrupt:
call print::reset
lwi _invalid_int, rg0
push rg0
call print::print
pop zero
hlt
db _err: "FATAL: Interrupt handler was not set!"
_guard:
call print::reset
lwi _err, rg0
push rg0
call print::print
pop zero
hlt
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
+336
View File
@@ -0,0 +1,336 @@
// 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
push rg0
push rg1
push rg2
push rg3
ldw bpr, rg0, 8
ldw current, rg1
_print_loop:
ldb rg0, rg2
ieq rg2, zero, rg3
jnz rg3, _print_end
stb rg2, rg1
addi rg0, 1
addi rg1, 1
jmp _print_loop
_print_end:
stw rg1, current
pop rg3
pop rg2
pop rg1
pop rg0
return
// ------------------------------------------
// 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
push rg0
push rg1
ldw bpr, rg0, 8
ldw current, rg1
stb rg0, rg1
addi rg1, 1
stw rg1, current
pop rg1
pop rg0
return
// ------------------------------------------
// 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
newline:
push bpr
mov spr, bpr
ldw display, rg0
ldw current, rg1
sub rg1, rg0, rg2 // offset from base
lli 80, rg3
_newline_mod:
ilt rg2, rg3, rg4
jnz rg4, _newline_done
sub rg2, rg3, rg2
jmp _newline_mod
_newline_done:
// rg2 = offset % 80 (position within current line)
sub rg1, rg2, rg1 // go back to line start
addi rg1, 80, rg1 // advance to next line
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
+135
View File
@@ -0,0 +1,135 @@
// Serial port address in MMIO
dw UART: 0x40000
// Reserve space for our read buffer
resb SERIAL_BUFFER: 1025 // final byte is a null terminator
dw SER_READ_PTR: 0
dw SER_WRITE_PTR: 0
reset: func
push rg0
lwi SERIAL_BUFFER, rg0
stw rg0, SER_READ_PTR, 0
stw rg0, SER_WRITE_PTR, 0
pop rg0
return
isr:
push rg0
push rg1
push rg2
ldw UART, rg0
ldb rg0, rg1, 2 // load ser_in_valid flag
// no serial input
jez rg1, _isr_end
// we should have a valid byte to read at offset 3
ldb rg0, rg1, 3 // data byte
stb zero, rg0, 2 // unset ser_in_valid
// write data to ptr and increment
ldw SER_WRITE_PTR, rg2
stb rg1, rg2
addi rg2, 1
// load buff+1024
lwi SERIAL_BUFFER, rg0
addi rg0, 1024, rg1
// if ptr != buff+1024, nowrap.
ine rg1, rg2, rg1
jnz rg1, _isr_nowrap
lwi SERIAL_BUFFER, rg2 // set the pointer
_isr_nowrap:
stw rg2, SER_WRITE_PTR
_isr_end:
pop rg2
pop rg1
pop rg0
iret
// serial_readline: waits until a null byte is received
// returns nothing, data is in SERIAL_BUFFER starting at SER_READ_PTR
readline: func
push rg0
push rg1
_readline_wait:
// check if write ptr == read ptr (buffer empty)
ldw SER_WRITE_PTR, rg0
ldw SER_READ_PTR, rg1
ieq rg0, rg1, rg0
jnz rg0, _readline_halt // nothing written yet, halt
// check if the byte just before write ptr is null
ldw SER_WRITE_PTR, rg0
// handle wrap: if write ptr == SERIAL_BUFFER, check last byte of buffer
lwi SERIAL_BUFFER, rg1
ieq rg0, rg1, rg1
jnz rg1, _readline_check_wrap
// normal case: read byte at write_ptr - 1
subi rg0, 1, rg0
ldb rg0, rg1, 0
jez rg1, _readline_done
jmp _readline_halt
_readline_check_wrap:
// write ptr is at start of buffer, last byte is at SERIAL_BUFFER + 1023
lwi SERIAL_BUFFER, rg0
addi rg0, 1023, rg0
ldb rg0, rg1, 0
jez rg1, _readline_done
_readline_halt:
hlt
jmp _readline_wait
_readline_done:
pop rg1
pop rg0
return
// _serial_send: trashes rg2, rg3, rg4, rg5
// byte to send in rg0
_serial_send:
ldw UART, rg5
_serial_wait:
ldb rg5, rg2, 0
lli 0x01, rg3
ieq rg2, rg3, rg4
jnz rg4, _serial_wait
stb rg0, rg5, 1
stb rg3, rg5, 0 // rg3 is still 0x01 from above
ret
print: func
push rg0
push rg1
ldw bpr, rg0, 8
_serial_print_loop:
ldb rg0, rg1
jez rg1, _serial_print_end
push rg0
mov rg1, rg0
call _serial_send
pop rg0
addi rg0, 1, rg0
jmp _serial_print_loop
_serial_print_end:
pop rg1
pop rg0
return
print_byte: func
push rg0
ldw bpr, rg0, 8
call _serial_send
pop rg0
return
+40
View File
@@ -0,0 +1,40 @@
include serial: "./serial.dsa"
include idt: "./idt.dsa"
include print: "./print.dsa"
dw stack: 0x10000
_init:
ldw stack, bpr
mov bpr, spr
call idt::setup_base
call idt::setup_io
call serial::reset
db hello: "Test message, hello world etc etc."
main:
//lwi hello, rg0
//push rg0
//call serial::print
//pop zero
// lwi hello, rg0
// push rg0
// call print::print
// pop zero
//lwi buff, rg0
//lwi 32, rg1
//push rg0
//push rg1
call serial::readline
lwi serial::SERIAL_BUFFER, rg0
push rg0
call serial::print
pop zero
call serial::reset
hlt
jmp main