9

I (as so many people before me) am developing a software simulation of the 6502, mostly based on the often cited block diagrams and several other sources of information.

Basically all the components are done and I am in the process of configuring the Decode ROM and the RCL (Random Control Logic), only to find some unexpected behaviour: DEX affects the behaviour of the CPU, even after its 2 cycles have completed.

Until now it was my understanding that instructions only control the CPU while they are actually being executed.

But, as can be seen in this Visual6502 example, the T0+T2 cycle of an LDA# right before DEX looks different from the T0+T2 cycle of an LDA# right after the DEX: RCL outputs an additional SB/X, which is necessary to transfer the decreased value back into the X register. So DEX has an effect AFTER its last cycle completed.

DEX does not seem to have any lingering effect on the decode ROM/PLA outputs however, as they are identical for both LDA#s, so there must be some kind of hidden state affecting RCL.

How does this work and which instruction groups are affected? Are there any sources going into more detail about this?

Edit: Just for clarification. I am not talking about pipelining. Of course, the second LDA# is prefetched during the last cycle of DEX (T1). The SB/X signal that confuses me happens one cycle later, during T0+T2, which is the first cycle of actual execution of LDA#, where DEX has already been wiped from the IR register.

3
  • I'm a bit puzzled what an emulation at such detail should be good for. If it's about a cycle exact emulation, to be used to emulate exact hardware behaviour, the effort going into Decode ROM or RCL isn't needed, as these have no external visible effects. Likewise, it's about a simulation at lowest possible level, to show internal workings, the Visual6502 does already a great job at maximum detail. I have a hard time to find a reasoning for anything inbetween. So what is it you want to archieve?
    – Raffzahn
    Jul 19, 2018 at 1:08
  • 5
    Because it's fun. Haven't enjoyed myself as much since I built my first NES emulator. Jul 19, 2018 at 1:36
  • 2
    See my answer here where I link to BreakNes and their GitHub repo. Jul 19, 2018 at 2:25

1 Answer 1

3

Until now it was my understanding that instructions only control the CPU while they are actually being executed.

True, but always keep in mind that the 6502 operation is pipelined. This means that there is an 'overhang' of the last instruction where it gets finished while the next is in preparation (opcode fetch). In this case it's storing the decremented value back to X. That cycle is often called T+ cycle and is always in parallel to T1 of the next instruction (*1,2).

So DEX has an effect AFTER its last cycle completed.

Congratulations, you discovered pipelining :=)

This is the last cycle of DEX - and it's in parallel to fetching the next instruction.

How does this work and which instruction groups are affected?

Next to all instructions are. As mentioned, it's the core idea of pipelining in the 6502 to finish one operation while the next gets fetched. Just change the first LDA to an ADC ($69), and see how it performs while the DEX is fetched.

Are there any sources going into more detail about this?

The primal source here is the 6502 Programming Manual - always a good read - in Chapter 5.1 (p52ff) the pipelining is explained (*3).


*1 - Unless it's a jump - but that's a different story.

*2 - So, depending the point of view, all 6502 manual lie, as every (well, most) instruction do take one more cycle than they tell - even though this cycle is well hidden and usually not seen :))

*3 - IIRC the Hardware Manual also mentions it.

6
  • 2
    Hi Raffzahn, thanks for your answer. Unfortunately that does not explain my issue. Of course I have pipelining implemented, as it is a fundamental component of the 6502. However, fetching of the next instruction into PD happens during T1 (which also asserts the SYNC pin). But as you can see in the example I posted, my problem is T0+T2, where the new instruction is already in the IR and has begun execution. The pla and rcl already show outputs that are part of the new instructions execution, BUT, in the case I mentioned, also of the completed DEX instruction. Jul 19, 2018 at 1:07
  • @ThomasHilbert Try an ADC instead of the first LDA and you'll easy see how it works. - And read the manual, as it decribes what happenes in great detail. The lines are exactly reflecting that behaviour of finishing an operation, while the next is fetched. Maybe even go ahead and key in exactly the example they make in the manual and watch!
    – Raffzahn
    Jul 19, 2018 at 1:14
  • 1
    Please change for chat for any discusion: chat.stackexchange.com/rooms/38597/the-bbs
    – Raffzahn
    Jul 19, 2018 at 1:35
  • 1
    As for footnote 1, I guess this explains why conditional branches take an extra cycle if they are taken. Jul 19, 2018 at 7:43
  • 1
    Would there be any problem with viewing the "first cycle" of each instruction as being the one following the opcode fetch, and viewing each instruction as ending with the opcode fetch of the next instruction? Since everything that happens within the opcode fetch is dependent upon the previous instruction, and nothing can depend upon the opcode that isn't yet fetched, I would think such a view would make things clearer.
    – supercat
    Feb 11, 2020 at 5:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .