The MOS 6502 CPU was introduced in September of 1975, and while the documentation described the three shift/rotate instructions ASL, LSR and ROL, the ROR instruction was missing – the documentation said that ROR would be available in chips starting in June 1976. In fact, the reason for this omission was that the instruction, while being present, didn’t behave correctly. Only few 6502s with the defect are in existence, and nobody seemed to have checked what was actually going on in these chips.
Simon C got my KIM-1 working again, which has a 6502 from week 51 of 1975. There are 512 possible inputs to ROR (8 bit A plus 1 bit C; assuming it doesn’t have dependencies on other registers), and roughly two bytes of output: the 8 bit result and the processor status (flags) register. We ran the following programs on the KIM-1 – note that we had to split the task into several programs, because the KIM-1 doesn’t have enough RAM to hold all results.
Program 1a: for A=00..FF, with C=0, execute “ROR A”, save result into array
.C:0200 A2 00 LDX #$00 .C:0202 8A TXA .C:0203 18 CLC .C:0204 6A ROR A .C:0205 9D 00 03 STA $0300,X .C:0208 E8 INX .C:0209 D0 F7 BNE $0202 .C:020B 00 BRK
Program 1b: for A=00..FF, with C=1, execute “ROR A”, save result into array
.C:0200 A2 00 LDX #$00 .C:0202 8A TXA .C:0203 38 SEC .C:0204 6A ROR A .C:0205 9D 00 03 STA $0300,X .C:0208 E8 INX .C:0209 D0 F7 BNE $0202 .C:020B 00 BRK
Program 2a: for A=00..FF, with C=0, execute “ROR A”, save flags into array
.C:0200 A2 00 LDX #$00 .C:0202 8A TXA .C:0203 38 SEC .C:0204 6A ROR A .C:0205 08 PHP .C:0206 68 PLA .C:0207 9D 00 03 STA $0300,X .C:020a E8 INX .C:020b D0 F5 BNE $0202 .C:020d 00 BRK
Program 2b: for A=00..FF, with C=1, execute “ROR A”, save flags into array
.C:0200 A2 00 LDX #$00 .C:0202 8A TXA .C:0203 38 SEC .C:0204 6A ROR A .C:0205 08 PHP .C:0206 68 PLA .C:0207 9D 00 03 STA $0300,X .C:020a E8 INX .C:020b D0 F5 BNE $0202 .C:020d 00 BRK
These are the results:
Program 1a and 1b (result with C=0 and C=1) produced the same output!
00 -> 00 01 -> 02 02 -> 04 03 -> 06 04 -> 08 05 -> 0A [...] FF -> FE
This is a shift left (!!!) of the input value; and it is independent of the carry flag – just like ASL.
Program 2a (status when C=0) produced the following output:
00: 7E (Z=1, N=0, C=0) 01..3F: 7C (Z=0, N=0, C=0) 40..7F: FC (Z=0, N=1, C=0) 80: 7E (Z=1, N=0, C=0) 81..BF: 7C (Z=0, N=0, C=0) C0..FF: FC (Z=0, N=1, C=0)
Program 2b (status when C=1) produced the following output:
00: 7F (Z=1, N=0, C=1) 01..3F: 7D (Z=0, N=0, C=1) 40..7F: FD (Z=0, N=1, C=1) 80: 7F (Z=1, N=0, C=1) 81..BF: 7D (Z=0, N=0, C=1) C0..FF: FD (Z=0, N=1, C=1)
These are the correct flags corresponding to the incorrect results in A. The carry flag is the same as the input carry flag, i.e. it is unmodified.
Our preliminary summary is this:
ROR Broken ROR on pre-June '76 CPU (Memory or Accumulator) +-+-+-+-+-+-+-+-+ Operation: |7|6|5|4|3|2|1|0| <- 0 +-+-+-+-+-+-+-+-+ N Z C I D V / / _ _ _ _ |
So ROR on early 6502s does three things wrong:
- It shifts left, instead of right (behaves like ASL)
- It shifts a zero in, instead of C (behaves like ASL)
- It doesn't update C (as if it wasn't a rotate instruction)
All three problems are flags that are sent to the ALU: the shift direction, the input bit, and the carry writeback.
Unresolved questions:
- We only tested ROR A; other addressing modes of ROR might behave differently. Other addressing modes might even be working - but I doubt that, since MOS would certainly have documented the working ones then.
- ROR might have more dependencies than A and C.
- What is it in the chip that causes the bug? I'm sure the fine guys at visual6502.org will be able to figure this one out soon. It is unlikely to be a bug in the PLA ROM, because a bug there would not affect different addressing modes of the same instruction with very different timings. It is more likely that it is in the "Random Control Logic" part.
How about putting that 6502 in a newer machine with more memory so you could more easily check for all dependencies and adressing modes?
(If it is socketed…).
You have a bug in Program 2a. It should be CLC not SEC.
Looks like you can replace your single ROR command with 8 ROL commands to resolve this issue.
Rev. A of the 6502 had no ROR instruction.
It was omitted by the engineer Bill Mensch to create a simple and cheap CPU.
There was no logic for the rotate-right-through-carry circuit.
ROR was added in Rev. B by the intervention of Steve Wozniak and required a lot of extra logic. It increases transistor count by about 1%.
Some of this information seems to have come out recently: TubeTime has a video showing the microphotographs of an early 6502. “The 6502 Rotate Right Myth” https://www.youtube.com/watch?v=Uk_QC1eU0Fg