mirror of
https://github.com/mre/mos6502.git
synced 2024-06-13 00:29:33 +00:00
Merge efa53efa08
into 11499b6bc8
This commit is contained in:
commit
a584053e7e
50
src/cpu.rs
50
src/cpu.rs
|
@ -31,10 +31,8 @@ use crate::Variant;
|
|||
|
||||
use crate::registers::{Registers, StackPointer, Status, StatusArgs};
|
||||
|
||||
fn arr_to_addr(arr: &[u8]) -> u16 {
|
||||
debug_assert!(arr.len() == 2);
|
||||
|
||||
u16::from(arr[0]) + (u16::from(arr[1]) << 8usize)
|
||||
fn address_from_bytes(lo: u8, hi: u8) -> u16 {
|
||||
u16::from(lo) + (u16::from(hi) << 8usize)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -136,24 +134,52 @@ impl<M: Bus, V: Variant> CPU<M, V> {
|
|||
AddressingMode::Absolute => {
|
||||
// Use [u8, ..2] from instruction as address
|
||||
// (Output: a 16-bit address)
|
||||
OpInput::UseAddress(arr_to_addr(&slice))
|
||||
OpInput::UseAddress(address_from_bytes(slice[0], slice[1]))
|
||||
}
|
||||
AddressingMode::AbsoluteX => {
|
||||
// Use [u8, ..2] from instruction as address, add X
|
||||
// (Output: a 16-bit address)
|
||||
OpInput::UseAddress(arr_to_addr(&slice).wrapping_add(x.into()))
|
||||
OpInput::UseAddress(
|
||||
address_from_bytes(slice[0], slice[1]).wrapping_add(x.into()),
|
||||
)
|
||||
}
|
||||
AddressingMode::AbsoluteY => {
|
||||
// Use [u8, ..2] from instruction as address, add Y
|
||||
// (Output: a 16-bit address)
|
||||
OpInput::UseAddress(arr_to_addr(&slice).wrapping_add(y.into()))
|
||||
OpInput::UseAddress(
|
||||
address_from_bytes(slice[0], slice[1]).wrapping_add(y.into()),
|
||||
)
|
||||
}
|
||||
AddressingMode::Indirect => {
|
||||
// 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
|
||||
|
@ -162,7 +188,7 @@ impl<M: Bus, V: Variant> CPU<M, V> {
|
|||
// (Output: a 16-bit address)
|
||||
let start = slice[0].wrapping_add(x);
|
||||
let slice = read_address(memory, u16::from(start));
|
||||
OpInput::UseAddress(arr_to_addr(&slice))
|
||||
OpInput::UseAddress(address_from_bytes(slice[0], slice[1]))
|
||||
}
|
||||
AddressingMode::IndirectIndexedY => {
|
||||
// Use [u8, ..1] from instruction
|
||||
|
@ -171,7 +197,9 @@ impl<M: Bus, V: Variant> CPU<M, V> {
|
|||
// (Output: a 16-bit address)
|
||||
let start = slice[0];
|
||||
let slice = read_address(memory, u16::from(start));
|
||||
OpInput::UseAddress(arr_to_addr(&slice).wrapping_add(y.into()))
|
||||
OpInput::UseAddress(
|
||||
address_from_bytes(slice[0], slice[1]).wrapping_add(y.into()),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -127,6 +127,7 @@ 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
|
||||
BuggyIndirect, // 3 JMP ($1000) jump to address stored at address, with the page-crossing bug founr in NMOS chips
|
||||
Indirect, // 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)
|
||||
|
@ -148,6 +149,7 @@ impl AddressingMode {
|
|||
AddressingMode::AbsoluteX => 2,
|
||||
AddressingMode::AbsoluteY => 2,
|
||||
AddressingMode::Indirect => 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 instructions here.
|
||||
match opcode {
|
||||
0x6c => Some((Instruction::JMP, AddressingMode::Indirect)),
|
||||
_ => Nmos6502::decode(opcode),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user