Elite on the BBC Micro and NES

# Maths (Arithmetic): DVID4

## [6502 Second Processor version]

```       Name: DVID4                                                   [Show more]
Type: Subroutine
Category: Maths (Arithmetic)
Summary: Calculate (P R) = 256 * A / Q
Deep dive: Shift-and-subtract division
Context: See this subroutine in context in the source code
Variations: See code variations for this subroutine in the different versions
References: This subroutine is called as follows:
* DOEXP calls DVID4
* SPS2 calls DVID4

Calculate the following division and remainder:

P = A / Q

R = remainder as a fraction of Q, where 1.0 = 255

Another way of saying the above is this:

(P R) = 256 * A / Q

This uses the same shift-and-subtract algorithm as TIS2, but this time we
keep the remainder and the loop is unrolled.

Returns:

C flag               The C flag is cleared

.DVID4

\LDX #8                 \ This instruction is commented out in the original
\ source

ASL A                  \ Shift A left and store in P (we will build the result
STA P                  \ in P)

LDA #0                 \ Set A = 0 for us to build a remainder

\.DVL4                  \ This label is commented out in the original source

\ We now repeat the following five instruction block
\ eight times, one for each bit in P. In the cassette
\ and disc versions of Elite the following is done with
\ a loop, but it is marginally faster to unroll the loop
\ and have eight copies of the code, though it does take
\ up a bit more memory (though that isn't a concern when
\ you have a 6502 Second Processor)

ROL A                  \ Shift A to the left

CMP Q                  \ If A < Q skip the following subtraction
BCC P%+4

SBC Q                  \ A >= Q, so set A = A - Q

ROL P                  \ Shift P to the left, pulling the C flag into bit 0

ROL A                  \ Repeat for the second time
CMP Q
BCC P%+4
SBC Q
ROL P

ROL A                  \ Repeat for the third time
CMP Q
BCC P%+4
SBC Q
ROL P

ROL A                  \ Repeat for the fourth time
CMP Q
BCC P%+4
SBC Q
ROL P

ROL A                  \ Repeat for the fifth time
CMP Q
BCC P%+4
SBC Q
ROL P

ROL A                  \ Repeat for the sixth time
CMP Q
BCC P%+4
SBC Q
ROL P

ROL A                  \ Repeat for the seventh time
CMP Q
BCC P%+4
SBC Q
ROL P

ROL A                  \ Repeat for the eighth time
CMP Q
BCC P%+4
SBC Q
ROL P

LDX #0                 \ Set X = 0 so this unrolled version of DVID4 also
\ returns X = 0

JMP LL28+4             \ Jump to LL28+4 to convert the remainder in A into an
\ integer representation of the fractional value A / Q,
\ in R, where 1.0 = 255. LL28+4 always returns with the
\ C flag cleared, and we return from the subroutine
\ using a tail call
```