mirror of
https://codeberg.org/sethm/symon.git
synced 2026-11-07 19:12:23 +00:00
* Add Support for All 65C02 Opcodes and all Rockwell/WDC opcodes except WAI/STP
* Add 65C02 Opcode tests * All tests pass, Klaus' 6502_functional_tests pass & Klaus' 65C02_extended_opcodes_test also all pass
This commit is contained in:
1 parent
faf5d22660
commit
a9c6d5964f
13 files changed
+2655
-153
No files matched your search
@@ -0,0 +1,125 @@
|
||||
package com.loomcom.symon;
|
||||
|
||||
import com.loomcom.symon.devices.Memory;
|
||||
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||
import junit.framework.*;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||
* in the 65C02 and 65816
|
||||
*/
|
||||
public class Cpu65C02AbsoluteModeTest extends TestCase {
|
||||
protected Cpu cpu;
|
||||
protected Bus bus;
|
||||
protected Memory mem;
|
||||
|
||||
private void makeCmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||
}
|
||||
|
||||
private void makeNmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||
}
|
||||
|
||||
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||
this.cpu = new Cpu(behavior);
|
||||
this.bus = new Bus(0x0000, 0xffff);
|
||||
this.mem = new Memory(0x0000, 0xffff);
|
||||
bus.addCpu(cpu);
|
||||
bus.addDevice(mem);
|
||||
|
||||
// Load the reset vector.
|
||||
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||
|
||||
cpu.reset();
|
||||
}
|
||||
|
||||
public void test_STZ() throws Exception {
|
||||
makeCmosCpu();
|
||||
bus.write(0x0010,0xff);
|
||||
|
||||
bus.loadProgram(0x9c, 0x10, 0x00); // STZ Absolute
|
||||
|
||||
// Test STZ Absolute ($0010)
|
||||
assertEquals(0xff, bus.read(0x0010, true));
|
||||
cpu.step();
|
||||
assertEquals(0x00, bus.read(0x0010, true));
|
||||
|
||||
}
|
||||
|
||||
public void test_STZRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
bus.write(0x0010,0xff);
|
||||
|
||||
bus.loadProgram(0x9c, 0x10, 0x00); // STZ Absolute
|
||||
|
||||
// Test STZ Absolute ($0010)
|
||||
assertEquals(0xff, bus.read(0x0010, true));
|
||||
cpu.step();
|
||||
assertEquals(0xff, bus.read(0x0010, true));
|
||||
|
||||
}
|
||||
|
||||
public void test_TSB() throws Exception {
|
||||
makeCmosCpu();
|
||||
bus.loadProgram(0x0c, 0x10, 0x00); // 65C02 TSB Absolute $0010
|
||||
|
||||
bus.write(0x10, 0x01);
|
||||
cpu.setAccumulator(0x01);
|
||||
cpu.step();
|
||||
assertEquals(0x01,bus.read(0x10,true)); // 0x01 & 0x01 = 0x01
|
||||
assertFalse(cpu.getZeroFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setAccumulator(0x02);
|
||||
cpu.step();
|
||||
assertEquals(0x03,bus.read(0x0010,true));
|
||||
assertTrue(cpu.getZeroFlag());
|
||||
|
||||
}
|
||||
|
||||
public void test_TSBRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
bus.loadProgram(0x0c, 0x10, 0x00); // 65C02 TSB Absolute $0010
|
||||
|
||||
bus.write(0x10, 0x00);
|
||||
cpu.setAccumulator(0x01);
|
||||
cpu.step();
|
||||
assertEquals(0x00,bus.read(0x0010,true));
|
||||
|
||||
}
|
||||
|
||||
public void test_TRB() throws Exception {
|
||||
makeCmosCpu();
|
||||
bus.loadProgram(0x1c, 0x00, 0x01); // 65C02 TRB Absolute $0010
|
||||
|
||||
bus.write(0x0100, 0x03);
|
||||
cpu.setAccumulator(0x01);
|
||||
cpu.step();
|
||||
assertEquals(0x02,bus.read(0x0100,true)); // $03 &= ~($01) = $02
|
||||
assertFalse(cpu.getZeroFlag()); // Z = !(A & M)
|
||||
|
||||
cpu.reset();
|
||||
cpu.setAccumulator(0x01);
|
||||
cpu.step();
|
||||
assertEquals(0x02,bus.read(0x0100,true)); // $02 &= ~($01) = $02
|
||||
assertTrue(cpu.getZeroFlag()); // Z = !(A & M)
|
||||
|
||||
}
|
||||
|
||||
public void test_TRBRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
bus.loadProgram(0x1c, 0x00, 0x01); // 65C02 TRB Absolute $0010
|
||||
|
||||
bus.write(0x0100, 0xff);
|
||||
cpu.setAccumulator(0x01);
|
||||
cpu.step();
|
||||
assertEquals(0xff,bus.read(0x0100,true));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.loomcom.symon;
|
||||
|
||||
import com.loomcom.symon.devices.Memory;
|
||||
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||
import junit.framework.*;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||
* in the 65C02 and 65816
|
||||
*/
|
||||
public class Cpu65C02AbsoluteXModeTest extends TestCase {
|
||||
protected Cpu cpu;
|
||||
protected Bus bus;
|
||||
protected Memory mem;
|
||||
|
||||
private void makeCmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||
}
|
||||
|
||||
private void makeNmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||
}
|
||||
|
||||
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||
this.cpu = new Cpu(behavior);
|
||||
this.bus = new Bus(0x0000, 0xffff);
|
||||
this.mem = new Memory(0x0000, 0xffff);
|
||||
bus.addCpu(cpu);
|
||||
bus.addDevice(mem);
|
||||
|
||||
// Load the reset vector.
|
||||
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||
|
||||
cpu.reset();
|
||||
}
|
||||
|
||||
public void test_STZ() throws Exception {
|
||||
makeCmosCpu();
|
||||
bus.write(0x0011,0xff);
|
||||
|
||||
bus.loadProgram(0x9e, 0x10, 0x00); // STZ Absolute,X
|
||||
|
||||
// Test STZ Absolute,X ($0011)
|
||||
cpu.setXRegister(0x01);
|
||||
assertEquals(0xff, bus.read(0x0011, true));
|
||||
cpu.step();
|
||||
assertEquals(0x00, bus.read(0x0011, true));
|
||||
}
|
||||
|
||||
public void test_STZRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
bus.write(0x0011,0xff);
|
||||
|
||||
bus.loadProgram(0x9e, 0x10, 0x00); // STZ Absolute,X
|
||||
|
||||
// Test STZ Absolute,X ($0011)
|
||||
cpu.setXRegister(0x01);
|
||||
assertEquals(0xff, bus.read(0x0011, true));
|
||||
cpu.step();
|
||||
assertEquals(0xff, bus.read(0x0011, true));
|
||||
}
|
||||
|
||||
public void test_JMP_Indirect_Absolute_X () throws Exception {
|
||||
makeCmosCpu();
|
||||
bus.write(0x304,00);
|
||||
bus.write(0x0305,04);
|
||||
bus.loadProgram(0x7c, 0x00, 0x03);
|
||||
cpu.setXRegister(0x04);
|
||||
cpu.step();
|
||||
assertEquals(0x0400,cpu.getProgramCounter());
|
||||
}
|
||||
|
||||
public void test_JMP_Indirect_Absolute_XRequiresCmosCpu () throws Exception {
|
||||
makeNmosCpu();
|
||||
bus.write(0x304,00);
|
||||
bus.write(0x0305,04);
|
||||
bus.loadProgram(0x7c, 0x00, 0x03);
|
||||
cpu.setXRegister(0x04);
|
||||
cpu.step();
|
||||
assertEquals(0x0203,cpu.getProgramCounter());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.loomcom.symon;
|
||||
|
||||
import com.loomcom.symon.devices.Memory;
|
||||
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||
import junit.framework.*;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||
* in the 65C02 and 65816
|
||||
*/
|
||||
public class Cpu65C02ImmediateModeTest extends TestCase {
|
||||
protected Cpu cpu;
|
||||
protected Bus bus;
|
||||
protected Memory mem;
|
||||
|
||||
private void makeCmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||
}
|
||||
|
||||
private void makeNmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||
}
|
||||
|
||||
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||
this.cpu = new Cpu(behavior);
|
||||
this.bus = new Bus(0x0000, 0xffff);
|
||||
this.mem = new Memory(0x0000, 0xffff);
|
||||
bus.addCpu(cpu);
|
||||
bus.addDevice(mem);
|
||||
|
||||
// Load the reset vector.
|
||||
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||
|
||||
cpu.reset();
|
||||
}
|
||||
|
||||
public void test_BIT_Immediate() throws Exception {
|
||||
makeCmosCpu();
|
||||
bus.loadProgram(0x89, 0xF1); // 65C02 BIT #$01
|
||||
cpu.setAccumulator(0x02);
|
||||
|
||||
cpu.step();
|
||||
assertTrue(cpu.getZeroFlag()); // #$02 & #$F1 = 0
|
||||
assertEquals(0x02,cpu.getAccumulator()); // Accumulator should not be modified
|
||||
assertFalse(cpu.getNegativeFlag()); // BIT #Immediate should not set N or V Flags
|
||||
assertFalse(cpu.getOverflowFlag());
|
||||
|
||||
cpu.reset();
|
||||
cpu.setAccumulator(0x01);
|
||||
cpu.step();
|
||||
assertFalse(cpu.getZeroFlag()); // #$F1 & #$01 = 1
|
||||
assertEquals(0x01,cpu.getAccumulator());
|
||||
|
||||
}
|
||||
|
||||
public void test_BIT_ImmediateRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
bus.loadProgram(0x89, 0xF1); // 65C02 BIT #$01
|
||||
|
||||
cpu.step();
|
||||
cpu.setAccumulator(0x01);
|
||||
assertTrue(cpu.getZeroFlag());
|
||||
assertEquals(0x01,cpu.getAccumulator());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
package com.loomcom.symon;
|
||||
|
||||
import com.loomcom.symon.devices.Memory;
|
||||
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||
import junit.framework.*;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||
* in the 65C02 and 65816
|
||||
*/
|
||||
public class Cpu65C02ImpliedModeTest extends TestCase {
|
||||
protected Cpu cpu;
|
||||
protected Bus bus;
|
||||
protected Memory mem;
|
||||
|
||||
private void makeCmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||
}
|
||||
|
||||
private void makeNmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||
}
|
||||
|
||||
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||
this.cpu = new Cpu(behavior);
|
||||
this.bus = new Bus(0x0000, 0xffff);
|
||||
this.mem = new Memory(0x0000, 0xffff);
|
||||
bus.addCpu(cpu);
|
||||
bus.addDevice(mem);
|
||||
|
||||
// Load the reset vector.
|
||||
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||
|
||||
cpu.reset();
|
||||
}
|
||||
|
||||
public void test_PHX() throws Exception {
|
||||
makeCmosCpu();
|
||||
cpu.stackPush(0x00);
|
||||
cpu.setXRegister(0xff);
|
||||
bus.loadProgram(0xda);
|
||||
|
||||
assertEquals(cpu.stackPeek(), 0x00);
|
||||
cpu.step();
|
||||
assertEquals(cpu.stackPeek(), 0xff);
|
||||
|
||||
}
|
||||
|
||||
public void test_PHXRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
cpu.stackPush(0x00);
|
||||
cpu.setXRegister(0xff);
|
||||
bus.loadProgram(0xda);
|
||||
|
||||
assertEquals(cpu.stackPeek(), 0x00);
|
||||
cpu.step();
|
||||
assertEquals(cpu.stackPeek(), 0x00);
|
||||
|
||||
}
|
||||
|
||||
public void test_PLX() throws Exception {
|
||||
makeCmosCpu();
|
||||
cpu.stackPush(0xff);
|
||||
cpu.setXRegister(0x00);
|
||||
bus.loadProgram(0xfa);
|
||||
|
||||
assertEquals(0x00, cpu.getXRegister());
|
||||
cpu.step();
|
||||
assertEquals(0xff, cpu.getXRegister());
|
||||
|
||||
}
|
||||
|
||||
public void test_PLXRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
cpu.stackPush(0xff);
|
||||
cpu.setXRegister(0x00);
|
||||
bus.loadProgram(0xfa);
|
||||
|
||||
assertEquals(0x00, cpu.getXRegister());
|
||||
cpu.step();
|
||||
assertEquals(0x00, cpu.getXRegister());
|
||||
|
||||
}
|
||||
|
||||
public void test_PHY() throws Exception {
|
||||
makeCmosCpu();
|
||||
cpu.stackPush(0x00);
|
||||
cpu.setYRegister(0xff);
|
||||
bus.loadProgram(0x5a);
|
||||
|
||||
assertEquals(0x00, cpu.stackPeek());
|
||||
cpu.step();
|
||||
assertEquals(0xff, cpu.stackPeek());
|
||||
|
||||
}
|
||||
|
||||
public void test_PHYRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
cpu.stackPush(0x00);
|
||||
cpu.setYRegister(0xff);
|
||||
bus.loadProgram(0x5a);
|
||||
|
||||
assertEquals(0x00, cpu.stackPeek());
|
||||
cpu.step();
|
||||
assertEquals(0x00, cpu.stackPeek());
|
||||
|
||||
}
|
||||
|
||||
public void test_PLY() throws Exception {
|
||||
makeCmosCpu();
|
||||
cpu.stackPush(0xff);
|
||||
cpu.setYRegister(0x00);
|
||||
bus.loadProgram(0x7a);
|
||||
|
||||
assertEquals(0x00, cpu.getYRegister());
|
||||
cpu.step();
|
||||
assertEquals(0xff, cpu.getYRegister());
|
||||
|
||||
}
|
||||
|
||||
public void test_PLYRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
cpu.stackPush(0xff);
|
||||
cpu.setYRegister(0x00);
|
||||
bus.loadProgram(0x7a);
|
||||
|
||||
assertEquals(0x00, cpu.getYRegister());
|
||||
cpu.step();
|
||||
assertEquals(0x00, cpu.getYRegister());
|
||||
|
||||
}
|
||||
|
||||
public void test_INC_A() throws Exception {
|
||||
makeCmosCpu();
|
||||
cpu.setAccumulator(0x10);
|
||||
bus.loadProgram(0x1a);
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x11, cpu.getAccumulator());
|
||||
assertFalse(cpu.getZeroFlag());
|
||||
assertFalse(cpu.getNegativeFlag());
|
||||
|
||||
// Incrementing to 0 should set Zero Flag
|
||||
cpu.reset();
|
||||
cpu.setAccumulator(0xff);
|
||||
cpu.step();
|
||||
assertTrue(cpu.getZeroFlag());
|
||||
assertFalse(cpu.getNegativeFlag());
|
||||
|
||||
// Should set Negative Flag
|
||||
cpu.reset();
|
||||
cpu.setAccumulator(0x7F);
|
||||
cpu.step();
|
||||
assertTrue(cpu.getNegativeFlag());
|
||||
assertFalse(cpu.getZeroFlag());
|
||||
|
||||
}
|
||||
|
||||
public void test_INC_ARequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
cpu.setAccumulator(0x10);
|
||||
bus.loadProgram(0x1a);
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x10, cpu.getAccumulator());
|
||||
|
||||
}
|
||||
|
||||
public void test_DEC_A() throws Exception {
|
||||
makeCmosCpu();
|
||||
cpu.setAccumulator(0x10);
|
||||
bus.loadProgram(0x3a);
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x0F, cpu.getAccumulator());
|
||||
assertFalse(cpu.getZeroFlag());
|
||||
assertFalse(cpu.getNegativeFlag());
|
||||
|
||||
// Decrementing to 0 should set Zero Flag
|
||||
cpu.reset();
|
||||
cpu.setAccumulator(0x01);
|
||||
cpu.step();
|
||||
assertTrue(cpu.getZeroFlag());
|
||||
assertFalse(cpu.getNegativeFlag());
|
||||
|
||||
// Should set Negative Flag
|
||||
cpu.reset();
|
||||
cpu.setAccumulator(0x00);
|
||||
cpu.step();
|
||||
assertTrue(cpu.getNegativeFlag());
|
||||
assertFalse(cpu.getZeroFlag());
|
||||
|
||||
}
|
||||
|
||||
public void test_DEC_ARequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
cpu.setAccumulator(0x10);
|
||||
bus.loadProgram(0x3a);
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x10, cpu.getAccumulator());
|
||||
assertFalse(cpu.getZeroFlag());
|
||||
assertFalse(cpu.getNegativeFlag());
|
||||
|
||||
}
|
||||
|
||||
public void test_BRK_clearsDecimalModeFlag() throws Exception {
|
||||
makeCmosCpu();
|
||||
cpu.setDecimalModeFlag();
|
||||
assertEquals(0x00, cpu.stackPeek());
|
||||
assertFalse(cpu.getBreakFlag());
|
||||
assertTrue(cpu.getDecimalModeFlag());
|
||||
assertEquals(0x0200, cpu.getProgramCounter());
|
||||
assertEquals(0xff, cpu.getStackPointer());
|
||||
|
||||
// Set the IRQ vector
|
||||
bus.write(0xffff, 0x12);
|
||||
bus.write(0xfffe, 0x34);
|
||||
|
||||
bus.loadProgram(0xea, // NOP
|
||||
0xea, // NOP
|
||||
0xea, // NOP
|
||||
0x00, // BRK
|
||||
0xea, // NOP
|
||||
0xea); // NOP
|
||||
|
||||
cpu.step(3); // Three NOP instructions
|
||||
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
assertTrue(cpu.getDecimalModeFlag());
|
||||
cpu.step(); // Triggers the BRK
|
||||
|
||||
// Was at PC = 0x204. PC+1 should now be on the stack
|
||||
assertEquals(0x02, bus.read(0x1ff, true)); // PC high byte
|
||||
assertEquals(0x05, bus.read(0x1fe, true)); // PC low byte
|
||||
|
||||
|
||||
// Interrupt vector held 0x1234, so we should be there.
|
||||
assertEquals(0x1234, cpu.getProgramCounter());
|
||||
assertEquals(0xfc, cpu.getStackPointer());
|
||||
|
||||
// B and I flags should have been set on P
|
||||
assertTrue(cpu.getBreakFlag());
|
||||
assertFalse(cpu.getDecimalModeFlag());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
package com.loomcom.symon;
|
||||
|
||||
import com.loomcom.symon.devices.Memory;
|
||||
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||
import junit.framework.*;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||
* in the 65C02 and 65816
|
||||
*/
|
||||
public class Cpu65C02ZeroPageModeTest extends TestCase {
|
||||
protected Cpu cpu;
|
||||
protected Bus bus;
|
||||
protected Memory mem;
|
||||
|
||||
private void makeCmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||
}
|
||||
|
||||
private void makeNmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||
}
|
||||
|
||||
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||
this.cpu = new Cpu(behavior);
|
||||
this.bus = new Bus(0x0000, 0xffff);
|
||||
this.mem = new Memory(0x0000, 0xffff);
|
||||
bus.addCpu(cpu);
|
||||
bus.addDevice(mem);
|
||||
|
||||
// Load the reset vector.
|
||||
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||
|
||||
cpu.reset();
|
||||
}
|
||||
|
||||
public void test_STZ() throws Exception {
|
||||
makeCmosCpu();
|
||||
bus.write(0x0000,0xff);
|
||||
|
||||
bus.loadProgram(0x64,0x00); // STZ Zero Page $00
|
||||
|
||||
// Test STZ Zero Page
|
||||
assertEquals(0xff,bus.read(0x00, true));
|
||||
cpu.step();
|
||||
assertEquals(0x00,bus.read(0x00, true));
|
||||
}
|
||||
|
||||
public void test_STZRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
bus.write(0x0000,0xff);
|
||||
|
||||
bus.loadProgram(0x64,0x00); // STZ Zero Page $00
|
||||
|
||||
// Test STZ Zero Page
|
||||
assertEquals(0xff,bus.read(0x00, true));
|
||||
cpu.step();
|
||||
assertEquals(0xff,bus.read(0x00, true));
|
||||
|
||||
}
|
||||
|
||||
public void test_SMB() throws Exception {
|
||||
makeCmosCpu();
|
||||
bus.loadProgram(0x87,0x01, // SMB0 $01
|
||||
0x97,0x01, // SMB1 $01
|
||||
0xa7,0x01, // SMB2 $01
|
||||
0xb7,0x01, // SMB3 $01
|
||||
0xc7,0x01, // SMB4 $01
|
||||
0xd7,0x01, // SMB5 $01
|
||||
0xe7,0x01, // SMB6 $01
|
||||
0xf7,0x01); // SMB7 $01
|
||||
|
||||
// SMB0
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(1 << 0,bus.read(0x0001, true));
|
||||
|
||||
// SMB1
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(1 << 1,bus.read(0x0001, true));
|
||||
|
||||
// SMB2
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(1 << 2,bus.read(0x0001, true));
|
||||
|
||||
// SMB3
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(1 << 3,bus.read(0x0001, true));
|
||||
|
||||
// SMB4
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(1 << 4,bus.read(0x0001, true));
|
||||
|
||||
// SMB5
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(1 << 5,bus.read(0x0001, true));
|
||||
|
||||
// SMB6
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(1 << 6,bus.read(0x0001, true));
|
||||
|
||||
// SMB7
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(1 << 7,bus.read(0x0001, true));
|
||||
|
||||
}
|
||||
|
||||
public void test_SMBRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
bus.loadProgram(0x87,0x01, // SMB0 $01
|
||||
0x97,0x01, // SMB1 $01
|
||||
0xa7,0x01, // SMB2 $01
|
||||
0xb7,0x01, // SMB3 $01
|
||||
0xc7,0x01, // SMB4 $01
|
||||
0xd7,0x01, // SMB5 $01
|
||||
0xe7,0x01, // SMB6 $01
|
||||
0xf7,0x01); // SMB7 $01
|
||||
|
||||
// SMB0
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
|
||||
// SMB1
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
|
||||
// SMB2
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
|
||||
// SMB3
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
|
||||
// SMB4
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
|
||||
// SMB5
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
|
||||
// SMB6
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
|
||||
// SMB7
|
||||
bus.write(0x01,0x00);
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0x00,bus.read(0x0001, true));
|
||||
|
||||
}
|
||||
|
||||
public void test_RMB() throws Exception {
|
||||
makeCmosCpu();
|
||||
bus.loadProgram(0x07,0x01, // SMB0 $01
|
||||
0x17,0x01, // SMB1 $01
|
||||
0x27,0x01, // SMB2 $01
|
||||
0x37,0x01, // SMB3 $01
|
||||
0x47,0x01, // SMB4 $01
|
||||
0x57,0x01, // SMB5 $01
|
||||
0x67,0x01, // SMB6 $01
|
||||
0x77,0x01); // SMB7 $01
|
||||
|
||||
// RMB0
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xfe,bus.read(0x0001, true));
|
||||
|
||||
// RMB1
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xfd,bus.read(0x0001, true));
|
||||
|
||||
// RMB2
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xfb,bus.read(0x0001, true));
|
||||
|
||||
// RMB3
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xf7,bus.read(0x0001, true));
|
||||
|
||||
// RMB4
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xef,bus.read(0x0001, true));
|
||||
|
||||
// RMB5
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xdf,bus.read(0x0001, true));
|
||||
|
||||
// RMB6
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xbf,bus.read(0x0001, true));
|
||||
|
||||
// RMB7
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0x7f,bus.read(0x0001, true));
|
||||
|
||||
}
|
||||
|
||||
public void test_RMBRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
bus.loadProgram(0x07,0x01, // SMB0 $01
|
||||
0x17,0x01, // SMB1 $01
|
||||
0x27,0x01, // SMB2 $01
|
||||
0x37,0x01, // SMB3 $01
|
||||
0x47,0x01, // SMB4 $01
|
||||
0x57,0x01, // SMB5 $01
|
||||
0x67,0x01, // SMB6 $01
|
||||
0x77,0x01); // SMB7 $01
|
||||
|
||||
// RMB0
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
|
||||
// RMB1
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
|
||||
// RMB2
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
|
||||
// RMB3
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
|
||||
// RMB4
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
|
||||
// RMB5
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
|
||||
// RMB6
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
|
||||
// RMB7
|
||||
bus.write(0x01,0xff);
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
cpu.step();
|
||||
assertEquals(0xff,bus.read(0x0001, true));
|
||||
|
||||
}
|
||||
|
||||
public void test_TSB() throws Exception {
|
||||
makeCmosCpu();
|
||||
bus.loadProgram(0x04, 0x10); // 65C02 TSB Zero Page $10
|
||||
|
||||
bus.write(0x10, 0x01);
|
||||
cpu.setAccumulator(0x03);
|
||||
cpu.step();
|
||||
assertEquals(0x03,bus.read(0x10,true));
|
||||
assertFalse(cpu.getZeroFlag());
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x10, 0x01);
|
||||
cpu.setAccumulator(0x02);
|
||||
cpu.step();
|
||||
assertEquals(0x03,bus.read(0x10,true));
|
||||
assertTrue(cpu.getZeroFlag());
|
||||
|
||||
}
|
||||
|
||||
public void test_TSBRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
bus.loadProgram(0x04, 0x10); // 65C02 TSB Zero Page $10
|
||||
|
||||
bus.write(0x10, 0x01);
|
||||
cpu.setAccumulator(0x03);
|
||||
cpu.step();
|
||||
assertEquals(0x01,bus.read(0x10,true));
|
||||
|
||||
}
|
||||
|
||||
public void test_TRB() throws Exception {
|
||||
makeCmosCpu();
|
||||
cpu.reset();
|
||||
bus.loadProgram(0x14, 0x40); // 65C02 TRB Zero Page $40
|
||||
|
||||
bus.write(0x0040, 0xff);
|
||||
cpu.setAccumulator(0x01);
|
||||
cpu.step();
|
||||
assertEquals(0xfe,bus.read(0x0040,true)); // $03 &= ~($01) = $02
|
||||
assertFalse(cpu.getZeroFlag()); // Z = !(A & M)
|
||||
|
||||
cpu.reset();
|
||||
cpu.setAccumulator(0x01);
|
||||
cpu.step();
|
||||
assertEquals(0xfe,bus.read(0x0040,true)); // $02 &= ~($01) = $02
|
||||
assertTrue(cpu.getZeroFlag()); // Z = !(A & M)
|
||||
|
||||
}
|
||||
|
||||
public void test_TRBRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
cpu.reset();
|
||||
bus.loadProgram(0x14, 0x40); // 65C02 TRB Zero Page $40
|
||||
|
||||
bus.write(0x0040, 0xff);
|
||||
cpu.setAccumulator(0x01);
|
||||
cpu.step();
|
||||
assertEquals(0xff,bus.read(0x0040,true)); // $03 &= ~($01) = $02
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,585 @@
|
||||
package com.loomcom.symon;
|
||||
|
||||
import com.loomcom.symon.devices.Memory;
|
||||
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||
import junit.framework.*;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||
* in the 65C02 and 65816
|
||||
*/
|
||||
public class Cpu65C02ZeroPageRelativeTest extends TestCase {
|
||||
protected Cpu cpu;
|
||||
protected Bus bus;
|
||||
protected Memory mem;
|
||||
|
||||
private void makeCmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||
}
|
||||
|
||||
private void makeNmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||
}
|
||||
|
||||
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||
this.cpu = new Cpu(behavior);
|
||||
this.bus = new Bus(0x0000, 0xffff);
|
||||
this.mem = new Memory(0x0000, 0xffff);
|
||||
bus.addCpu(cpu);
|
||||
bus.addDevice(mem);
|
||||
|
||||
// Load the reset vector.
|
||||
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||
|
||||
cpu.reset();
|
||||
}
|
||||
public void test_BRA() throws Exception {
|
||||
makeCmosCpu();
|
||||
// Positive Offset
|
||||
bus.loadProgram(0x80, 0x05); // 65C02 BRA $05 ; *=$0202+$05 ($0207)
|
||||
cpu.step();
|
||||
assertEquals(0x207, cpu.getProgramCounter());
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.loadProgram(0x80, 0xfb); // 65C02 BRA $fb ; *=$0202-$05 ($01fd)
|
||||
cpu.step();
|
||||
assertEquals(0x1fd, cpu.getProgramCounter());
|
||||
}
|
||||
|
||||
public void test_BRArequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
// Should be a NOOP on NMOS and end up at $0202
|
||||
// Positive Offset
|
||||
bus.loadProgram(0x80, 0x05); // BRA $05 ; *=$0202+$05 ($0207)
|
||||
cpu.step();
|
||||
assertEquals(0x202, cpu.getProgramCounter());
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.loadProgram(0x80, 0xfb); // BRA $fb ; *=$0202-$05 ($01fd)
|
||||
cpu.step();
|
||||
assertEquals(0x202, cpu.getProgramCounter());
|
||||
}
|
||||
|
||||
public void test_BBR() throws Exception {
|
||||
makeCmosCpu();
|
||||
|
||||
/* BBR0 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xff);
|
||||
bus.loadProgram(0x0f, 0x0a, 0x05); // 65C02 BBR0 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xfe);
|
||||
bus.loadProgram(0x0f, 0x0a, 0x05); // 65C02 BBR0 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xfe);
|
||||
bus.loadProgram(0x0f, 0x0a, 0xfb); // 65C02 BBR0 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
/* BBR1 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xff);
|
||||
bus.loadProgram(0x1f, 0x0a, 0x05); // 65C02 BBR1 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xfd);
|
||||
bus.loadProgram(0x1f, 0x0a, 0x05); // 65C02 BBR1 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xfd);
|
||||
bus.loadProgram(0x1f, 0x0a, 0xfb); // 65C02 BBR1 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
/* BBR2 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xff);
|
||||
bus.loadProgram(0x2f, 0x0a, 0x05); // 65C02 BBR2 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xfb);
|
||||
bus.loadProgram(0x2f, 0x0a, 0x05); // 65C02 BBR2 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xfb);
|
||||
bus.loadProgram(0x2f, 0x0a, 0xfb); // 65C02 BBR2 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
/* BBR3 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xff);
|
||||
bus.loadProgram(0x3f, 0x0a, 0x05); // 65C02 BBR3 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xf7);
|
||||
bus.loadProgram(0x3f, 0x0a, 0x05); // 65C02 BBR3 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xf7);
|
||||
bus.loadProgram(0x3f, 0x0a, 0xfb); // 65C02 BBR3 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
/* BBR4 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xff);
|
||||
bus.loadProgram(0x4f, 0x0a, 0x05); // 65C02 BBR4 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xef);
|
||||
bus.loadProgram(0x4f, 0x0a, 0x05); // 65C02 BBR4 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xef);
|
||||
bus.loadProgram(0x4f, 0x0a, 0xfb); // 65C02 BBR4 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
/* BBR5 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xff);
|
||||
bus.loadProgram(0x5f, 0x0a, 0x05); // 65C02 BBR5 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xdf);
|
||||
bus.loadProgram(0x5f, 0x0a, 0x05); // 65C02 BBR5 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xdf);
|
||||
bus.loadProgram(0x5f, 0x0a, 0xfb); // 65C02 BBR5 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
/* BBR6 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xff);
|
||||
bus.loadProgram(0x6f, 0x0a, 0x05); // 65C02 BBR6 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xbf);
|
||||
bus.loadProgram(0x6f, 0x0a, 0x05); // 65C02 BBR6 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xbf);
|
||||
bus.loadProgram(0x6f, 0x0a, 0xfb); // 65C02 BBR6 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
/* BBR7 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xff);
|
||||
bus.loadProgram(0x7f, 0x0a, 0x05); // 65C02 BBR7 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x7f);
|
||||
bus.loadProgram(0x7f, 0x0a, 0x05); // 65C02 BBR7 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x7f);
|
||||
bus.loadProgram(0x7f, 0x0a, 0xfb); // 65C02 BBR7 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
}
|
||||
|
||||
public void test_BBRNeedsCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
|
||||
/* BBR0 */
|
||||
bus.write(0x0a,0xfe);
|
||||
bus.loadProgram(0x0f, 0x0a, 0x05); // 65C02 BBR0 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
/* BBR1 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xfd);
|
||||
bus.loadProgram(0x1f, 0x0a, 0x05); // 65C02 BBR1 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
/* BBR2 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xfb);
|
||||
bus.loadProgram(0x2f, 0x0a, 0x05); // 65C02 BBR2 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
/* BBR3 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xf7);
|
||||
bus.loadProgram(0x3f, 0x0a, 0x05); // 65C02 BBR3 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
/* BBR4 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xef);
|
||||
bus.loadProgram(0x4f, 0x0a, 0x05); // 65C02 BBR4 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
/* BBR5 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xdf);
|
||||
bus.loadProgram(0x5f, 0x0a, 0x05); // 65C02 BBR5 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
/* BBR6 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0xbf);
|
||||
bus.loadProgram(0x6f, 0x0a, 0x05); // 65C02 BBR6 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
/* BBR7 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x7f);
|
||||
bus.loadProgram(0x7f, 0x0a, 0x05); // 65C02 BBR7 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
}
|
||||
|
||||
public void test_BBS() throws Exception {
|
||||
makeCmosCpu();
|
||||
|
||||
/* BBS0 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x00);
|
||||
bus.loadProgram(0x8f, 0x0a, 0x05); // 65C02 BBS0 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x01);
|
||||
bus.loadProgram(0x8f, 0x0a, 0x05); // 65C02 BBS0 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x01);
|
||||
bus.loadProgram(0x8f, 0x0a, 0xfb); // 65C02 BBS0 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
/* BBS1 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x00);
|
||||
bus.loadProgram(0x9f, 0x00, 0x05); // 65C02 BBS1 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x02);
|
||||
bus.loadProgram(0x9f, 0x0a, 0x05); // 65C02 BBS1 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x02);
|
||||
bus.loadProgram(0x9f, 0x0a, 0xfb); // 65C02 BBS1 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
/* BBS2 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x00);
|
||||
bus.loadProgram(0xaf, 0x0a, 0x05); // 65C02 BBS2 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x04);
|
||||
bus.loadProgram(0xaf, 0x0a, 0x05); // 65C02 BBS2 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x04);
|
||||
bus.loadProgram(0xaf, 0x0a, 0xfb); // 65C02 BBS2 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
/* BBS3 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x00);
|
||||
bus.loadProgram(0xbf, 0x0a, 0x05); // 65C02 BBS3 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x08);
|
||||
bus.loadProgram(0xbf, 0x0a, 0x05); // 65C02 BBS3 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x08);
|
||||
bus.loadProgram(0xbf, 0x0a, 0xfb); // 65C02 BBS3 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
/* BBS4 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x00);
|
||||
bus.loadProgram(0xcf, 0x0a, 0x05); // 65C02 BBS4 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x10);
|
||||
bus.loadProgram(0xcf, 0x0a, 0x05); // 65C02 BBS4 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x10);
|
||||
bus.loadProgram(0xcf, 0x0a, 0xfb); // 65C02 BBS4 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
/* BBS5 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x00);
|
||||
bus.loadProgram(0xdf, 0x0a, 0x05); // 65C02 BBS5 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x20);
|
||||
bus.loadProgram(0xdf, 0x0a, 0x05); // 65C02 BBS5 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x20);
|
||||
bus.loadProgram(0xdf, 0x0a, 0xfb); // 65C02 BBS5 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
/* BBS6 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x00);
|
||||
bus.loadProgram(0xef, 0x0a, 0x05); // 65C02 BBS6 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x40);
|
||||
bus.loadProgram(0xef, 0x0a, 0x05); // 65C02 BBS6 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x40);
|
||||
bus.loadProgram(0xef, 0x0a, 0xfb); // 65C02 BBS6 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
/* BBS7 */
|
||||
// Positive Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x00);
|
||||
bus.loadProgram(0xff, 0x0a, 0x05); // 65C02 BBS7 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter()); // Shouldn't have branched
|
||||
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x80);
|
||||
bus.loadProgram(0xff, 0x0a, 0x05); // 65C02 BBS7 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x208, cpu.getProgramCounter()); // Should have branched
|
||||
|
||||
// Negative Offset
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x80);
|
||||
bus.loadProgram(0xff, 0x0a, 0xfb); // 65C02 BBS7 $00 $fb ; *=$0203-$05 ($01fe)
|
||||
cpu.step();
|
||||
assertEquals(0x1fe, cpu.getProgramCounter());
|
||||
|
||||
}
|
||||
|
||||
public void test_BBSNeedsCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
|
||||
/* BBS0 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x01);
|
||||
bus.loadProgram(0x8f, 0x0a, 0x05); // 65C02 BBS0 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
/* BBS1 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x02);
|
||||
bus.loadProgram(0x9f, 0x0a, 0x05); // 65C02 BBS1 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
/* BBS2 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x04);
|
||||
bus.loadProgram(0xaf, 0x0a, 0x05); // 65C02 BBS2 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
/* BBS3 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x08);
|
||||
bus.loadProgram(0xbf, 0x0a, 0x05); // 65C02 BBS3 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
/* BBS4 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x10);
|
||||
bus.loadProgram(0xcf, 0x0a, 0x05); // 65C02 BBS4 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
/* BBS5 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x20);
|
||||
bus.loadProgram(0xdf, 0x0a, 0x05); // 65C02 BBS5 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
/* BBS6 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x40);
|
||||
bus.loadProgram(0xef, 0x0a, 0x05); // 65C02 BBS6 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
/* BBS7 */
|
||||
cpu.reset();
|
||||
bus.write(0x0a,0x80);
|
||||
bus.loadProgram(0xff, 0x0a, 0x05); // 65C02 BBS7 $00 $05 ; *=$0202+$05 ($0208)
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x203, cpu.getProgramCounter());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.loomcom.symon;
|
||||
|
||||
import com.loomcom.symon.devices.Memory;
|
||||
import com.loomcom.symon.exceptions.MemoryAccessException;
|
||||
import junit.framework.*;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||
* in the 65C02 and 65816
|
||||
*/
|
||||
public class Cpu65C02ZeroPageXModeTest extends TestCase {
|
||||
protected Cpu cpu;
|
||||
protected Bus bus;
|
||||
protected Memory mem;
|
||||
|
||||
private void makeCmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||
}
|
||||
|
||||
private void makeNmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||
}
|
||||
|
||||
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||
this.cpu = new Cpu(behavior);
|
||||
this.bus = new Bus(0x0000, 0xffff);
|
||||
this.mem = new Memory(0x0000, 0xffff);
|
||||
bus.addCpu(cpu);
|
||||
bus.addDevice(mem);
|
||||
|
||||
// Load the reset vector.
|
||||
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||
|
||||
cpu.reset();
|
||||
}
|
||||
|
||||
public void test_STZ() throws Exception {
|
||||
makeCmosCpu();
|
||||
bus.write(0x0002,0xff);
|
||||
|
||||
bus.loadProgram(0x74,0x01); // STZ Zero Page,X $01
|
||||
|
||||
// Test STZ Zero Page,X ($01+1)
|
||||
assertEquals(0xff,bus.read(0x02, true));
|
||||
cpu.setXRegister(0x01);
|
||||
cpu.step();
|
||||
assertEquals(0x00,bus.read(0x02, true));
|
||||
}
|
||||
|
||||
public void test_STZRequiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
bus.write(0x0002,0xff);
|
||||
|
||||
bus.loadProgram(0x74,0x01); // STZ Zero Page,X $01
|
||||
|
||||
// Test STZ Zero Page,X ($01+1)
|
||||
assertEquals(0xff,bus.read(0x02, true));
|
||||
cpu.setXRegister(0x01);
|
||||
cpu.step();
|
||||
assertEquals(0xff,bus.read(0x02, true));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class CpuIndirectModeTest extends TestCase {
|
||||
}
|
||||
|
||||
public void test_JMP_withIndirectBug() throws MemoryAccessException {
|
||||
cpu.setBehavior(Cpu.CpuBehavior.NMOS_WITH_INDIRECT_JMP_BUG);
|
||||
cpu.setBehavior(Cpu.CpuBehavior.NMOS_6502);
|
||||
bus.write(0x3400, 0x22);
|
||||
bus.write(0x34ff, 0x00);
|
||||
bus.write(0x3500, 0x54);
|
||||
@@ -76,7 +76,7 @@ public class CpuIndirectModeTest extends TestCase {
|
||||
}
|
||||
|
||||
public void test_JMP_withOutIndirectBug() throws MemoryAccessException {
|
||||
cpu.setBehavior(Cpu.CpuBehavior.NMOS_WITHOUT_INDIRECT_JMP_BUG);
|
||||
cpu.setBehavior(Cpu.CpuBehavior.CMOS_6502);
|
||||
bus.write(0x3400, 0x22);
|
||||
bus.write(0x34ff, 0x00);
|
||||
bus.write(0x3500, 0x54);
|
||||
@@ -88,7 +88,7 @@ public class CpuIndirectModeTest extends TestCase {
|
||||
}
|
||||
|
||||
public void test_JMP_cmos() throws MemoryAccessException {
|
||||
cpu.setBehavior(Cpu.CpuBehavior.CMOS);
|
||||
cpu.setBehavior(Cpu.CpuBehavior.CMOS_6502);
|
||||
bus.write(0x3400, 0x22);
|
||||
bus.write(0x34ff, 0x00);
|
||||
bus.write(0x3500, 0x54);
|
||||
|
||||
@@ -162,7 +162,7 @@ public class CpuIndirectXModeTest extends TestCase {
|
||||
|
||||
cpu.setXRegister(0x30);
|
||||
|
||||
bus.loadProgram(0xa9, 0x88, // LDA #$88
|
||||
bus.loadProgram(0xa9, 0x88, // LDA #$88
|
||||
0x5d, 0x10, 0xab, // EOR $ab10,X
|
||||
0x5d, 0x11, 0xab, // EOR $ab11,X
|
||||
0x5d, 0x12, 0xab, // EOR $ab12,X
|
||||
|
||||
@@ -0,0 +1,329 @@
|
||||
package com.loomcom.symon;
|
||||
|
||||
import com.loomcom.symon.devices.Memory;
|
||||
import org.junit.Test;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Test for Zero Page Indirect addressing mode, found on some instructions
|
||||
* in the 65C02 and 65816
|
||||
*/
|
||||
public class CpuZeroPageIndirectTest {
|
||||
protected Cpu cpu;
|
||||
protected Bus bus;
|
||||
protected Memory mem;
|
||||
|
||||
private void makeCmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.CMOS_6502);
|
||||
}
|
||||
|
||||
private void makeNmosCpu() throws Exception {
|
||||
makeCpu(InstructionTable.CpuBehavior.NMOS_6502);
|
||||
}
|
||||
|
||||
private void makeCpu(InstructionTable.CpuBehavior behavior) throws Exception {
|
||||
this.cpu = new Cpu(behavior);
|
||||
this.bus = new Bus(0x0000, 0xffff);
|
||||
this.mem = new Memory(0x0000, 0xffff);
|
||||
bus.addCpu(cpu);
|
||||
bus.addDevice(mem);
|
||||
|
||||
// Load the reset vector.
|
||||
bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff);
|
||||
bus.write(0xfffd, (Bus.DEFAULT_LOAD_ADDRESS & 0xff00) >>> 8);
|
||||
|
||||
cpu.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_ora() throws Exception {
|
||||
makeCmosCpu();
|
||||
|
||||
// Set some initial values in zero page.
|
||||
bus.write(0x30, 0x00);
|
||||
bus.write(0x31, 0x10);
|
||||
|
||||
bus.write(0x40, 0x01);
|
||||
bus.write(0x41, 0x10);
|
||||
|
||||
bus.write(0x50, 0x02);
|
||||
bus.write(0x51, 0x10);
|
||||
|
||||
bus.write(0x60, 0x03);
|
||||
bus.write(0x61, 0x10);
|
||||
|
||||
bus.write(0x1000, 0x11);
|
||||
bus.write(0x1001, 0x22);
|
||||
bus.write(0x1002, 0x44);
|
||||
bus.write(0x1003, 0x88);
|
||||
|
||||
bus.loadProgram(0x12, 0x30, // ORA ($30)
|
||||
0x12, 0x40, // ORA ($40)
|
||||
0x12, 0x50, // ORA ($50)
|
||||
0x12, 0x60); // ORA ($60)
|
||||
|
||||
|
||||
assertEquals(0x00, cpu.getAccumulator());
|
||||
|
||||
// 0x00 | 0x11 = 0x11
|
||||
cpu.step();
|
||||
assertEquals(0x11, cpu.getAccumulator());
|
||||
assertFalse(cpu.getZeroFlag());
|
||||
assertFalse(cpu.getNegativeFlag());
|
||||
|
||||
// 0x11 | 0x22 = 0x33
|
||||
cpu.step();
|
||||
assertEquals(0x33, cpu.getAccumulator());
|
||||
assertFalse(cpu.getZeroFlag());
|
||||
assertFalse(cpu.getNegativeFlag());
|
||||
|
||||
// 0x33 | 0x44 = 0x77
|
||||
cpu.step();
|
||||
assertEquals(0x77, cpu.getAccumulator());
|
||||
assertFalse(cpu.getZeroFlag());
|
||||
assertFalse(cpu.getNegativeFlag());
|
||||
|
||||
// 0x77 | 0x88 = 0xff
|
||||
cpu.step();
|
||||
assertEquals(0xff, cpu.getAccumulator());
|
||||
assertFalse(cpu.getZeroFlag());
|
||||
assertTrue(cpu.getNegativeFlag());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_ora_requiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
|
||||
// Set some initial values in zero page.
|
||||
bus.write(0x30, 0x00);
|
||||
bus.write(0x31, 0x10);
|
||||
|
||||
bus.write(0x40, 0x01);
|
||||
bus.write(0x41, 0x10);
|
||||
|
||||
bus.write(0x50, 0x02);
|
||||
bus.write(0x51, 0x10);
|
||||
|
||||
bus.write(0x60, 0x03);
|
||||
bus.write(0x61, 0x10);
|
||||
|
||||
bus.write(0x1000, 0x11);
|
||||
bus.write(0x1001, 0x22);
|
||||
bus.write(0x1002, 0x44);
|
||||
bus.write(0x1003, 0x88);
|
||||
|
||||
bus.loadProgram(0x12, 0x30, // ORA ($30)
|
||||
0x12, 0x40, // ORA ($40)
|
||||
0x12, 0x50, // ORA ($50)
|
||||
0x12, 0x60); // ORA ($60)
|
||||
|
||||
|
||||
assertEquals(0x00, cpu.getAccumulator());
|
||||
|
||||
boolean zState = cpu.getZeroFlag();
|
||||
boolean nState = cpu.getNegativeFlag();
|
||||
|
||||
// 0x00 | 0x11 = 0x11, but not implemented in NMOS cpu
|
||||
cpu.step();
|
||||
assertEquals(0x00, cpu.getAccumulator());
|
||||
assertEquals(zState, cpu.getZeroFlag()); // unchanged
|
||||
assertEquals(nState, cpu.getNegativeFlag()); // unchanged
|
||||
|
||||
// 0x11 | 0x22 = 0x33, but not implemented in NMOS cpu
|
||||
cpu.step();
|
||||
assertEquals(0x00, cpu.getAccumulator());
|
||||
assertEquals(zState, cpu.getZeroFlag()); // unchanged
|
||||
assertEquals(nState, cpu.getNegativeFlag()); // unchanged
|
||||
|
||||
// 0x33 | 0x44 = 0x77, but not implemented in NMOS cpu
|
||||
cpu.step();
|
||||
assertEquals(0x00, cpu.getAccumulator());
|
||||
assertEquals(zState, cpu.getZeroFlag()); // unchanged
|
||||
assertEquals(nState, cpu.getNegativeFlag()); // unchanged
|
||||
|
||||
// 0x77 | 0x88 = 0xff, but not implemented in NMOS cpu
|
||||
cpu.step();
|
||||
assertEquals(0x00, cpu.getAccumulator());
|
||||
assertEquals(zState, cpu.getZeroFlag()); // unchanged
|
||||
assertEquals(nState, cpu.getNegativeFlag()); // unchanged
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_and() throws Exception {
|
||||
makeCmosCpu();
|
||||
|
||||
// Set some initial values in zero page.
|
||||
bus.write(0x30, 0x00);
|
||||
bus.write(0x31, 0x10);
|
||||
|
||||
bus.write(0x40, 0x01);
|
||||
bus.write(0x41, 0x10);
|
||||
|
||||
bus.write(0x50, 0x02);
|
||||
bus.write(0x51, 0x10);
|
||||
|
||||
bus.write(0x1000, 0x33);
|
||||
bus.write(0x1001, 0x11);
|
||||
bus.write(0x1002, 0x88);
|
||||
|
||||
bus.loadProgram(0x32, 0x30, // AND ($30)
|
||||
0x32, 0x40, // AND ($40)
|
||||
0x32, 0x50); // AND ($50)
|
||||
|
||||
cpu.setAccumulator(0xff);
|
||||
|
||||
// 0xFF & 0x33 == 0x33
|
||||
cpu.step();
|
||||
assertEquals(0x33, cpu.getAccumulator());
|
||||
assertFalse(cpu.getZeroFlag());
|
||||
assertFalse(cpu.getNegativeFlag());
|
||||
|
||||
// 0x33 & 0x11 == 0x11
|
||||
cpu.step();
|
||||
assertEquals(0x11, cpu.getAccumulator());
|
||||
assertFalse(cpu.getZeroFlag());
|
||||
assertFalse(cpu.getNegativeFlag());
|
||||
|
||||
// 0x11 & 0x80 == 0
|
||||
cpu.step();
|
||||
assertEquals(0, cpu.getAccumulator());
|
||||
assertTrue(cpu.getZeroFlag());
|
||||
assertFalse(cpu.getNegativeFlag());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_and_requiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
|
||||
// Set some initial values in zero page.
|
||||
bus.write(0x30, 0x00);
|
||||
bus.write(0x31, 0x10);
|
||||
|
||||
bus.write(0x40, 0x01);
|
||||
bus.write(0x41, 0x10);
|
||||
|
||||
bus.write(0x50, 0x02);
|
||||
bus.write(0x51, 0x10);
|
||||
|
||||
bus.write(0x1000, 0x33);
|
||||
bus.write(0x1001, 0x11);
|
||||
bus.write(0x1002, 0x88);
|
||||
|
||||
bus.loadProgram(0x32, 0x30, // AND ($30)
|
||||
0x32, 0x40, // AND ($40)
|
||||
0x32, 0x50); // AND ($50)
|
||||
|
||||
|
||||
cpu.setAccumulator(0xff);
|
||||
|
||||
boolean zState = cpu.getZeroFlag();
|
||||
boolean nState = cpu.getNegativeFlag();
|
||||
|
||||
// 0xFF & 0x33 == 0x33, but not implemented in NMOS cpu
|
||||
cpu.step();
|
||||
assertEquals(0xff, cpu.getAccumulator());
|
||||
assertEquals(zState, cpu.getZeroFlag());
|
||||
assertEquals(nState, cpu.getNegativeFlag());
|
||||
|
||||
// 0x33 & 0x11 == 0x11, but not implemented in NMOS cpu
|
||||
cpu.step();
|
||||
assertEquals(0xff, cpu.getAccumulator());
|
||||
assertEquals(zState, cpu.getZeroFlag());
|
||||
assertEquals(nState, cpu.getNegativeFlag());
|
||||
|
||||
// 0x11 & 0x80 == 0, but not implemented in NMOS cpu
|
||||
cpu.step();
|
||||
assertEquals(0xff, cpu.getAccumulator());
|
||||
assertEquals(zState, cpu.getZeroFlag());
|
||||
assertEquals(nState, cpu.getNegativeFlag());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_eor() throws Exception {
|
||||
makeCmosCpu();
|
||||
|
||||
// Set some initial values in zero page.
|
||||
bus.write(0x30, 0x00);
|
||||
bus.write(0x31, 0x10);
|
||||
|
||||
bus.write(0x40, 0x01);
|
||||
bus.write(0x41, 0x10);
|
||||
|
||||
bus.write(0x50, 0x02);
|
||||
bus.write(0x51, 0x10);
|
||||
|
||||
bus.write(0x60, 0x03);
|
||||
bus.write(0x61, 0x10);
|
||||
|
||||
bus.write(0x1000, 0x00);
|
||||
bus.write(0x1001, 0xff);
|
||||
bus.write(0x1002, 0x33);
|
||||
bus.write(0x1003, 0x44);
|
||||
|
||||
bus.loadProgram(0x52, 0x30, // AND ($30)
|
||||
0x52, 0x40, // AND ($40)
|
||||
0x52, 0x50, // EOR ($50)
|
||||
0x52, 0x60); // AND ($60)
|
||||
|
||||
|
||||
cpu.setAccumulator(0x88);
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x88, cpu.getAccumulator());
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x77, cpu.getAccumulator());
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x44, cpu.getAccumulator());
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x00, cpu.getAccumulator());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_eor_requiresCmosCpu() throws Exception {
|
||||
makeNmosCpu();
|
||||
|
||||
// Set some initial values in zero page.
|
||||
bus.write(0x30, 0x00);
|
||||
bus.write(0x31, 0x10);
|
||||
|
||||
bus.write(0x40, 0x01);
|
||||
bus.write(0x41, 0x10);
|
||||
|
||||
bus.write(0x50, 0x02);
|
||||
bus.write(0x51, 0x10);
|
||||
|
||||
bus.write(0x60, 0x03);
|
||||
bus.write(0x61, 0x10);
|
||||
|
||||
bus.write(0x1000, 0x00);
|
||||
bus.write(0x1001, 0xff);
|
||||
bus.write(0x1002, 0x33);
|
||||
bus.write(0x1003, 0x44);
|
||||
|
||||
bus.loadProgram(0x52, 0x30, // AND ($30)
|
||||
0x52, 0x40, // AND ($40)
|
||||
0x52, 0x50, // EOR ($50)
|
||||
0x52, 0x60); // AND ($60)
|
||||
|
||||
|
||||
cpu.setAccumulator(0x88);
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x88, cpu.getAccumulator());
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x88, cpu.getAccumulator());
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x88, cpu.getAccumulator());
|
||||
|
||||
cpu.step();
|
||||
assertEquals(0x88, cpu.getAccumulator());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user