Help in understanding what happens each cycle

Topics pertaining to the emulation or simulation of the 65xx microprocessors and their peripheral chips.
Post Reply
jomag
Posts: 4
Joined: 01 Jul 2022

Help in understanding what happens each cycle

Post by jomag »

So I was quite happy about my 6502 emu. And then I started comparing logs with visual6502/perfect6502. Aaaand... no.

It's something about the "pipelining" that just breaks my brain. At least I think it's related to that.

For testing, I created a very small program:

Code: Select all

start:
  ldx #$02
loop:
  dex
  nop
  bne loop
  sta $20
  dey
  jmp start
Assembled listing:

Code: Select all

0000               START     
0000  A2 02                  LDX #$02
0002               LOOP      
0002  CA                     DEX
0003  EA                     NOP
0004  D0 FC                  BNE $0002
0006  85 20                  STA $20
0008  88                     DEY
0009  4C 00 00               JMP $0000
My first confusion happens already while executing the first two instructions. Here's the log from perfect6502, with my comments/questions embedded. Note that the status is printed before each half-cycle is executed:

Code: Select all

; Reset sequence. I've so far not attempted to get this right in my emulator, so I'm skipping
; these cycles for now.
halfcyc:0 phi0:1 AB:00FF D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:C0 P:02 IR:00 R$00FF=$00
halfcyc:1 phi0:0 AB:00FF D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:C0 P:02 IR:00
halfcyc:2 phi0:1 AB:00FF D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:C0 P:02 IR:00 R$00FF=$00
halfcyc:3 phi0:0 AB:00FF D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:C0 P:02 IR:00
halfcyc:4 phi0:1 AB:00FF D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:C0 P:02 IR:00 R$00FF=$00
halfcyc:5 phi0:0 AB:00FF D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:C0 P:02 IR:00
halfcyc:6 phi0:1 AB:00FF D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:C0 P:02 IR:00 R$00FF=$00
halfcyc:7 phi0:0 AB:01C0 D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:C0 P:02 IR:00
halfcyc:8 phi0:1 AB:01C0 D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:C0 P:02 IR:00 R$01C0=$00
halfcyc:9 phi0:0 AB:01BF D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:C0 P:02 IR:00
halfcyc:10 phi0:1 AB:01BF D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:C0 P:02 IR:00 R$01BF=$00
halfcyc:11 phi0:0 AB:01BE D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:C0 P:02 IR:00
halfcyc:12 phi0:1 AB:01BE D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:C0 P:02 IR:00 R$01BE=$00
halfcyc:13 phi0:0 AB:FFFC D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:BD P:02 IR:00
halfcyc:14 phi0:1 AB:FFFC D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:BD P:06 IR:00 R$FFFC=$00
halfcyc:15 phi0:0 AB:FFFD D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:BD P:16 IR:00
halfcyc:16 phi0:1 AB:FFFD D:00 RnW:1 PC:00FF A:00 X:C0 Y:00 SP:BD P:16 IR:00 R$FFFD=$00

; I've reset the half-cycle count, as this is the first cycle that has PC set to the start address (0).
;
; Reflection:
; As I understand it, AB is the address bus, and D is what's been buffered from the data bus.
; In comparison, visual6502 shows both "db" and "pd". I assume that "db" is the state of the
; data pins, while "pd" is what's been buffered, as visual6502 has value A2 for "db" already
; in half-cycle 0.
;
; Question:
; What would you consider a "full cycle"? Is it half-cycle 0+1, or 1+2? 0+1 makes sense to
; me as it allows the address bus to be set in the first half-cycle, and data pins to be valid in
; the second half-cycle.
;
; But on the other hand, 17 half-cycles have been executed before reaching this point,
; so it means that the reset sequence would have added one extra half-cycle.
;
; I will group the half-cycles below based on my assumption above.
;
; Based on what happens in the next cycle, I think we're in the first cycle of
; the LDX operation here ("fetch opcode"). See next comment.
halfcyc:0 phi0:0 AB:0000 D:00 RnW:1 PC:0000 A:00 X:C0 Y:00 SP:BD P:16 IR:00
halfcyc:1 phi0:1 AB:0000 D:A2 RnW:1 PC:0000 A:00 X:C0 Y:00 SP:BD P:16 IR:00 R$0000=$A2

; This is the first cycle where IR is A2 ("LDX #$02"). So the opcode has already been fetched.
; Because of that I assume this means that we're in the second cycle of "LDX"? The
; assumption is based on the well-known 6502_cpu.txt, which documents the cycles
; of this operation like this:
;
; Immediate addressing
;
;         #  address R/W description
;        --- ------- --- ------------------------------------------
;         1    PC     R  fetch opcode, increment PC
;         2    PC     R  fetch value, increment PC       <--- we're here
;
; Note that X is untouched.
halfcyc:2 phi0:0 AB:0001 D:A2 RnW:1 PC:0001 A:00 X:C0 Y:00 SP:BD P:16 IR:A2
halfcyc:3 phi0:1 AB:0001 D:02 RnW:1 PC:0001 A:00 X:C0 Y:00 SP:BD P:16 IR:A2 R$0001=$02

; When this cycle is about to be executed, X has been set to 2 by the LDX instruction. From this, I assume
; that X is set during "halfcyc 3" above, and is ready when this cycle begins.
;
; I assume that no pre-fetch was made during the execution of LDX, since the last cycle of LDX requires
; a bus read. This means we're at cycle 1 of DEX:
;
;   Accumulator or implied addressing
;
;         #  address R/W description
;        --- ------- --- -----------------------------------------------
;         1    PC     R  fetch opcode, increment PC        <--- we're here
;         2    PC     R  read next instruction byte (and throw it away)
;
halfcyc:4 phi0:0 AB:0002 D:02 RnW:1 PC:0002 A:00 X:02 Y:00 SP:BD P:14 IR:A2
halfcyc:5 phi0:1 AB:0002 D:CA RnW:1 PC:0002 A:00 X:02 Y:00 SP:BD P:14 IR:A2 R$0002=$CA

; Nothing interesting here. Next instruction byte is read. Not sure why it's thrown away?
halfcyc:6 phi0:0 AB:0003 D:CA RnW:1 PC:0003 A:00 X:02 Y:00 SP:BD P:14 IR:CA
halfcyc:7 phi0:1 AB:0003 D:EA RnW:1 PC:0003 A:00 X:02 Y:00 SP:BD P:14 IR:CA R$0003=$EA

; What? Third cycle of DEX? There should be no such, and X is still not decremented.
halfcyc:8 phi0:0 AB:0003 D:EA RnW:1 PC:0003 A:00 X:02 Y:00 SP:BD P:14 IR:CA
halfcyc:9 phi0:1 AB:0003 D:EA RnW:1 PC:0003 A:00 X:02 Y:00 SP:BD P:14 IR:CA R$0003=$EA

; Finally, X is decremented.
; As IR is already NOP, and as this operation has the same addressing mode as DEX,
; I assume this means we're at cycle 2 of the NOP.
halfcyc:10 phi0:0 AB:0004 D:EA RnW:1 PC:0004 A:00 X:01 Y:00 SP:BD P:14 IR:EA
halfcyc:11 phi0:1 AB:0004 D:D0 RnW:1 PC:0004 A:00 X:01 Y:00 SP:BD P:14 IR:EA R$0004=$D0

; Nothing changes here. I include some more cycles, but will not comment on them,
; as I think the above is enough to get started.
halfcyc:12 phi0:0 AB:0004 D:D0 RnW:1 PC:0004 A:00 X:01 Y:00 SP:BD P:14 IR:EA
halfcyc:13 phi0:1 AB:0004 D:D0 RnW:1 PC:0004 A:00 X:01 Y:00 SP:BD P:14 IR:EA R$0004=$D0

halfcyc:14 phi0:0 AB:0005 D:D0 RnW:1 PC:0005 A:00 X:01 Y:00 SP:BD P:14 IR:D0
halfcyc:15 phi0:1 AB:0005 D:FC RnW:1 PC:0005 A:00 X:01 Y:00 SP:BD P:14 IR:D0 R$0005=$FC

halfcyc:16 phi0:0 AB:0006 D:FC RnW:1 PC:0006 A:00 X:01 Y:00 SP:BD P:14 IR:D0
halfcyc:17 phi0:1 AB:0006 D:85 RnW:1 PC:0006 A:00 X:01 Y:00 SP:BD P:14 IR:D0 R$0006=$85

halfcyc:18 phi0:0 AB:0002 D:85 RnW:1 PC:0002 A:00 X:01 Y:00 SP:BD P:14 IR:D0
halfcyc:19 phi0:1 AB:0002 D:CA RnW:1 PC:0002 A:00 X:01 Y:00 SP:BD P:14 IR:D0 R$0002=$CA

halfcyc:20 phi0:0 AB:0003 D:CA RnW:1 PC:0003 A:00 X:01 Y:00 SP:BD P:14 IR:CA
halfcyc:21 phi0:1 AB:0003 D:EA RnW:1 PC:0003 A:00 X:01 Y:00 SP:BD P:14 IR:CA R$0003=$EA

halfcyc:22 phi0:0 AB:0003 D:EA RnW:1 PC:0003 A:00 X:01 Y:00 SP:BD P:14 IR:CA
halfcyc:23 phi0:1 AB:0003 D:EA RnW:1 PC:0003 A:00 X:01 Y:00 SP:BD P:14 IR:CA R$0003=$EA
While writing this, I was hoping for some "rubber ducking" effect to take place, but nope, I'm still as confused as before.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Help in understanding what happens each cycle

Post by BigEd »

Welcome! I'm having trouble accessing visual6502 but I have a local copy (you could download one from the Wayback Machine.) I'm not so familiar with perfect6502 - the model is fine, I'm sure, but I don't know about the inputs or the interpreting of the logs

Here's your test program running in visual6502:

Code: Select all

cycle ab	db	rw	Fetch	 pc	 a	 x	 y	 s	p
 0	0000	a2	1	LDX #	0000	aa	00	00	fd	nv‑BdIZc
 0	0000	a2	1	LDX #	0000	aa	00	00	fd	nv‑BdIZc
 1	0001	02	1			  0001	aa	00	00	fd	nv‑BdIZc
 1	0001	02	1			  0001	aa	00	00	fd	nv‑BdIZc
 2	0002	ca	1	DEX	  0002	aa	02	00	fd	nv‑BdIzc
 2	0002	ca	1	DEX	  0002	aa	02	00	fd	nv‑BdIzc
 3	0003	ea	1			  0003	aa	02	00	fd	nv‑BdIzc
 3	0003	ea	1			  0003	aa	02	00	fd	nv‑BdIzc
 4	0003	ea	1	NOP	  0003	aa	02	00	fd	nv‑BdIzc
 4	0003	ea	1	NOP	  0003	aa	02	00	fd	nv‑BdIzc
 5	0004	d0	1			  0004	aa	01	00	fd	nv‑BdIzc
 5	0004	d0	1			  0004	aa	01	00	fd	nv‑BdIzc
 6	0004	d0	1	BNE 	 0004	aa	01	00	fd	nv‑BdIzc
 6	0004	d0	1	BNE 	 0004	aa	01	00	fd	nv‑BdIzc
 7	0005	fc	1			  0005	aa	01	00	fd	nv‑BdIzc
 7	0005	fc	1			  0005	aa	01	00	fd	nv‑BdIzc
 8	0006	85	1			  0006	aa	01	00	fd	nv‑BdIzc
 8	0006	85	1			  0006	aa	01	00	fd	nv‑BdIzc
 9	0002	ca	1	DEX	  0002	aa	01	00	fd	nv‑BdIzc
 9	0002	ca	1	DEX	  0002	aa	01	00	fd	nv‑BdIzc
10	0003	ea	1			  0003	aa	01	00	fd	nv‑BdIzc
10	0003	ea	1			  0003	aa	01	00	fd	nv‑BdIzc
11	0003	ea	1	NOP	  0003	aa	01	00	fd	nv‑BdIzc
11	0003	ea	1	NOP	  0003	aa	01	00	fd	nv‑BdIzc
12	0004	d0	1			  0004	aa	00	00	fd	nv‑BdIZc
12	0004	d0	1			  0004	aa	00	00	fd	nv‑BdIZc
13	0004	d0	1	BNE 	 0004	aa	00	00	fd	nv‑BdIZc
13	0004	d0	1	BNE 	 0004	aa	00	00	fd	nv‑BdIZc
14	0005	fc	1			  0005	aa	00	00	fd	nv‑BdIZc
14	0005	fc	1			  0005	aa	00	00	fd	nv‑BdIZc
15	0006	85	1	STA zp  0006	aa	00	00	fd	nv‑BdIZc
15	0006	85	1	STA zp  0006	aa	00	00	fd	nv‑BdIZc
16	0007	20	1			  0007	aa	00	00	fd	nv‑BdIZc
16	0007	20	1			  0007	aa	00	00	fd	nv‑BdIZc
17	0020	20	0			  0008	aa	00	00	fd	nv‑BdIZc
17	0020	aa	0			  0008	aa	00	00	fd	nv‑BdIZc
18	0008	88	1	DEY	  0008	aa	00	00	fd	nv‑BdIZc
18	0008	88	1	DEY	  0008	aa	00	00	fd	nv‑BdIZc
19	0009	4c	1			  0009	aa	00	00	fd	nv‑BdIZc
19	0009	4c	1			  0009	aa	00	00	fd	nv‑BdIZc
20	0009	4c	1	JMP Abs 0009	aa	00	00	fd	nv‑BdIZc
20	0009	4c	1	JMP Abs 0009	aa	00	00	fd	nv‑BdIZc
21	000a	00	1			  000a	aa	00	ff	fd	Nv‑BdIzc
21	000a	00	1			  000a	aa	00	ff	fd	Nv‑BdIzc
22	000b	00	1			  000b	aa	00	ff	fd	Nv‑BdIzc
22	000b	00	1			  000b	aa	00	ff	fd	Nv‑BdIzc
23	0000	a2	1	LDX #	0000	aa	00	ff	fd	Nv‑BdIzc
23	0000	a2	1	LDX #	0000	aa	00	ff	fd	Nv‑BdIzc
To get the pairings of the half-cycles right, perhaps easiest to look at the RnW line going low for a write. But I would expect the address bus also to be a good indication. (It's possible this just isn't so for perfect6502.)

Note that the updated value of X from the LDA is first seen in the next cycle after the value appears on the bus.

But also note that the update of X from DEX is seen in the second cycle of the NOP: the decrement is done during the first cycle of NOP, and the write to X happens at the end of that first cycle, so it is first seen in the second cycle. This is because the ALU is needed and that takes a cycle to operate.

If you feel you might get lost, add sync to your traced signals.

I think I'd also add the alu inputs and outputs:
logmore=sync,alua,alub,alu

The way I think of it
- in a sync cycle, the 6502 is fetching the opcode, which arrives in the final nanoseconds. There's nothing it can do which is opcode specific, even though this is commonly counted as the first cycle.
- in the next cycle, the 6502 was already committed to reading the operand, whether or not there will be one, as it had no idea what it was going to need to do. In this cycle, it decodes the opcode and sets up the action for the following cycle. It also figures out if the next cycle needs to be the next sync
- in the third cycle, finally the 6502 can take an opcode-specific action. And it might be the next sync, or a fetch of a third byte, or something else.

Hope this helps - happy to discuss. If you have a single specific question that might be best - we can deal with each question as it comes up.
tmr4
Posts: 147
Joined: 19 Feb 2022

Re: Help in understanding what happens each cycle

Post by tmr4 »

When I started out with the 65C02 I never knew this existed, but Table 5-7 of the WDC 65816 datasheet lists what is on the address and data buses during each clock cycle. I've found this helpful in understanding what's going on as each instruction is executed. I don't think it's fully applicable to the 65C02, but I've used the 8-bit cycles from this table in working with the 65C02 more recently. The 65816 does differ from the 65C02 in cycle timing so this probably isn't perfect in all cases.

If anyone knows of a similar table specific for the 65C02, I'd appreciate a link.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Help in understanding what happens each cycle

Post by GARTHWILSON »

tmr4 wrote:
When I started out with the 65C02 I never knew this existed, but Table 5-7 of the WDC 65816 datasheet lists what is on the address and data buses during each clock cycle.  I've found this helpful in understanding what's going on as each instruction is executed.  I don't think it's fully applicable to the 65C02, but I've used the 8-bit cycles from this table in working with the 65C02 more recently.  The 65816 does differ from the 65C02 in cycle timing so this probably isn't perfect in all cases.

If anyone knows of a similar table specific for the 65C02, I'd appreciate a link.
I've been able to get most of the information I needed from the footnotes and the later section on caveats.  At the beginning of the footnotes, it says, "Be aware that notes #4-7, 9 and 10 apply to the W65C02S and W65C816S.  All other notes apply to the W65C816S only."
65cycleNotes.gif
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
jomag
Posts: 4
Joined: 01 Jul 2022

Re: Help in understanding what happens each cycle

Post by jomag »

BigEd wrote:
Welcome! I'm having trouble accessing visual6502 but I have a local copy (you could download one from the Wayback Machine.) I'm not so familiar with perfect6502 - the model is fine, I'm sure, but I don't know about the inputs or the interpreting of the logs
I've compared visual6502 and perfect6502, and they produce identical result. Pro with perfect6502 is that I could easily modify it to run from the command line and output whatever log I needed. With visual6502 I had to run a few cycles in the browser and copy the table for further adjustments. A con with perfect6502 is that it does not seem to easily allow logging of sync for example. Need to investigate a bit more. Anyway, either work!

One difference is that visual6502 happily starts at 0. I had to "trick" perfect6502 into doing that, using the reset vector. As far as I can see, half-cycles 0+0 in your visual6502 is equal to half-cycle 0+1 in my perfect6502 log (except the registers are not initialized with same values, for whatever reason...).
BigEd wrote:
Note that the updated value of X from the LDA is first seen in the next cycle after the value appears on the bus.
Yes. This is what I would expect:

- Cycle 0: read opcode
- Cycle 1: read value and set x
- Cycle 2: first state with the new x

This is what I would expect from an operation documented to take 2 cycles, and the cycles correspond to what cpu_6502.txt says about immediate addressing.
BigEd wrote:
But also note that the update of X from DEX is seen in the second cycle of the NOP: the decrement is done during the first cycle of NOP, and the write to X happens at the end of that first cycle, so it is first seen in the second cycle. This is because the ALU is needed and that takes a cycle to operate.
Uhm, this is where it gets strange. Implied addressing mode operations should take 2 cycles to execute, the same as LDX. This is according to both cpu_6502.txt and the W65C02S data sheet (table 4-1). But according to the log, it actually takes three cycles:

- Cycle 0: read opcode
- Cycle 1: (nothing...)
- Cycle 2: decrement X + read next op into IR
- Cycle 3: the first state with a new, decremented X value

Now, I understand that this does not really affect anything, as by the time the next operation can do something with X, it will always be decremented and ready. And it only consumes 2 cycles, as when the third cycle is running, the first cycle of the next operation executes in parallel. Could this be the reason why it's not documented?

This does however make it more complicated to compare logs between my emulator and perfect6502/visual6502. I could of course investigate every type of operation with the great tools we now have, but that's a lot of work!
BigEd wrote:
If you feel you might get lost, add sync to your traced signals.

I think I'd also add the alu inputs and outputs:
logmore=sync,alua,alub,alu
That's great! Will do that for future logs!
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Help in understanding what happens each cycle

Post by BigEd »

[Sorry, wrote this just prior to your reply. Hope it helps]

One way to look at this: from the programmer's perspective, we can simply say that LDX immediate, or DEX, takes two cycles. And several places tabulate the cycles, just in case one wishes to look one level deeper and see what the bus is doing on each cycles.

I'm pretty sure this level of abstraction is sufficient, to write a cycle accurate model of the externally visible behaviour.

And then there's another perspective, which goes deeper, which is about how the 6502 is implemented internally, and that's what you can see with visual6502 or perfect6502. Some of what you learn here might be useful if you were making a cycle-accurate HDL model.

But I think what's going on with the head post is some difficulty in reconciling the external perspective and the internal perspective. There's nothing going on which can't be understood, but it's operating at a different level.

In particular, you can't tell from outside which cycle it is that DEX causes the X register to get the new value. All you can tell from outside is what you can get from a program, and the program is going to pick up the value after it's written - because of the internal sequence of events.

As I say, keep an eye on SYNC. That's when the external observer starts counting cycles - and therefore, it's where the external observer stops worrying about the previous instruction. The internal machinery may still have further work to do.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Help in understanding what happens each cycle

Post by BigEd »

So, although DEX might take three cycles to get its job done (or even four), that's of no interest to any external observer or any program: the next instruction will be fetched after two cycles. Conventionally, and usefully, we say that DEX is a two cycle instruction.
jomag
Posts: 4
Joined: 01 Jul 2022

Re: Help in understanding what happens each cycle

Post by jomag »

Thanks BigEd, this was just the response I needed to get some confidence in how I interpret the logs and documentation! I'm sure more questions will pop up shortly! :)
User avatar
org
Posts: 201
Joined: 22 Jun 2012
Contact:

Re: Help in understanding what happens each cycle

Post by org »

Try Breaks Debugger: viewtopic.php?f=8&t=6973

https://github.com/emu-russia/breaks/re ... s-debug-18

There's a tab that shows what's going on at the bottom of the processor.
6502 addict
jomag
Posts: 4
Joined: 01 Jul 2022

Re: Help in understanding what happens each cycle

Post by jomag »

I ran into this strange behavior of the BIT operation. The BIT operation does two things:
Quote:
Bits 7 and 6 of operand are transfered to bit 7 and 6 of SR (N,V);
The zero-flag is set to the result of operand AND accumulator.
I'm still trying to get my emu to pass Klaus tests, and I'm running perfect6502 in parallel for comparison.

So what I've found is that the two tasks of the BIT operation seems to happen in two cycles, but not always. Here's the first BIT operation:

Code: Select all

; BIT cycle 0
; Read opcode
halfcyc:192600 phi0:0 AB:1B75 D:00 RnW:1 PC:1B75 A:FF X:00 Y:FF SP:FF P:10 IR:28  <--- sync
halfcyc:192601 phi0:1 AB:1B75 D:24 RnW:1 PC:1B75 A:FF X:00 Y:FF SP:FF P:10 IR:28 R$1B75=$24

; BIT cycle 1
; Read pointer
halfcyc:192602 phi0:0 AB:1B76 D:24 RnW:1 PC:1B76 A:FF X:00 Y:FF SP:FF P:10 IR:24
halfcyc:192603 phi0:1 AB:1B76 D:18 RnW:1 PC:1B76 A:FF X:00 Y:FF SP:FF P:10 IR:24 R$1B76=$18

; BIT cycle 2
; Read from the address
halfcyc:192604 phi0:0 AB:0018 D:18 RnW:1 PC:1B77 A:FF X:00 Y:FF SP:FF P:10 IR:24
halfcyc:192605 phi0:1 AB:0018 D:00 RnW:1 PC:1B77 A:FF X:00 Y:FF SP:FF P:10 IR:24 R$0018=$00

; BIT cycle 3
; Operand is $00, A is $FF, P is $10.
; - Bit 7 and 6 of operand are transferred to P. No change in P.
; - Operand ($00) AND accumulator ($FF) is zero, so zero flag is set: P is $12.
halfcyc:192606 phi0:0 AB:1B77 D:00 RnW:1 PC:1B77 A:FF X:00 Y:FF SP:FF P:12 IR:24  <--- sync
halfcyc:192607 phi0:1 AB:1B77 D:08 RnW:1 PC:1B77 A:FF X:00 Y:FF SP:FF P:12 IR:24 R$1B77=$08

; No more changes from the BIT operation ...
halfcyc:192608 phi0:0 AB:1B78 D:08 RnW:1 PC:1B78 A:FF X:00 Y:FF SP:FF P:12 IR:08
halfcyc:192609 phi0:1 AB:1B78 D:C9 RnW:1 PC:1B78 A:FF X:00 Y:FF SP:FF P:12 IR:08 R$1B78=$C9

halfcyc:192610 phi0:0 AB:01FF D:C9 RnW:0 PC:1B78 A:FF X:00 Y:FF SP:FF P:12 IR:08
halfcyc:192611 phi0:1 AB:01FF D:32 RnW:0 PC:1B78 A:FF X:00 Y:FF SP:FF P:12 IR:08 W$01FF=$32

halfcyc:192612 phi0:0 AB:1B78 D:C9 RnW:1 PC:1B78 A:FF X:00 Y:FF SP:FE P:12 IR:08
halfcyc:192613 phi0:1 AB:1B78 D:C9 RnW:1 PC:1B78 A:FF X:00 Y:FF SP:FE P:12 IR:08 R$1B78=$C9
But then, some cycles later, another BIT operation takes place. Same addressing mode, but what happens in cycle 3 and 4 differs:

Code: Select all

; BIT cycle 0
; Read opcode
halfcyc:192744 phi0:0 AB:1B9D D:00 RnW:1 PC:1B9D A:01 X:00 Y:FF SP:FF P:10 IR:28  <--- sync
halfcyc:192745 phi0:1 AB:1B9D D:24 RnW:1 PC:1B9D A:01 X:00 Y:FF SP:FF P:10 IR:28 R$1B9D=$24

; BIT cycle 1
; Read pointer
halfcyc:192746 phi0:0 AB:1B9E D:24 RnW:1 PC:1B9E A:01 X:00 Y:FF SP:FF P:10 IR:24
halfcyc:192747 phi0:1 AB:1B9E D:16 RnW:1 PC:1B9E A:01 X:00 Y:FF SP:FF P:10 IR:24 R$1B9E=$16

; BIT cycle 2
; Read from the address
halfcyc:192748 phi0:0 AB:0016 D:16 RnW:1 PC:1B9F A:01 X:00 Y:FF SP:FF P:10 IR:24
halfcyc:192749 phi0:1 AB:0016 D:82 RnW:1 PC:1B9F A:01 X:00 Y:FF SP:FF P:10 IR:24 R$0016=$82

; BIT cycle 3
; Operand is $82, A is $01, P is $10.
; Compare this and the next cycle with the equivalent above:
; P changes to $90 in this cycle
halfcyc:192750 phi0:0 AB:1B9F D:82 RnW:1 PC:1B9F A:01 X:00 Y:FF SP:FF P:90 IR:24  <--- sync
halfcyc:192751 phi0:1 AB:1B9F D:08 RnW:1 PC:1B9F A:01 X:00 Y:FF SP:FF P:90 IR:24 R$1B9F=$08

; BIT cycle 4
; ... and then it changes to $92 in this cycle
halfcyc:192752 phi0:0 AB:1BA0 D:08 RnW:1 PC:1BA0 A:01 X:00 Y:FF SP:FF P:92 IR:08
halfcyc:192753 phi0:1 AB:1BA0 D:C9 RnW:1 PC:1BA0 A:01 X:00 Y:FF SP:FF P:92 IR:08 R$1BA0=$C9

; No more changes from the BIT operation ...
halfcyc:192754 phi0:0 AB:01FF D:C9 RnW:0 PC:1BA0 A:01 X:00 Y:FF SP:FF P:92 IR:08
halfcyc:192755 phi0:1 AB:01FF D:B2 RnW:0 PC:1BA0 A:01 X:00 Y:FF SP:FF P:92 IR:08 W$01FF=$B2

halfcyc:192756 phi0:0 AB:1BA0 D:C9 RnW:1 PC:1BA0 A:01 X:00 Y:FF SP:FE P:92 IR:08
halfcyc:192757 phi0:1 AB:1BA0 D:C9 RnW:1 PC:1BA0 A:01 X:00 Y:FF SP:FE P:92 IR:08 R$1BA0=$C9

halfcyc:192758 phi0:0 AB:1BA1 D:C9 RnW:1 PC:1BA1 A:01 X:00 Y:FF SP:FE P:92 IR:C9
halfcyc:192759 phi0:1 AB:1BA1 D:01 RnW:1 PC:1BA1 A:01 X:00 Y:FF SP:FE P:92 IR:C9 R$1BA1=$01
I can't see why the two operations differ in execution. I understand that it makes no difference from the outside for the same reason as discussed above: the P register will be correct by the time the next operation can do anything with it.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Help in understanding what happens each cycle

Post by BigEd »

I think what's happening is because Z is set according to an internal bus value - and in the case where one of the operands is a zero, that zero is setting Z. The result of the AND, one cycle later, will also set Z, in the same cycle that it would (and should) anyway, but you can no longer see it because Z has already been set.

In effect, the value of Z in cycle 3 is a don't care, and so the implementation challenge of whether or not to set Z in cycle 3 is also a don't care.
User avatar
cjs
Posts: 759
Joined: 01 Dec 2018
Location: Tokyo, Japan
Contact:

Re: Help in understanding what happens each cycle

Post by cjs »

tmr4 wrote:
When I started out with the 65C02 I never knew this existed, but Table 5-7 of the WDC 65816 datasheet lists what is on the address and data buses during each clock cycle....
If anyone knows of a similar table specific for the 65C02, I'd appreciate a link.
I don't know of one for the 65C02 offhand, but MOS supplied something similar for the 6502 in the original in Appendix E of the 1976 MCS6500 Microcomputer Family Programming Manual.
Curt J. Sampson - github.com/0cjs
Post Reply