Is there a logic to instruction timings?

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
radgeRayden
Posts: 3
Joined: Sun Sep 20, 2020 9:20 am

Is there a logic to instruction timings?

Post by radgeRayden » Sun Sep 20, 2020 9:32 am

This is my first post here, so hi I suppose!

I've started developing a NES emulator for fun. At this point I have it passing nestest (CPU only), but I don't have any time information (so I don't check against that, though I check my output matches every line otherwise). I did this all without reading much on the PPU, and now that I've looked into it I'm getting convinced I can't get away with not having any timing info at all.

The way I've written my instructions is that I have a DSL where I specify each instruction (grouped by mnemonic) with its logic and the different opcodes it uses (by addressing mode), and I have some codegen to take care of the rest. Because of this I could get here much faster and with much less code, but also it means it's a bit less flexible. Now that I need to add instruction timings, I'm afraid I'll have to specify it per opcode (which would be laborious and kind of irk me since I went through all this trouble). So what I want to know is, if the timings work in a very consistent way such that I can specify eg. a base timing for the instruction and then calculate the cycles added by addressing mode, page crossed etc automatically. I haven't come across a succint explanation of this, but maybe I didn't look enough!

User avatar
Dwedit
Posts: 4410
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Is there a logic to instruction timings?

Post by Dwedit » Sun Sep 20, 2020 10:08 am

Each time the 6502 needs to get something from memory, that's 1 additional cycle.
And there's a minimum of 2 cycles for some reason, so the first 2 bytes of the instruction are already available.

Examples
TAX, TXA, ASL A, etc. are all 2 cycles because they don't need any additional memory access

LDA #n is 2 also cycles, because it doesn't grab anything else from memory other than the instruction itself

LDA ZPG is 3 cycles, because it needs to fetch a value from memory.
LDA ABS is 4 cycles, because it needs to fetch an additional byte from the instruction, and then fetch the byte from memory
LDA ABS,X is usually 4 cycles, but can be 5 cycles if it has to correct the high address byte. Usually an extra dummy read doesn't have side effects, so the dummy read is allowed to happen
STA ABS,X is 5 cycles, because you don't want stray writes to a non-corrected address.

LDA (ZPG),Y is usually 5 cycles, but can be 6 if it had to correct the address.
* Fetches 2 bytes for the instruction (2 cycles)
* Fetches 2 bytes for the 16-bit address
* May need to correct the high byte of the address
* Fetches the result byte

Now could address correction have been done without wasting a cycle? Maybe, but that's not how the 6502 was designed.


The page http://nesdev.com/6502_cpu.txt includes a cycle-by-cycle breakdown of each addressing mode, and what it needs to access. So you can do extra penalty cycles and whatever by addressing mode.

Note that games care about when a memory write or read happens (usually the end-time of the instruction), and not the start-time of the instruction, this can help avoid shaky scrolling artifacts.
Last edited by Dwedit on Sun Sep 20, 2020 10:19 am, edited 1 time in total.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!

radgeRayden
Posts: 3
Joined: Sun Sep 20, 2020 9:20 am

Re: Is there a logic to instruction timings?

Post by radgeRayden » Sun Sep 20, 2020 10:18 am

Thank you, this response already helps me a lot. So am I correct in my understanding that for load instructions I can always calculate by how many bytes I need to fetch +additional correction cycle, and store operations will always* correct, so they are also consistent in that regard? This may have been what tripped me up while looking at the references and trying to infer a pattern. Anyway I think with this I can add a flag to indicate whether an instruction loads or writes, and the computer figures it out from there :)

unregistered
Posts: 1126
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: Is there a logic to instruction timings?

Post by unregistered » Mon Sep 21, 2020 1:12 pm

It doesn’t seem that simple to me...

As Dwedit said, lda #n is two cycles; it’s also 2 bytes.

lda zpg is three cycles; but also 2 bytes.

Oooh, you mean you’d start with 2 cycles and add 1 cycle for the byte fetched from memory. :)

Though, you’d have to add another cycle for the high byte used in the byte fetch for lda abs... it’s 4 cycles and 3 bytes.

Hope that clarifies... :)

User avatar
Quietust
Posts: 1686
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: Is there a logic to instruction timings?

Post by Quietust » Mon Sep 21, 2020 3:29 pm

unregistered wrote:
Mon Sep 21, 2020 1:12 pm
It doesn’t seem that simple to me...

As Dwedit said, lda #n is two cycles; it’s also 2 bytes.

lda zpg is three cycles; but also 2 bytes.

Oooh, you mean you’d start with 2 cycles and add 1 cycle for the byte fetched from memory. :)

Though, you’d have to add another cycle for the high byte used in the byte fetch for lda abs... it’s 4 cycles and 3 bytes.

Hope that clarifies... :)
As Dwedit explained, the important part isn't the length of the instruction, but the number of memory accesses that need to be made.
For example, "LDA #$12" only requires reading 2 bytes from memory, while "LDA $12" requires reading 3 bytes (the opcode, the "$12", then the actual value at address $0012), and "LDA $1234" requires reading 4 bytes (the opcode, the two operand bytes "$34" and "$12", and finally the value at address $1234).

The various indexed and/or indirect addressing modes add further complications (especially with instructions that perform writes), as do certain instructions which perform Read-Modify-Write.
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.

User avatar
Zepper
Formerly Fx3
Posts: 3223
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: Is there a logic to instruction timings?

Post by Zepper » Tue Sep 22, 2020 6:48 am

The error of counting cycles, plus the wrong assignment of number of cycles (a cycle table to be exact) while the CPU is running.
Needless to say, but for each CPU read/write, the PPU runs for 3 cycles in NTSC mode. Depending on the addressing mode, as Q said, the instruction will take a certain amount of CPU cycles because of its I/O operations, and not because of a cycle table.

radgeRayden
Posts: 3
Joined: Sun Sep 20, 2020 9:20 am

Re: Is there a logic to instruction timings?

Post by radgeRayden » Tue Sep 22, 2020 8:35 am

Well now that I know more or less the logic of it (and consulting 6502_cpu.txt) I'm able to program it such that reads / writes are detected and increment the cycle counting, and that's basically what I'm doing. There's not really any table consulting apart from that. It just forces me to write the instructions a bit more explicitly so RW matches what the machine does.

Edit: it now passes nestest when comparing cycle counts. Thanks everyone! I'm sure there's some wrong stuff that I'll have to validate with other ROMs later but I'll start working on the PPU next for a change.

User avatar
rainwarrior
Posts: 8002
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Is there a logic to instruction timings?

Post by rainwarrior » Sat Oct 10, 2020 11:24 pm

I figured this topic might make a useful wiki article, so I've incorporated some of the things said here into Wiki: Cycle counting. If anyone's got anything useful to add/correct there, please feel free.

Post Reply