Parts of the 6502 opcode map are fairly regular, and parts of it aren't. One bit that strikes me as really weird is the decoding of LD_ instructions, in relation to the decoding of other ALU instructions.
Well, for one,
LDY do not use the ALU, but more importantly, the way you decode it is a bit off. See below for a more detailed view on the 6500 encoding.
LDY immediate encoding is fine. The quirk within the transfer instructions is at
TYA which is
98 instead of
88. And there is no technical reson why it has been done that way. There are similar other encodings, especially around the increment/decrement for the index registers.
6500 Opcode encoding
The format isn't built the way you assume. While the general structure follows a 3-3-2 stucture like
reading it requires to start at the end with
tt defining an instruction group
This is even visible the way the decoder hardware is done, as tt is not taken as seperate bits like all others, but turned into 3 lines for the three groups used, thus being the primary differentiation for all decoding.
(To simplify this, lets push group 0 (tt=
00) to the end.)
01 is the most simple. Here
aaa selects one of 8 instructions (
bbb defines an addressing mode (
ABS,X). Drawing this up(*1) will give a filled table with one empty spot at
89, where the nonsensical
STA IMM would end up (*2).
Group 2 (tt=
10) uses a similar encoding with
aaa as instruction and
bbb as addressing, just with different opcodes (
INC) and some addressing rearranged (
IMM) or not used (
ABS,Y). Here the
STX A and
LDX A are occupied exactly by
TAX. Similarly, the 'unused' addressing
110 is used with
LDX to form
Group 2 is also the point where they started to screw it up, as
STX ABS,Y should be, is left out. And while the logical position for
DEC A is filled by
NOP resides where a
INC A could be (*3).
Group 3 (tt=
11) is the most simple of all, as it doesn't exist :))
Group 0 (tt=
00) finally is where it gets crowded. At first it's much like group 2. The instructions are now (na,
BIT, na, na,
CPX) while the general addressing modes are the same as with group 2 plus
REL now overwrites (in a table for group 0) the instruction with
FLAG with flag manipulation - with the exception, that
CLV ended up where
SEV would be if it existed - and
TYA taking up its space.
Similarly, the stack operations lie diagonally to the encoding - and again
TAY is screwing up the somewhat regular placement of increment/decrement for the index registers.
JMP does follow the scheme in so far as the
01x.011.00 encoding used the
The remaining instructions (
RTS) fall completely out of context. But they show at least some inherent logic, especially when considering that
BRK is internally fed into the decoder also whenever a hardware interrupt occurs.
*1 - Drawing tables on SE sucks - so please use your imagination.
*2 - A hole filled up by the 65C02 with
BIT IMM, since the 'rightful' spot
20 was taken by the irregular
*3 - as a result the 65C02 had to put
DEC A onto new places.