MREV:	DB 33H ; 9/13/81 A. BENDER  ADD PIDGIN ENTRY POINTS
;MREV: DB 32H ;	06/08/79  R. CURTISS	FIX DMUL10  MOV D,H
;
;MREV: DB 31H ;	05/31/79  R. CURTISS	SIGNED OPERATIONS
;
;  DOUBLE SUBTRACT  (HL) = (HL) - (DE)
;
	ENTRY	?ISUB
?ISUB:
DSUB:	MOV	A,L
	SUB	E	; SUBTRACT LOW BYTE
	MOV	L,A
	MOV	A,H
	SBB	D	; SUBTRACT HIGH BYTE WITH BORROW
	MOV	H,A
	RET	
;
; ---------------------------------------- CMPEQ
; DOUBLE COMPARE (HL) - (DE)
;
;	IF HL = DE THEN Z=1
;
CMPEQ:	MOV	A,H
	CMP	D
	RNZ

	MOV	A,L
	CMP	E
	RET
;
;
;	IF HL < DE THEN CY=1  --  SIGNED
?CDEHL:
CMPLT:	MOV	A,H
	XRA	D
	MOV	A,H
	RLC		; SET CY = SIGN OF HL
	RM		; RETURN IF SIGNS DIFFERENT
;
;	IF HL < DE THEN CY=1  --  UNSIGNED
;
	ENTRY	?CDEHL
UCMPLT:	MOV	A,H
	CMP	D
	RNZ

	MOV	A,L
	CMP	E
	RET
;
; ----------------------------------------- SPECIAL
;  SPECIAL MULTIPLY AND DIVIDE
;
;	HL = HL * 10  --  SIGNED
;
DMUL10:	MVI	B,0	; MINUS SIGN COUNTER
	CALL	ICOMP	; COMPLEMENT IF NECESSARY
	MOV	D,H
	MOV	E,L
	DAD	H
	DAD	H
	DAD	D
	DAD	H
	DCR	B
	RNZ		; RETURN IF POSITIVE

	JMP	COMP	; COMPLEMENT RESULT
;
;
;	HL = HL / 10  -- SIGNED
;
DDIV10:	MVI	B,0	; MINUS SIGN COUNTER
	CALL	ICOMP
	PUSH	B
	CALL	UDIV10
	POP	B
	DCR	B
	RNZ		; RETURN IF POSITIVE

	XCHG
	CALL	COMP
	XCHG
	JMP	COMP
;
;
;	HL = HL / 10  --  UNSIGNED
;	DE = HL MOD 10
;
UDIV10:	LXI	D,0
	LXI	B,05000H+12  ; B=10  C=LOOP COUNT
	JMP	UDV10B

UDV10A:	XCHG
	DAD	H	; SHIFT DE LEFT 1 BIT
	XCHG
	DAD	H	; SHIFT HL LEFT 1 BIT

UDV10B:	MOV	A,H
	SUB	B
	JC	UDV10C	; JUMP IF CAN'T SUBTRACT 10

	MOV	H,A
	INR	E	; SET LSB OF DE TO 1

UDV10C:	DCR	C	; LOOP COUNT
	JNZ	UDV10A

	XCHG
	MOV	A,D
	RRC
	RRC
	RRC
	RRC
	ANI	0FH
	MOV	E,A	; REMAINDER
	MVI	D,0
	RET
;
;
;	HL = HL / 4  --  UNSIGNED
;
UDIV4:	MOV	A,H
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	MOV	L,H
	RRC
	RRC
	ANI	3FH
	MOV	H,A
	RET
;
; ------------------------------------------ NORMAL
;	NORMAL MULTIPLY AND DIVIDE
;
;	HL = HL * DE  --  SIGNED
;
	ENTRY	?IMUL
?IMUL:
DMULT:	MVI	B,0	; MINUS SIGN COUNTER
	XCHG
	CALL	ICOMP
	XCHG
	CALL	ICOMP
	PUSH	B	; SAVE MINUS SIGN COUNTER
	CALL	UMULT
	POP	PSW	; RECALL MINUS SIGN COUNTER
	ANI	1
	RZ		; RETURN IF RESULT POSITIVE

	JMP	COMP
;
;
;  DOUBLE MULTIPLY  (HL) = (HL) * (DE)  --  UNSIGNED
;
UMULT:	MOV	B,H	; MOVE MULTIPLICAND TO BC
	MOV	C,L
	LXI	H,0	; INITIALIZE RESULT
	MVI	A,16	; INITIALIZE LOOP COUNT
	ORA	A	; CLEAR CARRY
	PUSH	PSW	; SAVE COUNT AND ZERO CARRY
;
MLOOP:	MOV	A,D	; GET MULTIPLIER BIT
	RLC	
	JNC	OVER	; JUMP IF BIT ZERO

	DAD	B

OVER:	POP	PSW	; RECALL LOOP COUNT AND CLEAR CARRY
	DCR	A	; DECREMENT LOOP COUNT
	RZ		; RETURN IF COUNT ZERO

	PUSH	PSW	; SAVE COUNT AND ZERO CARRY
	DAD	H	; SHIFT RESULT LEFT
	XCHG	
	DAD	H	; SHIFT MULTIPLIER LEFT
	XCHG	
	JMP	MLOOP
;
;
;	HL = HL / DE  --  SIGNED
;	DE = HL MOD DE
;
	ENTRY	?IDIV
?IDIV:
DDIV:	MVI	B,0	; MINUS SIGN COUNTER
	CALL	ICOMP
	XCHG
	CALL	ICOMP
	PUSH	B
	CALL	DIV80
	XCHG
	POP	PSW
	ANI	1
	RZ		; RETURN IF RESULT POSITIVE

	XCHG
	CALL	COMP
	XCHG
	JMP	COMP
;
;
;  DOUBLE DIVIDE    (HL) = (HL) / (DE)
;
UDIV:	XCHG	
	CALL	DIV80
	XCHG	
	RET	
;
;
DIV80:	SHLD	TEMP	; SAVE DIVIDEND IN TEMPORARY
	LXI	H,BNUM	; STORE
	MVI	M,17	; BIT COUNT
	LXI	B,0	; INITIALIZE RESULT
	PUSH	B	; SAVE RESULT ON STACK
;
LOOP:	MOV	A,E	; GET LOW DIVISOR BYTE
	RAL	
	MOV	E,A	; SHIFT DIVISOR LEFT ONE BIT
	MOV	A,D
	RAL	
	MOV	D,A
	DCR	M	; DECREMENT BIT COUNT
	POP	H	; RESTORE TEMP RESULT
	RZ		; RETURN IF COUNT ZERO

	MVI	A,0	; ADD IN CARRY
	ACI	0
	DAD	H	; SHIFT TEMP RESULT LEFT
	MOV	B,H	; COPY HL TO AC
	ADD	L
	LHLD	TEMP	; GET DIVIDEND
	SUB	L	; SUBTRACT FROM
	MOV	C,A
	MOV	A,B
	SBB	H	; TEMPORARY RESULT
	MOV	B,A
	PUSH	B	; SAVE TEMP RESULT ON STACK
	JNC	SKIP	; NO BORROW FROM SUBRRACT
;
	DAD	B	; ADD DIVIDEND BACK IN
	XTHL		; REPLACE TEMP RESULT ON STACK
;
SKIP:	LXI	H,BNUM	; RESTORE HL
	CMC		; COMPLEMENT CARRY
	JMP	LOOP
;
;
TEMP:	DS	2	; FOR M   DIVIDE
BNUM:	DS	1	; FOR DIVIDE
;
; ------------------------------------------- ICOMP, COMP
;  TWO'S COMPLEMENT ROUTINE FOR (HL)
;
ICOMP:	MOV	A,H	; CHECK SIGN BIT
	ORA	A
	RP		; RETURN IF POSITIVE

	INR	B	; COUNT NEGATIVE
;
	ENTRY	?ICOMP
?ICOMP:
COMP:	MOV	A,H
	CMA		; COMPLEMENT HIGH BYTE
	MOV	H,A
	MOV	A,L
	CMA		; COMPLEMENT LOW BYTE
	MOV	L,A
	INX	H	; TWO'S COMPLEMENT
	RET	
;
;
	END
