package com.loomcom.symon; import com.loomcom.symon.devices.Memory; import com.loomcom.symon.exceptions.*; import junit.framework.*; public class CpuImmediateModeTest extends TestCase { protected Cpu cpu; protected Bus bus; protected Memory mem; public void setUp() throws MemoryRangeException, MemoryAccessException { this.cpu = new Cpu(); this.bus = new Bus(0x0000, 0xffff); this.mem = new Memory(0x0000, 0xffff); bus.addCpu(cpu); bus.addDevice(mem); // Load the reset vector. bus.write(0xfffc, Bus.DEFAULT_LOAD_ADDRESS & 0x00ff); bus.write(0xfffd, (Bus.DEFAULT_LOAD_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(0x24, cpu.getProcessorStatus()); } /* * The following opcodes are tested for correctness in this file: * * ORA - $09 * AND - $29 * EOR - $49 * ADC - $69 * LDY - $a0 * * LDX - $a2 * LDA - $a9 * CPY - $c0 * CMP - $c9 * CPX - $e0 * * SBC - $e9 */ /* ORA Immediate Mode Tests - 0x09 */ public void test_ORA() throws MemoryAccessException { bus.loadProgram(0x09, 0x00, // ORA #$00 0x09, 0x11, // ORA #$11 0x09, 0x22, // ORA #$22 0x09, 0x44, // ORA #$44 0x09, 0x88); // ORA #$88 cpu.step(); assertEquals(0x00, cpu.getAccumulator()); cpu.step(); assertEquals(0x11, cpu.getAccumulator()); cpu.step(); assertEquals(0x33, cpu.getAccumulator()); cpu.step(); assertEquals(0x77, cpu.getAccumulator()); cpu.step(); assertEquals(0xff, cpu.getAccumulator()); } public void test_ORA_SetsZeroFlagIfResultIsZero() throws MemoryAccessException { bus.loadProgram(0x09, 0x00); // ORA #$00 cpu.step(); assertTrue(cpu.getZeroFlag()); } public void test_ORA_DoesNotSetZeroFlagIfResultNotZero() throws MemoryAccessException { bus.loadProgram(0x09, 0x01); // ORA #$01 cpu.step(); assertFalse(cpu.getZeroFlag()); } public void test_ORA_SetsNegativeFlagIfResultIsNegative() throws MemoryAccessException { bus.loadProgram(0x09, 0x80); // ORA #$80 cpu.step(); assertTrue(cpu.getNegativeFlag()); } public void test_ORA_DoesNotSetNegativeFlagIfResultNotNegative() throws MemoryAccessException { bus.loadProgram(0x09, 0x7f); // ORA #$7F cpu.step(); assertFalse(cpu.getNegativeFlag()); } /* AND Immediate Mode Tests - 0x29 */ public void test_AND() throws MemoryAccessException { bus.loadProgram(0x29, 0x00, // AND #$00 0x29, 0x11, // AND #$11 0xa9, 0xaa, // LDA #$AA 0x29, 0xff, // AND #$FF 0x29, 0x99, // AND #$99 0x29, 0x11); // AND #$11 cpu.step(); assertEquals(0x00, cpu.getAccumulator()); cpu.step(); assertEquals(0x00, cpu.getAccumulator()); cpu.step(2); assertEquals(0xaa, cpu.getAccumulator()); cpu.step(); assertEquals(0x88, cpu.getAccumulator()); cpu.step(); assertEquals(0x00, cpu.getAccumulator()); } public void test_AND_SetsZeroFlagIfResultIsZero() throws MemoryAccessException { bus.loadProgram(0xa9, 0x88, // LDA #$88 0x29, 0x11); // AND #$11 cpu.step(2); assertTrue(cpu.getZeroFlag()); } public void test_AND_DoesNotSetZeroFlagIfResultNotZero() throws MemoryAccessException { bus.loadProgram(0xa9, 0x88, // LDA #$88 0x29, 0xf1); // AND #$F1 cpu.step(2); assertFalse(cpu.getZeroFlag()); } public void test_AND_SetsNegativeFlagIfResultIsNegative() throws MemoryAccessException { bus.loadProgram(0xa9, 0x88, // LDA #$88 0x29, 0xf0); // AND #$F0 cpu.step(2); assertTrue(cpu.getNegativeFlag()); } public void test_AND_DoesNotSetNegativeFlagIfResultNotNegative() throws MemoryAccessException { bus.loadProgram(0xa9, 0x88, // LDA #$88 0x29, 0x0f); // AND #$0F cpu.step(2); assertFalse(cpu.getNegativeFlag()); } /* EOR Immediate Mode Tests - 0x49 */ public void test_EOR() throws MemoryAccessException { bus.loadProgram(0xa9, 0x88, // LDA #$88 0x49, 0x00, // EOR #$00 0x49, 0xff, // EOR #$ff 0x49, 0x33); // EOR #$33 cpu.step(2); assertEquals(0x88, cpu.getAccumulator()); cpu.step(); assertEquals(0x77, cpu.getAccumulator()); cpu.step(); assertEquals(0x44, cpu.getAccumulator()); } public void test_EOR_SetsArithmeticFlags() throws MemoryAccessException { bus.loadProgram(0xa9, 0x77, // LDA #$77 0x49, 0x77, // EOR #$77 0x49, 0xff); // EOR #$ff cpu.step(2); assertEquals(0x00, cpu.getAccumulator()); assertTrue(cpu.getZeroFlag()); assertFalse(cpu.getNegativeFlag()); cpu.step(); assertEquals(0xff, cpu.getAccumulator()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getNegativeFlag()); } /* ADC Immediate Mode Tests - 0x69 */ public void test_ADC() throws MemoryAccessException { bus.loadProgram(0xa9, 0x00, // LDA #$00 0x69, 0x01); // ADC #$01 cpu.step(2); assertEquals(0x01, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertFalse(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xa9, 0x7f, // LDA #$7f 0x69, 0x01); // ADC #$01 cpu.step(2); assertEquals(0x80, cpu.getAccumulator()); assertTrue(cpu.getNegativeFlag()); assertTrue(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertFalse(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xa9, 0x80, // LDA #$80 0x69, 0x01); // ADC #$01 cpu.step(2); assertEquals(0x81, cpu.getAccumulator()); assertTrue(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertFalse(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xa9, 0xff, // LDA #$ff 0x69, 0x01); // ADC #$01 cpu.step(2); assertEquals(0x00, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertTrue(cpu.getZeroFlag()); assertTrue(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xa9, 0x00, // LDA #$00 0x69, 0xff); // ADC #$ff cpu.step(2); assertEquals(0xff, cpu.getAccumulator()); assertTrue(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertFalse(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xa9, 0x7f, // LDA #$7f 0x69, 0xff); // ADC #$ff cpu.step(2); assertEquals(0x7e, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xa9, 0x80, // LDA #$80 0x69, 0xff); // ADC #$ff cpu.step(2); assertEquals(0x7f, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertTrue(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xa9, 0xff, // LDA #$ff 0x69, 0xff); // ADC #$ff cpu.step(2); assertEquals(0xfe, cpu.getAccumulator()); assertTrue(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getCarryFlag()); } public void test_ADC_IncludesCarry() throws MemoryAccessException { bus.loadProgram(0xa9, 0x00, // LDA #$01 0x38, // SEC 0x69, 0x01); // ADC #$01 cpu.step(3); assertEquals(0x02, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertFalse(cpu.getCarryFlag()); } public void test_ADC_DecimalMode() throws MemoryAccessException { bus.loadProgram(0xf8, // SED 0xa9, 0x01, // LDA #$01 0x69, 0x01); // ADC #$01 cpu.step(3); assertEquals(0x02, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertFalse(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xf8, // SED 0xa9, 0x49, // LDA #$49 0x69, 0x01); // ADC #$01 cpu.step(3); assertEquals(0x50, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertFalse(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xf8, // SED 0xa9, 0x50, // LDA #$50 0x69, 0x01); // ADC #$01 cpu.step(3); assertEquals(0x51, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertFalse(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xf8, // SED 0xa9, 0x99, // LDA #$99 0x69, 0x01); // ADC #$01 cpu.step(3); assertEquals(0x00, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertTrue(cpu.getZeroFlag()); assertTrue(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xf8, // SED 0xa9, 0x00, // LDA #$00 0x69, 0x99); // ADC #$01 cpu.step(3); assertEquals(0x99, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertFalse(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xf8, // SED 0xa9, 0x49, // LDA #$49 0x69, 0x99); // ADC #$99 cpu.step(3); assertEquals(0x48, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xf8, // SED 0xa9, 0x50, // LDA #$59 0x69, 0x99); // ADC #$99 cpu.step(3); assertEquals(0x49, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getCarryFlag()); } /* LDY Immediate Mode Tests - 0xa0 */ public void test_LDY_SetsYRegister() throws MemoryAccessException { bus.loadProgram(0xa0, 0x12); // LDY #$12 cpu.step(); assertEquals(0x12, cpu.getYRegister()); } public void test_LDY_SetsZeroFlagIfArgIsZero() throws MemoryAccessException { bus.loadProgram(0xa0, 0x00); // LDY #$00 cpu.step(); assertTrue(cpu.getZeroFlag()); } public void test_LDY_DoesNotSetZeroFlagIfResultNotZero() throws MemoryAccessException { bus.loadProgram(0xa0, 0x12); // LDY #$12 cpu.step(); assertFalse(cpu.getZeroFlag()); } public void test_LDY_SetsNegativeFlagIfResultIsNegative() throws MemoryAccessException { bus.loadProgram(0xa0, 0x80); // LDY #$80 cpu.step(); assertTrue(cpu.getNegativeFlag()); } public void test_LDY_DoesNotSetNegativeFlagIfResultNotNegative() throws MemoryAccessException { bus.loadProgram(0xa0, 0x7f); // LDY #$7F cpu.step(); assertFalse(cpu.getNegativeFlag()); } /* LDX Immediate Mode Tests - 0xa2 */ public void test_LDX_SetsXRegister() throws MemoryAccessException { bus.loadProgram(0xa2, 0x12); // LDX #$12 cpu.step(); assertEquals(0x12, cpu.getXRegister()); } public void test_LDX_SetsZeroFlagIfResultIsZero() throws MemoryAccessException { bus.loadProgram(0xa2, 0x00); // LDX #$00 cpu.step(); assertTrue(cpu.getZeroFlag()); } public void test_LDX_DoesNotSetZeroFlagIfResultNotZero() throws MemoryAccessException { bus.loadProgram(0xa2, 0x12); // LDX #$12 cpu.step(); assertFalse(cpu.getZeroFlag()); } public void test_LDX_SetsNegativeFlagIfResultIsNegative() throws MemoryAccessException { bus.loadProgram(0xa2, 0x80); // LDX #$80 cpu.step(); assertTrue(cpu.getNegativeFlag()); } public void test_LDX_DoesNotSetNegativeFlagIfResultNotNegative() throws MemoryAccessException { bus.loadProgram(0xa2, 0x7f); // LDX #$7F cpu.step(); assertFalse(cpu.getNegativeFlag()); } /* LDA Immediate Mode Tests - 0xa9 */ public void test_LDA_SetsAccumulator() throws MemoryAccessException { bus.loadProgram(0xa9, 0x12); // LDA #$12 cpu.step(); assertEquals(0x12, cpu.getAccumulator()); } public void test_LDA_SetsZeroFlagIfResultIsZero() throws MemoryAccessException { bus.loadProgram(0xa9, 0x00); // LDA #$00 cpu.step(); assertTrue(cpu.getZeroFlag()); } public void test_LDA_DoesNotSetZeroFlagIfResultNotZero() throws MemoryAccessException { bus.loadProgram(0xa9, 0x12); // LDA #$12 cpu.step(); assertFalse(cpu.getZeroFlag()); } public void test_LDA_SetsNegativeFlagIfResultIsNegative() throws MemoryAccessException { bus.loadProgram(0xa9, 0x80); // LDA #$80 cpu.step(); assertTrue(cpu.getNegativeFlag()); } public void test_LDA_DoesNotSetNegativeFlagIfResultNotNegative() throws MemoryAccessException { bus.loadProgram(0xa9, 0x7f); // LDA #$7F cpu.step(); assertFalse(cpu.getNegativeFlag()); } /* CPY Immediate Mode Tests - 0xc0 */ public void test_CPY_SetsZeroAndCarryFlagsIfNumbersSame() throws MemoryAccessException { bus.loadProgram(0xa0, 0x00, // LDY #$00 0xc0, 0x00); // CPY #$00 cpu.step(2); assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getZeroFlag()); assertFalse(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa0, 0x01, // LDY #$01 0xc0, 0x01); // CPY #$01 cpu.step(2); assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getZeroFlag()); assertFalse(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa0, 0x7f, // LDY #$7F 0xc0, 0x7f); // CPY #$7F cpu.step(2); assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getZeroFlag()); assertFalse(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa0, 0xFF, // LDY #$FF 0xc0, 0xFF); // CPY #$FF cpu.step(2); assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getZeroFlag()); assertFalse(cpu.getNegativeFlag()); } public void test_CPY_SetsCarryFlagIfYGreaterThanMemory() throws MemoryAccessException { bus.loadProgram(0xa0, 0x0a, // LDY #$0A 0xc0, 0x08); // CPY #$08 cpu.step(2); assertTrue(cpu.getCarryFlag()); assertFalse(cpu.getZeroFlag()); // $0a - $08 = positive assertFalse(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa0, 0xfa, // LDY #$FA 0xc0, 0x80); // CPY #$80 cpu.step(2); assertTrue(cpu.getCarryFlag()); assertFalse(cpu.getZeroFlag()); // $fa - 80 = positive assertFalse(cpu.getNegativeFlag()); } public void test_CPY_DoesNotSetCarryFlagIfYLessThanThanMemory() throws MemoryAccessException { bus.loadProgram(0xa0, 0x08, // LDY #$08 0xc0, 0x0a); // CPY #$0A cpu.step(2); assertFalse(cpu.getCarryFlag()); assertFalse(cpu.getZeroFlag()); // 08 - 0a = negative assertTrue(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa0, 0x70, // LDY #$70 0xc0, 0x80); // CPY #$80 cpu.step(2); assertFalse(cpu.getCarryFlag()); assertFalse(cpu.getZeroFlag()); // $70 - $80 = negative assertTrue(cpu.getNegativeFlag()); } /* CMP Immediate Mode Tests - 0xc9 */ public void test_CMP_SetsZeroAndCarryFlagsIfNumbersSame() throws MemoryAccessException { bus.loadProgram(0xa9, 0x00, // LDA #$00 0xc9, 0x00); // CMP #$00 cpu.step(2); assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getZeroFlag()); assertFalse(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa9, 0x01, // LDA #$01 0xc9, 0x01); // CMP #$01 cpu.step(2); assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getZeroFlag()); assertFalse(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa9, 0x7f, // LDA #$7F 0xc9, 0x7f); // CMP #$7F cpu.step(2); assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getZeroFlag()); assertFalse(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa9, 0xFF, // LDA #$FF 0xc9, 0xFF); // CMP #$FF cpu.step(2); assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getZeroFlag()); assertFalse(cpu.getNegativeFlag()); } public void test_CMP_SetsCarryFlagIfYGreaterThanMemory() throws MemoryAccessException { bus.loadProgram(0xa9, 0x0a, // LDA #$0A 0xc9, 0x08); // CMP #$08 cpu.step(2); assertTrue(cpu.getCarryFlag()); assertFalse(cpu.getZeroFlag()); // $0a - $08 = positive assertFalse(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa9, 0xfa, // LDA #$FA 0xc9, 0x80); // CMP #$80 cpu.step(2); assertTrue(cpu.getCarryFlag()); assertFalse(cpu.getZeroFlag()); // $fa - $80 = positive assertFalse(cpu.getNegativeFlag()); } public void test_CMP_DoesNotSetCarryFlagIfYGreaterThanMemory() throws MemoryAccessException { bus.loadProgram(0xa9, 0x08, // LDA #$08 0xc9, 0x0a); // CMP #$0A cpu.step(2); assertFalse(cpu.getCarryFlag()); assertFalse(cpu.getZeroFlag()); // 08 - 0a = negative assertTrue(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa9, 0x70, // LDA #$70 0xc9, 0x80); // CMP #$80 cpu.step(2); assertFalse(cpu.getCarryFlag()); assertFalse(cpu.getZeroFlag()); // 70 - 80 = negative assertTrue(cpu.getNegativeFlag()); } /* CPX Immediate Mode Tests - 0xe0 */ public void test_CPX_SetsZeroAndCarryFlagsIfNumbersSame() throws MemoryAccessException { bus.loadProgram(0xa2, 0x00, // LDX #$00 0xe0, 0x00); // CPX #$00 cpu.step(2); assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getZeroFlag()); assertFalse(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa2, 0x01, // LDX #$01 0xe0, 0x01); // CPX #$01 cpu.step(2); assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getZeroFlag()); assertFalse(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa2, 0x7f, // LDX #$7F 0xe0, 0x7f); // CPX #$7F cpu.step(2); assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getZeroFlag()); assertFalse(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa2, 0xFF, // LDX #$FF 0xe0, 0xFF); // CPX #$FF cpu.step(2); assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getZeroFlag()); assertFalse(cpu.getNegativeFlag()); } public void test_CPX_SetsCarryFlagIfYGreaterThanMemory() throws MemoryAccessException { bus.loadProgram(0xa2, 0x0a, // LDX #$0A 0xe0, 0x08); // CPX #$08 cpu.step(2); assertTrue(cpu.getCarryFlag()); assertFalse(cpu.getZeroFlag()); // $0a - $08 = positive assertFalse(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa2, 0xfa, // LDX #$FA 0xe0, 0x80); // CPX #$80 cpu.step(2); assertTrue(cpu.getCarryFlag()); assertFalse(cpu.getZeroFlag()); // $fa - $80 = positive assertFalse(cpu.getNegativeFlag()); } public void test_CPX_DoesNotSetCarryFlagIfYGreaterThanMemory() throws MemoryAccessException { bus.loadProgram(0xa2, 0x08, // LDX #$08 0xe0, 0x0a); // CPX #$0A cpu.step(2); assertFalse(cpu.getCarryFlag()); assertFalse(cpu.getZeroFlag()); // $08 - $0a = negative assertTrue(cpu.getNegativeFlag()); cpu.reset(); bus.loadProgram(0xa2, 0x70, // LDX #$70 0xe0, 0x80); // CMX #$80 cpu.step(2); assertFalse(cpu.getCarryFlag()); assertFalse(cpu.getZeroFlag()); // $70 - $80 = negative assertTrue(cpu.getNegativeFlag()); } /* SBC Immediate Mode Tests - 0xe9 */ public void test_SBC() throws MemoryAccessException { bus.loadProgram(0xa9, 0x00, // LDA #$00 0xe9, 0x01); // SBC #$01 cpu.step(2); assertEquals(0xfe, cpu.getAccumulator()); assertTrue(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertFalse(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xa9, 0x7f, // LDA #$7f 0xe9, 0x01); // SBC #$01 cpu.step(2); assertEquals(0x7d, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xa9, 0x80, // LDA #$80 0xe9, 0x01); // SBC #$01 cpu.step(2); assertEquals(0x7e, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertTrue(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xa9, 0xff, // LDA #$ff 0xe9, 0x01); // SBC #$01 cpu.step(2); assertEquals(0xfd, cpu.getAccumulator()); assertTrue(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getCarryFlag()); cpu.reset(); bus.loadProgram(0xa9, 0x02, // LDA #$02 0xe9, 0x01); // SBC #$01 cpu.step(2); assertEquals(0x00, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertTrue(cpu.getZeroFlag()); assertTrue(cpu.getCarryFlag()); } public void test_SBC_IncludesNotOfCarry() throws MemoryAccessException { // Subtrace with Carry Flag cleared bus.loadProgram(0x18, // CLC 0xa9, 0x05, // LDA #$00 0xe9, 0x01); // SBC #$01 cpu.step(3); assertEquals(0x03, cpu.getAccumulator()); cpu.reset(); // Subtrace with Carry Flag cleared bus.loadProgram(0x18, // CLC 0xa9, 0x00, // LDA #$00 0xe9, 0x01); // SBC #$01 cpu.step(3); assertEquals(0xfe, cpu.getAccumulator()); cpu.reset(); // Subtract with Carry Flag set bus.loadProgram(0x38, // SEC 0xa9, 0x05, // LDA #$00 0xe9, 0x01); // SBC #$01 cpu.step(3); assertEquals(0x04, cpu.getAccumulator()); assertTrue(cpu.getCarryFlag()); cpu.reset(); // Subtract with Carry Flag set bus.loadProgram(0x38, // SEC 0xa9, 0x00, // LDA #$00 0xe9, 0x01); // SBC #$01 cpu.step(3); assertEquals(0xff, cpu.getAccumulator()); assertFalse(cpu.getCarryFlag()); } public void test_SBC_DecimalMode() throws MemoryAccessException { bus.loadProgram(0xf8, 0xa9, 0x00, 0xe9, 0x01); cpu.step(3); assertEquals(0x98, cpu.getAccumulator()); assertFalse(cpu.getCarryFlag()); // borrow = set flag assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getDecimalModeFlag()); cpu.reset(); bus.loadProgram(0xf8, 0xa9, 0x99, 0xe9, 0x01); cpu.step(3); assertEquals(0x97, cpu.getAccumulator()); assertTrue(cpu.getCarryFlag()); // No borrow = clear flag assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getDecimalModeFlag()); cpu.reset(); bus.loadProgram(0xf8, 0xa9, 0x50, 0xe9, 0x01); cpu.step(3); assertEquals(0x48, cpu.getAccumulator()); assertTrue(cpu.getCarryFlag()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getDecimalModeFlag()); cpu.reset(); bus.loadProgram(0xf8, // SED 0xa9, 0x02, // LDA #$02 0xe9, 0x01); // SBC #$01 cpu.step(3); assertEquals(0x00, cpu.getAccumulator()); assertTrue(cpu.getCarryFlag()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertTrue(cpu.getZeroFlag()); assertTrue(cpu.getDecimalModeFlag()); cpu.reset(); bus.loadProgram(0xf8, // SED 0xa9, 0x10, // LDA #$10 0xe9, 0x11); // SBC #$11 cpu.step(3); assertEquals(0x98, cpu.getAccumulator()); assertFalse(cpu.getCarryFlag()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getDecimalModeFlag()); cpu.reset(); bus.loadProgram(0x38, // SEC 0xf8, // SED 0xa9, 0x05, // LDA #$05 0xe9, 0x01); // SBC #$01 cpu.step(4); assertEquals(0x04, cpu.getAccumulator()); assertTrue(cpu.getCarryFlag()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getDecimalModeFlag()); cpu.reset(); bus.loadProgram(0x38, // SEC 0xf8, // SED 0xa9, 0x00, // LDA #$00 0xe9, 0x01); // SBC #$01 cpu.step(4); assertEquals(0x99, cpu.getAccumulator()); assertFalse(cpu.getCarryFlag()); assertFalse(cpu.getNegativeFlag()); assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getZeroFlag()); assertTrue(cpu.getDecimalModeFlag()); } }