|
|
|
|
|
|
|
|
|
#![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));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/// IZX IZX IZX IZX IZX IZX IZX IZX IZX
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
#[test]
|
|
|
|
|
fn IZX()
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
// Manually put 0x010B into the Zero Page
|
|
|
|
|
bus.write(0x000B, 0x0B);
|
|
|
|
|
bus.write(0x000C, 0x01);
|
|
|
|
|
|
|
|
|
|
// Program to compare 0x05 to 0x10
|
|
|
|
|
bus.write(addr, 0xC1); // CMP - Indirect, X mode
|
|
|
|
|
bus.write(addr + 1, 0x0A); // Argument lo 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);
|
|
|
|
|
|
|
|
|
|
// Manually put 0x010B into the Zero Page
|
|
|
|
|
bus.write(0x000B, 0x0B);
|
|
|
|
|
bus.write(0x000C, 0x01);
|
|
|
|
|
|
|
|
|
|
// Program to compare 0x05 to 0x10
|
|
|
|
|
bus.write(addr, 0xC1); // CMP - Indirect, X mode
|
|
|
|
|
bus.write(addr + 1, 0x0A); // Argument lo 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, 0xC1); // CMP - Indirect, X mode
|
|
|
|
|
bus.write(addr + 1, 0x0A); // Argument lo 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));
|
|
|
|
|
}
|