Group One instructions done EXCEPT for modes (Indirect, X) and (Indirect), Y

master
Joey Pollack 2 years ago
parent 4987266110
commit 7021dd1e56

@ -3,6 +3,25 @@
use super::{R6502, Bus}; use super::{R6502, Bus};
#[derive(Clone, Copy, PartialEq)]
pub enum ModeID
{
IMP, // Implied
ACM, // Accumulator - Not using, IMP might cover this
IMM, // Immediate
ZP0, // Zero Page
ZPX, // Zero Page, X
ZPY, // Zero Page, Y
REL, // Relative
ABS, // Absolute
ABX, // Absolute, X
ABY, // Aboslute, Y
IND, // Indirect
IZX, // Indirect, X
IZY, // Indirect, Y
}
// Instruction decoding: // Instruction decoding:
// https://llx.com/Neil/a2/opcodes.html // https://llx.com/Neil/a2/opcodes.html
@ -27,7 +46,7 @@ use super::{R6502, Bus};
pub struct AddressingModes; pub struct AddressingModes;
impl AddressingModes impl AddressingModes
{ {
pub const GROUP_ONE_ADDRS: [fn(&mut R6502, &mut dyn Bus); 8] = [ pub const GROUP_ONE_ADDRS: [fn(&mut R6502, &mut dyn Bus) -> ModeID; 8] = [
AddressingModes::IZX, AddressingModes::IZX,
AddressingModes::ZP0, AddressingModes::ZP0,
AddressingModes::IMM, AddressingModes::IMM,
@ -44,98 +63,120 @@ impl AddressingModes
impl AddressingModes impl AddressingModes
{ {
// This is also the accumulator mode // This is also the accumulator mode
pub fn IMP(cpu: &mut R6502, bus: &mut dyn Bus) pub fn IMP(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
cpu.working_data = cpu.a as u16; cpu.working_data = cpu.a as u16;
ModeID::IMP
} }
pub fn IMM(cpu: &mut R6502, bus: &mut dyn Bus) pub fn IMM(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
cpu.working_data = bus.read(cpu.pc) as u16; cpu.working_data = bus.read(cpu.pc) as u16;
cpu.pc += 1; cpu.pc += 1;
ModeID::IMM
} }
pub fn ZP0(cpu: &mut R6502, bus: &mut dyn Bus) pub fn ZP0(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
let working_addr = bus.read(cpu.pc) as u16 & 0x00FF; cpu.working_addr = bus.read(cpu.pc) as u16 & 0x00FF;
cpu.pc += 1; cpu.pc += 1;
cpu.working_data = bus.read(working_addr) as u16; cpu.working_data = bus.read(cpu.working_addr) as u16;
ModeID::ZP0
} }
pub fn ZPX(cpu: &mut R6502, bus: &mut dyn Bus) pub fn ZPX(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
let mut working_addr = bus.read(cpu.pc) as u16 & 0x00FF; cpu.working_addr = bus.read(cpu.pc) as u16 & 0x00FF;
working_addr += cpu.x as u16; cpu.working_addr += cpu.x as u16;
cpu.pc += 1; cpu.pc += 1;
cpu.working_data = bus.read(working_addr) as u16; cpu.working_data = bus.read(cpu.working_addr) as u16;
ModeID::ZPX
} }
pub fn ZPY(cpu: &mut R6502, bus: &mut dyn Bus) pub fn ZPY(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
let mut working_addr = bus.read(cpu.pc) as u16 & 0x00FF; cpu.working_addr = bus.read(cpu.pc) as u16 & 0x00FF;
working_addr += cpu.y as u16; cpu.working_addr += cpu.y as u16;
cpu.pc += 1; cpu.pc += 1;
cpu.working_data = bus.read(working_addr) as u16; cpu.working_data = bus.read(cpu.working_addr) as u16;
ModeID::ZPY
} }
pub fn REL(cpu: &mut R6502, bus: &mut dyn Bus) pub fn REL(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
// NOTE: Not sure if we can use the working_data variable for this. // NOTE: Not sure if we can use the working_data variable for this.
// if any instruction using this address mode needs extra data read // if any instruction using this address mode needs extra data read
// then we need another variable to store this address // then we need another variable to store this address
//
// Use working_addr to just like the other modes
cpu.working_data = bus.read(cpu.pc) as u16; cpu.working_data = bus.read(cpu.pc) as u16;
cpu.pc += 1; cpu.pc += 1;
ModeID::REL
} }
pub fn ABS(cpu: &mut R6502, bus: &mut dyn Bus) pub fn ABS(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
cpu.working_data = bus.read(cpu.pc) as u16; cpu.working_addr = bus.read(cpu.pc) as u16;
cpu.pc += 1; cpu.pc += 1;
cpu.working_data |= (bus.read(cpu.pc) as u16) << 8; cpu.working_addr |= (bus.read(cpu.pc) as u16) << 8;
cpu.pc += 1; cpu.pc += 1;
cpu.working_data = bus.read(cpu.working_data) as u16 & 0x00FF; cpu.working_data = bus.read(cpu.working_addr) as u16 & 0x00FF;
ModeID::ABS
} }
pub fn ABX(cpu: &mut R6502, bus: &mut dyn Bus) pub fn ABX(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
cpu.working_data = bus.read(cpu.pc) as u16; cpu.working_addr = bus.read(cpu.pc) as u16;
cpu.pc += 1; cpu.pc += 1;
cpu.working_data |= (bus.read(cpu.pc) as u16) << 8; cpu.working_addr |= (bus.read(cpu.pc) as u16) << 8;
cpu.pc += 1; cpu.pc += 1;
cpu.working_data += cpu.x as u16; cpu.working_addr += cpu.x as u16;
cpu.working_data = bus.read(cpu.working_data) as u16 & 0x00FF; cpu.working_data = bus.read(cpu.working_addr) as u16 & 0x00FF;
ModeID::ABX
} }
pub fn ABY(cpu: &mut R6502, bus: &mut dyn Bus) pub fn ABY(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
cpu.working_data = bus.read(cpu.pc) as u16; cpu.working_addr = bus.read(cpu.pc) as u16;
cpu.pc += 1; cpu.pc += 1;
cpu.working_data |= (bus.read(cpu.pc) as u16) << 8; cpu.working_addr |= (bus.read(cpu.pc) as u16) << 8;
cpu.pc += 1; cpu.pc += 1;
cpu.working_data += cpu.y as u16; cpu.working_addr += cpu.y as u16;
cpu.working_data = bus.read(cpu.working_addr) as u16 & 0x00FF;
cpu.working_data = bus.read(cpu.working_data) as u16 & 0x00FF; ModeID::ABY
} }
pub fn IND(cpu: &mut R6502, bus: &mut dyn Bus) pub fn IND(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
ModeID::IND
} }
pub fn IZX(cpu: &mut R6502, bus: &mut dyn Bus) pub fn IZX(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
ModeID::IZX
} }
pub fn IZY(cpu: &mut R6502, bus: &mut dyn Bus) pub fn IZY(cpu: &mut R6502, bus: &mut dyn Bus) -> ModeID
{ {
ModeID::IZY
} }
} }

@ -87,8 +87,10 @@ impl Instructions
// https://github.com/OneLoneCoder/olcNES/blob/master/Part%232%20-%20CPU/olc6502.cpp#L659 // https://github.com/OneLoneCoder/olcNES/blob/master/Part%232%20-%20CPU/olc6502.cpp#L659
pub fn ADC(cpu: &mut R6502, bus: &mut dyn Bus) pub fn ADC(cpu: &mut R6502, bus: &mut dyn Bus)
{ {
let carry = cpu.check_flag(Flags::C) as u16;
// 16 bit addition to capture the carry easier // 16 bit addition to capture the carry easier
let temp: u16 = cpu.a as u16 + cpu.working_data; let temp: u16 = cpu.a as u16 + cpu.working_data + carry;
if temp > 255 if temp > 255
{ {
@ -118,7 +120,7 @@ impl Instructions
pub fn STA(cpu: &mut R6502, bus: &mut dyn Bus) pub fn STA(cpu: &mut R6502, bus: &mut dyn Bus)
{ {
bus.write(cpu.working_data, cpu.a); bus.write(cpu.working_addr, cpu.a);
} }
pub fn LDA(cpu: &mut R6502, bus: &mut dyn Bus) pub fn LDA(cpu: &mut R6502, bus: &mut dyn Bus)
@ -139,14 +141,77 @@ impl Instructions
pub fn CMP(cpu: &mut R6502, bus: &mut dyn Bus) pub fn CMP(cpu: &mut R6502, bus: &mut dyn Bus)
{ {
let data = cpu.working_data as u8;
if cpu.a >= data
{
cpu.set_flag(Flags::C);
}
else
{
cpu.clear_flag(Flags::C);
}
if cpu.a == data
{
cpu.set_flag(Flags::Z);
}
else
{
cpu.clear_flag(Flags::Z);
}
if cpu.a < data
{
cpu.set_flag(Flags::N);
}
else
{
cpu.clear_flag(Flags::N);
}
} }
// Using a technique written javidx9
// The code in this function falls under the License (OLC-3) SEE LICENSE FILE
// https://github.com/OneLoneCoder/olcNES/blob/master/Part%232%20-%20CPU/olc6502.cpp#L714
pub fn SBC(cpu: &mut R6502, bus: &mut dyn Bus) pub fn SBC(cpu: &mut R6502, bus: &mut dyn Bus)
{ {
// Seem to need the + 1 here for javidx9's algorithm to work
let value = (cpu.working_data ^ 0x00FF) + 1;
let carry = cpu.check_flag(Flags::C) as u16;
let temp: u16 = cpu.a as u16 + value + carry;
if temp > 255
{
cpu.set_flag(Flags::C);
}
if temp == 0
{
cpu.set_flag(Flags::Z);
}
let did_overflow = (!((cpu.a as u16) ^ (value)) & ((cpu.a as u16) ^ temp)) & 0x0080;
cpu.clear_flag(Flags::V);
if did_overflow > 0
{
cpu.set_flag(Flags::V);
}
cpu.clear_flag(Flags::N);
if temp & 0x80 > 0
{
cpu.set_flag(Flags::N);
}
cpu.a = (temp & 0x00FF) as u8;
} }
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// GROUP TWO // GROUP TWO
///////////////////////////////////////////////////////////
// GROUP THREE
} }

@ -4,7 +4,7 @@
mod addressing_modes; mod addressing_modes;
mod instructions; mod instructions;
use addressing_modes::AddressingModes; use addressing_modes::{AddressingModes, ModeID};
use instructions::Instructions; use instructions::Instructions;
pub trait Bus pub trait Bus
@ -56,8 +56,9 @@ pub struct R6502
cycles: u32, // Track cycles cycles: u32, // Track cycles
// Helper Vars // Helper Vars
addr_mode: ModeID,
working_data: u16, // value fetched for the ALU working_data: u16, // value fetched for the ALU
// working_addr: u16, working_addr: u16,
} }
impl R6502 impl R6502
@ -65,7 +66,7 @@ impl R6502
// constructor // constructor
pub fn new() -> R6502 pub fn new() -> R6502
{ {
R6502 { a: 0, x: 0, y: 0, pc: 0, sp: 0, status: 0, cycles: 0, working_data: 0 } R6502 { a: 0, x: 0, y: 0, pc: 0, sp: 0, status: 0, cycles: 0, addr_mode: ModeID::IMP, working_data: 0, working_addr: 0 }
} }
// Debug Access // Debug Access
@ -157,9 +158,14 @@ impl R6502
self.status &= !(bit as u8); self.status &= !(bit as u8);
} }
pub fn check_flag(&mut self, bit: Flags) -> bool pub fn check_flag(&mut self, bit: Flags) -> u8
{ {
self.status & (bit as u8) > 0 if self.status & (bit as u8) > 0
{
return 1;
}
return 0;
} }
} }
@ -187,7 +193,7 @@ fn exe_group_one(instruction: u8, cpu: &mut R6502, bus: &mut dyn Bus)
let addr_mask = (instruction & 0x1C) >> 2; let addr_mask = (instruction & 0x1C) >> 2;
let op_mask = (instruction & 0xE0) >> 5; let op_mask = (instruction & 0xE0) >> 5;
AddressingModes::GROUP_ONE_ADDRS[addr_mask as usize](cpu, bus); cpu.addr_mode = AddressingModes::GROUP_ONE_ADDRS[addr_mask as usize](cpu, bus);
Instructions::GROUP_ONE_OPS[op_mask as usize](cpu, bus); Instructions::GROUP_ONE_OPS[op_mask as usize](cpu, bus);
} }

@ -0,0 +1,216 @@
#![allow(dead_code, non_snake_case)]
use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers, Flags};
#[test]
fn IMM()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Write the program to memory
// ADC 6
bus.write(addr, 0x69); // ADC - Immediate mode
bus.write(addr + 1, 0x06); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x04);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0A in the A register?
assert_eq!(0x0A, cpu.debug_get_reg(Registers::A), "Failed basic addition");
///////////////////////////////////////////
// EXTRA TESTING
// Add with carry in
// Write the program to memory
// ADC 6
bus.write(addr, 0x69); // ADC - Immediate mode
bus.write(addr + 1, 0x06); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu internals
cpu.debug_set_reg(Registers::A, 0x04);
cpu.set_flag(Flags::C);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A), "Failed addition with carry");
// Add with overflow
// Write the program to memory
// ADC 126
bus.write(addr, 0x69); // ADC - Immediate mode
bus.write(addr + 1, 126); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu internals
cpu.debug_set_reg(Registers::A, 0x04);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 130 in the A register?
assert_eq!(130, cpu.debug_get_reg(Registers::A));
// Is the overflow bit set?
assert_eq!(1, cpu.check_flag(Flags::V), "Failed addition with overflow");
}
#[test]
fn ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x04 into memory in the zero page
bus.write(0x000B, 0x04);
// ADC #6
bus.write(addr, 0x65); // ADC - Zero Page mode
bus.write(addr + 1, 0x0B); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x06);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0A in the A register?
assert_eq!(0x0A, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x000B, 0x04);
// ADC #A
bus.write(addr, 0x75); // ADC - Zero Page, X mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x06);
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0A in the A register?
assert_eq!(0x0A, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x010B, 0x06);
// AND $10B
bus.write(addr, 0x6D); // ADC - Absolute mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x04);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x09 in the A register?
assert_eq!(0x0A, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory
bus.write(0x010C, 0x04);
// ADC $10C
bus.write(addr, 0x7D); // ADC - Absolute, X mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x06);
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0A in the A register?
assert_eq!(0x0A, cpu.debug_get_reg(Registers::A));
}

@ -0,0 +1,207 @@
#![allow(dead_code, non_snake_case)]
use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers, Flags};
#[test]
fn IMM()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// AND #3
bus.write(addr, 0x29); // AND - Immediate mode
bus.write(addr + 1, 0x03); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x000B, 0x03);
// AND #3
bus.write(addr, 0x25); // AND - Zero Page mode
bus.write(addr + 1, 0x0B); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x000B, 0x03);
// AND #3
bus.write(addr, 0x35); // AND - Zero Page, X mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x010B, 0x03);
// AND #3
bus.write(addr, 0x2D); // AND - Absolute mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
//cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x010C, 0x03);
// AND #3
bus.write(addr, 0x3D); // AND - Absolute, X mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x010C, 0x03);
// AND #3
bus.write(addr, 0x39); // AND - Absolute, X mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::Y, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}

@ -0,0 +1,569 @@
#![allow(dead_code, non_snake_case)]
use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers, Flags};
//////////////////////////////////////////////////////////////////////////////
/// IMM IMM IMM IMM IMM IMM IMM IMM IMM
//////////////////////////////////////////////////////////////////////////////
#[test]
fn IMM()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
///////////////////////
// Parameter is less than A reg
// Program to compare 0x10 with 0x05 (0x05 will be the argument)
bus.write(addr, 0xC9); // CMP - Immediate mode
bus.write(addr + 1, 0x05); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Flag should be 1, Z N Flags should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is equal to the A reg
// Program to compare 0x10 with 0x10
bus.write(addr, 0xC9); // CMP - Immediate mode
bus.write(addr + 1, 0x10); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 1, N Flag should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(1, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is greater than A reg
// Program to compare 0x05 with 0x10
bus.write(addr, 0xC9); // CMP - Immediate mode
bus.write(addr + 1, 0x10); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x05);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 0, N Flag should be 1
assert_eq!(0, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(1, cpu.check_flag(Flags::N));
}
//////////////////////////////////////////////////////////////////////////////
/// ZP0 ZP0 ZP0 ZP0 ZP0 ZP0 ZP0 ZP0 ZP0
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
///////////////////////
// Parameter is less than A reg
// Manually put 0x05 into memory in the zero page
bus.write(0x000A, 0x05);
// Program to compare 0x10 with 0x05 (0x05 will be the argument)
bus.write(addr, 0xC5); // CMP - Zero Page mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Flag should be 1, Z N Flags should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is equal to the A reg
// Manually put 0x05 into memory in the zero page
bus.write(0x000A, 0x10);
// Program to compare 0x10 with 0x10
bus.write(addr, 0xC5); // CMP - Zero Page mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 1, N Flag should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(1, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is greater than A reg
// Manually put 0x05 into memory in the zero page
bus.write(0x000A, 0x10);
// Program to compare 0x10 with 0x10
bus.write(addr, 0xC5); // CMP - Zero Page mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x05);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 0, N Flag should be 1
assert_eq!(0, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(1, cpu.check_flag(Flags::N));
}
//////////////////////////////////////////////////////////////////////////////
/// ZPX ZPX ZPX ZPX ZPX ZPX ZPX ZPX ZPX
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
///////////////////////
// Parameter is less than A reg
// Manually put 0x05 into memory in the zero page
bus.write(0x000A, 0x05);
// Program to compare 0x05 and 0x10
bus.write(addr, 0xD5); // CMP - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x10);
cpu.debug_set_reg(Registers::X, 0x06);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Flag should be 1, Z N Flags should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is equal to the A reg
// Manually put 0x10 into memory in the zero page
bus.write(0x000A, 0x10);
// Program to compare 0x05 and 0x10
bus.write(addr, 0xD5); // CMP - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x10);
cpu.debug_set_reg(Registers::X, 0x06);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 1, N Flag should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(1, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is greater than A reg
// Manually put 0x10 into memory in the zero page
bus.write(0x000A, 0x10);
// Program to compare 0x05 and 0x10
bus.write(addr, 0xD5); // CMP - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x05);
cpu.debug_set_reg(Registers::X, 0x06);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 0, N Flag should be 1
assert_eq!(0, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(1, cpu.check_flag(Flags::N));
}
//////////////////////////////////////////////////////////////////////////////
/// ABS ABS ABS ABS ABS ABS ABS ABS ABS
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
///////////////////////
// Parameter is less than A reg
// Manually put 0x05 into memory
bus.write(0x010A, 0x05);
// Program to compare 0x05 and 0x10
bus.write(addr, 0xCD); // CMP - Absolute mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Flag should be 1, Z N Flags should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is equal to the A reg
// Manually put 0x10 into memory
bus.write(0x010A, 0x10);
// Program to compare 0x10 and 0x10
bus.write(addr, 0xCD); // LDA - Absolute mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 1, N Flag should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(1, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is greater than A reg
// Manually put 0x10 into memory
bus.write(0x010A, 0x10);
// Program to compare 0x05 and 0x10
bus.write(addr, 0xCD); // LDA - Absolute mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x05);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 0, N Flag should be 1
assert_eq!(0, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(1, cpu.check_flag(Flags::N));
}
//////////////////////////////////////////////////////////////////////////////
/// ABX ABX ABX ABX ABX ABX ABX ABX ABX
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
///////////////////////
// Parameter is less than A reg
// Manually put 0x05 into memory
bus.write(0x010B, 0x05);
// Program to compare 0x05 to 0x10
bus.write(addr, 0xDD); // CMP - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Flag should be 1, Z N Flags should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is equal to the A reg
// Manually put 0x10 into memory
bus.write(0x010B, 0x10);
// Program to compare 0x05 to 0x10
bus.write(addr, 0xDD); // CMP - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 1, N Flag should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(1, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is greater than A reg
// Manually put 0x05 into memory
bus.write(0x010B, 0x10);
// Program to compare 0x05 to 0x10
bus.write(addr, 0xDD); // CMP - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
cpu.debug_set_reg(Registers::A, 0x05);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 0, N Flag should be 1
assert_eq!(0, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(1, cpu.check_flag(Flags::N));
}
//////////////////////////////////////////////////////////////////////////////
/// ABY ABY ABY ABY ABY ABY ABY ABY ABY
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
///////////////////////
// Parameter is less than A reg
// Manually put 0x05 into memory
bus.write(0x010B, 0x05);
// Program to compare 0x05 to 0x10
bus.write(addr, 0xD9); // CMP - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Flag should be 1, Z N Flags should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is equal to the A reg
// Manually put 0x10 into memory
bus.write(0x010B, 0x10);
// Program to compare 0x05 to 0x10
bus.write(addr, 0xD9); // CMP - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
cpu.debug_set_reg(Registers::A, 0x10);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 1, N Flag should be 0
assert_eq!(1, cpu.check_flag(Flags::C));
assert_eq!(1, cpu.check_flag(Flags::Z));
assert_eq!(0, cpu.check_flag(Flags::N));
///////////////////////
// Parameter is greater than A reg
// Manually put 0x05 into memory
bus.write(0x010B, 0x10);
// Program to compare 0x05 to 0x10
bus.write(addr, 0xD9); // CMP - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
cpu.debug_set_reg(Registers::A, 0x05);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// C Z Flags should be 0, N Flag should be 1
assert_eq!(0, cpu.check_flag(Flags::C));
assert_eq!(0, cpu.check_flag(Flags::Z));
assert_eq!(1, cpu.check_flag(Flags::N));
}

@ -0,0 +1,207 @@
#![allow(dead_code, non_snake_case)]
use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers};
#[test]
fn IMM()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// AND #3
bus.write(addr, 0x49); // EOR - Immediate mode
bus.write(addr + 1, 0x03); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x09 in the A register?
assert_eq!(0x09, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x000B, 0x03);
// AND #3
bus.write(addr, 0x45); // EOR - Zero Page mode
bus.write(addr + 1, 0x0B); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x09 in the A register?
assert_eq!(0x09, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x000B, 0x03);
// AND #3
bus.write(addr, 0x55); // EOR - Zero Page, X mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x09 in the A register?
assert_eq!(0x09, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x010B, 0x03);
// AND #3
bus.write(addr, 0x4D); // EOR - Absolute mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
//cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x09 in the A register?
assert_eq!(0x09, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x03 into memory
bus.write(0x010C, 0x03);
// EOR $10B
bus.write(addr, 0x5D); // EOR - Absolute, X mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x09 in the A register?
assert_eq!(0x09, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x010C, 0x03);
// AND #3
bus.write(addr, 0x59); // EOR - Absolute, X mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::Y, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x09 in the A register?
assert_eq!(0x09, cpu.debug_get_reg(Registers::A));
}

@ -0,0 +1,194 @@
#![allow(dead_code, non_snake_case)]
use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers};
#[test]
fn IMM()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Program to load 0x08 into the accumulator
bus.write(addr, 0xA9); // LDA - Immediate mode
bus.write(addr + 1, 0x08); // Argument
// Restart cpu
cpu.reset(&mut bus);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x08 into memory in the zero page
bus.write(0x000A, 0x08);
// Program to load 0x08 into the accumulator
bus.write(addr, 0xA5); // LDA - Zero Page mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x08 into memory in the zero page
bus.write(0x000A, 0x08);
// Program to load 0x08 into the accumulator
bus.write(addr, 0xB5); // LDA - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x06);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x08 into memory in the zero page
bus.write(0x010A, 0x08);
// Program to load 0x08 into the accumulator
bus.write(addr, 0xAD); // LDA - Absolute mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x08 into memory in the zero page
bus.write(0x010B, 0x08);
// Program to load 0x08 into the accumulator
bus.write(addr, 0xBD); // LDA - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x08 into memory in the zero page
bus.write(0x010B, 0x08);
// Program to load 0x08 into the accumulator
bus.write(addr, 0xB9); // LDA - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}

@ -0,0 +1,227 @@
#![allow(dead_code, non_snake_case)]
// mod test_bus;
// #[cfg(test)]
use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers};
#[test]
fn IMM()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// ORA #2
bus.write(addr, 0x09); // ORA - Immediate mode
bus.write(addr + 1, 0x02); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x000A, 0x02);
// ORA #2
bus.write(addr, 0x05); // ORA - Zero Page mode
bus.write(addr +1, 0x0A); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x000A, 0x02);
// ORA #2
bus.write(addr, 0x15); // ORA - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x06);
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x010A, 0x02);
// ORA #2
bus.write(addr, 0x0D); // ORA - Absolute mode
bus.write(addr + 1, 0x0A); // Argument (memory address of the value we want to OR with)
bus.write(addr + 2, 0x01); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
// cpu.debug_set_reg(Registers::X, 0x06);
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x010B, 0x02);
// ORA #2
bus.write(addr, 0x1D); // ORA - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument (memory address of the value we want to OR with)
bus.write(addr + 2, 0x01); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x010B, 0x02);
// ORA #2
bus.write(addr, 0x19); // ORA - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument (memory address of the value we want to OR with)
bus.write(addr + 2, 0x01); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}

@ -0,0 +1,233 @@
#![allow(dead_code, non_snake_case)]
use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers};
//////////////////////////////////////////////////////////////////////////////
/// IMM IMM IMM IMM IMM IMM IMM IMM IMM
//////////////////////////////////////////////////////////////////////////////
#[test]
fn IMM()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Program to subtract 0x06 from 0x0A
bus.write(addr, 0xE9); // SBC - Immediate mode
bus.write(addr + 1, 0x06); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x04 in the A register?
assert_eq!(0x04, cpu.debug_get_reg(Registers::A));
}
//////////////////////////////////////////////////////////////////////////////
/// ZP0 ZP0 ZP0 ZP0 ZP0 ZP0 ZP0 ZP0 ZP0
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x06 into memory in the zero page
bus.write(0x000A, 0x06);
// Program to
bus.write(addr, 0xE5); // SBC - Zero Page mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x04 in the A register?
assert_eq!(0x04, cpu.debug_get_reg(Registers::A));
}
//////////////////////////////////////////////////////////////////////////////
/// ZPX ZPX ZPX ZPX ZPX ZPX ZPX ZPX ZPX
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x06 into memory in the zero page
bus.write(0x000A, 0x06);
// Program to
bus.write(addr, 0xF5); // - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x06);
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x04 in the A register?
assert_eq!(0x04, cpu.debug_get_reg(Registers::A));
}
//////////////////////////////////////////////////////////////////////////////
/// ABS ABS ABS ABS ABS ABS ABS ABS ABS
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x06 into memory in the zero page
bus.write(0x010A, 0x06);
// Program to
bus.write(addr, 0xED); // SBC - Absolute mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x04 in the A register?
assert_eq!(0x04, cpu.debug_get_reg(Registers::A));
}
//////////////////////////////////////////////////////////////////////////////
/// ABX ABX ABX ABX ABX ABX ABX ABX ABX
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x06 into memory in the zero page
bus.write(0x010B, 0x06);
// Program to
bus.write(addr, 0xFD); // SBC - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x04 in the A register?
assert_eq!(0x04, cpu.debug_get_reg(Registers::A));
}
//////////////////////////////////////////////////////////////////////////////
/// ABY ABY ABY ABY ABY ABY ABY ABY ABY
//////////////////////////////////////////////////////////////////////////////
#[test]
fn ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x08 into memory in the zero page
bus.write(0x010B, 0x06);
// Program to
bus.write(addr, 0xF9); // - Absolute, Y mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x04 in the A register?
assert_eq!(0x04, cpu.debug_get_reg(Registers::A));
}

@ -0,0 +1,185 @@
#![allow(dead_code, non_snake_case)]
use crate::tests::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers};
#[test]
fn ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
//bus.write(0x000B, 0x0A);
// STA $0A
bus.write(addr, 0x85); // STA - Zero Page mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0F);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0F at memory address 0x0A?
assert_eq!(0x0F, bus.read(0x0A));
}
#[test]
fn ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// STA
bus.write(addr, 0x95); // STA - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x06);
cpu.debug_set_reg(Registers::A, 0x0F);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0F at memory address 0x0A?
assert_eq!(0x0F, bus.read(0x0A));
}
#[test]
fn ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x010A, 0x02);
// STA
bus.write(addr, 0x8D); // STA - Absolute mode
bus.write(addr + 1, 0x0A); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
// cpu.debug_set_reg(Registers::X, 0x06);
cpu.debug_set_reg(Registers::A, 0x0F);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0F at memory address 0x010A?
assert_eq!(0x0F, bus.read(0x010A));
}
#[test]
fn ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// STA
bus.write(addr, 0x9D); // STA - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
cpu.debug_set_reg(Registers::A, 0x0F);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0F at memory address 0x010B?
assert_eq!(0x0F, bus.read(0x010B));
}
#[test]
fn ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x010B, 0x02);
// STA
bus.write(addr, 0x99); // STA - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
cpu.debug_set_reg(Registers::A, 0x0F);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0F at memory address 0x010B?
assert_eq!(0x0F, bus.read(0x010B));
}

@ -0,0 +1,24 @@
#[cfg(test)]
mod ORA;
#[cfg(test)]
mod AND;
#[cfg(test)]
mod EOR;
#[cfg(test)]
mod ADC;
#[cfg(test)]
mod LDA;
#[cfg(test)]
mod STA;
#[cfg(test)]
mod CMP;
#[cfg(test)]
mod SBC;

@ -4,628 +4,7 @@
mod test_bus; mod test_bus;
#[cfg(test)]
mod instructions
{
use super::test_bus::RAMBus;
use crate::r6502::{R6502, Bus, Registers};
//////////////////////////////////////////////////////////////////
/// ORA ORA ORA ORA
//////////////////////////////////////////////////////////////////
#[test]
fn ORA_IMM()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// ORA #2
bus.write(addr, 0x09); // ORA - Immediate mode
bus.write(addr + 1, 0x02); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ORA_ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x000A, 0x02);
// ORA #2
bus.write(addr, 0x05); // ORA - Zero Page mode
bus.write(addr +1, 0x0A); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ORA_ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x000A, 0x02);
// ORA #2
bus.write(addr, 0x15); // ORA - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x06);
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ORA_ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x010A, 0x02);
// ORA #2
bus.write(addr, 0x0D); // ORA - Absolute mode
bus.write(addr + 1, 0x0A); // Argument (memory address of the value we want to OR with)
bus.write(addr + 2, 0x01); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
// cpu.debug_set_reg(Registers::X, 0x06);
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ORA_ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x010B, 0x02);
// ORA #2
bus.write(addr, 0x1D); // ORA - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument (memory address of the value we want to OR with)
bus.write(addr + 2, 0x01); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
#[test]
fn ORA_ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x02 into memory in the zero page
bus.write(0x010B, 0x02);
// ORA #2
bus.write(addr, 0x19); // ORA - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument (memory address of the value we want to OR with)
bus.write(addr + 2, 0x01); // Argument (memory address of the value we want to OR with)
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
cpu.debug_set_reg(Registers::A, 0x09);
// Clock the cpu twice (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x0B in the A register?
assert_eq!(0x0B, cpu.debug_get_reg(Registers::A));
}
//////////////////////////////////////////////////////////////////
/// AND AND AND AND
//////////////////////////////////////////////////////////////////
#[test]
fn AND_IMM()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// AND #3
bus.write(addr, 0x29); // AND - Immediate mode
bus.write(addr + 1, 0x03); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn AND_ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x000B, 0x03);
// AND #3
bus.write(addr, 0x25); // AND - Zero Page mode
bus.write(addr + 1, 0x0B); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register? #[cfg(test)]
assert_eq!(0x02, cpu.debug_get_reg(Registers::A)); mod instructions;
}
#[test]
fn AND_ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x000B, 0x03);
// AND #3
bus.write(addr, 0x35); // AND - Zero Page, X mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn AND_ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x010B, 0x03);
// AND #3
bus.write(addr, 0x2D); // AND - Absolute mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
//cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn AND_ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x010C, 0x03);
// AND #3
bus.write(addr, 0x3D); // AND - Absolute, X mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
#[test]
fn AND_ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x0A into memory in the zero page
bus.write(0x010C, 0x03);
// AND #3
bus.write(addr, 0x39); // AND - Absolute, X mode
bus.write(addr + 1, 0x0B); // Argument
bus.write(addr + 2, 0x01); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::A, 0x0A);
cpu.debug_set_reg(Registers::Y, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x02 in the A register?
assert_eq!(0x02, cpu.debug_get_reg(Registers::A));
}
//////////////////////////////////////////////////////////////////
/// LDA LDA LDA LDA
//////////////////////////////////////////////////////////////////
#[test]
fn LDA_IMM()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Program to load 0x08 into the accumulator
bus.write(addr, 0xA9); // LDA - Immediate mode
bus.write(addr + 1, 0x08); // Argument
// Restart cpu
cpu.reset(&mut bus);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}
#[test]
fn LDA_ZP0()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x08 into memory in the zero page
bus.write(0x000A, 0x08);
// Program to load 0x08 into the accumulator
bus.write(addr, 0xA5); // LDA - Zero Page mode
bus.write(addr + 1, 0x0A); // Argument
// Restart cpu
cpu.reset(&mut bus);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}
#[test]
fn LDA_ZPX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x08 into memory in the zero page
bus.write(0x000A, 0x08);
// Program to load 0x08 into the accumulator
bus.write(addr, 0xB5); // LDA - Zero Page, X mode
bus.write(addr + 1, 0x04); // Argument
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x06);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}
#[test]
fn LDA_ABS()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x08 into memory in the zero page
bus.write(0x010A, 0x08);
// Program to load 0x08 into the accumulator
bus.write(addr, 0xAD); // LDA - Absolute mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}
#[test]
fn LDA_ABX()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x08 into memory in the zero page
bus.write(0x010B, 0x08);
// Program to load 0x08 into the accumulator
bus.write(addr, 0xBD); // LDA - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::X, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}
#[test]
fn LDA_ABY()
{
let mut cpu = R6502::new();
let mut bus = RAMBus::new();
// program address
let addr = 0x0020 as u16;
// Set the program counter address
bus.write(0xFFFC, (addr & 0x00FF) as u8); // low byte
bus.write(0xFFFD, ((addr & 0xFF00) >> 8) as u8); // high byte
// Manually put 0x08 into memory in the zero page
bus.write(0x010B, 0x08);
// Program to load 0x08 into the accumulator
bus.write(addr, 0xB9); // LDA - Absolute, X mode
bus.write(addr + 1, 0x0A); // Argument lo word
bus.write(addr + 2, 0x01); // Argument hi word
// Restart cpu
cpu.reset(&mut bus);
// manually setup the cpu registers
cpu.debug_set_reg(Registers::Y, 0x01);
// Clock the cpu to run the program (Clock essentially runs one full instruction)
cpu.clock(&mut bus);
// Is 0x08 in the A register?
assert_eq!(0x08, cpu.debug_get_reg(Registers::A));
}
}

@ -36,8 +36,8 @@ Instructions:
✔ 011 ADC @done(23-11-06 19:59) ✔ 011 ADC @done(23-11-06 19:59)
✔ 100 STA @done(23-11-07 15:04) ✔ 100 STA @done(23-11-07 15:04)
✔ 101 LDA @done(23-11-06 18:55) ✔ 101 LDA @done(23-11-06 18:55)
☐ 110 CMP ✔ 110 CMP @done(23-11-09 13:24)
☐ 111 SBC ✔ 111 SBC @done(23-11-09 13:24)
GROUP TWO: GROUP TWO:
☐ 000 ASL ☐ 000 ASL

Loading…
Cancel
Save