Skip to navigation

Elite on the BBC Micro and NES

Maths (Arithmetic): MULT1

[NES version, Bank 7]

Name: MULT1 [Show more] Type: Subroutine Category: Maths (Arithmetic) Summary: Calculate (A P) = Q * A Deep dive: Shift-and-add multiplication
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * MAD calls MULT1 * MULT12 calls MULT1

Do the following multiplication of two 8-bit sign-magnitude numbers: (A P) = Q * A
.MULT1 TAX ; Store A in X SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure ; the PPU to use nametable 0 and pattern table 0 TXA ; The macro call overwrites A, so restore the value of A ; which we copied into X above AND #%01111111 ; Set P = |A| >> 1 LSR A ; and C flag = bit 0 of A STA P TXA ; Restore argument A EOR Q ; Set bit 7 of A and T if Q and A have different signs, AND #%10000000 ; clear bit 7 if they have the same signs, 0 all other STA T ; bits, i.e. T contains the sign bit of Q * A LDA Q ; Set A = |Q| AND #%01111111 BEQ mu10 ; If |Q| = 0 jump to mu10 (with A set to 0) TAX ; Set T1 = |Q| - 1 DEX ; STX T1 ; We subtract 1 as the C flag will be set when we want ; to do an addition in the loop below ; We are now going to work our way through the bits of ; P, and do a shift-add for any bits that are set, ; keeping the running total in A. We already set up ; the first shift at the start of this routine, as ; P = |A| >> 1 and C = bit 0 of A, so we now need to set ; up a loop to sift through the other 7 bits in P LDA #0 ; Set A = 0 so we can start building the answer in A TAX ; Copy A into X, to make sure the unrolled version ; returns the same results as the loop versions, just ; in case something out there relies on MULT1 returning ; X = 0 BCC P%+4 ; If C (i.e. the next bit from P) is set, do the ADC T1 ; addition for this bit of P: ; ; A = A + T1 + C ; = A + |Q| - 1 + 1 ; = A + |Q| ROR A ; As mentioned above, this ROR shifts A right and ; catches bit 0 in C - giving another digit for our ; result - and the next ROR sticks that bit into the ; left end of P while also extracting the next bit of P ; for the next addition ROR P ; Add the overspill from shifting A to the right onto ; the start of P, and shift P right to fetch the next ; bit for the calculation BCC P%+4 ; Repeat for the second time ADC T1 ROR A ROR P BCC P%+4 ; Repeat for the third time ADC T1 ROR A ROR P BCC P%+4 ; Repeat for the fourth time ADC T1 ROR A ROR P BCC P%+4 ; Repeat for the fifth time ADC T1 ROR A ROR P BCC P%+4 ; Repeat for the sixth time ADC T1 ROR A ROR P BCC P%+4 ; Repeat for the seventh time ADC T1 ROR A ROR P LSR A ; Rotate (A P) once more to get the final result, as ROR P ; we only pushed 7 bits through the above process ORA T ; Set the sign bit of the result that we stored in T RTS ; Return from the subroutine .mu10 STA P ; If we get here, the result is 0 and A = 0, so set ; P = 0 so (A P) = 0 RTS ; Return from the subroutine