Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
MOS Technology 6502
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
==Bugs and quirks== The 6502 had several [[hardware bug|bugs]] and quirks, which had to be accounted for when programming it: * The earliest revisions of the 6502, such as those shipped with some [[KIM-1]] computers, did not have a [[circular shift|ROR]] (rotate right memory or accumulator) instruction. In these chips, the operation of the opcode that was later assigned to ROR is effectively an ASL (arithmetic shift left) instruction that does not affect the carry bit in the status register. Initially, MOS intentionally excluded ROR from the instruction set, deeming it not of enough value to justify its costs. In reaction to many customer inquirires, MOS promised in the second edition of the MCS6500 Programming Manual (document no. 6500-50A) that ROR would appear in 6502 chips starting in 1976.<ref name="ROR" />{{efn|Eric Schlaepfer, who built a transistorized replica of the 6502 at monster6502.com, argues in his Youtube video "The 6502 Rotate Right Myth" (by TubeTimeUS) that according to Chuck Peddle and Bill Mensch there was no ROR bug. Instead, the instruction was not implemented at all as it was deemed unnecessary. Schlaepfer then compares screenshots from the early revision to later revisions of the 6502 and proves that the ROR instruction was not present in either the instruction decoding, wiring, or execution parts of the chip.}} The vast majority of 6502 chips in existence today do feature the ROR instruction; these include all those CPUs originally installed in popular fully-assembled microcomputers such as the Apple II and Commodore 64 lines, all of which were manufactured after 1976. * The [[NMOS logic|NMOS]] 6502 family has a variety of [[illegal opcode|undocumented instructions]], which vary from one chip manufacturer to another. The 6502 instruction decoding is implemented in a [[hardwired control|hardwired]] logic array (similar to a [[programmable logic array]]) that is only defined for 151 of the 256 available [[opcode]]s. The remaining 105 trigger strange and occasionally hard-to-predict actions, such as crashing the processor, performing two valid instructions consecutively, performing strange mixtures of two instructions, or simply doing nothing at all. Some hardware designers used the undefined opcodes to extend the 6502 instruction set by detecting when a certain undefined opcode is fetched and performing an extension operation externally to the processor while substituting a neutral (NOP-like) opcode to the 6502 in order to make it idle while the external hardware handles the extension operation. Also, some programmers utilized this feature to extend the 6502 instruction set by providing functionality for the unimplemented opcodes with specially written software intercepted at the BRK instruction's 0xFFFE vector.<ref>{{cite magazine |last=Moser |first=Carl W. |title=Add a Trap Vector for Unimplemented 6502 Opcodes |magazine=Dr. Dobb's Journal of Computer Calisthenics and Orthodontia |issue=31 |page=32 |url=http://archive.6502.org/publications/dr_dobbs_journal/dr_dobbs_journal_vol_04.pdf |date=January 1979 |location=Menlo Park, California |access-date=2017-01-07 |archive-date=2016-06-11 |archive-url=https://web.archive.org/web/20160611125516/http://archive.6502.org/publications/dr_dobbs_journal/dr_dobbs_journal_vol_04.pdf |url-status=live}}</ref><ref>{{cite magazine |last=Harrod |first=Dennette A. |title=The 6502 Gets Microprogrammable Instructions |magazine=BYTE |volume=5 |issue=10 |page=282 |url=https://archive.org/details/byte-magazine-1980-10 |date=October 1980 |location=Peterborough, New Hampshire |access-date=2017-01-07}}</ref> All of the undefined opcodes have been replaced with [[NOP (code)|NOP]] instructions in the [[65C02]], an enhanced [[CMOS]] version of the 6502, although with varying byte sizes and execution times. (Some of them actually perform memory read operations but then ignore the data.) In the [[WDC 65C816|65C802/65C816]], all 256 opcodes perform defined operations. * The 6502's [[indirect branch|memory indirect jump]] instruction, <code>JMP (<address>)</code>, has a nonintuitive limitation which many users consider a defect. If <var><address></var> is [[hexadecimal|hex]] <var>xxFF</var> (i.e., any word ending in <var>FF</var>), the processor will not jump to the address stored in <var>xxFF</var> and <code>xxFF+1</code> as expected, but rather the one defined by <var>xxFF</var> and <var>xx00</var> (for example, <code>JMP ($10FF)</code> would jump to the address stored in 10FF and 1000, instead of the one stored in 10FF and 1100). This can be avoided simply by not placing any indirect jump target address across a page boundary, and the MOS Technology MCS6500 Programming Manual gives reason to believe that this was the intention of the designers of the 6502, in order to save space on the chip that would have been used to implement the more complex behavior of conditionally adding 1 clock cycle to propagate the carry when necessary. This ostensible defect continued through the entire NMOS line but was corrected in the CMOS derivatives. * The NMOS 6502 indexed addressing across page boundaries will do an extra read of an invalid address in the page of the base address (to which the index is added). This characteristic may cause random issues by accessing hardware that acts on a read, such as clearing timer or IRQ flags, sending an I/O handshake, etc. The extra read can be predicted and managed to avoid such problems, but only with special care in both hardware and software design. This flaw continued through the entire NMOS line but was corrected in the CMOS derivatives, in which the processor does an extra read of the last instruction byte. * The 6502 [[read–modify–write]] instructions perform one read and two write cycles. First, the unmodified data that was read is written back, and then the modified data is written. This characteristic may cause issues by twice accessing hardware that acts on a write. This anomaly continued through the full NMOS line but was fixed in the CMOS derivatives, in which the processor does two reads and one write cycle. [[Defensive programming]] practice will generally avoid this problem by not executing read/modify/write instructions on hardware registers. * The N (result negative), V (sign bit overflow) and Z (result zero) [[status register|status flags]] are generally meaningless when performing arithmetic operations while the processor is in [[binary-coded decimal|BCD]] mode, as these flags are undefined in decimal mode and have been empirically shown to reflect the binary, not BCD, result. This limitation was removed in the CMOS derivatives, at the cost of one added clock cycle for an ADC or SBC instruction in decimal mode (except on the 65C816). Therefore, this feature may be used to distinguish a CMOS processor from an NMOS version (by relying on the undocumented behavior of the NMOS version).<ref>{{cite web |url=http://www.s-direktnet.de/homepages/k_nadj/cputest.html |archive-url=https://web.archive.org/web/20080102014138/http://www.s-direktnet.de/homepages/k_nadj/cputest.html |title=65c02, 6502, 65816 ??? CPU sells but who's buying... |date=19 June 1997 |author=Draco |archive-date=2 January 2008 |url-status=dead}}</ref> * If the 6502 happens to be in BCD mode when a hardware interrupt occurs, it will not revert to binary mode. This characteristic could result in obscure bugs in the interrupt service routine (ISR) if it fails to clear BCD mode before performing any arithmetic operations. The 6502 programming manual thus requires each ISR to reset or set the D flag if it uses the ADC or SBC instruction, but occasionally a human programmer may mistakenly omit to do this, causing a bug. For example, the [[Commodore 64]]'s [[KERNAL]] did not correctly handle this processor characteristic, requiring that [[interrupt request|IRQ]]s be disabled or re-vectored during BCD math operations. This issue was addressed in the CMOS derivatives also, by making reset and all interrupts automatically reset the D flag. (The change has the one disadvantage that it makes a [rare] program that operates continuously in decimal mode slightly longer and slower, as now every ISR must ''set'' the D flag before executing ADC or SBC.) * The 6502 instruction set includes BRK (opcode $00), which is technically a [[software interrupt]] (similar in spirit to the SWI mnemonic of the [[Motorola 6800]] and [[ARM architecture family|ARM]] processors). BRK is most often used to interrupt program execution and start a [[Machine code monitor|machine language monitor]] for testing and debugging during software development. BRK could also be used to route program execution using a simple jump table (analogous to the manner in which the [[Intel 8086]] and derivatives handle software interrupts by number). However, if a maskable [[hardware interrupt]] occurs when the processor is fetching a BRK instruction, the NMOS version of the processor will fail to execute BRK and instead proceed as if only the hardware interrupt had occurred. This fault—an unequivocal hardware bug—was corrected in the CMOS implementation of the processor, which first calls the ISR for the hardware interrupt and then executes the BRK instruction. * When executing JSR (jump to subroutine) and RTS (return from subroutine) instructions, the return address pushed to the stack by JSR is that of the last byte of the JSR operand (that is, the most significant byte of the subroutine address), rather than the address of the following instruction. This is because the actual copy (from [[program counter]] to [[stack (abstract data type)|stack]] and then conversely) takes place before the automatic increment of the program counter that occurs at the end of every instruction.<ref>{{cite book |chapter-url=http://www.atariarchives.org/roots/chapter_6.php |title=Atari Roots – A Guide To Atari Assembly Language |chapter=6 |first=Mark |last=Andrews |year=1984 |publisher=Datamost, Incorporated |isbn=0-88190-171-7 |access-date=2008-06-14 |archive-date=2008-04-24 |archive-url=https://web.archive.org/web/20080424093352/http://www.atariarchives.org/roots/chapter_6.php |url-status=live}}</ref> This characteristic would go unnoticed unless the code examined the return address in order to retrieve parameters in the code stream (a 6502 programming idiom documented in the ''ProDOS 8 Technical Reference Manual''). It remains a characteristic of 6502 derivatives to this day. The original MCS6500 Programming Manual points it out and explains the reason: it saves one clock cycle in the JSR by not incrementing the PC before pushing it, while in the RET instruction, the deferred increment of the pulled PC is overlapped with other steps and adds no clock cycle. As designed, a JSR and RET take 12 clock cycles total; if the JSR pushed the incremented PC, the call and return would take 13 clock cycles. * The read access of the CPU can be delayed by setting the RDY pin to low temporarily. However, during write access, which can take up to three consecutive clock cycles for a BRK instruction, the CPU will stop only in the next read cycle.<ref>{{Cite book |title=6500 Series Hardware Manual; 2nd Ed |publisher= MOS Technology, INC. |date=January 1976 |chapter=1.4.1.2.8 RDY--Ready (p.37)}}</ref> This quirk was corrected in the CMOS derivatives and also in the 6510 and its variants.
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)