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