diff --git a/assembler/src/assembler/codegen.rs b/assembler/src/assembler/codegen.rs index 4d85ffc..a95c093 100644 --- a/assembler/src/assembler/codegen.rs +++ b/assembler/src/assembler/codegen.rs @@ -223,19 +223,31 @@ fn build_shift_instruction( opcode: Opcode, args: &[crate::assembler::model::Token], ) -> Result { - let Some(reg_token) = args.first() else { + let Some(src_reg) = args.first() else { 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)); }; - let reg = expect_token!(reg_token, Register)?; - let amount = expect_token!(amount_token, Immediate)? as u8; + let src = expect_token!(src_reg, Register)?; + 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 { - Opcode::Shl => Ok(Instruction::ShiftLeft(args!(R, sr1: reg, shamt: amount))), - Opcode::Shr => Ok(Instruction::ShiftRight(args!(R, sr1: reg, shamt: amount))), + Opcode::Shl => Ok(Instruction::ShiftLeft( + 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!(), } } diff --git a/assembler/src/assembler/parser.rs b/assembler/src/assembler/parser.rs index 7ac26b2..d8d50a5 100644 --- a/assembler/src/assembler/parser.rs +++ b/assembler/src/assembler/parser.rs @@ -1,5 +1,6 @@ use std::path::{Path, PathBuf}; +use crate::assembler::TokenType; use crate::{assembler::AssembleError, expect_token, expect_type, node}; use crate::assembler::model::{Node, Opcode, Token}; @@ -114,9 +115,10 @@ impl Parser { let mut offset = Token::Immediate(0); if let Ok(next) = self.peek_next() - && expect_type!(next, Immediate).is_ok() { - offset = self.next()?; - } + && expect_type!(next, Immediate).is_ok() + { + offset = self.next()?; + } args = vec![base, dest, offset]; } @@ -125,9 +127,10 @@ impl Parser { let dest = expect_type!(self.next()?, Register, Symbol)?; let mut offset = Token::Immediate(0); if let Ok(next) = self.peek_next() - && expect_type!(next, Immediate).is_ok() { - offset = self.next()?; - } + && expect_type!(next, Immediate).is_ok() + { + offset = self.next()?; + } args = vec![base, dest, offset]; } @@ -146,15 +149,49 @@ impl Parser { } Opcode::Not | Opcode::Cmp => { - let reg1 = expect_type!(self.next()?, Register, Symbol)?; - let reg2 = expect_type!(self.next()?, Register, Symbol)?; - args = vec![reg1, reg2]; + let src = expect_type!(self.next()?, Register, Symbol)?; + let dest = expect_type!(self.next()?, Register, Symbol)?; + args = vec![src, dest]; } - Opcode::Shl | Opcode::Shr => { - let reg = expect_type!(self.next()?, Register, Symbol)?; - let num = expect_type!(self.next()?, Immediate)?; - args = vec![reg, num]; + let src = expect_type!(self.next()?, Register, Symbol)?; + + // 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 => { diff --git a/emulator/src/emulator/system/model.rs b/emulator/src/emulator/system/model.rs index 2d49a94..5df1891 100644 --- a/emulator/src/emulator/system/model.rs +++ b/emulator/src/emulator/system/model.rs @@ -286,7 +286,7 @@ impl RegFile { Register::Sts => &mut self.sts, Register::Cir => &mut self.cir, 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::Pcx => self.pcx, Register::Zero => 0, - _ => return Err(ProcessorError::InvalidRegister(Register::NoReg as u8)), + _ => return Err(ProcessorError::InvalidRegister(Register::Null as u8)), }) } } diff --git a/emulator/src/emulator/system/processor/mod.rs b/emulator/src/emulator/system/processor/mod.rs index d48b80d..fb50926 100644 --- a/emulator/src/emulator/system/processor/mod.rs +++ b/emulator/src/emulator/system/processor/mod.rs @@ -349,17 +349,13 @@ impl Executable for Instruction { // Left shifts the value in Reg by the given amount (either a register, or a // literal value) Self::ShiftLeft(a) => { - let reg = cpu.get(a.sr1)?; - let val = a.shamt; - *cpu.reg(a.sr1)? = shl(reg, val); + *cpu.reg(a.dr)? = shl(cpu.get(a.sr1)?, a.shamt + cpu.get(a.sr2)? as u8); } // Right shifts the value in Reg by the given amount (either a register, or a // literal value). Self::ShiftRight(a) => { - let regval = cpu.get(a.sr1)?; - let val = a.shamt; - *cpu.reg(a.sr1)? = shr(regval, val); + *cpu.reg(a.dr)? = shr(cpu.get(a.sr1)?, a.shamt + cpu.get(a.sr2)? as u8); } // Adds the value of Src2 to Src1 and writes the result to a.dr