continuing with serial driver in dsa.
This commit is contained in:
@@ -272,9 +272,16 @@ impl Emulator {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn interrupt(&mut self, int: Interrupt) {
|
fn interrupt(&mut self, int: Interrupt) {
|
||||||
|
println!("Interrupt while at address {}", self.reg(Register::Pcx));
|
||||||
|
|
||||||
self.push(Register::Pcx);
|
self.push(Register::Pcx);
|
||||||
*self.mut_reg(Register::Pcx) =
|
*self.mut_reg(Register::Pcx) =
|
||||||
self.mem_read_word(self.reg(Register::Idr) + int.code() as u32 * 4)
|
self.mem_read_word(self.reg(Register::Idr) + int.code() as u32 * 4);
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Jumping to interrupt at address {}",
|
||||||
|
self.reg(Register::Pcx)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -489,6 +496,11 @@ impl Emulator {
|
|||||||
Some(Opcode::IRet) => {
|
Some(Opcode::IRet) => {
|
||||||
self.pop(Register::Ret);
|
self.pop(Register::Ret);
|
||||||
*self.mut_reg(Register::Pcx) = self.reg(Register::Ret);
|
*self.mut_reg(Register::Pcx) = self.reg(Register::Ret);
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Returning from interrupt to address {}",
|
||||||
|
self.reg(Register::Pcx)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
@@ -502,8 +514,12 @@ impl Emulator {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mem_write_byte(&mut self, addr: u32, val: u8) {
|
fn mem_write_byte(&mut self, addr: u32, val: u8) {
|
||||||
if addr == 0x40000 {
|
if addr == 0x40000 || addr == 0x40001 || addr == 0x40002 || addr == 0x40003 {
|
||||||
eprintln!("emulator wrote 0x{:08x} to uart", val);
|
eprintln!("emulator wrote 0x{:08x} to uart + {}", val, addr - 0x40000);
|
||||||
|
|
||||||
|
if addr == 0x40001 || addr == 0x40003 {
|
||||||
|
eprintln!("writing char {} to uart + {}", val as char, addr - 0x40000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.mainstore.write_byte(addr, val);
|
self.mainstore.write_byte(addr, val);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// ## SERIAL LAYOUT: (from the perspective of code inside the emulator)
|
/// ## SERIAL LAYOUT: (from the perspective of code inside the emulator)
|
||||||
/// - [base+0x00]: write valid flag - set by kernel after writing a byte to serial
|
/// - [base+0x00]: ser_out valid flag - set by kernel after writing a byte to serial
|
||||||
/// - [base+0x01]: write byte - data payload for emulator to read
|
/// - [base+0x01]: ser_out byte - data payload for emulator to read
|
||||||
/// - [base+0x02]: read valid flag - set by emulator after writing a byte to serial
|
/// - [base+0x02]: ser_in valid flag - set by emulator after writing a byte to serial
|
||||||
/// - [base+0x03]: read byte - data payload for kernel to read
|
/// - [base+0x03]: ser_in byte - data payload for kernel to read
|
||||||
pub struct Serial {
|
pub struct Serial {
|
||||||
pub read_rx: Receiver<u8>,
|
pub read_rx: Receiver<u8>,
|
||||||
pub write_tx: Sender<u8>,
|
pub write_tx: Sender<u8>,
|
||||||
@@ -33,20 +33,19 @@ impl Serial {
|
|||||||
rx: Receiver<u8>,
|
rx: Receiver<u8>,
|
||||||
) {
|
) {
|
||||||
loop {
|
loop {
|
||||||
let word = mem.read_word(uart_base);
|
let ser_out_valid = mem.read_byte(uart_base + 0);
|
||||||
|
// Kernel => emulator: valid flag in byte 0, data in byte 1
|
||||||
// Kernel → emulator: valid flag in bits 31:24, data in bits 23:16
|
if ser_out_valid == 0x01 {
|
||||||
if (word >> 24) as u8 == 0x01 {
|
let ser_out = mem.read_byte(uart_base + 1);
|
||||||
let byte = (word >> 16) as u8;
|
let _ = tx.send(ser_out);
|
||||||
let _ = tx.send(byte);
|
mem.write_byte(uart_base, 0x00); // clear the whole word
|
||||||
mem.write_word(uart_base, 0x00); // clear the whole word
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emulator → kernel: your existing rx path
|
// Emulator => kernel: valid flag in byte 2, data in byte 3
|
||||||
if (word >> 8) as u8 == 0x00 {
|
let ser_in_valid = mem.read_byte(uart_base + 2);
|
||||||
|
if ser_in_valid == 0x00 {
|
||||||
if let Ok(byte) = rx.try_recv() {
|
if let Ok(byte) = rx.try_recv() {
|
||||||
state.interrupt_queue.send(Interrupt::SerialIn).unwrap();
|
state.interrupt_queue.send(Interrupt::SerialIn).unwrap();
|
||||||
|
|
||||||
mem.write_byte(uart_base + 3, byte);
|
mem.write_byte(uart_base + 3, byte);
|
||||||
mem.write_byte(uart_base + 2, 0x01);
|
mem.write_byte(uart_base + 2, 0x01);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#![feature(likely_unlikely)]
|
#![feature(likely_unlikely)]
|
||||||
#![feature(inherent_associated_types)]
|
#![feature(inherent_associated_types)]
|
||||||
|
#![feature(str_as_str)]
|
||||||
|
|
||||||
pub mod args;
|
pub mod args;
|
||||||
pub mod backend;
|
pub mod backend;
|
||||||
|
|||||||
+48
-19
@@ -1,11 +1,20 @@
|
|||||||
dw DISPLAY: 0x30000
|
dw DISPLAY: 0x30000
|
||||||
dw stack: 0x10000
|
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:
|
// registers:
|
||||||
// rg0 = x position
|
// rg0 = x position
|
||||||
// rg1 = y position
|
// rg1 = y position
|
||||||
// rg2 = x direction (1 = right, 0 = left)
|
// rg2 = x direction (1 = right, 0 = left)
|
||||||
// rg3 = y direction (1 = down, 0 = up)
|
// rg3 = y direction (1 = down, 0 = up)
|
||||||
|
// rg5 = current colour
|
||||||
|
|
||||||
_init:
|
_init:
|
||||||
ldw stack, bpr
|
ldw stack, bpr
|
||||||
@@ -16,17 +25,20 @@ start:
|
|||||||
lli 0, rg1
|
lli 0, rg1
|
||||||
lli 1, rg2
|
lli 1, rg2
|
||||||
lli 1, rg3
|
lli 1, rg3
|
||||||
|
lli 0, rg8
|
||||||
|
stw rg8, COL_IDX
|
||||||
|
ldw COL0, rg5
|
||||||
|
|
||||||
frame_loop:
|
frame_loop:
|
||||||
// --- clear display ---
|
// --- clear display ---
|
||||||
ldw DISPLAY, rg4
|
ldw DISPLAY, rg4
|
||||||
lwi 76800, rg5
|
lwi 76800, rga
|
||||||
|
|
||||||
clear_loop:
|
clear_loop:
|
||||||
stw zero, rg4
|
stw zero, rg4
|
||||||
addi rg4, 4, rg4
|
addi rg4, 4, rg4
|
||||||
subi rg5, 1, rg5
|
subi rga, 1, rga
|
||||||
jnz rg5, clear_loop
|
jnz rga, clear_loop
|
||||||
|
|
||||||
// --- draw square ---
|
// --- draw square ---
|
||||||
mov rg1, rg6
|
mov rg1, rg6
|
||||||
@@ -36,7 +48,6 @@ draw_y_loop:
|
|||||||
add rg1, rg8, rg8
|
add rg1, rg8, rg8
|
||||||
ilt rg6, rg8, rg9
|
ilt rg6, rg8, rg9
|
||||||
jez rg9, draw_done
|
jez rg9, draw_done
|
||||||
|
|
||||||
mov rg0, rg7
|
mov rg0, rg7
|
||||||
|
|
||||||
draw_x_loop:
|
draw_x_loop:
|
||||||
@@ -44,7 +55,6 @@ draw_x_loop:
|
|||||||
add rg0, rg8, rg8
|
add rg0, rg8, rg8
|
||||||
ilt rg7, rg8, rg9
|
ilt rg7, rg8, rg9
|
||||||
jez rg9, draw_x_done
|
jez rg9, draw_x_done
|
||||||
|
|
||||||
shl rg6, 8, rg8
|
shl rg6, 8, rg8
|
||||||
shl rg6, 6, rg9
|
shl rg6, 6, rg9
|
||||||
add rg8, rg9, rg8
|
add rg8, rg9, rg8
|
||||||
@@ -52,11 +62,7 @@ draw_x_loop:
|
|||||||
shl rg8, 2, rg8
|
shl rg8, 2, rg8
|
||||||
ldw DISPLAY, rg9
|
ldw DISPLAY, rg9
|
||||||
add rg9, rg8, rg8
|
add rg9, rg8, rg8
|
||||||
|
stw rg5, rg8
|
||||||
lli 0xFFFF, rg9
|
|
||||||
lui 0xFFFF, rg9
|
|
||||||
stw rg9, rg8
|
|
||||||
|
|
||||||
addi rg7, 1, rg7
|
addi rg7, 1, rg7
|
||||||
jmp draw_x_loop
|
jmp draw_x_loop
|
||||||
|
|
||||||
@@ -65,24 +71,28 @@ draw_x_done:
|
|||||||
jmp draw_y_loop
|
jmp draw_y_loop
|
||||||
|
|
||||||
draw_done:
|
draw_done:
|
||||||
// --- check x walls before moving ---
|
// --- track bounces this frame ---
|
||||||
|
lli 0, rgb
|
||||||
|
lli 0, rgc
|
||||||
|
|
||||||
|
// --- check x walls ---
|
||||||
lli 1, rg8
|
lli 1, rg8
|
||||||
ieq rg2, rg8, rg9
|
ieq rg2, rg8, rg9
|
||||||
jez rg9, check_x_left_wall
|
jez rg9, check_x_left_wall
|
||||||
|
|
||||||
check_x_right_wall:
|
check_x_right_wall:
|
||||||
// moving right: if x >= 300 flip direction
|
|
||||||
lli 300, rg8
|
lli 300, rg8
|
||||||
ige rg0, rg8, rg9
|
ige rg0, rg8, rg9
|
||||||
jez rg9, move_x
|
jez rg9, move_x
|
||||||
lli 0, rg2
|
lli 0, rg2
|
||||||
|
lli 1, rgb
|
||||||
jmp move_x
|
jmp move_x
|
||||||
|
|
||||||
check_x_left_wall:
|
check_x_left_wall:
|
||||||
// moving left: if x == 0 flip direction
|
|
||||||
ieq rg0, zero, rg9
|
ieq rg0, zero, rg9
|
||||||
jez rg9, move_x
|
jez rg9, move_x
|
||||||
lli 1, rg2
|
lli 1, rg2
|
||||||
|
lli 1, rgb
|
||||||
|
|
||||||
move_x:
|
move_x:
|
||||||
lli 1, rg8
|
lli 1, rg8
|
||||||
@@ -94,40 +104,59 @@ do_x_left:
|
|||||||
subi rg0, 1, rg0
|
subi rg0, 1, rg0
|
||||||
|
|
||||||
check_y_walls:
|
check_y_walls:
|
||||||
// --- check y walls before moving ---
|
|
||||||
lli 1, rg8
|
lli 1, rg8
|
||||||
ieq rg3, rg8, rg9
|
ieq rg3, rg8, rg9
|
||||||
jez rg9, check_y_up_wall
|
jez rg9, check_y_up_wall
|
||||||
|
|
||||||
check_y_down_wall:
|
check_y_down_wall:
|
||||||
// moving down: if y >= 220 flip direction
|
|
||||||
lli 220, rg8
|
lli 220, rg8
|
||||||
ige rg1, rg8, rg9
|
ige rg1, rg8, rg9
|
||||||
jez rg9, move_y
|
jez rg9, move_y
|
||||||
lli 0, rg3
|
lli 0, rg3
|
||||||
|
lli 1, rgc
|
||||||
jmp move_y
|
jmp move_y
|
||||||
|
|
||||||
check_y_up_wall:
|
check_y_up_wall:
|
||||||
// moving up: if y == 0 flip direction
|
|
||||||
ieq rg1, zero, rg9
|
ieq rg1, zero, rg9
|
||||||
jez rg9, move_y
|
jez rg9, move_y
|
||||||
lli 1, rg3
|
lli 1, rg3
|
||||||
|
lli 1, rgc
|
||||||
|
|
||||||
move_y:
|
move_y:
|
||||||
lli 1, rg8
|
lli 1, rg8
|
||||||
ieq rg3, rg8, rg9
|
ieq rg3, rg8, rg9
|
||||||
jez rg9, do_y_up
|
jez rg9, do_y_up
|
||||||
addi rg1, 1, rg1
|
addi rg1, 1, rg1
|
||||||
jmp delay
|
jmp check_corner
|
||||||
do_y_up:
|
do_y_up:
|
||||||
subi rg1, 1, rg1
|
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:
|
delay:
|
||||||
lwi 2000000, rg8
|
lwi 2000000, rg8
|
||||||
delay_loop:
|
delay_loop:
|
||||||
subi rg8, 1, rg8
|
subi rg8, 1, rg8
|
||||||
jnz rg8, delay_loop
|
jnz rg8, delay_loop
|
||||||
|
|
||||||
jmp frame_loop
|
jmp frame_loop
|
||||||
|
|
||||||
hlt
|
hlt
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
include print: "./print.dsa"
|
include print: "./print.dsa"
|
||||||
|
include serial: "./serial.dsa"
|
||||||
|
|
||||||
dw idt: 0xFFFF0000
|
dw idt: 0xFFFF0000
|
||||||
setup_base: func
|
setup_base: func
|
||||||
@@ -15,8 +16,8 @@ setup_base: func
|
|||||||
_loop_start:
|
_loop_start:
|
||||||
stw rg1, rg2 // store guard into current IDT entry
|
stw rg1, rg2 // store guard into current IDT entry
|
||||||
subi rg2, 4, rg2 // decrement counter
|
subi rg2, 4, rg2 // decrement counter
|
||||||
ieq rg2, zero, rg3 // check if counter is zero
|
ieq rg2, idr, rg3 // check if we've reached the base address
|
||||||
jnz rg3, _loop_start // repeat until all entries set
|
jez rg3, _loop_start // repeat until all entries set
|
||||||
|
|
||||||
// make sure we can handle an invalid interrupt
|
// make sure we can handle an invalid interrupt
|
||||||
lwi _handle_invalid_interrupt, rg0
|
lwi _handle_invalid_interrupt, rg0
|
||||||
@@ -31,16 +32,12 @@ _loop_start:
|
|||||||
setup_io: func
|
setup_io: func
|
||||||
push rg0
|
push rg0
|
||||||
|
|
||||||
lwi _serial_interrupt, rg0
|
lwi serial::serial_isr, rg0
|
||||||
stw rg0, idr, 132 // 33*4, interrupt idx 32
|
stw rg0, idr, 128 // 32*4, interrupt idx 32
|
||||||
|
|
||||||
pop rg0
|
pop rg0
|
||||||
return
|
return
|
||||||
|
|
||||||
// does nothing, but wakes the kernel
|
|
||||||
_serial_interrupt:
|
|
||||||
nop
|
|
||||||
iret
|
|
||||||
|
|
||||||
db _invalid_int: "FATAL: Invalid Interrupt!"
|
db _invalid_int: "FATAL: Invalid Interrupt!"
|
||||||
_handle_invalid_interrupt:
|
_handle_invalid_interrupt:
|
||||||
|
|||||||
+97
-44
@@ -1,57 +1,74 @@
|
|||||||
dw uart: 0x40000
|
// Serial port address in MMIO
|
||||||
// ------------------------------------------
|
dw UART: 0x40000
|
||||||
// reads up to rg1 bytes into buffer at rg2
|
|
||||||
// args: buf_size @ bpr+8, buf_addr @ bpr+12
|
// Reserve space for our read buffer
|
||||||
// returns: 0 in bpr+8 on success, 1 on nullptr error
|
resb SERIAL_BUFFER: 1024
|
||||||
buf_read: func
|
dw SER_READ_PTR: 0
|
||||||
push rg0
|
dw SER_WRITE_PTR: 0
|
||||||
push rg1
|
|
||||||
push rg2
|
serial_init: func
|
||||||
push rg3
|
lwi SERIAL_BUFFER, rg0
|
||||||
ldw bpr, rg1, 8 // buf size
|
stw rg0, SER_READ_PTR, 0
|
||||||
ldw bpr, rg2, 12 // buf addr
|
stw rg0, SER_WRITE_PTR, 0
|
||||||
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
|
return
|
||||||
|
|
||||||
|
serial_isr:
|
||||||
|
push rg0
|
||||||
|
push rg1
|
||||||
|
push rg2
|
||||||
|
|
||||||
|
ldw UART, rg0
|
||||||
|
ldb rg0, rg1, 2 // load ser_in_valid flag
|
||||||
|
|
||||||
|
// no serial input
|
||||||
|
jez rg1, _serial_isr_end
|
||||||
|
|
||||||
|
// we should have a valid byte to read at offset 3
|
||||||
|
ldb rg0, rg1, 3 // data byte
|
||||||
|
|
||||||
|
// 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, _serial_isr_nowrap
|
||||||
|
|
||||||
|
lwi SERIAL_BUFFER, rg2 // set the pointer
|
||||||
|
|
||||||
|
_serial_isr_nowrap:
|
||||||
|
stw rg2, SER_WRITE_PTR
|
||||||
|
|
||||||
|
_serial_isr_end:
|
||||||
|
pop rg0
|
||||||
|
pop rg1
|
||||||
|
pop rg2
|
||||||
|
iret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// read_byte: emulator → kernel
|
// read_byte: emulator → kernel
|
||||||
// reads data from base+0x00, valid flag at base+0x01
|
// reads data from base+0x00, valid flag at base+0x01
|
||||||
read_byte: func
|
read_byte: func
|
||||||
push rg0
|
push rg0
|
||||||
push rg1
|
push rg1
|
||||||
push rg2
|
push rg2
|
||||||
ldw uart, rg1
|
ldw UART, rg1
|
||||||
_serial_read_wait:
|
_serial_read_wait:
|
||||||
ldb rg1, rg0, 1 // base+0x01 = read valid flag
|
ldb rg1, rg0, 2 // base+0x02 = read valid flag
|
||||||
lli 0x01, rg2
|
lli 0x01, rg2
|
||||||
ieq rg0, rg2, rg2
|
ieq rg0, rg2, rg2
|
||||||
jnz rg2, _serial_read_ready
|
jnz rg2, _serial_read_ready
|
||||||
hlt
|
hlt
|
||||||
jmp _serial_read_wait
|
jmp _serial_read_wait
|
||||||
_serial_read_ready:
|
_serial_read_ready:
|
||||||
ldb rg1, rg0, 0 // base+0x00 = data byte
|
ldb rg1, rg0, 3 // base+0x03 = data byte
|
||||||
stb zero, rg1, 1 // clear read valid flag
|
stb zero, rg1, 2 // clear read valid flag
|
||||||
stb rg0, bpr, 8 // return byte
|
stb rg0, bpr, 8 // return byte
|
||||||
pop rg2
|
pop rg2
|
||||||
pop rg1
|
pop rg1
|
||||||
@@ -59,22 +76,22 @@ _serial_read_ready:
|
|||||||
return
|
return
|
||||||
|
|
||||||
// _serial_send: kernel → emulator
|
// _serial_send: kernel → emulator
|
||||||
// writes data to base+0x02, valid flag to base+0x03
|
// writes data to base+0x01, valid flag to base+0x00
|
||||||
_serial_send:
|
_serial_send:
|
||||||
push rg0
|
push rg0
|
||||||
push rg2
|
push rg2
|
||||||
push rg3
|
push rg3
|
||||||
push rg4
|
push rg4
|
||||||
push rg5
|
push rg5
|
||||||
ldw uart, rg5
|
ldw UART, rg5
|
||||||
_serial_wait:
|
_serial_wait:
|
||||||
ldb rg5, rg2, 3 // base+0x03 = write valid flag
|
ldb rg5, rg2, 0 // base+0x00 = ser_out_valid
|
||||||
lli 0x01, rg3
|
lli 0x01, rg3
|
||||||
ieq rg2, rg3, rg4
|
ieq rg2, rg3, rg4
|
||||||
jnz rg4, _serial_wait // wait while emulator hasn't consumed yet
|
jnz rg4, _serial_wait // wait while emulator hasn't consumed yet
|
||||||
stb rg0, rg5, 2 // base+0x02 = data byte
|
stb rg0, rg5, 1 // base+0x01 = ser_out_data
|
||||||
lli 0x01, rg2
|
lli 0x01, rg2
|
||||||
stb rg2, rg5, 3 // base+0x03 = set valid flag
|
stb rg2, rg5, 0 // base+0x00 = ser_out_valid = 1
|
||||||
pop rg5
|
pop rg5
|
||||||
pop rg4
|
pop rg4
|
||||||
pop rg3
|
pop rg3
|
||||||
@@ -114,3 +131,39 @@ print_byte: func
|
|||||||
// ------------------------------------------
|
// ------------------------------------------
|
||||||
_serial_end:
|
_serial_end:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// 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
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ include serial: "./serial.dsa"
|
|||||||
include idt: "./idt.dsa"
|
include idt: "./idt.dsa"
|
||||||
include print: "./print.dsa"
|
include print: "./print.dsa"
|
||||||
|
|
||||||
resb buff: 256
|
|
||||||
|
|
||||||
dw stack: 0x1000
|
dw stack: 0x1000
|
||||||
_init:
|
_init:
|
||||||
ldw stack, bpr
|
ldw stack, bpr
|
||||||
@@ -28,10 +26,8 @@ main:
|
|||||||
//lwi 32, rg1
|
//lwi 32, rg1
|
||||||
//push rg0
|
//push rg0
|
||||||
//push rg1
|
//push rg1
|
||||||
push zero
|
|
||||||
call serial::read_byte
|
lwi serial::SERIAL_BUFFER, rg0
|
||||||
pop rg0
|
|
||||||
//pop zero
|
|
||||||
push rg0
|
push rg0
|
||||||
call print::print
|
call print::print
|
||||||
pop zero
|
pop zero
|
||||||
@@ -42,3 +38,4 @@ main:
|
|||||||
pop zero
|
pop zero
|
||||||
|
|
||||||
hlt
|
hlt
|
||||||
|
jmp main
|
||||||
|
|||||||
Reference in New Issue
Block a user