From a47cb18cda2217e9f340c1ea7dc5d00eb35b8f2e Mon Sep 17 00:00:00 2001 From: Michel Heily Date: Sat, 18 Jan 2020 22:47:31 +0200 Subject: [PATCH] core/arm7tdmi/arm/: Fix wrong calculation of op1 in DATA_PROCESSING instruction when RN==R15 The docs state: "If a register is used to specify the shift amount the PC will be 12 bytes ahead" I probably misread that when implementing DataProcessing instructions, and because of that added 4 bytes to (op1+8) when shift amount was specified by a rotated immediate. Fixes #6 (and probably tons of other bugs too!) Former-commit-id: 129f0951a6381221314c23a468c3da8b31435a30 --- README.md | 2 +- src/core/arm7tdmi/alu.rs | 17 +++++++++++++---- src/core/arm7tdmi/arm/exec.rs | 4 ++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index aa5c427..7fc135d 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ No issues so far Won't boot unless binary patched to remove a loop querying the flash chip ### Dragon Ball - Legacy of Goku 2 -crashes when entering in-game menu, other than that works fine. +~~crashes when entering in-game menu, other than that works fine.~~ ## Screenshots diff --git a/src/core/arm7tdmi/alu.rs b/src/core/arm7tdmi/alu.rs index 67d7e13..09677d8 100644 --- a/src/core/arm7tdmi/alu.rs +++ b/src/core/arm7tdmi/alu.rs @@ -47,7 +47,7 @@ impl AluOpCode { } } -#[derive(Debug, PartialEq, Primitive)] +#[derive(Debug, PartialEq, Primitive, Copy, Clone)] pub enum BarrelShiftOpCode { LSL = 0, LSR = 1, @@ -55,13 +55,13 @@ pub enum BarrelShiftOpCode { ROR = 3, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Copy, Clone)] pub enum ShiftRegisterBy { ByAmount(u32), ByRegister(usize), } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Copy, Clone)] pub struct ShiftedRegister { pub reg: usize, pub shift_by: ShiftRegisterBy, @@ -69,7 +69,16 @@ pub struct ShiftedRegister { pub added: Option, } -#[derive(Debug, PartialEq)] +impl ShiftedRegister { + pub fn is_shifted_by_reg(&self) -> bool { + match self.shift_by { + ShiftRegisterBy::ByRegister(_) => true, + _ => false + } + } +} + +#[derive(Debug, PartialEq, Copy, Clone)] pub enum BarrelShifterValue { ImmediateValue(u32), RotatedImmediate(u32, u32), diff --git a/src/core/arm7tdmi/arm/exec.rs b/src/core/arm7tdmi/arm/exec.rs index baca483..729053d 100644 --- a/src/core/arm7tdmi/arm/exec.rs +++ b/src/core/arm7tdmi/arm/exec.rs @@ -183,8 +183,8 @@ impl Core { let op2 = insn.operand2()?; match op2 { - BarrelShifterValue::ShiftedRegister(_) => { - if insn.rn() == REG_PC { + BarrelShifterValue::ShiftedRegister(shifted_reg) => { + if insn.rn() == REG_PC && shifted_reg.is_shifted_by_reg() { op1 += 4; } }