remove Address and AddressDiff from equation

This commit is contained in:
Sam M W 2022-10-18 06:57:59 +01:00
parent f3d3bf470f
commit 4b26e83529
4 changed files with 71 additions and 58 deletions

View File

@ -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

View File

@ -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)))
}
}
}

View File

@ -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
}
}

View File

@ -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(),
}
}