Why does ADC add one if carry flag set?

Building your first 6502-based project? We'll help you get started here.
jeffythedragonslayer
Posts: 114
Joined: 03 Oct 2021

Re: Why does ADC add one if carry flag set?

Post by jeffythedragonslayer »

Dr Jefyll wrote:
I don't find it at all illogical to expect fewer multi-precision additions when the word length doubles. Just my $.02 worth...

-- Jeff
this
BigEd wrote:
I hope you're not discouraged, jeffythedragonslayer, by the strongly-expressed opinions upthread. It's not how we usually conduct ourselves here.
thanks
User avatar
Sheep64
In Memoriam
Posts: 311
Joined: 11 Aug 2020
Location: A magnetic field

Re: Why does ADC add one if carry flag set?

Post by Sheep64 »

Discarding add without carry was a very bold move. It makes the processor smaller - at the expense of making your program larger and slower. Regardless, there are opportunities to skip CLC before ADC (or SEC before SBC). I'll start with an example in C where arrays of 80 elements are added. You might type:

Code: Select all

for(x=0;x<80;x++) {
  f[x]=d[x]+e[x];
}
In 6502 assembly, if you want to take 80 numbers in page $04, add them to 80 numbers in page $05 and store the results in page $06, it may preferable to iterate backwards:

Code: Select all

  LDX #79
loop:
  CLC         ; <----- this use of CLC might be optimized.
  LDA $0400,X ; d[x]
  ADC $0500,X ; e[x]
  STA $0600,X ; f[x]
  DEX         ; --x
  BPL loop    ; x>=0
In this example, RegX will start at 79 and decrease. The last iteration has RegX=0 and iteration stops when top bit of RegX is not zero. If you definitely know that the values will be small, it is possible to move CLC outside of the loop. In this case, CLC is only executed once. The small result from any addition will clear the carry flag before the next addition occurs. However, if this assumption changes, the optimized loop will completely foobar your data. One bit of precision is enough to cause integer overflow.

If you want a fantastically vivid example of integer overflow, find the video of the first Ariane 5 rocket launch. Then remember to dimension your data correctly.
jeffythedragonslayer
Posts: 114
Joined: 03 Oct 2021

Re: Why does ADC add one if carry flag set?

Post by jeffythedragonslayer »

That's good to know, Sheep64. As for why SBC needs SEC instead of CLC, I combed through this thread and think I can summarize why now:

viewtopic.php?f=2&t=2944&hilit=inverted+carry

The carry flag serves double duty as the borrow flag when doing subtraction. Subtraction on the 6502 is implemented by inverting the subtrahend and then sending that to the ALU, which performs an addition. Now, the way to invert a number in two's complement is to invert all the bits and then add one. To save some transistors, the 6502 does not add one for you automatically, so you need to manually set this flag manually with the SEC instruction. This is a more efficient use of transistors compared to always adding one in hardware and then undoing that when there is a borrow.

Also, I think there is a typo in Eyes & Lichty page 497:
Quote:
To avoid subtracting the carry flag from the result, either you must be sure it is set or you must explicity set it (using SEC) prior to executing the SBC instruction.
I think it should instead start with "To avoid subtracting one from the result," because the ALU actually adds the carry/borrow flag to the result.
Last edited by jeffythedragonslayer on Mon Jun 20, 2022 7:16 pm, edited 1 time in total.
User avatar
BigEd
Posts: 11463
Joined: 11 Dec 2008
Location: England
Contact:

Re: Why does ADC add one if carry flag set?

Post by BigEd »

Mmm, indeed that could be clearer. For the subtraction you're thinking of (not for the usual case!), you need to clear the carry first. For a multi-byte subtraction, in your case you'd clear the carry before starting out, but the whole point of the carry is that it then proprogates from each byte to the next higher byte.

Edit: added clarification

(Personally, I've never worried too much about trying to think of it as a borrow or a not-borrow or similar - I just remember firmly that it's obvious enough to CLC before an ADC, and so, for reasons, it's also correct to SEC before SBC.)

As I can never quite readily remember subtraction without working it out, I popped over to Easy6502 and put in this program to illustrate:

Code: Select all

LDX #0
SEC
LDA #$02
SBC #$01
TAX

CLC
LDA #$02
SBC #$01
TAY
After execution, we see X=01 and Y=00. Which tells us that the C=0 caused an extra 1 to be subtracted. Which indeed one could think of as a borrow.
Last edited by BigEd on Mon Jan 02, 2023 9:36 am, edited 1 time in total.
User avatar
Sheep64
In Memoriam
Posts: 311
Joined: 11 Aug 2020
Location: A magnetic field

Re: Why does ADC add one if carry flag set?

Post by Sheep64 »

BigEd on Mon 6 Jun 2022 wrote:
I hope you're not discouraged, jeffythedragonslayer, by the strongly-expressed opinions upthread. It's not how we usually conduct ourselves here.
Ignore BigEd. This is *exactly* how the 6502 Forum is conducted when a 65816 feature is questioned. As I was recently reminded when I suggested use of REP to simultaneously set C=0 or D=0 when setting M=0 or X=0, 65816 flags are particularly touchy subject.
jeffythedragonslayer
Posts: 114
Joined: 03 Oct 2021

Re: Why does ADC add one if carry flag set?

Post by jeffythedragonslayer »

BTW, the Super FX chip has ADD without carry.
User avatar
Dr Jefyll
Posts: 3525
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: Why does ADC add one if carry flag set?

Post by Dr Jefyll »

Sheep64 wrote:
This is *exactly* how the 6502 Forum is conducted when a 65816 feature is questioned. [...] 65816 flags are particularly touchy subject.
The forum is a collection of individuals, Sheep64, even including yourself. I hope you don't find us to be unanimously touchy! :| Overall, I think the decorum is pretty darn good! I prefer to keep a pretty relaxed outlook, myself...

-- Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
barnacle
Posts: 1831
Joined: 19 Jan 2004
Location: Potsdam, DE
Contact:

Re: Why does ADC add one if carry flag set?

Post by barnacle »

But the original question: Why does ADC add one if carry flag set? still remains... The obvious short answer is that, er, it's the function of the instruction, but that takes you back to how to design an adder. Text below assumes two's complement maths; it's not the only way!

Do you need an adder at all? No - it's quite feasible to have a processor which only has a single SUB (without carry) instruction in the ALU and no adder even if it generates a carry output - to add, you need to invert one of the operands before it is subtracted from the other (which is a little slow and repetitive in the absence of other ALU operations, but possible) and if you want to include the carry at any stage, that's a separate step. It hurts the head less and is (I think) more efficient if the subtracter is an adder but it still gets pretty tedious.

But the basic building block for a multibit adder is a single bit adder with three inputs and two outputs: A, B, and carry in, and C and carry out. Eight of those in a row give you an eight bit adder, with a carry input correctly propagated along the chain (that's the slowest path through the adder logic, so you might use a different approach for the carry at longer word lengths).

To add, it's obvious: provide the two inputs and the carry as required (if done with two instructions, the microcode needs to manage the value of the carry either to force it clear or to use a stored flag); and to subtract, invert the subtrahend, *add* it to the minuend, and add one. Adding one is already built into the adder using the carry input, so a simple way is just to use that: lo and behold, only two instructions are required. ADC and SBC. In both cases, the carry is included, and for SBC the carry input and output are inverted, with the same bit of circuitry and no worrying about the carry. It just happens. So to add, the carry flag is initially cleared; to subtract it is initially set.

Obviously this way multiprecision arithmetic is simpler because the carry ripples through the calculation without any programmer input apart from the initial setting or clearing of the carry flag; it also slightly simplifies the logic if the ALU is used to provide address increments in two or more bytes (though I have a vague idea that the 6502 has sixteen bit adders to manage the various indirect and indexed addressing modes, so perhaps not relevant here).

Neil
JimBoyd
Posts: 931
Joined: 05 May 2017

Re: Why does ADC add one if carry flag set?

Post by JimBoyd »


The carry flag can be used for more than just multi byte arithmetic. Sometimes it's useful to set the carry flag before ADC.
Here is a hand translated code fragment which skips over an inline count byte and string in Forth. The Y-register has a value of zero when this routine is entered.

Code: Select all

        LDA (IP)Y
        SEC
        ADC IP
        STA IP
        BCC RESUME
        INC IP+1
RESUME: JMP NEXT

And the original from my Forth system.

Code: Select all

   IP )Y LDA  SEC
   IP ADC  IP STA
   CS IF  IP 1+ INC  THEN
   NEXT JMP  END-CODE

Post Reply