6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Wed May 08, 2024 7:34 pm

All times are UTC




Post new topic Reply to topic  [ 24 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Tue Jun 07, 2022 12:26 am 
Offline

Joined: Sun Oct 03, 2021 2:17 am
Posts: 114
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


Top
 Profile  
Reply with quote  
PostPosted: Tue Jun 14, 2022 12:24 pm 
Offline
User avatar

Joined: Tue Aug 11, 2020 3:45 am
Posts: 311
Location: A magnetic field
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:
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:
  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.

_________________
Modules | Processors | Boards | Boxes | Beep, Beep! I'm a sheep!


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 20, 2022 2:02 am 
Offline

Joined: Sun Oct 03, 2021 2:17 am
Posts: 114
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.

Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 20, 2022 12:51 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10800
Location: England
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:
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.

Top
 Profile  
Reply with quote  
PostPosted: Sat Jul 09, 2022 4:21 pm 
Offline
User avatar

Joined: Tue Aug 11, 2020 3:45 am
Posts: 311
Location: A magnetic field
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.

_________________
Modules | Processors | Boards | Boxes | Beep, Beep! I'm a sheep!


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 02, 2023 12:03 am 
Offline

Joined: Sun Oct 03, 2021 2:17 am
Posts: 114
BTW, the Super FX chip has ADD without carry.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 02, 2023 1:20 am 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3354
Location: Ontario, Canada
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


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 02, 2023 6:44 am 
Offline

Joined: Mon Jan 19, 2004 12:49 pm
Posts: 683
Location: Potsdam, DE
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


Top
 Profile  
Reply with quote  
PostPosted: Tue Jan 03, 2023 3:58 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 858

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:
        LDA (IP)Y
        SEC
        ADC IP
        STA IP
        BCC RESUME
        INC IP+1
RESUME: JMP NEXT

And the original from my Forth system.
Code:
   IP )Y LDA  SEC
   IP ADC  IP STA
   CS IF  IP 1+ INC  THEN
   NEXT JMP  END-CODE



Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 24 posts ]  Go to page Previous  1, 2

All times are UTC


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: