arm: convert some instructions to const-generics
Former-commit-id: 493127ef64f3d5e396e0391c5bb0db985cac8945 Former-commit-id: 987edb22cd27584dfdee0a23602df45424a6f4b8
This commit is contained in:
parent
03d28c77b6
commit
9819bf611d
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Reference in a new issue