Skip to navigation

Aviator on the BBC Micro

Maths: Add16x16Bit0

Name: Add16x16Bit0 [Show more] Type: Subroutine Category: Maths Summary: Add two 16-bit numbers that have their signs in bit 0
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * SetMatrices calls Add16x16Bit0

This routine adds two 16-bit numbers, both of which have their signs in bit 0 of the low byte. It calculates: (S R) = (H G) + (J I) The result in (S R) has the sign in bit 0 of the low byte.
Arguments: (H G) A signed 16-bit number, with the sign in bit 0 of G (J I) A signed 16-bit number, with the sign in bit 0 of I
Returns: (S R) The result of the multiplication, with the sign in bit 0 of R K The sign of the result (in bit 0)
.Add16x16Bit0 LDA G \ Set K to the sign of G (from bit 0) AND #1 STA K EOR I \ If G and I have different sign bits, then this will AND #1 \ set A to 1, in which case jump to abit2 BNE abit2 \ If we get here then the two arguments (H G) and (J I) \ have the same sign, which is stored in K LDA G \ Set (S R) = (H G) + (J I) CLC \ ADC I \ starting with the low bytes, setting bit 0 of the AND #%11111110 \ result to the sign in K (as the result of adding two ORA K \ numbers with sign K will have sign K) STA R LDA H \ Then adding the high bytes ADC J STA S BCC abit1 \ If the addition didn't overflow, jump to abit1 to \ return from the subroutine, as the result is correct LDA #%11111111 \ The addition overflowed, so we return the maximum STA S \ value in (R S), which has every bit set except for the LDA #%11111110 \ sign bit, which is set to K ORA K STA R .abit1 RTS \ Return from the subroutine .abit2 \ If we get here then the two arguments (H G) and (J I) \ have different signs, with the sign of (H G) stored in \ K LDA G \ Set (S R) = (H G) - (J I) SEC \ SBC I \ starting with the low bytes STA R LDA H \ And then the high bytes SBC J STA S BCC abit3 \ If the subtraction underflowed, jump to abit3 \ Otherwise the result is correct apart from the sign, \ and the sign of the result should be that of (H G), as \ (H G) is the larger value (i.e. it has the highest \ magnitude), as otherwise the subtraction would \ underflow LDA R \ Set the sign bit of (S R) to K, as that contains the AND #%11111110 \ sign of (H G) ORA K STA R RTS \ Return from the subroutine .abit3 \ If we get here then the (H G) - (J I) subtraction \ underflowed, so (J I) is the larger value (i.e. it has \ the highest magnitude) \ \ We therefore need to negate the subtraction result to \ get (J I) - (H G), and the sign of the final result \ should be given the sign of (J I), as that's the \ dominant part... and as K contains the sign of (H G) \ and we know (H G) and (J I) have opposite signs, we \ should therefore give the result the opposite sign to \ the sign in K LDA #0 \ Negate the (S R) to get the correct result, SEC \ SBC R \ (S R) = 0 - (S R) AND #%11111110 \ ORA K \ while also setting the sign in bit 0 to the opposite EOR #1 \ of K STA R LDA #0 SBC S STA S RTS \ Return from the subroutine