thumb: more const-generics :)
Former-commit-id: e869dafa68973d944be3b8d88d3238451b64718c Former-commit-id: 8118d529e7a40303e4535f581ad4cf247b926b46
This commit is contained in:
parent
9e6b787536
commit
4a7eb53707
|
@ -62,14 +62,31 @@ fn thumb_decode(i: u16) -> (&'static str, String) {
|
||||||
} else if i & 0xf200 == 0x5000 {
|
} else if i & 0xf200 == 0x5000 {
|
||||||
(
|
(
|
||||||
"LdrStrRegOffset",
|
"LdrStrRegOffset",
|
||||||
String::from("exec_thumb_ldr_str_reg_offset"),
|
format!(
|
||||||
|
"exec_thumb_ldr_str_reg_offset::<{LOAD}, {RO}, {BYTE}>",
|
||||||
|
LOAD = i.bit(11),
|
||||||
|
RO = i.bit_range(6..9) as usize,
|
||||||
|
BYTE = i.bit(10),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
} else if i & 0xf200 == 0x5200 {
|
} else if i & 0xf200 == 0x5200 {
|
||||||
("LdrStrSHB", String::from("exec_thumb_ldr_str_shb"))
|
("LdrStrSHB", String::from("exec_thumb_ldr_str_shb"))
|
||||||
} else if i & 0xe000 == 0x6000 {
|
} else if i & 0xe000 == 0x6000 {
|
||||||
|
let is_transferring_bytes = i.bit(12);
|
||||||
|
let offset5 = i.bit_range(6..11) as u8;
|
||||||
|
let offset = if is_transferring_bytes {
|
||||||
|
offset5
|
||||||
|
} else {
|
||||||
|
(offset5 << 3) >> 1
|
||||||
|
};
|
||||||
(
|
(
|
||||||
"LdrStrImmOffset",
|
"LdrStrImmOffset",
|
||||||
String::from("exec_thumb_ldr_str_imm_offset"),
|
format!(
|
||||||
|
"exec_thumb_ldr_str_imm_offset::<{LOAD}, {BYTE}, {OFFSET}>",
|
||||||
|
LOAD = i.bit(11),
|
||||||
|
BYTE = is_transferring_bytes,
|
||||||
|
OFFSET = offset
|
||||||
|
),
|
||||||
)
|
)
|
||||||
} else if i & 0xf000 == 0x8000 {
|
} else if i & 0xf000 == 0x8000 {
|
||||||
(
|
(
|
||||||
|
|
|
@ -212,16 +212,14 @@ impl<I: MemoryInterface> Core<I> {
|
||||||
|
|
||||||
/// Helper function for various ldr/str handler
|
/// Helper function for various ldr/str handler
|
||||||
/// Execution Time: 1S+1N+1I for LDR, or 2N for STR
|
/// Execution Time: 1S+1N+1I for LDR, or 2N for STR
|
||||||
fn do_exec_thumb_ldr_str(
|
fn do_exec_thumb_ldr_str<const LOAD: bool, const BYTE: bool>(
|
||||||
&mut self,
|
&mut self,
|
||||||
insn: u16,
|
insn: u16,
|
||||||
|
|
||||||
addr: Addr,
|
addr: Addr,
|
||||||
is_transferring_bytes: bool,
|
|
||||||
) -> CpuAction {
|
) -> CpuAction {
|
||||||
let rd = (insn & 0b111) as usize;
|
let rd = (insn & 0b111) as usize;
|
||||||
if insn.is_load() {
|
if LOAD {
|
||||||
let data = if is_transferring_bytes {
|
let data = if BYTE {
|
||||||
self.load_8(addr, NonSeq) as u32
|
self.load_8(addr, NonSeq) as u32
|
||||||
} else {
|
} else {
|
||||||
self.ldr_word(addr, NonSeq)
|
self.ldr_word(addr, NonSeq)
|
||||||
|
@ -234,7 +232,7 @@ impl<I: MemoryInterface> Core<I> {
|
||||||
CpuAction::AdvancePC(Seq)
|
CpuAction::AdvancePC(Seq)
|
||||||
} else {
|
} else {
|
||||||
let value = self.get_reg(rd);
|
let value = self.get_reg(rd);
|
||||||
if is_transferring_bytes {
|
if BYTE {
|
||||||
self.store_8(addr, value as u8, NonSeq);
|
self.store_8(addr, value as u8, NonSeq);
|
||||||
} else {
|
} else {
|
||||||
self.store_aligned_32(addr, value, NonSeq);
|
self.store_aligned_32(addr, value, NonSeq);
|
||||||
|
@ -245,10 +243,17 @@ impl<I: MemoryInterface> Core<I> {
|
||||||
|
|
||||||
/// Format 7 load/store with register offset
|
/// Format 7 load/store with register offset
|
||||||
/// Execution Time: 1S+1N+1I for LDR, or 2N for STR
|
/// Execution Time: 1S+1N+1I for LDR, or 2N for STR
|
||||||
pub(in super::super) fn exec_thumb_ldr_str_reg_offset(&mut self, insn: u16) -> CpuAction {
|
pub(in super::super) fn exec_thumb_ldr_str_reg_offset<
|
||||||
|
const LOAD: bool,
|
||||||
|
const RO: usize,
|
||||||
|
const BYTE: bool,
|
||||||
|
>(
|
||||||
|
&mut self,
|
||||||
|
insn: u16,
|
||||||
|
) -> CpuAction {
|
||||||
let rb = insn.bit_range(3..6) as usize;
|
let rb = insn.bit_range(3..6) as usize;
|
||||||
let addr = self.gpr[rb].wrapping_add(self.gpr[insn.ro()]);
|
let addr = self.gpr[rb].wrapping_add(self.gpr[RO]);
|
||||||
self.do_exec_thumb_ldr_str(insn, addr, insn.bit(10))
|
self.do_exec_thumb_ldr_str::<LOAD, BYTE>(insn, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Format 8 load/store sign-extended byte/halfword
|
/// Format 8 load/store sign-extended byte/halfword
|
||||||
|
@ -294,16 +299,17 @@ impl<I: MemoryInterface> Core<I> {
|
||||||
|
|
||||||
/// Format 9
|
/// Format 9
|
||||||
/// Execution Time: 1S+1N+1I for LDR, or 2N for STR
|
/// Execution Time: 1S+1N+1I for LDR, or 2N for STR
|
||||||
pub(in super::super) fn exec_thumb_ldr_str_imm_offset(&mut self, insn: u16) -> CpuAction {
|
pub(in super::super) fn exec_thumb_ldr_str_imm_offset<
|
||||||
|
const LOAD: bool,
|
||||||
|
const BYTE: bool,
|
||||||
|
const OFFSET: u8,
|
||||||
|
>(
|
||||||
|
&mut self,
|
||||||
|
insn: u16,
|
||||||
|
) -> CpuAction {
|
||||||
let rb = insn.bit_range(3..6) as usize;
|
let rb = insn.bit_range(3..6) as usize;
|
||||||
|
let addr = self.gpr[rb].wrapping_add(OFFSET as u32);
|
||||||
let offset = if insn.bit(12) {
|
self.do_exec_thumb_ldr_str::<LOAD, BYTE>(insn, addr)
|
||||||
insn.offset5()
|
|
||||||
} else {
|
|
||||||
(insn.offset5() << 3) >> 1
|
|
||||||
};
|
|
||||||
let addr = self.gpr[rb].wrapping_add(offset as u32);
|
|
||||||
self.do_exec_thumb_ldr_str(insn, addr, insn.bit(12))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Format 10
|
/// Format 10
|
||||||
|
|
Reference in a new issue