split the Indirect addressing mode into BuggyIndirect and IndirectWithFix

This commit is contained in:
Sam M W 2024-04-23 17:07:05 +01:00 committed by Matthias Endler
parent da30c8c67d
commit 97d6b3fd89
2 changed files with 38 additions and 6 deletions

View File

@ -147,12 +147,29 @@ impl<M: Bus, V: Variant> CPU<M, V> {
// (Output: a 16-bit address)
OpInput::UseAddress(address_from_bytes(slice[0], slice[1]).wrapping_add(y.into()))
}
AddressingMode::Indirect => {
AddressingMode::IndirectWithFix => {
// Use [u8, ..2] from instruction as an address. Interpret the
// two bytes starting at that address as an address.
// (Output: a 16-bit address)
let slice = read_address(memory, arr_to_addr(&slice));
OpInput::UseAddress(arr_to_addr(&slice))
// TODO: If the pointer ends in 0xff, then incrementing it would propagate
// the carry to the high byte of the pointer. This incurs a cost of one
// machine on the real 65C02, which is not implemented here.
let slice = read_address(memory, address_from_bytes(slice[0], slice[1]));
OpInput::UseAddress(address_from_bytes(slice[0], slice[1]))
}
AddressingMode::BuggyIndirect => {
// Use [u8, ..2] from instruction as an address. Interpret the
// two bytes starting at that address as an address.
// (Output: a 16-bit address)
let pointer = address_from_bytes(slice[0], slice[1]);
let low_byte_of_target = memory.get_byte(pointer);
let low_byte_of_incremented_pointer = pointer.to_le_bytes()[0].wrapping_add(1);
let incremented_pointer = u16::from_le_bytes([low_byte_of_incremented_pointer, pointer.to_le_bytes()[1]]);
let high_byte_of_target = memory.get_byte(incremented_pointer);
OpInput::UseAddress(address_from_bytes(low_byte_of_target, high_byte_of_target))
}
AddressingMode::IndexedIndirectX => {
// Use [u8, ..1] from instruction

View File

@ -127,7 +127,8 @@ pub enum AddressingMode {
Absolute, // 3 JMP $1000 full 16-bit address
AbsoluteX, // 3 STA $1000,X full 16-bit address plus X register
AbsoluteY, // 3 STA $1000,Y full 16-bit address plus Y register
Indirect, // 3 JMP ($1000) jump to address stored at address
BuggyIndirect, // 3 JMP ($1000) jump to address stored at address
IndirectWithFix, // 3 JMP ($1000) jump to address stored at address
IndexedIndirectX, // 2 LDA ($10,X) load from address stored at (constant
// zero page address plus X register)
IndirectIndexedY, // 2 LDA ($10),Y load from (address stored at constant
@ -147,7 +148,8 @@ impl AddressingMode {
AddressingMode::Absolute => 2,
AddressingMode::AbsoluteX => 2,
AddressingMode::AbsoluteY => 2,
AddressingMode::Indirect => 2,
AddressingMode::IndirectWithFix => 2,
AddressingMode::BuggyIndirect => 2,
AddressingMode::IndexedIndirectX => 1,
AddressingMode::IndirectIndexedY => 1,
}
@ -270,7 +272,7 @@ impl crate::Variant for Nmos6502 {
0x69 => Some((Instruction::ADC, AddressingMode::Immediate)),
0x6a => Some((Instruction::ROR, AddressingMode::Accumulator)),
0x6b => None,
0x6c => Some((Instruction::JMP, AddressingMode::Indirect)),
0x6c => Some((Instruction::JMP, AddressingMode::BuggyIndirect)),
0x6d => Some((Instruction::ADC, AddressingMode::Absolute)),
0x6e => Some((Instruction::ROR, AddressingMode::Absolute)),
0x6f => None,
@ -466,3 +468,16 @@ impl crate::Variant for RevisionA {
}
}
}
/// Emulates the 65C02, which has a few bugfixes, and another addressing mode
pub struct Cmos6502;
impl crate::Variant for Cmos6502 {
fn decode(opcode: u8) -> Option<(Instruction, AddressingMode)> {
// TODO: We obviously need to add the other CMOS isntructions here.
match opcode {
0x6c => Some((Instruction::JMP, AddressingMode::IndirectWithFix)),
_ => Nmos6502::decode(opcode),
}
}
}