31

In 6502 Assembly, we can use INX and INY to increase the value stored in X and Y. They can be decreased with DEX and DEY. However, it seems that there are no such instructions for A, like INA or DEA. There is however an instruction to increment and decrement the content of an address (INC and DEC). But why are there no instructions like that for A? Does this have a reason? Or am I missing something? I know that you could just use ADC or SBC but I'm still wondering.

Raffzahn
  • 222,541
  • 22
  • 631
  • 918
LuNa
  • 588
  • 6
  • 9
  • 2
    It really is strange when you think about it, as the accumulator is the one place you'd most expect to be supported by any given arithmetic instruction. Something like, say, an absolute memory address offset by the X register, seems far less likely to be incrementable in a single instruction. And yet the 6502 can increment/decrement literally anything but the accumulator, including that. (Well, you can using ADC/SBC, but there's no way I know of to do it in a single instruction unless it's a point in the code where the carry flag will always be in the same state.) – Sparkette Dec 30 '20 at 01:55
  • Does anyone know if the 6502 was developed under a tight deadline? That could be the reason why something got left out even though it was added in later updates. – UncleBod Aug 02 '23 at 17:53

3 Answers3

34

The designers figured that you'd use X and Y for looping, indexing etc, and use A for adding and subtracting, shifts etc. So they saw a need for INX and INY, but didn't see a enough of a need for an instruction to increment or decrement the accumulator.

That's also the reason why X and Y cannot participate in many ALU operations, like adds, shifts, and whatever.

Unlike adc and sbc, the instructions to increment and decrement also do not heed the decimal mode. This might have been seen as a shortcoming early on, as the design was coming together.

(Later, with the 65C02, the instruction you are talking about was added, and variously called INA, INC A or INC.)

Omar and Lorraine
  • 38,883
  • 14
  • 134
  • 274
  • 1
    "but didn't see a need for an instruction to increment or decrement the accumulator." - apparently the addition of INA/DEA reduced typical code size by about 5% - adding STZ and similar changes made the overall reduction 10 to 15%. I suspect they would have been aware of the advantages even during the original design. – Maury Markowitz Dec 11 '19 at 16:08
  • 3
    @Maury You got a citation for the 5%? Just because I'm interested – Omar and Lorraine Dec 11 '19 at 16:15
  • I seem to recall it was mentioned in Wagner: https://archive.org/details/softalkv3n10jun1983 – Maury Markowitz Dec 11 '19 at 16:20
  • 5
    @MauryMarkowitz There are a lot of instructions that could be added to the 6502 to decrease code size and/or increase performance but weren't. The designers were trying to make a cheap microprocessor, not a fully featured one and they drew their line with INA on the wrong side of it. – JeremyP Dec 12 '19 at 10:22
  • 1
    Oh for sure, they didn't have the statistics that were available to WDC two years later. – Maury Markowitz Dec 12 '19 at 16:56
  • 2
    @JeremyP: What's funny is that the designers of the 6502 failed to design in some useful features, such as instructions to decrement an address and compare the result with the accumulator or store the bitwise AND of the values in A and X, that would have cost nothing beyond the ink necessary to document them. – supercat Dec 12 '19 at 18:14
  • 1
    @supercat you don't know that. There may have been design constraints you don't know about. for example, to AND A and X would probably require an extra data path to the ALU. – JeremyP Dec 13 '19 at 11:43
  • 2
    @JeremyP It does not. The original 6502 actually does have instructions to do everything supercat is describing -- they're just undocumented. – Omar and Lorraine Dec 13 '19 at 11:45
  • 3
    @JeremyP: I can be quite certain that an NMOS 6502 that includes the indicated instructions wouldn't cost any more than the NMOS 6502s that were actually produced, because the only thing necessary to make any existing NMOS 6502 chips or other parts based on that core store the bitwise AND of A and X to e.g. address $1234 is to feed it the instruction bytes 8F 34 12, and the only thing necessary to make such a chip decrement $56 and compare the result with A is to feed it the instruction bytes C7 56. – supercat Dec 13 '19 at 16:54
  • @JeremyP: Back when such instructions were first discovered, one might have worried about whether use of such instructions might stress the silicon, but analysis of the layout shows that's not a problem. Instructions in the range $8C-$8F, for example, are handled identically in the first two cycles, and in the first half of the third cycle where an internal data bus is precharged to $FF. Then in the second half of that cycle, circuitry is activated which will clear any bits of that bus which are cleared in Y if the two lower bits of the opcode are 00, clear any bits that are cleared in A... – supercat Dec 13 '19 at 16:57
  • ...if the bit 0 of the opcode is set, and clear any bits that are cleared in X if bit 1 of the opcode is set. If both lower bits of the opcode are set, then any bit which is cleared in X or A will be cleared. There's no bus conflict, or associated stress, because nothing is trying to set any bits of the bus at the time when A, X, or Y would be copied to it. The fusion of "DEC" and "CMP" is more interesting, and has the interesting quirk that it supports three addressing modes that are supported by CMP but not DEC. – supercat Dec 13 '19 at 17:04
13

If one writes opcodes in binary, using the format III-AAA-gg (with "III" generally being "Instruction", "AAA" being "Address mode", and "gg" as "general instruction group"), most instructions of the form III-AAA-01 or III-AA0-10 process addresses the same way using the address mode specified by AAA. The latter group of instructions are read-modify-write except that 10I-AAA-xx are LD_/ST_, with the registers selected by xx (in particular, 10I-AAA-10 are LDX/STX). The exception is that address mode 010, which would normally be immediate (e.g. ORA #imm is 000-010-01), becomes "accumulator" addressing for read-modify write instructions of the 0II-010-10 form. The increment and decrement instructions have the form 11I-AA0-10, which doesn't match that pattern.

The opcode map is a bit goofy in the areas which would match the general III-AAA-10 and 10I-AAA-xx patterns, but aren't used for read-modify-write or LD_/ST_ instructions. I would guess that instructions like "TXA" and "TAX", which are placed where "STX #imm" and "LDX #imm" would go, are placed at those spots to exploit the fact that instructions of the form 100-AAA-1x place X on the internal bus, and 101-AAA-1x loads X from the internal bus. I'm not sure when chronologically it was decided that various instructions would be supported, but supporting accumulator mode with INC and DEC would have required some extra circuitry, and would also require relocating DEX (which uses the opcode that would have fit the patterns of 110-AAA-10 for "decrement something" and 1x0-AAA-1x for "put something into X").

Incidentally, one thing that made chip designs of the 1970s and 1980s very different from those of today was that chips had only three layers that could carry current and signals, and any place the bottom two layers crossed would form a transistor. As a consequence, one needed to be very mindful of which signals would be sent to what part of a chip, or else a chip would spend more area on routing wires than on transistors. Today's fabrication processes generally support at least five layers, and many support far more than that, which allows much more routing flexibility.

supercat
  • 35,993
  • 3
  • 63
  • 159
  • Actually everything in 6502 controlled with its PLA or "microcode ROM" (though technically it is not pure ROM). The question could be whether INC A/DEC A was at all possible to implement within the existing PLA and why didn't they do it. – lvd Dec 11 '19 at 20:09
  • 3
    @lvd: It would be interesting to have a 6502 simulator that would allow editing the PLA. I suspect that many of the 6502's annoyances could be eased if parts of the instruction set were reworked, while keeping the same chip layout otherwise, but I suspect some features were added after other parts of the instruction set had already been decided upon. – supercat Dec 11 '19 at 20:20
  • 1
    @lvd: If I were trying to design a chip given the 6502's list of features, I think I'd be inclined to make all instructions whose two LSBs aren't 00 compute and access an effective address based on bits 2-4 of the opcode, and then perform some action based on bits 0-1 and 5-7. There's enough space in the opcode map to do that, and I would think that having the opcodes for LDX be the same as LDA except that the bottom two bits would be 10 rather than 01, would be simpler than having LDX, STX, and BIT use different address encodings. – supercat Dec 11 '19 at 20:57
1

Although the instructions LSR, ROR, ASL, and ROL were described as having five addressing modes that include "accumulator mode", each of them should really be thought of as two instructions, e.g. "LSR memory" and "LSR accumulator". If the 6502 hadn't included circuitry specifically to support the accumulator modes of those instructions, but simply advanced the state machine to "cleanup and fetch next instruction" after the second cycle for any bit pattern that would code an immediate-mode operand, the opcodes that would code the immediate-operand forms of those instructions would act as either one-cycle or two-cycle NOPs, depending upon whether incrementing of the program counter was suppressed during the second cycle, because the actual shifting work performed by the instructions occurs on the cycle after the memory-operand fetch, and immediate-mode opcodes don't perform a memory-operand fetch.

Making those instructions usable with both memory operands and the accumulator required a fair amount of extra circuitry--probably more than some other features that didn't make the cut, but they were included because some common operations would be awkward if only one were supported. Without accumulator mode, the scenario of loading a bit from one I/O port, shifting it, and then outputting it, would have gone from:

LDA input
LSR
STA output

to

LDA input
STA temp
LSR temp
LDA temp
STA output

increasing the time from 7 bytes/10 cycles to 12 bytes/19 cycles. Without memory mode, the scenario where one wants to shift a bit through a sequence of addresses would have increased from:

LSR buff+3
ROR buff+2
ROR buff+1
ROR buff

to

LDA buff+3
LSR
STA buff+3
LDA buff+2
ROR
STA buff+2
LDA buff+1
ROR
STA buff+1
LDA buff
ROR
STA buff

increasing the cost from 8 bytes/20 cycles ot 20 bytes/32 cycles. If the carry flag state is known, a lack of INC A/DEC A would add one byte and zero cycles; if it's not known, it would add two bytes and two cycles. If the 6502 had used all opcodes of the form xxxxxx11 as "some kind of add/subtract", using one opcode bit to enable/disable carry input, and one to control BCD mode, then I don't think the cost/benefit analysis of adding support for INC A/DEC A would have been particularly close to justifying it. As it is, the frequent need for a CLC or SEC when using ADC or SBC means that INC A/DEC A would have offered some savings, but more general ADD/SUB instructions would have been better yet.

supercat
  • 35,993
  • 3
  • 63
  • 159