mirror of
https://github.com/mre/mos6502.git
synced 2025-02-20 09:29:02 +00:00
remove Address and AddressDiff from equation
This commit is contained in:
parent
f3d3bf470f
commit
4b26e83529
40
src/cpu.rs
40
src/cpu.rs
@ -60,9 +60,9 @@ impl CPU {
|
||||
match instruction::OPCODES[x as usize] {
|
||||
Some((instr, am)) => {
|
||||
let extra_bytes = am.extra_bytes();
|
||||
let num_bytes = AddressDiff(1) + extra_bytes;
|
||||
let num_bytes = extra_bytes + 1;
|
||||
|
||||
let data_start = self.registers.program_counter + AddressDiff(1);
|
||||
let data_start = self.registers.program_counter.wrapping_add(1);
|
||||
|
||||
let slice = self.memory.get_slice(data_start, extra_bytes);
|
||||
let am_out = am.process(self, slice);
|
||||
@ -110,17 +110,17 @@ impl CPU {
|
||||
}
|
||||
|
||||
(Instruction::BCC, OpInput::UseRelative(rel)) => {
|
||||
let addr = self.registers.program_counter + AddressDiff(i32::from(rel));
|
||||
let addr = self.registers.program_counter.wrapping_add(rel);
|
||||
self.branch_if_carry_clear(addr);
|
||||
}
|
||||
|
||||
(Instruction::BCS, OpInput::UseRelative(rel)) => {
|
||||
let addr = self.registers.program_counter + AddressDiff(i32::from(rel));
|
||||
let addr = self.registers.program_counter.wrapping_add(rel);
|
||||
self.branch_if_carry_set(addr);
|
||||
}
|
||||
|
||||
(Instruction::BEQ, OpInput::UseRelative(rel)) => {
|
||||
let addr = self.registers.program_counter + AddressDiff(i32::from(rel));
|
||||
let addr = self.registers.program_counter.wrapping_add(rel);
|
||||
self.branch_if_equal(addr);
|
||||
}
|
||||
|
||||
@ -150,23 +150,23 @@ impl CPU {
|
||||
}
|
||||
|
||||
(Instruction::BMI, OpInput::UseRelative(rel)) => {
|
||||
let addr = self.registers.program_counter + AddressDiff(i32::from(rel));
|
||||
let addr = self.registers.program_counter.wrapping_add(rel);
|
||||
debug!("branch if minus relative. address: {:?}", addr);
|
||||
self.branch_if_minus(addr);
|
||||
}
|
||||
|
||||
(Instruction::BPL, OpInput::UseRelative(rel)) => {
|
||||
let addr = self.registers.program_counter + AddressDiff(i32::from(rel));
|
||||
let addr = self.registers.program_counter.wrapping_add(rel);
|
||||
self.branch_if_positive(addr);
|
||||
}
|
||||
|
||||
(Instruction::BVC, OpInput::UseRelative(rel)) => {
|
||||
let addr = self.registers.program_counter + AddressDiff(i32::from(rel));
|
||||
let addr = self.registers.program_counter.wrapping_add(rel);
|
||||
self.branch_if_overflow_clear(addr);
|
||||
}
|
||||
|
||||
(Instruction::BVS, OpInput::UseRelative(rel)) => {
|
||||
let addr = self.registers.program_counter + AddressDiff(i32::from(rel));
|
||||
let addr = self.registers.program_counter.wrapping_add(rel);
|
||||
self.branch_if_overflow_set(addr);
|
||||
}
|
||||
|
||||
@ -648,7 +648,7 @@ impl CPU {
|
||||
self.load_accumulator(result);
|
||||
}
|
||||
|
||||
fn decrement_memory(&mut self, addr: Address) {
|
||||
fn decrement_memory(&mut self, addr: u16) {
|
||||
let value_new = self.memory.get_byte(addr).wrapping_sub(1);
|
||||
|
||||
self.memory.set_byte(addr, value_new);
|
||||
@ -671,47 +671,47 @@ impl CPU {
|
||||
self.load_x_register(val - 1);
|
||||
}
|
||||
|
||||
fn jump(&mut self, addr: Address) {
|
||||
fn jump(&mut self, addr: u16) {
|
||||
self.registers.program_counter = addr;
|
||||
}
|
||||
|
||||
fn branch_if_carry_clear(&mut self, addr: Address) {
|
||||
fn branch_if_carry_clear(&mut self, addr: u16) {
|
||||
if !self.registers.status.contains(Status::PS_CARRY) {
|
||||
self.registers.program_counter = addr;
|
||||
}
|
||||
}
|
||||
|
||||
fn branch_if_carry_set(&mut self, addr: Address) {
|
||||
fn branch_if_carry_set(&mut self, addr: u16) {
|
||||
if self.registers.status.contains(Status::PS_CARRY) {
|
||||
self.registers.program_counter = addr;
|
||||
}
|
||||
}
|
||||
|
||||
fn branch_if_equal(&mut self, addr: Address) {
|
||||
fn branch_if_equal(&mut self, addr: u16) {
|
||||
if self.registers.status.contains(Status::PS_ZERO) {
|
||||
self.registers.program_counter = addr;
|
||||
}
|
||||
}
|
||||
|
||||
fn branch_if_minus(&mut self, addr: Address) {
|
||||
fn branch_if_minus(&mut self, addr: u16) {
|
||||
if self.registers.status.contains(Status::PS_NEGATIVE) {
|
||||
self.registers.program_counter = addr;
|
||||
}
|
||||
}
|
||||
|
||||
fn branch_if_positive(&mut self, addr: Address) {
|
||||
fn branch_if_positive(&mut self, addr: u16) {
|
||||
if !self.registers.status.contains(Status::PS_NEGATIVE) {
|
||||
self.registers.program_counter = addr;
|
||||
}
|
||||
}
|
||||
|
||||
fn branch_if_overflow_clear(&mut self, addr: Address) {
|
||||
fn branch_if_overflow_clear(&mut self, addr: u16) {
|
||||
if !self.registers.status.contains(Status::PS_OVERFLOW) {
|
||||
self.registers.program_counter = addr;
|
||||
}
|
||||
}
|
||||
|
||||
fn branch_if_overflow_set(&mut self, addr: Address) {
|
||||
fn branch_if_overflow_set(&mut self, addr: u16) {
|
||||
if self.registers.status.contains(Status::PS_OVERFLOW) {
|
||||
self.registers.program_counter = addr;
|
||||
}
|
||||
@ -773,13 +773,13 @@ impl CPU {
|
||||
}
|
||||
|
||||
fn push_on_stack(&mut self, val: u8) {
|
||||
let addr = self.registers.stack_pointer.to_address();
|
||||
let addr = self.registers.stack_pointer.to_u16();
|
||||
self.memory.set_byte(addr, val);
|
||||
self.registers.stack_pointer.decrement();
|
||||
}
|
||||
|
||||
fn pull_from_stack(&mut self) -> u8 {
|
||||
let addr = self.registers.stack_pointer.to_address();
|
||||
let addr = self.registers.stack_pointer.to_u16();
|
||||
let out = self.memory.get_byte(addr);
|
||||
self.registers.stack_pointer.increment();
|
||||
out
|
||||
|
@ -113,8 +113,8 @@ pub enum Instruction {
|
||||
pub enum OpInput {
|
||||
UseImplied,
|
||||
UseImmediate(u8),
|
||||
UseRelative(i8),
|
||||
UseAddress(Address),
|
||||
UseRelative(u16),
|
||||
UseAddress(u16),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
@ -136,16 +136,19 @@ pub enum AddressingMode {
|
||||
// zero page address) plus Y register
|
||||
}
|
||||
|
||||
fn arr_to_addr(arr: &[u8]) -> Address {
|
||||
fn xextend(x: u8) -> u16 {
|
||||
u16::from(x)
|
||||
}
|
||||
|
||||
fn arr_to_addr(arr: &[u8]) -> u16 {
|
||||
debug_assert!(arr.len() == 2);
|
||||
|
||||
let x = u16::from(arr[0]) + (u16::from(arr[1]) << 8usize);
|
||||
Address(x)
|
||||
u16::from(arr[0]) + (u16::from(arr[1]) << 8usize)
|
||||
}
|
||||
|
||||
impl AddressingMode {
|
||||
pub fn extra_bytes(self) -> AddressDiff {
|
||||
let x = match self {
|
||||
pub fn extra_bytes(self) -> u16 {
|
||||
match self {
|
||||
AddressingMode::Accumulator => 0,
|
||||
AddressingMode::Implied => 0,
|
||||
AddressingMode::Immediate => 1,
|
||||
@ -159,15 +162,11 @@ impl AddressingMode {
|
||||
AddressingMode::Indirect => 2,
|
||||
AddressingMode::IndexedIndirectX => 1,
|
||||
AddressingMode::IndirectIndexedY => 1,
|
||||
};
|
||||
AddressDiff(x)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process(self, cpu: &CPU, arr: &[u8]) -> OpInput {
|
||||
debug_assert!({
|
||||
let AddressDiff(x) = self.extra_bytes();
|
||||
arr.len() == x as usize
|
||||
});
|
||||
debug_assert!(arr.len() == self.extra_bytes() as usize);
|
||||
|
||||
let x = cpu.registers.index_x as u8;
|
||||
let y = cpu.registers.index_y as u8;
|
||||
@ -187,24 +186,29 @@ impl AddressingMode {
|
||||
// Use [u8, ..1] from instruction
|
||||
// Interpret as zero page address
|
||||
// (Output: an 8-bit zero-page address)
|
||||
OpInput::UseAddress(Address(u16::from(arr[0])))
|
||||
OpInput::UseAddress(u16::from(arr[0]))
|
||||
}
|
||||
AddressingMode::ZeroPageX => {
|
||||
// Use [u8, ..1] from instruction
|
||||
// Add to X register (as u8 -- the final address is in 0-page)
|
||||
// (Output: an 8-bit zero-page address)
|
||||
OpInput::UseAddress(Address(u16::from(arr[0] + x)))
|
||||
OpInput::UseAddress(u16::from(arr[0].wrapping_add(x)))
|
||||
}
|
||||
AddressingMode::ZeroPageY => {
|
||||
// Use [u8, ..1] from instruction
|
||||
// Add to Y register (as u8 -- the final address is in 0-page)
|
||||
// (Output: an 8-bit zero-page address)
|
||||
OpInput::UseAddress(Address(u16::from(arr[0] + y)))
|
||||
OpInput::UseAddress(u16::from(arr[0].wrapping_add(y)))
|
||||
}
|
||||
AddressingMode::Relative => {
|
||||
// Use [u8, ..1] from instruction
|
||||
// (interpret as relative...)
|
||||
OpInput::UseRelative(arr[0] as i8)
|
||||
// (This is sign extended to a 16-but data type, but an unsigned one: u16. It's a
|
||||
// little weird, but it's so we can add the PC and the offset easily)
|
||||
let offset = arr[0];
|
||||
let sign_extend = if offset & 0x80 == 0x80 { 0xffu8 } else { 0x0 };
|
||||
let rel = u16::from_le_bytes([offset, sign_extend]);
|
||||
OpInput::UseRelative(rel)
|
||||
}
|
||||
AddressingMode::Absolute => {
|
||||
// Use [u8, ..2] from instruction as address
|
||||
@ -214,18 +218,18 @@ impl AddressingMode {
|
||||
AddressingMode::AbsoluteX => {
|
||||
// Use [u8, ..2] from instruction as address, add X
|
||||
// (Output: a 16-bit address)
|
||||
OpInput::UseAddress(arr_to_addr(arr) + AddressDiff(i32::from(x)))
|
||||
OpInput::UseAddress(arr_to_addr(arr).wrapping_add(xextend(x)))
|
||||
}
|
||||
AddressingMode::AbsoluteY => {
|
||||
// Use [u8, ..2] from instruction as address, add Y
|
||||
// (Output: a 16-bit address)
|
||||
OpInput::UseAddress(arr_to_addr(arr) + AddressDiff(i32::from(y)))
|
||||
OpInput::UseAddress(arr_to_addr(arr).wrapping_add(xextend(y)))
|
||||
}
|
||||
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 = memory.get_slice(arr_to_addr(arr), AddressDiff(2));
|
||||
let slice = memory.get_slice(arr_to_addr(arr), 2);
|
||||
OpInput::UseAddress(arr_to_addr(slice))
|
||||
}
|
||||
AddressingMode::IndexedIndirectX => {
|
||||
@ -233,8 +237,8 @@ impl AddressingMode {
|
||||
// Add to X register with 0-page wraparound, like ZeroPageX.
|
||||
// This is where the absolute (16-bit) target address is stored.
|
||||
// (Output: a 16-bit address)
|
||||
let start = arr[0] + x;
|
||||
let slice = memory.get_slice(Address(u16::from(start)), AddressDiff(2));
|
||||
let start = arr[0].wrapping_add(x);
|
||||
let slice = memory.get_slice(u16::from(start), 2);
|
||||
OpInput::UseAddress(arr_to_addr(slice))
|
||||
}
|
||||
AddressingMode::IndirectIndexedY => {
|
||||
@ -243,8 +247,8 @@ impl AddressingMode {
|
||||
// Add Y register to this address to get the final address
|
||||
// (Output: a 16-bit address)
|
||||
let start = arr[0];
|
||||
let slice = memory.get_slice(Address(u16::from(start)), AddressDiff(2));
|
||||
OpInput::UseAddress(arr_to_addr(slice) + AddressDiff(i32::from(y)))
|
||||
let slice = memory.get_slice(u16::from(start), (2));
|
||||
OpInput::UseAddress(arr_to_addr(slice).wrapping_add(xextend(y)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
use crate::address::{Address, AddressDiff};
|
||||
use crate::num::ToPrimitive;
|
||||
|
||||
// JAM: We can probably come up with a better way to represent address ranges.
|
||||
// Address range type?
|
||||
@ -67,28 +68,31 @@ impl Memory {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_byte(&self, address: Address) -> u8 {
|
||||
self.bytes[address.to_usize()]
|
||||
pub fn get_byte(&self, address: u16) -> u8 {
|
||||
self.bytes[address as usize]
|
||||
}
|
||||
|
||||
pub fn get_byte_mut_ref(&mut self, address: Address) -> &mut u8 {
|
||||
&mut self.bytes[address.to_usize()]
|
||||
pub fn get_byte_mut_ref(&mut self, address: u16) -> &mut u8 {
|
||||
&mut self.bytes[address as usize]
|
||||
}
|
||||
|
||||
pub fn get_slice(&self, start: Address, diff: AddressDiff) -> &[u8] {
|
||||
&self.bytes[start.to_usize()..(start + diff).to_usize()]
|
||||
pub fn get_slice(&self, start: u16, diff: u16) -> &[u8] {
|
||||
let orig: usize = start.into();
|
||||
let end = orig + diff as usize;
|
||||
|
||||
&self.bytes[orig..end]
|
||||
}
|
||||
|
||||
// Sets the byte at the given address to the given value and returns the
|
||||
// previous value at the address.
|
||||
pub fn set_byte(&mut self, address: Address, value: u8) -> u8 {
|
||||
pub fn set_byte(&mut self, address: u16, value: u8) -> u8 {
|
||||
let old_value = self.get_byte(address);
|
||||
self.bytes[address.to_usize()] = value;
|
||||
self.bytes[address as usize] = value;
|
||||
old_value
|
||||
}
|
||||
|
||||
pub fn set_bytes(&mut self, start: Address, values: &[u8]) {
|
||||
let start = start.to_usize();
|
||||
pub fn set_bytes(&mut self, start: u16, values: &[u8]) {
|
||||
let start = start as usize;
|
||||
|
||||
// This panics if the range is invalid
|
||||
let end = start + values.len();
|
||||
@ -96,8 +100,8 @@ impl Memory {
|
||||
self.bytes[start..end].copy_from_slice(values);
|
||||
}
|
||||
|
||||
pub fn is_stack_address(address: Address) -> bool {
|
||||
(STACK_ADDRESS_LO..=STACK_ADDRESS_HI).contains(&address)
|
||||
pub fn is_stack_address(address: u16) -> bool {
|
||||
address > 0xff && address < 0x200
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,6 +151,11 @@ impl StackPointer {
|
||||
STACK_ADDRESS_LO + AddressDiff(i32::from(self.0))
|
||||
}
|
||||
|
||||
pub fn to_u16(self) -> u16 {
|
||||
let StackPointer(val) = self;
|
||||
u16::from_le_bytes([val, 0x01])
|
||||
}
|
||||
|
||||
pub fn decrement(&mut self) {
|
||||
self.0 = self.0.wrapping_sub(1);
|
||||
}
|
||||
@ -166,7 +171,7 @@ pub struct Registers {
|
||||
pub index_x: i8,
|
||||
pub index_y: i8,
|
||||
pub stack_pointer: StackPointer,
|
||||
pub program_counter: Address,
|
||||
pub program_counter: u16,
|
||||
pub status: Status,
|
||||
}
|
||||
|
||||
@ -184,7 +189,7 @@ impl Registers {
|
||||
index_x: 0,
|
||||
index_y: 0,
|
||||
stack_pointer: StackPointer(STACK_ADDRESS_HI.get_offset()),
|
||||
program_counter: Address(0),
|
||||
program_counter: 0,
|
||||
status: Status::default(),
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user