progress on serial and added editor
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
include print: "./print.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, zero, rg3 // check if counter is zero
|
||||
jnz 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_interrupt, rg0
|
||||
stw rg0, idr, 132 // 33*4, interrupt idx 32
|
||||
|
||||
pop rg0
|
||||
return
|
||||
|
||||
// does nothing, but wakes the kernel
|
||||
_serial_interrupt:
|
||||
nop
|
||||
iret
|
||||
|
||||
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
|
||||
Binary file not shown.
+22
-2
@@ -34,20 +34,34 @@ 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, rg4
|
||||
jnz rg4, _end
|
||||
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
|
||||
@@ -99,11 +113,17 @@ _print_loop:
|
||||
// ------------------------------------------
|
||||
// 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
|
||||
|
||||
pop rg1
|
||||
pop rg0
|
||||
jmp _end
|
||||
|
||||
// ------------------------------------------
|
||||
|
||||
+92
-39
@@ -1,63 +1,116 @@
|
||||
// lib:
|
||||
// serial.dsa
|
||||
//
|
||||
// usage:
|
||||
// include serial "<relative path>"
|
||||
//
|
||||
// push (register containing address of string)
|
||||
// call serial::print
|
||||
//
|
||||
// push (register containing byte)
|
||||
// call serial::print_byte
|
||||
|
||||
dw uart: 0x40000
|
||||
|
||||
// ------------------------------------------
|
||||
// transmit a single byte via sentinel protocol
|
||||
// expects: byte in rg0, trashes rg2, rg3, rg4, rg5
|
||||
// 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:
|
||||
shl rg0, 16, rg2 // shift byte to bits [23:16]
|
||||
lli 0x01, rg0
|
||||
shl rg0, 24, rg0 // valid flag in bits [31:24]
|
||||
or rg0, rg2, rg2 // rg2 = 0x01_XX_0000
|
||||
|
||||
ldw uart, rg5 // rg5 = 0x40000 (uart address, held for store)
|
||||
|
||||
push rg0
|
||||
push rg2
|
||||
push rg3
|
||||
push rg4
|
||||
push rg5
|
||||
ldw uart, rg5
|
||||
_serial_wait:
|
||||
ldw rg5, rg0 // poll mem[0x40000]
|
||||
shr rg0, 24, rg0
|
||||
ldb rg5, rg2, 3 // base+0x03 = write valid flag
|
||||
lli 0x01, rg3
|
||||
ieq rg0, rg3, rg4
|
||||
jnz rg4, _serial_wait // loop while valid == 1
|
||||
|
||||
stw rg2, rg5 // mem[0x40000] = sentinel word
|
||||
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, rg2 // load byte
|
||||
ieq rg2, zero, rg4 // null terminator?
|
||||
jnz rg4, _serial_end
|
||||
|
||||
ldb rg0, rg1 // load byte
|
||||
ieq rg1, zero, rg2 // null terminator?
|
||||
jnz rg2, _serial_print_end
|
||||
push rg0 // save string pointer
|
||||
mov rg2, rg0
|
||||
mov rg1, rg0
|
||||
call _serial_send
|
||||
pop rg0
|
||||
|
||||
addi rg0, 1
|
||||
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
|
||||
|
||||
@@ -1,14 +1,44 @@
|
||||
include serial: "./serial.dsa"
|
||||
include idt: "./idt.dsa"
|
||||
include print: "./print.dsa"
|
||||
|
||||
resb buff: 256
|
||||
|
||||
dw stack: 0x1000
|
||||
_init:
|
||||
ldw stack, bpr
|
||||
mov bpr, spr
|
||||
call idt::setup_base
|
||||
call idt::setup_io
|
||||
|
||||
db hello: "Serial works lol. this took ages and some clanker forgetting to dereference a pointer."
|
||||
db hello2: "hello2"
|
||||
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
|
||||
push zero
|
||||
call serial::read_byte
|
||||
pop rg0
|
||||
//pop zero
|
||||
push rg0
|
||||
call print::print
|
||||
pop zero
|
||||
|
||||
lwi hello2, rg0
|
||||
push rg0
|
||||
call print::print
|
||||
pop zero
|
||||
|
||||
hlt
|
||||
|
||||
Reference in New Issue
Block a user