Aviator on the BBC Micro

# Maths: Multiply16x16Mix

```       Name: Multiply16x16Mix                                        [Show more]
Type: Subroutine
Category: Maths
Summary: Multiply two 16-bit numbers with different sign bits (one in bit 7
of the high byte, the other in bit 0 of the low byte)
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* ApplyAerodynamics (Part 3 of 3) calls Multiply16x16Mix
* SetPointCoords calls Multiply16x16Mix

This routine multiplies two 16-bit numbers with different sign bits, where one
argument (J I) has the sign in bit 7 of the high byte, and the other argument
(S R) has the sign in bit 0 of the low byte. It calculates:

(H G) = (J I) * (S R) >> 16

The result in (H G) has the sign in bit 7 of the high byte.

The fractional part of the result is in W, so this is the full result, though
in practice W is ignored:

(H G W) = (J I) * (S R)

Arguments:

(J I)                A signed 16-bit number, with the sign in bit 7 of J

(S R)                A signed 16-bit number, with the sign in bit 0 of R

K                    Optionally negate (J I):

* 0 = calculate (J I) * (S R) >> 16

* 128 = calculate -(J I) * (S R) >> 16

In practice, this routine is always called with K = 0

Returns:

(H G)                The result of the multiplication, with the sign in bit 7
of H

K                    The sign of the result (in bit 7)

.Multiply16x16Mix

BPL mmix1              \ positive 16-bit number

LDA #0                 \ Negate (J I) so (J I) is now a positive 16-bit number
SEC
SBC I
STA I
LDA #0
SBC J
STA J

LDA K                  \ Flip bit 7 of K, so when K = 0 we negate the result
EOR #%10000000         \ below to give the result the correct sign
STA K

.mmix1

LDA R                  \ If bit 0 of R is 0, jump to mmix2 as (S R) is positive
AND #1
BEQ mmix2

LDA K                  \ Otherwise (S R) is negative, so flip bit 7 of K, so
EOR #%10000000         \ when K = 0 we negate the result below to give the
STA K                  \ result the correct sign

.mmix2

JSR Multiply16x16      \ Calculate (H A) = (S R) * (J I) >> 16
\
\ and set the C flag if we need to increment H

STA G                  \ Set (H G) = (H A)
\           = (S R) * (J I) >> 16

BCC mmix3              \ Increment the top byte in H if required
INC H

.mmix3

LDA K                  \ If K is positive, jump to mmix4 to return from the
BPL mmix4              \ subroutine as the sign of the result is already
\ correct

SEC                    \ Negate (H G) so the result has the correct sign
LDA #0
SBC G
STA G
LDA #0
SBC H
STA H

.mmix4

RTS                    \ Return from the subroutine
```