From b42780173a365839c33d3d3f6f2033bd79c73a89 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 12 Apr 2021 20:54:10 -0400 Subject: [PATCH] Establishes that there really is no Read4 and Read4Pre distinction. Will finish these unit tests, then clean up. --- .../Clock SignalTests/Z80ContentionTests.mm | 128 ++++++++++++++++++ Processors/Z80/Implementation/Z80Storage.cpp | 2 +- 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/OSBindings/Mac/Clock SignalTests/Z80ContentionTests.mm b/OSBindings/Mac/Clock SignalTests/Z80ContentionTests.mm index 0948f77bc..5408b1808 100644 --- a/OSBindings/Mac/Clock SignalTests/Z80ContentionTests.mm +++ b/OSBindings/Mac/Clock SignalTests/Z80ContentionTests.mm @@ -782,4 +782,132 @@ struct ContentionCheck { } } +- (void)testSETRESbHLind { + for(const auto &sequence : std::vector>{ + // SET b, (HL) + {0xcb, 0xc6}, {0xcb, 0xce}, {0xcb, 0xd6}, {0xcb, 0xde}, + {0xcb, 0xe6}, {0xcb, 0xee}, {0xcb, 0xf6}, {0xcb, 0xfe}, + + // RES b, (HL) + {0xcb, 0x86}, {0xcb, 0x8e}, {0xcb, 0x96}, {0xcb, 0x9e}, + {0xcb, 0xa6}, {0xcb, 0xae}, {0xcb, 0xb6}, {0xcb, 0xbe}, + + // SRO (HL) + {0xcb, 0x06}, {0xcb, 0x0e}, {0xcb, 0x16}, {0xcb, 0x1e}, + {0xcb, 0x26}, {0xcb, 0x2e}, {0xcb, 0x36}, {0xcb, 0x3e}, + }) { + CapturingZ80 z80(sequence); + z80.run_for(15); + + [self validate48Contention:{ + {initial_pc, 4}, + {initial_pc+1, 4}, + {initial_bc_de_hl, 3}, + {initial_bc_de_hl, 1}, + {initial_bc_de_hl, 3}, + } z80:z80]; + [self validatePlus3Contention:{ + {initial_pc, 4}, + {initial_pc+1, 4}, + {initial_bc_de_hl, 4}, + {initial_bc_de_hl, 3}, + } z80:z80]; + } +} + +- (void)testINCDECiin { + constexpr uint8_t offset = 0x10; + for(const auto &sequence : std::vector>{ + // INC (ii+n) + {0xdd, 0x34, offset}, {0xfd, 0x34, offset}, + + // DEC (ii+n) + {0xdd, 0x35, offset}, {0xfd, 0x35, offset}, + }) { + CapturingZ80 z80(sequence); + z80.run_for(23); + + [self validate48Contention:{ + {initial_pc, 4}, + {initial_pc+1, 4}, + {initial_pc+2, 3}, + {initial_pc+2, 1}, + {initial_pc+2, 1}, + {initial_pc+2, 1}, + {initial_pc+2, 1}, + {initial_pc+2, 1}, + {initial_ix_iy + offset, 3}, + {initial_ix_iy + offset, 1}, + {initial_ix_iy + offset, 3}, + } z80:z80]; + [self validatePlus3Contention:{ + {initial_pc, 4}, + {initial_pc+1, 4}, + {initial_pc+2, 8}, + {initial_ix_iy + offset, 4}, + {initial_ix_iy + offset, 3}, + } z80:z80]; + } +} + +- (void)testSETRESiin { + constexpr uint8_t offset = 0x10; + for(const auto &sequence : std::vector>{ + // SET b, (ii+n) + {0xdd, 0xcb, offset, 0xc6}, {0xdd, 0xcb, offset, 0xce}, + {0xdd, 0xcb, offset, 0xd6}, {0xdd, 0xcb, offset, 0xde}, + {0xdd, 0xcb, offset, 0xe6}, {0xdd, 0xcb, offset, 0xee}, + {0xdd, 0xcb, offset, 0xf6}, {0xdd, 0xcb, offset, 0xfe}, + + {0xfd, 0xcb, offset, 0xc6}, {0xfd, 0xcb, offset, 0xce}, + {0xfd, 0xcb, offset, 0xd6}, {0xfd, 0xcb, offset, 0xde}, + {0xfd, 0xcb, offset, 0xe6}, {0xfd, 0xcb, offset, 0xee}, + {0xfd, 0xcb, offset, 0xf6}, {0xfd, 0xcb, offset, 0xfe}, + + // RES b, (ii+n) + {0xdd, 0xcb, offset, 0x86}, {0xdd, 0xcb, offset, 0x8e}, + {0xdd, 0xcb, offset, 0x96}, {0xdd, 0xcb, offset, 0x9e}, + {0xdd, 0xcb, offset, 0xa6}, {0xdd, 0xcb, offset, 0xae}, + {0xdd, 0xcb, offset, 0xb6}, {0xdd, 0xcb, offset, 0xbe}, + + {0xfd, 0xcb, offset, 0x86}, {0xfd, 0xcb, offset, 0x8e}, + {0xfd, 0xcb, offset, 0x96}, {0xfd, 0xcb, offset, 0x9e}, + {0xfd, 0xcb, offset, 0xa6}, {0xfd, 0xcb, offset, 0xae}, + {0xfd, 0xcb, offset, 0xb6}, {0xfd, 0xcb, offset, 0xbe}, + + // SRO (ii+n) + {0xdd, 0xcb, offset, 0x06}, {0xdd, 0xcb, offset, 0x0e}, + {0xdd, 0xcb, offset, 0x16}, {0xdd, 0xcb, offset, 0x1e}, + {0xdd, 0xcb, offset, 0x26}, {0xdd, 0xcb, offset, 0x2e}, + {0xdd, 0xcb, offset, 0x36}, {0xdd, 0xcb, offset, 0x3e}, + + {0xfd, 0xcb, offset, 0x06}, {0xfd, 0xcb, offset, 0x0e}, + {0xfd, 0xcb, offset, 0x16}, {0xfd, 0xcb, offset, 0x1e}, + {0xfd, 0xcb, offset, 0x26}, {0xfd, 0xcb, offset, 0x2e}, + {0xfd, 0xcb, offset, 0x36}, {0xfd, 0xcb, offset, 0x3e}, + }) { + CapturingZ80 z80(sequence); + z80.run_for(23); + + [self validate48Contention:{ + {initial_pc, 4}, + {initial_pc+1, 4}, + {initial_pc+2, 3}, + {initial_pc+3, 3}, + {initial_pc+3, 1}, + {initial_pc+3, 1}, + {initial_ix_iy + offset, 3}, + {initial_ix_iy + offset, 1}, + {initial_ix_iy + offset, 3}, + } z80:z80]; + [self validatePlus3Contention:{ + {initial_pc, 4}, + {initial_pc+1, 4}, + {initial_pc+2, 3}, + {initial_pc+3, 5}, + {initial_ix_iy + offset, 4}, + {initial_ix_iy + offset, 3}, + } z80:z80]; + } +} @end diff --git a/Processors/Z80/Implementation/Z80Storage.cpp b/Processors/Z80/Implementation/Z80Storage.cpp index 1a11b6712..92a52ca01 100644 --- a/Processors/Z80/Implementation/Z80Storage.cpp +++ b/Processors/Z80/Implementation/Z80Storage.cpp @@ -55,7 +55,7 @@ ProcessorStorage::ProcessorStorage() { // Read4Pre is a four-cycle read that has to do something after reading: 1.5 cycles, then check the wait line, then 1.5 cycles, then a 1-cycle internal operation; // Read5 is a five-cycle read: 1.5 cycles, two wait cycles, check the wait line, 1.5 cycles. #define Read3(addr, val) BusOp(ReadStart(addr, val)), BusOp(ReadWait(2, addr, val, true)), BusOp(ReadEnd(addr, val)) -#define Read4(addr, val) BusOp(ReadStart(addr, val)), BusOp(ReadWait(2, addr, val, false)), BusOp(ReadWait(2, addr, val, true)), BusOp(ReadEnd(addr, val)) +#define Read4(addr, val) BusOp(ReadStart(addr, val)), BusOp(ReadWait(2, addr, val, true)), BusOp(ReadEnd(addr, val)), InternalOperation(2) #define Read4Pre(addr, val) BusOp(ReadStart(addr, val)), BusOp(ReadWait(2, addr, val, true)), BusOp(ReadEnd(addr, val)), InternalOperation(2) #define Read5(addr, val) BusOp(ReadStart(addr, val)), BusOp(ReadWait(2, addr, val, true)), BusOp(ReadEnd(addr, val)), InternalOperation(4)