Hi, I've run up against another problem on which I'm having trouble finding information. I can't find out in detail how the NMOS works with respect to the "garbage" reads and writes it performs during certain instructions. The CMOS chips are predictable from the documentation I have, but I need to be able to simulate both chips.
Of particular interest, I'm told that sometimes the NMOS reads from a garbage address, or writes a garbage value. I'm wondering if there is any way to calculate these values, or if they are truly random. If no one knows how, I'd appreciate recommendations about how to handle this phenomena. I'm mainly interested because my simulator may have to handle memory-mapped devices.
Thanks in advance.
6502 Simulator and Excess Read/Writes
Re: 6502 Simulator and Excess Read/Writes
>Of particular interest, I'm told that sometimes the NMOS reads from a
>garbage address, or writes a garbage value. I'm wondering if there is
>any way to calculate these values, or if they are truly random.
They're not truly random. Most of the time, instructions run at one cycle for each memory access they need. However, there are a few exceptions.
The one-byte two-cycle instructions fetch the next opcode during their second cycle.
Indexed reads that cross page boundaries read from the wrong address first. The low 8 bits of the address will be correct, but the high 8 bits have not been incremented.
Indexed writes always have the dead cycle. If a page boundary is crossed, they'll read from the wrong location (as above). If it is not crossed, the extra read is from the right location.
Read-modify-write instructions (like INC) read the original data, write it back, and then write the modified data.
Taken branches read the next opcode byte. Taken branches that cross a page boundary read the next opcode byte, then the wrong address (correct low 8 bits, current high 8 bits).
Some time ago I took traces of a few instructions with a logic analyser. These are from an NMOS 6510 in a C64. http://www.ucc.gu.uwa.edu.au/~john
64doc contains more information than you could ever want to know. http://www.atarihq.com/danb/files/64doc.txt
>garbage address, or writes a garbage value. I'm wondering if there is
>any way to calculate these values, or if they are truly random.
They're not truly random. Most of the time, instructions run at one cycle for each memory access they need. However, there are a few exceptions.
The one-byte two-cycle instructions fetch the next opcode during their second cycle.
Indexed reads that cross page boundaries read from the wrong address first. The low 8 bits of the address will be correct, but the high 8 bits have not been incremented.
Indexed writes always have the dead cycle. If a page boundary is crossed, they'll read from the wrong location (as above). If it is not crossed, the extra read is from the right location.
Read-modify-write instructions (like INC) read the original data, write it back, and then write the modified data.
Taken branches read the next opcode byte. Taken branches that cross a page boundary read the next opcode byte, then the wrong address (correct low 8 bits, current high 8 bits).
Some time ago I took traces of a few instructions with a logic analyser. These are from an NMOS 6510 in a C64. http://www.ucc.gu.uwa.edu.au/~john
64doc contains more information than you could ever want to know. http://www.atarihq.com/danb/files/64doc.txt
Thanks, that cleared up some things, especially with regard to the indexed addressing mode. My books finally came in so I think I'm set to start some serious work on my simulator.
On the suggestion to keep all your I/O ports on one page, that seems like the best way to avoid the indexed addressing mode reads. I don't know how many I/O ports are normally needed(I don't have much experience programming the 6502), but if you've got more than one page worth of ports, it might also be a good idea not to keep them on continuous pages. Either that, or simply put it in your documentation not to use indexed instructions on I/O ports.
On the suggestion to keep all your I/O ports on one page, that seems like the best way to avoid the indexed addressing mode reads. I don't know how many I/O ports are normally needed(I don't have much experience programming the 6502), but if you've got more than one page worth of ports, it might also be a good idea not to keep them on continuous pages. Either that, or simply put it in your documentation not to use indexed instructions on I/O ports.
While I've got everyone's attention, here's another question along the same vein.
I've read that the 6502 uses a sort of instruction pipelining, such that if a write isn't done on the last cycle of an instruction it pre-fetches the next opcode. My question is about the BRK, JSR, and JMP instructions. On their last cycle they modify the PC register. Some other instructions also seem to modify it on their last cycle by incrementing it. In these cases, is the next opcode still fetched? Is the wrong opcode fetched, followed by the right one?
Thanks in advance for your help.
I've read that the 6502 uses a sort of instruction pipelining, such that if a write isn't done on the last cycle of an instruction it pre-fetches the next opcode. My question is about the BRK, JSR, and JMP instructions. On their last cycle they modify the PC register. Some other instructions also seem to modify it on their last cycle by incrementing it. In these cases, is the next opcode still fetched? Is the wrong opcode fetched, followed by the right one?
Thanks in advance for your help.
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
I was glad to see John West's answer on the invisible reads and writes. I have WDC's cycle-by-cycle info, but couldn't find the same info on the NMOS 6502. Unfortunately, like John alluded, the logic analyzer is about the only way to check for yourself since you can't otherwise just single-cycle the processor and look. The problem with single-cycling an NMOS 6502 is that the clock can't be held in either state long enough to take a look and the buses by hand (which I _have_ done with a CMOS 6502).
> To avoid these garbage reads from I/O devices (like UART RCV) I
> believe everyone puts their I/O devices in address range 0-255. This
> seems like the work-around that everyone does.
This would be nice for faster I/O access, but depending on how much I/O you have, this method could eat up too much of your ZP. You can also simplify (and speed up) your address-decoding logic if you don't put this kind of limitation on the circuit. With nothing but a quad NAND (74HC04), you can have 16K of RAM and 32K of ROM (or vice-versa) and ten I/O ICs with a CS and CS\.
If you use the CMOS 6502, you won't have the random read problem we're talking about avoiding here. 6502-based microcontrollers generally have a lot of I/O in ZP, but that does not seem to be common in boards using '02 microprocessors and individual I/O ICs.
Garth
> To avoid these garbage reads from I/O devices (like UART RCV) I
> believe everyone puts their I/O devices in address range 0-255. This
> seems like the work-around that everyone does.
This would be nice for faster I/O access, but depending on how much I/O you have, this method could eat up too much of your ZP. You can also simplify (and speed up) your address-decoding logic if you don't put this kind of limitation on the circuit. With nothing but a quad NAND (74HC04), you can have 16K of RAM and 32K of ROM (or vice-versa) and ten I/O ICs with a CS and CS\.
If you use the CMOS 6502, you won't have the random read problem we're talking about avoiding here. 6502-based microcontrollers generally have a lot of I/O in ZP, but that does not seem to be common in boards using '02 microprocessors and individual I/O ICs.
Garth
Re: west
> What ever happened to Chris Jam? We had awesome 3 way
> programming challenges. His 38 cycles Julia plot is still a work of art...
If I was at work today, he'd be at the desk next to mine. We're both working on Playstation 2 games (all that C64 hacking had to be good for something). I think he's still dabbling in 6502, but the real world has a nasty habit of greatly reducing the time available for fun things.
I've never forgiven him for his 14 bit Mandelbrot iteration in less than twice the cycles of my fastest (at the time) 8 bit multiply :-)
> programming challenges. His 38 cycles Julia plot is still a work of art...
If I was at work today, he'd be at the desk next to mine. We're both working on Playstation 2 games (all that C64 hacking had to be good for something). I think he's still dabbling in 6502, but the real world has a nasty habit of greatly reducing the time available for fun things.
I've never forgiven him for his 14 bit Mandelbrot iteration in less than twice the cycles of my fastest (at the time) 8 bit multiply :-)
-
Guest
Magna wrote:
While I've got everyone's attention, here's another question along the same vein.
I've read that the 6502 uses a sort of instruction pipelining, such that if a write isn't done on the last cycle of an instruction it pre-fetches the next opcode. My question is about the BRK, JSR, and JMP instructions. On their last cycle they modify the PC register. Some other instructions also seem to modify it on their last cycle by incrementing it. In these cases, is the next opcode still fetched? Is the wrong opcode fetched, followed by the right one?
Thanks in advance for your help.
I've read that the 6502 uses a sort of instruction pipelining, such that if a write isn't done on the last cycle of an instruction it pre-fetches the next opcode. My question is about the BRK, JSR, and JMP instructions. On their last cycle they modify the PC register. Some other instructions also seem to modify it on their last cycle by incrementing it. In these cases, is the next opcode still fetched? Is the wrong opcode fetched, followed by the right one?
Thanks in advance for your help.
I've programmed on a Nintendo 8-bit game machine (6502 core w/o decimal mode) with a logic analyzer, and if you put a hardware breakpoint on the instruction after a conditional branch, it would always trigger. Was pretty confusing at first.
I never checked unconditional branches, but I'm guessing it probably happens there too.
Toshi
WRT exactly how the 6502 executes instructions (on a cycle-by-cycle level), I have had to address (no pun intended
) a similar problem for an emulator I'm writing.
I ended up using a Synertek reference document - in PDF format, found on the 6502.org site - for details, as it had an appendix at the end, listing details of all the documented instructions
After this, I used Adam Vardy's and Freddy Offenga's "Undocumented Instructions" lists to fill in the unofficial instructions.
HTH,
--Martin
I ended up using a Synertek reference document - in PDF format, found on the 6502.org site - for details, as it had an appendix at the end, listing details of all the documented instructions
After this, I used Adam Vardy's and Freddy Offenga's "Undocumented Instructions" lists to fill in the unofficial instructions.
HTH,
--Martin