misc: apply clippy lints
This commit is contained in:
+20
-23
@@ -1,11 +1,8 @@
|
|||||||
use common::{
|
use common::{args, prelude::*};
|
||||||
args, instructions,
|
|
||||||
prelude::{ITypeArgs, Instruction, Interrupt, RTypeArgs, Register},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AssembleError, expect_token, expect_type,
|
AssembleError, expect_token,
|
||||||
model::{Node, Opcode, Token, TokenType},
|
model::{Node, Opcode},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn codegen(nodes: Vec<Node>) -> Result<Vec<Instruction>, AssembleError> {
|
pub fn codegen(nodes: Vec<Node>) -> Result<Vec<Instruction>, AssembleError> {
|
||||||
@@ -25,12 +22,12 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
|
|||||||
match opcode {
|
match opcode {
|
||||||
Opcode::Nop => Ok(Instruction::Nop),
|
Opcode::Nop => Ok(Instruction::Nop),
|
||||||
Opcode::Mov => {
|
Opcode::Mov => {
|
||||||
let src = expect_token!(args.get(0).unwrap(), Register)?;
|
let src = expect_token!(args.first().unwrap(), Register)?;
|
||||||
let dest = expect_token!(args.get(1).unwrap(), Register)?;
|
let dest = expect_token!(args.get(1).unwrap(), Register)?;
|
||||||
Ok(Instruction::Mov(args!(R, sr1: src, dr: dest)))
|
Ok(Instruction::Mov(args!(R, sr1: src, dr: dest)))
|
||||||
}
|
}
|
||||||
Opcode::Movs => {
|
Opcode::Movs => {
|
||||||
let src = expect_token!(args.get(0).unwrap(), Register)?;
|
let src = expect_token!(args.first().unwrap(), Register)?;
|
||||||
let dest = expect_token!(args.get(1).unwrap(), Register)?;
|
let dest = expect_token!(args.get(1).unwrap(), Register)?;
|
||||||
Ok(Instruction::MovSigned(args!(R, sr1: src, dr: dest)))
|
Ok(Instruction::MovSigned(args!(R, sr1: src, dr: dest)))
|
||||||
}
|
}
|
||||||
@@ -42,7 +39,7 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
|
|||||||
| Opcode::Stb
|
| Opcode::Stb
|
||||||
| Opcode::Stw
|
| Opcode::Stw
|
||||||
| Opcode::Sth => {
|
| Opcode::Sth => {
|
||||||
let base = expect_token!(args.get(0).unwrap(), Register)?;
|
let base = expect_token!(args.first().unwrap(), Register)?;
|
||||||
let dest = expect_token!(args.get(1).unwrap(), Register)?;
|
let dest = expect_token!(args.get(1).unwrap(), Register)?;
|
||||||
let offset = expect_token!(args.get(2).unwrap(), Immediate)?;
|
let offset = expect_token!(args.get(2).unwrap(), Immediate)?;
|
||||||
let args = args!(I, immediate: offset as u16, r1: base, r2: dest);
|
let args = args!(I, immediate: offset as u16, r1: base, r2: dest);
|
||||||
@@ -60,14 +57,14 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Opcode::Lli => {
|
Opcode::Lli => {
|
||||||
let value = expect_token!(args.get(0).unwrap(), Immediate)?;
|
let value = expect_token!(args.first().unwrap(), Immediate)?;
|
||||||
let dest = expect_token!(args.get(1).unwrap(), Register)?;
|
let dest = expect_token!(args.get(1).unwrap(), Register)?;
|
||||||
let args = args!(I, immediate: value as u16, r1: dest);
|
let args = args!(I, immediate: value as u16, r1: dest);
|
||||||
|
|
||||||
Ok(Instruction::LoadLowerImmediate(args))
|
Ok(Instruction::LoadLowerImmediate(args))
|
||||||
}
|
}
|
||||||
Opcode::Lui => {
|
Opcode::Lui => {
|
||||||
let value = expect_token!(args.get(0).unwrap(), Immediate)? >> 16;
|
let value = expect_token!(args.first().unwrap(), Immediate)? >> 16;
|
||||||
let dest = expect_token!(args.get(1).unwrap(), Register)?;
|
let dest = expect_token!(args.get(1).unwrap(), Register)?;
|
||||||
let args = args!(I, immediate: value as u16, r1: dest);
|
let args = args!(I, immediate: value as u16, r1: dest);
|
||||||
|
|
||||||
@@ -80,7 +77,7 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
|
|||||||
| Opcode::Jge
|
| Opcode::Jge
|
||||||
| Opcode::Jlt
|
| Opcode::Jlt
|
||||||
| Opcode::Jle => {
|
| Opcode::Jle => {
|
||||||
let address = expect_token!(args.get(0).unwrap(), Immediate)?;
|
let address = expect_token!(args.first().unwrap(), Immediate)?;
|
||||||
let offset = expect_token!(args.get(1).unwrap(), Register)?;
|
let offset = expect_token!(args.get(1).unwrap(), Register)?;
|
||||||
let args = args!(I, immediate: address as u16, r1: offset);
|
let args = args!(I, immediate: address as u16, r1: offset);
|
||||||
|
|
||||||
@@ -96,25 +93,25 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Opcode::Cmp => {
|
Opcode::Cmp => {
|
||||||
let left = expect_token!(args.get(0).unwrap(), Register)?;
|
let left = expect_token!(args.first().unwrap(), Register)?;
|
||||||
let right = expect_token!(args.get(1).unwrap(), Register)?;
|
let right = expect_token!(args.get(1).unwrap(), Register)?;
|
||||||
Ok(Instruction::Compare(args!(R, sr1: left, sr2: right)))
|
Ok(Instruction::Compare(args!(R, sr1: left, sr2: right)))
|
||||||
}
|
}
|
||||||
Opcode::Inc => {
|
Opcode::Inc => {
|
||||||
let reg = expect_token!(args.get(0).unwrap(), Register)?;
|
let reg = expect_token!(args.first().unwrap(), Register)?;
|
||||||
Ok(Instruction::Increment(args!(R, sr1: reg)))
|
Ok(Instruction::Increment(args!(R, sr1: reg)))
|
||||||
}
|
}
|
||||||
Opcode::Dec => {
|
Opcode::Dec => {
|
||||||
let reg = expect_token!(args.get(0).unwrap(), Register)?;
|
let reg = expect_token!(args.first().unwrap(), Register)?;
|
||||||
Ok(Instruction::Decrement(args!(R, sr1: reg)))
|
Ok(Instruction::Decrement(args!(R, sr1: reg)))
|
||||||
}
|
}
|
||||||
Opcode::Shl => {
|
Opcode::Shl => {
|
||||||
let reg = expect_token!(args.get(0).unwrap(), Register)?;
|
let reg = expect_token!(args.first().unwrap(), Register)?;
|
||||||
let amount = expect_token!(args.get(1).unwrap(), Immediate)? as u8;
|
let amount = expect_token!(args.get(1).unwrap(), Immediate)? as u8;
|
||||||
Ok(Instruction::ShiftLeft(args!(R, sr1: reg, shamt: amount)))
|
Ok(Instruction::ShiftLeft(args!(R, sr1: reg, shamt: amount)))
|
||||||
}
|
}
|
||||||
Opcode::Shr => {
|
Opcode::Shr => {
|
||||||
let reg = expect_token!(args.get(0).unwrap(), Register)?;
|
let reg = expect_token!(args.first().unwrap(), Register)?;
|
||||||
let amount = expect_token!(args.get(1).unwrap(), Immediate)? as u8;
|
let amount = expect_token!(args.get(1).unwrap(), Immediate)? as u8;
|
||||||
Ok(Instruction::ShiftRight(args!(R, sr1: reg, shamt: amount)))
|
Ok(Instruction::ShiftRight(args!(R, sr1: reg, shamt: amount)))
|
||||||
}
|
}
|
||||||
@@ -126,7 +123,7 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
|
|||||||
| Opcode::Nand
|
| Opcode::Nand
|
||||||
| Opcode::Nor
|
| Opcode::Nor
|
||||||
| Opcode::Xnor => {
|
| Opcode::Xnor => {
|
||||||
let left = expect_token!(args.get(0).unwrap(), Register)?;
|
let left = expect_token!(args.first().unwrap(), Register)?;
|
||||||
let right = expect_token!(args.get(1).unwrap(), Register)?;
|
let right = expect_token!(args.get(1).unwrap(), Register)?;
|
||||||
let dest = expect_token!(args.get(2).unwrap(), Register)?;
|
let dest = expect_token!(args.get(2).unwrap(), Register)?;
|
||||||
let args = args!(R, sr1: left, sr2: right, dr: dest);
|
let args = args!(R, sr1: left, sr2: right, dr: dest);
|
||||||
@@ -144,7 +141,7 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Opcode::Iadd | Opcode::Isub => {
|
Opcode::Iadd | Opcode::Isub => {
|
||||||
let reg = expect_token!(args.get(0).unwrap(), Register)?;
|
let reg = expect_token!(args.first().unwrap(), Register)?;
|
||||||
let immediate = expect_token!(args.get(1).unwrap(), Immediate)? as u16;
|
let immediate = expect_token!(args.get(1).unwrap(), Immediate)? as u16;
|
||||||
let dest = expect_token!(args.get(2).unwrap(), Register)?;
|
let dest = expect_token!(args.get(2).unwrap(), Register)?;
|
||||||
let args = args!(I, immediate: immediate, r1: reg, r2: dest);
|
let args = args!(I, immediate: immediate, r1: reg, r2: dest);
|
||||||
@@ -156,22 +153,22 @@ fn build_instruction(node: Node) -> Result<Instruction, AssembleError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Opcode::Not => {
|
Opcode::Not => {
|
||||||
let reg = expect_token!(args.get(0).unwrap(), Register)?;
|
let reg = expect_token!(args.first().unwrap(), Register)?;
|
||||||
let dest = expect_token!(args.get(1).unwrap(), Register)?;
|
let dest = expect_token!(args.get(1).unwrap(), Register)?;
|
||||||
Ok(Instruction::Not(args!(R, sr1: reg, dr: dest)))
|
Ok(Instruction::Not(args!(R, sr1: reg, dr: dest)))
|
||||||
}
|
}
|
||||||
Opcode::Int => {
|
Opcode::Int => {
|
||||||
let code = expect_token!(args.get(0).unwrap(), Immediate)? as u8;
|
let code = expect_token!(args.first().unwrap(), Immediate)? as u8;
|
||||||
Ok(Instruction::Interrupt(Interrupt::Software(code)))
|
Ok(Instruction::Interrupt(Interrupt::Software(code)))
|
||||||
}
|
}
|
||||||
Opcode::Irt => Ok(Instruction::IntReturn),
|
Opcode::Irt => Ok(Instruction::IntReturn),
|
||||||
Opcode::Hlt => Ok(Instruction::Halt),
|
Opcode::Hlt => Ok(Instruction::Halt),
|
||||||
Opcode::Data => {
|
Opcode::Data => {
|
||||||
let immediate = expect_token!(args.get(0).unwrap(), Immediate)?;
|
let immediate = expect_token!(args.first().unwrap(), Immediate)?;
|
||||||
Ok(Instruction::Data(immediate))
|
Ok(Instruction::Data(immediate))
|
||||||
}
|
}
|
||||||
Opcode::Segment => {
|
Opcode::Segment => {
|
||||||
let immediate = expect_token!(args.get(0).unwrap(), Immediate)?;
|
let immediate = expect_token!(args.first().unwrap(), Immediate)?;
|
||||||
Ok(Instruction::Segment(immediate))
|
Ok(Instruction::Segment(immediate))
|
||||||
}
|
}
|
||||||
Opcode::Db
|
Opcode::Db
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use common::prelude::Register;
|
use common::prelude::Register;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AssembleError, dsa, expect_token, expect_type,
|
AssembleError, expect_token, expect_type,
|
||||||
model::{Node, Opcode, Token, TokenType},
|
model::{Node, Opcode, Token},
|
||||||
node,
|
node,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ pub fn expand_pseudo_ops(
|
|||||||
let mut result = Vec::<Node>::with_capacity(nodes.len());
|
let mut result = Vec::<Node>::with_capacity(nodes.len());
|
||||||
|
|
||||||
for node in nodes.iter_mut() {
|
for node in nodes.iter_mut() {
|
||||||
if let Err(_) = try_expand(node.clone(), &mut result, module) {
|
if try_expand(node.clone(), &mut result, module).is_err() {
|
||||||
result.push(node.clone());
|
result.push(node.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,9 +22,9 @@ pub fn expand_pseudo_ops(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn try_expand(
|
fn try_expand(
|
||||||
mut node: Node,
|
node: Node,
|
||||||
result: &mut Vec<Node>,
|
result: &mut Vec<Node>,
|
||||||
module: u64,
|
_module: u64,
|
||||||
) -> Result<(), AssembleError> {
|
) -> Result<(), AssembleError> {
|
||||||
match node.opcode() {
|
match node.opcode() {
|
||||||
Opcode::Push => expand_push(node.clone(), result)?,
|
Opcode::Push => expand_push(node.clone(), result)?,
|
||||||
@@ -176,7 +176,7 @@ fn expand_dx(current: Node, nodes: &mut Vec<Node>) -> Result<(), AssembleError>
|
|||||||
let mut buffer = vec![];
|
let mut buffer = vec![];
|
||||||
|
|
||||||
let mut args = current.args();
|
let mut args = current.args();
|
||||||
let label = args.remove(0);
|
let _label = args.remove(0);
|
||||||
|
|
||||||
for word in process_dx_data(args, size)? {
|
for word in process_dx_data(args, size)? {
|
||||||
buffer.push(node!(None, Opcode::Data, Token::Immediate(word)));
|
buffer.push(node!(None, Opcode::Data, Token::Immediate(word)));
|
||||||
|
|||||||
+29
-32
@@ -6,7 +6,7 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use common::prelude::Instruction;
|
use common::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::codegen,
|
codegen::codegen,
|
||||||
@@ -38,7 +38,7 @@ pub fn assemble(src: &Path) -> Result<Vec<Instruction>, AssembleError> {
|
|||||||
|
|
||||||
let instructions = codegen(nodes)?;
|
let instructions = codegen(nodes)?;
|
||||||
for inst in instructions.iter() {
|
for inst in instructions.iter() {
|
||||||
println!("{}", inst);
|
println!("{inst}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(instructions)
|
Ok(instructions)
|
||||||
@@ -87,7 +87,7 @@ fn prepare_dependency(
|
|||||||
);
|
);
|
||||||
|
|
||||||
for n in nodes.iter() {
|
for n in nodes.iter() {
|
||||||
println!("{}", n);
|
println!("{n}");
|
||||||
}
|
}
|
||||||
|
|
||||||
program.add_module(nodes);
|
program.add_module(nodes);
|
||||||
@@ -161,86 +161,83 @@ fn log(message: &str) {
|
|||||||
|
|
||||||
// create a macro that lexes and parses the input string into Nodes
|
// create a macro that lexes and parses the input string into Nodes
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[macro_use]
|
|
||||||
macro_rules! dsa {
|
macro_rules! dsa {
|
||||||
// Version with formatting arguments
|
// Version with formatting arguments
|
||||||
($hash:expr, $input:expr, $($args:expr),+) => {{
|
($hash:expr, $input:expr, $($args:expr),+) => {{
|
||||||
let input = format!($input, $($args),+);
|
let input = format!($input, $($args),+);
|
||||||
let tokens = crate::lexer::lexer(input, $hash)?;
|
let tokens = $crate::lexer::lexer(input, $hash)?;
|
||||||
let parsed = crate::parser::Parser::parse_nodes(tokens)?;
|
let parsed = $crate::parser::Parser::parse_nodes(tokens)?;
|
||||||
parsed
|
parsed
|
||||||
}};
|
}};
|
||||||
// Version without formatting
|
// Version without formatting
|
||||||
($hash:expr, $input:expr) => {{
|
($hash:expr, $input:expr) => {{
|
||||||
let input = String::from($input);
|
let input = String::from($input);
|
||||||
let tokens = crate::lexer::lexer(input, $hash)?;
|
let tokens = $crate::lexer::lexer(input, $hash)?;
|
||||||
let parsed = crate::parser::Parser::parse_nodes(tokens)?;
|
let parsed = $crate::parser::Parser::parse_nodes(tokens)?;
|
||||||
parsed
|
parsed
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[macro_use]
|
|
||||||
macro_rules! expect_token {
|
macro_rules! expect_token {
|
||||||
($token:expr, Symbol) => {
|
($token:expr, Symbol) => {
|
||||||
match $token {
|
match $token {
|
||||||
Token::Symbol(value) => Ok(value.clone()),
|
$crate::model::Token::Symbol(value) => Ok(value.clone()),
|
||||||
other => Err(AssembleError::UnexpectedToken(
|
other => Err($crate::AssembleError::UnexpectedToken(
|
||||||
other.clone(),
|
other.clone(),
|
||||||
TokenType::Symbol,
|
$crate::model::TokenType::Symbol,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($token:expr, Register) => {
|
($token:expr, Register) => {
|
||||||
match $token {
|
match $token {
|
||||||
Token::Register(value) => Ok(value.clone()),
|
$crate::model::Token::Register(value) => Ok(value.clone()),
|
||||||
other => Err(AssembleError::UnexpectedToken(
|
other => Err($crate::AssembleError::UnexpectedToken(
|
||||||
other.clone(),
|
other.clone(),
|
||||||
TokenType::Register,
|
$crate::model::TokenType::Register,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($token:expr, Immediate) => {
|
($token:expr, Immediate) => {
|
||||||
match $token {
|
match $token {
|
||||||
Token::Immediate(value) => Ok(value.clone()),
|
$crate::model::Token::Immediate(value) => Ok(value.clone()),
|
||||||
other => Err(AssembleError::UnexpectedToken(
|
other => Err($crate::AssembleError::UnexpectedToken(
|
||||||
other.clone(),
|
other.clone(),
|
||||||
TokenType::Immediate,
|
$crate::model::TokenType::Immediate,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($token:expr, StringLit) => {
|
($token:expr, StringLit) => {
|
||||||
match $token {
|
match $token {
|
||||||
Token::StringLit(value) => Ok(value.clone()),
|
$crate::model::Token::StringLit(value) => Ok(value.clone()),
|
||||||
other => Err(AssembleError::UnexpectedToken(
|
other => Err($crate::AssembleError::UnexpectedToken(
|
||||||
other.clone(),
|
other.clone(),
|
||||||
TokenType::StringLit,
|
$crate::model::TokenType::StringLit,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($token:expr, Opcode) => {
|
($token:expr, Opcode) => {
|
||||||
match $token {
|
match $token {
|
||||||
Token::Opcode(value) => Ok(value.clone()),
|
$crate::model::Token::Opcode(value) => Ok(value.clone()),
|
||||||
other => Err(AssembleError::UnexpectedToken(
|
other => Err($crate::AssembleError::UnexpectedToken(
|
||||||
other.clone(),
|
other.clone(),
|
||||||
TokenType::Opcode,
|
$crate::model::TokenType::Opcode,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[macro_use]
|
|
||||||
macro_rules! expect_type {
|
macro_rules! expect_type {
|
||||||
($token:expr, $($variant:ident),+) => {{
|
($token:expr, $($variant:ident),+) => {{
|
||||||
let token = $token;
|
let token = $token;
|
||||||
match &token {
|
match &token {
|
||||||
$(
|
$(
|
||||||
Token::$variant(_) => Ok(token.clone()),
|
$crate::model::Token::$variant(_) => Ok(token.clone()),
|
||||||
)+
|
)+
|
||||||
other => {
|
other => {
|
||||||
let expected_type = expect_type!(@get_first_type $($variant),+);
|
let expected_type = expect_type!(@get_first_type $($variant),+);
|
||||||
Err(AssembleError::UnexpectedToken(
|
Err($crate::AssembleError::UnexpectedToken(
|
||||||
other.clone().clone(),
|
other.clone().clone(),
|
||||||
expected_type,
|
expected_type,
|
||||||
))
|
))
|
||||||
@@ -248,9 +245,9 @@ macro_rules! expect_type {
|
|||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
(@get_first_type Symbol $(, $rest:ident)*) => { TokenType::Symbol };
|
(@get_first_type Symbol $(, $rest:ident)*) => { $crate::model::TokenType::Symbol };
|
||||||
(@get_first_type Register $(, $rest:ident)*) => { TokenType::Register };
|
(@get_first_type Register $(, $rest:ident)*) => { $crate::model::TokenType::Register };
|
||||||
(@get_first_type Immediate $(, $rest:ident)*) => { TokenType::Immediate };
|
(@get_first_type Immediate $(, $rest:ident)*) => { $crate::model::TokenType::Immediate };
|
||||||
(@get_first_type StringLit $(, $rest:ident)*) => { TokenType::StringLit };
|
(@get_first_type StringLit $(, $rest:ident)*) => { $crate::model::TokenType::StringLit };
|
||||||
(@get_first_type Opcode $(, $rest:ident)*) => { TokenType::Opcode };
|
(@get_first_type Opcode $(, $rest:ident)*) => { $crate::model::TokenType::Opcode };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ fn main() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{}", e);
|
eprintln!("{e}");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ pub struct Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
#[macro_use]
|
|
||||||
macro_rules! node {
|
macro_rules! node {
|
||||||
($symbol: expr, $opcode: expr, args: $tokens: expr) => {
|
($symbol: expr, $opcode: expr, args: $tokens: expr) => {
|
||||||
Node::new($symbol.clone(), $opcode.clone(), $tokens.clone())
|
Node::new($symbol.clone(), $opcode.clone(), $tokens.clone())
|
||||||
@@ -55,7 +54,7 @@ impl Node {
|
|||||||
impl fmt::Display for Node {
|
impl fmt::Display for Node {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let symbol = match &self.label() {
|
let symbol = match &self.label() {
|
||||||
Some(symbol) => format!("{}:\n", symbol),
|
Some(symbol) => format!("{symbol}:\n"),
|
||||||
None => "".to_string(),
|
None => "".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -146,12 +145,19 @@ impl fmt::Display for Opcode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, Hash)]
|
#[derive(Debug, Clone, Eq)]
|
||||||
pub struct Symbol {
|
pub struct Symbol {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub module: Module,
|
pub module: Module,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::hash::Hash for Symbol {
|
||||||
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.name.hash(state);
|
||||||
|
self.module.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PartialEq for Symbol {
|
impl PartialEq for Symbol {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.name == other.name && self.module == other.module
|
self.name == other.name && self.module == other.module
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use common::prelude::{Instruction, Register};
|
use crate::{
|
||||||
|
AssembleError, expect_token, expect_type,
|
||||||
|
model::{Node, Opcode, Token, TokenType},
|
||||||
|
node,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::model::{Module, Node, Opcode, Symbol, Token, TokenType};
|
use common::prelude::*;
|
||||||
use crate::{AssembleError, dsa, expect_token, expect_type, node, quick_hash};
|
|
||||||
|
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
tokens: Vec<Token>,
|
tokens: Vec<Token>,
|
||||||
@@ -93,7 +96,7 @@ impl Parser {
|
|||||||
|
|
||||||
let mut offset = Token::Immediate(0);
|
let mut offset = Token::Immediate(0);
|
||||||
if let Ok(next) = self.peek_next() {
|
if let Ok(next) = self.peek_next() {
|
||||||
if let Ok(_) = expect_type!(next, Immediate) {
|
if expect_type!(next, Immediate).is_ok() {
|
||||||
offset = self.next()?;
|
offset = self.next()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +108,7 @@ impl Parser {
|
|||||||
let dest = expect_type!(self.next()?, Register, Symbol)?;
|
let dest = expect_type!(self.next()?, Register, Symbol)?;
|
||||||
let mut offset = Token::Immediate(0);
|
let mut offset = Token::Immediate(0);
|
||||||
if let Ok(next) = self.peek_next() {
|
if let Ok(next) = self.peek_next() {
|
||||||
if let Ok(_) = expect_type!(next, Immediate) {
|
if expect_type!(next, Immediate).is_ok() {
|
||||||
offset = self.next()?;
|
offset = self.next()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -273,7 +276,7 @@ impl Parser {
|
|||||||
Token::StringLit(_) => {
|
Token::StringLit(_) => {
|
||||||
values.push(self.tokens.pop().unwrap());
|
values.push(self.tokens.pop().unwrap());
|
||||||
}
|
}
|
||||||
Token::Immediate(val) if *val <= u32::MAX as u32 => {
|
Token::Immediate(_) => {
|
||||||
values.push(self.tokens.pop().unwrap());
|
values.push(self.tokens.pop().unwrap());
|
||||||
}
|
}
|
||||||
_ => break,
|
_ => break,
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ use crate::{
|
|||||||
node, quick_hash,
|
node, quick_hash,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn resolve_symbols(nodes: &mut Vec<Node>) -> Result<(), AssembleError> {
|
pub fn resolve_symbols(nodes: &mut [Node]) -> Result<(), AssembleError> {
|
||||||
let symbol_table = generate_symbol_table(&nodes)?;
|
let symbol_table = generate_symbol_table(nodes)?;
|
||||||
|
|
||||||
for node in nodes.iter_mut() {
|
for node in nodes.iter_mut() {
|
||||||
match node.opcode() {
|
match node.opcode() {
|
||||||
@@ -53,9 +53,7 @@ pub fn resolve_symbols(nodes: &mut Vec<Node>) -> Result<(), AssembleError> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_symbol_table(
|
fn generate_symbol_table(nodes: &[Node]) -> Result<HashMap<Symbol, u32>, AssembleError> {
|
||||||
nodes: &Vec<Node>,
|
|
||||||
) -> Result<HashMap<Symbol, u32>, AssembleError> {
|
|
||||||
let mut table = HashMap::new();
|
let mut table = HashMap::new();
|
||||||
|
|
||||||
for (i, node) in nodes.iter().enumerate() {
|
for (i, node) in nodes.iter().enumerate() {
|
||||||
|
|||||||
@@ -86,7 +86,8 @@ impl TryFrom<u8> for Register {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(match idx {
|
Ok(match idx {
|
||||||
// System registers are not indexable in the reg file so they cannot be modified by instructions.
|
// System registers are not indexable in the reg file so they cannot be
|
||||||
|
// modified by instructions.
|
||||||
0x0 => Self::Rg0,
|
0x0 => Self::Rg0,
|
||||||
0x1 => Self::Rg1,
|
0x1 => Self::Rg1,
|
||||||
0x2 => Self::Rg2,
|
0x2 => Self::Rg2,
|
||||||
@@ -414,8 +415,8 @@ impl std::fmt::Display for Instruction {
|
|||||||
|
|
||||||
Self::Increment(a) | Self::Decrement(a) => write!(f, " {}", a.sr1),
|
Self::Increment(a) | Self::Decrement(a) => write!(f, " {}", a.sr1),
|
||||||
Self::Interrupt(a) => write!(f, " {}", a.as_u8()),
|
Self::Interrupt(a) => write!(f, " {}", a.as_u8()),
|
||||||
Self::Data(a) => write!(f, " {}", a),
|
Self::Data(a) => write!(f, " {a}"),
|
||||||
Self::Segment(x) => write!(f, " [SEGMENT {}]", x),
|
Self::Segment(x) => write!(f, " [SEGMENT {x}]"),
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -469,7 +470,7 @@ impl TryFrom<u32> for Instruction {
|
|||||||
0x24 => Ok(Self::Halt),
|
0x24 => Ok(Self::Halt),
|
||||||
0x25 => Ok(Self::AddImmediate(ITypeArgs::try_from(data)?)),
|
0x25 => Ok(Self::AddImmediate(ITypeArgs::try_from(data)?)),
|
||||||
0x26 => Ok(Self::SubImmediate(ITypeArgs::try_from(data)?)),
|
0x26 => Ok(Self::SubImmediate(ITypeArgs::try_from(data)?)),
|
||||||
0x3F => Ok(Self::Segment(data as u8 as u32)),
|
0x3F => Ok(Self::Segment(u32::from(data as u8))),
|
||||||
_ => Err(InstructionDecodeError::InvalidOpcode(opcode)),
|
_ => Err(InstructionDecodeError::InvalidOpcode(opcode)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ fn encode_no_args(opcode: u8) -> u32 {
|
|||||||
(opcode << 26) | (sr1 << 21) | (sr2 << 16) | (dr << 11) | (shamt << 6)
|
(opcode << 26) | (sr1 << 21) | (sr2 << 16) | (dr << 11) | (shamt << 6)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expands to a match statement that calls encode on instructions that implement [`Encode`]:
|
/// Expands to a match statement that calls encode on instructions that implement
|
||||||
|
/// [`Encode`]:
|
||||||
///
|
///
|
||||||
/// # Usage
|
/// # Usage
|
||||||
///
|
///
|
||||||
@@ -58,7 +59,7 @@ impl Encode for Instruction {
|
|||||||
Self::Segment(segment) => {
|
Self::Segment(segment) => {
|
||||||
let opcode = u32::from(self.opcode());
|
let opcode = u32::from(self.opcode());
|
||||||
let segment = segment as u8;
|
let segment = segment as u8;
|
||||||
(opcode << 26) | (segment as u32)
|
(opcode << 26) | u32::from(segment)
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ impl CodeEditor {
|
|||||||
text: &mut dyn egui::TextBuffer,
|
text: &mut dyn egui::TextBuffer,
|
||||||
) -> TextEditOutput {
|
) -> TextEditOutput {
|
||||||
let mut text_edit_output: Option<TextEditOutput> = None;
|
let mut text_edit_output: Option<TextEditOutput> = None;
|
||||||
let mut code_editor = |ui: &mut egui::Ui| {
|
let code_editor = |ui: &mut egui::Ui| {
|
||||||
ui.horizontal_top(|h| {
|
ui.horizontal_top(|h| {
|
||||||
self.theme.modify_style(h, self.fontsize);
|
self.theme.modify_style(h, self.fontsize);
|
||||||
if self.numlines {
|
if self.numlines {
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ pub fn run_emulator(
|
|||||||
// Execute one cycle.
|
// Execute one cycle.
|
||||||
match processor.cycle() {
|
match processor.cycle() {
|
||||||
Ok((addr, instruction)) => {
|
Ok((addr, instruction)) => {
|
||||||
history.push((addr, instruction.clone()));
|
history.push((addr, instruction));
|
||||||
}
|
}
|
||||||
Err(why) => {
|
Err(why) => {
|
||||||
let pcx = processor.get(Register::Pcx);
|
let pcx = processor.get(Register::Pcx);
|
||||||
@@ -148,7 +148,7 @@ pub fn run_emulator(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
history.push(instruction.clone());
|
history.push(instruction);
|
||||||
|
|
||||||
// let instruction = match Instruction::decode(cpu_lock.get(Register::Cir))
|
// let instruction = match Instruction::decode(cpu_lock.get(Register::Cir))
|
||||||
// {};
|
// {};
|
||||||
|
|||||||
@@ -225,19 +225,13 @@ impl Default for State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct PersistentState {
|
pub struct PersistentState {
|
||||||
pub history: Vec<(u32, Instruction)>,
|
pub history: Vec<(u32, Instruction)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PersistentState {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self { history: vec![] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PersistentState {
|
impl PersistentState {
|
||||||
pub fn update(&mut self, new_state: &PersistentState) {
|
pub fn update(&mut self, new_state: &Self) {
|
||||||
self.history.extend(new_state.history.clone());
|
self.history.extend(new_state.history.clone());
|
||||||
if self.history.len() > 32768 {
|
if self.history.len() > 32768 {
|
||||||
let len = self.history.len() - 32768;
|
let len = self.history.len() - 32768;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ impl Processor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&mut self) {
|
pub const fn reset(&mut self) {
|
||||||
// set all registers to zero
|
// set all registers to zero
|
||||||
// run memory.reset()
|
// run memory.reset()
|
||||||
self.registers.reset();
|
self.registers.reset();
|
||||||
@@ -166,8 +166,6 @@ impl Executable for Instruction {
|
|||||||
fn execute(self, cpu: &mut Processor) {
|
fn execute(self, cpu: &mut Processor) {
|
||||||
match self {
|
match self {
|
||||||
// No operation - a blank line.
|
// No operation - a blank line.
|
||||||
Self::Nop => {}
|
|
||||||
|
|
||||||
// Copies from SrcReg to a.drReg.
|
// Copies from SrcReg to a.drReg.
|
||||||
Self::Mov(a) => {
|
Self::Mov(a) => {
|
||||||
*cpu.reg(a.dr) = cpu.get(a.sr1);
|
*cpu.reg(a.dr) = cpu.get(a.sr1);
|
||||||
@@ -395,11 +393,9 @@ impl Executable for Instruction {
|
|||||||
cpu.halted = true;
|
cpu.halted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::Segment(_) => {}
|
Self::Segment(_) | Self::Nop | Self::Data(_) => {}
|
||||||
Self::Data(_) => {}
|
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
println!("unimplemented instruction: {}", self);
|
eprintln!("WARN: unimplemented instruction: {self}");
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::emulator::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use egui::{Color32, FontId, Margin, RichText, Vec2};
|
use egui::{Color32, FontId, Vec2};
|
||||||
|
|
||||||
const VGA_WIDTH: usize = 80;
|
const VGA_WIDTH: usize = 80;
|
||||||
const VGA_HEIGHT: usize = 25;
|
const VGA_HEIGHT: usize = 25;
|
||||||
@@ -14,11 +14,18 @@ pub struct Display {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Display {
|
impl Display {
|
||||||
pub fn new() -> Self {
|
#[must_use]
|
||||||
|
pub const fn new() -> Self {
|
||||||
Self { visible: false }
|
Self { visible: false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Display {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Component for Display {
|
impl Component for Display {
|
||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
"Display"
|
"Display"
|
||||||
@@ -32,13 +39,14 @@ impl Component for Display {
|
|||||||
&mut self.visible
|
&mut self.visible
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, state: &mut State, ui: &mut egui::Ui, ctx: &egui::Context) {
|
fn render(&mut self, state: &mut State, ui: &mut egui::Ui, _ctx: &egui::Context) {
|
||||||
let display: Vec<u8> = state.display_view.clone();
|
let display: Vec<u8> = state.display_view.clone();
|
||||||
let font_id = FontId::monospace(12.0);
|
let font_id = FontId::monospace(12.0);
|
||||||
|
|
||||||
let char_width = ui.fonts(|f| f.glyph_width(&font_id, 'W'));
|
let char_width = ui.fonts(|f| f.glyph_width(&font_id, 'W'));
|
||||||
let line_height = ui.fonts(|f| f.row_height(&font_id));
|
let line_height = ui.fonts(|f| f.row_height(&font_id));
|
||||||
|
|
||||||
|
#[expect(clippy::cast_precision_loss)]
|
||||||
let display_size = Vec2::new(
|
let display_size = Vec2::new(
|
||||||
char_width * VGA_WIDTH as f32,
|
char_width * VGA_WIDTH as f32,
|
||||||
line_height * VGA_HEIGHT as f32,
|
line_height * VGA_HEIGHT as f32,
|
||||||
@@ -56,7 +64,7 @@ impl Component for Display {
|
|||||||
let index = y * VGA_WIDTH + x;
|
let index = y * VGA_WIDTH + x;
|
||||||
if index < display.len() {
|
if index < display.len() {
|
||||||
let byte = display[index];
|
let byte = display[index];
|
||||||
let ch = if byte >= 32 && byte <= 126 {
|
let ch = if (32..=126).contains(&byte) {
|
||||||
byte as char
|
byte as char
|
||||||
} else {
|
} else {
|
||||||
' '
|
' '
|
||||||
@@ -67,7 +75,9 @@ impl Component for Display {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::cast_precision_loss)]
|
||||||
let text_pos = rect.min + Vec2::new(0.0, y as f32 * line_height);
|
let text_pos = rect.min + Vec2::new(0.0, y as f32 * line_height);
|
||||||
|
|
||||||
ui.painter().text(
|
ui.painter().text(
|
||||||
text_pos,
|
text_pos,
|
||||||
egui::Align2::LEFT_TOP,
|
egui::Align2::LEFT_TOP,
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ impl Component for Editor {
|
|||||||
|
|
||||||
impl Editor {
|
impl Editor {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(sender: Sender<Command>) -> Self {
|
pub const fn new(sender: Sender<Command>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
path: None,
|
path: None,
|
||||||
text: String::new(),
|
text: String::new(),
|
||||||
@@ -176,7 +176,7 @@ impl Editor {
|
|||||||
{
|
{
|
||||||
if let Ok(contents) = std::fs::read_to_string(&path) {
|
if let Ok(contents) = std::fs::read_to_string(&path) {
|
||||||
self.path = Some(path);
|
self.path = Some(path);
|
||||||
self.text = contents.clone();
|
self.text.clone_from(&contents);
|
||||||
self.buffer = contents;
|
self.buffer = contents;
|
||||||
self.unsaved = false;
|
self.unsaved = false;
|
||||||
}
|
}
|
||||||
@@ -294,7 +294,7 @@ impl Editor {
|
|||||||
editor.show(ui, &mut self.text);
|
editor.show(ui, &mut self.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_bottom_bar(&mut self, _state: &mut State, ui: &mut Ui, _ctx: &Context) {
|
fn render_bottom_bar(&self, _state: &mut State, ui: &mut Ui, _ctx: &Context) {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
// error display
|
// error display
|
||||||
ui.label(
|
ui.label(
|
||||||
@@ -337,22 +337,20 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// builds the current file
|
// builds the current file
|
||||||
if ui.button("Build").clicked() {
|
if ui.button("Build").clicked() && !self.unsaved {
|
||||||
if !self.unsaved {
|
if let Some(path) = &self.path {
|
||||||
if let Some(path) = &self.path {
|
let instructions = match assembler::assemble(path) {
|
||||||
let instructions = match assembler::assemble(path) {
|
Ok(instructions) => instructions,
|
||||||
Ok(instructions) => instructions,
|
Err(error) => {
|
||||||
Err(error) => {
|
self.error = Some(error.to_string());
|
||||||
self.error = Some(error.to_string());
|
return;
|
||||||
return;
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
self.output = instructions
|
self.output = instructions
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|i| i.encode().to_be_bytes().to_vec())
|
.flat_map(|i| i.encode().to_be_bytes().to_vec())
|
||||||
.collect();
|
.collect();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ impl Component for History {
|
|||||||
for (idx, instruction) in
|
for (idx, instruction) in
|
||||||
state.persistent.history.iter().enumerate()
|
state.persistent.history.iter().enumerate()
|
||||||
{
|
{
|
||||||
ui.label(format!("{}: ", idx));
|
ui.label(format!("{idx}: "));
|
||||||
|
|
||||||
// Hex column
|
// Hex column
|
||||||
let addr = instruction.0;
|
let addr = instruction.0;
|
||||||
@@ -65,9 +65,15 @@ impl Component for History {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for History {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl History {
|
impl History {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self { visible: false }
|
Self { visible: false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use std::io::Read;
|
|
||||||
|
|
||||||
use crate::emulator::{system::model::State, ui::interface::Component};
|
use crate::emulator::{system::model::State, ui::interface::Component};
|
||||||
|
|
||||||
use common::instructions::Register;
|
use common::instructions::Register;
|
||||||
@@ -52,7 +50,9 @@ impl Component for StackInspector {
|
|||||||
for (i, value) in
|
for (i, value) in
|
||||||
state.stack_view.chunks(4).take(32).enumerate()
|
state.stack_view.chunks(4).take(32).enumerate()
|
||||||
{
|
{
|
||||||
let value = u32::from_be_bytes(value.try_into().unwrap());
|
let value = u32::from_be_bytes(value.try_into().expect(
|
||||||
|
"Could not read 4 byte instruction or data! Something is wrong.",
|
||||||
|
));
|
||||||
ui.label(format!(
|
ui.label(format!(
|
||||||
"{} [{}]",
|
"{} [{}]",
|
||||||
i,
|
i,
|
||||||
|
|||||||
Reference in New Issue
Block a user