From 416cc2937b0bbe249cbaa5c0bbc6df46c5c249c0 Mon Sep 17 00:00:00 2001 From: Michel Heily Date: Sat, 3 Jul 2021 21:37:53 +0300 Subject: [PATCH] arm: do const-generics for HalfwordDataTransfer* Former-commit-id: 891fd23bef3a4ecc7fe5a4012456d51fc91f8601 Former-commit-id: 431ac09cbf73078988d6400c6320a7fdadceef1a --- core/build.rs | 30 +++++++++++-- core/src/arm7tdmi/arm/exec.rs | 83 +++++++++++++++++++++-------------- core/src/arm7tdmi/cpu.rs | 2 +- 3 files changed, 76 insertions(+), 39 deletions(-) diff --git a/core/build.rs b/core/build.rs index d7a5b87..2ec3479 100644 --- a/core/build.rs +++ b/core/build.rs @@ -272,10 +272,32 @@ fn arm_decode(i: u32) -> (&'static str, String) { _ => None, }; - result.unwrap_or_else(|| { + if let Some(result) = result { + result + } else { match (i.ibit(25), i.ibit(22), i.ibit(7), i.ibit(4)) { - (0, 0, 1, 1) => ("HalfwordDataTransferRegOffset", String::from("exec_arm_ldr_str_hs_reg")), - (0, 1, 1, 1) => ("HalfwordDataTransferImmediateOffset", String::from("exec_arm_ldr_str_hs_imm")), + (0, 0, 1, 1) => ( + "HalfwordDataTransferRegOffset", + format!( + "exec_arm_ldr_str_hs_reg::<{HS}, {LOAD}, {WRITEBACK}, {PRE_INDEX}, {ADD}>", + HS = (i & 0b1100000) >> 5, + LOAD = i.bit(20), + WRITEBACK = i.bit(21), + ADD = i.bit(23), + PRE_INDEX = i.bit(24), + ), + ), + (0, 1, 1, 1) => ( + "HalfwordDataTransferImmediateOffset", + format!( + "exec_arm_ldr_str_hs_imm::<{HS}, {LOAD}, {WRITEBACK}, {PRE_INDEX}, {ADD}>", + HS = (i & 0b1100000) >> 5, + LOAD = i.bit(20), + WRITEBACK = i.bit(21), + ADD = i.bit(23), + PRE_INDEX = i.bit(24) + ), + ), _ => { let set_cond_flags = i.bit(20); // PSR Transfers are encoded as a subset of Data Processing, @@ -297,7 +319,7 @@ fn arm_decode(i: u32) -> (&'static str, String) { } } } - }) + } } 0b01 => { match (i.bit(25), i.bit(4)) { diff --git a/core/src/arm7tdmi/arm/exec.rs b/core/src/arm7tdmi/arm/exec.rs index 5ca683d..e168b1c 100644 --- a/core/src/arm7tdmi/arm/exec.rs +++ b/core/src/arm7tdmi/arm/exec.rs @@ -373,36 +373,53 @@ impl Core { result } - pub fn exec_arm_ldr_str_hs_reg(&mut self, insn: u32) -> CpuAction { - let offset = { - let added = insn.add_offset_flag(); - let abs = self.get_reg((insn & 0xf) as usize); - if added { - abs as u32 - } else { - (-(abs as i32)) as u32 - } - }; - self.ldr_str_hs_common(insn, offset) + pub fn exec_arm_ldr_str_hs_reg< + const HS: u8, + const LOAD: bool, + const WRITEBACK: bool, + const PRE_INDEX: bool, + const ADD: bool, + >( + &mut self, + insn: u32, + ) -> CpuAction { + let offset = self.get_reg((insn & 0xf) as usize); + self.ldr_str_hs_common::(insn, offset) } - pub fn exec_arm_ldr_str_hs_imm(&mut self, insn: u32) -> CpuAction { + pub fn exec_arm_ldr_str_hs_imm< + const HS: u8, + const LOAD: bool, + const WRITEBACK: bool, + const PRE_INDEX: bool, + const ADD: bool, + >( + &mut self, + insn: u32, + ) -> CpuAction { let offset8 = (insn.bit_range(8..12) << 4) + insn.bit_range(0..4); - let offset8 = if insn.add_offset_flag() { - offset8 - } else { - (-(offset8 as i32)) as u32 - }; - self.ldr_str_hs_common(insn, offset8) + self.ldr_str_hs_common::(insn, offset8) } #[inline(always)] - pub fn ldr_str_hs_common(&mut self, insn: u32, offset: u32) -> CpuAction { + pub fn ldr_str_hs_common< + const HS: u8, + const LOAD: bool, + const WRITEBACK: bool, + const PRE_INDEX: bool, + const ADD: bool, + >( + &mut self, + insn: u32, + offset: u32, + ) -> CpuAction { let mut result = CpuAction::AdvancePC(NonSeq); - let load = insn.load_flag(); - let pre_index = insn.pre_index_flag(); - let writeback = insn.write_back_flag(); + let offset = if ADD { + offset + } else { + (-(offset as i32)) as u32 + }; let base_reg = insn.bit_range(16..20) as usize; let dest_reg = insn.bit_range(12..16) as usize; let mut addr = self.get_reg(base_reg); @@ -412,19 +429,17 @@ impl Core { // TODO - confirm this let old_mode = self.cpsr.mode(); - if !pre_index && writeback { + if !PRE_INDEX && WRITEBACK { self.change_mode(old_mode, CpuMode::User); } let effective_addr = (addr as i32).wrapping_add(offset as i32) as Addr; - addr = if insn.pre_index_flag() { - effective_addr - } else { - addr - }; + addr = if PRE_INDEX { effective_addr } else { addr }; - if load { - let data = match insn.halfword_data_transfer_type() { + let transfer_type = ArmHalfwordTransferType::from_u8(HS).unwrap(); + + if LOAD { + let data = match transfer_type { ArmHalfwordTransferType::SignedByte => self.load_8(addr, NonSeq) as u8 as i8 as u32, ArmHalfwordTransferType::SignedHalfwords => self.ldr_sign_half(addr, NonSeq), ArmHalfwordTransferType::UnsignedHalfwords => self.ldr_half(addr, NonSeq), @@ -446,7 +461,7 @@ impl Core { self.get_reg(dest_reg) }; - match insn.halfword_data_transfer_type() { + match transfer_type { ArmHalfwordTransferType::UnsignedHalfwords => { self.store_aligned_16(addr, value as u16, NonSeq); } @@ -454,10 +469,10 @@ impl Core { }; } - if !load || base_reg != dest_reg { - if !pre_index { + if !LOAD || base_reg != dest_reg { + if !PRE_INDEX { self.set_reg(base_reg, effective_addr); - } else if insn.write_back_flag() { + } else if WRITEBACK { self.set_reg(base_reg, effective_addr); } } diff --git a/core/src/arm7tdmi/cpu.rs b/core/src/arm7tdmi/cpu.rs index 76b1b07..0d95bcb 100644 --- a/core/src/arm7tdmi/cpu.rs +++ b/core/src/arm7tdmi/cpu.rs @@ -367,7 +367,7 @@ impl Core { cfg_if! { if #[cfg(feature = "arm7tdmi_dispatch_table")] { fn step_arm_exec(&mut self, insn: u32) -> CpuAction { - let hash = (((insn >> 16) & 0xff0) | ((insn >> 4) & 0x00f)) as usize; + let hash = (((insn >> 16) & 0xff0) | ((insn >> 4) & 0xf)) as usize; let arm_info = &Self::ARM_LUT[hash]; #[cfg(feature = "debugger")] self.debugger_record_step(DecodedInstruction::Arm(ArmInstruction::new(