5 ms·
How MOS 6502 illegal opcodes work
- qawwads 3y ago> illegal Seriously, stop using that word for things that aren't actually illegal.
- JohnFen 3y agoIt's been a technical term since forever. I don't really see anything wrong with it, outside of it maybe confusing laypeople.
- daneel_w 3y agoUndocumented is a better term for the MOS 6502 in my opinion, because these opcodes aren't invalid, they can't be trapped and they don't throw an exception.
- cdcarter 3y agoThe 6502 was reimplemented in fresh silicon several times by different manufacturers, its more "undefined" than "undocumented". Some clones use them as actual new opcodes specific to that manufacturer. Some might do what the MOS chip did. Some might throw the processor into an unrecoverable state.
- daneel_w 3y agoThis is why I'm emphasizing MOS 6502. I'm well-familiar with the most popular alternative, WDC's 65C02, where all of the undocumented opcodes execute as NOP with no changes to internal registers/flags or to memory, but with one or two harmless side effects on timing behavior.
- daneel_w 3y agoThe stable ones are thoroughly used in C-64 software these days. A more detailed matrix with extra information can be found here: http://www.oxyron.de/html/opcodes02.html http://www.oxyron.de/html/opcodes02.html
- zoky 3y agoWhat is wrong with me that I see an article about hacking a microprocessor that was released nearly a decade before I was born and I go, “Ooooh, gotta check that out!”
- jordigh 3y agoNothing. Old tech is fun for many reasons: 1) It's still simple enough that you can actually get a full diagram of the processor and actually have hope of understanding it. 2) It's interesting enough to actually produce good things. Blockbusters like Super Mario Bros 3 were based on this tech. The Terminator runs on the 6502. The low-cost CPU was comparatively as ubiquitous as the Intel architecture is today. 3) Limitations breed creativity and ingenuity. When you only have uint8 as your only data type, the kind of tricks you have to do to get a simple physics engine working are very interesting. https://www.youtube.com/watch?v=9UP7HImbAlA&t=517s https://www.youtube.com/watch?v=9UP7HImbAlA&t=517s So combined with not-too-complicated but complicated-enough-to-be-useful is basically why old tech is fun.
- vardump 3y agoMost importantly, Futurama's Bender runs on a 6502.
- systems_glitch 3y ago#1 is the main reason I hack on old stuff, #3 is also present. The 6502 in particular is a nice choice since they're still made and available (Mouser carries them), there's a zillion vintage things that use them if you want something actually old, there's hobbyist kits/preassembled if you want something new, and it's a super easy CPU to interface to, especially for trivial cases.
- monkpit 3y agoIs an illegal opcode something that was intentionally added to the instruction set but was disabled by the manufacturer? Or is it a side effect of calling an undefined operation?
- zoky 3y agoIt can be both. Anything not officially defined in the spec is an illegal opcode. Intel had a couple of opcodes that were clearly supposed to have been functional, but didn’t make any sense to use—I believe one such opcode popped the code segment register, which would have effectively served as a “jump to random memory” instruction as it would run the next instruction per the IP register but in a totally different part of memory, so it didn’t make any sense to document it as there was no use for it. And they had at least one other instruction introduced as a copyright trap, which they obviously wouldn’t document. And there were a few more that were undocumented but were aliases of other instructions due to the way the 8086 handled bit masking.
- hota_mazi 3y agoYup, that's POP CS, 0x0f. Since it made no sense to use, it became the way 286 and later processors used to indicate multibyte opcodes. When a 286 is running the code, encountering a 0x0f means that the following opcode is multibyte, while on an 8088, all opcodes are single bytes.
- cesarb 3y ago> while on an 8088, all opcodes are single bytes. According to a recent article on undocumented 8086/8088 opcodes (https://www.righto.com/2023/07/undocumented-8086-instructions.html https://www.righto.com/2023/07/undocumented-8086-instruction...), there are some two-byte opcodes: "For most of the 8086 instructions, the first byte specifies the instruction. However, the 8086 has a few instructions where the second byte specifies the instruction: the reg field of the ModR/M byte provides an opcode extension that selects the instruction."
- daneel_w 3y ago
- bartvk 3y agoThis is such a fun website. This guy also wrote something about recreating Apple I Basic: https://www.pagetable.com/?p=35 https://www.pagetable.com/?p=35
- curiousObject 3y agoThere’s some comments about those funny opcodes from a 2021 post on hacker news, that includes links to this site and other interesting sources https://news.ycombinator.com/item?id=27402655 https://news.ycombinator.com/item?id=27402655
- bonzini 3y agoThe question is why were the $AD and $AE instructions encoded in the PLA with don't-care bits (causing both of them to fire for an xxxxxx11 pattern such as $AF, instead of none)?
- wzdd 3y agoIt could be related to the fact that if an instruction was not handled at all the CPU would lock up (search https://www.righto.com/2016/02/reverse-engineering-arm1-instruction.html https://www.righto.com/2016/02/reverse-engineering-arm1-inst... for "kill"), so rather than add extra logic for illegal instructions the designers just decided to add undocumented ones. The only problem with this theory is that there are in fact several opcodes which will make a 6502 lock up...
- anticensor 3y agoThey could have wired those instructions as a NOP, rather than aliasing another opcode...
- Someone 3y agoThey could, but transistors were expensive at the time. Why spend valuable space making sure all instructions are well defined? On modern CPUs designed for multi-processing and protected memory, you don’t want some instructions to accidentally cross privilege boundaries (can’t have an ‘illegal’ opcode accidentally be non-privileged and modify some privileged processor state), so you have to do some of that. Transistors also are cheap, so you can afford to.
- NobodyNada 3y agoThe 6502 decodes instructions by matching the combination of opcode byte + cycle counter against bitmasks stored in a “ROM”. The ROM outputs signals to the control logic telling it to do things like accessing a register, performing an ALU operation, accessing memory, advancing to the next instruction, etc. This design meant the designers could efficiently reuse functionality across multiple instructions by assigning them similar opcodes, and creating a decode ROM entry that matches all of those opcodes. This becomes clearer if you look at an opcode matrix: https://www.nesdev.org/wiki/CPU_unofficial_opcodes https://www.nesdev.org/wiki/CPU_unofficial_opcodes For example, from a brief glance at the chart I noticed patterns like: - All of the instructions matching the bit pattern `xxx111xx` read an operand from memory using the ‘absolute, y’ addressing mode - All instructions matching the bit pattern `xxxyyy01` perform an ALU operation, where xxx specifies an operation and yyy specifies an addressing mode (with the exception of xxx=100, which performs a store rather than an ALU op) - Branch instructions all match the pattern `xxx10000`, where xxx specifies the predicate - … and many more similar patterns. The decode ROM looks at the opcode and says “if these bits are 1s and those bits are 0s, do this on that cycle”. So if you feed it an opcode that is not valid, then it activates arbitrary bits of logic based on whatever patterns in the decode ROM your opcode happened to trigger. The result is that the processor behaves strangely, combining bits and pieces of logic meant for other, sometimes unrelated instructions. Some opcodes cause the CPU to lock up entirely, because they don’t match any patterns in the decode ROM that trigger the “go to the next instruction” logic. Understanding how instruction decoding works will hopefully help reframe questions about undocumented opcodes: - “Why did they add undocumented opcodes?” They didn’t add them, they exist by happenstance — feed the instruction decoder garbage input, you get garbage output. - “Why didn’t they just make them all NOPs/crashes/aliases of existing instructions?” Because that would have required an enormous amount of extra logic on the decode ROM — now your decoder needs to support 256 opcodes rather than ~160, and it can’t do nearly as many partial-matching shortcuts. On a processor that only has ~3,000 transistors, you’re not going to add hundreds more to decode opcodes that programs will never (intentionally) use. - “Why didn’t they just document them?” Because 1) they didn’t add them on purpose in the first place, so they may not have thoroughly understood their behavior & it may have changed throughout development/hardware revisions 2) most of them don’t do anything useful, 3) many of them behave in very strange and unpredictable ways, and 4) they wanted to leave the opcode space open so that future backwards-compatible processors could use them to do actually useful things.
- flohofwoe 3y agoIf you want to play around with those opcodes on a netlist simulation of the 6502, may I recommend: https://floooh.github.io/visual6502remix/ https://floooh.github.io/visual6502remix/ ...which is essentially a WASM version of the famous visual6502.org with a couple more features (like an integrated assembler): http://www.visual6502.org/JSSim/index.html http://www.visual6502.org/JSSim/index.html (check out Help => About for credits) Unfortunately the assembler I used (ASMX) doesn't seem to support the illegal opcodes, so you need to enter the opcodes as hex values directly into the memory tab (the disassembler window recognizes the opcodes though).
- Floppyrom 3y agoYou can find here the most up to date exploration in how these opcodes work: https://csdb.dk/release/?id=226987 https://csdb.dk/release/?id=226987
- OnlyMortal 3y agoI recall some been used in copy protection schemes so that a monitor or disassembler wouldn’t process them. So, I created my own disassembler that did as many were documented.