117 lines
2.8 KiB
Plaintext
117 lines
2.8 KiB
Plaintext
dw uart: 0x40000
|
|
// ------------------------------------------
|
|
// reads up to rg1 bytes into buffer at rg2
|
|
// args: buf_size @ bpr+8, buf_addr @ bpr+12
|
|
// returns: 0 in bpr+8 on success, 1 on nullptr error
|
|
buf_read: func
|
|
push rg0
|
|
push rg1
|
|
push rg2
|
|
push rg3
|
|
ldw bpr, rg1, 8 // buf size
|
|
ldw bpr, rg2, 12 // buf addr
|
|
jez rg2, _buf_read_err // return err if nullptr
|
|
_buf_read_loop:
|
|
jez rg1, _buf_read_end
|
|
call read_byte
|
|
ldw bpr, rg3, 8 // read return value from frame
|
|
stb rg3, rg2 // store into buffer
|
|
addi rg2, 1, rg2
|
|
subi rg1, 1, rg1
|
|
jmp _buf_read_loop
|
|
_buf_read_end:
|
|
stw zero, bpr, 8 // return 0 (success)
|
|
pop rg3
|
|
pop rg2
|
|
pop rg1
|
|
pop rg0
|
|
return
|
|
_buf_read_err:
|
|
lli 1, rg0
|
|
stw rg0, bpr, 8 // return 1 (error)
|
|
pop rg3
|
|
pop rg2
|
|
pop rg1
|
|
pop rg0
|
|
return
|
|
|
|
// read_byte: emulator → kernel
|
|
// reads data from base+0x00, valid flag at base+0x01
|
|
read_byte: func
|
|
push rg0
|
|
push rg1
|
|
push rg2
|
|
ldw uart, rg1
|
|
_serial_read_wait:
|
|
ldb rg1, rg0, 1 // base+0x01 = read valid flag
|
|
lli 0x01, rg2
|
|
ieq rg0, rg2, rg2
|
|
jnz rg2, _serial_read_ready
|
|
hlt
|
|
jmp _serial_read_wait
|
|
_serial_read_ready:
|
|
ldb rg1, rg0, 0 // base+0x00 = data byte
|
|
stb zero, rg1, 1 // clear read valid flag
|
|
stb rg0, bpr, 8 // return byte
|
|
pop rg2
|
|
pop rg1
|
|
pop rg0
|
|
return
|
|
|
|
// _serial_send: kernel → emulator
|
|
// writes data to base+0x02, valid flag to base+0x03
|
|
_serial_send:
|
|
push rg0
|
|
push rg2
|
|
push rg3
|
|
push rg4
|
|
push rg5
|
|
ldw uart, rg5
|
|
_serial_wait:
|
|
ldb rg5, rg2, 3 // base+0x03 = write valid flag
|
|
lli 0x01, rg3
|
|
ieq rg2, rg3, rg4
|
|
jnz rg4, _serial_wait // wait while emulator hasn't consumed yet
|
|
stb rg0, rg5, 2 // base+0x02 = data byte
|
|
lli 0x01, rg2
|
|
stb rg2, rg5, 3 // base+0x03 = set valid flag
|
|
pop rg5
|
|
pop rg4
|
|
pop rg3
|
|
pop rg2
|
|
pop rg0
|
|
ret
|
|
// ------------------------------------------
|
|
// prints the null-terminated string at addr(arg[0])
|
|
print: func
|
|
push rg0
|
|
push rg1
|
|
push rg2
|
|
ldw bpr, rg0, 8 // load string address from arg
|
|
_serial_print_loop:
|
|
ldb rg0, rg1 // load byte
|
|
ieq rg1, zero, rg2 // null terminator?
|
|
jnz rg2, _serial_print_end
|
|
push rg0 // save string pointer
|
|
mov rg1, rg0
|
|
call _serial_send
|
|
pop rg0
|
|
addi rg0, 1, rg0
|
|
jmp _serial_print_loop
|
|
_serial_print_end:
|
|
pop rg2
|
|
pop rg1
|
|
pop rg0
|
|
jmp _serial_end
|
|
// ------------------------------------------
|
|
// prints the last byte of arg[0]
|
|
print_byte: func
|
|
push rg0
|
|
ldw bpr, rg0, 8
|
|
call _serial_send
|
|
pop rg0
|
|
jmp _serial_end
|
|
// ------------------------------------------
|
|
_serial_end:
|
|
return
|