Extra Instructions Of The 65XX Series CPU (1996)
Posted by embedding-shape 5 days ago
Comments
Comment by JetSetIlly 5 days ago
https://forums.atariage.com/topic/385516-fingerprinting-6502... https://forums.atariage.com/topic/385521-fingerprinting-6502...
Comment by rossjudson 5 days ago
Comment by embedding-shape 5 days ago
Comment by cyco130 5 days ago
The decoder is the part of the CPU that maps instruction opcodes to a set of control signals. For example "LDA absolute" (opcode 0xA5) would activate the "put the result in A" signal on its last cycle while "LDX absolute" (opcode 0xA6) would activate the "put the result in X" signal. The undocumented "LAX absolute" (opcode 0xA7) simply activates both because of the decoder logic's internal wiring, causing the result to be put in both registers. For other undocumented opcodes, the "do both of these things" logic is less recognizable but it's always there. Specifically disallowing these illegal states (to make them NOPs or raise an exception, for instance) would require more die space and push the price up.
See here[1] for example to get a sense of how opcode bits form certain patterns when arranged in a specific way.
[1] https://www.nesdev.org/wiki/CPU_unofficial_opcodesComment by kimixa 5 days ago
Wiring all the "illegal" instructions to a NOP would have taken a fair bit of extra logic, and that would have been a noticeable chunk of the transistor budget at the time.
Comment by NobodyNada 5 days ago
Comment by ruk_booze 5 days ago
Comment by gblargg 5 days ago
Comment by adrian_b 4 days ago
The manufacturer did not document them, so they really were undocumented.
The same happened with many other CPUs, like Zilog Z80, Intel 8086 and the following x86 CPUs.
They all had undocumented instructions, which have been discovered by certain users through reverse engineering.
Some of the undocumented instructions were unintended, so they existed only due to cost-cutting techniques used in the design of the CPU, therefore the CPU manufacturer intended to remove them in future models and they had a valid reason to not document them.
However a few instructions that were undocumented for the public were documented for certain privileged customers, like Microsoft in the case of Intel CPUs, so they were retained in all future CPU models, for compatibility.
Comment by bonzini 4 days ago
Comment by adrian_b 4 days ago
80386 also had an undocumented LOADALL instruction, but it was encoded with a different opcode, as it was incompatible with the 80286 LOADALL, by restoring many more registers.
After 1990, no successors to LOADALL were implemented, because Intel introduced the "System Management Mode" instead, which provided similar facilities and much extra.
Comment by bonzini 2 days ago
It amuses me that the SMM state save area still lists the descriptor cache fields as reserved, even now that (thanks to virtualization) descriptor caches and big real mode finally have become an official feature of the architecture.
Comment by djmips 4 days ago
Comment by Scaevolus 4 days ago
Comment by forinti 2 days ago
https://github.com/TobyLobster/multiply_test
Which is, I guess, the reason the folks at Acorn decided to put a barrel shifter in the first ARMs.
Comment by Dwedit 4 days ago
To understand, it helps if you write out the instruction table in columns, so here's the CMP and DEC instructions:
Byte C1: (add 4 to get to the next instruction in this table)
CMP X,ind [x indirect, read instruction's immediate value, add X, then read that pointer from zeropage, written like CMP ($nn,x)]
CMP zpg [zeropage, written like CMP $nn]
CMP # [immediate value, written like CMP #$nn]
CMP abs [absolute address, written like CMP $nnnn]
CMP ind,Y [indirect Y, read pointer from zeropage then add Y, written like CMP ($nnnn,Y)]
CMP zpg,X [zeropage plus X, add X to the zeropage address, written like CMP $nn,X]
CMP abs,Y [absolute address plus Y, add Y to the address, written like CMP $nnnn,Y]
CMP abs,X [absolute address plus X, add X to the address, written like CMP $nnnn,X]
So that's 8 possible addressing modes for this instruction.
Immediately afterwards:
Byte C2: (add 4 to get to the next instruction in this table)
???
DEC zpg
DEX
DEC abs
???
DEC zpg,X
???
DEC abs,X
That's 5 possible addressing modes. So where's "DEC X,ind", "DEC ind,Y", and "DEC abs,Y"? They don't exist.
Table for Byte C3 is 8 undocumented instructions that aren't supposed to be used. So people determined what the instruction did. Turns out, it's a combination of CMP and DEC, so people named the instruction "DCP".
Byte C3:
DCP X,ind
DCP zpg
???
DCP abs
DCP ind,Y
DCP zpg,X
DCP abs,Y
DCP abs,X
Unlike the "DEC" instruction, you have the "X,ind", "ind,Y", and "abs,Y" addressing modes available. So if you want to decrement memory, and don't care about your flags being correct (because it's also doing a CMP operation), you can use this DCP instruction.
Same idea with INC and SBC, you get the ISC instruction. For when you want to increment, and don't care about register A and flags afterwards.