1
0
mirror of https://github.com/sethm/symon.git synced 2024-06-03 07:29:30 +00:00

1. CPU now correctly sets Zero and Negative flags for LDA, LDX, and LDY

immediate mode instructions.

2. Added unit tests for LDA, LDX, LDY immediate mode instructions.
This commit is contained in:
Seth Morabito 2008-12-13 01:53:15 -08:00
parent 59e5572039
commit 9a6a256073
4 changed files with 215 additions and 27 deletions

View File

@ -27,6 +27,7 @@ public class Cpu implements InstructionTable {
/* Status Flag Register bits */
private boolean carryFlag;
private boolean negativeFlag;
private boolean zeroFlag;
private boolean irqDisableFlag;
private boolean decimalModeFlag;
@ -435,13 +436,15 @@ public class Cpu implements InstructionTable {
case 0xa0: // LDY - Immediate
y = operands[0];
// TODO: Set Zero Flag, Negative Flag
setZeroFlag(y);
setNegativeFlag(y);
break;
case 0xa1: // n/a
break;
case 0xa2: // LDX - Immediate
x = operands[0];
// TODO: Set Zero Flag, Negative Flag
setZeroFlag(x);
setNegativeFlag(x);
break;
case 0xa3: // n/a
break;
@ -457,7 +460,8 @@ public class Cpu implements InstructionTable {
break;
case 0xa9: // LDA - Immediate
a = operands[0];
// TODO: Set Zero Flag, Negative Flag
setZeroFlag(a);
setNegativeFlag(a);
break;
case 0xaa: // n/a
break;
@ -643,8 +647,21 @@ public class Cpu implements InstructionTable {
* @return the negative flag
*/
public boolean getNegativeFlag() {
// True if the most significant bit is '1'
return ((a>>>7)&0xff) == 1;
return negativeFlag;
}
/**
* @param register the register value to test for negativity
*/
public void setNegativeFlag(int register) {
this.negativeFlag = (((register>>>7)&0xff) == 1);
}
/**
* @param negativeFlag the negative flag to set
*/
public void setNegativeFlag(boolean negativeFlag) {
this.negativeFlag = negativeFlag;
}
/**
@ -668,6 +685,13 @@ public class Cpu implements InstructionTable {
return zeroFlag;
}
/**
* @param register the register to test for zero
*/
public void setZeroFlag(int register) {
this.zeroFlag = (register == 0);
}
/**
* @param zeroFlag the zero flag to set
*/
@ -731,6 +755,22 @@ public class Cpu implements InstructionTable {
this.overflowFlag = overflowFlag;
}
public int getAccumulator() {
return a;
}
public int getXRegister() {
return x;
}
public int getYRegister() {
return y;
}
public int getProgramCounter() {
return pc;
}
/**
* @return A string representing the current status register state.
*/
@ -751,12 +791,13 @@ public class Cpu implements InstructionTable {
*/
public String toString() {
String opcode = CpuUtils.opcode(ir, operands[0], operands[1]);
StringBuffer sb = new StringBuffer(String.format("$%04X", addr) + " ");
sb.append(String.format("%-12s", opcode));
sb.append("A=" + String.format("$%02X", a) + "; ");
sb.append("X=" + String.format("$%02X", x) + "; ");
sb.append("Y=" + String.format("$%02X", y) + "; ");
sb.append("PC=" + String.format("$%04X", pc)+ "; ");
StringBuffer sb = new StringBuffer(String.format("$%04X", addr) +
" ");
sb.append(String.format("%-14s", opcode));
sb.append("A=" + String.format("$%02X", a) + " ");
sb.append("X=" + String.format("$%02X", x) + " ");
sb.append("Y=" + String.format("$%02X", y) + " ");
sb.append("PC=" + String.format("$%04X", pc)+ " ");
sb.append("P=" + statusRegisterString());
return sb.toString();
}

View File

@ -20,7 +20,7 @@ public class CpuUtils {
*/
public static String opcode(int opcode, int op1, int op2) {
String opcodeName = Cpu.opcodeNames[opcode];
if (opcodeName == null) { return "??"; }
if (opcodeName == null) { return "???"; }
StringBuffer sb = new StringBuffer(opcodeName);

View File

@ -65,23 +65,30 @@ public class Simulator {
bus.write(0x0306, 0x1a);
bus.write(0x0307, 0xea); // NOP
bus.write(0x0308, 0xea); // NOP
bus.write(0x0309, 0xa2); // LDX #$03
bus.write(0x030a, 0x03);
bus.write(0x0309, 0xa2); // LDX #$90
bus.write(0x030a, 0x90);
bus.write(0x030b, 0xa9); // LDA #$00
bus.write(0x030c, 0x00);
bus.write(0x030d, 0xa2); // LDX #$00
bus.write(0x030e, 0x00);
bus.write(0x030f, 0xa0); // LDY #$00
bus.write(0x0310, 0x00);
bus.write(0x030b, 0xea); // NOP
bus.write(0x030c, 0xea); // NOP
bus.write(0x030d, 0xea); // NOP
bus.write(0x030e, 0xa2); // LDX #$02
bus.write(0x030f, 0x02);
bus.write(0x0310, 0xa9); // LDA #$00
bus.write(0x0311, 0x00);
bus.write(0x0312, 0xa2); // LDX #$00
bus.write(0x0313, 0x00);
bus.write(0x0314, 0xa0); // LDY #$00
bus.write(0x0315, 0x00);
bus.write(0x0311, 0x4c); // JMP #$0300
bus.write(0x0312, 0x00);
bus.write(0x0313, 0x03);
bus.write(0x0316, 0x4c); // JMP #$0300
bus.write(0x0317, 0x00);
bus.write(0x0318, 0x03);
cpu.reset();
for (int i = 0; i <= 23; i++) {
for (int i = 0; i <= 40; i++) {
cpu.step();
System.out.println(cpu.toString());
}

View File

@ -2,11 +2,18 @@ package com.loomcom.lm6502;
import junit.framework.*;
import com.loomcom.lm6502.devices.*;
import com.loomcom.lm6502.exceptions.*;
/**
*
*/
public class CpuTest extends TestCase {
private Cpu cpu;
private Bus bus;
private Memory mem;
public CpuTest(String testName) {
super(testName);
}
@ -14,10 +21,143 @@ public class CpuTest extends TestCase {
public static Test suite() {
return new TestSuite(CpuTest.class);
}
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(new Memory(0x0000, 0x10000));
public void testCpu() {
Cpu cpu = new Cpu();
assertNotNull(cpu);
// 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());
}
/* LDA Immediate Mode Tests - 0xa9 */
public void test_LDA_IMM_SetsAccumulator() {
bus.write(0x0200, 0xa9);
bus.write(0x0201, 0x12);
cpu.step();
assertEquals(0x12, cpu.getAccumulator());
}
public void test_LDA_IMM_SetsZeroFlagIfArgIsZero() {
bus.write(0x0200, 0xa9);
bus.write(0x0201, 0x00);
cpu.step();
assertTrue(cpu.getZeroFlag());
}
public void test_LDA_IMM_DoesNotSetZeroFlagIfArgNotZero() {
bus.write(0x0200, 0xa9);
bus.write(0x0201, 0x12);
cpu.step();
assertFalse(cpu.getZeroFlag());
}
public void test_LDA_IMM_SetsNegativeFlagIfArgIsNegative() {
bus.write(0x0200, 0xa9);
bus.write(0x0201, 0x80);
cpu.step();
assertTrue(cpu.getNegativeFlag());
}
public void test_LDA_IMM_DoesNotSetNegativeFlagIfArgNotNegative() {
bus.write(0x0200, 0xa9);
bus.write(0x0201, 0x7f);
cpu.step();
assertFalse(cpu.getNegativeFlag());
}
/* LDX Immediate Mode Tests - 0xa2 */
public void test_LDX_IMM_SetsXRegister() {
bus.write(0x0200, 0xa2);
bus.write(0x0201, 0x12);
cpu.step();
assertEquals(0x12, cpu.getXRegister());
}
public void test_LDX_IMM_SetsZeroFlagIfArgIsZero() {
bus.write(0x0200, 0xa2);
bus.write(0x0201, 0x00);
cpu.step();
assertTrue(cpu.getZeroFlag());
}
public void test_LDX_IMM_DoesNotSetZeroFlagIfArgNotZero() {
bus.write(0x0200, 0xa2);
bus.write(0x0201, 0x12);
cpu.step();
assertFalse(cpu.getZeroFlag());
}
public void test_LDX_IMM_SetsNegativeFlagIfArgIsNegative() {
bus.write(0x0200, 0xa2);
bus.write(0x0201, 0x80);
cpu.step();
assertTrue(cpu.getNegativeFlag());
}
public void test_LDX_IMM_DoesNotSetNegativeFlagIfArgNotNegative() {
bus.write(0x0200, 0xa2);
bus.write(0x0201, 0x7f);
cpu.step();
assertFalse(cpu.getNegativeFlag());
}
/* LDY Immediate Mode Tests - 0xa0 */
public void test_LDY_IMM_SetsYRegister() {
bus.write(0x0200, 0xa0);
bus.write(0x0201, 0x12);
cpu.step();
assertEquals(0x12, cpu.getYRegister());
}
public void test_LDY_IMM_SetsZeroFlagIfArgIsZero() {
bus.write(0x0200, 0xa0);
bus.write(0x0201, 0x00);
cpu.step();
assertTrue(cpu.getZeroFlag());
}
public void test_LDY_IMM_DoesNotSetZeroFlagIfArgNotZero() {
bus.write(0x0200, 0xa0);
bus.write(0x0201, 0x12);
cpu.step();
assertFalse(cpu.getZeroFlag());
}
public void test_LDY_IMM_SetsNegativeFlagIfArgIsNegative() {
bus.write(0x0200, 0xa0);
bus.write(0x0201, 0x80);
cpu.step();
assertTrue(cpu.getNegativeFlag());
}
public void test_LDY_IMM_DoesNotSetNegativeFlagIfArgNotNegative() {
bus.write(0x0200, 0xa0);
bus.write(0x0201, 0x7f);
cpu.step();
assertFalse(cpu.getNegativeFlag());
}
}