From f012ba7775ea8050f5507a069f660075aa9307d1 Mon Sep 17 00:00:00 2001 From: "Seth J. Morabito" Date: Tue, 23 Dec 2008 16:06:09 -0800 Subject: [PATCH] More implied mode instructions implemented, with tests. --- src/main/java/com/loomcom/symon/Cpu.java | 47 ++- .../com/loomcom/symon/CpuImpliedModeTest.java | 292 ++++++++++++++++++ 2 files changed, 327 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/loomcom/symon/Cpu.java b/src/main/java/com/loomcom/symon/Cpu.java index 3ffac94..2707e70 100644 --- a/src/main/java/com/loomcom/symon/Cpu.java +++ b/src/main/java/com/loomcom/symon/Cpu.java @@ -96,6 +96,8 @@ public class Cpu implements InstructionTable { * Performs an individual machine cycle. */ public void step() { + int lo, hi; // Used in address calculation + // Store the address from which the IR was read, for debugging addr = pc; @@ -143,7 +145,8 @@ public class Cpu implements InstructionTable { break; case 0x07: // n/a break; - case 0x08: // n/a + case 0x08: // PHP - Push Processor Status - Implied + stackPush(getProcessorStatus()); break; case 0x09: // ORA - Immediate a |= operands[0]; @@ -212,7 +215,8 @@ public class Cpu implements InstructionTable { break; case 0x27: // n/a break; - case 0x28: // n/a + case 0x28: // PLP - Pull Processor Status - Implied + setProcessorStatus(stackPop()); break; case 0x29: // n/a a &= operands[0]; @@ -265,7 +269,11 @@ public class Cpu implements InstructionTable { case 0x3f: // n/a break; - case 0x40: // n/a + case 0x40: // RTI - Return from Interrupt - Implied + setProcessorStatus(stackPop()); + lo = stackPop(); + hi = stackPop(); + setProgramCounter(CpuUtils.address(lo, hi)); break; case 0x41: // n/a break; @@ -281,7 +289,8 @@ public class Cpu implements InstructionTable { break; case 0x47: // n/a break; - case 0x48: // n/a + case 0x48: // PHA - Push Accumulator - Implied + stackPush(a); break; case 0x49: // EOR - Immediate a ^= operands[0]; @@ -317,7 +326,7 @@ public class Cpu implements InstructionTable { break; case 0x57: // n/a break; - case 0x58: // CLI - Clear Interrupt Disable, Implied + case 0x58: // CLI - Clear Interrupt Disable - Implied clearIrqDisableFlag(); break; case 0x59: // n/a @@ -335,7 +344,11 @@ public class Cpu implements InstructionTable { case 0x5f: // n/a break; - case 0x60: // n/a + case 0x60: // RTS - Return from Subrouting - Implied + lo = stackPop(); + hi = stackPop(); + setProgramCounter((CpuUtils.address(lo, hi) - 1) & 0xffff); + break; case 0x61: // n/a break; @@ -351,7 +364,9 @@ public class Cpu implements InstructionTable { break; case 0x67: // n/a break; - case 0x68: // n/a + case 0x68: // PLA - Pull Accumulator - Implied + a = stackPop(); + setArithmeticFlags(a); break; case 0x69: // ADC - Immediate Mode a = adc(a, operands[0]); @@ -420,7 +435,9 @@ public class Cpu implements InstructionTable { break; case 0x87: // n/a break; - case 0x88: // n/a + case 0x88: // DEY - Decrement the Y Register - Implied + y = --y & 0xff; + setArithmeticFlags(y); break; case 0x89: // n/a break; @@ -560,12 +577,16 @@ public class Cpu implements InstructionTable { break; case 0xc7: // n/a break; - case 0xc8: // n/a + case 0xc8: // INY - Increment the Y Register - Implied + y = ++y & 0xff; + setArithmeticFlags(y); break; case 0xc9: // CMP - Immediate cmp(a, operands[0]); break; - case 0xca: // n/a + case 0xca: // DEX - Decrement the X Register - Implied + x = --x & 0xff; + setArithmeticFlags(x); break; case 0xcb: // n/a break; @@ -629,9 +650,11 @@ public class Cpu implements InstructionTable { break; case 0xe7: // n/a break; - case 0xe8: // n/a + case 0xe8: // INX - Increment X Register - Implied + x = ++x & 0xff; + setArithmeticFlags(x); break; - case 0xe9: // n/a + case 0xe9: // SBC - Subtract with Carry (Borrow) - Immediate a = sbc(a, operands[0]); setArithmeticFlags(a); break; diff --git a/src/test/java/com/loomcom/symon/CpuImpliedModeTest.java b/src/test/java/com/loomcom/symon/CpuImpliedModeTest.java index 094ba90..e6076b9 100644 --- a/src/test/java/com/loomcom/symon/CpuImpliedModeTest.java +++ b/src/test/java/com/loomcom/symon/CpuImpliedModeTest.java @@ -22,6 +22,14 @@ public class CpuImpliedModeTest extends TestCase { bus.write(0xfffd, (Cpu.DEFAULT_BASE_ADDRESS & 0xff00)>>>8); cpu.reset(); + + // Assert initial state + assertEquals(0, cpu.getAccumulator()); + assertEquals(0, cpu.getXRegister()); + assertEquals(0, cpu.getYRegister()); + assertEquals(0x200, cpu.getProgramCounter()); + assertEquals(0xff, cpu.getStackPointer()); + assertEquals(0x20, cpu.getProcessorStatus()); } /* @@ -127,4 +135,288 @@ public class CpuImpliedModeTest extends TestCase { assertEquals(0xff, cpu.getStackPointer()); } + /* CLC - Clear Carry Flag - $18 */ + public void test_CLC() { + cpu.setCarryFlag(); + assertTrue(cpu.getCarryFlag()); + + bus.loadProgram(0x18); + cpu.step(); + + assertFalse(cpu.getCarryFlag()); + } + + /* CLD - Clear Decimal Mode Flag - $d8 */ + public void test_CLD() { + cpu.setDecimalModeFlag(); + assertTrue(cpu.getDecimalModeFlag()); + + bus.loadProgram(0xd8); + cpu.step(); + + assertFalse(cpu.getDecimalModeFlag()); + } + + /* CLI - Clear Interrupt Disabled Flag - $58 */ + public void test_CLI() { + cpu.setIrqDisableFlag(); + assertTrue(cpu.getIrqDisableFlag()); + + bus.loadProgram(0x58); + cpu.step(); + + assertFalse(cpu.getIrqDisableFlag()); + } + + /* CLV - Clear Overflow Flag - $b8 */ + public void test_CLV() { + cpu.setOverflowFlag(); + assertTrue(cpu.getOverflowFlag()); + + bus.loadProgram(0xb8); + cpu.step(); + + assertFalse(cpu.getOverflowFlag()); + } + + /* DEX - Decrement the X register - $ca */ + + public void test_DEX() { + bus.loadProgram(0xca); + cpu.setXRegister(0x02); + cpu.step(); + assertEquals(0x01, cpu.getXRegister()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_DEX_SetsZeroFlagWhenZero() { + bus.loadProgram(0xca); + cpu.setXRegister(0x01); + cpu.step(); + assertEquals(0x00, cpu.getXRegister()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_DEX_SetsNegativeFlagWhen() { + bus.loadProgram(0xca); + cpu.step(); + assertEquals(0xff, cpu.getXRegister()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* DEY - Decrement the Y register - $88 */ + + public void test_DEY() { + bus.loadProgram(0x88); + cpu.setYRegister(0x02); + cpu.step(); + assertEquals(0x01, cpu.getYRegister()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_DEY_SetsZeroFlagWhenZero() { + bus.loadProgram(0x88); + cpu.setYRegister(0x01); + cpu.step(); + assertEquals(0x00, cpu.getYRegister()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_DEY_SetsNegativeFlagWhen() { + bus.loadProgram(0x88); + cpu.step(); + assertEquals(0xff, cpu.getYRegister()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + /* INX - Increment the X register - $e8 */ + + public void test_INX() { + bus.loadProgram(0xe8); + cpu.step(); + assertEquals(0x01, cpu.getXRegister()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_INX_SetsNegativeFlagWhenNegative() { + bus.loadProgram(0xe8); + cpu.setXRegister(0x7f); + cpu.step(); + assertEquals(0x80, cpu.getXRegister()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + public void test_INX_SetsZeroFlagWhenZero() { + bus.loadProgram(0xe8); + cpu.setXRegister(0xff); + cpu.step(); + assertEquals(0x00, cpu.getXRegister()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + /* INY - Increment the Y register - $c8 */ + + public void test_INY() { + bus.loadProgram(0xc8); + cpu.step(); + assertEquals(0x01, cpu.getYRegister()); + assertFalse(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + public void test_INY_SetsNegativeFlagWhenNegative() { + bus.loadProgram(0xc8); + cpu.setYRegister(0x7f); + cpu.step(); + assertEquals(0x80, cpu.getYRegister()); + assertFalse(cpu.getZeroFlag()); + assertTrue(cpu.getNegativeFlag()); + } + + public void test_INY_SetsZeroFlagWhenZero() { + bus.loadProgram(0xc8); + cpu.setYRegister(0xff); + cpu.step(); + assertEquals(0x00, cpu.getYRegister()); + assertTrue(cpu.getZeroFlag()); + assertFalse(cpu.getNegativeFlag()); + } + + /* NOP - No Operation - $ea */ + + public void test_NOP() { + bus.loadProgram(0xea); + cpu.step(); + // Should just not change anything except PC + assertEquals(0, cpu.getAccumulator()); + assertEquals(0, cpu.getXRegister()); + assertEquals(0, cpu.getYRegister()); + assertEquals(0x201, cpu.getProgramCounter()); + assertEquals(0xff, cpu.getStackPointer()); + assertEquals(0x20, cpu.getProcessorStatus()); + } + + /* PHA - Push Accumulator - $48 */ + + public void test_PHA() { + bus.loadProgram(0x48); + cpu.setAccumulator(0x3a); + cpu.step(); + assertEquals(0xfe, cpu.getStackPointer()); + assertEquals(0x3a, cpu.stackPeek()); + } + + /* PHP - Push Processor Status - $08 */ + + public void test_PHP() { + bus.loadProgram(0x08); + cpu.setProcessorStatus(0x27); + cpu.step(); + assertEquals(0xfe, cpu.getStackPointer()); + assertEquals(0x27, cpu.stackPeek()); + } + + /* PLA - Pul Accumulator - $68 */ + + public void test_PLA() { + cpu.stackPush(0x32); + bus.loadProgram(0x68); + cpu.step(); + assertEquals(0x32, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertFalse(cpu.getZeroFlag()); + } + + public void test_PLA_SetsZeroIfAccumulatorIsZero() { + cpu.stackPush(0x00); + bus.loadProgram(0x68); + cpu.step(); + assertEquals(0x00, cpu.getAccumulator()); + assertFalse(cpu.getNegativeFlag()); + assertTrue(cpu.getZeroFlag()); + } + + public void test_PLA_SetsNegativeIfAccumulatorIsNegative() { + cpu.stackPush(0xff); + bus.loadProgram(0x68); + cpu.step(); + assertEquals(0xff, cpu.getAccumulator()); + assertTrue(cpu.getNegativeFlag()); + assertFalse(cpu.getZeroFlag()); + } + + /* PLP - Pull Processor Status - $28 */ + + public void test_PLP() { + cpu.stackPush(0x2f); + bus.loadProgram(0x28); + cpu.step(); + assertEquals(0x2f, cpu.getProcessorStatus()); + } + + /* RTI - Return from Interrupt - $40 */ + + public void test_RTI() { + cpu.stackPush(0x0f); // PC hi + cpu.stackPush(0x11); // PC lo + cpu.stackPush(0x29); // status + + bus.loadProgram(0x40); + cpu.step(); + + assertEquals(0x0f11, cpu.getProgramCounter()); + assertEquals(0x29, cpu.getProcessorStatus()); + } + + /* RTS - Return from Subroutine - $60 */ + + public void test_RTS() { + cpu.stackPush(0x0f); // PC hi + cpu.stackPush(0x11); // PC lo + + bus.loadProgram(0x60); + cpu.step(); + + assertEquals(0x0f10, cpu.getProgramCounter()); + assertEquals(0x20, cpu.getProcessorStatus()); + } + + /* SEC - Set Carry Flag - $38 */ + + public void test_SEC() { + bus.loadProgram(0x38); + cpu.step(); + assertTrue(cpu.getCarryFlag()); + } + + /* SED - Set Decimal Mode Flag - $f8 */ + + public void test_SED() { + bus.loadProgram(0xf8); + cpu.step(); + assertTrue(cpu.getDecimalModeFlag()); + } + + /* SEI - Set Interrupt Disable Flag - $78 */ + + public void test_SEI() { + bus.loadProgram(0x78); + cpu.step(); + assertTrue(cpu.getIrqDisableFlag()); + } + + /* TAX - - $aa */ + + public void test_TAX() { + } + } \ No newline at end of file