- updated assembler to support new shift implementation

- updated emulator to support new shift implementation
- updated emulator to rename NoReg to Null as in the common lib
This commit is contained in:
2026-02-09 00:05:45 +00:00
parent f7ed764e96
commit e2be83414b
4 changed files with 72 additions and 27 deletions
+18 -6
View File
@@ -223,19 +223,31 @@ fn build_shift_instruction(
opcode: Opcode, opcode: Opcode,
args: &[crate::assembler::model::Token], args: &[crate::assembler::model::Token],
) -> Result<Instruction, AssembleError> { ) -> Result<Instruction, AssembleError> {
let Some(reg_token) = args.first() else { let Some(src_reg) = args.first() else {
return Err(AssembleError::MissingArgument(0)); return Err(AssembleError::MissingArgument(0));
}; };
let Some(amount_token) = args.get(1) else { let Some(r_shamt) = args.get(1) else {
return Err(AssembleError::MissingArgument(0));
};
let Some(i_shamt) = args.get(2) else {
return Err(AssembleError::MissingArgument(1));
};
let Some(dest_reg) = args.get(3) else {
return Err(AssembleError::MissingArgument(1)); return Err(AssembleError::MissingArgument(1));
}; };
let reg = expect_token!(reg_token, Register)?; let src = expect_token!(src_reg, Register)?;
let amount = expect_token!(amount_token, Immediate)? as u8; let r_shamt = expect_token!(r_shamt, Register)?;
let i_shamt = expect_token!(i_shamt, Immediate)? as u8;
let dest = expect_token!(dest_reg, Register)?;
match opcode { match opcode {
Opcode::Shl => Ok(Instruction::ShiftLeft(args!(R, sr1: reg, shamt: amount))), Opcode::Shl => Ok(Instruction::ShiftLeft(
Opcode::Shr => Ok(Instruction::ShiftRight(args!(R, sr1: reg, shamt: amount))), args!(R, sr1: src, sr2: r_shamt, shamt: i_shamt, dr: dest),
)),
Opcode::Shr => Ok(Instruction::ShiftRight(
args!(R, sr1: src, sr2: r_shamt, shamt: i_shamt, dr: dest),
)),
_ => unreachable!(), _ => unreachable!(),
} }
} }
+46 -9
View File
@@ -1,5 +1,6 @@
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use crate::assembler::TokenType;
use crate::{assembler::AssembleError, expect_token, expect_type, node}; use crate::{assembler::AssembleError, expect_token, expect_type, node};
use crate::assembler::model::{Node, Opcode, Token}; use crate::assembler::model::{Node, Opcode, Token};
@@ -114,7 +115,8 @@ 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()
&& expect_type!(next, Immediate).is_ok() { && expect_type!(next, Immediate).is_ok()
{
offset = self.next()?; offset = self.next()?;
} }
@@ -125,7 +127,8 @@ 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()
&& expect_type!(next, Immediate).is_ok() { && expect_type!(next, Immediate).is_ok()
{
offset = self.next()?; offset = self.next()?;
} }
args = vec![base, dest, offset]; args = vec![base, dest, offset];
@@ -146,15 +149,49 @@ impl Parser {
} }
Opcode::Not | Opcode::Cmp => { Opcode::Not | Opcode::Cmp => {
let reg1 = expect_type!(self.next()?, Register, Symbol)?; let src = expect_type!(self.next()?, Register, Symbol)?;
let reg2 = expect_type!(self.next()?, Register, Symbol)?; let dest = expect_type!(self.next()?, Register, Symbol)?;
args = vec![reg1, reg2]; args = vec![src, dest];
} }
Opcode::Shl | Opcode::Shr => { Opcode::Shl | Opcode::Shr => {
let reg = expect_type!(self.next()?, Register, Symbol)?; let src = expect_type!(self.next()?, Register, Symbol)?;
let num = expect_type!(self.next()?, Immediate)?;
args = vec![reg, num]; // First operand after src: could be immediate or register
let first = self.next()?;
let (r_shamt, i_shamt) = match first {
Token::Register(_) => (
first,
if let Ok(tok) = self.peek_next() {
if expect_type!(tok, Immediate).is_ok() {
self.next()?
} else {
Token::Immediate(0)
}
} else {
Token::Immediate(0)
},
),
Token::Immediate(_) => (Token::Register(Register::Zero), first),
_ => {
return Err(AssembleError::UnexpectedToken(
first,
TokenType::Immediate,
));
}
};
let dest = if let Ok(tok) = self.peek_next() {
if expect_type!(tok, Register).is_ok() {
self.next()?
} else {
src.clone() // Default to src if no dest specified
}
} else {
src.clone() // Default to src if no dest specified
};
args = vec![src, r_shamt, i_shamt, dest];
} }
Opcode::Inc | Opcode::Dec => { Opcode::Inc | Opcode::Dec => {
+2 -2
View File
@@ -286,7 +286,7 @@ impl RegFile {
Register::Sts => &mut self.sts, Register::Sts => &mut self.sts,
Register::Cir => &mut self.cir, Register::Cir => &mut self.cir,
Register::Pcx => &mut self.pcx, Register::Pcx => &mut self.pcx,
_ => return Err(ProcessorError::InvalidRegister(Register::NoReg as u8)), _ => return Err(ProcessorError::InvalidRegister(Register::Null as u8)),
}) })
} }
@@ -321,7 +321,7 @@ impl RegFile {
Register::Cir => self.cir, Register::Cir => self.cir,
Register::Pcx => self.pcx, Register::Pcx => self.pcx,
Register::Zero => 0, Register::Zero => 0,
_ => return Err(ProcessorError::InvalidRegister(Register::NoReg as u8)), _ => return Err(ProcessorError::InvalidRegister(Register::Null as u8)),
}) })
} }
} }
@@ -349,17 +349,13 @@ impl Executable for Instruction {
// Left shifts the value in Reg by the given amount (either a register, or a // Left shifts the value in Reg by the given amount (either a register, or a
// literal value) // literal value)
Self::ShiftLeft(a) => { Self::ShiftLeft(a) => {
let reg = cpu.get(a.sr1)?; *cpu.reg(a.dr)? = shl(cpu.get(a.sr1)?, a.shamt + cpu.get(a.sr2)? as u8);
let val = a.shamt;
*cpu.reg(a.sr1)? = shl(reg, val);
} }
// Right shifts the value in Reg by the given amount (either a register, or a // Right shifts the value in Reg by the given amount (either a register, or a
// literal value). // literal value).
Self::ShiftRight(a) => { Self::ShiftRight(a) => {
let regval = cpu.get(a.sr1)?; *cpu.reg(a.dr)? = shr(cpu.get(a.sr1)?, a.shamt + cpu.get(a.sr2)? as u8);
let val = a.shamt;
*cpu.reg(a.sr1)? = shr(regval, val);
} }
// Adds the value of Src2 to Src1 and writes the result to a.dr // Adds the value of Src2 to Src1 and writes the result to a.dr