6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 9:41 pm

All times are UTC




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Intentional 6502 "Bugs"
PostPosted: Fri Feb 03, 2006 11:05 am 
Offline

Joined: Tue Dec 30, 2003 10:35 am
Posts: 42
I get annoyed whenever I encounter people referring to some of the unexpected behaviors of 6502 instructions as bugs (for example, JSR pushing the address of the byte before next instruction). Basically the logic seems to be "This instruction doesn't behave how I want it to. It's a bug!" I'm all for pointing out faults, but these are not faults in the 6502, unless you consider it a fault that it was one tenth the cost and significantly faster than the other chips at the time.

A bug is some aspect of behavior that is unintentional and would likely be simple to fix; in most cases I think that the designers of the 6502 knew about and made these tradeoffs intentionally, weighing the reduced transistor count against fully consistent and straight-forward behavior. The only things that could be considered actual bugs were places where the documentation didn't mention this subtle behavior. Put another way, if you consider the following to be documentation of the 6502 chip, then there are no bugs, just aspects of behavior that you must take into account to avoid putting bugs into your code/emulator.

I did a quick search for "6502 bugs" and put together the things I found. This might have inaccuracies; it's just for discussing whether they really are unintentional and easily fixable without adding lots of transistors, and how significant the impact is on the programmer.

- Zero-page indexing wraps around instead of going into page 1.

- When the vector of an indirect address begins at the last byte of a page, the second byte is fetched from the beginning of that page rather than the beginning of the next.

- Return address pushed on the stack by JSR is one less than actual next instruction. RTS increments PC after popping. RTI doesn't.

- The status bits pushed on the stack by PHP have the breakpoint bit set.

- The D (decimal mode) flag is not defined after RESET.

- The D (decimal mode) flag is not cleared by interrupts.

- The ADC and SBC instructions don't set N,V, and Z status bits if decimal mode is on. C status is set correctly.

- If an interrupt occurs on a BRK instruction, the breakpoint is ignored.

- Undefined op-codes do strange things, some lock up the CPU.

- When adding a carry to the MSB of an address, a fetch occurs at a garbage address. The CMOS chips refetch the last byte of the instruction.

- When doing a fetch-modify-store instruction (INC, DEC, ASL, LSR, ROL, ROR) garbage is stored into the location during the "modify" cycle... followed by the "real" store cycle which stores the correct data. The CMOS chips do a second fetch instead of a garbage store.


Top
 Profile  
Reply with quote  
PostPosted: Fri Feb 03, 2006 4:57 pm 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
blargg wrote:
I get annoyed whenever I encounter people referring to some of the unexpected behaviors of 6502 instructions as bugs (for example, JSR pushing the address of the byte before next instruction). Basically the logic seems to be "This instruction doesn't behave how I want it to. It's a bug!" I'm all for pointing out faults, but these are not faults in the 6502, unless you consider it a fault that it was one tenth the cost and significantly faster than the other chips at the time.


Indeed, the fact that JSR pushes PC+2 instead of PC+3 stems from the fact that the PC is pre-incremented, not post-incremented, when fetching an instruction. Hence, the final +1 occurs on each instruction fetch.

Quote:
- If an interrupt occurs on a BRK instruction, the breakpoint is ignored.


I believe this to be a bug, on the basis that the interrupt should execute first (higher priority), then it should return to the BRK instruction, which is re-executed, thus allowing the BRK to execute.

The bug can expose itself in some circumstances -- for example, using BRK as a breakpoint instruction (one of its uses) -- imagine telling a debugger to single-step, only to have it run the program to completion. Imagine if this happens only periodically and sporadically.

IIRC, 65C02 and 65816 CPUs fixed this.

Quote:
- Undefined op-codes do strange things, some lock up the CPU.


I don't think these were ever documented as bugs, as it's pretty clear this was a cost-cutting measure.

Quote:
- When adding a carry to the MSB of an address, a fetch occurs at a garbage address. The CMOS chips refetch the last byte of the instruction.


This is an artifact of the bus architecture in use. Since the bus interface has no real "valid bus cycle" indication, it must rely on phi2 to perform this action. So, while some internal activity is taking place, you end up with what appears to be sporadic/spurious bus fetches.

The 65816 at least now has a VPA and VDA set of signals, which are properly set to '00'b when performing an internal operation of this sort.

Quote:
- When doing a fetch-modify-store instruction (INC, DEC, ASL, LSR, ROL, ROR) garbage is stored into the location during the "modify" cycle... followed by the "real" store cycle which stores the correct data. The CMOS chips do a second fetch instead of a garbage store.


This *IS* a bug -- consider doing an INC on an I/O port in a heart defribulator (one of the many applications for the 6502 today). Would you like garbage being dumped to an I/O port that could potentially affect your life? 6502s are still used heavily in automotive environments as well, where they control things like air bags and such. Do you want your airbag to glitch out because of some garbage byte stored to an I/O port?

Remember, INCing and DECing an I/O port is a VERY common way to affect a single bit with the minimum number of clock cycles, so in real-time, deeply embedded environments, this IS an issue. A potentially life threatening issue.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Feb 03, 2006 6:42 pm 
Offline

Joined: Tue Dec 30, 2003 10:35 am
Posts: 42
Quote:
This *IS* a bug -- consider doing an INC on an I/O port in a heart defribulator (one of the many applications for the 6502 today). Would you like garbage being dumped to an I/O port that could potentially affect your life? 6502s are still used heavily in automotive environments as well, where they control things like air bags and such. Do you want your airbag to glitch out because of some garbage byte stored to an I/O port?


I'd rather the programmer take into account the behavior of the instructions.

If the designers intended this to happen, then it's not a bug, regardless of how inconvenient it is for people wanting to use it on memory-mapped I/O locations. I'm sure they knew of these garbage fetches. The question is, how much extra silicon does it take to avoid this?

Quote:
Remember, INCing and DECing an I/O port is a VERY common way to affect a single bit with the minimum number of clock cycles, so in real-time, deeply embedded environments, this IS an issue. A potentially life threatening issue.


It seems like a great way to introduce bugs, even if INC/DEC don't write a garbage byte, because it requires that you know the value of bit 0 beforehand; if you get it wrong, you'll affect other bits, possibly all seven of them (DEC when the value is 0 or INC when the value is 0xFF).


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri Feb 03, 2006 8:43 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8546
Location: Southern California
I'd call it a bug only if it deviated from the design intentions. Some things are called "quirks" in the tables comparing the NMOS version to the CMOS version perhaps because it was found out after the NMOS processor was out that, for example, it would be desirable for the D flag to start in a predetermined state at the beginning of an interrupt. Having the interrupt sequence clearing it automatically is a good feature they should have thought of sooner-- or maybe, as mentioned already, they were just on too tight a transistor budget the first time around.

Sometimes bugs are known at the time the product is introduced but the manufacturer has concluded that they're not major enough to hold up orders. They might document it and say, "We hope to have it fixed in the next production run" (or as soon as practical). Some bugs are not easy or economical at all to fix. As I see it, there's really not much sense in criticizing the '02 for bugs since they were all corrected in the CMOS version that first came out about 24 years ago.

ZP indexing into page 1 would be kind of cool, but then you'd need an additional clock to increment ADH if necessary. You'd save an operand byte and spread the extra address modes into page 1, but you wouldn't get all the speed of ZP addressing. The designers actually did intend that ADH would always be kept at $00 for ZP addressing. If they really had intended that ZP indexing be able to take you into page 1, they probably would have put the stack in page 2 instead.

I might also prefer that RTS and RTI worked the same as far as return addresses go, but you couldn't use the same routine as both an ISR and a subroutine anyway, because the ISR needs to restore the status too. I can't think of any actual disadvantage there is, except the matter of understanding it all.

As for B in a pushed status byte which we discussed at length at http://www.6502.org/forum/viewtopic.php?t=24 , I have to think that the interrupt call itself, whether from hardware or BRK, is the only time it would be valid anyway (although it seems like PHP should always make B in the stacked status byte to be 0 instead of 1). Without going into detail right now about why, I can imagine situations where you could get yourself in trouble if B were an actual bit in P that could be pushed with PHP or tested. The whole reason for the thread however was because it is indeed confusing.

The bug I'm looking forward to seeing fixed is with the 65c22 using an external shift clock on its synchronous serial port. WDC's owner says that it's simple designwise, but is a non-trivial matter considering inventory, mask, test and production costs.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat Feb 04, 2006 12:07 am 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
blargg wrote:
I'd rather the programmer take into account the behavior of the instructions.


Except the precise behavior of the instructions were not documented back then. All these things came about through trial and error, and looking a logic analyzer to the bus to see what is going on. Note that Western Design Center is the *only* processor manufacturer today who provides a cycle-by-cycle detail of how their CPUs work.

Quote:
If the designers intended this to happen, then it's not a bug, regardless of how inconvenient it is for people wanting to use it on memory-mapped I/O locations. I'm sure they knew of these garbage fetches. The question is, how much extra silicon does it take to avoid this?


Unless you have hard experience designing and then later fixing finite state machines implemented in hardware (remember the 6502 and 65816 do not use microcode), it can be quite a daunting task.

Quote:
It seems like a great way to introduce bugs, even if INC/DEC don't write a garbage byte, because it requires that you know the value of bit 0 beforehand; if you get it wrong, you'll affect other bits, possibly all seven of them (DEC when the value is 0 or INC when the value is 0xFF).


Unless you are writing software which runs under a multitasking OS environment, 99.99% of the time, you'll know precisely what the port values are, thus allowing you to pull this trick off without a hitch. In many cases, the port's layout is specifically engineered to support this practice. In practice, this is rarely a problem on small systems.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: