BBC Micro Elite

```       Name: ADD                                               [View in context]
Type: Subroutine
Category: Maths (Arithmetic)
Summary: Calculate (A X) = (A P) + (S R)

Add two 16-bit sign-magnitude numbers together, calculating:

(A X) = (A P) + (S R)

STA T1                 \ Store argument A in T1

AND #%10000000         \ Extract the sign (bit 7) of A and store it in T
STA T

EOR S                  \ EOR bit 7 of A with S. If they have different bit 7s
BMI MU8                \ (i.e. they have different signs) then bit 7 in the
\ EOR result will be 1, which means the EOR result is
\ negative. So the AND, EOR and BMI together mean "jump
\ to MU8 if A and S have different signs"

\ If we reach here, then A and S have the same sign, so
\ we can add them and set the sign to get the result

LDA R                  \ Add the least significant bytes together into X:
CLC                    \
ADC P                  \   X = P + R
TAX

LDA S                  \ Add the most significant bytes together into A. We
ADC T1                 \ stored the original argument A in T1 earlier, so we
\ can do this with:
\
\   A = A  + S + C
\     = T1 + S + C

ORA T                  \ If argument A was negative (and therefore S was also
\ negative) then make sure result A is negative by
\ OR-ing the result with the sign bit from argument A
\ (which we stored in T)

RTS                    \ Return from the subroutine

.MU8

\ If we reach here, then A and S have different signs,
\ so we can subtract their absolute values and set the
\ sign to get the result

LDA S                  \ Clear the sign (bit 7) in S and store the result in
AND #%01111111         \ U, so U now contains |S|
STA U

LDA P                  \ Subtract the least significant bytes into X:
SEC                    \
SBC R                  \   X = P - R
TAX

LDA T1                 \ Restore the A of the argument (A P) from T1 and
AND #%01111111         \ clear the sign (bit 7), so A now contains |A|

SBC U                  \ Set A = |A| - |S|

\ At this point we have |A P| - |S R| in (A X), so we
\ need to check whether the subtraction above was the
\ the right way round (i.e. that we subtracted the
\ smaller absolute value from the larger absolute
\ value)

BCS MU9                \ If |A| >= |S|, our subtraction was the right way

\ If we get here, then |A| < |S|, so our subtraction
\ above was the wrong way round (we actually subtracted
\ the larger absolute value from the smaller absolute
\ value). So let's subtract the result we have in (A X)
\ from zero, so that the subtraction is the right way
\ round

STA U                  \ Store A in U

TXA                    \ Set X = 0 - X using two's complement (to negate a
EOR #&FF               \ number in two's complement, you can invert the bits
ADC #1                 \ and add one - and we know the C flag is clear as we
TAX                    \ didn't take the BCS branch above, so the ADC will do

LDA #0                 \ Set A = 0 - A, which we can do this time using a
SBC U                  \ a subtraction with the C flag clear

ORA #%10000000         \ We now set the sign bit of A, so that the EOR on the
\ next line will give the result the opposite sign to
\ argument A (as T contains the sign bit of argument
\ A). This is the same as giving the result the same
\ sign as argument S (as A and S have different signs),
\ which is what we want, as S has the larger absolute
\ value

.MU9

EOR T                  \ If we get here from the BCS above, then |A| >= |S|,
\ so we want to give the result the same sign as
\ argument A, so if argument A was negative, we flip
\ the sign of the result with an EOR (to make it
\ negative)

RTS                    \ Return from the subroutine
```