Compare commits
2 Commits
7ab1ac8842
...
42bc666c11
| Author | SHA1 | Date | |
|---|---|---|---|
| 42bc666c11 | |||
| 1d38aca523 |
@@ -2,107 +2,38 @@
|
|||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
use std::{fmt, sync::mpsc::Sender};
|
use std::{fmt, sync::mpsc::Sender};
|
||||||
|
|
||||||
// pub struct Logger {}
|
// pub struct Entry {
|
||||||
|
// etype: EntryType,
|
||||||
// impl Logger {
|
// pub message: String,
|
||||||
// pub const fn new() -> Self {
|
|
||||||
// Self {}
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// pub fn log(&self, message: &str) {
|
// #[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
// _ = self;
|
// enum EntryType {
|
||||||
// println!("\x1b[32mINFO:\x1b[0m {message}");
|
// Debug,
|
||||||
|
// Info,
|
||||||
|
// Warn,
|
||||||
|
// Error,
|
||||||
|
// Fatal,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl fmt::Display for EntryType {
|
||||||
|
// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
// write!(
|
||||||
|
// f,
|
||||||
|
// "{:<5}",
|
||||||
|
// match self {
|
||||||
|
// Self::Debug => "DEBUG",
|
||||||
|
// Self::Info => "INFO",
|
||||||
|
// Self::Warn => "WARN",
|
||||||
|
// Self::Error => "ERROR",
|
||||||
|
// Self::Fatal => "FATAL",
|
||||||
|
// }
|
||||||
|
// )
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// #[derive(Debug)]=
|
// impl fmt::Display for Entry {
|
||||||
// pub struct Logger {
|
// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
// pub sender: Sender<Entry>,
|
// write!(f, "{}: {}", self.etype, self.message)
|
||||||
// }
|
|
||||||
|
|
||||||
// impl Logger {
|
|
||||||
// pub fn new(sender: Sender<Entry>) -> Self {
|
|
||||||
// Self { sender }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn debug<T: fmt::Display>(&self, message: T) {
|
|
||||||
// self.sender
|
|
||||||
// .send(Entry {
|
|
||||||
// etype: EntryType::Debug,
|
|
||||||
// message: message.to_string(),
|
|
||||||
// })
|
|
||||||
// .unwrap();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn info<T: fmt::Display>(&self, message: T) {
|
|
||||||
// self.sender
|
|
||||||
// .send(Entry {
|
|
||||||
// etype: EntryType::Info,
|
|
||||||
// message: message.to_string(),
|
|
||||||
// })
|
|
||||||
// .unwrap();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn warn<T: fmt::Display>(&self, message: T) {
|
|
||||||
// self.sender
|
|
||||||
// .send(Entry {
|
|
||||||
// etype: EntryType::Warn,
|
|
||||||
// message: message.to_string(),
|
|
||||||
// })
|
|
||||||
// .unwrap();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn error<T: fmt::Display>(&self, message: T) {
|
|
||||||
// self.sender
|
|
||||||
// .send(Entry {
|
|
||||||
// etype: EntryType::Error,
|
|
||||||
// message: message.to_string(),
|
|
||||||
// })
|
|
||||||
// .unwrap();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn fatal<T: fmt::Display>(&self, message: T) {
|
|
||||||
// self.sender
|
|
||||||
// .send(Entry {
|
|
||||||
// etype: EntryType::Fatal,
|
|
||||||
// message: message.to_string(),
|
|
||||||
// })
|
|
||||||
// .unwrap();
|
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub struct Entry {
|
|
||||||
etype: EntryType,
|
|
||||||
pub message: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
|
||||||
enum EntryType {
|
|
||||||
Debug,
|
|
||||||
Info,
|
|
||||||
Warn,
|
|
||||||
Error,
|
|
||||||
Fatal,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for EntryType {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"{:<5}",
|
|
||||||
match self {
|
|
||||||
Self::Debug => "DEBUG",
|
|
||||||
Self::Info => "INFO",
|
|
||||||
Self::Warn => "WARN",
|
|
||||||
Self::Error => "ERROR",
|
|
||||||
Self::Fatal => "FATAL",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Entry {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "{}: {}", self.etype, self.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ pub fn generate_ast(input: &str, logger: &Logger) -> Result<Program, CompilerErr
|
|||||||
|
|
||||||
let lexer = lexer::Lexer::new(&input);
|
let lexer = lexer::Lexer::new(&input);
|
||||||
let tokens = lexer.collect::<Vec<_>>();
|
let tokens = lexer.collect::<Vec<_>>();
|
||||||
println!("{tokens:#?}");
|
|
||||||
|
// println!("{tokens:#?}");
|
||||||
|
|
||||||
logger.info(&format!("Parsing {} Tokens...", tokens.len()));
|
logger.info(&format!("Parsing {} Tokens...", tokens.len()));
|
||||||
|
|
||||||
|
|||||||
@@ -800,8 +800,6 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_type(&mut self) -> ParseResult<TypeId, CompilerError> {
|
fn parse_type(&mut self) -> ParseResult<TypeId, CompilerError> {
|
||||||
println!("yes {:?}", self.peek_next()?);
|
|
||||||
|
|
||||||
// parse primitive or named type
|
// parse primitive or named type
|
||||||
if expect_tt!(self.peek_next()?, Identifier).accepted() {
|
if expect_tt!(self.peek_next()?, Identifier).accepted() {
|
||||||
return self.parse_type_identifier();
|
return self.parse_type_identifier();
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
use std::thread::sleep;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::{env, fs};
|
||||||
|
|
||||||
|
use crate::emulator::system::model::{Command, Running};
|
||||||
|
use crate::emulator::{config::Config, system::model::State};
|
||||||
|
|
||||||
|
pub fn run_cli() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
// Initialize channels and read in configuration.
|
||||||
|
let (cmd_sender, cmd_receiver) = std::sync::mpsc::channel();
|
||||||
|
let (state_sender, state_reciever) = std::sync::mpsc::channel();
|
||||||
|
|
||||||
|
// not needed for now.
|
||||||
|
// let config = Config::load(Path::new(".dsa.emulator.toml"))?;
|
||||||
|
|
||||||
|
crate::setup_emulator(cmd_receiver, state_sender, None);
|
||||||
|
|
||||||
|
// run CLI.
|
||||||
|
let mut state = State::new(cmd_sender, state_reciever);
|
||||||
|
|
||||||
|
let mut bin_path: Option<String> = None;
|
||||||
|
for (i, arg) in env::args().enumerate().skip(1) {
|
||||||
|
// check for args --bin and <bin_path>
|
||||||
|
if arg == "--bin" {
|
||||||
|
bin_path = Some(env::args().nth(i + 1).expect("Binary path not provided"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let binary =
|
||||||
|
fs::read(bin_path.expect("unreachable")).expect("unable to read binary file");
|
||||||
|
state.send(Command::Write(0, binary));
|
||||||
|
println!("{:?}", state.running);
|
||||||
|
|
||||||
|
sleep(Duration::from_secs(1));
|
||||||
|
|
||||||
|
state.update().unwrap();
|
||||||
|
state.cmd_sender.send(Command::Start).unwrap();
|
||||||
|
loop {
|
||||||
|
sleep(Duration::from_millis(20));
|
||||||
|
state.send(Command::DisplayRequest);
|
||||||
|
state.send(Command::RunningRequest);
|
||||||
|
state.update().expect("update failed");
|
||||||
|
|
||||||
|
for ch in state.serial_buff.drain(..) {
|
||||||
|
print!("{}", ch as char);
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.running == Running::Halted {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
pub mod cli;
|
||||||
#[cfg(feature = "config")]
|
#[cfg(feature = "config")]
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod misc;
|
pub mod misc;
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
pub const DISPLAY_ADDRESS: u32 = 0x20000;
|
||||||
|
pub const SERIAL_ADDRESS: u32 = DISPLAY_ADDRESS + 2000;
|
||||||
@@ -135,6 +135,9 @@ pub fn run_emulator(
|
|||||||
Vec::new()
|
Vec::new()
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
|
let _ = state_tx.send(StateUpdate::Serial(
|
||||||
|
processor.serial_buff.drain(..).collect(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
Command::StackRequest if update => {
|
Command::StackRequest if update => {
|
||||||
let _ = state_tx.send(StateUpdate::StackView(
|
let _ = state_tx.send(StateUpdate::StackView(
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod cache;
|
pub mod cache;
|
||||||
|
pub mod constants;
|
||||||
pub mod emulator;
|
pub mod emulator;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
pub mod model;
|
pub mod model;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ pub enum Command {
|
|||||||
WriteBlock(Address, Box<[u8; 256]>),
|
WriteBlock(Address, Box<[u8; 256]>),
|
||||||
|
|
||||||
// request emulator state.
|
// request emulator state.
|
||||||
|
SerialRequest,
|
||||||
MemRequest(Address, u32),
|
MemRequest(Address, u32),
|
||||||
DisplayRequest,
|
DisplayRequest,
|
||||||
StackRequest,
|
StackRequest,
|
||||||
@@ -79,6 +80,7 @@ pub struct State {
|
|||||||
pub error_log: Vec<String>,
|
pub error_log: Vec<String>,
|
||||||
|
|
||||||
pub instruction_history: Vec<(u32, u32)>,
|
pub instruction_history: Vec<(u32, u32)>,
|
||||||
|
pub serial_buff: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
@@ -95,6 +97,7 @@ impl State {
|
|||||||
display_view: vec![],
|
display_view: vec![],
|
||||||
error_log: vec![],
|
error_log: vec![],
|
||||||
instruction_history: vec![],
|
instruction_history: vec![],
|
||||||
|
serial_buff: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +124,9 @@ impl State {
|
|||||||
StateUpdate::InstructionHistory(history) => {
|
StateUpdate::InstructionHistory(history) => {
|
||||||
self.instruction_history.extend(history);
|
self.instruction_history.extend(history);
|
||||||
}
|
}
|
||||||
|
StateUpdate::Serial(buffer) => {
|
||||||
|
self.serial_buff.extend(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.error_log.len() > 256 {
|
if self.error_log.len() > 256 {
|
||||||
@@ -148,6 +154,7 @@ impl State {
|
|||||||
|
|
||||||
pub enum StateUpdate {
|
pub enum StateUpdate {
|
||||||
Registers(RegFile),
|
Registers(RegFile),
|
||||||
|
Serial(Vec<u8>),
|
||||||
Running(Running),
|
Running(Running),
|
||||||
Instructions(usize),
|
Instructions(usize),
|
||||||
StackView(Vec<u8>),
|
StackView(Vec<u8>),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ use std::{
|
|||||||
|
|
||||||
use crate::emulator::system::{
|
use crate::emulator::system::{
|
||||||
cache::Cache,
|
cache::Cache,
|
||||||
|
constants::{DISPLAY_ADDRESS, SERIAL_ADDRESS},
|
||||||
memory::MemoryUnit,
|
memory::MemoryUnit,
|
||||||
model::{IODevice, ProcessorError, RegFile},
|
model::{IODevice, ProcessorError, RegFile},
|
||||||
};
|
};
|
||||||
@@ -19,6 +20,8 @@ pub struct Processor {
|
|||||||
|
|
||||||
pub void: u32,
|
pub void: u32,
|
||||||
pub cache: Cache,
|
pub cache: Cache,
|
||||||
|
|
||||||
|
pub serial_buff: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Processor {
|
impl Processor {
|
||||||
@@ -31,6 +34,8 @@ impl Processor {
|
|||||||
io_devices,
|
io_devices,
|
||||||
void: 0,
|
void: 0,
|
||||||
cache: Cache::new(),
|
cache: Cache::new(),
|
||||||
|
|
||||||
|
serial_buff: Vec::with_capacity(32768),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +102,7 @@ impl Processor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn display(&mut self) -> Result<Vec<u8>, ProcessorError> {
|
pub fn display(&mut self) -> Result<Vec<u8>, ProcessorError> {
|
||||||
Ok(self.memory.read_range(0x20000, 2000))
|
Ok(self.memory.read_range(DISPLAY_ADDRESS, 2000))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cmp(&mut self, a: u32, b: u32) {
|
pub fn cmp(&mut self, a: u32, b: u32) {
|
||||||
@@ -267,30 +272,41 @@ impl Executable for Instruction {
|
|||||||
// Stores a byte from SrcReg in memory address (base + offset) The effective
|
// Stores a byte from SrcReg in memory address (base + offset) The effective
|
||||||
// address must be byte-aligned.
|
// address must be byte-aligned.
|
||||||
Self::StoreByte(a) => {
|
Self::StoreByte(a) => {
|
||||||
cpu.memory.write_byte(
|
let addr = cpu.get(a.r2)? + u32::from(a.immediate);
|
||||||
cpu.get(a.r2)? + u32::from(a.immediate),
|
let val = cpu.get(a.r1)? as u8;
|
||||||
cpu.get(a.r1)? as u8,
|
if addr == SERIAL_ADDRESS {
|
||||||
);
|
cpu.serial_buff.push(val);
|
||||||
|
}
|
||||||
|
cpu.memory.write_byte(addr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stores a half-word from SrcReg in memory address (base + offset) The
|
// Stores a half-word from SrcReg in memory address (base + offset) The
|
||||||
// effective address must be 2-byte-aligned.
|
// effective address must be 2-byte-aligned.
|
||||||
Self::StoreHalfword(a) => {
|
Self::StoreHalfword(a) => {
|
||||||
// split the value into bytes and then write two bytes
|
let addr = cpu.get(a.r2)? + u32::from(a.immediate);
|
||||||
let bytes = (cpu.get(a.r1)? as u16).to_le_bytes();
|
let bytes = (cpu.get(a.r1)? as u16).to_le_bytes();
|
||||||
cpu.memory
|
|
||||||
.write_byte(cpu.get(a.r2)? + u32::from(a.immediate), bytes[0]);
|
if addr == SERIAL_ADDRESS {
|
||||||
cpu.memory
|
cpu.serial_buff.extend(bytes);
|
||||||
.write_byte(cpu.get(a.r2)? + u32::from(a.immediate) + 1, bytes[1]);
|
}
|
||||||
|
|
||||||
|
// split the value into bytes and then write two bytes
|
||||||
|
cpu.memory.write_byte(addr, bytes[0]);
|
||||||
|
cpu.memory.write_byte(addr + 1, bytes[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stores a word from SrcReg in memory address (base + offset) The effective
|
// Stores a word from SrcReg in memory address (base + offset) The effective
|
||||||
// address must be 4-byte-aligned.
|
// address must be 4-byte-aligned.
|
||||||
Self::StoreWord(a) => {
|
Self::StoreWord(a) => {
|
||||||
cpu.memory.write_word(
|
let addr = cpu.get(a.r2)? + u32::from(a.immediate);
|
||||||
cpu.get(a.r2)? + u32::from(a.immediate),
|
let val = cpu.get(a.r1)?;
|
||||||
cpu.get(a.r1)?,
|
let bytes = val.to_le_bytes();
|
||||||
)?;
|
|
||||||
|
if addr == SERIAL_ADDRESS {
|
||||||
|
cpu.serial_buff.extend(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu.memory.write_word(addr, val)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loads a 16-bit literal value into reg, setting the bottom 16 bits of the
|
// Loads a 16-bit literal value into reg, setting the bottom 16 bits of the
|
||||||
|
|||||||
@@ -448,7 +448,7 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut assembler = Assembler::new(&dsa_path);
|
let mut assembler = Assembler::new(&dsa_path);
|
||||||
compiler.start();
|
assembler.start();
|
||||||
|
|
||||||
// Or block until done
|
// Or block until done
|
||||||
self.output = match assembler.output() {
|
self.output = match assembler.output() {
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
|
use std::env;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use dsa_rs::emulator::{config::Config, misc::rpc::get_rpc_client_or_none};
|
use dsa_rs::emulator::{config::Config, misc::rpc::get_rpc_client_or_none};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
if env::args().any(|arg| arg == "--cli") {
|
||||||
|
dsa_rs::emulator::cli::run_cli()?;
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize channels and read in configuration.
|
// Initialize channels and read in configuration.
|
||||||
let (cmd_sender, cmd_receiver) = std::sync::mpsc::channel();
|
let (cmd_sender, cmd_receiver) = std::sync::mpsc::channel();
|
||||||
let (state_sender, state_reciever) = std::sync::mpsc::channel();
|
let (state_sender, state_reciever) = std::sync::mpsc::channel();
|
||||||
|
|||||||
@@ -0,0 +1,244 @@
|
|||||||
|
// lib:
|
||||||
|
// print_serial.dsa
|
||||||
|
|
||||||
|
// usage:
|
||||||
|
//
|
||||||
|
// include print_serial "<relative path>"
|
||||||
|
//
|
||||||
|
// usage for print:
|
||||||
|
// push (register containing address of string)
|
||||||
|
// push pcx
|
||||||
|
// jmp print_serial::print
|
||||||
|
//
|
||||||
|
// usage for print_byte:
|
||||||
|
// push (register containing byte)
|
||||||
|
// push pcx
|
||||||
|
// jmp print_serial::print_byte
|
||||||
|
//
|
||||||
|
// usage for print_word:
|
||||||
|
// push (register containing word)
|
||||||
|
// push pcx
|
||||||
|
// jmp print_serial::print_word
|
||||||
|
//
|
||||||
|
// usage for print_hex_byte:
|
||||||
|
// push (register containing byte)
|
||||||
|
// push pcx
|
||||||
|
// jmp print_serial::print_hex_byte
|
||||||
|
//
|
||||||
|
// usage for print_hex_word:
|
||||||
|
// push (register containing word)
|
||||||
|
// push pcx
|
||||||
|
// jmp print_serial::print_hex_word
|
||||||
|
//
|
||||||
|
// usage for print_num:
|
||||||
|
// push (register containing number to print in decimal)
|
||||||
|
// push pcx
|
||||||
|
// jmp print_serial::print_num
|
||||||
|
//
|
||||||
|
// usage for println:
|
||||||
|
// push (register containing address of string)
|
||||||
|
// push pcx
|
||||||
|
// jmp print_serial::println
|
||||||
|
//
|
||||||
|
|
||||||
|
include maths "../maths/core.dsa"
|
||||||
|
|
||||||
|
dw serial: 0x207D0 // 0x20000 + 2000
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// prints the string at addr(arg[0]) to the serial port.
|
||||||
|
print:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
|
ldw bpr, rg0, 8
|
||||||
|
lwi 0x207D0, rg1
|
||||||
|
|
||||||
|
_print_loop:
|
||||||
|
ldb rg0, acc
|
||||||
|
cmp acc, zero
|
||||||
|
jeq _end
|
||||||
|
stb acc, rg1
|
||||||
|
|
||||||
|
addi rg0, 1
|
||||||
|
jmp _print_loop
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// prints the string at addr(arg[0]) followed by a newline to the serial port.
|
||||||
|
println:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
|
ldw bpr, rg0, 8
|
||||||
|
lwi 0x207D0, rg1
|
||||||
|
|
||||||
|
_println_loop:
|
||||||
|
ldb rg0, acc
|
||||||
|
cmp acc, zero
|
||||||
|
jeq _println_end
|
||||||
|
stb acc, rg1
|
||||||
|
|
||||||
|
addi rg0, 1
|
||||||
|
jmp _println_loop
|
||||||
|
|
||||||
|
_println_end:
|
||||||
|
lli 0x0A, rg2 // newline character
|
||||||
|
stb rg2, rg1
|
||||||
|
jmp _end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// prints the word in arg[0] as 4 raw bytes to the serial port.
|
||||||
|
print_word:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
|
ldw bpr, rg0, 8
|
||||||
|
lwi 0x207D0, rg1
|
||||||
|
|
||||||
|
stb rg0, rg1
|
||||||
|
shr rg0, 8
|
||||||
|
stb rg0, rg1
|
||||||
|
shr rg0, 8
|
||||||
|
stb rg0, rg1
|
||||||
|
shr rg0, 8
|
||||||
|
stb rg0, rg1
|
||||||
|
jmp _end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// prints the last byte of arg[0] to the serial port.
|
||||||
|
print_byte:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
|
ldw bpr, rg0, 8
|
||||||
|
lwi 0x207D0, rg1
|
||||||
|
|
||||||
|
stb rg0, rg1
|
||||||
|
jmp _end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// prints the value of arg[0] to the serial port in hex.
|
||||||
|
print_hex_word:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
|
lwi 0x207D0, 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 serial port in hex.
|
||||||
|
print_hex_byte:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
|
ldw bpr, rg0, 8
|
||||||
|
lwi 0x207D0, 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
|
||||||
|
return
|
||||||
|
|
||||||
|
// print a hex digit
|
||||||
|
_print_hex_nibble:
|
||||||
|
lli 10, rg3
|
||||||
|
cmp rg0, rg3
|
||||||
|
jlt _print_hex_nibble_number
|
||||||
|
addi rg0, 0x37, rg0
|
||||||
|
stb rg0, rg1
|
||||||
|
return
|
||||||
|
|
||||||
|
_print_hex_nibble_number:
|
||||||
|
addi rg0, 0x30, rg0
|
||||||
|
stb rg0, rg1
|
||||||
|
return
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// prints arg[0] as a decimal number to the serial port.
|
||||||
|
print_num:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
|
||||||
|
ldw bpr, rg0, 8
|
||||||
|
lli 0, rg5
|
||||||
|
|
||||||
|
cmp rg0, zero
|
||||||
|
jne _print_num_extract_digits
|
||||||
|
|
||||||
|
lli 0x30, rg6
|
||||||
|
push rg6
|
||||||
|
lli 1, rg5
|
||||||
|
jmp _print_num_output
|
||||||
|
|
||||||
|
_print_num_extract_digits:
|
||||||
|
cmp rg0, zero
|
||||||
|
jeq _print_num_output
|
||||||
|
|
||||||
|
push rg0
|
||||||
|
lli 10, rg1
|
||||||
|
push rg1
|
||||||
|
call maths::divmod
|
||||||
|
pop rg0
|
||||||
|
pop rg1
|
||||||
|
|
||||||
|
addi rg1, 0x30, rg6
|
||||||
|
push rg6
|
||||||
|
inc rg5
|
||||||
|
|
||||||
|
jmp _print_num_extract_digits
|
||||||
|
|
||||||
|
_print_num_output:
|
||||||
|
lwi 0x207D0, rg1
|
||||||
|
|
||||||
|
_print_num_output_loop:
|
||||||
|
cmp rg5, zero
|
||||||
|
jeq _print_num_done
|
||||||
|
|
||||||
|
pop rg6
|
||||||
|
stb rg6, rg1
|
||||||
|
dec rg5
|
||||||
|
|
||||||
|
jmp _print_num_output_loop
|
||||||
|
|
||||||
|
_print_num_done:
|
||||||
|
// fall through to _end
|
||||||
|
|
||||||
|
// ------------------------------------------
|
||||||
|
// return
|
||||||
|
_end:
|
||||||
|
mov bpr, spr
|
||||||
|
pop bpr
|
||||||
|
return
|
||||||
+140
-9
@@ -1,12 +1,143 @@
|
|||||||
// program to just test compute power
|
// GENERATED BY DSC COMPILER
|
||||||
|
// Generated at 2026-02-23 17:29:47
|
||||||
|
|
||||||
dw large_num: 0x333333 // 333,333 instructions
|
// Imports
|
||||||
start:
|
include print: "./lib/io/print.dsa"
|
||||||
ldw large_num, rg0
|
include alloc: "./lib/memory/block_alloc.dsa"
|
||||||
|
|
||||||
// run approx 1m instructions
|
// Globals & Reserved Memory
|
||||||
loop:
|
|
||||||
dec rg0
|
// Entry Point
|
||||||
cmp rg0, zero
|
dw stack: 0x010000
|
||||||
jgt loop
|
db message: "Process Exited with code:"
|
||||||
|
_init:
|
||||||
|
ldw stack, bpr, 0
|
||||||
|
mov bpr, spr
|
||||||
|
push zero
|
||||||
|
call main
|
||||||
|
call print::print_newline
|
||||||
|
lwi message, rg0
|
||||||
|
push rg0
|
||||||
|
call print::print
|
||||||
|
pop zero
|
||||||
|
call print::print_hex_word
|
||||||
|
pop zero
|
||||||
hlt
|
hlt
|
||||||
|
|
||||||
|
// Return
|
||||||
|
_ret:
|
||||||
|
mov bpr, spr
|
||||||
|
pop bpr
|
||||||
|
return
|
||||||
|
|
||||||
|
db str_16: "successful free of ptr"
|
||||||
|
// fn main() -> u32
|
||||||
|
main:
|
||||||
|
push bpr
|
||||||
|
mov spr, bpr
|
||||||
|
lli 32, rg0
|
||||||
|
lli 64, rg1
|
||||||
|
// push arg 1
|
||||||
|
push rg0
|
||||||
|
// push arg 0
|
||||||
|
push rg1
|
||||||
|
call alloc::init
|
||||||
|
pop rg2
|
||||||
|
pop zero
|
||||||
|
push rg2
|
||||||
|
// push arg 0
|
||||||
|
push rg2
|
||||||
|
call print::print_hex_word
|
||||||
|
pop zero
|
||||||
|
call print::print_newline
|
||||||
|
ldw spr, rg0, 0
|
||||||
|
stw rg0, spr, 0
|
||||||
|
// push arg 0
|
||||||
|
push rg0
|
||||||
|
call alloc::alloc
|
||||||
|
pop rg1
|
||||||
|
push rg1
|
||||||
|
// push arg 0
|
||||||
|
push rg1
|
||||||
|
call print::print_hex_word
|
||||||
|
pop zero
|
||||||
|
lli 200, rg0
|
||||||
|
ldw spr, rg1, 0
|
||||||
|
stw rg0, rg1, 0
|
||||||
|
stw rg1, spr, 0
|
||||||
|
call print::print_newline
|
||||||
|
ldw spr, rg0, 4
|
||||||
|
stw rg0, spr, 4
|
||||||
|
// push arg 0
|
||||||
|
push rg0
|
||||||
|
call alloc::alloc
|
||||||
|
pop rg2
|
||||||
|
push rg2
|
||||||
|
// push arg 0
|
||||||
|
push rg2
|
||||||
|
call print::print_hex_word
|
||||||
|
pop zero
|
||||||
|
call print::print_newline
|
||||||
|
ldw spr, rg0, 4
|
||||||
|
ldw rg0, rg2, 0
|
||||||
|
stw rg0, spr, 4
|
||||||
|
// push arg 0
|
||||||
|
push rg2
|
||||||
|
call print::print_num
|
||||||
|
pop zero
|
||||||
|
ldw spr, rg2, 4
|
||||||
|
stw rg2, spr, 4
|
||||||
|
addi spr, 4, rg3
|
||||||
|
ldw spr, rg2, 8
|
||||||
|
stw rg2, spr, 8
|
||||||
|
// push arg 1
|
||||||
|
push rg3
|
||||||
|
// push arg 0
|
||||||
|
push rg2
|
||||||
|
call alloc::free
|
||||||
|
pop zero
|
||||||
|
pop zero
|
||||||
|
ldw spr, rg2, 8
|
||||||
|
stw rg2, spr, 8
|
||||||
|
// push arg 0
|
||||||
|
push rg2
|
||||||
|
call alloc::alloc
|
||||||
|
pop rg3
|
||||||
|
push rg3
|
||||||
|
call print::print_newline
|
||||||
|
ldw spr, rg2, 0
|
||||||
|
stw rg2, spr, 0
|
||||||
|
// push arg 0
|
||||||
|
push rg2
|
||||||
|
call print::print_hex_word
|
||||||
|
pop zero
|
||||||
|
call print::print_newline
|
||||||
|
ldw spr, rg2, 8
|
||||||
|
stw rg2, spr, 8
|
||||||
|
// push arg 0
|
||||||
|
push rg2
|
||||||
|
call print::print_hex_word
|
||||||
|
pop zero
|
||||||
|
ldw spr, rg2, 8
|
||||||
|
lli 0, rg4
|
||||||
|
cmp rg2, rg4
|
||||||
|
lli 1, rg5
|
||||||
|
jeq _cmp_end_12
|
||||||
|
lli 0, rg5
|
||||||
|
_cmp_end_12:
|
||||||
|
cmp rg5, zero
|
||||||
|
jeq _else_14
|
||||||
|
_then_13:
|
||||||
|
lwi str_16, rg4
|
||||||
|
stw rg2, spr, 8
|
||||||
|
// push arg 0
|
||||||
|
push rg4
|
||||||
|
call print::print
|
||||||
|
pop zero
|
||||||
|
jmp _end_15
|
||||||
|
_else_14:
|
||||||
|
nop
|
||||||
|
_end_15:
|
||||||
|
lli 0, rg4
|
||||||
|
stw rg4, bpr, 8
|
||||||
|
jmp _ret
|
||||||
Reference in New Issue
Block a user