// lib: // serial.dsa // // usage: // include serial "" // // 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 _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) _serial_wait: ldw rg5, rg0 // poll mem[0x40000] shr rg0, 24, rg0 lli 0x01, rg3 ieq rg0, rg3, rg4 jnz rg4, _serial_wait // loop while valid == 1 stw rg2, rg5 // mem[0x40000] = sentinel word ret // ------------------------------------------ // prints the null-terminated string at addr(arg[0]) print: func 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 push rg0 // save string pointer mov rg2, rg0 call _serial_send pop rg0 addi rg0, 1 jmp _serial_print_loop // ------------------------------------------ // prints the last byte of arg[0] print_byte: func ldw bpr, rg0, 8 call _serial_send jmp _serial_end // ------------------------------------------ _serial_end: return