At long last, implemented BRK. Lots more unit tests for stack processing, as well.
This commit is contained in:
1 parent
46a5943736
commit
473b47e832
3 files changed
+546
-18
No files matched your search
@@ -9,6 +9,16 @@ public class Cpu implements InstructionTable {
|
|||||||
|
|
||||||
public static final int DEFAULT_BASE_ADDRESS = 0x200;
|
public static final int DEFAULT_BASE_ADDRESS = 0x200;
|
||||||
|
|
||||||
|
/* Process status register mnemonics */
|
||||||
|
public static final int P_CARRY = 0x01;
|
||||||
|
public static final int P_ZERO = 0x02;
|
||||||
|
public static final int P_IRQ_DISABLE = 0x04;
|
||||||
|
public static final int P_DECIMAL = 0x08;
|
||||||
|
public static final int P_BREAK = 0x10;
|
||||||
|
// Bit 5 is always '1'
|
||||||
|
public static final int P_OVERFLOW = 0x40;
|
||||||
|
public static final int P_NEGATIVE = 0x80;
|
||||||
|
|
||||||
/* The Bus */
|
/* The Bus */
|
||||||
private Bus bus;
|
private Bus bus;
|
||||||
|
|
||||||
@@ -19,7 +29,7 @@ public class Cpu implements InstructionTable {
|
|||||||
|
|
||||||
/* Internal Registers */
|
/* Internal Registers */
|
||||||
private int pc; // Program Counter register
|
private int pc; // Program Counter register
|
||||||
private int sp; // Stack Pointer register
|
private int sp; // Stack Pointer register, offset into page 1
|
||||||
private int ir; // Instruction register
|
private int ir; // Instruction register
|
||||||
|
|
||||||
/* Operands for the current instruction */
|
/* Operands for the current instruction */
|
||||||
@@ -35,7 +45,6 @@ public class Cpu implements InstructionTable {
|
|||||||
private boolean decimalModeFlag;
|
private boolean decimalModeFlag;
|
||||||
private boolean breakFlag;
|
private boolean breakFlag;
|
||||||
private boolean overflowFlag;
|
private boolean overflowFlag;
|
||||||
// Note: Zero Flag and Negative Flag are read directly from Accumulator.
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new CPU.
|
* Construct a new CPU.
|
||||||
@@ -61,7 +70,7 @@ public class Cpu implements InstructionTable {
|
|||||||
*/
|
*/
|
||||||
public void reset() {
|
public void reset() {
|
||||||
// Registers
|
// Registers
|
||||||
sp = 0x01ff;
|
sp = 0xff;
|
||||||
|
|
||||||
// Set the PC to the address stored in 0xfffc
|
// Set the PC to the address stored in 0xfffc
|
||||||
pc = CpuUtils.address(bus.read(0xfffc), bus.read(0xfffd));
|
pc = CpuUtils.address(bus.read(0xfffc), bus.read(0xfffd));
|
||||||
@@ -110,8 +119,15 @@ public class Cpu implements InstructionTable {
|
|||||||
// Execute
|
// Execute
|
||||||
switch(ir) {
|
switch(ir) {
|
||||||
|
|
||||||
case 0x00: // HLT
|
case 0x00: // BRK - Force Interrupt, Implied
|
||||||
// TODO: Halt!
|
if (!getIrqDisableFlag()) {
|
||||||
|
stackPush((pc >> 8) & 0xff); // PC high byte
|
||||||
|
stackPush(pc & 0xff); // PC low byte
|
||||||
|
stackPush(getProcessorStatus());
|
||||||
|
// Load interrupt vector address into PC
|
||||||
|
pc = CpuUtils.address(bus.read(0xfffc), bus.read(0xfffd));
|
||||||
|
setBreakFlag();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x01: // n/a
|
case 0x01: // n/a
|
||||||
break;
|
break;
|
||||||
@@ -726,6 +742,14 @@ public class Cpu implements InstructionTable {
|
|||||||
this.negativeFlag = negativeFlag;
|
this.negativeFlag = negativeFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setNegativeFlag() {
|
||||||
|
this.negativeFlag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearNegativeFlag() {
|
||||||
|
this.negativeFlag = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the carry flag
|
* @return the carry flag
|
||||||
*/
|
*/
|
||||||
@@ -921,6 +945,69 @@ public class Cpu implements InstructionTable {
|
|||||||
this.pc = addr;
|
this.pc = addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getStackPointer() {
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStackPointer(int offset) {
|
||||||
|
this.sp = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @value The value of the Process Status Register bits to be set.
|
||||||
|
*/
|
||||||
|
public void setProcessorStatus(int value) {
|
||||||
|
if ((value&P_CARRY) != 0)
|
||||||
|
setCarryFlag();
|
||||||
|
else
|
||||||
|
clearCarryFlag();
|
||||||
|
|
||||||
|
if ((value&P_ZERO) != 0)
|
||||||
|
setZeroFlag();
|
||||||
|
else
|
||||||
|
clearZeroFlag();
|
||||||
|
|
||||||
|
if ((value&P_IRQ_DISABLE) != 0)
|
||||||
|
setIrqDisableFlag();
|
||||||
|
else
|
||||||
|
clearIrqDisableFlag();
|
||||||
|
|
||||||
|
if ((value&P_DECIMAL) != 0)
|
||||||
|
setDecimalModeFlag();
|
||||||
|
else
|
||||||
|
clearDecimalModeFlag();
|
||||||
|
|
||||||
|
if ((value&P_BREAK) != 0)
|
||||||
|
setBreakFlag();
|
||||||
|
else
|
||||||
|
clearBreakFlag();
|
||||||
|
|
||||||
|
if ((value&P_OVERFLOW) != 0)
|
||||||
|
setOverflowFlag();
|
||||||
|
else
|
||||||
|
clearOverflowFlag();
|
||||||
|
|
||||||
|
if ((value&P_NEGATIVE) != 0)
|
||||||
|
setNegativeFlag();
|
||||||
|
else
|
||||||
|
clearNegativeFlag();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns The value of the Process Status Register, as a byte.
|
||||||
|
*/
|
||||||
|
public int getProcessorStatus() {
|
||||||
|
int status = 0x20;
|
||||||
|
if (getCarryFlag()) { status |= P_CARRY; }
|
||||||
|
if (getZeroFlag()) { status |= P_ZERO; }
|
||||||
|
if (getIrqDisableFlag()) { status |= P_IRQ_DISABLE; }
|
||||||
|
if (getDecimalModeFlag()) { status |= P_DECIMAL; }
|
||||||
|
if (getBreakFlag()) { status |= P_BREAK; }
|
||||||
|
if (getOverflowFlag()) { status |= P_OVERFLOW; }
|
||||||
|
if (getNegativeFlag()) { status |= P_NEGATIVE; }
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A string representing the current status register state.
|
* @return A string representing the current status register state.
|
||||||
*/
|
*/
|
||||||
@@ -955,24 +1042,38 @@ public class Cpu implements InstructionTable {
|
|||||||
/**
|
/**
|
||||||
* Push an item onto the stack, and decrement the stack counter.
|
* Push an item onto the stack, and decrement the stack counter.
|
||||||
* Silently fails to push onto the stack if SP is
|
* Silently fails to push onto the stack if SP is
|
||||||
* TODO: Unit tests.
|
|
||||||
*/
|
*/
|
||||||
protected void push(int data) {
|
void stackPush(int data) {
|
||||||
bus.write(sp, data);
|
bus.write(0x100+sp, data);
|
||||||
if (sp > 0x100) { sp--; }
|
|
||||||
|
if (sp == 0)
|
||||||
|
sp = 0xff;
|
||||||
|
else
|
||||||
|
--sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pop a byte off the user stack, and increment the stack counter.
|
* Pre-increment the stack pointer, and return the top of the stack.
|
||||||
* TODO: Unit tests.
|
|
||||||
*/
|
*/
|
||||||
protected int pop() {
|
int stackPop() {
|
||||||
int data = bus.read(sp);
|
if (sp == 0xff)
|
||||||
if (sp < 0x1ff) { sp++; }
|
sp = 0x00;
|
||||||
|
else
|
||||||
|
++sp;
|
||||||
|
|
||||||
|
int data = bus.read(0x100+sp);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peek at the value currently at the top of the stack
|
||||||
|
*/
|
||||||
|
int stackPeek() {
|
||||||
|
return bus.read(0x100+sp+1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Increment the PC, rolling over if necessary.
|
* Increment the PC, rolling over if necessary.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package com.loomcom.symon;
|
||||||
|
|
||||||
|
import com.loomcom.symon.devices.Memory;
|
||||||
|
import com.loomcom.symon.exceptions.MemoryRangeException;
|
||||||
|
import junit.framework.*;
|
||||||
|
|
||||||
|
public class CpuImpliedModeTest extends TestCase {
|
||||||
|
|
||||||
|
protected Cpu cpu;
|
||||||
|
protected Bus bus;
|
||||||
|
protected Memory mem;
|
||||||
|
|
||||||
|
public void setUp() throws MemoryRangeException {
|
||||||
|
this.cpu = new Cpu();
|
||||||
|
this.bus = new Bus(0x0000, 0xffff);
|
||||||
|
this.mem = new Memory(0x0000, 0x10000);
|
||||||
|
bus.addCpu(cpu);
|
||||||
|
bus.addDevice(mem);
|
||||||
|
|
||||||
|
// Load the reset vector.
|
||||||
|
bus.write(0xfffc, Cpu.DEFAULT_BASE_ADDRESS & 0x00ff);
|
||||||
|
bus.write(0xfffd, (Cpu.DEFAULT_BASE_ADDRESS & 0xff00)>>>8);
|
||||||
|
|
||||||
|
cpu.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following opcodes are tested for correctness in this file:
|
||||||
|
*
|
||||||
|
* BRK - $00
|
||||||
|
* CLC - $18
|
||||||
|
* CLD - $d8
|
||||||
|
* CLI - $58
|
||||||
|
* CLV - $B8
|
||||||
|
*
|
||||||
|
* DEX - $ca
|
||||||
|
* DEY - $88
|
||||||
|
* INX - $e8
|
||||||
|
* INY - $c8
|
||||||
|
* NOP - $ea
|
||||||
|
*
|
||||||
|
* PHA - $48
|
||||||
|
* PHP - $08
|
||||||
|
* PLA - $68
|
||||||
|
* PLP - $28
|
||||||
|
* RTI - $40
|
||||||
|
*
|
||||||
|
* RTS - $60
|
||||||
|
* SEC - $38
|
||||||
|
* SED - $f8
|
||||||
|
* SEI - $78
|
||||||
|
* TAX - $aa
|
||||||
|
*
|
||||||
|
* TAY - $a8
|
||||||
|
* TSX - $ba
|
||||||
|
* TXA - $8a
|
||||||
|
* TXS - $9a
|
||||||
|
* TYA - $98
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* BRK Tests - 0x00 */
|
||||||
|
|
||||||
|
public void test_BRK() {
|
||||||
|
cpu.setCarryFlag();
|
||||||
|
cpu.setOverflowFlag();
|
||||||
|
assertEquals(0x20|Cpu.P_CARRY|Cpu.P_OVERFLOW,
|
||||||
|
cpu.getProcessorStatus());
|
||||||
|
assertEquals(0xff, cpu.stackPeek());
|
||||||
|
assertFalse(cpu.getBreakFlag());
|
||||||
|
assertEquals(0x0200, cpu.getProgramCounter());
|
||||||
|
assertEquals(0xff, cpu.getStackPointer());
|
||||||
|
|
||||||
|
bus.loadProgram(0xea,
|
||||||
|
0xea,
|
||||||
|
0xea,
|
||||||
|
0x00);
|
||||||
|
|
||||||
|
cpu.step(3); // Three NOP instructions
|
||||||
|
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
cpu.step(); // Triggers the BRK
|
||||||
|
|
||||||
|
// Was at PC = 0x204, which should now be on the stack
|
||||||
|
assertEquals(0x02, bus.read(0x1ff)); // PC high byte
|
||||||
|
assertEquals(0x04, bus.read(0x1fe)); // PC low byte
|
||||||
|
assertEquals(0x20|Cpu.P_CARRY|Cpu.P_OVERFLOW,
|
||||||
|
bus.read(0x1fd)); // Processor Status
|
||||||
|
|
||||||
|
// Reset to original contents of PC
|
||||||
|
assertEquals(0x0200, cpu.getProgramCounter());
|
||||||
|
assertEquals(0xfc, cpu.getStackPointer());
|
||||||
|
assertEquals(0x20|Cpu.P_CARRY|Cpu.P_OVERFLOW|Cpu.P_BREAK,
|
||||||
|
cpu.getProcessorStatus());
|
||||||
|
assertEquals(0x20|Cpu.P_CARRY|Cpu.P_OVERFLOW,
|
||||||
|
cpu.stackPeek());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void test_BRK_HonorsIrqDisableFlag() {
|
||||||
|
cpu.setIrqDisableFlag();
|
||||||
|
|
||||||
|
bus.loadProgram(0xea,
|
||||||
|
0xea,
|
||||||
|
0xea,
|
||||||
|
0x00,
|
||||||
|
0xea,
|
||||||
|
0xea);
|
||||||
|
|
||||||
|
cpu.step(3); // Three NOP instructions
|
||||||
|
|
||||||
|
assertEquals(0x203, cpu.getProgramCounter());
|
||||||
|
|
||||||
|
// Triggers the BRK, which should do nothing because
|
||||||
|
// of the Interrupt Disable flag
|
||||||
|
cpu.step();
|
||||||
|
|
||||||
|
// Reset to original contents of PC
|
||||||
|
assertEquals(0x0204, cpu.getProgramCounter());
|
||||||
|
// Empty stack
|
||||||
|
assertEquals(0xff, cpu.getStackPointer());
|
||||||
|
|
||||||
|
cpu.step(2); // Two more NOPs
|
||||||
|
|
||||||
|
// Reset to original contents of PC
|
||||||
|
assertEquals(0x0206, cpu.getProgramCounter());
|
||||||
|
// Empty stack
|
||||||
|
assertEquals(0xff, cpu.getStackPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,11 +9,11 @@ import com.loomcom.symon.exceptions.*;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CpuTest extends TestCase {
|
public class CpuTest extends TestCase {
|
||||||
|
|
||||||
private Cpu cpu;
|
private Cpu cpu;
|
||||||
private Bus bus;
|
private Bus bus;
|
||||||
private Memory mem;
|
private Memory mem;
|
||||||
|
|
||||||
public CpuTest(String testName) {
|
public CpuTest(String testName) {
|
||||||
super(testName);
|
super(testName);
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ public class CpuTest extends TestCase {
|
|||||||
public static Test suite() {
|
public static Test suite() {
|
||||||
return new TestSuite(CpuTest.class);
|
return new TestSuite(CpuTest.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUp() throws MemoryRangeException {
|
public void setUp() throws MemoryRangeException {
|
||||||
this.cpu = new Cpu();
|
this.cpu = new Cpu();
|
||||||
this.bus = new Bus(0x0000, 0xffff);
|
this.bus = new Bus(0x0000, 0xffff);
|
||||||
@@ -35,7 +35,7 @@ public class CpuTest extends TestCase {
|
|||||||
|
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testReset() {
|
public void testReset() {
|
||||||
assertEquals(0, cpu.getAccumulator());
|
assertEquals(0, cpu.getAccumulator());
|
||||||
assertEquals(0, cpu.getXRegister());
|
assertEquals(0, cpu.getXRegister());
|
||||||
@@ -49,4 +49,301 @@ public class CpuTest extends TestCase {
|
|||||||
assertFalse(cpu.getOverflowFlag());
|
assertFalse(cpu.getOverflowFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testStack() {
|
||||||
|
|
||||||
|
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() {
|
||||||
|
assertEquals(0xff, cpu.getStackPointer());
|
||||||
|
assertEquals(0xff, 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() {
|
||||||
|
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() {
|
||||||
|
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() {
|
||||||
|
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() {
|
||||||
|
int val = 0;
|
||||||
|
|
||||||
|
assertEquals(0xff, 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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user