mirror of
https://codeberg.org/sethm/symon.git
synced 2026-11-09 03:22:24 +00:00
Implemented set/clear flag instructions. More tests, but SBC is still BROKEN.
This commit is contained in:
1 parent
088b0823e1
commit
46a5943736
2 files changed
+332
-244
No files matched your search
@@ -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) {
|
||||||
@@ -720,119 +727,214 @@ public class Cpu implements InstructionTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the carry flag
|
* @return the carry flag
|
||||||
*/
|
*/
|
||||||
public boolean getCarryFlag() {
|
public boolean getCarryFlag() {
|
||||||
return carryFlag;
|
return carryFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param carryFlag the carry flag to set
|
* @param carryFlag the carry flag to set
|
||||||
*/
|
*/
|
||||||
public void setCarryFlag(boolean carryFlag) {
|
public void setCarryFlag(boolean carryFlag) {
|
||||||
this.carryFlag = carryFlag;
|
this.carryFlag = carryFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the zero flag
|
|
||||||
*/
|
|
||||||
public boolean getZeroFlag() {
|
|
||||||
return zeroFlag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param zeroFlag the zero flag to set
|
|
||||||
*/
|
|
||||||
public void setZeroFlag(boolean zeroFlag) {
|
|
||||||
this.zeroFlag = zeroFlag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the irq disable flag
|
* Sets the Carry Flag
|
||||||
*/
|
*/
|
||||||
public boolean getIrqDisableFlag() {
|
public void setCarryFlag() {
|
||||||
return irqDisableFlag;
|
this.carryFlag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param irqDisableFlag the irq disable flag to set
|
* Clears the Carry Flag
|
||||||
*/
|
*/
|
||||||
public void setIrqDisableFlag(boolean irqDisableFlag) {
|
public void clearCarryFlag() {
|
||||||
this.irqDisableFlag = irqDisableFlag;
|
this.carryFlag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the decimal mode flag
|
* @return the zero flag
|
||||||
*/
|
*/
|
||||||
public boolean getDecimalModeFlag() {
|
public boolean getZeroFlag() {
|
||||||
return decimalModeFlag;
|
return zeroFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param decimalModeFlag the decimal mde flag to set
|
* @param zeroFlag the zero flag to set
|
||||||
*/
|
*/
|
||||||
public void setDecimalModeFlag(boolean decimalModeFlag) {
|
public void setZeroFlag(boolean zeroFlag) {
|
||||||
this.decimalModeFlag = decimalModeFlag;
|
this.zeroFlag = zeroFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the break flag
|
* Sets the Zero Flag
|
||||||
*/
|
*/
|
||||||
public boolean getBreakFlag() {
|
public void setZeroFlag() {
|
||||||
return breakFlag;
|
this.zeroFlag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param breakFlag the break flag to set
|
* Clears the Zero Flag
|
||||||
*/
|
*/
|
||||||
public void setBreakFlag(boolean breakFlag) {
|
public void clearZeroFlag() {
|
||||||
this.breakFlag = breakFlag;
|
this.zeroFlag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the overflow flag
|
* @return the irq disable flag
|
||||||
*/
|
*/
|
||||||
public boolean getOverflowFlag() {
|
public boolean getIrqDisableFlag() {
|
||||||
return overflowFlag;
|
return irqDisableFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param overflowFlag the overflow flag to set
|
* @param irqDisableFlag the irq disable flag to set
|
||||||
*/
|
*/
|
||||||
public void setOverflowFlag(boolean overflowFlag) {
|
public void setIrqDisableFlag(boolean irqDisableFlag) {
|
||||||
this.overflowFlag = overflowFlag;
|
this.irqDisableFlag = irqDisableFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAccumulator() {
|
public void setIrqDisableFlag() {
|
||||||
return a;
|
this.irqDisableFlag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getXRegister() {
|
public void clearIrqDisableFlag() {
|
||||||
return x;
|
this.irqDisableFlag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getYRegister() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getProgramCounter() {
|
/**
|
||||||
return pc;
|
* @return the decimal mode flag
|
||||||
}
|
*/
|
||||||
|
public boolean getDecimalModeFlag() {
|
||||||
|
return decimalModeFlag;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A string representing the current status register state.
|
* @param decimalModeFlag the decimal mode flag to set
|
||||||
*/
|
*/
|
||||||
public String statusRegisterString() {
|
public void setDecimalModeFlag(boolean decimalModeFlag) {
|
||||||
StringBuffer sb = new StringBuffer();
|
this.decimalModeFlag = decimalModeFlag;
|
||||||
sb.append("(N:" + (getNegativeFlag() ? '1' : '0') + ", ");
|
}
|
||||||
sb.append("V:" + (getOverflowFlag() ? '1' : '0') + ", ");
|
|
||||||
sb.append("B:" + (getBreakFlag() ? '1' : '0') + ", ");
|
/**
|
||||||
sb.append("D:" + (getDecimalModeFlag() ? '1' : '0') + ", ");
|
* Sets the Decimal Mode Flag to true.
|
||||||
sb.append("I:" + (getIrqDisableFlag() ? '1' : '0') + ", ");
|
*/
|
||||||
sb.append("Z:" + (getZeroFlag() ? '1' : '0') + ", ");
|
public void setDecimalModeFlag() {
|
||||||
sb.append("C:" + (getCarryFlag() ? '1' : '0') + ")");
|
this.decimalModeFlag = true;
|
||||||
return sb.toString();
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Clears the Decimal Mode Flag.
|
||||||
|
*/
|
||||||
|
public void clearDecimalModeFlag() {
|
||||||
|
this.decimalModeFlag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the break flag
|
||||||
|
*/
|
||||||
|
public boolean getBreakFlag() {
|
||||||
|
return breakFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param breakFlag the break flag to set
|
||||||
|
*/
|
||||||
|
public void setBreakFlag(boolean 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
|
||||||
|
*/
|
||||||
|
public boolean getOverflowFlag() {
|
||||||
|
return overflowFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param overflowFlag the overflow flag to set
|
||||||
|
*/
|
||||||
|
public void setOverflowFlag(boolean 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() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccumulator(int val) {
|
||||||
|
this.a = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getXRegister() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setXRegister(int val) {
|
||||||
|
this.x = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getYRegister() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYRegister(int val) {
|
||||||
|
this.y = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getProgramCounter() {
|
||||||
|
return pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProgramCounter(int addr) {
|
||||||
|
this.pc = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return A string representing the current status register state.
|
||||||
|
*/
|
||||||
|
public String statusRegisterString() {
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
sb.append("(N:" + (getNegativeFlag() ? '1' : '0') + ", ");
|
||||||
|
sb.append("V:" + (getOverflowFlag() ? '1' : '0') + ", ");
|
||||||
|
sb.append("B:" + (getBreakFlag() ? '1' : '0') + ", ");
|
||||||
|
sb.append("D:" + (getDecimalModeFlag() ? '1' : '0') + ", ");
|
||||||
|
sb.append("I:" + (getIrqDisableFlag() ? '1' : '0') + ", ");
|
||||||
|
sb.append("Z:" + (getZeroFlag() ? '1' : '0') + ", ");
|
||||||
|
sb.append("C:" + (getCarryFlag() ? '1' : '0') + ")");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a string representing the CPU state.
|
* Returns a string representing the CPU 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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user