Starting emulator - help with basics of Z80 timing needed
Starting emulator - help with basics of Z80 timing needed
Hello,
I am planning to start my own Spectrum emulator (yes, another one is just what is needed ).
The first step should be emulating the CPU. So, I started to read Zilog's manual and other docs found on http://www.z80.info/, in order to implement instructions.
Now, let me explain what I'm confused with:
1. Z80 manual says in chapter Timing that fetching an instruction from memory takes 4 clock cycles (T-states); otherwise, reading a byte from memory takes 3 T-states.
2. Then, when explaining particular instructions, with each instruction there is documented how many T-states the instruction takes.
For example, the manual says that EX AF, AF' takes 4 T-states.
My question is -- does the number of T-cycles mentioned with instruction includes instruction fetching, or it is just instruction processing, which should be added to first four T-states taken when fetching the instruction from memory.
So, which of the following is correct:
- fetching op-code 0x08 (EX AF, AF') takes four T-states, and then processing this instruction takes another four, making eight T-states in total.
OR
- fetching and processing this instruction takes just four T-states?
I am planning to start my own Spectrum emulator (yes, another one is just what is needed ).
The first step should be emulating the CPU. So, I started to read Zilog's manual and other docs found on http://www.z80.info/, in order to implement instructions.
Now, let me explain what I'm confused with:
1. Z80 manual says in chapter Timing that fetching an instruction from memory takes 4 clock cycles (T-states); otherwise, reading a byte from memory takes 3 T-states.
2. Then, when explaining particular instructions, with each instruction there is documented how many T-states the instruction takes.
For example, the manual says that EX AF, AF' takes 4 T-states.
My question is -- does the number of T-cycles mentioned with instruction includes instruction fetching, or it is just instruction processing, which should be added to first four T-states taken when fetching the instruction from memory.
So, which of the following is correct:
- fetching op-code 0x08 (EX AF, AF') takes four T-states, and then processing this instruction takes another four, making eight T-states in total.
OR
- fetching and processing this instruction takes just four T-states?
Re: Starting emulator - help with basics of Z80 timing needed
EX AF,AF' takes 4 t-states in total to fetch and process.
Re: Starting emulator - help with basics of Z80 timing needed
The tricky bit is managing on which ticks in the instruction a memory read or write actually happens, so you can time that with the memory contention that goes on in the RAM when read by the ULA to generate the display. It's not beginner stuff, but if you don't allow for it from the start, you'll find it hard to add in later.
- Einar Saukas
- Bugaboo
- Posts: 3070
- Joined: Wed Nov 15, 2017 2:48 pm
Re: Starting emulator - help with basics of Z80 timing needed
Thank you.
Joefish wrote: ↑Fri Aug 16, 2019 2:21 pm The tricky bit is managing on which ticks in the instruction a memory read or write actually happens, so you can time that with the memory contention that goes on in the RAM when read by the ULA to generate the display. It's not beginner stuff, but if you don't allow for it from the start, you'll find it hard to add in later.
Thank you. Hopefully, I'll be able to cope with the contention...Einar Saukas wrote: ↑Fri Aug 16, 2019 2:28 pm Total T-states:
https://www.ime.usp.br/~einar/z80table/
Partial T-states:
https://www.worldofspectrum.org/faq/ref ... erence.htm
Definitely I should try to implement partial timings from the start.
Not a beginner's task either. When I plunge into memory/i-o contention, then time will come for thinking of a cool name.
Re: Starting emulator - help with basics of Z80 timing needed
Now, to be able to later implement memory contention, I am reading the table with partial timings, as Einar pointed to - https://www.worldofspectrum.org/faq/ref ... Contention.
I am not sure whether everything is quite clear to me.
Could you please take a look at this. I will try to show how I understand the flow of instruction "JR 25". Its purpose is to add 25 to program counter.
Let's see timings for "JR n", that is: pc:4,pc+1:3,pc+1:1 x 5
Especially I need the third part clarified -- pc+1:1 x 5
Does it mean that T-states should be incremented five times by 1 and each time check if delay should be inserted?
I don't know how else to understand this, but still...
So, let's say that we have JR 25, somewhere in lower 16 bit of RAM and PC gets to this position (eg. PC = 25000), and that we have 14330 (14335 minus 5) t-states passed since ULA's interruption.
Now, will this be the correct flow (whenever t-states are mentioned, it means t-states passed since interruption started):
1. pc:4 -- no delay inserted, as we are below the 14335 t-states.
- read the (first byte of) instruction from memory
- increase T-states by 4, it is now 14334.
- increase PC by 1.
2. pc+1: 3
- pc (which was incremented in 1.) is now 25001, so still we are in lower ram, but T-states are 14334, so still bellow 14335 -- no delay.
- read a byte from memory (it is 25 in our example), but still do not use it to change the content of PC.
- increase T-states by 3, it is now 14337
- increase PC by 1.
3. pc+1:1 x 5
PC is 25002 (we still wait with adding 25 to it)
now loop five times:
first pass:
- t-states are 14337, according to table insert 4 t-states delay, t-states are now 14341,
- increase t-states by 1. t-states are now 14342
second pass:
- t-states are 14342, no delay
- increase t-states, now 14343
third pass:
- t-states are 14343, insert 6 t-states, now 14349
- increase t-states, now 14350
...
etc.
4. Finally, increase PC by 25 (as that is the meaning of JR 25 instruction), so it is now 25027.
Is this correct?
I know I might have understood wrongly who knows what, so please read it carefully.
I am not sure whether everything is quite clear to me.
Could you please take a look at this. I will try to show how I understand the flow of instruction "JR 25". Its purpose is to add 25 to program counter.
Let's see timings for "JR n", that is: pc:4,pc+1:3,pc+1:1 x 5
Especially I need the third part clarified -- pc+1:1 x 5
Does it mean that T-states should be incremented five times by 1 and each time check if delay should be inserted?
I don't know how else to understand this, but still...
So, let's say that we have JR 25, somewhere in lower 16 bit of RAM and PC gets to this position (eg. PC = 25000), and that we have 14330 (14335 minus 5) t-states passed since ULA's interruption.
Now, will this be the correct flow (whenever t-states are mentioned, it means t-states passed since interruption started):
1. pc:4 -- no delay inserted, as we are below the 14335 t-states.
- read the (first byte of) instruction from memory
- increase T-states by 4, it is now 14334.
- increase PC by 1.
2. pc+1: 3
- pc (which was incremented in 1.) is now 25001, so still we are in lower ram, but T-states are 14334, so still bellow 14335 -- no delay.
- read a byte from memory (it is 25 in our example), but still do not use it to change the content of PC.
- increase T-states by 3, it is now 14337
- increase PC by 1.
3. pc+1:1 x 5
PC is 25002 (we still wait with adding 25 to it)
now loop five times:
first pass:
- t-states are 14337, according to table insert 4 t-states delay, t-states are now 14341,
- increase t-states by 1. t-states are now 14342
second pass:
- t-states are 14342, no delay
- increase t-states, now 14343
third pass:
- t-states are 14343, insert 6 t-states, now 14349
- increase t-states, now 14350
...
etc.
4. Finally, increase PC by 25 (as that is the meaning of JR 25 instruction), so it is now 25027.
Is this correct?
I know I might have understood wrongly who knows what, so please read it carefully.
Re: Starting emulator - help with basics of Z80 timing needed
Looks like you understand the concept of how to implement the contention just fine but the pc:n (or reg:n entries in some opcodes) are relative to the starting values of the registers at the start of opcode execution.
Hence your pc+1:1x5 will be using pc+1 as meaning 25001 rather than as being 25002 in your write-up.
Hence your pc+1:1x5 will be using pc+1 as meaning 25001 rather than as being 25002 in your write-up.
Re: Starting emulator - help with basics of Z80 timing needed
Or another way you can think of it in the opcode breakdowns is to always try to think what is on the address bus at any moment in time as the ULA will contend based on the address bus contents rather than any specific register pair. So your pc+1 address fetching the offset (25 in your example) is the address of that offset in memory on which contention will be based. Does that make sense?
Re: Starting emulator - help with basics of Z80 timing needed
I am in the middle of looking at generating timing sensitive code (SAM MOD player) and am surprised by the pc:1 x 5 contention on the last 5 t-states.
Based on http://www.z80.info/z80ins.txt
JR e 2 OCF(4) OD(3) IO(5)
So that's
- 4 t-state opcode fetch (memory access -> contended)
- 3 t-state opcode data (memory access -> contended)
- 5 t-state internal operation.
I did not expect an internal operation on the z80 to be contended?
Based on http://www.z80.info/z80ins.txt
JR e 2 OCF(4) OD(3) IO(5)
So that's
- 4 t-state opcode fetch (memory access -> contended)
- 3 t-state opcode data (memory access -> contended)
- 5 t-state internal operation.
I did not expect an internal operation on the z80 to be contended?
Re: Starting emulator - help with basics of Z80 timing needed
And if I am reading what SimCoupe is doing correctly, https://github.com/simonowen/simcoupe/b ... e/Z80ops.h is simply adding 5 to the CycleCounter.
Re: Starting emulator - help with basics of Z80 timing needed
They're contended because the ULA doesn't look at the control bus for MREQ signals and the like and only respond to what it sees on the address bus which is the last address latched, or the address of the JR offset byte in this case.
The +2a/+3 does acknowledge these signals and those final 5 t-states are not contended.
Re: Starting emulator - help with basics of Z80 timing needed
Aha - it's an (old) Speccy thing, so I am going to assume that the SAM Coupé is also sensible enough to leave them uncontended.Woodster wrote: ↑Sun Aug 18, 2019 9:45 amThey're contended because the ULA doesn't look at the control bus for MREQ signals and the like and only respond to what it sees on the address bus which is the last address latched, or the address of the JR offset byte in this case.
The +2a/+3 does acknowledge these signals and those final 5 t-states are not contended.
Thank you for clearing that up.
- DouglasReynholm
- Manic Miner
- Posts: 347
- Joined: Wed Feb 20, 2019 8:38 pm
- Ast A. Moore
- Rick Dangerous
- Posts: 2640
- Joined: Mon Nov 13, 2017 3:16 pm
Re: Starting emulator - help with basics of Z80 timing needed
“You’ve got spunk and balls, and I like that in a woman.”DouglasReynholm wrote: ↑Sun Aug 18, 2019 10:45 am Best I can do at short notice, take it or leave it.
Every man should plant a tree, build a house, and write a ZX Spectrum game.
Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Re: Starting emulator - help with basics of Z80 timing needed
Dobro došao Zorane.
Glad to see some ex-yu Spectrum fans here and look forward to your future emulator.
Once again, welcome to this great forum.