mirror of
https://github.com/FranLMSP/snes.git
synced 2026-10-03 16:05:18 -04:00
Refactor opcode execution and adc instruction
This commit is contained in:
@@ -86,6 +86,11 @@ pub fn stack_relative_indirect_indexed(bus: &Bus, pc_addr: u32, stack_pointer: u
|
||||
absolute_indexed(bus, pc_addr, stack_pointer) + (xy as u32)
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum IndexRegister {
|
||||
X, Y,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum AddressingMode {
|
||||
Immediate,
|
||||
@@ -94,18 +99,19 @@ pub enum AddressingMode {
|
||||
DirectPage,
|
||||
DirectPageIndirect,
|
||||
DirectPageIndirectLong,
|
||||
AbsoluteIndexed,
|
||||
AbsoluteLongIndexed,
|
||||
DirectPageIndexed,
|
||||
DirectPageIndexedIndirect,
|
||||
DirectPageIndirectIndexed,
|
||||
DirectPageIndirectLongIndexed,
|
||||
AbsoluteIndexed(IndexRegister),
|
||||
AbsoluteLongIndexed(IndexRegister),
|
||||
DirectPageIndexed(IndexRegister),
|
||||
DirectPageIndexedIndirect(IndexRegister),
|
||||
DirectPageIndirectIndexed(IndexRegister),
|
||||
DirectPageIndirectLongIndexed(IndexRegister),
|
||||
StackRelative,
|
||||
StackRelativeIndirectIndexed,
|
||||
StackRelativeIndirectIndexed(IndexRegister),
|
||||
}
|
||||
|
||||
impl AddressingMode {
|
||||
pub fn effective_address(self, bus: &Bus, pc_addr: u32, direct_page_register: u16, stack_pointer: u16, xy: u16) -> u32 {
|
||||
pub fn effective_address(self, bus: &Bus, pc_addr: u32, direct_page_register: u16, stack_pointer: u16, x: u16, y: u16) -> u32 {
|
||||
use IndexRegister::X as X;
|
||||
match self {
|
||||
Self::Immediate => immediate(pc_addr),
|
||||
Self::Absolute => absolute(bus, pc_addr),
|
||||
@@ -113,24 +119,24 @@ impl AddressingMode {
|
||||
Self::DirectPage => direct_page(bus, pc_addr, direct_page_register),
|
||||
Self::DirectPageIndirect => direct_page_indirect(bus, pc_addr, direct_page_register),
|
||||
Self::DirectPageIndirectLong => direct_page_indirect_long(bus, pc_addr, direct_page_register),
|
||||
Self::AbsoluteIndexed => absolute_indexed(bus, pc_addr, xy),
|
||||
Self::AbsoluteLongIndexed => absolute_long_indexed(bus, pc_addr, xy),
|
||||
Self::DirectPageIndexed => direct_page_indexed(bus, pc_addr, direct_page_register, xy),
|
||||
Self::DirectPageIndexedIndirect => direct_page_indexed_indirect(bus, pc_addr, direct_page_register, xy),
|
||||
Self::DirectPageIndirectIndexed => direct_page_indirect_indexed(bus, pc_addr, direct_page_register, xy),
|
||||
Self::DirectPageIndirectLongIndexed => direct_page_indirect_long_indexed(bus, pc_addr, direct_page_register, xy),
|
||||
Self::AbsoluteIndexed(idx) => absolute_indexed(bus, pc_addr, if idx == X {x} else {y}),
|
||||
Self::AbsoluteLongIndexed(idx) => absolute_long_indexed(bus, pc_addr, if idx == X {x} else {y}),
|
||||
Self::DirectPageIndexed(idx) => direct_page_indexed(bus, pc_addr, direct_page_register, if idx == X {x} else {y}),
|
||||
Self::DirectPageIndexedIndirect(idx) => direct_page_indexed_indirect(bus, pc_addr, direct_page_register, if idx == X {x} else {y}),
|
||||
Self::DirectPageIndirectIndexed(idx) => direct_page_indirect_indexed(bus, pc_addr, direct_page_register, if idx == X {x} else {y}),
|
||||
Self::DirectPageIndirectLongIndexed(idx) => direct_page_indirect_long_indexed(bus, pc_addr, direct_page_register, if idx == X {x} else {y}),
|
||||
Self::StackRelative => stack_relative(bus, pc_addr, stack_pointer),
|
||||
Self::StackRelativeIndirectIndexed => stack_relative_indirect_indexed(bus, pc_addr, stack_pointer, xy),
|
||||
Self::StackRelativeIndirectIndexed(idx) => stack_relative_indirect_indexed(bus, pc_addr, stack_pointer, if idx == X {x} else {y}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn value_8bit(self, bus: &Bus, pc_addr: u32, direct_page_register: u16, stack_pointer: u16, xy: u16) -> u8 {
|
||||
let address = self.effective_address(bus, pc_addr, direct_page_register, stack_pointer, xy);
|
||||
pub fn value_8bit(self, bus: &Bus, pc_addr: u32, direct_page_register: u16, stack_pointer: u16, x: u16, y: u16) -> u8 {
|
||||
let address = self.effective_address(bus, pc_addr, direct_page_register, stack_pointer, x, y);
|
||||
return bus.read(address);
|
||||
}
|
||||
|
||||
pub fn value_16bit(self, bus: &Bus, pc_addr: u32, direct_page_register: u16, stack_pointer: u16, xy: u16) -> u16 {
|
||||
let address = self.effective_address(bus, pc_addr, direct_page_register, stack_pointer, xy);
|
||||
pub fn value_16bit(self, bus: &Bus, pc_addr: u32, direct_page_register: u16, stack_pointer: u16, x: u16, y: u16) -> u16 {
|
||||
let address = self.effective_address(bus, pc_addr, direct_page_register, stack_pointer, x, y);
|
||||
return (bus.read(address) as u16) | ((bus.read(address + 1) as u16) << 8);
|
||||
}
|
||||
}
|
||||
@@ -389,7 +395,7 @@ mod addressing_modes_tests {
|
||||
bus.write(pc_addr + 1, 0x20);
|
||||
bus.write(pc_addr + 2, 0x10);
|
||||
bus.write(0x001020, 0xFE);
|
||||
let val = AddressingMode::Absolute.value_8bit(&bus, pc_addr, 0x00, 0x00, 0x00);
|
||||
let val = AddressingMode::Absolute.value_8bit(&bus, pc_addr, 0x00, 0x00, 0x00, 0x00);
|
||||
assert_eq!(val, 0xFE);
|
||||
|
||||
let mut bus = Bus::new();
|
||||
@@ -398,7 +404,7 @@ mod addressing_modes_tests {
|
||||
bus.write(pc_addr + 2, 0x10);
|
||||
bus.write(0x001020, 0xFF);
|
||||
bus.write(0x001021, 0xEE);
|
||||
let val = AddressingMode::Absolute.value_16bit(&bus, pc_addr, 0x00, 0x00, 0x00);
|
||||
let val = AddressingMode::Absolute.value_16bit(&bus, pc_addr, 0x00, 0x00, 0x00, 0x00);
|
||||
assert_eq!(val, 0xEEFF);
|
||||
}
|
||||
}
|
||||
+32
-40
@@ -32,26 +32,15 @@ pub fn adc16bin(target: u16, value: u16, carry: bool) -> (u16, bool, bool, bool)
|
||||
|
||||
pub fn adc8bcd(target: u8, value: u8, carry: bool) -> (u8, bool, bool, bool) {
|
||||
let mut is_carry = carry;
|
||||
let mut result: u8 = 0;
|
||||
let mut operand_mask: u8 = 0x0F;
|
||||
let mut result_mask: u8 = 0x00;
|
||||
let mut carry_check: u8= 0x09;
|
||||
let mut carry_add: u8 = 0x06;
|
||||
let mut is_carry_shifts: u8 = 0;
|
||||
for _ in 0..2 {
|
||||
result = (result & result_mask)
|
||||
.wrapping_add(target & operand_mask)
|
||||
.wrapping_add(value & operand_mask)
|
||||
.wrapping_add((is_carry as u8) << is_carry_shifts);
|
||||
is_carry = result > carry_check;
|
||||
if is_carry {
|
||||
result = result.wrapping_add(carry_add);
|
||||
}
|
||||
operand_mask = operand_mask << 4;
|
||||
carry_add = carry_add << 4;
|
||||
carry_check = (carry_check << 4) | 0x0F;
|
||||
result_mask = (result_mask << 4) | 0x0F;
|
||||
is_carry_shifts += 4;
|
||||
let mut result = (target & 0xF) + (value & 0xF) + (is_carry as u8);
|
||||
is_carry = result > 9;
|
||||
if is_carry {
|
||||
result += 6;
|
||||
}
|
||||
result = (result & 0xF0) + (target & 0xF0) + (value & 0xF0) + ((is_carry as u8) << 4);
|
||||
is_carry = result > 0x9F;
|
||||
if is_carry {
|
||||
result = result.wrapping_add(0x60);
|
||||
}
|
||||
let is_negative = (result >> 7) == 1;
|
||||
let is_zero = result == 0;
|
||||
@@ -60,26 +49,29 @@ pub fn adc8bcd(target: u8, value: u8, carry: bool) -> (u8, bool, bool, bool) {
|
||||
|
||||
pub fn adc16bcd(target: u16, value: u16, carry: bool) -> (u16, bool, bool, bool) {
|
||||
let mut is_carry = carry;
|
||||
let mut result: u16 = 0;
|
||||
let mut operand_mask: u16 = 0x0F;
|
||||
let mut result_mask: u16 = 0x00;
|
||||
let mut carry_check: u16 = 0x09;
|
||||
let mut carry_add: u16 = 0x06;
|
||||
let mut is_carry_shifts: u16 = 0;
|
||||
for _ in 0..4 {
|
||||
result = (result & result_mask)
|
||||
.wrapping_add(target & operand_mask)
|
||||
.wrapping_add(value & operand_mask)
|
||||
.wrapping_add((is_carry as u16) << is_carry_shifts);
|
||||
is_carry = result > carry_check;
|
||||
if is_carry {
|
||||
result = result.wrapping_add(carry_add);
|
||||
}
|
||||
operand_mask = operand_mask << 4;
|
||||
carry_add = carry_add << 4;
|
||||
carry_check = (carry_check << 4) | 0x0F;
|
||||
result_mask = (result_mask << 4) | 0x0F;
|
||||
is_carry_shifts += 4;
|
||||
let mut result = (target & 0xF) + (value & 0xF) + (is_carry as u16);
|
||||
is_carry = false;
|
||||
if result > 9 {
|
||||
result += 6;
|
||||
is_carry = true;
|
||||
}
|
||||
result = (result & 0xF0) + (target & 0xF0) + (value & 0xF0) + ((is_carry as u16) << 4);
|
||||
is_carry = false;
|
||||
if result > 0x9F {
|
||||
result += 0x60;
|
||||
is_carry = true;
|
||||
}
|
||||
result = (result & 0xF00) + (target & 0xF00) + (value & 0xF00) + ((is_carry as u16) << 8);
|
||||
is_carry = false;
|
||||
if result > 0x9FF {
|
||||
result += 0x600;
|
||||
is_carry = true;
|
||||
}
|
||||
result = (result & 0xF000) + (target & 0xF000) + (target & 0xF000) + ((is_carry as u16) << 12);
|
||||
is_carry = false;
|
||||
if result > 0x9FFF {
|
||||
result += 0x6000;
|
||||
is_carry = true;
|
||||
}
|
||||
let is_negative = (result >> 15) == 1;
|
||||
let is_zero = result == 0;
|
||||
|
||||
Reference in New Issue
Block a user