; MATHLIB: a 16 Bit Arithmetic Package for Z80
; Sourced 26 Nov '80 by Trevor Marshall
; SYSOP, Thousand Oaks Tech RBBS
;
;
MULTIPLY: ; 16 x 16 Bit multiplication
; (may be truncated to 16 x n bits)
;
;result (HL) = multiplicand (DE) x multiplier (BC)
;
; The multiplicand is in DE
; The multiplier is in BC
; The result will be in HL
; It overflows safely, but without indication
; Registers are destroyed
;
; Example: 5 x 3
; 101
; x 011
; ----------------
; 101 (Shifted LSBit=1)
; 101 (Shifted LSBit=1)
; 000 (Shifted LSBit=0,no add)
; ----------------
; 01111 (Result)
;
; Multiplier is in BC
LD A,16 ; Loop count in A
;This count must be >= the number of bits used in BC
;
LD HL,0 ;Clear result
;
ZZMULT:
; is multiplier LSBit = 1 ?
SRL B ;Right shift multiplier MSB
; 0 -> MSBit, LSBit -> Carry
RR C ;Rotate right multiplier LSB
;Carry -> MSBit, LSBit -> Carry
JR NC,ZZNOADD ;LSBit not 1, Dont add
;
; Could test for overflow by using this here:
; CCF ;Carry will be 1, C -> 0
; ADC HL,DE
; JR C,OVERFLOW.ROUTINE
; But will use the simpler
ADD HL,DE ;LSBit = 1, so add multiplicand
; to (shifted) result
;
ZZNOADD:
;Now we shift left the multiplicand
SLA E ; 0 -> LSBit, MSBit -> Carry
RL D ; Carry -> LSBit, MSBit -> Carry
;
DEC A ;Loop cntr
JR NZ,ZZMULT
;
RET ; ***** DONE *****
;
;-------------------------------------------------------
;
DIVIDE: ;16 Bit by 16 Bit Integer Division
;
; dividend (BC)
; result (BC) = --------------- + remainder (HL)
; divisor (DE)
;
; The dividend is in BC, and the result returns in BC
; The divisor is in DE
; After the division HL contains the remainder
;
; The divisor is successively subtracted from the high
; order bits of the dividend. After each subtraction
; the result is used instead of the initial dividend
; The result is increased by 1 each time.
; When the result of the subtraction is negative the
; partial result is restored by adding the divisor
; back to it.
; The result is simulataneously decremented by 1
;
;First check if divisor is 0
LD A,D
OR E
JR Z,DIVIDE.BY.ZERO
; Dividend is in BC
;clear result
LD HL,0
;loop counter
LD A,16 ;DO NOT TRUNCATE
;
;Rotate Dividend left
;Carry has been zeroed by the OR E above
ZZDIV1: RL C ;Carry -> LSBit, MSBit -> Carry
RL B ;ditto
;Rotate Remainder left
ADC HL,HL ;Never sets carry,
; ie RESETS carry
;Trial subtraction of divisor from result
SBC HL,DE ;Carry -> 0 if no borrow
;Carry -> 1 if borrow
JR NC,ZZPOS
;otherwise negative
ADD HL,DE ;Restore dividend
ZZPOS: CCF ;Calc Result Bit, Z80 carry peculiar
DEC A ;Loop counter
JR NZ,ZZDIV1 ;Loop for 16 Bits
;
RL C ;Shift in last result bit
RL B
; The result is in BC, the remainder in HL
;
RET ; ***** DONE ****
;
DIVIDE.BY.ZERO: LD BC,0FFFFH ;Infinity
; Output a diagnostic message if desired
RET
;