arm: convert some instructions to const-generics

Former-commit-id: 493127ef64f3d5e396e0391c5bb0db985cac8945
Former-commit-id: 987edb22cd27584dfdee0a23602df45424a6f4b8
This commit is contained in:
Michel Heily 2021-07-03 21:19:11 +03:00 committed by MichelOS
parent 03d28c77b6
commit 9819bf611d
2 changed files with 42 additions and 14 deletions

View file

@ -231,15 +231,33 @@ fn arm_decode(i: u32) -> (&'static str, String) {
let result = match (i.bit_range(23..26), i.bit_range(4..8)) { let result = match (i.bit_range(23..26), i.bit_range(4..8)) {
(0b000, 0b1001) => { (0b000, 0b1001) => {
if 0b0 == i.ibit(22) { if 0b0 == i.ibit(22) {
Some(("Multiply", String::from("exec_arm_mul_mla"))) Some((
"Multiply",
format!(
"exec_arm_mul_mla::<{UPDATE_FLAGS}, {ACCUMULATE}>",
UPDATE_FLAGS = i.bit(20),
ACCUMULATE = i.bit(21),
),
))
} else { } else {
None None
} }
} }
(0b001, 0b1001) => Some(("MultiplyLong", String::from("exec_arm_mull_mlal"))), (0b001, 0b1001) => Some((
"MultiplyLong",
format!(
"exec_arm_mull_mlal::<{UPDATE_FLAGS}, {ACCUMULATE}, {U_FLAG}>",
UPDATE_FLAGS = i.bit(20),
ACCUMULATE = i.bit(21),
U_FLAG = i.bit(22),
),
)),
(0b010, 0b1001) => { (0b010, 0b1001) => {
if 0b00 == i.bit_range(20..22) { if 0b00 == i.bit_range(20..22) {
Some(("SingleDataSwap", String::from("exec_arm_swp"))) Some((
"SingleDataSwap",
format!("exec_arm_swp::<{BYTE}>", BYTE = i.bit(22)),
))
} else { } else {
None None
} }

View file

@ -620,11 +620,14 @@ impl<I: MemoryInterface> Core<I> {
/// Multiply and Multiply-Accumulate (MUL, MLA) /// Multiply and Multiply-Accumulate (MUL, MLA)
/// Execution Time: 1S+mI for MUL, and 1S+(m+1)I for MLA. /// Execution Time: 1S+mI for MUL, and 1S+(m+1)I for MLA.
pub fn exec_arm_mul_mla(&mut self, insn: u32) -> CpuAction { pub fn exec_arm_mul_mla<const UPDATE_FLAGS: bool, const ACCUMULATE: bool>(
&mut self,
insn: u32,
) -> CpuAction {
let rd = insn.bit_range(16..20) as usize; let rd = insn.bit_range(16..20) as usize;
let rn = insn.bit_range(12..16) as usize; let rn = insn.bit_range(12..16) as usize;
let rs = insn.rs(); let rs = insn.bit_range(8..12) as usize;
let rm = insn.rm(); let rm = insn.bit_range(0..4) as usize;
// // check validity // // check validity
// assert!(!(REG_PC == rd || REG_PC == rn || REG_PC == rs || REG_PC == rm)); // assert!(!(REG_PC == rd || REG_PC == rn || REG_PC == rs || REG_PC == rm));
@ -634,7 +637,7 @@ impl<I: MemoryInterface> Core<I> {
let op2 = self.get_reg(rs); let op2 = self.get_reg(rs);
let mut result = op1.wrapping_mul(op2); let mut result = op1.wrapping_mul(op2);
if insn.accumulate_flag() { if ACCUMULATE {
result = result.wrapping_add(self.get_reg(rn)); result = result.wrapping_add(self.get_reg(rn));
self.idle_cycle(); self.idle_cycle();
} }
@ -646,7 +649,7 @@ impl<I: MemoryInterface> Core<I> {
self.idle_cycle(); self.idle_cycle();
} }
if insn.set_cond_flag() { if UPDATE_FLAGS {
self.cpsr.set_N((result as i32) < 0); self.cpsr.set_N((result as i32) < 0);
self.cpsr.set_Z(result == 0); self.cpsr.set_Z(result == 0);
self.cpsr.set_C(false); self.cpsr.set_C(false);
@ -658,7 +661,14 @@ impl<I: MemoryInterface> Core<I> {
/// Multiply Long and Multiply-Accumulate Long (MULL, MLAL) /// Multiply Long and Multiply-Accumulate Long (MULL, MLAL)
/// Execution Time: 1S+(m+1)I for MULL, and 1S+(m+2)I for MLAL /// Execution Time: 1S+(m+1)I for MULL, and 1S+(m+2)I for MLAL
pub fn exec_arm_mull_mlal(&mut self, insn: u32) -> CpuAction { pub fn exec_arm_mull_mlal<
const UPDATE_FLAGS: bool,
const ACCUMULATE: bool,
const U_FLAG: bool,
>(
&mut self,
insn: u32,
) -> CpuAction {
let rd_hi = insn.rd_hi(); let rd_hi = insn.rd_hi();
let rd_lo = insn.rd_lo(); let rd_lo = insn.rd_lo();
let rs = insn.rs(); let rs = insn.rs();
@ -666,13 +676,13 @@ impl<I: MemoryInterface> Core<I> {
let op1 = self.get_reg(rm); let op1 = self.get_reg(rm);
let op2 = self.get_reg(rs); let op2 = self.get_reg(rs);
let mut result: u64 = if insn.u_flag() { let mut result: u64 = if U_FLAG {
// signed // signed
(op1 as i32 as i64).wrapping_mul(op2 as i32 as i64) as u64 (op1 as i32 as i64).wrapping_mul(op2 as i32 as i64) as u64
} else { } else {
(op1 as u64).wrapping_mul(op2 as u64) (op1 as u64).wrapping_mul(op2 as u64)
}; };
if insn.accumulate_flag() { if ACCUMULATE {
let hi = self.get_reg(rd_hi) as u64; let hi = self.get_reg(rd_hi) as u64;
let lo = self.get_reg(rd_lo) as u64; let lo = self.get_reg(rd_lo) as u64;
result = result.wrapping_add(hi << 32 | lo); result = result.wrapping_add(hi << 32 | lo);
@ -686,7 +696,7 @@ impl<I: MemoryInterface> Core<I> {
self.idle_cycle(); self.idle_cycle();
} }
if insn.set_cond_flag() { if UPDATE_FLAGS {
self.cpsr.set_N(result.bit(63)); self.cpsr.set_N(result.bit(63));
self.cpsr.set_Z(result == 0); self.cpsr.set_Z(result == 0);
self.cpsr.set_C(false); self.cpsr.set_C(false);
@ -698,10 +708,10 @@ impl<I: MemoryInterface> Core<I> {
/// ARM Opcodes: Memory: Single Data Swap (SWP) /// ARM Opcodes: Memory: Single Data Swap (SWP)
/// Execution Time: 1S+2N+1I. That is, 2N data cycles, 1S code cycle, plus 1I. /// Execution Time: 1S+2N+1I. That is, 2N data cycles, 1S code cycle, plus 1I.
pub fn exec_arm_swp(&mut self, insn: u32) -> CpuAction { pub fn exec_arm_swp<const BYTE: bool>(&mut self, insn: u32) -> CpuAction {
let base_addr = self.get_reg(insn.bit_range(16..20) as usize); let base_addr = self.get_reg(insn.bit_range(16..20) as usize);
let rd = insn.bit_range(12..16) as usize; let rd = insn.bit_range(12..16) as usize;
if insn.transfer_size() == 1 { if BYTE {
let t = self.load_8(base_addr, NonSeq); let t = self.load_8(base_addr, NonSeq);
self.store_8(base_addr, self.get_reg(insn.rm()) as u8, Seq); self.store_8(base_addr, self.get_reg(insn.rm()) as u8, Seq);
self.set_reg(rd, t as u32); self.set_reg(rd, t as u32);