diff --git a/.idea/dsa2.iml b/.idea/dsa2.iml
index 433611a..0a6f00f 100644
--- a/.idea/dsa2.iml
+++ b/.idea/dsa2.iml
@@ -7,9 +7,13 @@
-
-
-
+
+
+
+
+
+
+
diff --git a/Cargo.toml b/Cargo.toml
index 1b5ed0a..a5bd01b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
[workspace]
-members = ["dsa/common", "dsa/assembler", "dsa/emulator/frontend", "dsa/linker", "dsa/compiler", "dsa/emulator/backend"]
+members = ["dsa/common", "dsa/assembler", "dsa/emulator/emulator_ui", "dsa/linker", "dsa/compiler", "dsa/emulator/emulator_core", "dsx/dsx_common", "dsx/dsx_server", "dsx/dsx_client", "dsa/disassembler"]
resolver = "3"
[workspace.package]
diff --git a/dsa/assembler/Cargo.toml b/dsa/assembler/Cargo.toml
index 6165c2d..f5f1547 100644
--- a/dsa/assembler/Cargo.toml
+++ b/dsa/assembler/Cargo.toml
@@ -13,6 +13,7 @@ name = "assembler"
path = "src/lib.rs"
[dependencies]
+binrw = "0.15.1"
clap = { version = "4.6.0", features = ["derive"] }
common = { path = "../common" }
diff --git a/dsa/assembler/src/assembler/codegen.rs b/dsa/assembler/src/assembler/codegen.rs
index 78ddadf..f08dcb5 100644
--- a/dsa/assembler/src/assembler/codegen.rs
+++ b/dsa/assembler/src/assembler/codegen.rs
@@ -78,7 +78,7 @@ fn build_instruction(node: &Node) -> Result {
fn ins_mov(
opcode: Opcode,
- args: &[crate::assembler::model::Token],
+ args: &[Token],
) -> Result {
let Some(src_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
@@ -98,7 +98,7 @@ fn ins_mov(
fn ins_cmov(
opcode: Opcode,
- args: &[crate::assembler::model::Token],
+ args: &[Token],
) -> Result {
let Some(src_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
@@ -122,7 +122,7 @@ fn ins_cmov(
fn ins_ldx_stx(
opcode: Opcode,
- args: &[crate::assembler::model::Token],
+ args: &[Token],
) -> Result {
let Some(src_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
@@ -153,7 +153,7 @@ fn ins_ldx_stx(
fn ins_stack(
opcode: Opcode,
- args: &[crate::assembler::model::Token],
+ args: &[Token],
) -> Result {
let Some(reg_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
@@ -169,7 +169,7 @@ fn ins_stack(
fn ins_load_imm(
opcode: Opcode,
- args: &[crate::assembler::model::Token],
+ args: &[Token],
) -> Result {
let Some(value_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
@@ -190,7 +190,7 @@ fn ins_load_imm(
fn ins_jump_unconditional(
opcode: Opcode,
- args: &[crate::assembler::model::Token],
+ args: &[Token],
) -> Result {
let Some(addr_imm_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
@@ -212,7 +212,7 @@ fn ins_jump_unconditional(
fn ins_jump_conditional(
opcode: Opcode,
- args: &[crate::assembler::model::Token],
+ args: &[Token],
) -> Result {
let Some(condition_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
@@ -239,7 +239,7 @@ fn ins_jump_conditional(
fn ins_comparison(
opcode: Opcode,
- args: &[crate::assembler::model::Token],
+ args: &[Token],
) -> Result {
let Some(left_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
@@ -267,7 +267,7 @@ fn ins_comparison(
fn ins_bitshift(
opcode: Opcode,
- args: &[crate::assembler::model::Token],
+ args: &[Token],
) -> Result {
let Some(src_reg) = args.first() else {
return Err(AssembleError::MissingArgument(0));
@@ -296,7 +296,7 @@ fn ins_bitshift(
fn ins_arithmetic(
opcode: Opcode,
- args: &[crate::assembler::model::Token],
+ args: &[Token],
) -> Result {
let Some(left_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
@@ -327,7 +327,7 @@ fn ins_arithmetic(
fn ins_imm_arithmetic(
opcode: Opcode,
- args: &[crate::assembler::model::Token],
+ args: &[Token],
) -> Result {
let Some(reg_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
@@ -350,7 +350,7 @@ fn ins_imm_arithmetic(
})
}
-fn ins_not(args: &[crate::assembler::model::Token]) -> Result {
+fn ins_not(args: &[Token]) -> Result {
let Some(reg_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
@@ -363,7 +363,7 @@ fn ins_not(args: &[crate::assembler::model::Token]) -> Result Result {
+fn ins_interrupt(args: &[Token]) -> Result {
let Some(code_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
};
@@ -373,7 +373,7 @@ fn ins_interrupt(args: &[crate::assembler::model::Token]) -> Result Result {
let Some(immediate_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
@@ -384,7 +384,7 @@ fn build_data_instruction(
}
fn build_segment_instruction(
- args: &[crate::assembler::model::Token],
+ args: &[Token],
) -> Result {
let Some(immediate_token) = args.first() else {
return Err(AssembleError::MissingArgument(0));
diff --git a/dsa/assembler/src/assembler/mod.rs b/dsa/assembler/src/assembler/mod.rs
index 9f3d8a7..f1ab0ad 100644
--- a/dsa/assembler/src/assembler/mod.rs
+++ b/dsa/assembler/src/assembler/mod.rs
@@ -11,8 +11,11 @@ use std::{
},
thread,
};
-
+use std::collections::HashMap;
+use std::io::Cursor;
+use common::formats::binary_dse::{DseExecutable, SymbolEntry};
use common::prelude::Instruction;
+use crate::assembler::resolver2::{resolve_address, resolve_dependencies, resolve_symbols, split_sections, SectionId};
// Module declarations
#[macro_use]
@@ -21,12 +24,14 @@ pub mod macros;
#[allow(clippy::module_inception)]
pub mod codegen;
pub mod expand;
-pub mod lexer;
-pub mod model;
-pub mod parser;
-pub mod resolver;
-use crate::assemblerv2::lexer::Lexer;
+mod lexer;
+mod model;
+pub mod parser;
+// pub mod resolver;
+pub mod resolver2;
+
+
// Re-exports
pub use self::{
@@ -35,7 +40,7 @@ pub use self::{
lexer::lexer,
model::{Module, Node, Opcode, Symbol, Token, TokenType},
parser::{Parser, Program},
- resolver::{create_sections, resolve_dependencies, resolve_symbols},
+ // resolver::{create_sections, resolve_dependencies, resolve_symbols},
};
pub struct Assembler {
@@ -67,23 +72,33 @@ impl Assembler {
let tx = self.result_tx.clone();
thread::spawn(move || match assemble(&src) {
- Ok(res) => {
- let buffer: Vec = res
- .iter()
- .flat_map(|instruction| instruction.to_le_bytes())
- .collect();
- tx.send(Ok(buffer))
- .expect("Failed to send compilation result from worker thread");
- }
- Err(err) => {
- tx.send(Err(err))
- .expect("Failed to send compilation error from worker thread");
+ Ok(exe) => {
+ let mut buffer = Cursor::new(Vec::new());
+ match exe.write(&mut buffer) {
+ Ok(()) => {
+ tx.send(Ok(buffer.into_inner()))
+ .expect("Failed to send compilation result from worker thread");
+ }
+ Err(e) => {
+ tx.send(Err(AssembleError::Generic))
+ .expect("...");
+ }
+ }
}
+ Err(err) => { /* unchanged */ }
});
self.is_running = true;
}
+ /// Polls the result channel to check if a compilation result is ready.
+ ///
+ /// This method attempts a non-blocking read (`try_recv`) from the result receiver.
+ /// It returns `Some(Ok(Vec))` if the compilation successfully finished and
+ /// the binary output is available, or `None` if no result was received yet.
+ ///
+ /// If it receives an error via `mpsc::TryRecvError::Disconnected`, it indicates that
+ /// the worker thread terminated unexpectedly, returning a specific error string.
pub fn poll(&mut self) -> Option, String>> {
if !self.is_running {
return None;
@@ -130,36 +145,114 @@ impl Assembler {
impl Assembler {}
-fn assemble(src: &Path) -> Result, AssembleError> {
+// fn assemble(src: &Path) -> Result, AssembleError> {
+// let mut modules = HashSet::new();
+// let mut program = Program::new();
+//
+// let hash = quick_hash(src);
+//
+// if modules.contains(&hash) {
+// return Ok(vec![]);
+// }
+//
+// prepare_dependency(src, &mut modules, &mut program)?;
+//
+// let mut nodes = program.nodes.clone();
+//
+// println!("PRE LINK");
+// for node in &nodes {
+// println!("{:?}", node);
+// }
+//
+// create_sections(&mut nodes)?;
+// resolve_symbols(&mut nodes)?;
+//
+// println!("Generating assembly output...");
+//
+// let instructions = codegen(nodes)?;
+//
+// println!("Compilation Successful");
+// Ok(instructions)
+// }
+
+fn assemble(src: &Path) -> Result {
let mut modules = HashSet::new();
let mut program = Program::new();
- let hash = quick_hash(src);
-
- if modules.contains(&hash) {
- return Ok(vec![]);
- }
-
prepare_dependency(src, &mut modules, &mut program)?;
- let mut nodes = program.nodes.clone();
+ let nodes = program.nodes.clone();
println!("PRE LINK");
for node in &nodes {
println!("{:?}", node);
}
- create_sections(&mut nodes)?;
- resolve_symbols(&mut nodes)?;
+ let (data_nodes, mut text_nodes) = split_sections(nodes);
+ let symbol_table = resolve_symbols(&data_nodes, &mut text_nodes)?;
+ let text_len = text_nodes.len() as u32;
println!("Generating assembly output...");
+ let instructions = codegen(text_nodes)?;
+ let text: Vec = instructions
+ .iter()
+ .map(|i| i.0).collect();
- let instructions = codegen(nodes)?;
+ let data = build_data_bytes(&data_nodes)?;
+
+ // Build string table + SymbolEntry list from the resolved symbol table
+ let mut string_table = Vec::new();
+ let mut symbols = Vec::new();
+ for (symbol, entry) in &symbol_table {
+ let name_offset = string_table.len() as u32;
+ string_table.extend_from_slice(symbol.name.as_bytes());
+ string_table.push(0); // null terminator
+
+ symbols.push(SymbolEntry {
+ name_offset,
+ value: resolve_address(*entry, text_len),
+ section: match entry.1 {
+ SectionId::Text => 2,
+ SectionId::Data => 1,
+ },
+ binding: 1, // global — refine later if adding local/weak
+ _pad: 0,
+ });
+ }
+
+ // Entry point: first symbol to jump to is '_init'
+ let entry_point = symbol_table
+ .iter()
+ .find(|(sym, _)| sym.name == "_init")
+ .map(|(_, entry)| resolve_address(*entry, text_len))
+ .ok_or(AssembleError::UndefinedSymbol(Symbol {
+ name: "_init".to_string(),
+ module: Module::Resolved(0),
+ }))?;
println!("Compilation Successful");
- Ok(instructions)
+
+ Ok(DseExecutable::new(
+ symbols.as_slice(),
+ &string_table,
+ &data,
+ &text,
+ entry_point,
+ ).unwrap())
}
+fn build_data_bytes(data_nodes: &[Node]) -> Result, AssembleError> {
+ let mut bytes = Vec::with_capacity(data_nodes.len() * 4);
+ for node in data_nodes {
+ let Token::Immediate(value) = node.arg(0)? else {
+ return Err(AssembleError::InvalidArg);
+ };
+ bytes.extend_from_slice(&value.to_le_bytes());
+ }
+ Ok(bytes)
+}
+
+
fn prepare_dependency(
path: &Path,
modules: &mut HashSet,
diff --git a/dsa/assembler/src/assembler/resolver2.rs b/dsa/assembler/src/assembler/resolver2.rs
new file mode 100644
index 0000000..e19510f
--- /dev/null
+++ b/dsa/assembler/src/assembler/resolver2.rs
@@ -0,0 +1,168 @@
+use std::collections::HashMap;
+use std::path::Path;
+
+use crate::assembler::model::{Module, Node, Opcode, Symbol, Token};
+use crate::assembler::{quick_hash, AssembleError};
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum SectionId {
+ Data,
+ Text,
+}
+
+/// Splits a flat (possibly multi-module) node list into separate data and
+/// text streams. Segment/Include markers are dropped here — module
+/// disambiguation lives on `Symbol.module`, not node position, so we don't
+/// need them past this point.
+pub fn split_sections(nodes: Vec) -> (Vec, Vec) {
+ let mut data = Vec::new();
+ let mut text = Vec::new();
+
+ for node in nodes {
+ match node.opcode() {
+ Opcode::Data => data.push(node),
+ Opcode::Segment | Opcode::Include => {}
+ _ => text.push(node),
+ }
+ }
+
+ (data, text)
+}
+
+pub fn generate_symbol_table(
+ data_nodes: &[Node],
+ text_nodes: &[Node],
+) -> HashMap {
+ let mut table = HashMap::new();
+
+ for (i, node) in data_nodes.iter().enumerate() {
+ if let Some(symbol) = node.label() {
+ table.insert(symbol, (4 * i as u32, SectionId::Data));
+ }
+ }
+ for (i, node) in text_nodes.iter().enumerate() {
+ if let Some(symbol) = node.label() {
+ table.insert(symbol, (4 * i as u32, SectionId::Text));
+ }
+ }
+
+ table
+}
+
+/// v1 loader convention: TEXT is placed at address 0, DATA immediately
+/// follows it. This is a stopgap until real relocations exist — it's the
+/// same assumption your current jmp-hack already makes, just explicit now.
+pub fn resolve_address((offset, section): (u32, SectionId), text_len_words: u32) -> u32 {
+ match section {
+ SectionId::Text => offset,
+ SectionId::Data => (text_len_words * 4) + offset,
+ }
+}
+
+/// Patches every symbol reference in `text_nodes` with its resolved absolute
+/// address, and returns the symbol table so the caller can build the
+/// executable's symbol/string tables from it.
+pub fn resolve_symbols(
+ data_nodes: &[Node],
+ text_nodes: &mut [Node],
+) -> Result, AssembleError> {
+ let symbol_table = generate_symbol_table(data_nodes, text_nodes);
+ let text_len = text_nodes.len() as u32;
+
+ for node in text_nodes.iter_mut() {
+ match node.opcode() {
+ Opcode::Jmp | Opcode::Call | Opcode::Jic | Opcode::Jnc | Opcode::Lli | Opcode::Lui => {
+ if let Token::Symbol(symbol) = node
+ .arg(0)
+ .expect("Expected argument 0 for jump-like opcode")
+ {
+ let Some(entry) = symbol_table.get(&symbol) else {
+ return Err(AssembleError::UndefinedSymbol(symbol));
+ };
+ node.tokens[0] = Token::Immediate(resolve_address(*entry, text_len));
+ }
+ }
+ Opcode::Jez | Opcode::Jnz => {
+ if let Token::Symbol(symbol) = node
+ .arg(1)
+ .expect("Expected argument 1 for jump-like opcode")
+ {
+ let Some(entry) = symbol_table.get(&symbol) else {
+ return Err(AssembleError::UndefinedSymbol(symbol));
+ };
+ node.tokens[1] = Token::Immediate(resolve_address(*entry, text_len));
+ }
+ }
+ _ => (),
+ }
+ }
+
+ Ok(symbol_table)
+}
+
+// resolve_dependencies is unchanged — keep exactly as you have it.
+pub fn resolve_dependencies(
+ mut nodes: Vec,
+ base_dir: &Path,
+) -> Result, AssembleError> {
+ // First we get a list of imports.
+ let mut dependencies = Vec::new();
+ for node in &nodes {
+ if node.opcode() == Opcode::Include {
+ // we want the path, and the name
+ let name = if let Token::Symbol(name) = node
+ .arg(0)
+ .expect("Expected argument #0 for Include directive.")
+ {
+ name.name.clone()
+ } else {
+ unreachable!()
+ }; //node.2.get(0).unwrap()
+
+ let Ok(Token::StringLit(path)) = node.arg(1) else {
+ unreachable!()
+ };
+
+ let full_path = base_dir.join(path);
+ let canonical_path = full_path
+ .canonicalize()
+ .map_err(|_| AssembleError::InvalidFile(full_path.clone()))?;
+
+ let hash = quick_hash(&canonical_path);
+
+ dependencies.push((name, hash));
+ }
+ }
+
+ let mut changes = Vec::<(u32, u32, Symbol)>::new();
+ // now we resolve the symbols on all the nodes
+ // we need to check all operands for unresolved signals
+ for (i, node) in nodes.clone().iter().enumerate() {
+ let Node {
+ tokens: operands, ..
+ } = node;
+ for (j, token) in operands.iter().enumerate() {
+ if let Token::Symbol(symbol) = token {
+ for d in &dependencies {
+ if let Module::Unresolved(name) = symbol.module.clone() {
+ if name != d.0 {
+ continue;
+ }
+
+ let symbol = Symbol {
+ name: symbol.name.clone(),
+ module: Module::Resolved(d.1),
+ };
+ changes.push((i as u32, j as u32, symbol));
+ }
+ }
+ }
+ }
+ }
+
+ for (i, j, symbol) in changes {
+ nodes[i as usize].tokens[j as usize] = Token::Symbol(symbol);
+ }
+
+ Ok(nodes)
+}
diff --git a/dsa/assembler/src/assemblerv2/context.rs b/dsa/assembler/src/assemblerv2/context.rs
new file mode 100644
index 0000000..e1c2b28
--- /dev/null
+++ b/dsa/assembler/src/assemblerv2/context.rs
@@ -0,0 +1,24 @@
+use std::path::PathBuf;
+
+pub struct BuildContext {
+ filename: PathBuf,
+ stage: BuildStage,
+ // Logging
+}
+
+impl BuildContext {
+ pub fn new(filename: PathBuf) -> Self {
+ Self {
+ filename,
+ stage: BuildStage::Lexing,
+ }
+ }
+}
+
+pub enum BuildStage {
+ Lexing,
+ Parsing,
+ PseudoExpansion,
+ Linking,
+ CodeGeneration,
+}
diff --git a/dsa/assembler/src/assemblerv2/lexer.rs b/dsa/assembler/src/assemblerv2/lexer.rs
index f280404..71c09cd 100644
--- a/dsa/assembler/src/assemblerv2/lexer.rs
+++ b/dsa/assembler/src/assemblerv2/lexer.rs
@@ -2,7 +2,8 @@ use std::{str::FromStr, thread, time::Duration};
use common::{asm::AsmOpcode, prelude::Register};
-use crate::assembler::{AssembleError, Module, Opcode, Symbol, Token, lexer::parse_opcode};
+use crate::assembler::{AssembleError, Module, Symbol};
+use crate::assemblerv2::Token;
pub struct Lexer {
src: Vec,
@@ -75,7 +76,7 @@ impl Lexer {
buffer.push(self.src.pop().unwrap() as char);
}
- if let Ok(opcode) = Opcode::from_str(&buffer) {
+ if let Ok(opcode) = AsmOpcode::from_str(&buffer) {
tokens.push(Token::Opcode(opcode));
continue;
}
diff --git a/dsa/assembler/src/assemblerv2/mod.rs b/dsa/assembler/src/assemblerv2/mod.rs
index ac38c29..e038948 100644
--- a/dsa/assembler/src/assemblerv2/mod.rs
+++ b/dsa/assembler/src/assemblerv2/mod.rs
@@ -1,46 +1,43 @@
-// mod error;
-pub mod lexer;
-// pub mod parser;
+mod error;
+mod lexer;
+mod parser;
use core::fmt;
-
use crate::assembler::{AssembleError, Symbol};
-// use common::{asm::AsmOpcode, prelude::Register};
+use common::{asm::AsmOpcode, prelude::Register};
use lexer::Lexer;
-// use parser::Parser;
+use parser::Parser;
pub fn asm(input: &str) -> Result, AssembleError> {
let mut lexer = Lexer::new(input.to_string(), 0);
let tokens = lexer.run()?;
- // let ast = Parser::new(tokens).parse().unwrap();
+ let ast = Parser::new(tokens).parse().unwrap();
- // println!("{:#?}", ast);
-
- // let ast = parser::parse(tokens)?;
+ println!("{:#?}", ast);
Ok(vec![])
}
-// #[derive(Debug, Clone)]
-// pub enum Token {
-// Symbol(Symbol),
-// Register(Register),
-// Immediate(u32),
-// StringLit(String),
-// CharLit(char),
-// Opcode(AsmOpcode),
-// }
+#[derive(Debug, Clone)]
+pub enum Token {
+ Symbol(Symbol),
+ Register(Register),
+ Immediate(u32),
+ StringLit(String),
+ CharLit(char),
+ Opcode(AsmOpcode),
+}
-// impl fmt::Display for Token {
-// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-// match self {
-// Self::Symbol(symbol) => write!(f, "{symbol}"),
-// Self::Register(register) => write!(f, "{register}",),
-// Self::Immediate(immediate) => write!(f, "{immediate}",),
-// Self::StringLit(string_lit) => write!(f, "{string_lit}",),
-// Self::CharLit(char_lit) => write!(f, "{char_lit}",),
-// Self::Opcode(opcode) => write!(f, "{opcode}",),
-// }
-// }
-// }
+impl fmt::Display for Token {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::Symbol(symbol) => write!(f, "{symbol}"),
+ Self::Register(register) => write!(f, "{register}",),
+ Self::Immediate(immediate) => write!(f, "{immediate}",),
+ Self::StringLit(string_lit) => write!(f, "{string_lit}",),
+ Self::CharLit(char_lit) => write!(f, "{char_lit}",),
+ Self::Opcode(opcode) => write!(f, "{opcode}",),
+ }
+ }
+}
diff --git a/dsa/assembler/src/assemblerv2/parser.rs b/dsa/assembler/src/assemblerv2/parser.rs
index c77d978..1aca47b 100644
--- a/dsa/assembler/src/assemblerv2/parser.rs
+++ b/dsa/assembler/src/assemblerv2/parser.rs
@@ -2,11 +2,11 @@ use std::path::PathBuf;
use common::asm::{AsmInstruction, AsmOpcode};
-use crate::assembler::Symbol;
+use crate::assembler::{Symbol};
use crate::{expect_tt, expect_value};
-use super::{Token, error::AssembleError};
+use super::{error::AssembleError, Token};
pub struct AsmNode {
pub label: Option,
diff --git a/dsa/assembler/src/disassembler.rs b/dsa/assembler/src/disassembler.rs
deleted file mode 100644
index 457489a..0000000
--- a/dsa/assembler/src/disassembler.rs
+++ /dev/null
@@ -1,158 +0,0 @@
-use std::fs;
-use std::path::PathBuf;
-use std::io::{Cursor, Read, Seek, SeekFrom, Write};
-use std::fs::File;
-use binrw::{binrw, BinRead, binwrite, NullString, BinReaderExt, BinWriterExt, BinWrite};
-
-use common::prelude::Instruction;
-use crate::assembler::Symbol;
-
-pub fn disassemble(in_path: PathBuf, out_path: PathBuf) -> Result<(), String> {
-
- let Ok(content) = fs::read(in_path) else {
- return Err(String::new())
- };
-
- for (line_num, chunk) in content.chunks(4).enumerate() {
- let address = line_num * 4;
-
- let value = u32::from_le_bytes(*chunk.as_array().unwrap());
- println!("{:#?}", Instruction(value));
- }
- Ok(())
-}
-
-
-#[binrw]
-#[brw(magic = b"DSAX", little)]
-#[derive(Debug, Clone)]
-struct DseHeader {
- version: u16,
- flags: u16,
- entry_point: u32,
-
- symbol_table_offset: u32,
- symbol_table_size: u32,
-
- string_table_offset: u32,
- string_table_size: u32,
-
- data_offset: u32,
- data_size: u32,
-
- text_offset: u32,
- text_size: u32
-}
-
-#[binrw]
-#[brw(little)]
-#[derive(Debug, Clone)]
-struct SymbolEntry {
- name_offset: u32,
- value: u32,
- section: u8,
- binding: u8,
- _pad: u16
-}
-
-#[derive(Debug, Clone)]
-struct DseExecutable {
- header: DseHeader,
- symbols: Vec,
- string_table: Vec,
- data: Vec,
- text: Vec
-}
-
-impl DseExecutable {
- fn load(path: PathBuf) -> binrw::BinResult {
- let mut file = File::open(path).map_err(|e| binrw::Error::Io(e))?;
- Self::read(&mut file)
- }
-
- fn read(reader: &mut R) -> binrw::BinResult {
- let header = DseHeader::read(reader)?;
-
- reader.seek(SeekFrom::Start(header.symbol_table_offset as u64))?;
- let symbols: Vec = (0..header.symbol_table_size)
- .map(|_| SymbolEntry::read(reader))
- .collect::>()?;
-
- reader.seek(SeekFrom::Start(header.string_table_offset as u64))?;
- let mut string_table = vec![0u8; header.string_table_size as usize];
- reader.read_exact(&mut string_table).map_err(|e| binrw::Error::Io(e))?;
-
- reader.seek(SeekFrom::Start(header.data_offset as u64))?;
- let mut data = vec![0u8; header.data_size as usize];
- reader.read_exact(&mut data).map_err(|e| binrw::Error::Io(e))?;
-
- reader.seek(SeekFrom::Start(header.text_offset as u64))?;
- let text: Vec = (0..header.text_size)
- .map(|_| reader.read_le::())
- .collect::>()?;
-
- Ok(DseExecutable { header, symbols, string_table, data, text })
- }
-
- fn save(&self, path: PathBuf) -> binrw::BinResult<()> {
- let mut file = File::create(path)
- .map_err(|e| binrw::Error::Io(e))?;
- self.write(&mut file)
- }
-
- fn write(&self, writer: &mut W) -> binrw::BinResult<()> {
- self.header.write(writer)?;
-
- for symbol in &self.symbols {
- symbol.write(writer)?;
- }
-
- writer.write_all(&self.string_table)?;
- writer.write_all(&self.data)?;
-
- for word in &self.text {
- writer.write_le(word)?;
- }
-
- Ok(())
- }
-
- fn new(
- symbols: &[SymbolEntry],
- string_table: &[u8],
- data: &[u8],
- text: &[u32],
- entry_point: u32,
- ) -> DseExecutable {
- const HEADER_SIZE: u32 = 4 + 2 + 2 + 4 + 4*2 + 4*2 + 4*2 + 4*2; // adjust to actual packed size
-
- let symbol_table_offset = HEADER_SIZE;
- let symbol_table_size = symbols.len() as u32 * 8; // 4+4+1+1+2 padded = 8 bytes each
- let string_table_offset = symbol_table_offset + symbol_table_size;
- let data_offset = string_table_offset + string_table.len() as u32;
- let text_offset = data_offset + data.len() as u32;
-
- let header = DseHeader {
- version: 1,
- flags: 0,
- entry_point,
- symbol_table_offset,
- symbol_table_size: symbols.len() as u32,
- string_table_offset,
- string_table_size: string_table.len() as u32,
- data_offset,
- data_size: data.len() as u32,
- text_offset,
- text_size: text.len() as u32,
- };
-
- DseExecutable {
- header,
- symbols: symbols.to_vec(),
- string_table: string_table.to_vec(),
- data: data.to_vec(),
- text: text.to_vec(),
- }
- }
-}
-
diff --git a/dsa/assembler/src/main.rs b/dsa/assembler/src/main.rs
index 06f58eb..80bb7ba 100644
--- a/dsa/assembler/src/main.rs
+++ b/dsa/assembler/src/main.rs
@@ -1,5 +1,5 @@
use assembler::prelude::*;
-use clap::{Parser, arg, command};
+use clap::{Parser, arg};
use std::{fs, path::PathBuf};
#[derive(Parser, Debug, Clone)]
@@ -23,11 +23,4 @@ fn main() {
eprintln!("Failed to write to output file: {e}");
std::process::exit(1);
}
-
- // let input = fs::read_to_string("../../dsa_resources/framebuffer.dsa").unwrap();
- // let output = asm(&input).unwrap();
-
- // for token in output {
- // println!("{:?}", token);
- // }
}
diff --git a/dsa/common/Cargo.toml b/dsa/common/Cargo.toml
index c2431e4..e3b39c1 100644
--- a/dsa/common/Cargo.toml
+++ b/dsa/common/Cargo.toml
@@ -7,4 +7,5 @@ edition = "2024"
path = "src/lib.rs"
[dependencies]
+binrw = "0.15.1"
strum = { version = "0.28.0", features = ["derive"] }
diff --git a/dsa/common/src/formats/binary_dse.rs b/dsa/common/src/formats/binary_dse.rs
new file mode 100644
index 0000000..41ad4ea
--- /dev/null
+++ b/dsa/common/src/formats/binary_dse.rs
@@ -0,0 +1,264 @@
+
+use std::fs::File;
+use std::io::{Cursor, Read, Seek, SeekFrom, Write};
+use std::path::PathBuf;
+use binrw::{binrw, BinRead, binwrite, NullString, BinReaderExt, BinWriterExt, BinWrite};
+use std::fmt;
+use crate::prelude::Instruction;
+
+#[binrw]
+#[brw(magic = b"DSAX", little)]
+#[derive(Debug, Clone)]
+pub struct DseHeader {
+ version: u16,
+ flags: u16,
+ pub entry_point: u32,
+
+ symbol_table_offset: u32,
+ symbol_table_size: u32,
+
+ string_table_offset: u32,
+ string_table_size: u32,
+
+ data_offset: u32,
+ data_size: u32,
+
+ pub text_offset: u32,
+ text_size: u32
+}
+
+#[binrw]
+#[brw(little)]
+#[derive(Debug, Clone)]
+pub struct SymbolEntry {
+ pub name_offset: u32,
+ pub value: u32,
+ pub section: u8,
+ pub binding: u8,
+ pub _pad: u16
+}
+
+#[derive(Debug, Clone)]
+pub struct DseExecutable {
+ pub header: DseHeader,
+ pub symbols: Vec,
+ pub string_table: Vec,
+ pub data: Vec,
+ pub text: Vec
+}
+
+impl DseExecutable {
+ pub fn load(path: PathBuf) -> binrw::BinResult {
+ let mut file = File::open(path).map_err(|e| binrw::Error::Io(e))?;
+ Self::read(&mut file)
+ }
+
+ pub fn read(reader: &mut R) -> binrw::BinResult {
+ let header = DseHeader::read(reader)?;
+
+ reader.seek(SeekFrom::Start(header.symbol_table_offset as u64))?;
+ let symbols: Vec = (0..header.symbol_table_size)
+ .map(|_| SymbolEntry::read(reader))
+ .collect::>()?;
+
+ reader.seek(SeekFrom::Start(header.string_table_offset as u64))?;
+ let mut string_table = vec![0u8; header.string_table_size as usize];
+ reader.read_exact(&mut string_table).map_err(|e| binrw::Error::Io(e))?;
+
+ reader.seek(SeekFrom::Start(header.data_offset as u64))?;
+ let mut data = vec![0u8; header.data_size as usize];
+ reader.read_exact(&mut data).map_err(|e| binrw::Error::Io(e))?;
+
+ reader.seek(SeekFrom::Start(header.text_offset as u64))?;
+ let text: Vec = (0..header.text_size)
+ .map(|_| reader.read_le::())
+ .collect::>()?;
+
+ Ok(DseExecutable { header, symbols, string_table, data, text })
+ }
+
+ pub fn save(&self, path: PathBuf) -> binrw::BinResult<()> {
+ let mut file = File::create(path)
+ .map_err(|e| binrw::Error::Io(e))?;
+ self.write(&mut file)
+ }
+
+ pub fn write(&self, writer: &mut W) -> binrw::BinResult<()> {
+ self.header.write(writer)?;
+
+ for symbol in &self.symbols {
+ symbol.write(writer)?;
+ }
+
+ writer.write_all(&self.string_table)?;
+ writer.write_all(&self.data)?;
+
+ for word in &self.text {
+ writer.write_le(word)?;
+ }
+
+ Ok(())
+ }
+
+ pub fn new(
+ symbols: &[SymbolEntry],
+ string_table: &[u8],
+ data: &[u8],
+ text: &[u32],
+ entry_point: u32,
+ ) -> binrw::BinResult {
+ // Derive sizes from real serialization instead of hand-counted constants.
+ let header_size = {
+ let mut buf = Cursor::new(Vec::new());
+ // dummy header just to measure length; fields' values don't matter here
+ let dummy = DseHeader {
+ version: 0, flags: 0, entry_point: 0,
+ symbol_table_offset: 0, symbol_table_size: 0,
+ string_table_offset: 0, string_table_size: 0,
+ data_offset: 0, data_size: 0,
+ text_offset: 0, text_size: 0,
+ };
+ dummy.write(&mut buf)?;
+ buf.into_inner().len() as u32
+ };
+
+ let symbol_entry_size = if symbols.is_empty() {
+ // measure using a zeroed entry even if symbols is empty
+ let mut buf = Cursor::new(Vec::new());
+ SymbolEntry { name_offset: 0, value: 0, section: 0, binding: 0, _pad: 0 }
+ .write(&mut buf)?;
+ buf.into_inner().len() as u32
+ } else {
+ let mut buf = Cursor::new(Vec::new());
+ symbols[0].write(&mut buf)?;
+ buf.into_inner().len() as u32
+ };
+
+ let symbol_table_offset = header_size;
+ let symbol_table_bytes = symbols.len() as u32 * symbol_entry_size;
+ let string_table_offset = symbol_table_offset + symbol_table_bytes;
+ let data_offset = string_table_offset + string_table.len() as u32;
+ let text_offset = data_offset + data.len() as u32;
+
+ let header = DseHeader {
+ version: 1,
+ flags: 0,
+ entry_point,
+ symbol_table_offset,
+ symbol_table_size: symbols.len() as u32,
+ string_table_offset,
+ string_table_size: string_table.len() as u32,
+ data_offset,
+ data_size: data.len() as u32,
+ text_offset,
+ text_size: text.len() as u32,
+ };
+
+ Ok(DseExecutable {
+ header,
+ symbols: symbols.to_vec(),
+ string_table: string_table.to_vec(),
+ data: data.to_vec(),
+ text: text.to_vec(),
+ })
+ }
+
+ /// Produces the runtime memory image: TEXT followed immediately by DATA,
+ /// matching the exact layout `resolve_address` assumed when the assembler
+ /// resolved symbol addresses. This is NOT the same as the on-disk file
+ /// layout (header/symtab/strtab/data/text) — this is what actually needs
+ /// to end up in emulator memory.
+ pub fn to_memory_image(&self) -> Vec {
+ let mut image = Vec::with_capacity(self.text.len() * 4 + self.data.len());
+
+ for word in &self.text {
+ image.extend_from_slice(&word.to_le_bytes());
+ }
+ image.extend_from_slice(&self.data);
+
+ image
+ }
+
+ /// Runtime address where DATA begins, given TEXT is loaded at `text_base`.
+ /// Matches the assembler's `resolve_address` convention exactly.
+ pub fn data_base(&self, text_base: u32) -> u32 {
+ text_base + (self.text.len() as u32 * 4)
+ }
+
+ /// Absolute runtime entry point address, given TEXT is loaded at `text_base`.
+ /// `self.header.entry_point` is already an absolute address under the
+ /// assumption text_base == 0, so this just re-bases it if you're loading
+ /// somewhere other than address 0.
+ pub fn entry_point(&self, text_base: u32) -> u32 {
+ text_base + self.header.entry_point
+ }
+}
+
+// Display implementations for dumping binary contents
+impl fmt::Display for DseHeader {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "DseHeader {{ version: {}, flags: {}, entry_point: 0x{:08X}, symbol_table_offset: 0x{:08X}, symbol_table_size: {}, string_table_offset: 0x{:08X}, string_table_size: {}, data_offset: 0x{:08X}, data_size: {}, text_offset: 0x{:08X}, text_size: {} }}",
+ self.version,
+ self.flags,
+ self.entry_point,
+ self.symbol_table_offset,
+ self.symbol_table_size,
+ self.string_table_offset,
+ self.string_table_size,
+ self.data_offset,
+ self.data_size,
+ self.text_offset,
+ self.text_size)
+ }
+}
+
+impl fmt::Display for SymbolEntry {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "SymbolEntry {{ name_offset: 0x{:08X}, value: 0x{:08X}, section: {}, binding: {} }}",
+ self.name_offset,
+ self.value,
+ self.section,
+ self.binding)
+ }
+}
+
+impl fmt::Display for DseExecutable {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ // Header
+ writeln!(f, "{}", self.header)?;
+ // Symbols
+ writeln!(f, "Symbols:")?;
+ for s in &self.symbols {
+ writeln!(f, " {}", s)?;
+ }
+ // String table as hex dump
+ writeln!(f, "String Table ({} bytes):", self.string_table.len())?;
+ for chunk in self.string_table.chunks(16) {
+ write!(f, "{}", String::from_utf8_lossy(chunk))?;
+ // for byte in chunk { write!(f, "{:02X} ", byte)?; }
+ writeln!(f)?;
+ }
+ // Data section
+ writeln!(f, "Data ({} bytes):", self.data.len())?;
+ for chunk in self.data.chunks(16) {
+ write!(f, " ")?;
+ for byte in chunk { write!(f, "{:02X} ", byte)?; }
+ for byte in chunk { write!(f, "{} ", *byte as char)?; }
+ writeln!(f)?;
+ }
+ // Text section as Instructions
+ writeln!(f, "Text ({} words):", self.text.len())?;
+ for word in &self.text {
+ writeln!(f, " {:#010X} {:?}", word, Instruction(*word))?;
+ }
+ Ok(())
+ }
+}
+
+#[test]
+fn symbol_entry_size_is_12_bytes() {
+ let mut buf = Cursor::new(Vec::new());
+ SymbolEntry { name_offset: 0, value: 0, section: 0, binding: 0, _pad: 0 }
+ .write(&mut buf).unwrap();
+ assert_eq!(buf.into_inner().len(), 12);
+}
\ No newline at end of file
diff --git a/decomp2.txt b/dsa/common/src/formats/binary_dso.rs
similarity index 100%
rename from decomp2.txt
rename to dsa/common/src/formats/binary_dso.rs
diff --git a/dsa/common/src/formats/mod.rs b/dsa/common/src/formats/mod.rs
new file mode 100644
index 0000000..2c88e30
--- /dev/null
+++ b/dsa/common/src/formats/mod.rs
@@ -0,0 +1,2 @@
+pub mod binary_dse;
+pub mod binary_dso;
\ No newline at end of file
diff --git a/dsa/common/src/lib.rs b/dsa/common/src/lib.rs
index be900cf..6e0d694 100644
--- a/dsa/common/src/lib.rs
+++ b/dsa/common/src/lib.rs
@@ -1,5 +1,6 @@
pub mod asm;
pub mod isa;
+pub mod formats;
pub mod prelude {
pub use crate::isa::instructions::Instruction;
diff --git a/dsa/disassembler/Cargo.toml b/dsa/disassembler/Cargo.toml
new file mode 100644
index 0000000..af7dce3
--- /dev/null
+++ b/dsa/disassembler/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "disassembler"
+edition.workspace = true
+version.workspace = true
+authors.workspace = true
+
+[[bin]]
+name = "dsa-a"
+path = "src/main.rs"
+
+[lib]
+name = "disassembler"
+path = "src/lib.rs"
+
+[dependencies]
+clap = { version = "4.6.0", features = ["derive"] }
+common = { path = "../common" }
\ No newline at end of file
diff --git a/dsa/disassembler/src/internal.rs b/dsa/disassembler/src/internal.rs
new file mode 100644
index 0000000..cd986d8
--- /dev/null
+++ b/dsa/disassembler/src/internal.rs
@@ -0,0 +1,350 @@
+use std::collections::HashMap;
+use std::fmt;
+use common::formats::binary_dse::DseExecutable;
+use common::isa::instructions::Opcode;
+use common::prelude::{Instruction, Register};
+
+#[derive(Debug)]
+pub struct Disassembly {
+ pub symbols: Vec,
+ pub text_lines: Vec,
+ pub data_lines: Vec,
+}
+
+#[derive(Debug)]
+pub struct SymbolLine {
+ pub name: String,
+ pub address: u32,
+ pub section: SectionKind,
+ pub binding: BindingKind,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum SectionKind { Data, Text, Abs, Undef }
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum BindingKind { Local, Global, Weak }
+
+impl SectionKind {
+ fn from_raw(v: u8) -> Self {
+ match v { 1 => Self::Data, 2 => Self::Text, 0 => Self::Abs, _ => Self::Undef }
+ }
+}
+impl BindingKind {
+ fn from_raw(v: u8) -> Self {
+ match v { 1 => Self::Global, 2 => Self::Weak, _ => Self::Local }
+ }
+}
+
+pub fn disassemble(exe: &DseExecutable) -> Disassembly {
+ let symbols = build_symbol_lines(exe);
+
+ let mut text_labels: HashMap = HashMap::new();
+ let mut data_labels: HashMap = HashMap::new();
+ for sym in &symbols {
+ match sym.section {
+ SectionKind::Text => { text_labels.insert(sym.address, sym.name.clone()); }
+ SectionKind::Data => { data_labels.insert(sym.address, sym.name.clone()); }
+ _ => {}
+ }
+ }
+ // symbols can refer to either section by full resolved address (per your
+ // v1 loader convention: data lives right after text), so a single combined
+ // map is actually what address-resolution needs — keep both, but merge
+ // for lookups against full 32-bit addresses.
+ let mut all_labels = text_labels.clone();
+ all_labels.extend(data_labels.clone());
+
+ let text_lines = build_text_lines(&exe.text, &all_labels);
+ let data_lines = build_data_lines(&exe.data, &data_labels);
+
+ Disassembly { symbols, text_lines, data_lines }
+}
+
+fn build_symbol_lines(exe: &DseExecutable) -> Vec {
+ exe.symbols
+ .iter()
+ .map(|s| SymbolLine {
+ name: read_string(&exe.string_table, s.name_offset),
+ address: s.value,
+ section: SectionKind::from_raw(s.section),
+ binding: BindingKind::from_raw(s.binding),
+ })
+ .collect()
+}
+
+fn read_string(strtab: &[u8], offset: u32) -> String {
+ let start = offset as usize;
+ let end = strtab[start..].iter().position(|&b| b == 0).map(|p| start + p).unwrap_or(strtab.len());
+ String::from_utf8_lossy(&strtab[start..end]).into_owned()
+}
+
+/// Address a jump-like instruction actually targets, if statically known.
+/// Returns None when the jump is register-relative (addr reg != Zero) since
+/// that depends on runtime state and can't be resolved here.
+fn static_jump_target(addr_reg: Register, imm: u16) -> Option {
+ (addr_reg == Register::Zero).then_some(imm as u32)
+}
+
+fn build_text_lines(words: &[u32], labels: &HashMap) -> Vec {
+ let mut out = Vec::new();
+ let mut i = 0;
+
+ while i < words.len() {
+ let addr = 4 * i as u32;
+ if let Some(label) = labels.get(&addr) {
+ out.push(format!("{label}:"));
+ }
+
+ let instr = Instruction(words[i]);
+ let opcode = Opcode::from_u8(instr.opcode());
+
+ // Collapse Lli+Lui address-load pairs back into `lwi` (or a full
+ // ldx/stx pseudo-op if a matching mem instruction follows), mirroring
+ // what expand_ldx/expand_stx/expand_lwi originally expanded from.
+ if let Some(Opcode::Lli) = opcode {
+ if let Some(collapsed) = try_collapse_addr_load(words, i, labels) {
+ out.push(format!(" {}", collapsed.text));
+ i += collapsed.consumed;
+ continue;
+ }
+ }
+
+ out.push(format!(" {}", render_instruction(instr, opcode, labels)));
+ i += 1;
+ }
+
+ out
+}
+
+struct Collapsed {
+ text: String,
+ consumed: usize,
+}
+
+fn try_collapse_addr_load(
+ words: &[u32],
+ i: usize,
+ labels: &HashMap,
+) -> Option {
+ let lli = Instruction(words[i]);
+ let lui = Instruction(*words.get(i + 1)?);
+
+ if Opcode::from_u8(lui.opcode())? as u8 != Opcode::Lui as u8 {
+ return None;
+ }
+ if lui.dest_checked() != lli.dest_checked() {
+ return None;
+ }
+
+ let dest = lli.dest_checked();
+ let full_addr = (lli.imm16() as u32) | ((lui.imm16() as u32) << 16);
+ let addr_text = labels.get(&full_addr).cloned().unwrap_or_else(|| format!("{full_addr:#010x}"));
+
+ // Check whether a mem op immediately follows, referencing `dest` —
+ // that's the ldb/ldh/ldw/stb/sth/stw expansion pattern, not a bare lwi.
+ if let Some(&mem_word) = words.get(i + 2) {
+ let mem = Instruction(mem_word);
+ if let Some(mem_op) = Opcode::from_u8(mem.opcode()) {
+ let is_mem_op = matches!(
+ mem_op,
+ Opcode::Ldb | Opcode::Ldbs | Opcode::Ldh | Opcode::Ldhs | Opcode::Ldw
+ | Opcode::Stb | Opcode::Sth | Opcode::Stw
+ );
+ if is_mem_op && (mem.src1_checked() == dest || mem.dest_checked() == dest) {
+ let mnemonic = format!("{mem_op:?}").to_lowercase();
+ let other = if mem.src1_checked() == dest { mem.dest_checked() } else { mem.src1_checked() };
+ return Some(Collapsed {
+ text: format!("{mnemonic} {addr_text}, {other:?}, {:#06x}", mem.imm16()),
+ consumed: 3,
+ });
+ }
+ }
+ }
+
+ Some(Collapsed {
+ text: format!("lwi {addr_text}, {dest:?}"),
+ consumed: 2,
+ })
+}
+
+fn render_instruction(instr: Instruction, opcode: Option, labels: &HashMap) -> String {
+ let Some(op) = opcode else {
+ return format!("; INVALID OPCODE {:#04x} (word {:#010x})", instr.opcode(), instr.0);
+ };
+
+ let mnemonic = format!("{op:?}").to_lowercase();
+
+ match op {
+ Opcode::Nop | Opcode::Hlt | Opcode::Ret | Opcode::IRet => mnemonic,
+
+ Opcode::Push => format!("{mnemonic} {:?}", instr.src1_checked()),
+ Opcode::Pop => format!("{mnemonic} {:?}", instr.dest_checked()),
+
+ Opcode::Lli | Opcode::Lui => {
+ format!("{mnemonic} {:?}, {:#06x}", instr.dest_checked(), instr.imm16())
+ }
+
+ Opcode::Int => format!("{mnemonic} {:#06x}", instr.imm16()),
+
+ Opcode::Ldb | Opcode::Ldbs | Opcode::Ldh | Opcode::Ldhs | Opcode::Ldw
+ | Opcode::Stb | Opcode::Sth | Opcode::Stw | Opcode::Addi | Opcode::Subi => format!(
+ "{mnemonic} {:?}, {:?}, {:#06x}",
+ instr.src1_checked(), instr.dest_checked(), instr.imm16()
+ ),
+
+ Opcode::Jez | Opcode::Jnz => {
+ let addr_reg = instr.dest_checked();
+ let target = static_jump_target(addr_reg, instr.imm16())
+ .and_then(|a| labels.get(&a).cloned());
+ match target {
+ Some(label) => format!("{mnemonic} {:?}, {label}", instr.src1_checked()),
+ None if addr_reg == Register::Zero => {
+ format!("{mnemonic} {:?}, {:#06x}", instr.src1_checked(), instr.imm16())
+ }
+ None => format!(
+ "{mnemonic} {:?}, {:#06x}, {addr_reg:?}",
+ instr.src1_checked(), instr.imm16()
+ ),
+ }
+ }
+
+ Opcode::Jmp | Opcode::Call | Opcode::Jic | Opcode::Jnc => {
+ let addr_reg = instr.dest_checked();
+ let target = static_jump_target(addr_reg, instr.imm16())
+ .and_then(|a| labels.get(&a).cloned());
+ match target {
+ Some(label) => format!("{mnemonic} {label}"),
+ None if addr_reg == Register::Zero => format!("{mnemonic} {:#06x}", instr.imm16()),
+ None => format!("{mnemonic} {:#06x}, {addr_reg:?}", instr.imm16()),
+ }
+ }
+
+ Opcode::Mov | Opcode::Not => {
+ format!("{mnemonic} {:?}, {:?}", instr.src1_checked(), instr.dest_checked())
+ }
+
+ Opcode::CMov => format!(
+ "{mnemonic} {:?}, {:?}, {:?}",
+ instr.src1_checked(), instr.dest_checked(), instr.src2_checked()
+ ),
+
+ Opcode::Add | Opcode::Sub | Opcode::And | Opcode::Nand | Opcode::Or | Opcode::Nor
+ | Opcode::Xor | Opcode::Xnor | Opcode::Ieq | Opcode::Ine | Opcode::Ilt | Opcode::Ile
+ | Opcode::Igt | Opcode::Ige => format!(
+ "{mnemonic} {:?}, {:?}, {:?}",
+ instr.src1_checked(), instr.src2_checked(), instr.dest_checked()
+ ),
+
+ Opcode::Shl | Opcode::Shr => format!(
+ "{mnemonic} {:?}, {:?}, {:?}, {}",
+ instr.src1_checked(), instr.dest_checked(), instr.src2_checked(), instr.shamt()
+ ),
+ }
+}
+
+fn build_data_lines(data: &[u8], data_labels: &HashMap) -> Vec {
+ let mut out = Vec::new();
+ let mut i = 0;
+
+ while i < data.len() {
+ let addr = i as u32;
+ if let Some(label) = data_labels.get(&addr) {
+ out.push(format!("{label}:"));
+ }
+
+ // Try string detection only when this byte could actually start one.
+ if data[i] != 0 {
+ if let Some(end) = data[i..].iter().position(|&b| b == 0) {
+ let slice = &data[i..i + end];
+ if slice.iter().all(|&b| b.is_ascii_graphic() || b == b' ') {
+ out.push(format!(" db \"{}\"", String::from_utf8_lossy(slice).escape_default()));
+ i += end + 1; // skip the null terminator too
+ continue;
+ }
+ }
+ }
+
+ // Not a string start: consume only the run of zero bytes here,
+ // grouped into 4-byte words, stopping the instant a non-zero byte
+ // appears so we never swallow the start of the next string/value.
+ let run_end = data[i..]
+ .iter()
+ .position(|&b| b != 0)
+ .map(|p| i + p)
+ .unwrap_or(data.len());
+
+ if run_end == i {
+ // data[i] is non-zero but didn't form a printable/terminated
+ // string (e.g. binary constant) — dump one raw word.
+ let mut buf = [0u8; 4];
+ let take = (data.len() - i).min(4);
+ buf[..take].copy_from_slice(&data[i..i + take]);
+ out.push(format!(" dw {:#010x}", u32::from_le_bytes(buf)));
+ i += take;
+ } else {
+ let mut j = i;
+ while j < run_end {
+ let take = (run_end - j).min(4);
+ let mut buf = [0u8; 4];
+ buf[..take].copy_from_slice(&data[j..j + take]);
+ out.push(format!(" dw {:#010x}", u32::from_le_bytes(buf)));
+ j += take;
+ }
+ i = j;
+ }
+ }
+
+ out
+}
+
+impl fmt::Display for SectionKind {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::Data => write!(f, "DATA"),
+ Self::Text => write!(f, "TEXT"),
+ Self::Abs => write!(f, "ABS"),
+ Self::Undef => write!(f, "UNDEF"),
+ }
+ }
+}
+
+impl fmt::Display for BindingKind {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::Local => write!(f, "local"),
+ Self::Global => write!(f, "global"),
+ Self::Weak => write!(f, "weak"),
+ }
+ }
+}
+
+impl fmt::Display for SymbolLine {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "; {:<24} {:#010x} {:<5} {}",
+ self.name, self.address, self.section, self.binding
+ )
+ }
+}
+
+impl fmt::Display for Disassembly {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ writeln!(f, "; ==== symbols ====")?;
+ for sym in &self.symbols {
+ writeln!(f, "{sym}")?;
+ }
+
+ writeln!(f, "\n; ==== data ====")?;
+ for line in &self.data_lines {
+ writeln!(f, "{line}")?;
+ }
+
+ writeln!(f, "\n; ==== text ====")?;
+ for line in &self.text_lines {
+ writeln!(f, "{line}")?;
+ }
+
+ Ok(())
+ }
+}
\ No newline at end of file
diff --git a/dsa/disassembler/src/lib.rs b/dsa/disassembler/src/lib.rs
new file mode 100644
index 0000000..bf72fc0
--- /dev/null
+++ b/dsa/disassembler/src/lib.rs
@@ -0,0 +1,15 @@
+mod internal;
+
+use std::fs;
+use std::fs::File;
+use std::io::Write;
+use std::path::PathBuf;
+
+use std::collections::HashMap;
+use common::formats::binary_dse::DseExecutable;
+use common::isa::instructions::{Instruction, Opcode};
+use common::isa::register::Register;
+
+pub use internal::{
+ disassemble, Disassembly, BindingKind, SectionKind, SymbolLine
+};
diff --git a/dsa/disassembler/src/main.rs b/dsa/disassembler/src/main.rs
new file mode 100644
index 0000000..a526d13
--- /dev/null
+++ b/dsa/disassembler/src/main.rs
@@ -0,0 +1,27 @@
+use std::fs::File;
+use std::io::Write;
+use std::path::PathBuf;
+use clap::Parser;
+use disassembler::disassemble;
+use common::formats::binary_dse::DseExecutable;
+
+#[derive(Parser, Debug, Clone)]
+#[command(version, about, long_about = None)]
+struct Args {
+ #[arg(short = 'i')]
+ pub input_path: PathBuf,
+ #[arg(short = 'o')]
+ pub output_path: PathBuf,
+}
+
+fn main() {
+ let args = Args::parse();
+
+ let Ok(exec) = DseExecutable::load(args.input_path) else {
+ panic!("Failed to load the input file")
+ };
+
+ let result = disassemble(&exec);
+ File::create(args.output_path).unwrap()
+ .write(result.to_string().as_bytes()).unwrap();
+}
diff --git a/dsa/emulator/backend/Cargo.toml b/dsa/emulator/emulator_core/Cargo.toml
similarity index 85%
rename from dsa/emulator/backend/Cargo.toml
rename to dsa/emulator/emulator_core/Cargo.toml
index a19d96d..f701668 100644
--- a/dsa/emulator/backend/Cargo.toml
+++ b/dsa/emulator/emulator_core/Cargo.toml
@@ -1,11 +1,11 @@
[package]
-name = "emu_core"
+name = "emulator_core"
edition.workspace = true
version.workspace = true
authors.workspace = true
[lib]
-name = "emu_core"
+name = "emulator_core"
path = "src/lib.rs"
[dependencies]
diff --git a/dsa/emulator/backend/src/config/default/dsa.iomap.ron b/dsa/emulator/emulator_core/src/config/default/dsa.iomap.ron
similarity index 100%
rename from dsa/emulator/backend/src/config/default/dsa.iomap.ron
rename to dsa/emulator/emulator_core/src/config/default/dsa.iomap.ron
diff --git a/dsa/emulator/backend/src/config/default/dsa.mmap.ron b/dsa/emulator/emulator_core/src/config/default/dsa.mmap.ron
similarity index 100%
rename from dsa/emulator/backend/src/config/default/dsa.mmap.ron
rename to dsa/emulator/emulator_core/src/config/default/dsa.mmap.ron
diff --git a/dsa/emulator/backend/src/config/default/mod.rs b/dsa/emulator/emulator_core/src/config/default/mod.rs
similarity index 100%
rename from dsa/emulator/backend/src/config/default/mod.rs
rename to dsa/emulator/emulator_core/src/config/default/mod.rs
diff --git a/dsa/emulator/backend/src/config/mod.rs b/dsa/emulator/emulator_core/src/config/mod.rs
similarity index 100%
rename from dsa/emulator/backend/src/config/mod.rs
rename to dsa/emulator/emulator_core/src/config/mod.rs
diff --git a/dsa/emulator/backend/src/lib.rs b/dsa/emulator/emulator_core/src/lib.rs
similarity index 100%
rename from dsa/emulator/backend/src/lib.rs
rename to dsa/emulator/emulator_core/src/lib.rs
diff --git a/dsa/emulator/backend/src/memory/cache.rs b/dsa/emulator/emulator_core/src/memory/cache.rs
similarity index 100%
rename from dsa/emulator/backend/src/memory/cache.rs
rename to dsa/emulator/emulator_core/src/memory/cache.rs
diff --git a/dsa/emulator/backend/src/memory/mmu.rs b/dsa/emulator/emulator_core/src/memory/mmu.rs
similarity index 100%
rename from dsa/emulator/backend/src/memory/mmu.rs
rename to dsa/emulator/emulator_core/src/memory/mmu.rs
diff --git a/dsa/emulator/backend/src/memory/mod.rs b/dsa/emulator/emulator_core/src/memory/mod.rs
similarity index 100%
rename from dsa/emulator/backend/src/memory/mod.rs
rename to dsa/emulator/emulator_core/src/memory/mod.rs
diff --git a/dsa/emulator/backend/src/memory/ram.rs b/dsa/emulator/emulator_core/src/memory/ram.rs
similarity index 100%
rename from dsa/emulator/backend/src/memory/ram.rs
rename to dsa/emulator/emulator_core/src/memory/ram.rs
diff --git a/dsa/emulator/backend/src/memory/tlb.rs b/dsa/emulator/emulator_core/src/memory/tlb.rs
similarity index 100%
rename from dsa/emulator/backend/src/memory/tlb.rs
rename to dsa/emulator/emulator_core/src/memory/tlb.rs
diff --git a/dsa/emulator/backend/src/processor/interrupts.rs b/dsa/emulator/emulator_core/src/processor/interrupts.rs
similarity index 100%
rename from dsa/emulator/backend/src/processor/interrupts.rs
rename to dsa/emulator/emulator_core/src/processor/interrupts.rs
diff --git a/dsa/emulator/backend/src/processor/mod.rs b/dsa/emulator/emulator_core/src/processor/mod.rs
similarity index 100%
rename from dsa/emulator/backend/src/processor/mod.rs
rename to dsa/emulator/emulator_core/src/processor/mod.rs
diff --git a/dsa/emulator/backend/src/processor/processor.rs b/dsa/emulator/emulator_core/src/processor/processor.rs
similarity index 98%
rename from dsa/emulator/backend/src/processor/processor.rs
rename to dsa/emulator/emulator_core/src/processor/processor.rs
index f2c75b5..5ae070e 100644
--- a/dsa/emulator/backend/src/processor/processor.rs
+++ b/dsa/emulator/emulator_core/src/processor/processor.rs
@@ -164,6 +164,11 @@ impl Emulator {
self.update();
}
+ if let x = self.shared_state.goto.load(Ordering::Relaxed) && x != -1 {
+ *self.mut_reg(Register::Pcx) = x as u32;
+ self.shared_state.goto.store(-1, Ordering::Relaxed);
+ }
+
if self.shared_state.reseting.load(Ordering::Relaxed) {
self.internal_state.registers = [0; Register::COUNT as usize];
self.internal_state.clock = 0;
diff --git a/dsa/emulator/backend/src/processor/state.rs b/dsa/emulator/emulator_core/src/processor/state.rs
similarity index 87%
rename from dsa/emulator/backend/src/processor/state.rs
rename to dsa/emulator/emulator_core/src/processor/state.rs
index 839a15e..0cb4165 100644
--- a/dsa/emulator/backend/src/processor/state.rs
+++ b/dsa/emulator/emulator_core/src/processor/state.rs
@@ -1,5 +1,5 @@
use std::sync::{Arc, atomic::AtomicBool, mpsc};
-
+use std::sync::atomic::AtomicIsize;
use arc_swap::ArcSwap;
use crate::processor::processor::ProcessorSnapshot;
@@ -9,6 +9,7 @@ use super::interrupts::Interrupt;
pub struct SharedState {
pub proc: ArcSwap,
+ pub goto: AtomicIsize,
pub reseting: AtomicBool,
pub paused: AtomicBool,
pub update_req: AtomicBool,
@@ -21,6 +22,7 @@ impl SharedState {
reseting: AtomicBool::new(false),
proc: ArcSwap::new(Arc::new(ProcessorSnapshot::default())),
+ goto: AtomicIsize::new(-1),
paused: AtomicBool::new(true),
interrupt_queue: sender,
update_req: AtomicBool::new(false),
diff --git a/dsa/emulator/frontend/Cargo.toml b/dsa/emulator/emulator_ui/Cargo.toml
similarity index 74%
rename from dsa/emulator/frontend/Cargo.toml
rename to dsa/emulator/emulator_ui/Cargo.toml
index 7bbcac8..1c5c75d 100644
--- a/dsa/emulator/frontend/Cargo.toml
+++ b/dsa/emulator/emulator_ui/Cargo.toml
@@ -1,5 +1,5 @@
[package]
-name = "emulator"
+name = "emulator_ui"
version = "0.3.0"
edition.workspace = true
authors.workspace = true
@@ -13,7 +13,7 @@ name = "dsa"
path = "src/lib.rs"
[dev-dependencies]
-criterion = { version = "0.5.0", features = ["html_reports"] }
+criterion = { version = "0.8.2", features = ["html_reports"] }
[dependencies]
arc-swap = "1.8.2"
@@ -23,15 +23,15 @@ ron = "0.12.0"
serde = { version = "1.0.228", features = ["derive"] }
common = { path = "../../common" }
-egui = "0.33.3"
-eframe = "0.33.3"
-egui_tiles = "0.14.1"
-egui_code_editor = "0.2.21"
-egui_file = "0.25.0"
+egui = "0.35.0"
+eframe = "0.35.0"
+egui_tiles = "0.16.0"
+egui_code_editor = "0.3.7"
+egui_file = "0.27.0"
dirs = "6.0.0"
assembler = { path = "../../assembler" }
-egui_extras = "0.33.3"
-emu_core = { version = "0.3.0", path = "../backend" }
+egui_extras = "0.35.0"
+emulator_core = { version = "0.3.0", path = "../emulator_core" }
[features]
default = ["mainstore-prealloc"]
diff --git a/dsa/emulator/frontend/font/JetBrainsMonoNerdFontMono_Regular.ttf b/dsa/emulator/emulator_ui/font/JetBrainsMonoNerdFontMono_Regular.ttf
similarity index 100%
rename from dsa/emulator/frontend/font/JetBrainsMonoNerdFontMono_Regular.ttf
rename to dsa/emulator/emulator_ui/font/JetBrainsMonoNerdFontMono_Regular.ttf
diff --git a/dsa/emulator/frontend/src/args.rs b/dsa/emulator/emulator_ui/src/args.rs
similarity index 95%
rename from dsa/emulator/frontend/src/args.rs
rename to dsa/emulator/emulator_ui/src/args.rs
index a1f3f41..5fe0124 100644
--- a/dsa/emulator/frontend/src/args.rs
+++ b/dsa/emulator/emulator_ui/src/args.rs
@@ -2,7 +2,7 @@ use std::{fs, path::PathBuf};
use clap::Parser;
-use emu_core::config::{IoMap, IoMapping, MemoryMap};
+use emulator_core::config::{IoMap, IoMapping, MemoryMap};
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
diff --git a/dsa/emulator/frontend/src/lib.rs b/dsa/emulator/emulator_ui/src/lib.rs
similarity index 100%
rename from dsa/emulator/frontend/src/lib.rs
rename to dsa/emulator/emulator_ui/src/lib.rs
diff --git a/dsa/emulator/frontend/src/main.rs b/dsa/emulator/emulator_ui/src/main.rs
similarity index 95%
rename from dsa/emulator/frontend/src/main.rs
rename to dsa/emulator/emulator_ui/src/main.rs
index fec9a96..58184f1 100644
--- a/dsa/emulator/frontend/src/main.rs
+++ b/dsa/emulator/emulator_ui/src/main.rs
@@ -4,8 +4,10 @@ use common::prelude::Instruction;
use std::thread;
use dsa::args::DsaArgs;
use dsa::ui::run_app;
-use emu_core::memory::ram::Page;
-use emu_core::processor::processor::Emulator;
+use emulator_core::{
+ memory::ram::Page,
+ processor::processor::Emulator
+};
const STACK_SIZE: usize = 1024 * 1024 * 16;
diff --git a/dsa/emulator/frontend/src/ui/components/controller.rs b/dsa/emulator/emulator_ui/src/ui/components/controller.rs
similarity index 95%
rename from dsa/emulator/frontend/src/ui/components/controller.rs
rename to dsa/emulator/emulator_ui/src/ui/components/controller.rs
index 4a17b3e..0a9ba63 100644
--- a/dsa/emulator/frontend/src/ui/components/controller.rs
+++ b/dsa/emulator/emulator_ui/src/ui/components/controller.rs
@@ -2,8 +2,10 @@ use std::sync::{Arc, atomic::Ordering};
use super::Component;
use common::prelude::Register;
-use emu_core::memory::ram::MemoryBank;
-use emu_core::processor::state::SharedState;
+use emulator_core::{
+ memory::ram::MemoryBank,
+ processor::state::SharedState
+};
pub struct Controller {
state: Arc,
@@ -30,7 +32,7 @@ impl Component for Controller {
&mut self.visible
}
- fn ui(&mut self, ui: &mut egui::Ui, ctx: &egui::Context) {
+ fn ui(&mut self, ui: &mut egui::Ui) {
let state = self.state.proc.load();
let paused = self.state.paused.load(Ordering::Relaxed);
diff --git a/dsa/emulator/frontend/src/ui/components/display.rs b/dsa/emulator/emulator_ui/src/ui/components/display.rs
similarity index 95%
rename from dsa/emulator/frontend/src/ui/components/display.rs
rename to dsa/emulator/emulator_ui/src/ui/components/display.rs
index d303c95..e9360eb 100644
--- a/dsa/emulator/frontend/src/ui/components/display.rs
+++ b/dsa/emulator/emulator_ui/src/ui/components/display.rs
@@ -1,6 +1,8 @@
use egui::{Color32, FontId, Vec2};
-use emu_core::memory::PhysAddr;
-use emu_core::memory::ram::{MemoryBank, Page};
+use emulator_core::{
+ memory::PhysAddr,
+ memory::ram::{MemoryBank, Page}
+};
use super::Component;
pub struct Display {
@@ -72,7 +74,7 @@ impl Component for Display {
self.visible()
}
- fn ui(&mut self, ui: &mut egui::Ui, ctx: &egui::Context) {
+ fn ui(&mut self, ui: &mut egui::Ui) {
let display_w = self.width();
let display_h = self.height();
let data = self.read();
diff --git a/dsa/emulator/frontend/src/ui/components/editor/mod.rs b/dsa/emulator/emulator_ui/src/ui/components/editor/mod.rs
similarity index 75%
rename from dsa/emulator/frontend/src/ui/components/editor/mod.rs
rename to dsa/emulator/emulator_ui/src/ui/components/editor/mod.rs
index db5e7e4..e5da6cd 100644
--- a/dsa/emulator/frontend/src/ui/components/editor/mod.rs
+++ b/dsa/emulator/emulator_ui/src/ui/components/editor/mod.rs
@@ -1,7 +1,8 @@
use std::fmt::Write;
-use std::fs::{self, File};
-use std::sync::Arc;
+use std::fs::{self};
+use std::io::Cursor;
use std::sync::atomic::Ordering;
+use std::sync::Arc;
use std::{
ffi::OsStr,
path::{Path, PathBuf},
@@ -9,15 +10,18 @@ use std::{
pub mod syntax;
+use super::Component;
use assembler::prelude::Assembler;
+use common::formats::binary_dse::DseExecutable;
use common::prelude::Instruction;
use egui::{Align, Context, Key, Layout, Ui};
use egui_code_editor::{CodeEditor, ColorTheme, Completer, Syntax};
use egui_extras::{Column, TableBuilder};
use egui_file::FileDialog;
-use emu_core::memory::ram::{MemoryBank, Page};
-use emu_core::processor::state::SharedState;
-use super::Component;
+use emulator_core::{
+ memory::ram::{MemoryBank, Page},
+ processor::state::SharedState
+};
pub struct Editor {
state: Arc,
@@ -32,16 +36,13 @@ pub struct Editor {
// editor widget
editor: CodeEditor,
completer: Completer,
+ syntax: Syntax,
// output / loading
output: Output,
load_offset: u32,
offset_str: String,
- // cursor - currently unused
- cursor_col: usize,
- cursor_line: usize,
-
// file dialogs
open_file_dialog: Option,
save_file_dialog: Option,
@@ -61,7 +62,7 @@ impl Component for Editor {
&mut self.visible
}
- fn ui(&mut self, ui: &mut Ui, ctx: &Context) {
+ fn ui(&mut self, ui: &mut Ui) {
if self.buffer != self.text {
self.unsaved = true;
}
@@ -73,7 +74,7 @@ impl Component for Editor {
self.save();
}
- self.render_toolbar(ui, ctx);
+ self.render_toolbar(ui);
ui.add_space(4.0); // Add some spacing instead of just a separator
ui.separator();
@@ -85,15 +86,15 @@ impl Component for Editor {
Layout::left_to_right(Align::Min),
|ui| {
if self.show_output {
- egui::SidePanel::right("Editor Output").resizable(false).show_inside(ui, |ui| {
- self.output.ui(ui, ctx);
+ egui::Panel::right("Editor Output").resizable(false).show_inside(ui, |ui| {
+ self.output.ui(ui);
});
}
- self.render_editor(ui, ctx);
+ self.render_editor(ui);
},
);
- self.render_bottom_bar(ui, ctx);
+ self.render_bottom_bar(ui);
});
}
}
@@ -108,17 +109,15 @@ impl Editor {
text: String::new(),
buffer: String::new(),
completer: Completer::new_with_syntax(&Syntax::default()).with_user_words(),
+ syntax: Syntax::default(),
editor: CodeEditor::default()
.id_source("editor")
.with_fontsize(12.0)
.with_rows(0)
.with_theme(THEME)
- .with_syntax(Syntax::default())
.with_numlines(true),
output: Output::new(),
unsaved: true,
- cursor_col: 1,
- cursor_line: 1,
visible: false,
load_offset: 0,
offset_str: String::new(),
@@ -226,21 +225,20 @@ impl Editor {
self.open_file_dialog = Some(dialog);
}
- let syntax = match self.extension() {
+ self.syntax = match self.extension() {
"dsa" => syntax::dsa(),
"dsc" => syntax::dsc(),
"rs" => Syntax::rust(),
_ => Syntax::default(),
};
- self.completer = Completer::new_with_syntax(&syntax).with_user_words();
- self.editor = self.editor.clone().with_syntax(syntax);
+ self.completer = Completer::new_with_syntax(&self.syntax).with_user_words();
}
- fn handle_file_dialogs(&mut self, ctx: &egui::Context) {
+ fn handle_file_dialogs(&mut self, ui: &Ui) {
// Handle open dialog
if let Some(dialog) = &mut self.open_file_dialog
- && dialog.show(ctx).selected()
+ && dialog.show(ui).selected()
{
if let Some(file) = dialog.path() {
// check if the file is a binary file
@@ -284,7 +282,7 @@ impl Editor {
// Handle save dialog
if let Some(dialog) = &mut self.save_file_dialog
- && dialog.show(ctx).selected()
+ && dialog.show(ui).selected()
{
if let Some(file) = dialog.path() {
self.buffer = self.text.clone();
@@ -324,24 +322,19 @@ impl Editor {
}
}
- fn render_editor(&mut self, ui: &mut Ui, _ctx: &Context) {
+ fn render_editor(&mut self, ui: &mut Ui) {
let available_width = ui.available_width();
let mut editor = self.editor.clone().desired_width(available_width);
- editor.show_with_completer(ui, &mut self.text, &mut self.completer);
+ editor.show_with_completer(ui, &mut self.text, &self.syntax, &mut self.completer);
}
- fn render_bottom_bar(&self, ui: &mut Ui, _ctx: &Context) {
+ fn render_bottom_bar(&self, ui: &mut Ui) {
ui.horizontal(|ui| {
// error display
ui.label(
egui::RichText::new(self.error.clone().unwrap_or_default())
.color(egui::Color32::RED),
);
-
- // line and col
- ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
- ui.label(format!("Ln {}, Col {}", self.cursor_line, self.cursor_col));
- });
});
}
@@ -399,8 +392,8 @@ impl Editor {
}
}
- fn render_toolbar(&mut self, ui: &mut Ui, ctx: &Context) {
- self.handle_file_dialogs(ctx);
+ fn render_toolbar(&mut self, ui: &mut Ui) {
+ self.handle_file_dialogs(ui);
ui.horizontal(|ui| {
ui.label(format!("File type: {}", self.extension()));
@@ -443,13 +436,21 @@ impl Editor {
self.error = Some("Can't load program at invalid offset!".to_string());
}
- let program: Vec = Page::paginate(self.output.data()).collect();
+ let mut reader = Cursor::new(self.output.data().clone());
+ let Ok(executable) = DseExecutable::read(&mut reader) else {
+ self.error = Some("Failed to read program!".to_string());
+ return
+ };
+
+ let image: Vec = Page::paginate(&executable.to_memory_image()).collect();
self.state.reseting.store(true, Ordering::Relaxed);
+
self.memory.clear();
- for (i, page) in program.iter().enumerate() {
+ for (i, page) in image.iter().enumerate() {
self.memory.write_page(i as u32 * 4096, &page);
}
+ self.state.goto.store(executable.entry_point(0) as isize, Ordering::Relaxed);
self.state.reseting.store(false, Ordering::Relaxed);
}
@@ -463,7 +464,7 @@ impl Editor {
}
}
- ui.checkbox(&mut self.show_output, "Show Output")
+ ui.checkbox(&mut self.show_output, "Show Output");
});
}
}
@@ -488,18 +489,18 @@ fn parse_address(address: &str) -> Option {
pub const THEME: ColorTheme = ColorTheme {
name: "Theme",
dark: true,
- bg: "#1b1b1b",
- cursor: "#de5252", // fg4
- selection: "#28323B", // bg2
- comments: "#444444", // gray1
- functions: "#7CCCC7", // green1
- keywords: "#6C81E0", // red1
- literals: "#A3ABFF", // fg1
- numerics: "#8A46CF", // purple1
- punctuation: "#99C9C9", // orange1
- strs: "#618c84", // aqua1
- types: "#B8B9D4", // yellow1
- special: "#de5252", // blue1
+ bg: "1b1b1b",
+ cursor: "de5252", // fg4
+ selection: "28323B", // bg2
+ comments: "444444", // gray1
+ functions: "7CCCC7", // green1
+ keywords: "6C81E0", // red1
+ literals: "A3ABFF", // fg1
+ numerics: "8A46CF", // purple1
+ punctuation: "99C9C9", // orange1
+ strs: "618c84", // aqua1
+ types: "B8B9D4", // yellow1
+ special: "de5252", // blue1
};
struct Output {
@@ -532,7 +533,7 @@ impl Output {
&self.data
}
- fn ui(&mut self, ui: &mut Ui, _ctx: &Context) {
+ fn ui(&mut self, ui: &mut Ui) {
// Output area with synchronized scrolling
egui::ScrollArea::vertical()
.id_salt("output_scroll")
@@ -613,8 +614,9 @@ impl Output {
for (line_num, chunk) in self.data.chunks(4).enumerate() {
body.row(18.0, |mut row| {
let address = line_num * 4;
-
- let value = u32::from_le_bytes(*chunk.as_array().unwrap());
+ let mut buf = [0u8; 4];
+ buf[..chunk.len()].copy_from_slice(chunk);
+ let value = u32::from_le_bytes(buf);
// Address column
row.col(|ui| {
@@ -688,111 +690,6 @@ impl Output {
})
}
});
-
- // egui::Grid::new("output_grid")
- // .spacing([5.0, 2.0]) // Horizontal and vertical spacing
- // .num_columns(4)
- // .striped(false)
- // .show(ui, |ui| {
- // ui.label("Address");
-
- // if self.show_bytes {
- // ui.label("Bytes");
- // }
- // if self.show_words {
- // ui.label("Word");
- // }
- // if self.show_decimal {
- // ui.label("Decimal");
- // }
- // if self.show_ascii {
- // ui.label("Ascii");
- // }
- // if self.show_instruction {
- // ui.label("Hex");
- // }
- // ui.end_row();
-
- // // Process bytes in chunks of 4
- // for (line_num, chunk) in self.data.chunks(4).enumerate() {
- // let address = line_num * 4;
-
- // // Convert chunk to u32 (little-endian)
- // let mut bytes = [0u8; 4];
- // for (i, &byte) in chunk.iter().enumerate() {
- // if i < 4 {
- // bytes[i] = byte;
- // }
- // }
- // let value = u32::from_le_bytes(bytes);
-
- // // Address column
- // ui.with_layout(
- // egui::Layout::left_to_right(egui::Align::Center),
- // |ui| {
- // ui.set_min_width(80.0);
- // let style = ui.style_mut();
- // style.visuals.widgets.inactive.bg_fill =
- // egui::Color32::from_gray(30);
- // ui.label(
- // egui::RichText::new(format!("0x{address:04X}"))
- // .font(egui::FontId::monospace(12.0)),
- // );
- // },
- // );
-
- // // Individual bytes column
- // let byte_str = chunk
- // .iter()
- // .map(|b| format!("{b:02X}"))
- // .collect::>()
- // .join(" ");
-
- // if self.show_bytes {
- // ui.label(
- // egui::RichText::new(format!("{byte_str:<11}"))
- // .font(egui::FontId::monospace(12.0))
- // .color(egui::Color32::from_rgb(200, 200, 255)),
- // );
- // }
-
- // if self.show_words {
- // // Hex column
- // ui.label(
- // egui::RichText::new(format!("0x{value:08X}"))
- // .font(egui::FontId::monospace(12.0))
- // .color(egui::Color32::from_rgb(255, 100, 100)),
- // );
- // }
-
- // if self.show_decimal {
- // ui.label(
- // egui::RichText::new(format!("{value}"))
- // .font(egui::FontId::monospace(12.0))
- // .color(egui::Color32::from_rgb(100, 255, 100)),
- // );
- // }
-
- // if self.show_ascii {
- // let ascii = value.to_le_bytes();
- // ui.label(
- // egui::RichText::new(String::from_utf8_lossy(&ascii))
- // .font(egui::FontId::monospace(12.0))
- // .color(egui::Color32::from_rgb(100, 255, 255)),
- // );
- // }
-
- // if self.show_instruction {
- // ui.label(
- // egui::RichText::new(format!("{:?}", Instruction(value)))
- // .font(egui::FontId::monospace(12.0))
- // .color(egui::Color32::from_rgb(255, 100, 255)),
- // );
- // }
-
- // ui.end_row();
- // }
- // });
});
}
}
diff --git a/dsa/emulator/frontend/src/ui/components/editor/syntax/mod.rs b/dsa/emulator/emulator_ui/src/ui/components/editor/syntax/mod.rs
similarity index 91%
rename from dsa/emulator/frontend/src/ui/components/editor/syntax/mod.rs
rename to dsa/emulator/emulator_ui/src/ui/components/editor/syntax/mod.rs
index e388fd7..8583a7a 100644
--- a/dsa/emulator/frontend/src/ui/components/editor/syntax/mod.rs
+++ b/dsa/emulator/emulator_ui/src/ui/components/editor/syntax/mod.rs
@@ -1,9 +1,10 @@
use std::collections::BTreeSet;
-use egui_code_editor::Syntax;
+use egui_code_editor::{Patch, Syntax};
pub fn dsa() -> Syntax {
Syntax {
+ word_start: BTreeSet::new(),
quotes: BTreeSet::from(['"', '\'']),
language: "Assembly",
case_sensitive: false,
@@ -22,11 +23,13 @@ pub fn dsa() -> Syntax {
"RGC", "RGD", "RGE", "RGF", "ACC", "SPR", "BPR", "IDR", "MMR", "ZERO", "PCX", "STS",
"CIR",
]),
+ patch: Patch::default(),
}
}
pub fn dsc() -> Syntax {
Syntax {
+ word_start: BTreeSet::from(['_']),
quotes: BTreeSet::from(['"', '\'', '`']),
language: "Damn Simple Code",
case_sensitive: false,
@@ -44,5 +47,6 @@ pub fn dsc() -> Syntax {
",", ";", ".", ":", "=", "+", "-", "*", "/", "%", "&", "|", "^", "~", "!", "?", "<",
">", "<<", ">>", "==", "!=", "<=", ">=", "&&", "||",
]),
+ patch: Patch::default(),
}
}
diff --git a/dsa/emulator/frontend/src/ui/components/framebuffer.rs b/dsa/emulator/emulator_ui/src/ui/components/framebuffer.rs
similarity index 95%
rename from dsa/emulator/frontend/src/ui/components/framebuffer.rs
rename to dsa/emulator/emulator_ui/src/ui/components/framebuffer.rs
index c916a91..2536a02 100644
--- a/dsa/emulator/frontend/src/ui/components/framebuffer.rs
+++ b/dsa/emulator/emulator_ui/src/ui/components/framebuffer.rs
@@ -1,6 +1,8 @@
use egui::Vec2;
-use emu_core::memory::PhysAddr;
-use emu_core::memory::ram::{MemoryBank, Page};
+use emulator_core::{
+ memory::PhysAddr,
+ memory::ram::{MemoryBank, Page}
+};
use super::Component;
pub struct FrameBuffer {
@@ -86,12 +88,12 @@ impl Component for FrameBuffer {
&mut self.visible
}
- fn ui(&mut self, ui: &mut egui::Ui, ctx: &egui::Context) {
+ fn ui(&mut self, ui: &mut egui::Ui) {
let changed = self.changed();
// get or create the texture
let texture = self.texture.get_or_insert_with(|| {
- ctx.load_texture(
+ ui.load_texture(
"framebuffer",
egui::ColorImage {
size: [self.width, self.height],
diff --git a/dsa/emulator/emulator_ui/src/ui/components/memory.rs b/dsa/emulator/emulator_ui/src/ui/components/memory.rs
new file mode 100644
index 0000000..612cc29
--- /dev/null
+++ b/dsa/emulator/emulator_ui/src/ui/components/memory.rs
@@ -0,0 +1,264 @@
+use std::num::ParseIntError;
+use egui_extras::{Column, TableBuilder};
+use common::prelude::Instruction;
+use emulator_core::memory::ram::MemoryBank;
+use super::Component;
+
+pub struct MemoryInspector {
+ memory: MemoryBank,
+
+ view_size: u32,
+ view_addr: u32,
+ visible: bool,
+ addr_input: String,
+
+ // settings
+ show_bytes: bool,
+ show_words: bool,
+ show_ascii: bool,
+ show_instruction: bool,
+ show_decimal: bool,
+}
+
+impl MemoryInspector {
+ #[must_use]
+ pub fn new(memory: MemoryBank) -> Self {
+ Self {
+ memory,
+ view_size: 1024,
+ view_addr: 0,
+ visible: false,
+ addr_input: String::from("0x00"),
+
+ show_bytes: true,
+ show_words: true,
+ show_ascii: true,
+ show_instruction: true,
+ show_decimal: true,
+ }
+ }
+}
+
+impl Component for MemoryInspector {
+ fn title(&self) -> &'static str {
+ "Memory Inspector"
+ }
+
+ fn visible(&mut self) -> &mut bool {
+ &mut self.visible
+ }
+
+ fn ui(&mut self, ui: &mut egui::Ui) {
+ // Right column - Memory
+ // ui.vertical(|ui| {
+ // ui.add_space(10.0);
+ // });
+ // Memory table
+
+ egui::ScrollArea::vertical()
+ .auto_shrink([false; 2])
+ .id_salt("memory_inspector_scroll")
+ .show(ui, |ui| {
+
+ // ui.heading("Memory Inspector");
+ // ui.add_space(10.0);
+ //
+ // // Address input section
+ ui.horizontal(|ui| {
+ ui.label("Address:");
+
+ let address_response = ui.add(
+ egui::TextEdit::singleline(&mut self.addr_input)
+ .hint_text("0x1000 or 4096")
+ .desired_width(150.0),
+ );
+
+ ui.add_space(10.0);
+
+ // Search button
+ let search_clicked = ui.button("🔍 Search").clicked();
+
+ // Handle Enter key in text field
+ let enter_pressed =
+ address_response.lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter));
+
+ if search_clicked || enter_pressed {
+ if let Ok(new) = parse_address(&self.addr_input) {
+ if new % 4 == 0 {
+ self.view_addr = new;
+ } else {
+ println!("Address must be 4-byte aligned");
+ }
+ } else {
+ println!("Invalid address");
+ // state.error_log.push("Invalid address".to_string());
+ }
+ }
+
+ ui.label("(hex or decimal)");
+ });
+
+
+ ui.horizontal(|ui| {
+ ui.toggle_value(&mut self.show_bytes, "Bytes");
+ ui.toggle_value(&mut self.show_words, "Words");
+ ui.toggle_value(&mut self.show_decimal, "Decimal");
+ ui.toggle_value(&mut self.show_ascii, "Ascii");
+ ui.toggle_value(&mut self.show_instruction, "Instructions");
+ });
+
+ ui.separator();
+
+ let mut table = TableBuilder::new(ui)
+ .resizable(false) // makes all columns resizable at once
+ .column(Column::initial(75.0)); // addr
+
+ if self.show_bytes {
+ table = table.column(Column::initial(90.0));
+ }
+ if self.show_words {
+ table = table.column(Column::initial(75.0));
+ }
+ if self.show_decimal {
+ table = table.column(Column::initial(80.0));
+ }
+ if self.show_ascii {
+ table = table.column(Column::initial(50.0));
+ }
+ if self.show_instruction {
+ table = table.column(Column::initial(200.0).clip(true));
+ }
+
+ table
+ .header(20.0, |mut header| {
+ header.col(|ui| {
+ ui.label("Addr");
+ });
+ if self.show_bytes {
+ header.col(|ui| {
+ ui.label("Bytes");
+ });
+ }
+ if self.show_words {
+ header.col(|ui| {
+ ui.label("Word");
+ });
+ }
+ if self.show_decimal {
+ header.col(|ui| {
+ ui.label("Decimal");
+ });
+ }
+ if self.show_ascii {
+ header.col(|ui| {
+ ui.label("Ascii");
+ });
+ }
+ if self.show_instruction {
+ header.col(|ui| {
+ ui.label("Instruction");
+ });
+ }
+ })
+ .body(|mut body| {
+ // Process bytes in chunks of 4
+ for (line_num, value) in (0..self.view_size / 4)
+ .map(|i| (i, self.memory.read_word(self.view_addr + i * 4))) {
+ body.row(18.0, |mut row| {
+ let address = line_num * 4 * self.view_addr;
+
+ let chunk = value.to_le_bytes();
+
+ // Address column
+ row.col(|ui| {
+ ui.label(
+ egui::RichText::new(format!("0x{address:08X}"))
+ .font(egui::FontId::monospace(12.0)),
+ );
+ });
+
+ if self.show_bytes {
+ row.col(|ui| {
+ // Individual bytes column
+ ui.label(
+ egui::RichText::new(
+ chunk
+ .iter()
+ .map(|b| format!("{b:02X}"))
+ .collect::>()
+ .join(" "),
+ )
+ .font(egui::FontId::monospace(12.0))
+ .color(egui::Color32::from_rgb(200, 200, 255)),
+ );
+ });
+ }
+
+ if self.show_words {
+ row.col(|ui| {
+ // Hex column
+ ui.label(
+ egui::RichText::new(format!("0x{value:08X}"))
+ .font(egui::FontId::monospace(12.0))
+ .color(egui::Color32::from_rgb(255, 100, 100)),
+ );
+ });
+ }
+
+ if self.show_decimal {
+ row.col(|ui| {
+ ui.label(
+ egui::RichText::new(format!("{value}"))
+ .font(egui::FontId::monospace(12.0))
+ .color(egui::Color32::from_rgb(100, 255, 100)),
+ );
+ });
+ }
+
+ if self.show_ascii {
+ let ascii = value.to_le_bytes();
+ row.col(|ui| {
+ ui.label(
+ egui::RichText::new(String::from_utf8_lossy(&ascii))
+ .font(egui::FontId::monospace(12.0))
+ .color(egui::Color32::from_rgb(100, 255, 255)),
+ );
+ });
+ }
+
+ if self.show_instruction {
+ row.col(|ui| {
+ ui.label(
+ egui::RichText::new(format!(
+ "{:?}",
+ Instruction(value)
+ ))
+ .font(egui::FontId::monospace(12.0))
+ .color(egui::Color32::from_rgb(255, 100, 255)),
+ );
+ });
+ }
+ })
+ }
+ });
+ });
+
+ }
+}
+
+fn parse_address(address: &str) -> Result {
+ if let Some(hex_part) = address.strip_prefix("0x") {
+ return u32::from_str_radix(hex_part, 16);
+ }
+
+ if let Some(bin_part) = address.strip_prefix("0b") {
+ return u32::from_str_radix(bin_part, 2);
+ }
+
+ if let Some(oct_part) = address.strip_prefix("0o") {
+ return u32::from_str_radix(oct_part, 8);
+ }
+
+ address.parse::()
+}
+
diff --git a/dsa/emulator/frontend/src/ui/components/mod.rs b/dsa/emulator/emulator_ui/src/ui/components/mod.rs
similarity index 84%
rename from dsa/emulator/frontend/src/ui/components/mod.rs
rename to dsa/emulator/emulator_ui/src/ui/components/mod.rs
index 68ca1b2..a5b6c95 100644
--- a/dsa/emulator/frontend/src/ui/components/mod.rs
+++ b/dsa/emulator/emulator_ui/src/ui/components/mod.rs
@@ -13,5 +13,5 @@ pub trait Component {
fn visible(&mut self) -> &mut bool;
/// Draw the component's UI inside the provided `Ui`.
- fn ui(&mut self, ui: &mut egui::Ui, ctx: &egui::Context);
+ fn ui(&mut self, ui: &mut egui::Ui);
}
diff --git a/dsa/emulator/frontend/src/ui/components/registers.rs b/dsa/emulator/emulator_ui/src/ui/components/registers.rs
similarity index 92%
rename from dsa/emulator/frontend/src/ui/components/registers.rs
rename to dsa/emulator/emulator_ui/src/ui/components/registers.rs
index fe71745..067606e 100644
--- a/dsa/emulator/frontend/src/ui/components/registers.rs
+++ b/dsa/emulator/emulator_ui/src/ui/components/registers.rs
@@ -1,7 +1,7 @@
use std::{f32, sync::Arc};
use common::prelude::Register;
-use emu_core::processor::state::SharedState;
+use emulator_core::processor::state::SharedState;
use super::Component;
@@ -14,7 +14,6 @@ impl Registers {
fn section(
&mut self,
ui: &mut egui::Ui,
- ctx: &egui::Context,
registers: Vec<(Register, u32)>,
col_pairs: usize,
name: &str,
@@ -67,7 +66,7 @@ impl Component for Registers {
&mut self.visible
}
- fn ui(&mut self, ui: &mut egui::Ui, ctx: &egui::Context) {
+ fn ui(&mut self, ui: &mut egui::Ui) {
ui.set_min_width(200.0);
let state = self.state.proc.load();
@@ -87,7 +86,6 @@ impl Component for Registers {
.collect();
self.section(
ui,
- ctx,
gp_registers,
col_pairs,
"General Purpose Registers",
@@ -99,7 +97,7 @@ impl Component for Registers {
(Register::Spr, state.registers[Register::Spr as usize]),
(Register::Bpr, state.registers[Register::Bpr as usize]),
];
- self.section(ui, ctx, stack_registers, col_pairs, "Stack Registers");
+ self.section(ui, stack_registers, col_pairs, "Stack Registers");
ui.separator();
// ── Special Purpose ───────────────────────────────────────
@@ -111,7 +109,6 @@ impl Component for Registers {
];
self.section(
ui,
- ctx,
special_registers,
col_pairs,
"Special Purpose Registers",
@@ -124,7 +121,7 @@ impl Component for Registers {
(Register::Sts, state.registers[Register::Sts as usize]),
(Register::Cir, state.registers[Register::Cir as usize]),
];
- self.section(ui, ctx, system_registers, col_pairs, "System Registers");
+ self.section(ui, system_registers, col_pairs, "System Registers");
});
}
}
diff --git a/dsa/emulator/frontend/src/ui/components/serial.rs b/dsa/emulator/emulator_ui/src/ui/components/serial.rs
similarity index 93%
rename from dsa/emulator/frontend/src/ui/components/serial.rs
rename to dsa/emulator/emulator_ui/src/ui/components/serial.rs
index 6bffda7..f383b6b 100644
--- a/dsa/emulator/frontend/src/ui/components/serial.rs
+++ b/dsa/emulator/emulator_ui/src/ui/components/serial.rs
@@ -6,10 +6,16 @@ use std::{
mpsc::{Receiver, Sender},
},
};
-use emu_core::memory::PhysAddr;
-use emu_core::memory::ram::MemoryBank;
-use emu_core::processor::interrupts::Interrupt;
-use emu_core::processor::state::SharedState;
+use emulator_core::{
+ memory::{
+ PhysAddr,
+ ram::MemoryBank
+ },
+ processor::{
+ interrupts::Interrupt,
+ state::SharedState
+ }
+};
use super::Component;
/// ## SERIAL LAYOUT: (from the perspective of code inside the ui)
@@ -100,7 +106,7 @@ impl Component for Serial {
&mut self.visible
}
- fn ui(&mut self, ui: &mut egui::Ui, _ctx: &egui::Context) {
+ fn ui(&mut self, ui: &mut egui::Ui) {
self.update();
// Text field for input and a send button
diff --git a/dsa/emulator/frontend/src/ui/mod.rs b/dsa/emulator/emulator_ui/src/ui/mod.rs
similarity index 90%
rename from dsa/emulator/frontend/src/ui/mod.rs
rename to dsa/emulator/emulator_ui/src/ui/mod.rs
index b898655..aae8e8d 100644
--- a/dsa/emulator/frontend/src/ui/mod.rs
+++ b/dsa/emulator/emulator_ui/src/ui/mod.rs
@@ -8,9 +8,11 @@ use components::{
controller::Controller, display::Display, editor::Editor, framebuffer::FrameBuffer, memory::MemoryInspector,
registers::Registers, serial::Serial, Component,
};
-use emu_core::config::VERSION;
-use emu_core::memory::ram::MemoryBank;
-use emu_core::processor::state::SharedState;
+use emulator_core::{
+ config::VERSION,
+ memory::ram::MemoryBank,
+ processor::state::SharedState
+};
pub fn run_app(state: Arc, mem_handle: MemoryBank) -> eframe::Result<()> {
eframe::run_native(
@@ -21,12 +23,13 @@ pub fn run_app(state: Arc, mem_handle: MemoryBank) -> eframe::Resul
}
impl eframe::App for DsaUi {
- fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
+
+ fn ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) {
// request an update from ui every cycle
self.state.update_req.store(true, Ordering::Relaxed);
// title panel with dsa title
- egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
+ egui::containers::Panel::top("top_panel").show(ui, |ui| {
ui.with_layout(
egui::Layout::top_down_justified(egui::Align::Center)
.with_main_align(egui::Align::Min),
@@ -39,7 +42,7 @@ impl eframe::App for DsaUi {
});
// menu bar.
- egui::TopBottomPanel::top("menu_bar").show(ctx, |ui| {
+ egui::Panel::top("menu_bar").show(ui, |ui| {
egui::MenuBar::new().ui(ui, |ui| {
ui.menu_button("Panels", |ui| {
ui.set_max_width(300.0);
@@ -54,21 +57,21 @@ impl eframe::App for DsaUi {
});
});
- egui::CentralPanel::default().show(ctx, |ui| {
+ egui::CentralPanel::default().show(ui, |ui| {
for c in &mut self.components {
let mut visible = *c.visible();
if visible {
egui::Window::new(c.title())
.open(&mut visible)
- .show(ctx, |ui| {
- c.ui(ui, ctx);
+ .show(ui, |ui| {
+ c.ui(ui);
});
}
*c.visible() = visible;
}
});
- ctx.request_repaint_after(std::time::Duration::from_millis(16)); // ~60fps
+ ui.request_repaint_after(std::time::Duration::from_millis(16)); // ~60fps
}
}
diff --git a/dsa/emulator/frontend/src/ui/components/memory.rs b/dsa/emulator/frontend/src/ui/components/memory.rs
deleted file mode 100644
index 557f18d..0000000
--- a/dsa/emulator/frontend/src/ui/components/memory.rs
+++ /dev/null
@@ -1,138 +0,0 @@
-use std::num::ParseIntError;
-
-use common::prelude::Instruction;
-use emu_core::memory::ram::MemoryBank;
-use super::Component;
-
-pub struct MemoryInspector {
- memory: MemoryBank,
-
- view_size: u32,
- view_addr: u32,
- visible: bool,
- addr_input: String,
-}
-
-impl MemoryInspector {
- #[must_use]
- pub fn new(memory: MemoryBank) -> Self {
- Self {
- memory,
- view_size: 1024,
- view_addr: 0,
- visible: false,
- addr_input: String::from("0x00"),
- }
- }
-}
-
-impl Component for MemoryInspector {
- fn title(&self) -> &'static str {
- "Memory Inspector"
- }
-
- fn visible(&mut self) -> &mut bool {
- &mut self.visible
- }
-
- fn ui(&mut self, ui: &mut egui::Ui, ctx: &egui::Context) {
- // Right column - Memory
- ui.vertical(|ui| {
- ui.heading("Memory Inspector");
- ui.add_space(10.0);
-
- // Address input section
- ui.horizontal(|ui| {
- ui.label("Address:");
-
- let address_response = ui.add(
- egui::TextEdit::singleline(&mut self.addr_input)
- .hint_text("0x1000 or 4096")
- .desired_width(150.0),
- );
-
- ui.add_space(10.0);
-
- // Search button
- let search_clicked = ui.button("🔍 Search").clicked();
-
- // Handle Enter key in text field
- let enter_pressed =
- address_response.lost_focus() && ctx.input(|i| i.key_pressed(egui::Key::Enter));
-
- if search_clicked || enter_pressed {
- if let Ok(new) = parse_address(&self.addr_input) {
- if new % 4 == 0 {
- self.view_addr = new;
- } else {
- println!("Address must be 4-byte aligned");
- }
- } else {
- println!("Invalid address");
- // state.error_log.push("Invalid address".to_string());
- }
- }
-
- ui.label("(hex or decimal)");
- });
-
- ui.add_space(10.0);
-
- // Memory table
- egui::ScrollArea::vertical()
- .auto_shrink(true)
- .id_salt("memory_inspector_scroll")
- .show(ui, |ui| {
- egui::Grid::new("memory_grid")
- .spacing([12.0, 2.0])
- .min_col_width(5.0)
- .striped(true)
- .show(ui, |ui| {
- // Header
- ui.strong("Address");
-
- for i in 0..4 {
- ui.strong(format!("{i:X}"));
- }
-
- ui.strong("Decimal");
- ui.strong("Instruction");
-
- ui.end_row();
-
- // Memory data (8 bytes per row)
- for (offset, word) in (0..self.view_size / 4)
- .map(|i| i * 4)
- .map(|i| (i, self.memory.read_word(self.view_addr + i)))
- {
- let row_address = self.view_addr + offset;
- ui.monospace(format!("0x{row_address:08X} ({row_address})"));
- for byte in word.to_le_bytes() {
- ui.monospace(format!("{byte:02X}"));
- }
-
- ui.monospace(format!("{word}"));
- ui.monospace(format!("{:?}", Instruction(word)));
- ui.end_row();
- }
- });
- });
- });
- }
-}
-
-fn parse_address(address: &str) -> Result {
- if let Some(hex_part) = address.strip_prefix("0x") {
- return u32::from_str_radix(hex_part, 16);
- }
-
- if let Some(bin_part) = address.strip_prefix("0b") {
- return u32::from_str_radix(bin_part, 2);
- }
-
- if let Some(oct_part) = address.strip_prefix("0o") {
- return u32::from_str_radix(oct_part, 8);
- }
-
- address.parse::()
-}
diff --git a/dsa_resources/bf.dsa b/dsa_resources/bf.dsa
index 2d0272a..fcc2b35 100644
--- a/dsa_resources/bf.dsa
+++ b/dsa_resources/bf.dsa
@@ -37,11 +37,11 @@ db program: "++++++++++++++++++++++++++++++++++++++++++++
db error: "Invalid Instruction!"
dh counter: 0xFF
dw stack: 0x10000
-dw input: 0x30000
+dw input_addr: 0x30000
resb data: 1024
// set up a stack so we can call functions
-_init_stack:
+_init:
ldw stack, bpr
mov bpr, spr
@@ -162,7 +162,7 @@ output:
// ------------------------------------------
// read a byte into the current cell
input:
- ldw input, rg2
+ ldw input_addr, rg2
jmp loop_end
// ------------------------------------------
diff --git a/dsx/dsx_client/Cargo.toml b/dsx/dsx_client/Cargo.toml
new file mode 100644
index 0000000..1010d4b
--- /dev/null
+++ b/dsx/dsx_client/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "dsx_client"
+edition.workspace = true
+version.workspace = true
+authors.workspace = true
+
+[dependencies]
diff --git a/dsx/dsx_client/src/main.rs b/dsx/dsx_client/src/main.rs
new file mode 100644
index 0000000..e7a11a9
--- /dev/null
+++ b/dsx/dsx_client/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Hello, world!");
+}
diff --git a/dsx/dsx_common/Cargo.toml b/dsx/dsx_common/Cargo.toml
new file mode 100644
index 0000000..b67cd8f
--- /dev/null
+++ b/dsx/dsx_common/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "dsx_common"
+edition.workspace = true
+version.workspace = true
+authors.workspace = true
+
+[dependencies]
diff --git a/dsx/dsx_common/src/lib.rs b/dsx/dsx_common/src/lib.rs
new file mode 100644
index 0000000..b93cf3f
--- /dev/null
+++ b/dsx/dsx_common/src/lib.rs
@@ -0,0 +1,14 @@
+pub fn add(left: u64, right: u64) -> u64 {
+ left + right
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ let result = add(2, 2);
+ assert_eq!(result, 4);
+ }
+}
diff --git a/dsx/dsx_server/Cargo.toml b/dsx/dsx_server/Cargo.toml
new file mode 100644
index 0000000..4f821b7
--- /dev/null
+++ b/dsx/dsx_server/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "dsx_server"
+edition.workspace = true
+version.workspace = true
+authors.workspace = true
+
+[dependencies]
diff --git a/dsx/dsx_server/src/main.rs b/dsx/dsx_server/src/main.rs
new file mode 100644
index 0000000..e7a11a9
--- /dev/null
+++ b/dsx/dsx_server/src/main.rs
@@ -0,0 +1,3 @@
+fn main() {
+ println!("Hello, world!");
+}
diff --git a/e.txt b/e.txt
deleted file mode 100644
index 6f3a5d1..0000000
--- a/e.txt
+++ /dev/null
@@ -1,1072 +0,0 @@
-Building serialtest.dsa [/home/zxq5/Projects/HardwareDev/dsa2/dsa_resources/serialtest.dsa]
-Tokenising serialtest.dsa
-Parsing serialtest.dsa
-Resolving Deps serialtest.dsa
-Expanding Pseudo-ops serialtest.dsa
-Including serial.dsa
-Building serial.dsa [/home/zxq5/Projects/HardwareDev/dsa2/dsa_resources/serial.dsa]
-Tokenising serial.dsa
-Parsing serial.dsa
-Resolving Deps serial.dsa
-Expanding Pseudo-ops serial.dsa
-Including idt.dsa
-Building idt.dsa [/home/zxq5/Projects/HardwareDev/dsa2/dsa_resources/idt.dsa]
-Tokenising idt.dsa
-Parsing idt.dsa
-Resolving Deps idt.dsa
-Expanding Pseudo-ops idt.dsa
-Including print.dsa
-Building print.dsa [/home/zxq5/Projects/HardwareDev/dsa2/dsa_resources/print.dsa]
-Tokenising print.dsa
-Parsing print.dsa
-Resolving Deps print.dsa
-Expanding Pseudo-ops print.dsa
-Including serial.dsa
-Including print.dsa
-PRE LINK
-Node { symbol: None, opcode: Segment, tokens: [Immediate(3193829041)] }
-Node { symbol: None, opcode: Include, tokens: [Symbol(Symbol { name: "serial", module: Resolved(10077013596335634097) }), StringLit("./serial.dsa")] }
-Node { symbol: None, opcode: Include, tokens: [Symbol(Symbol { name: "idt", module: Resolved(10077013596335634097) }), StringLit("./idt.dsa")] }
-Node { symbol: None, opcode: Include, tokens: [Symbol(Symbol { name: "print", module: Resolved(10077013596335634097) }), StringLit("./print.dsa")] }
-Node { symbol: Some(Symbol { name: "stack", module: Resolved(10077013596335634097) }), opcode: Data, tokens: [Immediate(65536)] }
-Node { symbol: Some(Symbol { name: "_init", module: Resolved(10077013596335634097) }), opcode: Lli, tokens: [Symbol(Symbol { name: "stack", module: Resolved(10077013596335634097) }), Register(Bpr)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "stack", module: Resolved(10077013596335634097) }), Register(Bpr)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Bpr), Register(Bpr), Immediate(0)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Bpr), Register(Spr)] }
-Node { symbol: None, opcode: Call, tokens: [Symbol(Symbol { name: "setup_base", module: Resolved(2519286859380657757) })] }
-Node { symbol: None, opcode: Call, tokens: [Symbol(Symbol { name: "setup_io", module: Resolved(2519286859380657757) })] }
-Node { symbol: None, opcode: Call, tokens: [Symbol(Symbol { name: "serial_init", module: Resolved(12290222962602515901) })] }
-Node { symbol: Some(Symbol { name: "hello", module: Resolved(10077013596335634097) }), opcode: Data, tokens: [Immediate(1953719636)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1936026912)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1701273971)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1701322796)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(544173164)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1819438967)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1952784484)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1952784483)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(11875)] }
-Node { symbol: Some(Symbol { name: "main", module: Resolved(10077013596335634097) }), opcode: Lli, tokens: [Symbol(Symbol { name: "SERIAL_BUFFER", module: Resolved(12290222962602515901) }), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "SERIAL_BUFFER", module: Resolved(12290222962602515901) }), Register(Rg0)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Call, tokens: [Symbol(Symbol { name: "print", module: Resolved(11993558320162734964) })] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Zero)] }
-Node { symbol: None, opcode: Hlt, tokens: [] }
-Node { symbol: None, opcode: Jmp, tokens: [Symbol(Symbol { name: "main", module: Resolved(10077013596335634097) }), Register(Zero)] }
-Node { symbol: None, opcode: Segment, tokens: [Immediate(138780093)] }
-Node { symbol: Some(Symbol { name: "UART", module: Resolved(12290222962602515901) }), opcode: Data, tokens: [Immediate(262144)] }
-Node { symbol: Some(Symbol { name: "SERIAL_BUFFER", module: Resolved(12290222962602515901) }), opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: Some(Symbol { name: "SER_READ_PTR", module: Resolved(12290222962602515901) }), opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: Some(Symbol { name: "SER_WRITE_PTR", module: Resolved(12290222962602515901) }), opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: Some(Symbol { name: "serial_init", module: Resolved(12290222962602515901) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "SERIAL_BUFFER", module: Resolved(12290222962602515901) }), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "SERIAL_BUFFER", module: Resolved(12290222962602515901) }), Register(Rg0)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "SER_READ_PTR", module: Resolved(12290222962602515901) }), Register(Acc)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "SER_READ_PTR", module: Resolved(12290222962602515901) }), Register(Acc)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Rg0), Register(Acc), Immediate(0)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "SER_WRITE_PTR", module: Resolved(12290222962602515901) }), Register(Acc)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "SER_WRITE_PTR", module: Resolved(12290222962602515901) }), Register(Acc)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Rg0), Register(Acc), Immediate(0)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Bpr), Register(Spr)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Node { symbol: Some(Symbol { name: "serial_isr", module: Resolved(12290222962602515901) }), opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg2)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "UART", module: Resolved(12290222962602515901) }), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "UART", module: Resolved(12290222962602515901) }), Register(Rg0)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg0), Register(Rg0), Immediate(0)] }
-Node { symbol: None, opcode: Ldb, tokens: [Register(Rg0), Register(Rg1), Immediate(2)] }
-Node { symbol: None, opcode: Jez, tokens: [Register(Rg1), Symbol(Symbol { name: "_serial_isr_end", module: Resolved(12290222962602515901) }), Register(Zero)] }
-Node { symbol: None, opcode: Ldb, tokens: [Register(Rg0), Register(Rg1), Immediate(3)] }
-Node { symbol: None, opcode: Stb, tokens: [Register(Zero), Register(Rg0), Immediate(2)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "SER_WRITE_PTR", module: Resolved(12290222962602515901) }), Register(Rg2)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "SER_WRITE_PTR", module: Resolved(12290222962602515901) }), Register(Rg2)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg2), Register(Rg2), Immediate(0)] }
-Node { symbol: None, opcode: Stb, tokens: [Register(Rg1), Register(Rg2), Immediate(0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg2), Immediate(1), Register(Rg2)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "SERIAL_BUFFER", module: Resolved(12290222962602515901) }), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "SERIAL_BUFFER", module: Resolved(12290222962602515901) }), Register(Rg0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg0), Immediate(1024), Register(Rg1)] }
-Node { symbol: None, opcode: Ine, tokens: [Register(Rg1), Register(Rg2), Register(Rg1)] }
-Node { symbol: None, opcode: Jnz, tokens: [Register(Rg1), Symbol(Symbol { name: "_serial_isr_nowrap", module: Resolved(12290222962602515901) }), Register(Zero)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "SERIAL_BUFFER", module: Resolved(12290222962602515901) }), Register(Rg2)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "SERIAL_BUFFER", module: Resolved(12290222962602515901) }), Register(Rg2)] }
-Node { symbol: Some(Symbol { name: "_serial_isr_nowrap", module: Resolved(12290222962602515901) }), opcode: Lli, tokens: [Symbol(Symbol { name: "SER_WRITE_PTR", module: Resolved(12290222962602515901) }), Register(Acc)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "SER_WRITE_PTR", module: Resolved(12290222962602515901) }), Register(Acc)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Rg2), Register(Acc), Immediate(0)] }
-Node { symbol: Some(Symbol { name: "_serial_isr_end", module: Resolved(12290222962602515901) }), opcode: Pop, tokens: [Register(Rg2)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: IRet, tokens: [] }
-Node { symbol: None, opcode: Segment, tokens: [Immediate(78745181)] }
-Node { symbol: None, opcode: Include, tokens: [Symbol(Symbol { name: "print", module: Resolved(2519286859380657757) }), StringLit("./print.dsa")] }
-Node { symbol: None, opcode: Include, tokens: [Symbol(Symbol { name: "serial", module: Resolved(2519286859380657757) }), StringLit("./serial.dsa")] }
-Node { symbol: Some(Symbol { name: "idt", module: Resolved(2519286859380657757) }), opcode: Data, tokens: [Immediate(4294901760)] }
-Node { symbol: Some(Symbol { name: "setup_base", module: Resolved(2519286859380657757) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg2)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg3)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "idt", module: Resolved(2519286859380657757) }), Register(Idr)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "idt", module: Resolved(2519286859380657757) }), Register(Idr)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Idr), Register(Idr), Immediate(0)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "_guard", module: Resolved(2519286859380657757) }), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "_guard", module: Resolved(2519286859380657757) }), Register(Rg1)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Idr), Immediate(1024), Register(Rg2)] }
-Node { symbol: Some(Symbol { name: "_loop_start", module: Resolved(2519286859380657757) }), opcode: Stw, tokens: [Register(Rg1), Register(Rg2), Immediate(0)] }
-Node { symbol: None, opcode: SubI, tokens: [Register(Rg2), Immediate(4), Register(Rg2)] }
-Node { symbol: None, opcode: Ieq, tokens: [Register(Rg2), Register(Idr), Register(Rg3)] }
-Node { symbol: None, opcode: Jez, tokens: [Register(Rg3), Symbol(Symbol { name: "_loop_start", module: Resolved(2519286859380657757) }), Register(Zero)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "_handle_invalid_interrupt", module: Resolved(2519286859380657757) }), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "_handle_invalid_interrupt", module: Resolved(2519286859380657757) }), Register(Rg0)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Rg0), Register(Idr), Immediate(0)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg3)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg2)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Bpr), Register(Spr)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Node { symbol: Some(Symbol { name: "setup_io", module: Resolved(2519286859380657757) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "serial_isr", module: Resolved(12290222962602515901) }), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "serial_isr", module: Resolved(12290222962602515901) }), Register(Rg0)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Rg0), Register(Idr), Immediate(128)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Bpr), Register(Spr)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Node { symbol: Some(Symbol { name: "_invalid_int", module: Resolved(2519286859380657757) }), opcode: Data, tokens: [Immediate(1096040774)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1226848844)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1818326638)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1226859625)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1919251566)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1953527154)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(33)] }
-Node { symbol: Some(Symbol { name: "_handle_invalid_interrupt", module: Resolved(2519286859380657757) }), opcode: Call, tokens: [Symbol(Symbol { name: "reset", module: Resolved(11993558320162734964) })] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "_invalid_int", module: Resolved(2519286859380657757) }), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "_invalid_int", module: Resolved(2519286859380657757) }), Register(Rg0)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Call, tokens: [Symbol(Symbol { name: "print", module: Resolved(11993558320162734964) })] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Zero)] }
-Node { symbol: None, opcode: Hlt, tokens: [] }
-Node { symbol: Some(Symbol { name: "_err", module: Resolved(2519286859380657757) }), opcode: Data, tokens: [Immediate(1096040774)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1226848844)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1919251566)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1953527154)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1851877408)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1919249508)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1935767328)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1953459744)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1952805664)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(33)] }
-Node { symbol: Some(Symbol { name: "_guard", module: Resolved(2519286859380657757) }), opcode: Call, tokens: [Symbol(Symbol { name: "reset", module: Resolved(11993558320162734964) })] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "_err", module: Resolved(2519286859380657757) }), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "_err", module: Resolved(2519286859380657757) }), Register(Rg0)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Call, tokens: [Symbol(Symbol { name: "print", module: Resolved(11993558320162734964) })] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Zero)] }
-Node { symbol: None, opcode: Hlt, tokens: [] }
-Node { symbol: None, opcode: Segment, tokens: [Immediate(1648034676)] }
-Node { symbol: Some(Symbol { name: "display", module: Resolved(11993558320162734964) }), opcode: Data, tokens: [Immediate(131072)] }
-Node { symbol: Some(Symbol { name: "current", module: Resolved(11993558320162734964) }), opcode: Data, tokens: [Immediate(131072)] }
-Node { symbol: Some(Symbol { name: "print", module: Resolved(11993558320162734964) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg2)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg3)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Bpr), Register(Rg0), Immediate(8)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "current", module: Resolved(11993558320162734964) }), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "current", module: Resolved(11993558320162734964) }), Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg1), Register(Rg1), Immediate(0)] }
-Node { symbol: Some(Symbol { name: "_print_loop", module: Resolved(11993558320162734964) }), opcode: Ldb, tokens: [Register(Rg0), Register(Rg2), Immediate(0)] }
-Node { symbol: None, opcode: Ieq, tokens: [Register(Rg2), Register(Zero), Register(Rg3)] }
-Node { symbol: None, opcode: Jnz, tokens: [Register(Rg3), Symbol(Symbol { name: "_print_end", module: Resolved(11993558320162734964) }), Register(Zero)] }
-Node { symbol: None, opcode: Stb, tokens: [Register(Rg2), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg0), Immediate(1), Register(Rg0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg1), Immediate(1), Register(Rg1)] }
-Node { symbol: None, opcode: Jmp, tokens: [Symbol(Symbol { name: "_print_loop", module: Resolved(11993558320162734964) }), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "_print_end", module: Resolved(11993558320162734964) }), opcode: Lli, tokens: [Symbol(Symbol { name: "current", module: Resolved(11993558320162734964) }), Register(Acc)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "current", module: Resolved(11993558320162734964) }), Register(Acc)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Rg1), Register(Acc), Immediate(0)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg3)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg2)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Bpr), Register(Spr)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Node { symbol: Some(Symbol { name: "print_byte", module: Resolved(11993558320162734964) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Bpr), Register(Rg0), Immediate(8)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "current", module: Resolved(11993558320162734964) }), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "current", module: Resolved(11993558320162734964) }), Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg1), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: Stb, tokens: [Register(Rg0), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg1), Immediate(1), Register(Rg1)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Jmp, tokens: [Symbol(Symbol { name: "_end", module: Resolved(11993558320162734964) }), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "print_hex_byte", module: Resolved(11993558320162734964) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Bpr), Register(Rg0), Immediate(8)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "current", module: Resolved(11993558320162734964) }), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "current", module: Resolved(11993558320162734964) }), Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg1), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: Call, tokens: [Symbol(Symbol { name: "_print_hex_byte", module: Resolved(11993558320162734964) })] }
-Node { symbol: None, opcode: Jmp, tokens: [Symbol(Symbol { name: "_end", module: Resolved(11993558320162734964) }), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "_print_hex_byte", module: Resolved(11993558320162734964) }), opcode: Lli, tokens: [Immediate(15), Register(Rg2)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Shr, tokens: [Register(Rg0), Register(Zero), Immediate(4), Register(Rg0)] }
-Node { symbol: None, opcode: And, tokens: [Register(Rg0), Register(Rg2), Register(Rg0)] }
-Node { symbol: None, opcode: Call, tokens: [Symbol(Symbol { name: "_print_hex_nibble", module: Resolved(11993558320162734964) })] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: And, tokens: [Register(Rg0), Register(Rg2), Register(Rg0)] }
-Node { symbol: None, opcode: Call, tokens: [Symbol(Symbol { name: "_print_hex_nibble", module: Resolved(11993558320162734964) })] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Node { symbol: Some(Symbol { name: "_print_hex_nibble", module: Resolved(11993558320162734964) }), opcode: Lli, tokens: [Immediate(10), Register(Rg3)] }
-Node { symbol: None, opcode: Ilt, tokens: [Register(Rg0), Register(Rg3), Register(Rg4)] }
-Node { symbol: None, opcode: Jnz, tokens: [Register(Rg4), Symbol(Symbol { name: "_print_hex_nibble_number", module: Resolved(11993558320162734964) }), Register(Zero)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg0), Immediate(55), Register(Rg0)] }
-Node { symbol: None, opcode: Stb, tokens: [Register(Rg0), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg1), Immediate(1), Register(Rg1)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Node { symbol: Some(Symbol { name: "_print_hex_nibble_number", module: Resolved(11993558320162734964) }), opcode: AddI, tokens: [Register(Rg0), Immediate(48), Register(Rg0)] }
-Node { symbol: None, opcode: Stb, tokens: [Register(Rg0), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg1), Immediate(1), Register(Rg1)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Node { symbol: Some(Symbol { name: "print_whitespace", module: Resolved(11993558320162734964) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "current", module: Resolved(11993558320162734964) }), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "current", module: Resolved(11993558320162734964) }), Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg1), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(32), Register(Rg0)] }
-Node { symbol: None, opcode: Stb, tokens: [Register(Rg0), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg1), Immediate(1), Register(Rg1)] }
-Node { symbol: None, opcode: Jmp, tokens: [Symbol(Symbol { name: "_end", module: Resolved(11993558320162734964) }), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "newline", module: Resolved(11993558320162734964) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "display", module: Resolved(11993558320162734964) }), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "display", module: Resolved(11993558320162734964) }), Register(Rg0)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg0), Register(Rg0), Immediate(0)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "current", module: Resolved(11993558320162734964) }), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "current", module: Resolved(11993558320162734964) }), Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg1), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: Sub, tokens: [Register(Rg1), Register(Rg0), Register(Rg2)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(80), Register(Rg3)] }
-Node { symbol: Some(Symbol { name: "_newline_mod", module: Resolved(11993558320162734964) }), opcode: Ilt, tokens: [Register(Rg2), Register(Rg3), Register(Rg4)] }
-Node { symbol: None, opcode: Jnz, tokens: [Register(Rg4), Symbol(Symbol { name: "_newline_done", module: Resolved(11993558320162734964) }), Register(Zero)] }
-Node { symbol: None, opcode: Sub, tokens: [Register(Rg2), Register(Rg3), Register(Rg2)] }
-Node { symbol: None, opcode: Jmp, tokens: [Symbol(Symbol { name: "_newline_mod", module: Resolved(11993558320162734964) }), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "_newline_done", module: Resolved(11993558320162734964) }), opcode: Sub, tokens: [Register(Rg1), Register(Rg2), Register(Rg1)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg1), Immediate(80), Register(Rg1)] }
-Node { symbol: None, opcode: Jmp, tokens: [Symbol(Symbol { name: "_end", module: Resolved(11993558320162734964) }), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "reset", module: Resolved(11993558320162734964) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "display", module: Resolved(11993558320162734964) }), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "display", module: Resolved(11993558320162734964) }), Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg1), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: Jmp, tokens: [Symbol(Symbol { name: "_end", module: Resolved(11993558320162734964) }), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "clear", module: Resolved(11993558320162734964) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(500), Register(Rg0)] }
-Node { symbol: None, opcode: Lli, tokens: [Symbol(Symbol { name: "display", module: Resolved(11993558320162734964) }), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "display", module: Resolved(11993558320162734964) }), Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg1), Register(Rg1), Immediate(0)] }
-Node { symbol: Some(Symbol { name: "_clear_loop", module: Resolved(11993558320162734964) }), opcode: SubI, tokens: [Register(Rg0), Immediate(1), Register(Rg0)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Zero), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg1), Immediate(4), Register(Rg1)] }
-Node { symbol: None, opcode: Igt, tokens: [Register(Rg0), Register(Zero), Register(Rg4)] }
-Node { symbol: None, opcode: Jnz, tokens: [Register(Rg4), Symbol(Symbol { name: "_clear_loop", module: Resolved(11993558320162734964) }), Register(Zero)] }
-Node { symbol: None, opcode: Jmp, tokens: [Symbol(Symbol { name: "_end", module: Resolved(11993558320162734964) }), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "_end", module: Resolved(11993558320162734964) }), opcode: Lli, tokens: [Symbol(Symbol { name: "current", module: Resolved(11993558320162734964) }), Register(Acc)] }
-Node { symbol: None, opcode: Lui, tokens: [Symbol(Symbol { name: "current", module: Resolved(11993558320162734964) }), Register(Acc)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Rg1), Register(Acc), Immediate(0)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Bpr), Register(Spr)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Generating assembly output...
-Node { symbol: None, opcode: Jmp, tokens: [Immediate(1172), Register(Zero)] }
-Node { symbol: None, opcode: Segment, tokens: [Immediate(0)] }
-Node { symbol: Some(Symbol { name: "stack", module: Resolved(10077013596335634097) }), opcode: Data, tokens: [Immediate(65536)] }
-Node { symbol: Some(Symbol { name: "hello", module: Resolved(10077013596335634097) }), opcode: Data, tokens: [Immediate(1953719636)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1936026912)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1701273971)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1701322796)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(544173164)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1819438967)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1952784484)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1952784483)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(11875)] }
-Node { symbol: Some(Symbol { name: "UART", module: Resolved(12290222962602515901) }), opcode: Data, tokens: [Immediate(262144)] }
-Node { symbol: Some(Symbol { name: "SERIAL_BUFFER", module: Resolved(12290222962602515901) }), opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: Some(Symbol { name: "SER_READ_PTR", module: Resolved(12290222962602515901) }), opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: Some(Symbol { name: "SER_WRITE_PTR", module: Resolved(12290222962602515901) }), opcode: Data, tokens: [Immediate(0)] }
-Node { symbol: Some(Symbol { name: "idt", module: Resolved(2519286859380657757) }), opcode: Data, tokens: [Immediate(4294901760)] }
-Node { symbol: Some(Symbol { name: "_invalid_int", module: Resolved(2519286859380657757) }), opcode: Data, tokens: [Immediate(1096040774)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1226848844)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1818326638)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1226859625)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1919251566)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1953527154)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(33)] }
-Node { symbol: Some(Symbol { name: "_err", module: Resolved(2519286859380657757) }), opcode: Data, tokens: [Immediate(1096040774)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1226848844)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1919251566)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1953527154)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1851877408)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1919249508)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1935767328)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1953459744)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(1952805664)] }
-Node { symbol: None, opcode: Data, tokens: [Immediate(33)] }
-Node { symbol: Some(Symbol { name: "display", module: Resolved(11993558320162734964) }), opcode: Data, tokens: [Immediate(131072)] }
-Node { symbol: Some(Symbol { name: "current", module: Resolved(11993558320162734964) }), opcode: Data, tokens: [Immediate(131072)] }
-Node { symbol: None, opcode: Segment, tokens: [Immediate(3193829041)] }
-Node { symbol: Some(Symbol { name: "_init", module: Resolved(10077013596335634097) }), opcode: Lli, tokens: [Immediate(8), Register(Bpr)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(8), Register(Bpr)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Bpr), Register(Bpr), Immediate(0)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Bpr), Register(Spr)] }
-Node { symbol: None, opcode: Call, tokens: [Immediate(1404)] }
-Node { symbol: None, opcode: Call, tokens: [Immediate(1508)] }
-Node { symbol: None, opcode: Call, tokens: [Immediate(1232)] }
-Node { symbol: Some(Symbol { name: "main", module: Resolved(10077013596335634097) }), opcode: Lli, tokens: [Immediate(52), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(52), Register(Rg0)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Call, tokens: [Immediate(1608)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Zero)] }
-Node { symbol: None, opcode: Hlt, tokens: [] }
-Node { symbol: None, opcode: Jmp, tokens: [Immediate(1200), Register(Zero)] }
-Node { symbol: None, opcode: Segment, tokens: [Immediate(138780093)] }
-Node { symbol: Some(Symbol { name: "serial_init", module: Resolved(12290222962602515901) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(52), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(52), Register(Rg0)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1080), Register(Acc)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1080), Register(Acc)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Rg0), Register(Acc), Immediate(0)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1084), Register(Acc)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1084), Register(Acc)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Rg0), Register(Acc), Immediate(0)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Bpr), Register(Spr)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Node { symbol: Some(Symbol { name: "serial_isr", module: Resolved(12290222962602515901) }), opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg2)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(48), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(48), Register(Rg0)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg0), Register(Rg0), Immediate(0)] }
-Node { symbol: None, opcode: Ldb, tokens: [Register(Rg0), Register(Rg1), Immediate(2)] }
-Node { symbol: None, opcode: Jez, tokens: [Register(Rg1), Immediate(1384), Register(Zero)] }
-Node { symbol: None, opcode: Ldb, tokens: [Register(Rg0), Register(Rg1), Immediate(3)] }
-Node { symbol: None, opcode: Stb, tokens: [Register(Zero), Register(Rg0), Immediate(2)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1084), Register(Rg2)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1084), Register(Rg2)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg2), Register(Rg2), Immediate(0)] }
-Node { symbol: None, opcode: Stb, tokens: [Register(Rg1), Register(Rg2), Immediate(0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg2), Immediate(1), Register(Rg2)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(52), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(52), Register(Rg0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg0), Immediate(1024), Register(Rg1)] }
-Node { symbol: None, opcode: Ine, tokens: [Register(Rg1), Register(Rg2), Register(Rg1)] }
-Node { symbol: None, opcode: Jnz, tokens: [Register(Rg1), Immediate(1372), Register(Zero)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(52), Register(Rg2)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(52), Register(Rg2)] }
-Node { symbol: Some(Symbol { name: "_serial_isr_nowrap", module: Resolved(12290222962602515901) }), opcode: Lli, tokens: [Immediate(1084), Register(Acc)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1084), Register(Acc)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Rg2), Register(Acc), Immediate(0)] }
-Node { symbol: Some(Symbol { name: "_serial_isr_end", module: Resolved(12290222962602515901) }), opcode: Pop, tokens: [Register(Rg2)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: IRet, tokens: [] }
-Node { symbol: None, opcode: Segment, tokens: [Immediate(78745181)] }
-Node { symbol: Some(Symbol { name: "setup_base", module: Resolved(2519286859380657757) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg2)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg3)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1088), Register(Idr)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1088), Register(Idr)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Idr), Register(Idr), Immediate(0)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1576), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1576), Register(Rg1)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Idr), Immediate(1024), Register(Rg2)] }
-Node { symbol: Some(Symbol { name: "_loop_start", module: Resolved(2519286859380657757) }), opcode: Stw, tokens: [Register(Rg1), Register(Rg2), Immediate(0)] }
-Node { symbol: None, opcode: SubI, tokens: [Register(Rg2), Immediate(4), Register(Rg2)] }
-Node { symbol: None, opcode: Ieq, tokens: [Register(Rg2), Register(Idr), Register(Rg3)] }
-Node { symbol: None, opcode: Jez, tokens: [Register(Rg3), Immediate(1452), Register(Zero)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1548), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1548), Register(Rg0)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Rg0), Register(Idr), Immediate(0)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg3)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg2)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Bpr), Register(Spr)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Node { symbol: Some(Symbol { name: "setup_io", module: Resolved(2519286859380657757) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1284), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1284), Register(Rg0)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Rg0), Register(Idr), Immediate(128)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Bpr), Register(Spr)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Node { symbol: Some(Symbol { name: "_handle_invalid_interrupt", module: Resolved(2519286859380657757) }), opcode: Call, tokens: [Immediate(1984)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1092), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1092), Register(Rg0)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Call, tokens: [Immediate(1608)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Zero)] }
-Node { symbol: None, opcode: Hlt, tokens: [] }
-Node { symbol: Some(Symbol { name: "_guard", module: Resolved(2519286859380657757) }), opcode: Call, tokens: [Immediate(1984)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1120), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1120), Register(Rg0)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Call, tokens: [Immediate(1608)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Zero)] }
-Node { symbol: None, opcode: Hlt, tokens: [] }
-Node { symbol: None, opcode: Segment, tokens: [Immediate(1648034676)] }
-Node { symbol: Some(Symbol { name: "print", module: Resolved(11993558320162734964) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg2)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg3)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Bpr), Register(Rg0), Immediate(8)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1164), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1164), Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg1), Register(Rg1), Immediate(0)] }
-Node { symbol: Some(Symbol { name: "_print_loop", module: Resolved(11993558320162734964) }), opcode: Ldb, tokens: [Register(Rg0), Register(Rg2), Immediate(0)] }
-Node { symbol: None, opcode: Ieq, tokens: [Register(Rg2), Register(Zero), Register(Rg3)] }
-Node { symbol: None, opcode: Jnz, tokens: [Register(Rg3), Immediate(1676), Register(Zero)] }
-Node { symbol: None, opcode: Stb, tokens: [Register(Rg2), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg0), Immediate(1), Register(Rg0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg1), Immediate(1), Register(Rg1)] }
-Node { symbol: None, opcode: Jmp, tokens: [Immediate(1648), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "_print_end", module: Resolved(11993558320162734964) }), opcode: Lli, tokens: [Immediate(1164), Register(Acc)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1164), Register(Acc)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Rg1), Register(Acc), Immediate(0)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg3)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg2)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Bpr), Register(Spr)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Node { symbol: Some(Symbol { name: "print_byte", module: Resolved(11993558320162734964) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Bpr), Register(Rg0), Immediate(8)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1164), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1164), Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg1), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: Stb, tokens: [Register(Rg0), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg1), Immediate(1), Register(Rg1)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg1)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Jmp, tokens: [Immediate(2056), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "print_hex_byte", module: Resolved(11993558320162734964) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Bpr), Register(Rg0), Immediate(8)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1164), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1164), Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg1), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: Call, tokens: [Immediate(1800)] }
-Node { symbol: None, opcode: Jmp, tokens: [Immediate(2056), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "_print_hex_byte", module: Resolved(11993558320162734964) }), opcode: Lli, tokens: [Immediate(15), Register(Rg2)] }
-Node { symbol: None, opcode: Push, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: Shr, tokens: [Register(Rg0), Register(Zero), Immediate(4), Register(Rg0)] }
-Node { symbol: None, opcode: And, tokens: [Register(Rg0), Register(Rg2), Register(Rg0)] }
-Node { symbol: None, opcode: Call, tokens: [Immediate(1836)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Rg0)] }
-Node { symbol: None, opcode: And, tokens: [Register(Rg0), Register(Rg2), Register(Rg0)] }
-Node { symbol: None, opcode: Call, tokens: [Immediate(1836)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Node { symbol: Some(Symbol { name: "_print_hex_nibble", module: Resolved(11993558320162734964) }), opcode: Lli, tokens: [Immediate(10), Register(Rg3)] }
-Node { symbol: None, opcode: Ilt, tokens: [Register(Rg0), Register(Rg3), Register(Rg4)] }
-Node { symbol: None, opcode: Jnz, tokens: [Register(Rg4), Immediate(1864), Register(Zero)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg0), Immediate(55), Register(Rg0)] }
-Node { symbol: None, opcode: Stb, tokens: [Register(Rg0), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg1), Immediate(1), Register(Rg1)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Node { symbol: Some(Symbol { name: "_print_hex_nibble_number", module: Resolved(11993558320162734964) }), opcode: AddI, tokens: [Register(Rg0), Immediate(48), Register(Rg0)] }
-Node { symbol: None, opcode: Stb, tokens: [Register(Rg0), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg1), Immediate(1), Register(Rg1)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-Node { symbol: Some(Symbol { name: "print_whitespace", module: Resolved(11993558320162734964) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1164), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1164), Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg1), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(32), Register(Rg0)] }
-Node { symbol: None, opcode: Stb, tokens: [Register(Rg0), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg1), Immediate(1), Register(Rg1)] }
-Node { symbol: None, opcode: Jmp, tokens: [Immediate(2056), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "newline", module: Resolved(11993558320162734964) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1160), Register(Rg0)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1160), Register(Rg0)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg0), Register(Rg0), Immediate(0)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1164), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1164), Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg1), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: Sub, tokens: [Register(Rg1), Register(Rg0), Register(Rg2)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(80), Register(Rg3)] }
-Node { symbol: Some(Symbol { name: "_newline_mod", module: Resolved(11993558320162734964) }), opcode: Ilt, tokens: [Register(Rg2), Register(Rg3), Register(Rg4)] }
-Node { symbol: None, opcode: Jnz, tokens: [Register(Rg4), Immediate(1972), Register(Zero)] }
-Node { symbol: None, opcode: Sub, tokens: [Register(Rg2), Register(Rg3), Register(Rg2)] }
-Node { symbol: None, opcode: Jmp, tokens: [Immediate(1956), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "_newline_done", module: Resolved(11993558320162734964) }), opcode: Sub, tokens: [Register(Rg1), Register(Rg2), Register(Rg1)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg1), Immediate(80), Register(Rg1)] }
-Node { symbol: None, opcode: Jmp, tokens: [Immediate(2056), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "reset", module: Resolved(11993558320162734964) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1160), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1160), Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg1), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: Jmp, tokens: [Immediate(2056), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "clear", module: Resolved(11993558320162734964) }), opcode: Push, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Spr), Register(Bpr)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(500), Register(Rg0)] }
-Node { symbol: None, opcode: Lli, tokens: [Immediate(1160), Register(Rg1)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1160), Register(Rg1)] }
-Node { symbol: None, opcode: Ldw, tokens: [Register(Rg1), Register(Rg1), Immediate(0)] }
-Node { symbol: Some(Symbol { name: "_clear_loop", module: Resolved(11993558320162734964) }), opcode: SubI, tokens: [Register(Rg0), Immediate(1), Register(Rg0)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Zero), Register(Rg1), Immediate(0)] }
-Node { symbol: None, opcode: AddI, tokens: [Register(Rg1), Immediate(4), Register(Rg1)] }
-Node { symbol: None, opcode: Igt, tokens: [Register(Rg0), Register(Zero), Register(Rg4)] }
-Node { symbol: None, opcode: Jnz, tokens: [Register(Rg4), Immediate(2032), Register(Zero)] }
-Node { symbol: None, opcode: Jmp, tokens: [Immediate(2056), Register(Zero)] }
-Node { symbol: Some(Symbol { name: "_end", module: Resolved(11993558320162734964) }), opcode: Lli, tokens: [Immediate(1164), Register(Acc)] }
-Node { symbol: None, opcode: Lui, tokens: [Immediate(1164), Register(Acc)] }
-Node { symbol: None, opcode: Stw, tokens: [Register(Rg1), Register(Acc), Immediate(0)] }
-Node { symbol: None, opcode: Mov, tokens: [Register(Bpr), Register(Spr)] }
-Node { symbol: None, opcode: Pop, tokens: [Register(Bpr)] }
-Node { symbol: None, opcode: Ret, tokens: [] }
-[32mINFO:[0m Assembly Successful ✅
-Compilation Successful