Refactor opcode execution and adc instruction

This commit is contained in:
2022-10-13 00:37:03 -05:00
parent 6acf97c7bd
commit e1f9542cca
5 changed files with 134 additions and 394 deletions
+27 -21
View File
@@ -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
View File
@@ -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;