More const generics..
Former-commit-id: 74e4c88128d8c83bbb23a874ba8e0821ffc583a7 Former-commit-id: 99ed5c5f73ba9ad2e95b9b190e0100d0e1b9e6a2
This commit is contained in:
parent
0665ff7451
commit
892dfbe395
160
core/build.rs
160
core/build.rs
|
@ -7,47 +7,83 @@ extern crate bit;
|
||||||
use bit::BitIndex;
|
use bit::BitIndex;
|
||||||
|
|
||||||
// copied and slightly adjusted from src/core/arm7tdmi/thumb/mod.rs
|
// copied and slightly adjusted from src/core/arm7tdmi/thumb/mod.rs
|
||||||
fn thumb_decode(i: u16) -> &'static str {
|
fn thumb_decode(i: u16) -> (&'static str, String) {
|
||||||
if i & 0xf800 == 0x1800 {
|
if i & 0xf800 == 0x1800 {
|
||||||
"AddSub"
|
(
|
||||||
|
"AddSub",
|
||||||
|
format!(
|
||||||
|
"exec_thumb_add_sub::<{SUB}, {IMM}, {RN}>",
|
||||||
|
SUB = i.bit(9),
|
||||||
|
IMM = i.bit(10),
|
||||||
|
RN = i.bit_range(6..9) as usize
|
||||||
|
),
|
||||||
|
)
|
||||||
} else if i & 0xe000 == 0x0000 {
|
} else if i & 0xe000 == 0x0000 {
|
||||||
"MoveShiftedReg"
|
(
|
||||||
|
"MoveShiftedReg",
|
||||||
|
format!(
|
||||||
|
"exec_thumb_move_shifted_reg::<{BS_OP}, {OFFSET5}>",
|
||||||
|
BS_OP = i.bit_range(11..13) as u8,
|
||||||
|
OFFSET5 = i.bit_range(6..11) as u8
|
||||||
|
),
|
||||||
|
)
|
||||||
} else if i & 0xe000 == 0x2000 {
|
} else if i & 0xe000 == 0x2000 {
|
||||||
"DataProcessImm"
|
(
|
||||||
|
"DataProcessImm",
|
||||||
|
String::from("exec_thumb_data_process_imm"),
|
||||||
|
)
|
||||||
} else if i & 0xfc00 == 0x4000 {
|
} else if i & 0xfc00 == 0x4000 {
|
||||||
"AluOps"
|
("AluOps", String::from("exec_thumb_alu_ops"))
|
||||||
} else if i & 0xfc00 == 0x4400 {
|
} else if i & 0xfc00 == 0x4400 {
|
||||||
"HiRegOpOrBranchExchange"
|
(
|
||||||
|
"HiRegOpOrBranchExchange",
|
||||||
|
String::from("exec_thumb_hi_reg_op_or_bx"),
|
||||||
|
)
|
||||||
} else if i & 0xf800 == 0x4800 {
|
} else if i & 0xf800 == 0x4800 {
|
||||||
"LdrPc"
|
("LdrPc", String::from("exec_thumb_ldr_pc"))
|
||||||
} else if i & 0xf200 == 0x5000 {
|
} else if i & 0xf200 == 0x5000 {
|
||||||
"LdrStrRegOffset"
|
(
|
||||||
|
"LdrStrRegOffset",
|
||||||
|
String::from("exec_thumb_ldr_str_reg_offset"),
|
||||||
|
)
|
||||||
} else if i & 0xf200 == 0x5200 {
|
} else if i & 0xf200 == 0x5200 {
|
||||||
"LdrStrSHB"
|
("LdrStrSHB", String::from("exec_thumb_ldr_str_shb"))
|
||||||
} else if i & 0xe000 == 0x6000 {
|
} else if i & 0xe000 == 0x6000 {
|
||||||
"LdrStrImmOffset"
|
(
|
||||||
|
"LdrStrImmOffset",
|
||||||
|
String::from("exec_thumb_ldr_str_imm_offset"),
|
||||||
|
)
|
||||||
} else if i & 0xf000 == 0x8000 {
|
} else if i & 0xf000 == 0x8000 {
|
||||||
"LdrStrHalfWord"
|
(
|
||||||
|
"LdrStrHalfWord",
|
||||||
|
String::from("exec_thumb_ldr_str_halfword"),
|
||||||
|
)
|
||||||
} else if i & 0xf000 == 0x9000 {
|
} else if i & 0xf000 == 0x9000 {
|
||||||
"LdrStrSp"
|
("LdrStrSp", String::from("exec_thumb_ldr_str_sp"))
|
||||||
} else if i & 0xf000 == 0xa000 {
|
} else if i & 0xf000 == 0xa000 {
|
||||||
"LoadAddress"
|
("LoadAddress", String::from("exec_thumb_load_address"))
|
||||||
} else if i & 0xff00 == 0xb000 {
|
} else if i & 0xff00 == 0xb000 {
|
||||||
"AddSp"
|
("AddSp", String::from("exec_thumb_add_sp"))
|
||||||
} else if i & 0xf600 == 0xb400 {
|
} else if i & 0xf600 == 0xb400 {
|
||||||
"PushPop"
|
("PushPop", String::from("exec_thumb_push_pop"))
|
||||||
} else if i & 0xf000 == 0xc000 {
|
} else if i & 0xf000 == 0xc000 {
|
||||||
"LdmStm"
|
("LdmStm", String::from("exec_thumb_ldm_stm"))
|
||||||
} else if i & 0xff00 == 0xdf00 {
|
} else if i & 0xff00 == 0xdf00 {
|
||||||
"Swi"
|
("Swi", String::from("exec_thumb_swi"))
|
||||||
} else if i & 0xf000 == 0xd000 {
|
} else if i & 0xf000 == 0xd000 {
|
||||||
"BranchConditional"
|
(
|
||||||
|
"BranchConditional",
|
||||||
|
String::from("exec_thumb_branch_with_cond"),
|
||||||
|
)
|
||||||
} else if i & 0xf800 == 0xe000 {
|
} else if i & 0xf800 == 0xe000 {
|
||||||
"Branch"
|
("Branch", String::from("exec_thumb_branch"))
|
||||||
} else if i & 0xf000 == 0xf000 {
|
} else if i & 0xf000 == 0xf000 {
|
||||||
"BranchLongWithLink"
|
(
|
||||||
|
"BranchLongWithLink",
|
||||||
|
String::from("exec_thumb_branch_long_with_link"),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
"Undefined"
|
("Undefined", String::from("thumb_undefined"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +134,7 @@ impl BitAsInt<u32> for u32 {}
|
||||||
/// |_Cond__|1_1_1_0|CPopc|L|__CRn__|__Rd___|__CP#__|_CP__|1|__CRm__| CoRegTrans
|
/// |_Cond__|1_1_1_0|CPopc|L|__CRn__|__Rd___|__CP#__|_CP__|1|__CRm__| CoRegTrans
|
||||||
/// |_Cond__|1_1_1_1|_____________Ignored_by_Processor______________| SWI
|
/// |_Cond__|1_1_1_1|_____________Ignored_by_Processor______________| SWI
|
||||||
/// ```
|
/// ```
|
||||||
fn arm_decode(i: u32) -> String {
|
fn arm_decode(i: u32) -> (&'static str, String) {
|
||||||
const T: bool = true;
|
const T: bool = true;
|
||||||
const F: bool = false;
|
const F: bool = false;
|
||||||
|
|
||||||
|
@ -107,25 +143,25 @@ fn arm_decode(i: u32) -> String {
|
||||||
0b00 => {
|
0b00 => {
|
||||||
/* DataProcessing and friends */
|
/* DataProcessing and friends */
|
||||||
|
|
||||||
let result: Option<String> = 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(String::from("exec_arm_mul_mla"))
|
Some(("Multiply", String::from("exec_arm_mul_mla")))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(0b001, 0b1001) => Some(String::from("exec_arm_mull_mlal")),
|
(0b001, 0b1001) => Some(("MultiplyLong", String::from("exec_arm_mull_mlal"))),
|
||||||
(0b010, 0b1001) => {
|
(0b010, 0b1001) => {
|
||||||
if 0b00 == i.bit_range(20..22) {
|
if 0b00 == i.bit_range(20..22) {
|
||||||
Some(String::from("exec_arm_swp"))
|
Some(("SingleDataSwap", String::from("exec_arm_swp")))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(0b010, 0b0001) => {
|
(0b010, 0b0001) => {
|
||||||
if 0b010 == i.bit_range(20..23) {
|
if 0b010 == i.bit_range(20..23) {
|
||||||
Some(format!("exec_arm_bx"))
|
Some(("BranchExchange", format!("exec_arm_bx")))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -135,8 +171,8 @@ fn arm_decode(i: u32) -> String {
|
||||||
|
|
||||||
result.unwrap_or_else(|| {
|
result.unwrap_or_else(|| {
|
||||||
match (i.ibit(25), i.ibit(22), i.ibit(7), i.ibit(4)) {
|
match (i.ibit(25), i.ibit(22), i.ibit(7), i.ibit(4)) {
|
||||||
(0, 0, 1, 1) => String::from("exec_arm_ldr_str_hs_reg"),
|
(0, 0, 1, 1) => ("HalfwordDataTransferRegOffset", String::from("exec_arm_ldr_str_hs_reg")),
|
||||||
(0, 1, 1, 1) => String::from("exec_arm_ldr_str_hs_imm"),
|
(0, 1, 1, 1) => ("HalfwordDataTransferImmediateOffset", String::from("exec_arm_ldr_str_hs_imm")),
|
||||||
_ => {
|
_ => {
|
||||||
let set_cond_flags = i.bit(20);
|
let set_cond_flags = i.bit(20);
|
||||||
// PSR Transfers are encoded as a subset of Data Processing,
|
// PSR Transfers are encoded as a subset of Data Processing,
|
||||||
|
@ -145,16 +181,16 @@ fn arm_decode(i: u32) -> String {
|
||||||
if !set_cond_flags && is_op_not_touching_rd {
|
if !set_cond_flags && is_op_not_touching_rd {
|
||||||
if i.bit(21) {
|
if i.bit(21) {
|
||||||
// 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
|
// 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")
|
("MoveToStatus", String::from("exec_arm_transfer_to_status"))
|
||||||
} else {
|
} else {
|
||||||
String::from("exec_arm_mrs")
|
("MoveFromStatus", String::from("exec_arm_mrs"))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
format!("exec_arm_data_processing::<{OP}, {IMM}, {SET_FLAGS}, {SHIFT_BY_REG}>",
|
("DataProcessing", format!("exec_arm_data_processing::<{OP}, {IMM}, {SET_FLAGS}, {SHIFT_BY_REG}>",
|
||||||
OP=i.bit_range(21..25),
|
OP=i.bit_range(21..25),
|
||||||
IMM=i.bit(25),
|
IMM=i.bit(25),
|
||||||
SET_FLAGS=i.bit(20),
|
SET_FLAGS=i.bit(20),
|
||||||
SHIFT_BY_REG=i.bit(4))
|
SHIFT_BY_REG=i.bit(4)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,7 +198,7 @@ fn arm_decode(i: u32) -> String {
|
||||||
}
|
}
|
||||||
0b01 => {
|
0b01 => {
|
||||||
match (i.bit(25), i.bit(4)) {
|
match (i.bit(25), i.bit(4)) {
|
||||||
(_, F) | (F, T) => format!(
|
(_, F) | (F, T) => ("SingleDataTransfer", format!(
|
||||||
"exec_arm_ldr_str::<{LOAD}, {WRITEBACK}, {PRE_INDEX}, {BYTE}, {SHIFT}, {ADD}, {BS_OP}, {SHIFT_BY_REG}>",
|
"exec_arm_ldr_str::<{LOAD}, {WRITEBACK}, {PRE_INDEX}, {BYTE}, {SHIFT}, {ADD}, {BS_OP}, {SHIFT_BY_REG}>",
|
||||||
LOAD = i.bit(20),
|
LOAD = i.bit(20),
|
||||||
WRITEBACK = i.bit(21),
|
WRITEBACK = i.bit(21),
|
||||||
|
@ -172,53 +208,30 @@ fn arm_decode(i: u32) -> String {
|
||||||
SHIFT = i.bit(25),
|
SHIFT = i.bit(25),
|
||||||
BS_OP = i.bit_range(5..7) as u8,
|
BS_OP = i.bit_range(5..7) as u8,
|
||||||
SHIFT_BY_REG = i.bit(4),
|
SHIFT_BY_REG = i.bit(4),
|
||||||
),
|
)),
|
||||||
(T, T) => String::from("arm_undefined"), /* Possible ARM11 but we don't implement these */
|
(T, T) => ("Undefined", String::from("arm_undefined")), /* Possible ARM11 but we don't implement these */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0b10 => match i.bit(25) {
|
0b10 => match i.bit(25) {
|
||||||
F => String::from("exec_arm_ldm_stm"),
|
F => ("BlockDataTransfer", String::from("exec_arm_ldm_stm")),
|
||||||
T => format!("exec_arm_b_bl::<{LINK}>", LINK = i.bit(24)),
|
T => (
|
||||||
|
"BranchLink",
|
||||||
|
format!("exec_arm_b_bl::<{LINK}>", LINK = i.bit(24)),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
0b11 => {
|
0b11 => {
|
||||||
match (i.ibit(25), i.ibit(24), i.ibit(4)) {
|
match (i.ibit(25), i.ibit(24), i.ibit(4)) {
|
||||||
(0b0, _, _) => String::from("arm_undefined"), /* CoprocessorDataTransfer not implemented */
|
(0b0, _, _) => ("Undefined", String::from("arm_undefined")), /* CoprocessorDataTransfer not implemented */
|
||||||
(0b1, 0b0, 0b0) => String::from("arm_undefined"), /* CoprocessorDataOperation not implemented */
|
(0b1, 0b0, 0b0) => ("Undefined", String::from("arm_undefined")), /* CoprocessorDataOperation not implemented */
|
||||||
(0b1, 0b0, 0b1) => String::from("arm_undefined"), /* CoprocessorRegisterTransfer not implemented */
|
(0b1, 0b0, 0b1) => ("Undefined", String::from("arm_undefined")), /* CoprocessorRegisterTransfer not implemented */
|
||||||
(0b1, 0b1, _) => String::from("exec_arm_swi"),
|
(0b1, 0b1, _) => ("SoftwareInterrupt", String::from("exec_arm_swi")),
|
||||||
_ => String::from("arm_undefined"),
|
_ => ("Undefined", String::from("arm_undefined")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn thumb_format_to_handler(thumb_fmt: &str) -> &'static str {
|
|
||||||
match thumb_fmt {
|
|
||||||
"MoveShiftedReg" => "exec_thumb_move_shifted_reg",
|
|
||||||
"AddSub" => "exec_thumb_add_sub",
|
|
||||||
"DataProcessImm" => "exec_thumb_data_process_imm",
|
|
||||||
"AluOps" => "exec_thumb_alu_ops",
|
|
||||||
"HiRegOpOrBranchExchange" => "exec_thumb_hi_reg_op_or_bx",
|
|
||||||
"LdrPc" => "exec_thumb_ldr_pc",
|
|
||||||
"LdrStrRegOffset" => "exec_thumb_ldr_str_reg_offset",
|
|
||||||
"LdrStrSHB" => "exec_thumb_ldr_str_shb",
|
|
||||||
"LdrStrImmOffset" => "exec_thumb_ldr_str_imm_offset",
|
|
||||||
"LdrStrHalfWord" => "exec_thumb_ldr_str_halfword",
|
|
||||||
"LdrStrSp" => "exec_thumb_ldr_str_sp",
|
|
||||||
"LoadAddress" => "exec_thumb_load_address",
|
|
||||||
"AddSp" => "exec_thumb_add_sp",
|
|
||||||
"PushPop" => "exec_thumb_push_pop",
|
|
||||||
"LdmStm" => "exec_thumb_ldm_stm",
|
|
||||||
"BranchConditional" => "exec_thumb_branch_with_cond",
|
|
||||||
"Swi" => "exec_thumb_swi",
|
|
||||||
"Branch" => "exec_thumb_branch",
|
|
||||||
"BranchLongWithLink" => "exec_thumb_branch_long_with_link",
|
|
||||||
"Undefined" => "thumb_undefined",
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_thumb_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
|
fn generate_thumb_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
|
||||||
writeln!(file, "impl<I: MemoryInterface> Core<I> {{")?;
|
writeln!(file, "impl<I: MemoryInterface> Core<I> {{")?;
|
||||||
writeln!(
|
writeln!(
|
||||||
|
@ -227,8 +240,7 @@ fn generate_thumb_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
for i in 0..1024 {
|
for i in 0..1024 {
|
||||||
let thumb_fmt = thumb_decode(i << 6);
|
let (thumb_fmt, handler_name) = thumb_decode(i << 6);
|
||||||
let handler_name = thumb_format_to_handler(thumb_fmt);
|
|
||||||
writeln!(
|
writeln!(
|
||||||
file,
|
file,
|
||||||
" /* {:#x} */
|
" /* {:#x} */
|
||||||
|
@ -254,16 +266,16 @@ fn generate_arm_lut(file: &mut fs::File) -> Result<(), std::io::Error> {
|
||||||
" pub const ARM_LUT: [ArmInstructionInfo<I>; 4096] = ["
|
" pub const ARM_LUT: [ArmInstructionInfo<I>; 4096] = ["
|
||||||
)?;
|
)?;
|
||||||
for i in 0..4096 {
|
for i in 0..4096 {
|
||||||
let handler_name = arm_decode(((i & 0xff0) << 16) | ((i & 0x00f) << 4));
|
let (arm_fmt, handler_name) = arm_decode(((i & 0xff0) << 16) | ((i & 0x00f) << 4));
|
||||||
writeln!(
|
writeln!(
|
||||||
file,
|
file,
|
||||||
" /* {:#x} */
|
" /* {:#x} */
|
||||||
ArmInstructionInfo {{
|
ArmInstructionInfo {{
|
||||||
handler_fn: Core::{},
|
handler_fn: Core::{},
|
||||||
#[cfg(feature = \"debugger\")]
|
#[cfg(feature = \"debugger\")]
|
||||||
fmt: ArmFormat::Undefined,
|
fmt: ArmFormat::{},
|
||||||
}} ,",
|
}} ,",
|
||||||
i, handler_name
|
i, handler_name, arm_fmt
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
writeln!(file, " ];")?;
|
writeln!(file, " ];")?;
|
||||||
|
|
|
@ -272,7 +272,7 @@ impl<I: MemoryInterface> Core<I> {
|
||||||
1 => BarrelShiftOpCode::LSR,
|
1 => BarrelShiftOpCode::LSR,
|
||||||
2 => BarrelShiftOpCode::ASR,
|
2 => BarrelShiftOpCode::ASR,
|
||||||
3 => BarrelShiftOpCode::ROR,
|
3 => BarrelShiftOpCode::ROR,
|
||||||
_ => unreachable!(),
|
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||||
};
|
};
|
||||||
if SHIFT_BY_REG {
|
if SHIFT_BY_REG {
|
||||||
let rs = offset.bit_range(8..12) as usize;
|
let rs = offset.bit_range(8..12) as usize;
|
||||||
|
|
|
@ -10,19 +10,23 @@ use MemoryAccess::*;
|
||||||
impl<I: MemoryInterface> Core<I> {
|
impl<I: MemoryInterface> Core<I> {
|
||||||
/// Format 1
|
/// Format 1
|
||||||
/// Execution Time: 1S
|
/// Execution Time: 1S
|
||||||
pub(in super::super) fn exec_thumb_move_shifted_reg(&mut self, insn: u16) -> CpuAction {
|
pub(in super::super) fn exec_thumb_move_shifted_reg<const BS_OP: u8, const OFFSET5: u8>(
|
||||||
|
&mut self,
|
||||||
|
insn: u16,
|
||||||
|
) -> CpuAction {
|
||||||
let rd = (insn & 0b111) as usize;
|
let rd = (insn & 0b111) as usize;
|
||||||
let rs = insn.bit_range(3..6) as usize;
|
let rs = insn.bit_range(3..6) as usize;
|
||||||
|
|
||||||
let shift_amount = insn.offset5() as u8 as u32;
|
let shift_amount = OFFSET5 as u32;
|
||||||
let mut carry = self.cpsr.C();
|
let mut carry = self.cpsr.C();
|
||||||
let op2 = self.barrel_shift_op(
|
let bsop = match BS_OP {
|
||||||
insn.format1_op(),
|
0 => BarrelShiftOpCode::LSL,
|
||||||
self.gpr[rs],
|
1 => BarrelShiftOpCode::LSR,
|
||||||
shift_amount,
|
2 => BarrelShiftOpCode::ASR,
|
||||||
&mut carry,
|
3 => BarrelShiftOpCode::ROR,
|
||||||
true,
|
_ => unsafe { std::hint::unreachable_unchecked() },
|
||||||
);
|
};
|
||||||
|
let op2 = self.barrel_shift_op(bsop, self.gpr[rs], shift_amount, &mut carry, true);
|
||||||
self.gpr[rd] = op2;
|
self.gpr[rd] = op2;
|
||||||
self.alu_update_flags(op2, false, carry, self.cpsr.V());
|
self.alu_update_flags(op2, false, carry, self.cpsr.V());
|
||||||
|
|
||||||
|
@ -31,18 +35,21 @@ impl<I: MemoryInterface> Core<I> {
|
||||||
|
|
||||||
/// Format 2
|
/// Format 2
|
||||||
/// Execution Time: 1S
|
/// Execution Time: 1S
|
||||||
pub(in super::super) fn exec_thumb_add_sub(&mut self, insn: u16) -> CpuAction {
|
pub(in super::super) fn exec_thumb_add_sub<
|
||||||
|
const SUB: bool,
|
||||||
|
const IMM: bool,
|
||||||
|
const RN: usize,
|
||||||
|
>(
|
||||||
|
&mut self,
|
||||||
|
insn: u16,
|
||||||
|
) -> CpuAction {
|
||||||
let rd = (insn & 0b111) as usize;
|
let rd = (insn & 0b111) as usize;
|
||||||
let op1 = self.get_reg(insn.rs());
|
let op1 = self.get_reg(insn.rs());
|
||||||
let op2 = if insn.is_immediate_operand() {
|
let op2 = if IMM { RN as u32 } else { self.get_reg(RN) };
|
||||||
insn.rn() as u32
|
|
||||||
} else {
|
|
||||||
self.get_reg(insn.rn())
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut carry = self.cpsr.C();
|
let mut carry = self.cpsr.C();
|
||||||
let mut overflow = self.cpsr.V();
|
let mut overflow = self.cpsr.V();
|
||||||
let result = if insn.is_subtract() {
|
let result = if SUB {
|
||||||
self.alu_sub_flags(op1, op2, &mut carry, &mut overflow)
|
self.alu_sub_flags(op1, op2, &mut carry, &mut overflow)
|
||||||
} else {
|
} else {
|
||||||
self.alu_add_flags(op1, op2, &mut carry, &mut overflow)
|
self.alu_add_flags(op1, op2, &mut carry, &mut overflow)
|
||||||
|
|
Reference in a new issue