Started on Zero Page opcodes and tests.
This commit is contained in:
1 parent
de0742f59f
commit
ecde55c6b8
6 files changed
+346
-126
No files matched your search
@@ -18,7 +18,7 @@ public class Cpu implements InstructionTable {
|
|||||||
// Bit 5 is always '1'
|
// Bit 5 is always '1'
|
||||||
public static final int P_OVERFLOW = 0x40;
|
public static final int P_OVERFLOW = 0x40;
|
||||||
public static final int P_NEGATIVE = 0x80;
|
public static final int P_NEGATIVE = 0x80;
|
||||||
|
|
||||||
// NMI vector
|
// NMI vector
|
||||||
public static final int IRQ_VECTOR_L = 0xfffa;
|
public static final int IRQ_VECTOR_L = 0xfffa;
|
||||||
public static final int IRQ_VECTOR_H = 0xfffb;
|
public static final int IRQ_VECTOR_H = 0xfffb;
|
||||||
@@ -28,7 +28,7 @@ public class Cpu implements InstructionTable {
|
|||||||
// IRQ vector
|
// IRQ vector
|
||||||
public static final int NMI_VECTOR_L = 0xfffe;
|
public static final int NMI_VECTOR_L = 0xfffe;
|
||||||
public static final int NMI_VECTOR_H = 0xffff;
|
public static final int NMI_VECTOR_H = 0xffff;
|
||||||
|
|
||||||
/* The Bus */
|
/* The Bus */
|
||||||
private Bus bus;
|
private Bus bus;
|
||||||
|
|
||||||
@@ -42,6 +42,11 @@ public class Cpu implements InstructionTable {
|
|||||||
private int sp; // Stack Pointer register, offset into page 1
|
private int sp; // Stack Pointer register, offset into page 1
|
||||||
private int ir; // Instruction register
|
private int ir; // Instruction register
|
||||||
|
|
||||||
|
/* Internal scratch space */
|
||||||
|
private int lo = 0, hi = 0; // Used in address calculation
|
||||||
|
private int j = 0, k = 0; // Used for temporary storage
|
||||||
|
|
||||||
|
|
||||||
/* Operands for the current instruction */
|
/* Operands for the current instruction */
|
||||||
private int[] operands = new int[2];
|
private int[] operands = new int[2];
|
||||||
private int addr; // The address the most recent instruction
|
private int addr; // The address the most recent instruction
|
||||||
@@ -83,7 +88,7 @@ public class Cpu implements InstructionTable {
|
|||||||
sp = 0xff;
|
sp = 0xff;
|
||||||
|
|
||||||
// Set the PC to the address stored in the reset vector
|
// Set the PC to the address stored in the reset vector
|
||||||
pc = CpuUtils.address(bus.read(RST_VECTOR_L), bus.read(RST_VECTOR_H));
|
pc = address(bus.read(RST_VECTOR_L), bus.read(RST_VECTOR_H));
|
||||||
|
|
||||||
// Clear instruction register.
|
// Clear instruction register.
|
||||||
ir = 0;
|
ir = 0;
|
||||||
@@ -106,8 +111,6 @@ public class Cpu implements InstructionTable {
|
|||||||
* Performs an individual machine cycle.
|
* Performs an individual machine cycle.
|
||||||
*/
|
*/
|
||||||
public void step() {
|
public void step() {
|
||||||
int lo, hi; // Used in address calculation
|
|
||||||
|
|
||||||
// Store the address from which the IR was read, for debugging
|
// Store the address from which the IR was read, for debugging
|
||||||
addr = pc;
|
addr = pc;
|
||||||
|
|
||||||
@@ -139,7 +142,7 @@ public class Cpu implements InstructionTable {
|
|||||||
// Set the Interrupt Disabled flag. RTI will clear it.
|
// Set the Interrupt Disabled flag. RTI will clear it.
|
||||||
setIrqDisableFlag();
|
setIrqDisableFlag();
|
||||||
// Load interrupt vector address into PC
|
// Load interrupt vector address into PC
|
||||||
pc = CpuUtils.address(bus.read(IRQ_VECTOR_L), bus.read(IRQ_VECTOR_H));
|
pc = address(bus.read(IRQ_VECTOR_L), bus.read(IRQ_VECTOR_H));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x01: // n/a
|
case 0x01: // n/a
|
||||||
@@ -150,9 +153,13 @@ public class Cpu implements InstructionTable {
|
|||||||
break;
|
break;
|
||||||
case 0x04: // n/a
|
case 0x04: // n/a
|
||||||
break;
|
break;
|
||||||
case 0x05: // n/a
|
case 0x05: // ORA - Logical Inclusive OR - Zero Page
|
||||||
|
a |= bus.read(operands[0]);
|
||||||
|
setArithmeticFlags(a);
|
||||||
break;
|
break;
|
||||||
case 0x06: // n/a
|
case 0x06: // ASL - Arithmetic Shift Left - Zero Page
|
||||||
|
bus.write(operands[0], asl(bus.read(operands[0])));
|
||||||
|
setArithmeticFlags(bus.read(operands[0]));
|
||||||
break;
|
break;
|
||||||
case 0x07: // n/a
|
case 0x07: // n/a
|
||||||
break;
|
break;
|
||||||
@@ -218,7 +225,12 @@ public class Cpu implements InstructionTable {
|
|||||||
break;
|
break;
|
||||||
case 0x23: // n/a
|
case 0x23: // n/a
|
||||||
break;
|
break;
|
||||||
case 0x24: // n/a
|
case 0x24: // BIT - Bit Test - Zero Page
|
||||||
|
j = bus.read(operands[0]);
|
||||||
|
k = a & j;
|
||||||
|
setZeroFlag(k == 0);
|
||||||
|
setNegativeFlag((k & 0x80) != 0);
|
||||||
|
setOverflowFlag((k & 0x40) != 0);
|
||||||
break;
|
break;
|
||||||
case 0x25: // n/a
|
case 0x25: // n/a
|
||||||
break;
|
break;
|
||||||
@@ -284,7 +296,7 @@ public class Cpu implements InstructionTable {
|
|||||||
setProcessorStatus(stackPop());
|
setProcessorStatus(stackPop());
|
||||||
lo = stackPop();
|
lo = stackPop();
|
||||||
hi = stackPop();
|
hi = stackPop();
|
||||||
setProgramCounter(CpuUtils.address(lo, hi));
|
setProgramCounter(address(lo, hi));
|
||||||
break;
|
break;
|
||||||
case 0x41: // n/a
|
case 0x41: // n/a
|
||||||
break;
|
break;
|
||||||
@@ -312,7 +324,7 @@ public class Cpu implements InstructionTable {
|
|||||||
case 0x4b: // n/a
|
case 0x4b: // n/a
|
||||||
break;
|
break;
|
||||||
case 0x4c: // JMP - Jump - Absolute
|
case 0x4c: // JMP - Jump - Absolute
|
||||||
pc = CpuUtils.address(operands[0], operands[1]);
|
pc = address(operands[0], operands[1]);
|
||||||
break;
|
break;
|
||||||
case 0x4d: // n/a
|
case 0x4d: // n/a
|
||||||
break;
|
break;
|
||||||
@@ -358,7 +370,7 @@ public class Cpu implements InstructionTable {
|
|||||||
case 0x60: // RTS - Return from Subroutine - Implied
|
case 0x60: // RTS - Return from Subroutine - Implied
|
||||||
lo = stackPop();
|
lo = stackPop();
|
||||||
hi = stackPop();
|
hi = stackPop();
|
||||||
setProgramCounter((CpuUtils.address(lo, hi) + 1) & 0xffff);
|
setProgramCounter((address(lo, hi) + 1) & 0xffff);
|
||||||
break;
|
break;
|
||||||
case 0x61: // n/a
|
case 0x61: // n/a
|
||||||
break;
|
break;
|
||||||
@@ -753,17 +765,17 @@ public class Cpu implements InstructionTable {
|
|||||||
setArithmeticFlags(result);
|
setArithmeticFlags(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add with Carry (BCD).
|
* Add with Carry (BCD).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public int adcDecimal(int acc, int operand) {
|
public int adcDecimal(int acc, int operand) {
|
||||||
int l, h, result;
|
int l, h, result;
|
||||||
l = (acc & 0x0f) + (operand & 0x0f) + getCarryBit();
|
l = (acc & 0x0f) + (operand & 0x0f) + getCarryBit();
|
||||||
if ((l & 0xff) > 9) l += 6;
|
if ((l & 0xff) > 9) l += 6;
|
||||||
h = (acc >> 4) + (operand >> 4) + (l > 15 ? 1 : 0);
|
h = (acc >> 4) + (operand >> 4) + (l > 15 ? 1 : 0);
|
||||||
if ((h & 0xff) > 9) h += 6;
|
if ((h & 0xff) > 9) h += 6;
|
||||||
result = (l & 0x0f) | (h << 4);
|
result = (l & 0x0f) | (h << 4);
|
||||||
result &= 0xff;
|
result &= 0xff;
|
||||||
setCarryFlag(h > 15);
|
setCarryFlag(h > 15);
|
||||||
@@ -771,13 +783,13 @@ public class Cpu implements InstructionTable {
|
|||||||
setNegativeFlag(false); // BCD is never negative
|
setNegativeFlag(false); // BCD is never negative
|
||||||
setOverflowFlag(false); // BCD never sets overflow flag
|
setOverflowFlag(false); // BCD never sets overflow flag
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common code for Subtract with Carry. Just calls ADC of the
|
* Common code for Subtract with Carry. Just calls ADC of the
|
||||||
* one's complement of the operand. This lets the N, V, C, and Z
|
* one's complement of the operand. This lets the N, V, C, and Z
|
||||||
* flags work out nicely without any additional logic.
|
* flags work out nicely without any additional logic.
|
||||||
*
|
*
|
||||||
* @param acc
|
* @param acc
|
||||||
* @param operand
|
* @param operand
|
||||||
* @return
|
* @return
|
||||||
@@ -788,10 +800,10 @@ public class Cpu implements InstructionTable {
|
|||||||
setArithmeticFlags(result);
|
setArithmeticFlags(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subtract with Carry, BCD mode.
|
* Subtract with Carry, BCD mode.
|
||||||
*
|
*
|
||||||
* @param acc
|
* @param acc
|
||||||
* @param operand
|
* @param operand
|
||||||
* @return
|
* @return
|
||||||
@@ -813,7 +825,7 @@ public class Cpu implements InstructionTable {
|
|||||||
/**
|
/**
|
||||||
* Compare two values, and set carry, zero, and negative flags
|
* Compare two values, and set carry, zero, and negative flags
|
||||||
* appropriately.
|
* appropriately.
|
||||||
*
|
*
|
||||||
* @param reg
|
* @param reg
|
||||||
* @param operand
|
* @param operand
|
||||||
*/
|
*/
|
||||||
@@ -833,7 +845,28 @@ public class Cpu implements InstructionTable {
|
|||||||
zeroFlag = (reg == 0);
|
zeroFlag = (reg == 0);
|
||||||
negativeFlag = (reg & 0x80) != 0;
|
negativeFlag = (reg & 0x80) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shifts the given value left by one bit, and sets the carry
|
||||||
|
* flag to the high bit of the initial value.
|
||||||
|
*
|
||||||
|
* @param m The value to shift left.
|
||||||
|
* @return the left shifted value (m * 2).
|
||||||
|
*/
|
||||||
|
private int asl(int m) {
|
||||||
|
setCarryFlag((m & 0x80) != 0);
|
||||||
|
return (m << 1) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shifts the given value right by one bit, filling with zeros,
|
||||||
|
* and sets the carry flag to the low bit of the initial value.
|
||||||
|
*/
|
||||||
|
private int lsr(int m) {
|
||||||
|
setCarryFlag((m & 0x01) != 0);
|
||||||
|
return (m >>> 1) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the negative flag
|
* @return the negative flag
|
||||||
*/
|
*/
|
||||||
@@ -876,7 +909,7 @@ public class Cpu implements InstructionTable {
|
|||||||
public boolean getCarryFlag() {
|
public boolean getCarryFlag() {
|
||||||
return carryFlag;
|
return carryFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 1 if the carry flag is set, 0 if it is clear.
|
* @return 1 if the carry flag is set, 0 if it is clear.
|
||||||
*/
|
*/
|
||||||
@@ -946,7 +979,7 @@ public class Cpu implements InstructionTable {
|
|||||||
public boolean getIrqDisableFlag() {
|
public boolean getIrqDisableFlag() {
|
||||||
return irqDisableFlag;
|
return irqDisableFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 1 if the interrupt disable flag is set, 0 if it is clear.
|
* @return 1 if the interrupt disable flag is set, 0 if it is clear.
|
||||||
*/
|
*/
|
||||||
@@ -1011,7 +1044,7 @@ public class Cpu implements InstructionTable {
|
|||||||
public boolean getBreakFlag() {
|
public boolean getBreakFlag() {
|
||||||
return breakFlag;
|
return breakFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 1 if the break flag is set, 0 if it is clear.
|
* @return 1 if the break flag is set, 0 if it is clear.
|
||||||
*/
|
*/
|
||||||
@@ -1046,7 +1079,7 @@ public class Cpu implements InstructionTable {
|
|||||||
public boolean getOverflowFlag() {
|
public boolean getOverflowFlag() {
|
||||||
return overflowFlag;
|
return overflowFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 1 if the overflow flag is set, 0 if it is clear.
|
* @return 1 if the overflow flag is set, 0 if it is clear.
|
||||||
*/
|
*/
|
||||||
@@ -1191,7 +1224,7 @@ public class Cpu implements InstructionTable {
|
|||||||
* Returns a string representing the CPU state.
|
* Returns a string representing the CPU state.
|
||||||
*/
|
*/
|
||||||
public String toString() {
|
public String toString() {
|
||||||
String opcode = CpuUtils.opcode(ir, operands[0], operands[1]);
|
String opcode = opcode(ir, operands[0], operands[1]);
|
||||||
StringBuffer sb = new StringBuffer(String.format("$%04X", addr) +
|
StringBuffer sb = new StringBuffer(String.format("$%04X", addr) +
|
||||||
" ");
|
" ");
|
||||||
sb.append(String.format("%-14s", opcode));
|
sb.append(String.format("%-14s", opcode));
|
||||||
@@ -1241,7 +1274,7 @@ public class Cpu implements InstructionTable {
|
|||||||
/*
|
/*
|
||||||
* Increment the PC, rolling over if necessary.
|
* Increment the PC, rolling over if necessary.
|
||||||
*/
|
*/
|
||||||
protected void incrementPC() {
|
void incrementPC() {
|
||||||
if (pc == 0xffff) {
|
if (pc == 0xffff) {
|
||||||
pc = 0;
|
pc = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -1249,4 +1282,34 @@ public class Cpu implements InstructionTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given two bytes, return an address.
|
||||||
|
*/
|
||||||
|
int address(int lowByte, int hiByte) {
|
||||||
|
return ((hiByte<<8)|lowByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an opcode and its operands, return a formatted name.
|
||||||
|
*
|
||||||
|
* @param opcode
|
||||||
|
* @param operands
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String opcode(int opcode, int op1, int op2) {
|
||||||
|
String opcodeName = Cpu.opcodeNames[opcode];
|
||||||
|
if (opcodeName == null) { return "???"; }
|
||||||
|
|
||||||
|
StringBuffer sb = new StringBuffer(opcodeName);
|
||||||
|
|
||||||
|
switch (Cpu.instructionModes[opcode]) {
|
||||||
|
case ABS:
|
||||||
|
sb.append(String.format(" $%04X", address(op1, op2)));
|
||||||
|
break;
|
||||||
|
case IMM:
|
||||||
|
sb.append(String.format(" #$%02X", op1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package com.loomcom.symon;
|
|
||||||
|
|
||||||
import com.loomcom.symon.InstructionTable.Mode;
|
|
||||||
|
|
||||||
public class CpuUtils {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given two bytes, return an address.
|
|
||||||
*/
|
|
||||||
public static int address(int lowByte, int hiByte) {
|
|
||||||
return ((hiByte<<8)|lowByte);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given an opcode and its operands, return a formatted name.
|
|
||||||
*
|
|
||||||
* @param opcode
|
|
||||||
* @param operands
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String opcode(int opcode, int op1, int op2) {
|
|
||||||
String opcodeName = Cpu.opcodeNames[opcode];
|
|
||||||
if (opcodeName == null) { return "???"; }
|
|
||||||
|
|
||||||
StringBuffer sb = new StringBuffer(opcodeName);
|
|
||||||
|
|
||||||
switch (Cpu.instructionModes[opcode]) {
|
|
||||||
case ABS:
|
|
||||||
sb.append(String.format(" $%04X", address(op1, op2)));
|
|
||||||
break;
|
|
||||||
case IMM:
|
|
||||||
sb.append(String.format(" #$%02X", op1));
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -30,7 +30,7 @@ public class CpuImmediateModeTest extends TestCase {
|
|||||||
assertEquals(0xff, cpu.getStackPointer());
|
assertEquals(0xff, cpu.getStackPointer());
|
||||||
assertEquals(0x20, cpu.getProcessorStatus());
|
assertEquals(0x20, cpu.getProcessorStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following opcodes are tested for correctness in this file:
|
* The following opcodes are tested for correctness in this file:
|
||||||
*
|
*
|
||||||
@@ -39,19 +39,19 @@ public class CpuImmediateModeTest extends TestCase {
|
|||||||
* EOR - $49
|
* EOR - $49
|
||||||
* ADC - $69
|
* ADC - $69
|
||||||
* LDY - $a0
|
* LDY - $a0
|
||||||
*
|
*
|
||||||
* LDX - $a2
|
* LDX - $a2
|
||||||
* LDA - $a9
|
* LDA - $a9
|
||||||
* CPY - $c0
|
* CPY - $c0
|
||||||
* CMP - $c9
|
* CMP - $c9
|
||||||
* CPX - $e0
|
* CPX - $e0
|
||||||
*
|
*
|
||||||
* SBC - $e9
|
* SBC - $e9
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* ORA Immediate Mode Tests - 0x09 */
|
/* ORA Immediate Mode Tests - 0x09 */
|
||||||
|
|
||||||
public void test_ORA_SetsAccumulator() {
|
public void test_ORA() {
|
||||||
bus.loadProgram(0x09, 0x00, // ORA #$00
|
bus.loadProgram(0x09, 0x00, // ORA #$00
|
||||||
0x09, 0x11, // ORA #$11
|
0x09, 0x11, // ORA #$11
|
||||||
0x09, 0x22, // ORA #$22
|
0x09, 0x22, // ORA #$22
|
||||||
@@ -722,22 +722,22 @@ public class CpuImmediateModeTest extends TestCase {
|
|||||||
bus.loadProgram(0x18, // CLC
|
bus.loadProgram(0x18, // CLC
|
||||||
0xa9, 0x05, // LDA #$00
|
0xa9, 0x05, // LDA #$00
|
||||||
0xe9, 0x01); // SBC #$01
|
0xe9, 0x01); // SBC #$01
|
||||||
|
|
||||||
cpu.step(3);
|
cpu.step(3);
|
||||||
assertEquals(0x03, cpu.getAccumulator());
|
assertEquals(0x03, cpu.getAccumulator());
|
||||||
|
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
|
|
||||||
// Subtrace with Carry Flag cleared
|
// Subtrace with Carry Flag cleared
|
||||||
bus.loadProgram(0x18, // CLC
|
bus.loadProgram(0x18, // CLC
|
||||||
0xa9, 0x00, // LDA #$00
|
0xa9, 0x00, // LDA #$00
|
||||||
0xe9, 0x01); // SBC #$01
|
0xe9, 0x01); // SBC #$01
|
||||||
|
|
||||||
cpu.step(3);
|
cpu.step(3);
|
||||||
assertEquals(0xfe, cpu.getAccumulator());
|
assertEquals(0xfe, cpu.getAccumulator());
|
||||||
|
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
|
|
||||||
// Subtract with Carry Flag set
|
// Subtract with Carry Flag set
|
||||||
bus.loadProgram(0x38, // SEC
|
bus.loadProgram(0x38, // SEC
|
||||||
0xa9, 0x05, // LDA #$00
|
0xa9, 0x05, // LDA #$00
|
||||||
@@ -745,9 +745,9 @@ public class CpuImmediateModeTest extends TestCase {
|
|||||||
cpu.step(3);
|
cpu.step(3);
|
||||||
assertEquals(0x04, cpu.getAccumulator());
|
assertEquals(0x04, cpu.getAccumulator());
|
||||||
assertTrue(cpu.getCarryFlag());
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
|
|
||||||
// Subtract with Carry Flag set
|
// Subtract with Carry Flag set
|
||||||
bus.loadProgram(0x38, // SEC
|
bus.loadProgram(0x38, // SEC
|
||||||
0xa9, 0x00, // LDA #$00
|
0xa9, 0x00, // LDA #$00
|
||||||
@@ -757,7 +757,7 @@ public class CpuImmediateModeTest extends TestCase {
|
|||||||
assertFalse(cpu.getCarryFlag());
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void test_SBC_DecimalMode() {
|
public void test_SBC_DecimalMode() {
|
||||||
bus.loadProgram(0xf8,
|
bus.loadProgram(0xf8,
|
||||||
0xa9, 0x00,
|
0xa9, 0x00,
|
||||||
@@ -771,7 +771,7 @@ public class CpuImmediateModeTest extends TestCase {
|
|||||||
assertTrue(cpu.getDecimalModeFlag());
|
assertTrue(cpu.getDecimalModeFlag());
|
||||||
|
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
|
|
||||||
bus.loadProgram(0xf8,
|
bus.loadProgram(0xf8,
|
||||||
0xa9, 0x99,
|
0xa9, 0x99,
|
||||||
0xe9, 0x01);
|
0xe9, 0x01);
|
||||||
@@ -784,7 +784,7 @@ public class CpuImmediateModeTest extends TestCase {
|
|||||||
assertTrue(cpu.getDecimalModeFlag());
|
assertTrue(cpu.getDecimalModeFlag());
|
||||||
|
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
|
|
||||||
bus.loadProgram(0xf8,
|
bus.loadProgram(0xf8,
|
||||||
0xa9, 0x50,
|
0xa9, 0x50,
|
||||||
0xe9, 0x01);
|
0xe9, 0x01);
|
||||||
@@ -796,9 +796,9 @@ public class CpuImmediateModeTest extends TestCase {
|
|||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getDecimalModeFlag());
|
assertTrue(cpu.getDecimalModeFlag());
|
||||||
|
|
||||||
|
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
|
|
||||||
bus.loadProgram(0xf8, // SED
|
bus.loadProgram(0xf8, // SED
|
||||||
0xa9, 0x02, // LDA #$02
|
0xa9, 0x02, // LDA #$02
|
||||||
0xe9, 0x01); // SBC #$01
|
0xe9, 0x01); // SBC #$01
|
||||||
@@ -809,9 +809,9 @@ public class CpuImmediateModeTest extends TestCase {
|
|||||||
assertFalse(cpu.getOverflowFlag());
|
assertFalse(cpu.getOverflowFlag());
|
||||||
assertTrue(cpu.getZeroFlag());
|
assertTrue(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getDecimalModeFlag());
|
assertTrue(cpu.getDecimalModeFlag());
|
||||||
|
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
|
|
||||||
bus.loadProgram(0xf8, // SED
|
bus.loadProgram(0xf8, // SED
|
||||||
0xa9, 0x10, // LDA #$10
|
0xa9, 0x10, // LDA #$10
|
||||||
0xe9, 0x11); // SBC #$11
|
0xe9, 0x11); // SBC #$11
|
||||||
@@ -822,7 +822,7 @@ public class CpuImmediateModeTest extends TestCase {
|
|||||||
assertFalse(cpu.getOverflowFlag());
|
assertFalse(cpu.getOverflowFlag());
|
||||||
assertFalse(cpu.getZeroFlag());
|
assertFalse(cpu.getZeroFlag());
|
||||||
assertTrue(cpu.getDecimalModeFlag());
|
assertTrue(cpu.getDecimalModeFlag());
|
||||||
|
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
|
|
||||||
bus.loadProgram(0x38, // SEC
|
bus.loadProgram(0x38, // SEC
|
||||||
@@ -838,7 +838,7 @@ public class CpuImmediateModeTest extends TestCase {
|
|||||||
assertTrue(cpu.getDecimalModeFlag());
|
assertTrue(cpu.getDecimalModeFlag());
|
||||||
|
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
|
|
||||||
bus.loadProgram(0x38, // SEC
|
bus.loadProgram(0x38, // SEC
|
||||||
0xf8, // SED
|
0xf8, // SED
|
||||||
0xa9, 0x00, // LDA #$00
|
0xa9, 0x00, // LDA #$00
|
||||||
|
|||||||
@@ -346,4 +346,13 @@ public class CpuTest extends TestCase {
|
|||||||
assertFalse(cpu.getOverflowFlag());
|
assertFalse(cpu.getOverflowFlag());
|
||||||
assertFalse(cpu.getNegativeFlag());
|
assertFalse(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testAddress() {
|
||||||
|
assertEquals(0xf1ea, cpu.address(0xea, 0xf1));
|
||||||
|
assertEquals(0x00ea, cpu.address(0xea, 0x00));
|
||||||
|
assertEquals(0xf100, cpu.address(0x00, 0xf1));
|
||||||
|
assertEquals(0x1234, cpu.address(0x34, 0x12));
|
||||||
|
assertEquals(0xffff, cpu.address(0xff, 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package com.loomcom.symon;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
public class CpuUtilsTest extends TestCase {
|
|
||||||
|
|
||||||
public void testAddress() {
|
|
||||||
assertEquals(0xf1ea, CpuUtils.address(0xea, 0xf1));
|
|
||||||
assertEquals(0x00ea, CpuUtils.address(0xea, 0x00));
|
|
||||||
assertEquals(0xf100, CpuUtils.address(0x00, 0xf1));
|
|
||||||
assertEquals(0x1234, CpuUtils.address(0x34, 0x12));
|
|
||||||
assertEquals(0xffff, CpuUtils.address(0xff, 0xff));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -34,41 +34,241 @@ public class CpuZeroPageModeTest extends TestCase {
|
|||||||
/*
|
/*
|
||||||
* The following opcodes are tested for correctness in this file:
|
* The following opcodes are tested for correctness in this file:
|
||||||
*
|
*
|
||||||
* ADC - $65
|
* ORA - $05
|
||||||
* AND - $25
|
|
||||||
* ASL - $06
|
* ASL - $06
|
||||||
* BIT - $24
|
* BIT - $24
|
||||||
* CMP - $c5
|
* AND - $25
|
||||||
*
|
|
||||||
* CPX - $e4
|
|
||||||
* CPY - $c4
|
|
||||||
* DEC - $c6
|
|
||||||
* EOR - $45
|
|
||||||
* INC - $e6
|
|
||||||
*
|
|
||||||
* LDA - $a5
|
|
||||||
* LDX - $a6
|
|
||||||
* LDY - $a4
|
|
||||||
* LSR - $46
|
|
||||||
* ORA - $05
|
|
||||||
*
|
|
||||||
* ROL - $26
|
* ROL - $26
|
||||||
|
*
|
||||||
|
* EOR - $45
|
||||||
|
* LSR - $46
|
||||||
|
* ADC - $65
|
||||||
* ROR - $66
|
* ROR - $66
|
||||||
* SBC - $e5
|
* STY - $84
|
||||||
|
*
|
||||||
* STA - $85
|
* STA - $85
|
||||||
* STX - $86
|
* STX - $86
|
||||||
*
|
* LDY - $a4
|
||||||
* STY - $84
|
* LDA - $a5
|
||||||
*
|
* LDX - $a6
|
||||||
|
*
|
||||||
|
* CPY - $c4
|
||||||
|
* CMP - $c5
|
||||||
|
* DEC - $c6
|
||||||
|
* CPX - $e4
|
||||||
|
* SBC - $e5
|
||||||
|
*
|
||||||
|
* INC - $e6
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* ADC - Add with Carry - $88 */
|
/* ORA - Logical Inclusive OR - $05 */
|
||||||
public void test_ADC() {
|
public void test_ORA() {
|
||||||
|
// Set some initial values in zero page.
|
||||||
|
bus.write(0x0000, 0x00);
|
||||||
|
bus.write(0x0002, 0x11);
|
||||||
|
bus.write(0x0004, 0x22);
|
||||||
|
bus.write(0x0008, 0x44);
|
||||||
|
bus.write(0x0010, 0x88);
|
||||||
|
|
||||||
|
bus.loadProgram(0x05, 0x00, // ORA $00
|
||||||
|
0x05, 0x02, // ORA $02
|
||||||
|
0x05, 0x04, // ORA $04
|
||||||
|
0x05, 0x08, // ORA $08
|
||||||
|
0x05, 0x10); // ORA $10
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00, cpu.getAccumulator());
|
||||||
|
assertTrue(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x11, cpu.getAccumulator());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x33, cpu.getAccumulator());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x77, cpu.getAccumulator());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0xff, cpu.getAccumulator());
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertTrue(cpu.getNegativeFlag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ASL - Arithmetic Shift Left - $06 */
|
||||||
|
public void test_ASL() {
|
||||||
|
bus.write(0x0000, 0x00);
|
||||||
|
bus.write(0x0001, 0x01);
|
||||||
|
bus.write(0x0002, 0x02);
|
||||||
|
bus.write(0x0003, 0x44);
|
||||||
|
bus.write(0x0004, 0x80);
|
||||||
|
|
||||||
|
bus.loadProgram(0x06, 0x00,
|
||||||
|
0x06, 0x01,
|
||||||
|
0x06, 0x02,
|
||||||
|
0x06, 0x03,
|
||||||
|
0x06, 0x04);
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00, bus.read(0x0000));
|
||||||
|
assertTrue(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x02, bus.read(0x0001));
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x04, bus.read(0x0002));
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x88, bus.read(0x0003));
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
assertFalse(cpu.getCarryFlag());
|
||||||
|
|
||||||
|
cpu.step();
|
||||||
|
assertEquals(0x00, bus.read(0x0004));
|
||||||
|
assertTrue(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
assertTrue(cpu.getCarryFlag());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BIT - Bit Test - $24 */
|
||||||
|
public void test_BIT() {
|
||||||
|
bus.write(0x0000, 0xc0);
|
||||||
|
|
||||||
|
bus.loadProgram(0xa9, 0x01, // LDA #$01
|
||||||
|
0x24, 0x00, // BIT $00
|
||||||
|
|
||||||
|
0xa9, 0x0f, // LDA #$0f
|
||||||
|
0x24, 0x00, // BIT $00
|
||||||
|
|
||||||
|
0xa9, 0x40, // LDA #$40
|
||||||
|
0x24, 0x00, // BIT $00
|
||||||
|
|
||||||
|
0xa9, 0x80, // LDA #$80
|
||||||
|
0x24, 0x00, // BIT $00
|
||||||
|
|
||||||
|
0xa9, 0xc0, // LDA #$c0
|
||||||
|
0x24, 0x00, // BIT $00
|
||||||
|
|
||||||
|
0xa9, 0xff, // LDA #$ff
|
||||||
|
0x24, 0x00); // BIT $00
|
||||||
|
|
||||||
|
cpu.step(2);
|
||||||
|
assertTrue(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
assertFalse(cpu.getOverflowFlag());
|
||||||
|
|
||||||
|
cpu.step(2);
|
||||||
|
assertTrue(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
assertFalse(cpu.getOverflowFlag());
|
||||||
|
|
||||||
|
cpu.step(2);
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertFalse(cpu.getNegativeFlag());
|
||||||
|
assertTrue(cpu.getOverflowFlag());
|
||||||
|
|
||||||
|
cpu.step(2);
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
assertFalse(cpu.getOverflowFlag());
|
||||||
|
|
||||||
|
cpu.step(2);
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
assertTrue(cpu.getOverflowFlag());
|
||||||
|
|
||||||
|
cpu.step(2);
|
||||||
|
assertFalse(cpu.getZeroFlag());
|
||||||
|
assertTrue(cpu.getNegativeFlag());
|
||||||
|
assertTrue(cpu.getOverflowFlag());
|
||||||
|
}
|
||||||
|
|
||||||
/* AND - Logical AND - $25 */
|
/* AND - Logical AND - $25 */
|
||||||
public void test_AND() {
|
public void test_AND() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ROL - Rotate Left - $26 */
|
||||||
|
public void test_ROL() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EOR - Exclusive OR - $45 */
|
||||||
|
public void test_EOR() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LSR - Logical Shift Right - $46 */
|
||||||
|
public void test_LSR() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ADC - Add with Carry - $65 */
|
||||||
|
public void test_ADC() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ROR - Rotate Right - $66 */
|
||||||
|
public void test_ROR() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STY - Store Y Register - $84 */
|
||||||
|
public void test_STY() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STA - Store Accumulator - $85 */
|
||||||
|
public void test_STA() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STX - Store X Register - $86 */
|
||||||
|
public void test_STX() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LDY - Load Y Register - $a4 */
|
||||||
|
public void test_LDY() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LDA - Load Accumulator - $a5 */
|
||||||
|
public void test_LDA() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LDX - Load X Register - $a6 */
|
||||||
|
public void test_LDX() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CPY - Compare Y Register - $c4 */
|
||||||
|
public void test_CPY() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CMP - Compare Accumulator - $c5 */
|
||||||
|
public void test_CMP() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DEC - Decrement Memory Location - $c6 */
|
||||||
|
public void test_DEC() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CPX - Compare X Register - $e4 */
|
||||||
|
public void test_CPX() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SBC - Subtract with Carry - $e5 */
|
||||||
|
public void test_SBC() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* INC - Increment Memory Location - $e6 */
|
||||||
|
public void test_INC() {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user