TL;DR:
Why doesn't the NMOS 6502 have the illegal instruction, STA immediate?
It doesn't, because $89 is none of the undecoded ('illegal') operations, but decoded as NOP by design.
So in a reference of illegal opcodes $89 appears to be NOP zp, which I imagine reads a byte from the zero page and ignores it.
That reference seems off. $89 is a NOP #imm, much like already implied by your question. It's executed in two cycles, there is no ZP access of any kind.
As I recall, the related 6800 and 6801 have an illegal store immediate instruction
That would be the infamous STA* instructions (*1), except that these do not store the value into the immediate field of the instruction, but after the instruction, at the location where the next instruction would be - except execution continues after that (*2). The immediate value gets ignored.
Obviously, it would not have been useful.
Not really, so why should they have bothered to implement it, as doing so would have needed to add at least one (more like two or three) additional ROM entries (*3).
So Why Is It That Way
When it comes to the 'illegal' opcodes (*4) it helps to differentiate between the 'tamed' ones and the 'wild' beasts. The differentiation becomes quite obvious when looking at the opcode chart:
(Taken from Norbert Landsteiner's 6502 "Illegal" Opcodes Demystified page - with some colouring added (*5))
By marking the various types of undefined opcodes it becomes clear that there are three different groups:
- The Good (Green) are in tamed as NOPs by design
- The Bad (Red) are the wild ones everbody talks about
- The Ugly (Pink), sending the CPU into an infinite T1 loop
The questioned $89 falls into the green group. They are well decoded withing their group (CC=00/01/10) and executed as NOP by design, because they do not make any sense - $80, STY #imm
, is a similar case.
There are two exceptions to this, $8C SHY abs,X and $8E SHX abs,y (*6)
The read ones, mix up functionality from other groups as their group (CC=11) is simply not decoded at all. They are the real orphans of the 6500 design - and like orphans they look for surrogate parents in group CC=01 and 10 (*7).
The pink group in turn are somewhat similar. While their group line (CC=10) is decoded, there are no entries in the decode ROM except for AAA=1xx BBB=x00 (light green), which gives that $A2, LDX #imm
its 3 siblings work as intended. Having no entries makes them stuck in a never ending T1 cycle, reading the second byte over and over until freed by RESET.
Bottom line: $89 has been made a NOP on purpose by design. It might be undefined, but is not really a member of the 'illegal' bunch.
1 - STAA ($87), STAB ($C7), STX ($8F) and STS ($CF), each being two byte opcodes with the second byte being ignored, store their register after the instruction and continue with execution thereafter. This means the STA variant would be a 3 byte structure, where the value of A or B would be stored in the third, while ST* would be 4 bytes storing IX or SP into bytes 3 (low) and 4 (high).
*2 - Now, that would have been a quite interesting use case for self modifying code, kind of an EX-instruction where the to be executed instruction had to be prepared in an accumulator, for single byte, or IX, for two byte instructions. Not that it would have saved code or make it more elegant, just interesting.
*3 - It would at least need to suppress the increment of the PC, like done with a NOP, during the second cycle, followed by the store and an increment after the store, so maybe 3 additional lines or ~2.5% additional ROM for an instruction with rather dubious usability?
*4 - Naming is a real crux here, as the term 'illegal' implies something that not really exists in an instruction set. Opcodes not defined to carry out some operation (aka 'unused') are simply that: Undefined/Unused Opcodes.
The story could end here, except that the 6500 design added an additional pitfall by not straight making all unused do nothing (like the 65C02 later corrected), but some of them were left undecoded, resulting in additional functionality. Not intended but deterministic - as long as thedcoder was not changed.
*5 - Norbert Landsteiner's page goes way beyond listing the 'illegal' opcodes, but dives deep into the structure, following Neil Parkers well known The 6502/65C02/65C816 Instruction Set Decoded
*6 - Personally I would see them as leftover/unfinished implementation of STY abs,X
and STX abs,Y
, but that might be a different story.
*7 - I know that this is due the way that the groups are decoded into three select lines within the decoder and 11 simply activating the group 1 (CC=01) line as well as the group 2 (CC=10) line. adding one gate here could have prevented all of that and saved us all the hype about 'secret' opcodes and so on.
STA #
instruction would do.