diff --git a/src/main/java/com/loomcom/symon/Cpu.java b/src/main/java/com/loomcom/symon/Cpu.java index 4d7c9fc..09cef71 100644 --- a/src/main/java/com/loomcom/symon/Cpu.java +++ b/src/main/java/com/loomcom/symon/Cpu.java @@ -121,7 +121,10 @@ public class Cpu implements InstructionTable { break; case 0x08: // n/a break; - case 0x09: // n/a + case 0x09: // ORA - Immediate + a |= operands[0]; + setZeroFlag(a); + setNegativeFlag(a); break; case 0x0a: // n/a break; @@ -188,6 +191,9 @@ public class Cpu implements InstructionTable { case 0x28: // n/a break; case 0x29: // n/a + a &= operands[0]; + setZeroFlag(a); + setNegativeFlag(a); break; case 0x2a: // n/a break; @@ -253,7 +259,10 @@ public class Cpu implements InstructionTable { break; case 0x48: // n/a break; - case 0x49: // n/a + case 0x49: // EOR - Immediate + a ^= operands[0]; + setZeroFlag(a); + setNegativeFlag(a); break; case 0x4a: // n/a break; diff --git a/src/main/java/com/loomcom/symon/Simulator.java b/src/main/java/com/loomcom/symon/Simulator.java index a23437f..65821dd 100644 --- a/src/main/java/com/loomcom/symon/Simulator.java +++ b/src/main/java/com/loomcom/symon/Simulator.java @@ -45,50 +45,55 @@ public class Simulator { public void write(int address, int value) { } - + + public void loadProgram(int address, int[] program) { + // Reset interrupt vector + int hi = (address&0xff00)>>>8; + int lo = address&0x00ff; + bus.write(0xfffc, lo); + bus.write(0xfffd, hi); + + int i = 0; + for (int d : program) { + bus.write(address + i, program[i++]); + } + } + /** * A test method. */ - + public void runTest() { - - // Start at 0x0300 - bus.write(0xfffc, 0x00); - bus.write(0xfffd, 0x03); - - bus.write(0x0300, 0xa9); // LDA #$FF - bus.write(0x0301, 0xff); - bus.write(0x0302, 0xea); // NOP - bus.write(0x0303, 0xea); // NOP - bus.write(0x0304, 0xea); // NOP - bus.write(0x0305, 0xa0); // LDY #$1A - bus.write(0x0306, 0x1a); - bus.write(0x0307, 0xea); // NOP - bus.write(0x0308, 0xea); // NOP - bus.write(0x0309, 0xa2); // LDX #$90 - bus.write(0x030a, 0x90); - - 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(0x0316, 0x4c); // JMP #$0300 - bus.write(0x0317, 0x00); - bus.write(0x0318, 0x03); + int[] program = { + 0xa9, // LDA #$FF + 0xff, + 0xa0, // LDY #$1A + 0x1a, + 0xa2, // LDX #$90 + 0x90, + 0xa2, // LDX #$02 + 0x02, + 0x49, // EOR #$FF + 0xff, + 0xa9, // LDA #$00 + 0x00, + 0xa2, // LDX #$00 + 0x00, + 0x29, // AND #$FF + 0xff, + 0xa0, // LDY #$00 + 0x00, + 0x4c, // JMP #$0300 + 0x00, + 0x03 + }; + loadProgram(0x0300, program); cpu.reset(); - for (int i = 0; i <= 40; i++) { + int steps = program.length; + + for (int i = 0; i <= steps; i++) { cpu.step(); System.out.println(cpu.toString()); } diff --git a/src/test/java/com/loomcom/symon/CpuImmediateModeTests.java b/src/test/java/com/loomcom/symon/CpuImmediateModeTests.java new file mode 100644 index 0000000..2849ac0 --- /dev/null +++ b/src/test/java/com/loomcom/symon/CpuImmediateModeTests.java @@ -0,0 +1,313 @@ +package com.loomcom.symon; + +import com.loomcom.symon.devices.Memory; +import com.loomcom.symon.exceptions.MemoryRangeException; + +import junit.framework.TestCase; + +public class CpuImmediateModeTests extends TestCase { + + private Cpu cpu; + private Bus bus; + private 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); + + // All test programs start at 0x0200; + bus.write(0xfffc, 0x00); + bus.write(0xfffd, 0x02); + + cpu.reset(); + } + + /* ORA Immediate Mode Tests - 0x09 */ + + public void test_ORA_SetsAccumulator() { + bus.write(0x0200, 0x09); // ORA #$00 + bus.write(0x0201, 0x00); + cpu.step(); + // 0x00 | 0x00 == 0x00 + assertEquals(0x00, cpu.getAccumulator()); + + bus.write(0x0202, 0x09); // ORA #$11 + bus.write(0x0203, 0x11); + cpu.step(); + // 0x00 | 0x11 == 0x11 + assertEquals(0x11, cpu.getAccumulator()); + + bus.write(0x0204, 0x09); // ORA #$22 + bus.write(0x0205, 0x22); + cpu.step(); + // 0x11 | 0x22 == 0x33 + assertEquals(0x33, cpu.getAccumulator()); + + bus.write(0x0206, 0x09); // ORA #$44 + bus.write(0x0207, 0x44); + cpu.step(); + // 0x33 | 0x44 == 0x77 + assertEquals(0x77, cpu.getAccumulator()); + + bus.write(0x0208, 0x09); // ORA #$88 + bus.write(0x0209, 0x88); + cpu.step(); + // 0x77 | 0x88 == 0xFF + assertEquals(0xff, cpu.getAccumulator()); + } + + public void test_ORA_SetsZeroFlagIfResultIsZero() { + bus.write(0x0200, 0x09); // ORA #$00 + bus.write(0x0201, 0x00); + cpu.step(); + assertTrue(cpu.getZeroFlag()); + } + + public void test_ORA_DoesNotSetZeroFlagIfResultNotZero() { + bus.write(0x0200, 0x09); // ORA #$01 + bus.write(0x0201, 0x01); + cpu.step(); + assertFalse(cpu.getZeroFlag()); + } + + public void test_ORA_SetsNegativeFlagIfResultIsNegative() { + bus.write(0x0200, 0x09); // ORA #$80 + bus.write(0x0201, 0x80); + cpu.step(); + assertTrue(cpu.getNegativeFlag()); + } + + public void test_ORA_DoesNotSetNegativeFlagIfResultNotNegative() { + bus.write(0x0200, 0x09); // ORA #$7F + bus.write(0x0201, 0x7f); + cpu.step(); + assertFalse(cpu.getNegativeFlag()); + } + + /* AND Immediate Mode Tests - 0x29 */ + + public void test_AND_SetsAccumulator() { + bus.write(0x0200, 0x29); // AND #$00 + bus.write(0x0201, 0x00); + cpu.step(); + // 0x00 & 0x00 == 0x00 + assertEquals(0x00, cpu.getAccumulator()); + + bus.write(0x0202, 0x29); // AND #$FF + bus.write(0x0203, 0x11); + cpu.step(); + // 0x00 & 0xff == 0x00 + assertEquals(0x00, cpu.getAccumulator()); + + // Load Accumulator with AA - %10101010 + + bus.write(0x0204, 0xa9); // LDA #$AA + bus.write(0x0205, 0xaa); + cpu.step(); + + bus.write(0x0206, 0x29); // AND #$FF + bus.write(0x0207, 0xff); + cpu.step(); + // 0xaa & 0xff == 0xaa + assertEquals(0xaa, cpu.getAccumulator()); + + bus.write(0x0208, 0x29); // AND #$99 + bus.write(0x0209, 0x99); + cpu.step(); + // 0xaa & 0x99 == 0x88 + + assertEquals(0x88, cpu.getAccumulator()); + bus.write(0x020a, 0x29); // AND #$99 + bus.write(0x020b, 0x11); + cpu.step(); + // 0x88 & 0x11 == 0x00 + assertEquals(0x00, cpu.getAccumulator()); + } + + public void test_AND_SetsZeroFlagIfResultIsZero() { + bus.write(0x0200, 0xa9); // LDA #$88 + bus.write(0x0201, 0x88); + cpu.step(); + bus.write(0x0202, 0x29); // AND #$11 + bus.write(0x0203, 0x11); + cpu.step(); + assertTrue(cpu.getZeroFlag()); + } + + public void test_AND_DoesNotSetZeroFlagIfResultNotZero() { + bus.write(0x0200, 0xa9); // LDA #$88 + bus.write(0x0201, 0x88); + cpu.step(); + bus.write(0x0202, 0x29); // AND #$f1 + bus.write(0x0203, 0xf1); + cpu.step(); + assertFalse(cpu.getZeroFlag()); + } + + public void test_AND_SetsNegativeFlagIfResultIsNegative() { + bus.write(0x0200, 0xa9); // LDA #$88 + bus.write(0x0201, 0x88); + cpu.step(); + bus.write(0x0202, 0x29); // AND #$F0 + bus.write(0x0203, 0xf0); + cpu.step(); + assertTrue(cpu.getNegativeFlag()); + } + + public void test_AND_DoesNotSetNegativeFlagIfResultNotNegative() { + bus.write(0x0200, 0xa9); // LDA #$88 + bus.write(0x0201, 0x88); + cpu.step(); + bus.write(0x0202, 0x29); // AND #$0F + bus.write(0x0203, 0x0f); + cpu.step(); + assertFalse(cpu.getNegativeFlag()); + } + + /* EOR Immediate Mode Tests - 0x49 */ + + public void test_EOR_SetsAccumulator() { + bus.write(0x0200, 0xa9); // LDA #$88 + bus.write(0x0201, 0x88); + cpu.step(); + + bus.write(0x0202, 0x49); // EOR #$00 + bus.write(0x0203, 0x00); + cpu.step(); + assertEquals(0x88, cpu.getAccumulator()); + + bus.write(0x0204, 0x49); // EOR #$ff + bus.write(0x0205, 0xff); + cpu.step(); + assertEquals(0x77, cpu.getAccumulator()); + + bus.write(0x0206, 0x49); // EOR #$33 + bus.write(0x0207, 0x33); + cpu.step(); + assertEquals(0x44, cpu.getAccumulator()); + } + + /* ADC Immediate Mode Tests - 0x69 */ + + /* LDY Immediate Mode Tests - 0xa0 */ + + public void test_LDY_SetsYRegister() { + bus.write(0x0200, 0xa0); + bus.write(0x0201, 0x12); + cpu.step(); + assertEquals(0x12, cpu.getYRegister()); + } + + public void test_LDY_SetsZeroFlagIfArgIsZero() { + bus.write(0x0200, 0xa0); + bus.write(0x0201, 0x00); + cpu.step(); + assertTrue(cpu.getZeroFlag()); + } + + public void test_LDY_DoesNotSetZeroFlagIfResultNotZero() { + bus.write(0x0200, 0xa0); + bus.write(0x0201, 0x12); + cpu.step(); + assertFalse(cpu.getZeroFlag()); + } + + public void test_LDY_SetsNegativeFlagIfResultIsNegative() { + bus.write(0x0200, 0xa0); + bus.write(0x0201, 0x80); + cpu.step(); + assertTrue(cpu.getNegativeFlag()); + } + + public void test_LDY_DoesNotSetNegativeFlagIfResultNotNegative() { + bus.write(0x0200, 0xa0); + bus.write(0x0201, 0x7f); + cpu.step(); + assertFalse(cpu.getNegativeFlag()); + } + + /* LDX Immediate Mode Tests - 0xa2 */ + + public void test_LDX_SetsXRegister() { + bus.write(0x0200, 0xa2); + bus.write(0x0201, 0x12); + cpu.step(); + assertEquals(0x12, cpu.getXRegister()); + } + + public void test_LDX_SetsZeroFlagIfResultIsZero() { + bus.write(0x0200, 0xa2); + bus.write(0x0201, 0x00); + cpu.step(); + assertTrue(cpu.getZeroFlag()); + } + + public void test_LDX_DoesNotSetZeroFlagIfResultNotZero() { + bus.write(0x0200, 0xa2); + bus.write(0x0201, 0x12); + cpu.step(); + assertFalse(cpu.getZeroFlag()); + } + + public void test_LDX_SetsNegativeFlagIfResultIsNegative() { + bus.write(0x0200, 0xa2); + bus.write(0x0201, 0x80); + cpu.step(); + assertTrue(cpu.getNegativeFlag()); + } + + public void test_LDX_DoesNotSetNegativeFlagIfResultNotNegative() { + bus.write(0x0200, 0xa2); + bus.write(0x0201, 0x7f); + cpu.step(); + assertFalse(cpu.getNegativeFlag()); + } + + /* LDA Immediate Mode Tests - 0xa9 */ + + public void test_LDA_SetsAccumulator() { + bus.write(0x0200, 0xa9); + bus.write(0x0201, 0x12); + cpu.step(); + assertEquals(0x12, cpu.getAccumulator()); + } + + public void test_LDA_SetsZeroFlagIfResultIsZero() { + bus.write(0x0200, 0xa9); + bus.write(0x0201, 0x00); + cpu.step(); + assertTrue(cpu.getZeroFlag()); + } + + public void test_LDA_DoesNotSetZeroFlagIfResultNotZero() { + bus.write(0x0200, 0xa9); + bus.write(0x0201, 0x12); + cpu.step(); + assertFalse(cpu.getZeroFlag()); + } + + public void test_LDA_SetsNegativeFlagIfResultIsNegative() { + bus.write(0x0200, 0xa9); + bus.write(0x0201, 0x80); + cpu.step(); + assertTrue(cpu.getNegativeFlag()); + } + + public void test_LDA_DoesNotSetNegativeFlagIfResultNotNegative() { + bus.write(0x0200, 0xa9); + bus.write(0x0201, 0x7f); + cpu.step(); + assertFalse(cpu.getNegativeFlag()); + } + + /* CPY Immediate Mode Tests - 0xc0 */ + + /* CMP Immediate Mode Tests - 0xc9 */ + + /* CPX Immediate Mode Tests - 0xe0 */ + + /* SBC Immediate Mode Tests - 0xe9 */ +} diff --git a/src/test/java/com/loomcom/symon/CpuTest.java b/src/test/java/com/loomcom/symon/CpuTest.java index c3e2219..763f72f 100644 --- a/src/test/java/com/loomcom/symon/CpuTest.java +++ b/src/test/java/com/loomcom/symon/CpuTest.java @@ -9,7 +9,7 @@ import com.loomcom.symon.exceptions.*; * */ public class CpuTest extends TestCase { - + private Cpu cpu; private Bus bus; private Memory mem; @@ -27,7 +27,7 @@ public class CpuTest extends TestCase { this.bus = new Bus(0x0000, 0xffff); this.mem = new Memory(0x0000, 0x10000); bus.addCpu(cpu); - bus.addDevice(new Memory(0x0000, 0x10000)); + bus.addDevice(mem); // All test programs start at 0x0200; bus.write(0xfffc, 0x00); @@ -49,115 +49,4 @@ public class CpuTest extends TestCase { 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()); - } } \ No newline at end of file