Detecting Free Bus Cycles

Let's talk about anything related to the 6502 microprocessor.
User avatar
Druzyek
Posts: 367
Joined: 12 May 2014
Contact:

Detecting Free Bus Cycles

Post by Druzyek »

I'm running a 65C02 from a microcontroller and feeding it data from the microcontroller's memory. If the processor tries to read an address that the microcontroller has marked uninitialized, the microcontroller stops execution. This is really handy for debugging. The problem is detecting the difference between when the processor is reading from an address or just pointing to that address but not reading or writing anything. For example, I noticed on JSR the address bus first jumps to the top of the stack for one cycle then writes data there on the next cycle. If this address is uninitialized, it won't matter since it's just going to write there on the second cycle but I need a way to know that it isn't doing anything on the first cycle. When I did this on a 65C816 I just had to check that both VPA and VDA were zero to know it was an internal operation. Any suggestions on how to find the same thing out on a 65C02?
nyef
Posts: 235
Joined: 28 Jul 2013

Re: Detecting Free Bus Cycles

Post by nyef »

Assuming a WDC 'c02, and checking the data sheet for pinout information and the like, I find SYNC and VPB outputs that give the opportunity for an external state machine to "lock on" to the CPU state. You can then keep track of where the CPU is in terms of handling each opcode.

The problem comes with your page-boundary penalty for indexing across a page boundary. In these cases, there doesn't appear to be a way to know that a "free" cycle is being emitted until the start of the following cycle. The WDC 'c02 is at least specified to have the invalid address be the last instruction byte fetched, but that's no guarantee: If the last instruction byte is actually the given target then it isn't dead. This may not matter for your use-case, however.

The same cycle for a "taken" branch is easy to detect: If the second cycle after a branch opcode is fetched does not involve SYNC, then you have a "free" cycle.

I guess what I'm saying is "not for the general case, here's an 80% solution, how to drive it to 90%, and when it's not going to work". If it's a "good enough" solution for your project is a judgment call that only you are qualified to make.
User avatar
Druzyek
Posts: 367
Joined: 12 May 2014
Contact:

Re: Detecting Free Bus Cycles

Post by Druzyek »

Thanks for your reply nyef. It seems like I would need to include a description of the bus for every op code on every cycle, which does not seem like much fun. Does that seem like the only way to accomplish this?
nyef
Posts: 235
Joined: 28 Jul 2013

Re: Detecting Free Bus Cycles

Post by nyef »

There are only so many instructions, and far, far fewer addressing modes, which are the primary determiner of behavior in this respect. It may or may not be fun. It may even be yet another tedious thing that needs to be dealt with in order to achieve your goals. But it is unlikely to take very long to determine if it would work for you, nor is it likely to take very long to implement.

... Or someone could have a better idea. But this is the approach that I see that comes closest to actually working.
User avatar
Dr Jefyll
Posts: 3526
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: Detecting Free Bus Cycles

Post by Dr Jefyll »

nyef wrote:
SYNC and VPB outputs that give the opportunity for an external state machine to "lock on" to the CPU state. You can then keep track of where the CPU is in terms of handling each opcode.
Yup.
nyef wrote:
The WDC 'c02 [ Rockwell, too - JL ] is at least specified to have the invalid address be the last instruction byte fetched, but that's no guarantee: If the last instruction byte is actually the given target then it isn't dead.
Interesting; you're right. But occasions where the last instruction byte is actually the given target are hardly the norm. </droll understatement> :D I think the external state machine idea is highly feasible -- but (and you make this point yourself) perhaps more effort than is justified.

nyef wrote:
I guess what I'm saying is "not for the general case, here's an 80% solution, how to drive it to 90%, and when it's not going to work". If it's a "good enough" solution for your project is a judgment call that only you are qualified to make.
Agreed. Druzyek, how would you feel about simply making the stack an exception? Ie; don't check for uninitialized accesses if the address is in Page 1. It seems to me the utility of your debugging feature would be largely unaffected.

-- Jeff
Last edited by Dr Jefyll on Fri Jun 26, 2015 4:07 am, edited 1 time in total.
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Detecting Free Bus Cycles

Post by GARTHWILSON »

We've talked about something like this before, but I can't remember what search terms might find it. One thing that came up was that the microcontroller watching it would have to keep track of whether the 6502 is in decimal mode or not, because it affects what you should expect in the various cycles of some instructions.

Is this really necessary though? I don't recall ever in 30 years having had a bug due to an uninitialized variable. Ever. It's because with good programming habits, you initialize what you need to when you write the reset routine and other routines that initialize programs.
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?
User avatar
Druzyek
Posts: 367
Joined: 12 May 2014
Contact:

Re: Detecting Free Bus Cycles

Post by Druzyek »

Quote:
Agreed. Druzyek, how would you feel about simply making the stack an exception?
That is a really good idea. Can you think of any other op codes that I might need to watch out for outside the stack? For example, I know RTS points to the next byte even though its not used, although this wouldn't be a problem unless its the very last opcode in my program.
Quote:
Is this really necessary though? I don't recall ever in 30 years having had a bug due to an uninitialized variable.
YES! I started this project because I didn't know how the processor worked or how to use assembly. So far the majority of mistakes I have made learning assembly have been pointing the processor to the wrong place such as writing LDA $40 when I really meant LDA #$40.

I am leaning against storing info on all the opcodes and addressing modes on the microcontroller.
User avatar
BigEd
Posts: 11464
Joined: 11 Dec 2008
Location: England
Contact:

Re: Detecting Free Bus Cycles

Post by BigEd »

RTS reads the next byte because every instruction reads the next byte - the CPU has no choice because it doesn't yet know what the opcode is. So, the cycle after a SYNC is always going to be a read, and can't (practically) be a case of reading uninit data.
White Flame
Posts: 704
Joined: 24 Jul 2012

Re: Detecting Free Bus Cycles

Post by White Flame »

It's also hard to know what on the stack is truly initialized vs uninitialized just by looking at reads and writes. If the stack pointer is incremented for popping things off, those locations should ideally become uninitialized again, but you can't really know that just by basic r/w bus sniffing.
User avatar
Druzyek
Posts: 367
Joined: 12 May 2014
Contact:

Re: Detecting Free Bus Cycles

Post by Druzyek »

Quote:
the cycle after a SYNC is always going to be a read
That makes sense. I should do some testing and see exactly what cycles VDA and VPA were marking as internal.

By the way, is there a reference anywhere that would show what op codes are doing internal operations when? If it is not that many, maybe I can have the microcontroller look out for them.
Quote:
It's also hard to know what on the stack is truly initialized vs uninitialized just by looking at reads and writes.
In a way, yes. The whole stack gets marked uninitialized between runs for one and I find that mismatched JSR and RTS pairs (again easy to do for a beginner like me) can lead to reading uninitialized stack memory pretty quickly.

I don't mean to make a big deal about detecting the uninitialized reads but it has been by far the handiest debug feature. It also breaks on trying to execute any addresses marked as data or trying to load data that is marked as code (unless you want it to be self modifying) but this practically never happens. Looking out for uninitialized reads can save you from all sorts of things like even doing an indirect jump to the wrong address since most of the address space is empty.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Detecting Free Bus Cycles

Post by GARTHWILSON »

Quote:
By the way, is there a reference anywhere that would show what op codes are doing internal operations when? If it is not that many, maybe I can have the microcontroller look out for them.
That used to be in the data sheet, but I see the newer revisions don't have it. And again, the microcontroller would have to know if the processor's D flag is set, because that affects some of the instructions' bus cycles and internal-operations cycles.
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?
User avatar
Michael
Posts: 633
Joined: 13 Feb 2013
Location: Michigan, USA

Re: Detecting Free Bus Cycles

Post by Michael »

Druzyek wrote:
... By the way, is there a reference anywhere that would show what op codes are doing internal operations when? If it is not that many, maybe I can have the microcontroller look out for them.
Do you mean a document that shows what's going on during each cycle? Something like this?

Code: Select all

  Instructions accessing the stack

     BRK

        #  address R/W description
       --- ------- --- -----------------------------------------------
        1    PC     R  fetch opcode, increment PC
        2    PC     R  read next instruction byte (and throw it away),
                       increment PC
        3  $0100,S  W  push PCH on stack, decrement S
        4  $0100,S  W  push PCL on stack, decrement S
        5  $0100,S  W  push P on stack (with B flag set), decrement S
        6   $FFFE   R  fetch PCL
        7   $FFFF   R  fetch PCH


     RTI

        #  address R/W description
       --- ------- --- -----------------------------------------------
        1    PC     R  fetch opcode, increment PC
        2    PC     R  read next instruction byte (and throw it away)
        3  $0100,S  R  increment S
        4  $0100,S  R  pull P from stack, increment S
        5  $0100,S  R  pull PCL from stack, increment S
        6  $0100,S  R  pull PCH from stack


     RTS

        #  address R/W description
       --- ------- --- -----------------------------------------------
        1    PC     R  fetch opcode, increment PC
        2    PC     R  read next instruction byte (and throw it away)
        3  $0100,S  R  increment S
        4  $0100,S  R  pull PCL from stack, increment S
        5  $0100,S  R  pull PCH from stack
        6    PC     R  increment PC

User avatar
Dr Jefyll
Posts: 3526
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: Detecting Free Bus Cycles

Post by Dr Jefyll »

Michael wrote:
Something like this?
That's good info, Michael -- clear and easy to read. Where did it come from? Unfortunately it's not arranged in a way that lets you quickly notice all the dummy bus cycles. Table 5-7 of WDC's '816 datasheet is NOT easy to read, but at least it makes dummy bus cycles obvious; you can just scan down the columns for VPA & VDA and look for cases where they're both zero. But Table 5-7 is seven pages long!

Here, then, is my edited version of Table 5-7 -- sorted and highlighted to show every case where dummy bus cycles occur. Despite being part of an '816 datasheet, Table 5-7 apparently applies to WDC's current 'C02 as well (the W65C02S).

As you can see below, I rearranged and condensed the seven-page table into two tall, skinny gif files. Although I was reasonably careful, it's possible I accidentally introduced some errors, so check the WDC original if you prefer to see their errors only! :wink:

Edit: I will be adding detail and revising these gif diagrams, so I suggest you do NOT download them. Here is rev1 of the first table. Matters related to indexed addressing I moved up near the top, for easier reference to the notes. IMO indexed addressing is by far the most confusing cause of dummy bus cycles!

cheers,
Jeff
Attachments
'02 and '816 dummy cycles due to misc causes rev1.gif
'02 and '816 dummy cycles due to extra read at PC.gif
Last edited by Dr Jefyll on Sat Jun 27, 2015 11:47 pm, edited 1 time in total.
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
User avatar
Druzyek
Posts: 367
Joined: 12 May 2014
Contact:

Re: Detecting Free Bus Cycles

Post by Druzyek »

Dr Jefyll, thanks! That is exactly what I was hoping to find.

Yikes, having to keep track of the D flag is a deal breaker :( I do plan to use a lot of BCD arithmetic. Thanks for the ideas but I think I will have to leave this feature out. In the future I think I will also only buy 65C816s even when I really want a 6502.
Post Reply