Implemented set/clear flag instructions. More tests, but SBC is still BROKEN.

This commit is contained in:
Seth J. Morabito committed 2008-12-20 02:00:45 -08:00
1 parent 088b0823e1
commit 46a5943736
2 files changed
+243 -155

No files matched your search

+112 -10
View File
@@ -162,7 +162,8 @@ public class Cpu implements InstructionTable {
break; break;
case 0x17: // n/a case 0x17: // n/a
break; break;
case 0x18: // n/a case 0x18: // CLC - Clear Carry Flag, Implied
clearCarryFlag();
break; break;
case 0x19: // n/a case 0x19: // n/a
break; break;
@@ -230,7 +231,8 @@ public class Cpu implements InstructionTable {
break; break;
case 0x37: // n/a case 0x37: // n/a
break; break;
case 0x38: // n/a case 0x38: // SEC - Set Carry Flag, Implied
setCarryFlag();
break; break;
case 0x39: // n/a case 0x39: // n/a
break; break;
@@ -299,7 +301,8 @@ public class Cpu implements InstructionTable {
break; break;
case 0x57: // n/a case 0x57: // n/a
break; break;
case 0x58: // n/a case 0x58: // CLI - Clear Interrupt Disable, Implied
clearIrqDisableFlag();
break; break;
case 0x59: // n/a case 0x59: // n/a
break; break;
@@ -367,7 +370,8 @@ public class Cpu implements InstructionTable {
break; break;
case 0x77: // n/a case 0x77: // n/a
break; break;
case 0x78: // n/a case 0x78: // SEI - Set Interrupt Disable, Implied
setIrqDisableFlag();
break; break;
case 0x79: // n/a case 0x79: // n/a
break; break;
@@ -505,7 +509,8 @@ public class Cpu implements InstructionTable {
break; break;
case 0xb7: // n/a case 0xb7: // n/a
break; break;
case 0xb8: // n/a case 0xb8: // CLV - Clear Overflow Flag, Implied
clearOverflowFlag();
break; break;
case 0xb9: // n/a case 0xb9: // n/a
break; break;
@@ -573,7 +578,8 @@ public class Cpu implements InstructionTable {
break; break;
case 0xd7: // n/a case 0xd7: // n/a
break; break;
case 0xd8: // n/a case 0xd8: // CLD - Clear Decimal Mode, Implied
clearDecimalModeFlag();
break; break;
case 0xd9: // n/a case 0xd9: // n/a
break; break;
@@ -642,7 +648,8 @@ public class Cpu implements InstructionTable {
break; break;
case 0xf7: // n/a case 0xf7: // n/a
break; break;
case 0xf8: // n/a case 0xf8: // SED - Set Decimal Flag, Implied
setDecimalModeFlag();
break; break;
case 0xf9: // n/a case 0xf9: // n/a
break; break;
@@ -679,8 +686,8 @@ public class Cpu implements InstructionTable {
} }
public int sbc(int acc, int operand) { public int sbc(int acc, int operand) {
// Equivalent to ADC of the 2's complement of the operand // Equivalent to ADC of the 2's complement of the operand, minus the /carry
return adc(acc, (--operand) ^ 0xff); return adc(acc, (--operand ^ 0xff));
} }
public void cmp(int reg, int operand) { public void cmp(int reg, int operand) {
@@ -733,6 +740,20 @@ public class Cpu implements InstructionTable {
this.carryFlag = carryFlag; this.carryFlag = carryFlag;
} }
/**
* Sets the Carry Flag
*/
public void setCarryFlag() {
this.carryFlag = true;
}
/**
* Clears the Carry Flag
*/
public void clearCarryFlag() {
this.carryFlag = false;
}
/** /**
* @return the zero flag * @return the zero flag
*/ */
@@ -747,6 +768,20 @@ public class Cpu implements InstructionTable {
this.zeroFlag = zeroFlag; this.zeroFlag = zeroFlag;
} }
/**
* Sets the Zero Flag
*/
public void setZeroFlag() {
this.zeroFlag = true;
}
/**
* Clears the Zero Flag
*/
public void clearZeroFlag() {
this.zeroFlag = false;
}
/** /**
* @return the irq disable flag * @return the irq disable flag
*/ */
@@ -761,6 +796,15 @@ public class Cpu implements InstructionTable {
this.irqDisableFlag = irqDisableFlag; this.irqDisableFlag = irqDisableFlag;
} }
public void setIrqDisableFlag() {
this.irqDisableFlag = true;
}
public void clearIrqDisableFlag() {
this.irqDisableFlag = false;
}
/** /**
* @return the decimal mode flag * @return the decimal mode flag
*/ */
@@ -769,12 +813,26 @@ public class Cpu implements InstructionTable {
} }
/** /**
* @param decimalModeFlag the decimal mde flag to set * @param decimalModeFlag the decimal mode flag to set
*/ */
public void setDecimalModeFlag(boolean decimalModeFlag) { public void setDecimalModeFlag(boolean decimalModeFlag) {
this.decimalModeFlag = decimalModeFlag; this.decimalModeFlag = decimalModeFlag;
} }
/**
* Sets the Decimal Mode Flag to true.
*/
public void setDecimalModeFlag() {
this.decimalModeFlag = true;
}
/**
* Clears the Decimal Mode Flag.
*/
public void clearDecimalModeFlag() {
this.decimalModeFlag = false;
}
/** /**
* @return the break flag * @return the break flag
*/ */
@@ -789,6 +847,20 @@ public class Cpu implements InstructionTable {
this.breakFlag = breakFlag; this.breakFlag = breakFlag;
} }
/**
* Sets the Break Flag
*/
public void setBreakFlag() {
this.breakFlag = true;
}
/**
* Clears the Break Flag
*/
public void clearBreakFlag() {
this.breakFlag = false;
}
/** /**
* @return the overflow flag * @return the overflow flag
*/ */
@@ -803,22 +875,52 @@ public class Cpu implements InstructionTable {
this.overflowFlag = overflowFlag; this.overflowFlag = overflowFlag;
} }
/**
* Sets the Overflow Flag
*/
public void setOverflowFlag() {
this.overflowFlag = true;
}
/**
* Clears the Overflow Flag
*/
public void clearOverflowFlag() {
this.overflowFlag = false;
}
public int getAccumulator() { public int getAccumulator() {
return a; return a;
} }
public void setAccumulator(int val) {
this.a = val;
}
public int getXRegister() { public int getXRegister() {
return x; return x;
} }
public void setXRegister(int val) {
this.x = val;
}
public int getYRegister() { public int getYRegister() {
return y; return y;
} }
public void setYRegister(int val) {
this.y = val;
}
public int getProgramCounter() { public int getProgramCounter() {
return pc; return pc;
} }
public void setProgramCounter(int addr) {
this.pc = addr;
}
/** /**
* @return A string representing the current status register state. * @return A string representing the current status register state.
*/ */
@@ -159,147 +159,99 @@ public class CpuImmediateModeTest extends TestCase {
/* ADC Immediate Mode Tests - 0x69 */ /* ADC Immediate Mode Tests - 0x69 */
public void test_ADC_SetsAccumulator() { public void test_ADC() {
bus.loadProgram(0x69, 0x01, // ADC #$01 bus.loadProgram(0xa9, 0x00, // LDA #$00
0x69, 0xa0, // ADC #$a0 0x69, 0x01); // ADC #$01
0x69, 0x02, // ADC #$02 cpu.step(2);
0x69, 0x06); // ADC #$06
cpu.step();
assertEquals(0x01, cpu.getAccumulator()); assertEquals(0x01, cpu.getAccumulator());
assertFalse(cpu.getNegativeFlag());
assertFalse(cpu.getOverflowFlag());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getCarryFlag());
cpu.step(); cpu.reset();
assertEquals(0xa1, cpu.getAccumulator()); 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.step(); cpu.reset();
assertEquals(0xa3, cpu.getAccumulator()); 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.step(); cpu.reset();
assertEquals(0xa9, cpu.getAccumulator()); 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() { public void test_ADC_IncludesCarry() {
cpu.setCarryFlag(true); bus.loadProgram(0xa9, 0x00, // LDA #$01
0x38, // SEC
bus.loadProgram(0x69, 0x01); // ADC #$01 0x69, 0x01); // ADC #$01
cpu.step(3);
cpu.step();
assertEquals(0x02, cpu.getAccumulator()); assertEquals(0x02, cpu.getAccumulator());
} assertFalse(cpu.getNegativeFlag());
public void test_ADC_SetsCarryIfResultCarries() {
bus.loadProgram(0xa9, 0xff, // LDA #$FE
0x69, 0x02);
cpu.step(2);
assertEquals(0x01, cpu.getAccumulator());
assertFalse(cpu.getZeroFlag());
assertTrue(cpu.getCarryFlag());
assertFalse(cpu.getOverflowFlag()); assertFalse(cpu.getOverflowFlag());
}
public void test_ADC_SetsOverflowIfResultChangesSign() {
bus.loadProgram(0xa9, 0x7f, // LDA #$7f
0x69, 0x01); // ADC #$01
cpu.step(2);
assertEquals(0x80, cpu.getAccumulator());
assertFalse(cpu.getZeroFlag()); assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getCarryFlag()); assertFalse(cpu.getCarryFlag());
assertTrue(cpu.getOverflowFlag());
cpu.reset();
bus.loadProgram(0xa9, 0x80, // LDA #$80
0x69, 0xff); // ADC #$ff
cpu.step(2);
assertEquals(0x7f, cpu.getAccumulator());
assertFalse(cpu.getZeroFlag());
assertTrue(cpu.getCarryFlag());
assertFalse(cpu.getNegativeFlag());
assertTrue(cpu.getOverflowFlag());
} }
public void test_ADC_DoesNotSetOverflowIfNotNeeded() {
bus.loadProgram(0xa9, 0xff, // LDA #$ff
0x69, 0x01); // ADC #$01
cpu.step(2);
assertEquals(0x00, cpu.getAccumulator());
assertTrue(cpu.getZeroFlag());
assertTrue(cpu.getCarryFlag());
assertFalse(cpu.getNegativeFlag());
assertFalse(cpu.getOverflowFlag());
cpu.reset();
bus.loadProgram(0xa9, 0x01, // LDA #$01
0x69, 0x01); // ADC #$01
cpu.step(2);
assertEquals(0x02, cpu.getAccumulator());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getCarryFlag());
assertFalse(cpu.getNegativeFlag());
assertFalse(cpu.getOverflowFlag());
}
public void test_ADC_SetsNegativeFlagIfResultIsNegative() {
bus.loadProgram(0xa9, 0x7f, // LDA #$7F
0x69, 0x01); // ADC #$01
cpu.step(2);
assertEquals(0x80, cpu.getAccumulator());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getCarryFlag());
assertTrue(cpu.getNegativeFlag());
assertTrue(cpu.getOverflowFlag());
}
public void test_ADC_SetsZeroFlagIfResultIsZero() {
bus.loadProgram(0xa9, 0xff, // LDA #$FF
0x69, 0x01); // ADC #$01
cpu.step(2);
assertEquals(0x00, cpu.getAccumulator());
assertTrue(cpu.getZeroFlag());
assertTrue(cpu.getCarryFlag());
assertFalse(cpu.getNegativeFlag());
assertFalse(cpu.getOverflowFlag());
}
public void test_ADC_DoesNotSetNegativeFlagIfResultNotNegative() {
bus.loadProgram(0xa9, 0x7e, // LDA #$7E
0x69, 0x01); // ADC #$01
cpu.step(2);
assertEquals(0x7f, cpu.getAccumulator());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getCarryFlag());
assertFalse(cpu.getNegativeFlag());
assertFalse(cpu.getOverflowFlag());
}
public void test_ADC_DoesNotSetZeroFlagIfResultNotZero() {
bus.loadProgram(0xa9, 0xff, // LDA #$ff
0x69, 0x03); // ADC #$03
cpu.step(2);
assertEquals(0x2, cpu.getAccumulator());
assertFalse(cpu.getZeroFlag());
assertTrue(cpu.getCarryFlag());
assertFalse(cpu.getNegativeFlag());
assertFalse(cpu.getOverflowFlag());
}
/* LDY Immediate Mode Tests - 0xa0 */ /* LDY Immediate Mode Tests - 0xa0 */
@@ -612,29 +564,63 @@ public class CpuImmediateModeTest extends TestCase {
/* SBC Immediate Mode Tests - 0xe9 */ /* SBC Immediate Mode Tests - 0xe9 */
public void test_SBC_SetsAccumulator() { public void test_SBC() {
bus.loadProgram(0xa9, 0xff, // LDA #$FF bus.loadProgram(0xa9, 0x00, // LDA #$00
0xe9, 0x01, // SBC #$01 0xe9, 0x01); // SBC #$01
0xe9, 0x01, // SBC #$a0 cpu.step(2);
0xe9, 0x01, // SBC #$02 assertEquals(0xfe, cpu.getAccumulator());
0xe9, 0x01); // SBC #$06 assertTrue(cpu.getNegativeFlag());
assertFalse(cpu.getOverflowFlag());
assertFalse(cpu.getZeroFlag());
assertFalse(cpu.getCarryFlag()); 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); cpu.step(2);
assertEquals(0xfd, cpu.getAccumulator()); assertEquals(0xfd, cpu.getAccumulator());
assertTrue(cpu.getNegativeFlag());
assertFalse(cpu.getOverflowFlag());
assertFalse(cpu.getZeroFlag());
assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getCarryFlag());
cpu.step(); cpu.reset();
assertEquals(0xfc, cpu.getAccumulator()); bus.loadProgram(0xa9, 0x02, // LDA #$02
assertTrue(cpu.getCarryFlag()); 0xe9, 0x01); // SBC #$01
cpu.step(2);
cpu.step(); assertEquals(0x00, cpu.getAccumulator());
assertEquals(0xfb, cpu.getAccumulator()); assertFalse(cpu.getNegativeFlag());
assertTrue(cpu.getCarryFlag()); assertFalse(cpu.getOverflowFlag());
assertTrue(cpu.getZeroFlag());
cpu.step();
assertEquals(0xfa, cpu.getAccumulator());
assertTrue(cpu.getCarryFlag()); assertTrue(cpu.getCarryFlag());
} }
public void test_SBC_IncludesNotOfCarry() {
cpu.reset();
bus.loadProgram(0x38, // SEC
0xa9, 0x00, // LDA #$00
0xe9, 0x01); // SBC #$01
cpu.step(3);
assertEquals(0xff, cpu.getAccumulator());
}
} }