68 lines
2.1 KiB
Go
68 lines
2.1 KiB
Go
package z80
|
|
|
|
import "testing"
|
|
|
|
// Basic conditional flow timing: JR cc, RET cc, CALL cc
|
|
func TestJRcc_RETcc_CALLcc_Timing_Basics(t *testing.T) {
|
|
cpu, mem, _ := testCPU()
|
|
|
|
// Make a small program space
|
|
// OR A (keeps Z=0), then JR Z,+2 (not taken), then XOR A (Z=1), JR NZ,+2 (not taken), JR Z,+2 (taken)
|
|
loadProgram(cpu, mem, 0x0000,
|
|
0xB7, // OR A (A starts FF; Z=0)
|
|
0x28, 0x02, // JR Z, +2 -> not taken (7)
|
|
0xAF, // XOR A -> A=0 Z=1
|
|
0x20, 0x02, // JR NZ, +2 -> not taken now (7)
|
|
0x28, 0x02, // JR Z, +2 -> taken (12)
|
|
0x00, 0x00,
|
|
)
|
|
cpu.A = 0xff // HUMAN: my cpu not set A to FF
|
|
mustStep(t, cpu)
|
|
assertEq(t, mustStep(t, cpu), 7, "JR Z not taken")
|
|
mustStep(t, cpu)
|
|
assertEq(t, mustStep(t, cpu), 7, "JR NZ not taken")
|
|
assertEq(t, mustStep(t, cpu), 12, "JR Z taken")
|
|
|
|
// RET cc: make a simple CALL, then set flags so condition is false/true
|
|
cpu, mem, _ = testCPU()
|
|
cpu.SP = 0xFFFE
|
|
// CALL next; place RET C (D8) and RET NC (D0) in two spots and test both timings
|
|
loadProgram(cpu, mem, 0x0000, 0xCD, 0x06, 0x00) // CALL 0006
|
|
mem.WriteByte(0x0006, 0xD8) // RET C
|
|
cpu.SetFlag(FLAG_C, false)
|
|
mustStep(t, cpu) // CALL
|
|
// RET C (not taken): 5 cycles
|
|
assertEq(t, mustStep(t, cpu), 5, "RET C not taken")
|
|
|
|
// Put RET NC; set C so taken path triggers
|
|
loadProgram(cpu, mem, cpu.PC, 0xCD, 0x06, 0x00)
|
|
mem.WriteByte(0x0006, 0xD0) // RET NC
|
|
cpu.SetFlag(FLAG_C, false)
|
|
pcBefore := cpu.PC
|
|
mustStep(t, cpu) // CALL
|
|
// RET NC (taken): 11 cycles
|
|
c := mustStep(t, cpu)
|
|
assertEq(t, c, 11, "RET NC taken")
|
|
assertEq(t, cpu.PC, pcBefore+3, "Returned to next instruction after CALL")
|
|
}
|
|
|
|
func TestDJNZ_Taken(t *testing.T) {
|
|
cpu, mem, _ := testCPU()
|
|
loadProgram(cpu, mem, 0x0000,
|
|
0x06, 0x02, // LD B,2
|
|
0x10, 0x02, // DJNZ +2 (B->1, taken)
|
|
)
|
|
mustStep(t, cpu) // LD B,2
|
|
assertEq(t, mustStep(t, cpu), 13, "DJNZ taken")
|
|
}
|
|
|
|
func TestDJNZ_NotTaken(t *testing.T) {
|
|
cpu, mem, _ := testCPU()
|
|
loadProgram(cpu, mem, 0x0000,
|
|
0x06, 0x01, // LD B,1
|
|
0x10, 0x02, // DJNZ +2 (B->0, not taken)
|
|
)
|
|
mustStep(t, cpu) // LD B,1
|
|
assertEq(t, mustStep(t, cpu), 8, "DJNZ not taken")
|
|
}
|