From 65de0c4e9d67b2a681925b45c8c56643c0456135 Mon Sep 17 00:00:00 2001 From: Michel Heily Date: Tue, 9 Jul 2019 01:30:24 +0300 Subject: [PATCH] Thumb 4 - Take care of "neg" case. I overlooked it :/ Former-commit-id: 360eb755bcf343cddd98807e9faeff007c94cf64 --- src/arm7tdmi/alu.rs | 22 ++++++++++++++++++- src/arm7tdmi/arm/exec.rs | 24 ++------------------- src/arm7tdmi/thumb/display.rs | 9 +++++++- src/arm7tdmi/thumb/exec.rs | 3 +-- src/arm7tdmi/thumb/mod.rs | 40 ++++++++++++++++++++--------------- 5 files changed, 55 insertions(+), 43 deletions(-) diff --git a/src/arm7tdmi/alu.rs b/src/arm7tdmi/alu.rs index b71f80b..39ac008 100644 --- a/src/arm7tdmi/alu.rs +++ b/src/arm7tdmi/alu.rs @@ -3,7 +3,7 @@ use num::FromPrimitive; use super::{Core, CpuError, CpuResult, REG_PC}; -#[derive(Debug, Primitive)] +#[derive(Debug, Primitive, PartialEq)] pub enum AluOpCode { AND = 0b0000, EOR = 0b0001, @@ -229,6 +229,26 @@ impl Core { } } + pub fn get_barrel_shifted_value(&mut self, sval: BarrelShifterValue) -> i32 { + // TODO decide if error handling or panic here + match sval { + BarrelShifterValue::ImmediateValue(offset) => offset, + BarrelShifterValue::ShiftedRegister { + reg, + shift, + added: Some(added), + } => { + let abs = self.register_shift(reg, shift).unwrap(); + if added { + abs + } else { + -abs + } + } + _ => panic!("bad barrel shift"), + } + } + fn alu_sub_flags(a: i32, b: i32, carry: &mut bool, overflow: &mut bool) -> i32 { let res = a.wrapping_sub(b); *carry = b <= a; diff --git a/src/arm7tdmi/arm/exec.rs b/src/arm7tdmi/arm/exec.rs index 01c47d7..797d88f 100644 --- a/src/arm7tdmi/arm/exec.rs +++ b/src/arm7tdmi/arm/exec.rs @@ -135,26 +135,6 @@ impl Core { Ok(pipeline_action) } - fn get_rn_offset(&mut self, sval: BarrelShifterValue) -> i32 { - // TODO decide if error handling or panic here - match sval { - BarrelShifterValue::ImmediateValue(offset) => offset, - BarrelShifterValue::ShiftedRegister { - reg, - shift, - added: Some(added), - } => { - let abs = self.register_shift(reg, shift).unwrap(); - if added { - abs - } else { - -abs - } - } - _ => panic!("bad barrel shift"), - } - } - /// Memory Load/Store /// Instruction | Cycles | Flags | Expl. /// ------------------------------------------------------------------------------ @@ -178,7 +158,7 @@ impl Core { addr = insn.pc + 8; // prefetching } - let offset = self.get_rn_offset(insn.ldr_str_offset()); + let offset = self.get_barrel_shifted_value(insn.ldr_str_offset()); let effective_addr = (addr as i32).wrapping_add(offset) as Addr; addr = if insn.pre_index_flag() { @@ -238,7 +218,7 @@ impl Core { addr = insn.pc + 8; // prefetching } - let offset = self.get_rn_offset(insn.ldr_str_hs_offset().unwrap()); + let offset = self.get_barrel_shifted_value(insn.ldr_str_hs_offset().unwrap()); let effective_addr = (addr as i32).wrapping_add(offset) as Addr; addr = if insn.pre_index_flag() { diff --git a/src/arm7tdmi/thumb/display.rs b/src/arm7tdmi/thumb/display.rs index 45c2473..f3164e9 100644 --- a/src/arm7tdmi/thumb/display.rs +++ b/src/arm7tdmi/thumb/display.rs @@ -37,9 +37,16 @@ impl ThumbInstruction { } fn fmt_thumb_alu_ops(&self, f: &mut fmt::Formatter) -> fmt::Result { + use ShiftedRegister::ByRegister; let (op, shft) = self.alu_opcode(); - if let Some(ShiftedRegister::ByRegister(_, op)) = shft { + if let Some(BarrelShifterValue::ShiftedRegister { + shift: ByRegister(_, op), + .. + }) = shft + { write!(f, "{}", op)?; + } else if op == AluOpCode::RSB { + write!(f, "neg")?; } else { write!(f, "{}", op)?; } diff --git a/src/arm7tdmi/thumb/exec.rs b/src/arm7tdmi/thumb/exec.rs index 6c4f999..9727f0b 100644 --- a/src/arm7tdmi/thumb/exec.rs +++ b/src/arm7tdmi/thumb/exec.rs @@ -92,8 +92,7 @@ impl Core { 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 + self.get_barrel_shifted_value(shft) } else { self.get_reg(insn.rs()) as i32 }; diff --git a/src/arm7tdmi/thumb/mod.rs b/src/arm7tdmi/thumb/mod.rs index 277417e..84ff609 100644 --- a/src/arm7tdmi/thumb/mod.rs +++ b/src/arm7tdmi/thumb/mod.rs @@ -242,36 +242,42 @@ impl ThumbInstruction { OpFormat5::from_u8(self.raw.bit_range(8..10) as u8).unwrap() } - pub fn alu_opcode(&self) -> (AluOpCode, Option) { + pub fn alu_opcode(&self) -> (AluOpCode, Option) { + use ShiftedRegister::*; match self.raw.bit_range(6..10) { 0b0010 => ( AluOpCode::MOV, - Some(ShiftedRegister::ByRegister( - self.rs(), - BarrelShiftOpCode::LSL, - )), + Some(BarrelShifterValue::ShiftedRegister { + reg: self.rd(), + shift: ByRegister(self.rs(), BarrelShiftOpCode::LSL), + added: Some(true), + }), ), 0b0011 => ( AluOpCode::MOV, - Some(ShiftedRegister::ByRegister( - self.rs(), - BarrelShiftOpCode::LSR, - )), + Some(BarrelShifterValue::ShiftedRegister { + reg: self.rd(), + shift: ByRegister(self.rs(), BarrelShiftOpCode::LSR), + added: Some(true), + }), ), 0b0100 => ( AluOpCode::MOV, - Some(ShiftedRegister::ByRegister( - self.rs(), - BarrelShiftOpCode::ASR, - )), + Some(BarrelShifterValue::ShiftedRegister { + reg: self.rd(), + shift: ByRegister(self.rs(), BarrelShiftOpCode::ASR), + added: Some(true), + }), ), 0b0111 => ( AluOpCode::MOV, - Some(ShiftedRegister::ByRegister( - self.rs(), - BarrelShiftOpCode::ROR, - )), + Some(BarrelShifterValue::ShiftedRegister { + reg: self.rd(), + shift: ByRegister(self.rs(), BarrelShiftOpCode::ROR), + added: Some(true), + }), ), + 0b1001 => (AluOpCode::RSB, Some(BarrelShifterValue::ImmediateValue(0))), 0b1101 => panic!("tried to decode MUL"), op => (AluOpCode::from_u16(op).unwrap(), None), }