arm: do const-generics for HalfwordDataTransfer*
Former-commit-id: 891fd23bef3a4ecc7fe5a4012456d51fc91f8601 Former-commit-id: 431ac09cbf73078988d6400c6320a7fdadceef1a
This commit is contained in:
parent
9819bf611d
commit
416cc2937b
|
@ -272,10 +272,32 @@ fn arm_decode(i: u32) -> (&'static str, String) {
|
||||||
_ => None,
|
_ => 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)) {
|
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, 0, 1, 1) => (
|
||||||
(0, 1, 1, 1) => ("HalfwordDataTransferImmediateOffset", String::from("exec_arm_ldr_str_hs_imm")),
|
"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);
|
let set_cond_flags = i.bit(20);
|
||||||
// PSR Transfers are encoded as a subset of Data Processing,
|
// PSR Transfers are encoded as a subset of Data Processing,
|
||||||
|
@ -297,7 +319,7 @@ fn arm_decode(i: u32) -> (&'static str, String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
0b01 => {
|
0b01 => {
|
||||||
match (i.bit(25), i.bit(4)) {
|
match (i.bit(25), i.bit(4)) {
|
||||||
|
|
|
@ -373,36 +373,53 @@ impl<I: MemoryInterface> Core<I> {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exec_arm_ldr_str_hs_reg(&mut self, insn: u32) -> CpuAction {
|
pub fn exec_arm_ldr_str_hs_reg<
|
||||||
let offset = {
|
const HS: u8,
|
||||||
let added = insn.add_offset_flag();
|
const LOAD: bool,
|
||||||
let abs = self.get_reg((insn & 0xf) as usize);
|
const WRITEBACK: bool,
|
||||||
if added {
|
const PRE_INDEX: bool,
|
||||||
abs as u32
|
const ADD: bool,
|
||||||
} else {
|
>(
|
||||||
(-(abs as i32)) as u32
|
&mut self,
|
||||||
}
|
insn: u32,
|
||||||
};
|
) -> CpuAction {
|
||||||
self.ldr_str_hs_common(insn, offset)
|
let offset = self.get_reg((insn & 0xf) as usize);
|
||||||
|
self.ldr_str_hs_common::<HS, LOAD, WRITEBACK, PRE_INDEX, ADD>(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 = (insn.bit_range(8..12) << 4) + insn.bit_range(0..4);
|
||||||
let offset8 = if insn.add_offset_flag() {
|
self.ldr_str_hs_common::<HS, LOAD, WRITEBACK, PRE_INDEX, ADD>(insn, offset8)
|
||||||
offset8
|
|
||||||
} else {
|
|
||||||
(-(offset8 as i32)) as u32
|
|
||||||
};
|
|
||||||
self.ldr_str_hs_common(insn, offset8)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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 mut result = CpuAction::AdvancePC(NonSeq);
|
||||||
|
|
||||||
let load = insn.load_flag();
|
let offset = if ADD {
|
||||||
let pre_index = insn.pre_index_flag();
|
offset
|
||||||
let writeback = insn.write_back_flag();
|
} else {
|
||||||
|
(-(offset as i32)) as u32
|
||||||
|
};
|
||||||
let base_reg = insn.bit_range(16..20) as usize;
|
let base_reg = insn.bit_range(16..20) as usize;
|
||||||
let dest_reg = insn.bit_range(12..16) as usize;
|
let dest_reg = insn.bit_range(12..16) as usize;
|
||||||
let mut addr = self.get_reg(base_reg);
|
let mut addr = self.get_reg(base_reg);
|
||||||
|
@ -412,19 +429,17 @@ impl<I: MemoryInterface> Core<I> {
|
||||||
|
|
||||||
// TODO - confirm this
|
// TODO - confirm this
|
||||||
let old_mode = self.cpsr.mode();
|
let old_mode = self.cpsr.mode();
|
||||||
if !pre_index && writeback {
|
if !PRE_INDEX && WRITEBACK {
|
||||||
self.change_mode(old_mode, CpuMode::User);
|
self.change_mode(old_mode, CpuMode::User);
|
||||||
}
|
}
|
||||||
|
|
||||||
let effective_addr = (addr as i32).wrapping_add(offset as i32) as Addr;
|
let effective_addr = (addr as i32).wrapping_add(offset as i32) as Addr;
|
||||||
addr = if insn.pre_index_flag() {
|
addr = if PRE_INDEX { effective_addr } else { addr };
|
||||||
effective_addr
|
|
||||||
} else {
|
|
||||||
addr
|
|
||||||
};
|
|
||||||
|
|
||||||
if load {
|
let transfer_type = ArmHalfwordTransferType::from_u8(HS).unwrap();
|
||||||
let data = match insn.halfword_data_transfer_type() {
|
|
||||||
|
if LOAD {
|
||||||
|
let data = match transfer_type {
|
||||||
ArmHalfwordTransferType::SignedByte => self.load_8(addr, NonSeq) as u8 as i8 as u32,
|
ArmHalfwordTransferType::SignedByte => self.load_8(addr, NonSeq) as u8 as i8 as u32,
|
||||||
ArmHalfwordTransferType::SignedHalfwords => self.ldr_sign_half(addr, NonSeq),
|
ArmHalfwordTransferType::SignedHalfwords => self.ldr_sign_half(addr, NonSeq),
|
||||||
ArmHalfwordTransferType::UnsignedHalfwords => self.ldr_half(addr, NonSeq),
|
ArmHalfwordTransferType::UnsignedHalfwords => self.ldr_half(addr, NonSeq),
|
||||||
|
@ -446,7 +461,7 @@ impl<I: MemoryInterface> Core<I> {
|
||||||
self.get_reg(dest_reg)
|
self.get_reg(dest_reg)
|
||||||
};
|
};
|
||||||
|
|
||||||
match insn.halfword_data_transfer_type() {
|
match transfer_type {
|
||||||
ArmHalfwordTransferType::UnsignedHalfwords => {
|
ArmHalfwordTransferType::UnsignedHalfwords => {
|
||||||
self.store_aligned_16(addr, value as u16, NonSeq);
|
self.store_aligned_16(addr, value as u16, NonSeq);
|
||||||
}
|
}
|
||||||
|
@ -454,10 +469,10 @@ impl<I: MemoryInterface> Core<I> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if !load || base_reg != dest_reg {
|
if !LOAD || base_reg != dest_reg {
|
||||||
if !pre_index {
|
if !PRE_INDEX {
|
||||||
self.set_reg(base_reg, effective_addr);
|
self.set_reg(base_reg, effective_addr);
|
||||||
} else if insn.write_back_flag() {
|
} else if WRITEBACK {
|
||||||
self.set_reg(base_reg, effective_addr);
|
self.set_reg(base_reg, effective_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -367,7 +367,7 @@ impl<I: MemoryInterface> Core<I> {
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature = "arm7tdmi_dispatch_table")] {
|
if #[cfg(feature = "arm7tdmi_dispatch_table")] {
|
||||||
fn step_arm_exec(&mut self, insn: u32) -> CpuAction {
|
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];
|
let arm_info = &Self::ARM_LUT[hash];
|
||||||
#[cfg(feature = "debugger")]
|
#[cfg(feature = "debugger")]
|
||||||
self.debugger_record_step(DecodedInstruction::Arm(ArmInstruction::new(
|
self.debugger_record_step(DecodedInstruction::Arm(ArmInstruction::new(
|
||||||
|
|
Reference in a new issue