Files
ksymon/src/test/java/com/loomcom/symon/CpuTest.java
T
Seth Morabito bc3de80892 Execution Trace Log
Introduces an execution trace window that will keep track of the most
recent 10000 execution steps. I'm not entirely happy with the
implementation, yet.
2012-12-09 17:04:31 -08:00

395 lines
13 KiB
Java

package com.loomcom.symon;
import junit.framework.*;
import com.loomcom.symon.devices.*;
import com.loomcom.symon.exceptions.*;
/**
*
*/
public class CpuTest extends TestCase {
private Cpu cpu;
private Bus bus;
private Memory mem;
public CpuTest(String testName) {
super(testName);
}
public static Test suite() {
return new TestSuite(CpuTest.class);
}
public void setUp() throws MemoryRangeException, MemoryAccessException {
this.cpu = new Cpu();
this.bus = new Bus(0x0000, 0xffff);
this.mem = new Memory(0x0000, 0x10000);
bus.addCpu(cpu);
bus.addDevice(mem);
// All test programs start at 0x0200;
bus.write(0xfffc, 0x00);
bus.write(0xfffd, 0x02);
cpu.reset();
}
public void testReset() {
assertEquals(0, cpu.getAccumulator());
assertEquals(0, cpu.getXRegister());
assertEquals(0, cpu.getYRegister());
assertEquals(0x0200, cpu.getProgramCounter());
assertFalse(cpu.getCarryFlag());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getIrqDisableFlag());
assertFalse(cpu.getDecimalModeFlag());
assertFalse(cpu.getBreakFlag());
assertFalse(cpu.getOverflowFlag());
assertFalse(cpu.getNegativeFlag());
}
public void testStack() throws MemoryAccessException {
cpu.stackPush(0x13);
assertEquals(0x13, cpu.stackPop());
cpu.stackPush(0x12);
assertEquals(0x12, cpu.stackPop());
for (int i = 0x00; i <= 0xff; i++) {
cpu.stackPush(i);
}
for (int i = 0xff; i >= 0x00; i--) {
assertEquals(i, cpu.stackPop());
}
}
public void testStackPush() throws MemoryAccessException {
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0x00, bus.read(0x1ff));
cpu.stackPush(0x06);
assertEquals(0xfe, cpu.getStackPointer());
assertEquals(0x06, bus.read(0x1ff));
cpu.stackPush(0x05);
assertEquals(0xfd, cpu.getStackPointer());
assertEquals(0x06, bus.read(0x1ff));
assertEquals(0x05, bus.read(0x1fe));
cpu.stackPush(0x04);
assertEquals(0xfc, cpu.getStackPointer());
assertEquals(0x06, bus.read(0x1ff));
assertEquals(0x05, bus.read(0x1fe));
assertEquals(0x04, bus.read(0x1fd));
cpu.stackPush(0x03);
assertEquals(0xfb, cpu.getStackPointer());
assertEquals(0x06, bus.read(0x1ff));
assertEquals(0x05, bus.read(0x1fe));
assertEquals(0x04, bus.read(0x1fd));
assertEquals(0x03, bus.read(0x1fc));
cpu.stackPush(0x02);
assertEquals(0xfa, cpu.getStackPointer());
assertEquals(0x06, bus.read(0x1ff));
assertEquals(0x05, bus.read(0x1fe));
assertEquals(0x04, bus.read(0x1fd));
assertEquals(0x03, bus.read(0x1fc));
assertEquals(0x02, bus.read(0x1fb));
cpu.stackPush(0x01);
assertEquals(0xf9, cpu.getStackPointer());
assertEquals(0x06, bus.read(0x1ff));
assertEquals(0x05, bus.read(0x1fe));
assertEquals(0x04, bus.read(0x1fd));
assertEquals(0x03, bus.read(0x1fc));
assertEquals(0x02, bus.read(0x1fb));
assertEquals(0x01, bus.read(0x1fa));
}
public void testStackPushWrapsAroundToStackTop() throws MemoryAccessException {
cpu.setStackPointer(0x01);
cpu.stackPush(0x01);
assertEquals(0x01, bus.read(0x101));
assertEquals(0x00, cpu.getStackPointer());
cpu.stackPush(0x02);
assertEquals(0x02, bus.read(0x100));
assertEquals(0xff, cpu.getStackPointer());
cpu.stackPush(0x03);
assertEquals(0x03, bus.read(0x1ff));
assertEquals(0xfe, cpu.getStackPointer());
}
public void testStackPop() throws MemoryAccessException {
bus.write(0x1ff, 0x06);
bus.write(0x1fe, 0x05);
bus.write(0x1fd, 0x04);
bus.write(0x1fc, 0x03);
bus.write(0x1fb, 0x02);
bus.write(0x1fa, 0x01);
cpu.setStackPointer(0xf9);
assertEquals(0x01, cpu.stackPop());
assertEquals(0xfa, cpu.getStackPointer());
assertEquals(0x02, cpu.stackPop());
assertEquals(0xfb, cpu.getStackPointer());
assertEquals(0x03, cpu.stackPop());
assertEquals(0xfc, cpu.getStackPointer());
assertEquals(0x04, cpu.stackPop());
assertEquals(0xfd, cpu.getStackPointer());
assertEquals(0x05, cpu.stackPop());
assertEquals(0xfe, cpu.getStackPointer());
assertEquals(0x06, cpu.stackPop());
assertEquals(0xff, cpu.getStackPointer());
}
public void testStackPopWrapsAroundToStackBottom() throws MemoryAccessException {
bus.write(0x1ff, 0x0f); // top of stack
bus.write(0x100, 0xf0); // bottom of stack
bus.write(0x101, 0xf1);
bus.write(0x102, 0xf2);
cpu.setStackPointer(0xfe);
assertEquals(0x0f, cpu.stackPop());
assertEquals(0xff, cpu.getStackPointer());
assertEquals(0xf0, cpu.stackPop());
assertEquals(0x00, cpu.getStackPointer());
assertEquals(0xf1, cpu.stackPop());
assertEquals(0x01, cpu.getStackPointer());
assertEquals(0xf2, cpu.stackPop());
assertEquals(0x02, cpu.getStackPointer());
}
public void testStackPeekDoesNotAlterStackPointer() throws MemoryAccessException {
assertEquals(0x00, cpu.stackPeek());
assertEquals(0xff, cpu.getStackPointer());
cpu.stackPush(0x01);
assertEquals(0x01, cpu.stackPeek());
assertEquals(0xfe, cpu.getStackPointer());
cpu.stackPush(0x02);
assertEquals(0x02, cpu.stackPeek());
assertEquals(0xfd, cpu.getStackPointer());
cpu.stackPush(0x03);
assertEquals(0x03, cpu.stackPeek());
assertEquals(0xfc, cpu.getStackPointer());
cpu.stackPush(0x04);
assertEquals(0x04, cpu.stackPeek());
assertEquals(0xfb, cpu.getStackPointer());
assertEquals(0x04, cpu.stackPeek());
assertEquals(0xfb, cpu.getStackPointer());
assertEquals(0x04, cpu.stackPeek());
assertEquals(0xfb, cpu.getStackPointer());
}
public void testGetProcessorStatus() {
// By default, no flags are set. Remember, bit 5
// is always '1'.
assertEquals(0x20, cpu.getProcessorStatus());
cpu.setCarryFlag();
assertEquals(0x21, cpu.getProcessorStatus());
cpu.setZeroFlag();
assertEquals(0x23, cpu.getProcessorStatus());
cpu.setIrqDisableFlag();
assertEquals(0x27, cpu.getProcessorStatus());
cpu.setDecimalModeFlag();
assertEquals(0x2f, cpu.getProcessorStatus());
cpu.setBreakFlag();
assertEquals(0x3f, cpu.getProcessorStatus());
cpu.setOverflowFlag();
assertEquals(0x7f, cpu.getProcessorStatus());
cpu.setNegativeFlag();
assertEquals(0xff, cpu.getProcessorStatus());
cpu.clearCarryFlag();
assertEquals(0xfe, cpu.getProcessorStatus());
cpu.clearZeroFlag();
assertEquals(0xfc, cpu.getProcessorStatus());
cpu.clearIrqDisableFlag();
assertEquals(0xf8, cpu.getProcessorStatus());
cpu.clearDecimalModeFlag();
assertEquals(0xf0, cpu.getProcessorStatus());
cpu.clearBreakFlag();
assertEquals(0xe0, cpu.getProcessorStatus());
cpu.clearOverflowFlag();
assertEquals(0xa0, cpu.getProcessorStatus());
cpu.clearNegativeFlag();
assertEquals(0x20, cpu.getProcessorStatus());
}
public void testSetProcessorStatus() {
// Default
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getIrqDisableFlag());
assertFalse(cpu.getDecimalModeFlag());
assertFalse(cpu.getBreakFlag());
assertFalse(cpu.getOverflowFlag());
assertFalse(cpu.getNegativeFlag());
cpu.setProcessorStatus(0x20 | Cpu.P_CARRY);
assertTrue(cpu.getCarryFlag());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getIrqDisableFlag());
assertFalse(cpu.getDecimalModeFlag());
assertFalse(cpu.getBreakFlag());
assertFalse(cpu.getOverflowFlag());
assertFalse(cpu.getNegativeFlag());
cpu.setProcessorStatus(0x20 | Cpu.P_CARRY | Cpu.P_NEGATIVE);
assertTrue(cpu.getCarryFlag());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getIrqDisableFlag());
assertFalse(cpu.getDecimalModeFlag());
assertFalse(cpu.getBreakFlag());
assertFalse(cpu.getOverflowFlag());
assertTrue(cpu.getNegativeFlag());
cpu.setProcessorStatus(0x20 | Cpu.P_CARRY | Cpu.P_NEGATIVE | Cpu.P_ZERO);
assertTrue(cpu.getCarryFlag());
assertTrue(cpu.getZeroFlag());
assertFalse(cpu.getIrqDisableFlag());
assertFalse(cpu.getDecimalModeFlag());
assertFalse(cpu.getBreakFlag());
assertFalse(cpu.getOverflowFlag());
assertTrue(cpu.getNegativeFlag());
cpu.setProcessorStatus(0x20 | Cpu.P_CARRY | Cpu.P_NEGATIVE | Cpu.P_ZERO |
Cpu.P_OVERFLOW);
assertTrue(cpu.getCarryFlag());
assertTrue(cpu.getZeroFlag());
assertFalse(cpu.getIrqDisableFlag());
assertFalse(cpu.getDecimalModeFlag());
assertFalse(cpu.getBreakFlag());
assertTrue(cpu.getOverflowFlag());
assertTrue(cpu.getNegativeFlag());
cpu.setProcessorStatus(0x20 | Cpu.P_CARRY | Cpu.P_NEGATIVE | Cpu.P_ZERO |
Cpu.P_OVERFLOW | Cpu.P_BREAK);
assertTrue(cpu.getCarryFlag());
assertTrue(cpu.getZeroFlag());
assertFalse(cpu.getIrqDisableFlag());
assertFalse(cpu.getDecimalModeFlag());
assertTrue(cpu.getBreakFlag());
assertTrue(cpu.getOverflowFlag());
assertTrue(cpu.getNegativeFlag());
cpu.setProcessorStatus(0x20 | Cpu.P_CARRY | Cpu.P_NEGATIVE | Cpu.P_ZERO |
Cpu.P_OVERFLOW | Cpu.P_BREAK | Cpu.P_DECIMAL);
assertTrue(cpu.getCarryFlag());
assertTrue(cpu.getZeroFlag());
assertFalse(cpu.getIrqDisableFlag());
assertTrue(cpu.getDecimalModeFlag());
assertTrue(cpu.getBreakFlag());
assertTrue(cpu.getOverflowFlag());
assertTrue(cpu.getNegativeFlag());
cpu.setProcessorStatus(0x20 | Cpu.P_CARRY | Cpu.P_NEGATIVE | Cpu.P_ZERO |
Cpu.P_OVERFLOW | Cpu.P_BREAK | Cpu.P_DECIMAL |
Cpu.P_IRQ_DISABLE);
assertTrue(cpu.getCarryFlag());
assertTrue(cpu.getZeroFlag());
assertTrue(cpu.getIrqDisableFlag());
assertTrue(cpu.getDecimalModeFlag());
assertTrue(cpu.getBreakFlag());
assertTrue(cpu.getOverflowFlag());
assertTrue(cpu.getNegativeFlag());
cpu.setProcessorStatus(0x20);
assertFalse(cpu.getCarryFlag());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getIrqDisableFlag());
assertFalse(cpu.getDecimalModeFlag());
assertFalse(cpu.getBreakFlag());
assertFalse(cpu.getOverflowFlag());
assertFalse(cpu.getNegativeFlag());
cpu.setProcessorStatus(0x00);
assertFalse(cpu.getCarryFlag());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getIrqDisableFlag());
assertFalse(cpu.getDecimalModeFlag());
assertFalse(cpu.getBreakFlag());
assertFalse(cpu.getOverflowFlag());
assertFalse(cpu.getNegativeFlag());
}
public void testAddress() {
assertEquals(0xf1ea, cpu.address(0xea, 0xf1));
assertEquals(0x00ea, cpu.address(0xea, 0x00));
assertEquals(0xf100, cpu.address(0x00, 0xf1));
assertEquals(0x1234, cpu.address(0x34, 0x12));
assertEquals(0xffff, cpu.address(0xff, 0xff));
}
public void testZpxAddress() {
cpu.setXRegister(0x00);
assertEquals(0x10, cpu.zpxAddress(0x10));
cpu.setXRegister(0x10);
assertEquals(0x20, cpu.zpxAddress(0x10));
cpu.setXRegister(0x25);
assertEquals(0x35, cpu.zpxAddress(0x10));
cpu.setXRegister(0xf5);
assertEquals(0x05, cpu.zpxAddress(0x10));
cpu.setXRegister(0x00);
assertEquals(0x80, cpu.zpxAddress(0x80));
cpu.setXRegister(0x10);
assertEquals(0x90, cpu.zpxAddress(0x80));
cpu.setXRegister(0x25);
assertEquals(0xa5, cpu.zpxAddress(0x80));
cpu.setXRegister(0x95);
assertEquals(0x15, cpu.zpxAddress(0x80));
}
public void testZpyAddress() {
cpu.setYRegister(0x00);
assertEquals(0x10, cpu.zpyAddress(0x10));
cpu.setYRegister(0x10);
assertEquals(0x20, cpu.zpyAddress(0x10));
cpu.setYRegister(0x25);
assertEquals(0x35, cpu.zpyAddress(0x10));
cpu.setYRegister(0xf5);
assertEquals(0x05, cpu.zpyAddress(0x10));
cpu.setYRegister(0x00);
assertEquals(0x80, cpu.zpyAddress(0x80));
cpu.setYRegister(0x10);
assertEquals(0x90, cpu.zpyAddress(0x80));
cpu.setYRegister(0x25);
assertEquals(0xa5, cpu.zpyAddress(0x80));
cpu.setYRegister(0x95);
assertEquals(0x15, cpu.zpyAddress(0x80));
}
}