; MATHLIB: a 16 Bit Arithmetic Package for 6805
; Sourced Feb '81 by 	Trevor Marshall
;			SYSOP, Thousand Oaks, Tech RBBS
;
;MULTIPLY:  16 x 16 Bit multiplication
;
; RESULT,RESULT+1 = MPLICAND,MPLICAND+1
;                         x MPLIER,MPLIER+1
; MPLIER, MPLICAND may be destroyed
;COUNT:	DS	1	;loop counter
;RESULT: DS	2
;MPLICAND DS	2
;MPLIER	DS	2
;
;	Example: 5 x 3
;		101
;	     x  011
;	----------------
;		101	(Shifted LSBit=1)
;	       101	(Shifted LSBit=1)
;	      000	(Shifted LSBit=0,no add)
;	----------------
;	      01111	(Result)
;
MULTIPLY: LDA	#16	;initialize count
	STA	COUNT
	CLR	RESULT+1 ;and result
	CLR	RESULT
;
; is multiplier LSBit = 1 ?
ZZMULT:	SHR	MPLIER ;right shift multIplier MSB
;			; 0 -> MSBit, LSBit -> Carry
	RRC	MPLIER+1 ;shift right multiplier LSB
;			;Carry-> MSBit, LSBit -> Carry
	BNC	ZZNOADD ;LSBit not 1, don't add
;
; Could test for overflow here:
; (.Z80) CCF	;Carry will be 1, C -> 0
;	ADC	HL,DE
;	JR	C,OVERFLOW.ROUTINE
; But will add without carry
	LDA	MPLICAND+1 ;LSBit=1, so add multiplicand
;			;to (shifted) result
	ADD	RESULT+1
	STA	RESULT+1
	LDA	MPLICAND
	ADC	RESULT
	STA	RESULT
;
ZZNOADD: SHL	MPLICAND+1 ; 0 -> LSBit, MSBit -> Carry
	RLC	MPLICAND   ;Carry -> LSBit, MSBit -> Carry
	DEC	COUNT
	BNZ	ZZMULT
	RET             ; ***** DONE *****
;
;
;
;DIVIDE: ;16 Bit by 16 Bit Integer Division
;
;                        (DIVIDEND,DIVIDEND+1)
; DIVIDEND,DIVIDEND+1  =----------------------- + REM,REM+1
;                        (DIVISOR,DIVISOR+1)
; The dividend & divisor are stored in memory with
;   the MSByte first
; Their location is via EQU statements
;COUNTER:  EQU	$39	;A scratch location for loop count
;DIVIDEND: EQU	$3A	;2 locs at top of user RAM
;RESULT:   EQU	$	;Result replaces dividend
;DIVISOR:  EQU	$3C	; "
;REM:	   EQU	$3E	; "
;
; 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
DIVIDE:	LDA	DIVISOR
	XOR	DIVISOR+1
	BZ	DIVBY0
;clear result
	CLRA
	STA	REM
	STA	REM+1
;loop counter
	LDA	#16
	STA	COUNTER
;
;Rotate Dividend left 
	CLRC
ZZDIV1:	RLC	DIVIDEND+1
	RLC	DIVIDEND
;Rotate Remainder left and collect carry result
	RLC	REM+1
	RLC	REM
	LDA	REM+1
	SUB	DIVISOR+1
	STA	REM+1	;Modify to reflect result
	LDA	REM
	SBC	DIVISOR
	STA	REM	;	"
	BNC	ZZPOS
;otherwise negative
	LDA	REM+1	;Restore dividend
	ADD	DIVISOR+1
	STA	REM+1
	LDA	REM
	ADC	DIVISOR
	STA	REM
ZZPOS:	BNC	ZZPOS1 ;If carry is clear set it
	CLRC           ;if set, clear it
	BR	ZZPOS2 ;Thus complement the carry
ZZPOS1:	SETC
ZZPOS2:	DEC	COUNTER
	BNZ	ZZDIV1
	RLC	DIVIDEND+1 ;Shift in last result bit
	RLC	DIVIDEND
	RET             ; ***** DONE ****
;
DIVBY0	LDA	$FF	;infinity
	STA	DIVIDEND+1
	STA	DIVIDEND
; Output a diagnostic message if desired
	RET
;
