-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MCLZ8 - Some opcodes should take 5 cycles (for instance, DJNZ) and not only 4 cycles in M-cycle M1 #11
Comments
Here a list of instructions having potential inaccurate T-state points when accessing memory or I/O port :
** T-states ** are the problematic ones that should not be shifted in the end of instruction in mode 0 and 1 (and maybe 2) to be fully accurate with genuine Z80 timings. |
The situation is even worse. MCLZ80 is not accurate in T-states even in mode 0 !
Basically, using total cycles in tables is not good. Better handling extra M-cycle in the opcode functions (opcode_0xXX) to get a more accurate and precise timing.
with : Also note that you must check /INT on the rising edge of the last T-state of the last M-cycle of the instruction, so that's why I call both wait_for_CLK_rising_edge() and wait_for_CLK_falling_edge() during the extra cycles. Case of DJNZ n :
And so on... |
Thank you for spending so much of your time analyzing the MCLZ8. The goal of the project was not to create a cycle-perfect Z80 clone, although it potentially could be if there was a desire to make it so. The experiment was to create an opcode-correct emulator running on a fast microcontroller which could be a drop-in replacement for most Z80 motherboards. With this goal achieved I have moved on to other projects. Updating the MCLZ8 to be a cycle-perfect drop-in emulator could be an enjoyable project if someone wanted to pursue it.
…________________________________
From: hlide ***@***.***>
Sent: Tuesday, February 28, 2023 5:35 AM
To: MicroCoreLabs/Projects ***@***.***>
Cc: Subscribed ***@***.***>
Subject: Re: [MicroCoreLabs/Projects] MCLZ8 - Some opcodes should take 5 cycles (for instance, DJNZ) and not only 4 cycles in M-cycle M1 (Issue #11)
The situation is even worse.
MCLZ80 is not accurate in T-states even in mode 0 !
1. ED opcodes timing are all wrong. For instance, IM 1 is executed in 11 T-states (4,7) instead of 7 T-states (4,3) because of the way clock_counter is accumulated.
2. I didn't check for CB and DD/FD tables but there are chances they are wrong if handled in the same way as ED tables.
3. CALL/RET/JR/RST instructions have too many cycles. For instance, a CALL took 24 T-states when taken (4,3,4,3,3,7) instead of 17 T-states (4,3,4,3,3).
Basically, using total cycles in tables is not good. Better handling extra M-cycle in the opcode functions (opcode_0xXX) to get a more accurate and precise timing.
void opcode_0xED56() { /* (4) */ register_im=1; /* (4) */ Extra_Cycles< 3 >(); /* (4, 3) */ return; } // IM1
with :
template < uint8_t cycles > // compile-time optimization inline void Extra_Cycles() { if (bus_mode < 3) { for (uint8_t i=cycles; --i;) wait_for_CLK_rising_edge(), wait_for_CLK_falling_edge(); } }
Clock_counter and clock tables not being used any longer.
Also not, you must check /INT on the rising edge of the last T-state of the last M-cycle of the instruction, so that's why I call both wait_for_CLK_rising_edge() and wait_for_CLK_falling_edge() during the extra cycles.
Case of DJNZ n :
void opcode_0x10() { /* (4) */ register_b--; Extra_Cycles< 1 >(); /* (5) */ if (register_b != 0) { Jump_Taken8(); /* (5,3) */ Extra_Cycles< 5 >(); /* (5,3,5) */ } else { Jump_Not_Taken8(); /* (5,3) */ } return; }
And so on...
—
Reply to this email directly, view it on GitHub<#11 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AM4AVEKZDVMETFYLQCFJHT3WZX5KHANCNFSM6AAAAAAUNATDI4>.
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
Projects/MCLZ8/Code/Standard_Z80/MCLZ8.ino
Line 847 in ea66a81
The memory access to the byte for displacement jump (or not) is taken one T-state too early compared to a genuine Z80. For Z80 machines which are very sensitive to /WAIT pattern (e.g: AMSTRAD CPC), it may alter the whole timing and so the behavior of the CPC program counting very much about the cycle accuracy regarding the memory access.
That extra T-state at the end of M1 M-cycle is due to an internal "dec b". In mode 0, the MEMORY READ M-cycle for memory access to displacement byte should happen 5 CLK cycles after M1 M-cycle, not the usual 4 CLK cycles.
See DJNZ: https://www.manualsdir.com/manuals/753749/zilog-z08470.html?page=287
It is not the only instruction to have extra T-states inserted in the middle of the whole instruction T-states.
The text was updated successfully, but these errors were encountered: