WIP const generics

Former-commit-id: 2c38215fb57de66bfce26cfa7e61c460bd2954ac
Former-commit-id: 8fe5cc4fdc58b1155590dbfd6546b280fcdcc259
This commit is contained in:
Michel Heily 2021-06-30 01:25:44 +03:00 committed by MichelOS
parent 1545be7b4f
commit b3c3c70bce
3 changed files with 47 additions and 56 deletions

View file

@ -98,7 +98,7 @@ impl BitAsInt<u32> for u32 {}
/// |_Cond__|1_1_1_0|CPopc|L|__CRn__|__Rd___|__CP#__|_CP__|1|__CRm__| CoRegTrans
/// |_Cond__|1_1_1_1|_____________Ignored_by_Processor______________| SWI
/// ```
fn arm_decode(i: u32) -> &'static str {
fn arm_decode(i: u32) -> String {
const T: bool = true;
const F: bool = false;
@ -107,25 +107,25 @@ fn arm_decode(i: u32) -> &'static str {
0b00 => {
/* DataProcessing and friends */
let result: Option<&str> = match (i.bit_range(23..26), i.bit_range(4..8)) {
let result: Option<String> = match (i.bit_range(23..26), i.bit_range(4..8)) {
(0b000, 0b1001) => {
if 0b0 == i.ibit(22) {
Some("Multiply")
Some(String::from("exec_arm_mul_mla"))
} else {
None
}
}
(0b001, 0b1001) => Some("MultiplyLong"),
(0b001, 0b1001) => Some(String::from("exec_arm_mull_mlal")),
(0b010, 0b1001) => {
if 0b00 == i.bit_range(20..22) {
Some("SingleDataSwap")
Some(String::from("exec_arm_swp"))
} else {
None
}
}
(0b010, 0b0001) => {
if 0b010 == i.bit_range(20..23) {
Some("BranchExchange")
Some(format!("exec_arm_bx"))
} else {
None
}
@ -135,8 +135,8 @@ fn arm_decode(i: u32) -> &'static str {
result.unwrap_or_else(|| {
match (i.ibit(25), i.ibit(22), i.ibit(7), i.ibit(4)) {
(0, 0, 1, 1) => "HalfwordDataTransferRegOffset",
(0, 1, 1, 1) => "HalfwordDataTransferImmediateOffset",
(0, 0, 1, 1) => String::from("exec_arm_ldr_str_hs_reg"),
(0, 1, 1, 1) => String::from("exec_arm_ldr_str_hs_imm"),
_ => {
let set_cond_flags = i.bit(20);
// PSR Transfers are encoded as a subset of Data Processing,
@ -144,13 +144,17 @@ fn arm_decode(i: u32) -> &'static str {
let is_op_not_touching_rd = i.bit_range(21..25) & 0b1100 == 0b1000;
if !set_cond_flags && is_op_not_touching_rd {
if i.bit(21) {
// Since bit-16 is ignored and we can't know statically if this is a MoveToStatus or MoveToFlags
"MoveToStatus"
// Since bit-16 is ignored and we can't know statically if this is a exec_arm_transfer_to_status or exec_arm_transfer_to_status
String::from("exec_arm_transfer_to_status")
} else {
"MoveFromStatus"
String::from("exec_arm_mrs")
}
} else {
"DataProcessing"
format!("exec_arm_data_processing::<{OP}, {IMM}, {SET_FLAGS}, {SHIFT_BY_REG}>",
OP=i.bit_range(21..25),
IMM=i.bit(25),
SET_FLAGS=i.bit(20),
SHIFT_BY_REG=i.bit(4))
}
}
}
@ -158,21 +162,21 @@ fn arm_decode(i: u32) -> &'static str {
}
0b01 => {
match (i.bit(25), i.bit(4)) {
(_, F) | (F, T) => "SingleDataTransfer",
(T, T) => "Undefined", /* Possible ARM11 but we don't implement these */
(_, F) | (F, T) => String::from("exec_arm_ldr_str"),
(T, T) => String::from("arm_undefined"), /* Possible ARM11 but we don't implement these */
}
}
0b10 => match i.bit(25) {
F => "BlockDataTransfer",
T => "BranchLink",
F => String::from("exec_arm_ldm_stm"),
T => format!("exec_arm_b_bl::<{LINK}>", LINK = i.bit(24)),
},
0b11 => {
match (i.ibit(25), i.ibit(24), i.ibit(4)) {
(0b0, _, _) => "Undefined", /* CoprocessorDataTransfer not implemented */
(0b1, 0b0, 0b0) => "Undefined", /* CoprocessorDataOperation not implemented */
(0b1, 0b0, 0b1) => "Undefined", /* CoprocessorRegisterTransfer not implemented */
(0b1, 0b1, _) => "SoftwareInterrupt",
_ => "Undefined",
(0b0, _, _) => String::from("arm_undefined"), /* CoprocessorDataTransfer not implemented */
(0b1, 0b0, 0b0) => String::from("arm_undefined"), /* CoprocessorDataOperation not implemented */
(0b1, 0b0, 0b1) => String::from("arm_undefined"), /* CoprocessorRegisterTransfer not implemented */
(0b1, 0b1, _) => String::from("exec_arm_swi"),
_ => String::from("arm_undefined"),
}
}
_ => unreachable!(),
@ -205,27 +209,6 @@ fn thumb_format_to_handler(thumb_fmt: &str) -> &'static str {
}
}
fn arm_format_to_handler(arm_fmt: &str) -> &'static str {
match arm_fmt {
"BranchExchange" => "exec_arm_bx",
"BranchLink" => "exec_arm_b_bl",
"DataProcessing" => "exec_arm_data_processing",
"SoftwareInterrupt" => "exec_arm_swi",
"SingleDataTransfer" => "exec_arm_ldr_str",
"HalfwordDataTransferImmediateOffset" => "exec_arm_ldr_str_hs_imm",
"HalfwordDataTransferRegOffset" => "exec_arm_ldr_str_hs_reg",
"BlockDataTransfer" => "exec_arm_ldm_stm",
"MoveFromStatus" => "exec_arm_mrs",
"MoveToStatus" => "exec_arm_transfer_to_status",
"MoveToFlags" => "exec_arm_transfer_to_status",
"Multiply" => "exec_arm_mul_mla",
"MultiplyLong" => "exec_arm_mull_mlal",
"SingleDataSwap" => "exec_arm_swp",
"Undefined" => "arm_undefined",
_ => unreachable!(),
}
}
fn generate_thumb_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
writeln!(file, "impl<I: MemoryInterface> Core<I> {{")?;
writeln!(
@ -261,17 +244,16 @@ fn generate_arm_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
" pub const ARM_LUT: [ArmInstructionInfo<I>; 4096] = ["
)?;
for i in 0..4096 {
let arm_fmt = arm_decode(((i & 0xff0) << 16) | ((i & 0x00f) << 4));
let handler_name = arm_format_to_handler(arm_fmt);
let handler_name = arm_decode(((i & 0xff0) << 16) | ((i & 0x00f) << 4));
writeln!(
file,
" /* {:#x} */
ArmInstructionInfo {{
handler_fn: Core::{},
#[cfg(feature = \"debugger\")]
fmt: ArmFormat::{},
fmt: ArmFormat::Undefined,
}} ,",
i, handler_name, arm_fmt
i, handler_name
)?;
}
writeln!(file, " ];")?;

View file

@ -3,7 +3,7 @@ use bit::BitIndex;
use super::memory::MemoryInterface;
use super::{Core, REG_PC};
#[derive(Debug, Primitive, PartialEq)]
#[derive(Debug, Primitive, Eq, PartialEq)]
pub enum AluOpCode {
AND = 0b0000,
EOR = 0b0001,

View file

@ -43,11 +43,10 @@ impl<I: MemoryInterface> Core<I> {
/// Branch and Branch with Link (B, BL)
/// Execution Time: 2S + 1N
pub fn exec_arm_b_bl(&mut self, insn: u32) -> CpuAction {
if insn.link_flag() {
pub fn exec_arm_b_bl<const LINK: bool>(&mut self, insn: u32) -> CpuAction {
if LINK {
self.set_reg(REG_LR, (self.pc_arm() + (self.word_size() as u32)) & !0b1);
}
self.pc = (self.pc as i32).wrapping_add(insn.branch_offset()) as u32 & !1;
self.reload_pipeline32(); // Implies 2S + 1N
@ -165,9 +164,16 @@ impl<I: MemoryInterface> Core<I> {
///
/// Cycles: 1S+x+y (from GBATEK)
/// Add x=1I cycles if Op2 shifted-by-register. Add y=1S+1N cycles if Rd=R15.
pub fn exec_arm_data_processing(&mut self, insn: u32) -> CpuAction {
pub fn exec_arm_data_processing<
const OP: u8,
const IMM: bool,
const SET_FLAGS: bool,
const SHIFT_BY_REG: bool,
>(
&mut self,
insn: u32,
) -> CpuAction {
use AluOpCode::*;
let rn = insn.bit_range(16..20) as usize;
let rd = insn.bit_range(12..16) as usize;
let mut op1 = if rn == REG_PC {
@ -175,11 +181,14 @@ impl<I: MemoryInterface> Core<I> {
} else {
self.get_reg(rn)
};
let mut s_flag = insn.set_cond_flag();
let opcode = insn.opcode();
let mut s_flag = SET_FLAGS;
let opcode =
AluOpCode::from_u8(OP).unwrap_or_else(|| unsafe { std::hint::unreachable_unchecked() });
// println!("{:?} {} {} {}, {:?} {} {} {}", insn.opcode(), insn.bit(25), insn.set_cond_flags(), insn.bit(4), opcode, IMM, SET_FLAGS, SHIFT_BY_REG);
let mut carry = self.cpsr.C();
let op2 = if insn.bit(25) {
let op2 = if IMM {
let immediate = insn & 0xff;
let rotate = 2 * insn.bit_range(8..12);
// TODO refactor out
@ -187,7 +196,7 @@ impl<I: MemoryInterface> Core<I> {
} else {
let reg = insn & 0xf;
let shift_by = if insn.bit(4) {
let shift_by = if SHIFT_BY_REG {
if rn == REG_PC {
op1 += 4;
}