cc! assembler and examples

This commit is contained in:
c0repwn3r 2023-05-08 18:01:50 -04:00
parent 6c1cf0f620
commit 596254394f
Signed by: core
GPG key ID: FDBF740DADDCEECF
7 changed files with 298 additions and 169 deletions

View file

@ -1,7 +1,7 @@
use crate::opt_sim_asm::SimpleAssemblySimulator;
use std::error::Error;
use std::fs;
use std::path::PathBuf;
use crate::opt_sim_asm::SimpleAssemblySimulator;
pub fn assemble(processed: String, out: PathBuf) -> Result<(), Box<dyn Error>> {
let mut simple_sim = SimpleAssemblySimulator {

View file

@ -1,6 +1,8 @@
use std::error::Error;
use std::path::PathBuf;
pub fn disassemble(file: PathBuf, out: PathBuf) -> Result<(), Box<dyn Error>> {
// TODO
pub fn disassemble(_file: PathBuf, _out: PathBuf) -> Result<(), Box<dyn Error>> {
Ok(())
}

View file

@ -1,16 +1,16 @@
use std::path::PathBuf;
use clap::{Parser, ArgAction};
use crate::asm::assemble;
use crate::disasm::disassemble;
use crate::normalizer::normalize;
use crate::preprocessor::preprocess;
use clap::{ArgAction, Parser};
use std::path::PathBuf;
pub mod ops;
pub mod asm;
pub mod disasm;
pub mod normalizer;
pub mod asm;
pub mod preprocessor;
pub mod ops;
pub mod opt_sim_asm;
pub mod preprocessor;
#[derive(Parser)]
pub struct Cli {
@ -25,7 +25,7 @@ pub struct Cli {
#[clap(short, long, action = ArgAction::SetTrue)]
pub preprocess_only: bool,
#[clap(short, long, action = ArgAction::SetTrue)]
pub disassemble: bool
pub disassemble: bool,
}
fn main() {

View file

@ -14,7 +14,12 @@ pub fn normalize(file: PathBuf) -> Result<String, Box<dyn Error>> {
match line_split[0] {
"lsh" => {
if line_split.len() != 3 {
return Err(format!("line {}: expected exactly 2 arguments to 'lsh', instead got {}", line_num, line_split.len() - 1).into());
return Err(format!(
"line {}: expected exactly 2 arguments to 'lsh', instead got {}",
line_num,
line_split.len() - 1
)
.into());
}
let dest = line_split[1];
if !dest.ends_with(',') {
@ -23,21 +28,33 @@ pub fn normalize(file: PathBuf) -> Result<String, Box<dyn Error>> {
let dest = &dest[..dest.len() - 1];
let rg = line_split[2];
normalized += &format!("add {}, {} {} ; normalizer: originally '{}'\n", dest, rg, rg, line);
},
normalized += &format!(
"add {}, {} {} ; normalizer: originally '{}'\n",
dest, rg, rg, line
);
}
"cmp" => {
if line_split.len() != 3 {
return Err(format!("line {}: expected exactly 2 arguments to 'cmp', instead got {}", line_num, line_split.len() - 1).into());
return Err(format!(
"line {}: expected exactly 2 arguments to 'cmp', instead got {}",
line_num,
line_split.len() - 1
)
.into());
}
let a = line_split[1];
let b = line_split[2];
normalized += &format!("sub r0, {} {} ; normalizer: originally '{}'\n", a, b, line);
},
}
"cpy" => {
if line_split.len() != 3 {
return Err(format!("line {}: expected exactly 2 arguments to 'cpy', instead got {}", line_num, line_split.len() - 1).into());
return Err(format!(
"line {}: expected exactly 2 arguments to 'cpy', instead got {}",
line_num,
line_split.len() - 1
)
.into());
}
let dest = line_split[1];
let a = line_split[2];
@ -47,11 +64,21 @@ pub fn normalize(file: PathBuf) -> Result<String, Box<dyn Error>> {
}
normalized += "ldi r0, 0 ; normalizer: originally below\n";
normalized += &format!("add {}, {} r0 ; normalizer: originally '{}'\n", &dest[..dest.len()-1], a, line);
},
normalized += &format!(
"add {}, {} r0 ; normalizer: originally '{}'\n",
&dest[..dest.len() - 1],
a,
line
);
}
"not" => {
if line_split.len() != 3 {
return Err(format!("line {}: expected exactly 2 arguments to 'not', instead got {}", line_num, line_split.len() - 1).into());
return Err(format!(
"line {}: expected exactly 2 arguments to 'not', instead got {}",
line_num,
line_split.len() - 1
)
.into());
}
let dest = line_split[1];
let a = line_split[2];
@ -61,7 +88,12 @@ pub fn normalize(file: PathBuf) -> Result<String, Box<dyn Error>> {
}
normalized += "ldi r0, 0 ; normalizer: originally below\n";
normalized += &format!("nor {}, {} r0 ; normalizer: originally '{}'\n", &dest[..dest.len()-1], a, line);
normalized += &format!(
"nor {}, {} r0 ; normalizer: originally '{}'\n",
&dest[..dest.len() - 1],
a,
line
);
}
_ => {
normalized += line;

View file

@ -13,7 +13,7 @@ pub enum Register {
RD,
RE,
PC,
FLG
FLG,
}
impl Register {
fn byte(&self) -> u8 {
@ -35,7 +35,7 @@ pub fn add(reg_dest: Register, reg_a: Register, reg_b: Register) -> Vec<u8> {
0b1111_1101, // opcode
reg_dest.byte() << 5 | reg_a.byte() << 2, // operands 1
reg_b.byte() << 5, // operands 2,
0b0000_0000 // operands 3
0b0000_0000, // operands 3
]
}
@ -44,7 +44,7 @@ pub fn sub(reg_dest: Register, reg_a: Register, reg_b: Register) -> Vec<u8> {
0b1111_1100, // opcode
reg_dest.byte() << 5 | reg_a.byte() << 2, // operands 1
reg_b.byte() << 5, // operands 2,
0b0000_0000 // operands 3
0b0000_0000, // operands 3
]
}
@ -53,7 +53,7 @@ pub fn or(reg_dest: Register, reg_a: Register, reg_b: Register) -> Vec<u8> {
0b1111_1011, // opcode
reg_dest.byte() << 5 | reg_a.byte() << 2, // operands 1
reg_b.byte() << 5, // operands 2,
0b0000_0000 // operands 3
0b0000_0000, // operands 3
]
}
@ -62,7 +62,7 @@ pub fn nor(reg_dest: Register, reg_a: Register, reg_b: Register) -> Vec<u8> {
0b1111_1010, // opcode
reg_dest.byte() << 5 | reg_a.byte() << 2, // operands 1
reg_b.byte() << 5, // operands 2,
0b0000_0000 // operands 3
0b0000_0000, // operands 3
]
}
@ -71,7 +71,7 @@ pub fn and(reg_dest: Register, reg_a: Register, reg_b: Register) -> Vec<u8> {
0b1111_1001, // opcode
reg_dest.byte() << 5 | reg_a.byte() << 2, // operands 1
reg_b.byte() << 5, // operands 2,
0b0000_0000 // operands 3
0b0000_0000, // operands 3
]
}
@ -80,7 +80,7 @@ pub fn xor(reg_dest: Register, reg_a: Register, reg_b: Register) -> Vec<u8> {
0b1111_1000, // opcode
reg_dest.byte() << 5 | reg_a.byte() << 2, // operands 1
reg_b.byte() << 5, // operands 2,
0b0000_0000 // operands 3
0b0000_0000, // operands 3
]
}
@ -89,7 +89,7 @@ pub fn rsh(reg_dest: Register, reg_a: Register) -> Vec<u8> {
0b1111_0111, // opcode
reg_dest.byte() << 5 | reg_a.byte() << 2, // operands 1
0b0000_0000, // operands 2,
0b0000_0000 // operands 3
0b0000_0000, // operands 3
]
}
@ -98,7 +98,7 @@ pub fn ldi(reg_dest: Register, immediate: u8) -> Vec<u8> {
0b1111_0110, // opcode
reg_dest.byte() << 5, // operands 1
immediate, // operands 2,
0b0000_0000 // operands 3
0b0000_0000, // operands 3
]
}
@ -129,7 +129,7 @@ pub fn jmp(address: u16) -> Vec<u8> {
0b1111_0011, // opcode
address_higher_half(address), // operands 1
address_lower_half(address), // operands 2,
0b0000_0000
0b0000_0000,
]
}
@ -138,7 +138,7 @@ pub fn jez(address: u16) -> Vec<u8> {
0b1111_0010, // opcode
address_higher_half(address), // operands 1
address_lower_half(address), // operands 2,
0b0000_0000
0b0000_0000,
]
}
@ -152,21 +152,11 @@ pub fn rmmr(reg_dest: Register, address: u16) -> Vec<u8> {
}
pub fn r#in(reg_dest: Register, port: u8) -> Vec<u8> {
vec![
0b1111_0000,
reg_dest.byte() << 5,
port,
0b0000_0000
]
vec![0b1111_0000, reg_dest.byte() << 5, port, 0b0000_0000]
}
pub fn out(reg_src: Register, port: u8) -> Vec<u8> {
vec![
0b1110_1111,
reg_src.byte() << 5,
port,
0b0000_0000
]
vec![0b1110_1111, reg_src.byte() << 5, port, 0b0000_0000]
}
// See `mmr` for how these values are calculated
@ -178,8 +168,12 @@ fn address_lower_half(address: u16) -> u8 {
((address & 0b0000_0000_0000_1111) << 4).try_into().unwrap()
}
#[cfg(test)]
mod tests {
use crate::ops::{add, and, hcf, jez, jmp, ldi, mmr, mrm, nop, nor, or, out, r#in, Register, rmmr, rsh, sub, xor};
use crate::ops::{
add, and, hcf, jez, jmp, ldi, mmr, mrm, nop, nor, or, out, r#in, rmmr, rsh, sub, xor,
Register,
};
#[test]
fn test_nop() {
@ -193,76 +187,121 @@ mod tests {
#[test]
fn test_add() {
assert_eq!(add(Register::R0, Register::RA, Register::RB), vec![0b1111_1101, 0b0000_0100, 0b0100_0000, 0b0000_0000])
assert_eq!(
add(Register::R0, Register::RA, Register::RB),
vec![0b1111_1101, 0b0000_0100, 0b0100_0000, 0b0000_0000]
)
}
#[test]
fn test_sub() {
assert_eq!(sub(Register::R0, Register::RA, Register::RB), vec![0b1111_1100, 0b0000_0100, 0b0100_0000, 0b0000_0000])
assert_eq!(
sub(Register::R0, Register::RA, Register::RB),
vec![0b1111_1100, 0b0000_0100, 0b0100_0000, 0b0000_0000]
)
}
#[test]
fn test_or() {
assert_eq!(or(Register::R0, Register::RA, Register::RB), vec![0b1111_1011, 0b0000_0100, 0b0100_0000, 0b0000_0000])
assert_eq!(
or(Register::R0, Register::RA, Register::RB),
vec![0b1111_1011, 0b0000_0100, 0b0100_0000, 0b0000_0000]
)
}
#[test]
fn test_nor() {
assert_eq!(nor(Register::R0, Register::RA, Register::RB), vec![0b1111_1010, 0b0000_0100, 0b0100_0000, 0b0000_0000])
assert_eq!(
nor(Register::R0, Register::RA, Register::RB),
vec![0b1111_1010, 0b0000_0100, 0b0100_0000, 0b0000_0000]
)
}
#[test]
fn test_and() {
assert_eq!(and(Register::R0, Register::RA, Register::RB), vec![0b1111_1001, 0b0000_0100, 0b0100_0000, 0b0000_0000])
assert_eq!(
and(Register::R0, Register::RA, Register::RB),
vec![0b1111_1001, 0b0000_0100, 0b0100_0000, 0b0000_0000]
)
}
#[test]
fn test_xor() {
assert_eq!(xor(Register::R0, Register::RA, Register::RB), vec![0b1111_1000, 0b0000_0100, 0b0100_0000, 0b0000_0000])
assert_eq!(
xor(Register::R0, Register::RA, Register::RB),
vec![0b1111_1000, 0b0000_0100, 0b0100_0000, 0b0000_0000]
)
}
#[test]
fn test_rsh() {
assert_eq!(rsh(Register::R0, Register::RA), vec![0b1111_0111, 0b0000_0100, 0b0000_0000, 0b0000_0000])
assert_eq!(
rsh(Register::R0, Register::RA),
vec![0b1111_0111, 0b0000_0100, 0b0000_0000, 0b0000_0000]
)
}
#[test]
fn test_ldi() {
assert_eq!(ldi(Register::R0, 0b0101_1010), vec![0b1111_0110, 0b0000_0000, 0b0101_1010, 0b0000_0000])
assert_eq!(
ldi(Register::R0, 0b0101_1010),
vec![0b1111_0110, 0b0000_0000, 0b0101_1010, 0b0000_0000]
)
}
#[test]
fn test_mmr() {
assert_eq!(mmr(Register::R0, 0b0000_0101_1010_0110), vec![0b1111_0101, 0b0000_0000, 0b0101_1010, 0b0110_0000])
assert_eq!(
mmr(Register::R0, 0b0000_0101_1010_0110),
vec![0b1111_0101, 0b0000_0000, 0b0101_1010, 0b0110_0000]
)
}
#[test]
fn test_mrm() {
assert_eq!(mrm(Register::R0, 0b0000_0101_1010_0110), vec![0b1111_0100, 0b0000_0000, 0b0101_1010, 0b0110_0000])
assert_eq!(
mrm(Register::R0, 0b0000_0101_1010_0110),
vec![0b1111_0100, 0b0000_0000, 0b0101_1010, 0b0110_0000]
)
}
#[test]
fn test_jmp() {
assert_eq!(jmp(0b0000_0101_1010_0110), vec![0b1111_0011, 0b0101_1010, 0b0110_0000, 0b0000_0000])
assert_eq!(
jmp(0b0000_0101_1010_0110),
vec![0b1111_0011, 0b0101_1010, 0b0110_0000, 0b0000_0000]
)
}
#[test]
fn test_jez() {
assert_eq!(jez(0b0000_0101_1010_0110), vec![0b1111_0010, 0b0101_1010, 0b0110_0000, 0b0000_0000])
assert_eq!(
jez(0b0000_0101_1010_0110),
vec![0b1111_0010, 0b0101_1010, 0b0110_0000, 0b0000_0000]
)
}
#[test]
fn test_rmmr() {
assert_eq!(rmmr(Register::R0, 0b0000_0101_1010_0110), vec![0b1111_0001, 0b0000_0000, 0b0101_1010, 0b0110_0000])
assert_eq!(
rmmr(Register::R0, 0b0000_0101_1010_0110),
vec![0b1111_0001, 0b0000_0000, 0b0101_1010, 0b0110_0000]
)
}
#[test]
fn test_in() {
assert_eq!(r#in(Register::R0, 0b0101_1010), vec![0b1111_0000, 0b0000_0000, 0b0101_1010, 0b0000_0000])
assert_eq!(
r#in(Register::R0, 0b0101_1010),
vec![0b1111_0000, 0b0000_0000, 0b0101_1010, 0b0000_0000]
)
}
#[test]
fn test_out() {
assert_eq!(out(Register::R0, 0b0101_1010), vec![0b1110_1111, 0b0000_0000, 0b0101_1010, 0b0000_0000])
assert_eq!(
out(Register::R0, 0b0101_1010),
vec![0b1110_1111, 0b0000_0000, 0b0101_1010, 0b0000_0000]
)
}
}

View file

@ -1,5 +1,7 @@
use crate::ops::{
add, and, hcf, ldi, mmr, mrm, nop, nor, or, out, r#in, rmmr, rsh, sub, xor, Register,
};
use std::error::Error;
use crate::ops::{add, and, hcf, ldi, mmr, mrm, nop, nor, or, out, r#in, Register, rmmr, rsh, sub, xor};
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct SimpleAssemblySimulator {
@ -13,7 +15,7 @@ pub struct SimpleAssemblySimulator {
pub rd: u8,
pub re: u8,
pub pc: u16,
pub flg: u8
pub flg: u8,
}
impl SimpleAssemblySimulator {
pub fn line(&mut self, line: &str) -> Result<Vec<u8>, Box<dyn Error>> {
@ -23,10 +25,14 @@ impl SimpleAssemblySimulator {
"nop" => Ok(nop()),
"hcf" => Ok(hcf()), // ignored for the simulator
"add" => {
if line_split.len() != 4 { return Err("add requires exactly 3 arguments".into()) }
if line_split.len() != 4 {
return Err("add requires exactly 3 arguments".into());
}
let dest = line_split[1];
if !dest.ends_with(',') { return Err("1st argument of add must end in , ".into()) }
if !dest.ends_with(',') {
return Err("1st argument of add must end in , ".into());
}
let dest = to_reg(&dest[..dest.len() - 1])?;
let a = to_reg(line_split[2])?;
@ -38,7 +44,7 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd,
Register::RE => self.re,
Register::PC => return Err("Cannot use program counter as a register".into()),
Register::FLG => self.flg
Register::FLG => self.flg,
};
let b = to_reg(line_split[3])?;
@ -51,7 +57,7 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd,
Register::RE => self.re,
Register::PC => return Err("Cannot use program counter as a register".into()),
Register::FLG => self.flg
Register::FLG => self.flg,
};
let mut val = (a_val as u16) + (b_val as u16);
@ -67,16 +73,20 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd = val as u8,
Register::RE => self.re = val as u8,
Register::PC => self.pc = (val as u8) as u16,
Register::FLG => self.flg = val as u8
Register::FLG => self.flg = val as u8,
}
Ok(add(dest, a, b))
},
}
"sub" => {
if line_split.len() != 4 { return Err("sub requires exactly 3 arguments".into()) }
if line_split.len() != 4 {
return Err("sub requires exactly 3 arguments".into());
}
let dest = line_split[1];
if !dest.ends_with(',') { return Err("1st argument of sub must end in , ".into()) }
if !dest.ends_with(',') {
return Err("1st argument of sub must end in , ".into());
}
let dest = to_reg(&dest[..dest.len() - 1])?;
let a = to_reg(line_split[2])?;
@ -88,7 +98,7 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd,
Register::RE => self.re,
Register::PC => return Err("Cannot use program counter as a register".into()),
Register::FLG => self.flg
Register::FLG => self.flg,
};
let b = to_reg(line_split[3])?;
@ -101,15 +111,15 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd,
Register::RE => self.re,
Register::PC => return Err("Cannot use program counter as a register".into()),
Register::FLG => self.flg
Register::FLG => self.flg,
};
let val;
if b_val > a_val {
val = 0;
let val = if b_val > a_val {
0
} else {
val = a_val - b_val;
}
a_val - b_val
};
match dest {
Register::R0 => self.r0 = val,
@ -119,16 +129,20 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd = val,
Register::RE => self.re = val,
Register::PC => self.pc = (val) as u16,
Register::FLG => self.flg = val
Register::FLG => self.flg = val,
}
Ok(sub(dest, a, b))
},
}
"or" => {
if line_split.len() != 4 { return Err("or requires exactly 3 arguments".into()) }
if line_split.len() != 4 {
return Err("or requires exactly 3 arguments".into());
}
let dest = line_split[1];
if !dest.ends_with(',') { return Err("1st argument of or must end in , ".into()) }
if !dest.ends_with(',') {
return Err("1st argument of or must end in , ".into());
}
let dest = to_reg(&dest[..dest.len() - 1])?;
let a = to_reg(line_split[2])?;
@ -140,7 +154,7 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd,
Register::RE => self.re,
Register::PC => return Err("Cannot use program counter as a register".into()),
Register::FLG => self.flg
Register::FLG => self.flg,
};
let b = to_reg(line_split[3])?;
@ -153,7 +167,7 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd,
Register::RE => self.re,
Register::PC => return Err("Cannot use program counter as a register".into()),
Register::FLG => self.flg
Register::FLG => self.flg,
};
match dest {
@ -164,16 +178,20 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd = a_val | b_val,
Register::RE => self.re = a_val | b_val,
Register::PC => self.pc = (a_val | b_val) as u16,
Register::FLG => self.flg = a_val | b_val
Register::FLG => self.flg = a_val | b_val,
}
Ok(or(dest, a, b))
},
}
"nor" => {
if line_split.len() != 4 { return Err("nor requires exactly 3 arguments".into()) }
if line_split.len() != 4 {
return Err("nor requires exactly 3 arguments".into());
}
let dest = line_split[1];
if !dest.ends_with(',') { return Err("1st argument of nor must end in , ".into()) }
if !dest.ends_with(',') {
return Err("1st argument of nor must end in , ".into());
}
let dest = to_reg(&dest[..dest.len() - 1])?;
let a = to_reg(line_split[2])?;
@ -185,7 +203,7 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd,
Register::RE => self.re,
Register::PC => return Err("Cannot use program counter as a register".into()),
Register::FLG => self.flg
Register::FLG => self.flg,
};
let b = to_reg(line_split[3])?;
@ -198,7 +216,7 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd,
Register::RE => self.re,
Register::PC => return Err("Cannot use program counter as a register".into()),
Register::FLG => self.flg
Register::FLG => self.flg,
};
match dest {
@ -209,16 +227,20 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd = !(a_val | b_val),
Register::RE => self.re = !(a_val | b_val),
Register::PC => self.pc = !(a_val | b_val) as u16,
Register::FLG => self.flg = !(a_val | b_val)
Register::FLG => self.flg = !(a_val | b_val),
}
Ok(nor(dest, a, b))
},
}
"and" => {
if line_split.len() != 4 { return Err("and requires exactly 3 arguments".into()) }
if line_split.len() != 4 {
return Err("and requires exactly 3 arguments".into());
}
let dest = line_split[1];
if !dest.ends_with(',') { return Err("1st argument of and must end in , ".into()) }
if !dest.ends_with(',') {
return Err("1st argument of and must end in , ".into());
}
let dest = to_reg(&dest[..dest.len() - 1])?;
let a = to_reg(line_split[2])?;
@ -230,7 +252,7 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd,
Register::RE => self.re,
Register::PC => return Err("Cannot use program counter as a register".into()),
Register::FLG => self.flg
Register::FLG => self.flg,
};
let b = to_reg(line_split[3])?;
@ -243,7 +265,7 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd,
Register::RE => self.re,
Register::PC => return Err("Cannot use program counter as a register".into()),
Register::FLG => self.flg
Register::FLG => self.flg,
};
match dest {
@ -254,16 +276,20 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd = a_val & b_val,
Register::RE => self.re = a_val & b_val,
Register::PC => self.pc = (a_val & b_val) as u16,
Register::FLG => self.flg = a_val & b_val
Register::FLG => self.flg = a_val & b_val,
}
Ok(and(dest, a, b))
},
}
"xor" => {
if line_split.len() != 4 { return Err("xor requires exactly 3 arguments".into()) }
if line_split.len() != 4 {
return Err("xor requires exactly 3 arguments".into());
}
let dest = line_split[1];
if !dest.ends_with(',') { return Err("1st argument of xor must end in , ".into()) }
if !dest.ends_with(',') {
return Err("1st argument of xor must end in , ".into());
}
let dest = to_reg(&dest[..dest.len() - 1])?;
let a = to_reg(line_split[2])?;
@ -275,7 +301,7 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd,
Register::RE => self.re,
Register::PC => return Err("Cannot use program counter as a register".into()),
Register::FLG => self.flg
Register::FLG => self.flg,
};
let b = to_reg(line_split[3])?;
@ -288,7 +314,7 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd,
Register::RE => self.re,
Register::PC => return Err("Cannot use program counter as a register".into()),
Register::FLG => self.flg
Register::FLG => self.flg,
};
match dest {
@ -299,16 +325,20 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd = a_val ^ b_val,
Register::RE => self.re = a_val ^ b_val,
Register::PC => self.pc = (a_val ^ b_val) as u16,
Register::FLG => self.flg = a_val ^ b_val
Register::FLG => self.flg = a_val ^ b_val,
}
Ok(xor(dest, a, b))
},
}
"rsh" => {
if line_split.len() != 3 { return Err("rsh requires exactly 2 arguments".into()) }
if line_split.len() != 3 {
return Err("rsh requires exactly 2 arguments".into());
}
let dest = line_split[1];
if !dest.ends_with(',') { return Err("1st argument of rsh must end in , ".into()) }
if !dest.ends_with(',') {
return Err("1st argument of rsh must end in , ".into());
}
let dest = to_reg(&dest[..dest.len() - 1])?;
let a = to_reg(line_split[2])?;
@ -320,7 +350,7 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd,
Register::RE => self.re,
Register::PC => return Err("Cannot use program counter as a register".into()),
Register::FLG => self.flg
Register::FLG => self.flg,
};
match dest {
@ -331,16 +361,20 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd = a_val >> 1,
Register::RE => self.re = a_val >> 1,
Register::PC => self.pc = (a_val >> 1) as u16,
Register::FLG => self.flg = a_val >> 1
Register::FLG => self.flg = a_val >> 1,
}
Ok(rsh(dest, a))
},
}
"ldi" => {
if line_split.len() != 3 { return Err("rsh requires exactly 2 arguments".into()) }
if line_split.len() != 3 {
return Err("rsh requires exactly 2 arguments".into());
}
let dest = line_split[1];
if !dest.ends_with(',') { return Err("1st argument of rsh must end in , ".into()) }
if !dest.ends_with(',') {
return Err("1st argument of rsh must end in , ".into());
}
let dest = to_reg(&dest[..dest.len() - 1])?;
let data: u8 = parse_int::parse(line_split[2])?;
@ -352,16 +386,20 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd = data,
Register::RE => self.re = data,
Register::PC => self.pc = data as u16,
Register::FLG => self.flg = data
Register::FLG => self.flg = data,
}
Ok(ldi(dest, data))
},
}
"mmr" => {
if line_split.len() != 3 { return Err("mmr requires exactly 2 arguments".into()) }
if line_split.len() != 3 {
return Err("mmr requires exactly 2 arguments".into());
}
let dest = line_split[1];
if !dest.ends_with(',') { return Err("1st argument of mmr must end in , ".into()) }
if !dest.ends_with(',') {
return Err("1st argument of mmr must end in , ".into());
}
let dest = to_reg(&dest[..dest.len() - 1])?;
let address: u16 = parse_int::parse(line_split[2])?;
@ -373,16 +411,20 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd = self.ram[address as usize],
Register::RE => self.re = self.ram[address as usize],
Register::PC => self.pc = self.ram[address as usize] as u16,
Register::FLG => self.flg = self.ram[address as usize]
Register::FLG => self.flg = self.ram[address as usize],
}
Ok(mmr(dest, address))
},
}
"mrm" => {
if line_split.len() != 3 { return Err("mrm requires exactly 2 arguments".into()) }
if line_split.len() != 3 {
return Err("mrm requires exactly 2 arguments".into());
}
let dest = line_split[1];
if !dest.ends_with(',') { return Err("1st argument of mrm must end in , ".into()) }
if !dest.ends_with(',') {
return Err("1st argument of mrm must end in , ".into());
}
let src = line_split[2];
let src = to_reg(src)?;
@ -397,26 +439,34 @@ impl SimpleAssemblySimulator {
Register::RD => self.ram[address as usize] = self.rd,
Register::RE => self.ram[address as usize] = self.re,
Register::PC => self.ram[address as usize] = self.pc.try_into().unwrap(),
Register::FLG => self.ram[address as usize] = self.flg
Register::FLG => self.ram[address as usize] = self.flg,
}
Ok(mrm(src, address))
},
}
"in" => {
if line_split.len() != 3 { return Err("in requires exactly 2 arguments".into()) }
if line_split.len() != 3 {
return Err("in requires exactly 2 arguments".into());
}
let dest = line_split[1];
if !dest.ends_with(',') { return Err("1st argument of in must end in , ".into()) }
if !dest.ends_with(',') {
return Err("1st argument of in must end in , ".into());
}
let dest = to_reg(&dest[..dest.len() - 1])?;
let port: u8 = parse_int::parse(line_split[2])?;
Ok(r#in(dest, port))
},
}
"out" => {
if line_split.len() != 3 { return Err("in requires exactly 2 arguments".into()) }
if line_split.len() != 3 {
return Err("in requires exactly 2 arguments".into());
}
let dest = line_split[1];
if !dest.ends_with(',') { return Err("1st argument of in must end in , ".into()) }
if !dest.ends_with(',') {
return Err("1st argument of in must end in , ".into());
}
let src = line_split[2];
let src = to_reg(src)?;
@ -424,12 +474,16 @@ impl SimpleAssemblySimulator {
let port: u8 = parse_int::parse(&line_split[1][..line_split[1].len() - 1])?;
Ok(out(src, port))
},
}
"rmmr" => {
if line_split.len() != 3 { return Err("rmmr requires exactly 2 arguments".into()) }
if line_split.len() != 3 {
return Err("rmmr requires exactly 2 arguments".into());
}
let dest = line_split[1];
if !dest.ends_with(',') { return Err("1st argument of rmmr must end in , ".into()) }
if !dest.ends_with(',') {
return Err("1st argument of rmmr must end in , ".into());
}
let dest = to_reg(&dest[..dest.len() - 1])?;
let address: u16 = parse_int::parse(line_split[2])?;
@ -441,12 +495,12 @@ impl SimpleAssemblySimulator {
Register::RD => self.rd = self.ram[address as usize],
Register::RE => self.re = self.ram[address as usize],
Register::PC => self.pc = self.ram[address as usize] as u16,
Register::FLG => self.flg = self.ram[address as usize]
Register::FLG => self.flg = self.ram[address as usize],
}
Ok(rmmr(dest, address))
}
_ => Err(format!("Unknown instruction {}", line_split[0]).into())
_ => Err(format!("Unknown instruction {}", line_split[0]).into()),
}
}
}
@ -461,6 +515,6 @@ fn to_reg(s: &str) -> Result<Register, Box<dyn Error>> {
"re" => Ok(Register::RE),
"pc" => Ok(Register::PC),
"flg" => Ok(Register::FLG),
_ => Err(format!("Unknown register {}", s).into())
_ => Err(format!("Unknown register {}", s).into()),
}
}

View file

@ -14,7 +14,9 @@ pub fn preprocess(normalized: String) -> Result<String, Box<dyn Error>> {
}
if !line_comments_removed.is_empty() {
processed += line_comments_removed.trim_start_matches(' ').trim_end_matches(' ');
processed += line_comments_removed
.trim_start_matches(' ')
.trim_end_matches(' ');
processed += "\n";
}
}