WIP const generics
Former-commit-id: 2c38215fb57de66bfce26cfa7e61c460bd2954ac Former-commit-id: 8fe5cc4fdc58b1155590dbfd6546b280fcdcc259
This commit is contained in:
parent
1545be7b4f
commit
b3c3c70bce
|
@ -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, " ];")?;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Reference in a new issue