From ecdd6e0ed47575995dd9c26235f693ac881a8688 Mon Sep 17 00:00:00 2001 From: Michel Heily Date: Mon, 8 Jul 2019 01:47:41 +0300 Subject: [PATCH] thumb: Fix ALU ops for barrel shifter opcodes I kinda missed these when I read the manual >< Former-commit-id: 7d6c21b6c3b46bf065a177c1c7f7a7a1baa6b8fa --- src/arm7tdmi/thumb/display.rs | 9 +++++++-- src/arm7tdmi/thumb/exec.rs | 18 +++++++++++++----- src/arm7tdmi/thumb/mod.rs | 34 +++++++++++++++++++++++++++++++--- 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/arm7tdmi/thumb/display.rs b/src/arm7tdmi/thumb/display.rs index 7deff87..7a1d529 100644 --- a/src/arm7tdmi/thumb/display.rs +++ b/src/arm7tdmi/thumb/display.rs @@ -37,10 +37,15 @@ impl ThumbInstruction { } fn fmt_thumb_alu_ops(&self, f: &mut fmt::Formatter) -> fmt::Result { + let (op, shft) = self.alu_opcode(); + if let Some(ArmRegisterShift::ShiftRegister(_, shftOp)) = shft { + write!(f, "{}", shftOp)?; + } else { + write!(f, "{}", op)?; + } write!( f, - "{op}\t{Rd}, {Rs}", - op = self.alu_opcode(), + "\t{Rd}, {Rs}", Rd = reg_string(self.rd()), Rs = reg_string(self.rs()) ) diff --git a/src/arm7tdmi/thumb/exec.rs b/src/arm7tdmi/thumb/exec.rs index bec4dbb..65bfb16 100644 --- a/src/arm7tdmi/thumb/exec.rs +++ b/src/arm7tdmi/thumb/exec.rs @@ -1,4 +1,4 @@ -use crate::arm7tdmi::arm::*; +use crate::arm7tdmi::arm::exec::*; use crate::arm7tdmi::bus::Bus; use crate::arm7tdmi::cpu::{Core, CpuExecResult, CpuPipelineAction}; use crate::arm7tdmi::*; @@ -82,12 +82,20 @@ impl Core { } fn exec_thumb_alu_ops(&mut self, _bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult { - let arm_alu_op: ArmOpCode = insn.alu_opcode(); - let op1 = self.get_reg(insn.rd()) as i32; - let op2 = self.get_reg(insn.rs()) as i32; + let rd = insn.rd(); + + let (arm_alu_op, shft) = insn.alu_opcode(); + let op1 = self.get_reg(rd) as i32; + let op2 = if let Some(shft) = shft { + let bs_result = self.register_shift(rd, shft)?; + bs_result + } else { + self.get_reg(insn.rs()) as i32 + }; + let result = self.alu(arm_alu_op, op1, op2, true); if let Some(result) = result { - self.set_reg(insn.rd(), result as u32); + self.set_reg(rd, result as u32); } Ok(CpuPipelineAction::IncPC) diff --git a/src/arm7tdmi/thumb/mod.rs b/src/arm7tdmi/thumb/mod.rs index ea40faa..c4e84e5 100644 --- a/src/arm7tdmi/thumb/mod.rs +++ b/src/arm7tdmi/thumb/mod.rs @@ -4,7 +4,7 @@ use crate::bit::BitIndex; use crate::byteorder::{LittleEndian, ReadBytesExt}; use crate::num::FromPrimitive; -use super::arm::{ArmCond, ArmOpCode, ArmShiftType}; +use super::arm::*; use super::{Addr, InstructionDecoder, InstructionDecoderError}; pub mod display; @@ -241,10 +241,38 @@ impl ThumbInstruction { OpFormat5::from_u8(self.raw.bit_range(8..10) as u8).unwrap() } - pub fn alu_opcode(&self) -> ArmOpCode { + pub fn alu_opcode(&self) -> (ArmOpCode, Option) { match self.raw.bit_range(6..10) { + 0b0010 => ( + ArmOpCode::MOV, + Some(ArmRegisterShift::ShiftRegister( + self.rs(), + ArmShiftType::LSL, + )), + ), + 0b0011 => ( + ArmOpCode::MOV, + Some(ArmRegisterShift::ShiftRegister( + self.rs(), + ArmShiftType::LSR, + )), + ), + 0b0100 => ( + ArmOpCode::MOV, + Some(ArmRegisterShift::ShiftRegister( + self.rs(), + ArmShiftType::ASR, + )), + ), + 0b0111 => ( + ArmOpCode::MOV, + Some(ArmRegisterShift::ShiftRegister( + self.rs(), + ArmShiftType::ROR, + )), + ), 0b1101 => panic!("tried to decode MUL"), - op => ArmOpCode::from_u16(op).unwrap(), + op => (ArmOpCode::from_u16(op).unwrap(), None), } }