
; Author: Carl Mueller, Jr.

IDIV        PROC

            ; Descr:   Signed integer divide. For a "fast" integer divide for
            ;          numbers less than $8000, use the "Fast" entry point.

            ; Input:   R1  = Dividend (Numerator)
            ;          R2  = Divisor  (Denominator)

            ; Output:  R0  = Quotient
            ;          R1  = Remainder
            ;          R2  = Divisor  (2's complement if Divisor negative)

            ; Notes:   - Quotient = 0 if you pass in a Divisor of 0 (undefined).
            ;          - Signed entry point handles values of -32,768 correctly.
            ;          - Register and space compatible with EXEC's signed
            ;            division routine at $1DFB.

            ; Costs:   40 locations

            MOVR    R1, R1              ; Dividend signed ?
            BPL     @@NumPlus           ; no,  so now check Divisor's sign

            NEGR    R1                  ; yes, so get 2's complement first

            MVO@    R5, R6              ; save RetAddr

            MVII    #@@Negate, R5       ; make Quotient negative on exit
@@NumPlus:
            MOVR    R2, R0              ; Divisor ..
            BPL     @@DenPlus           ; .15 == 0 ? if yes, already positive

            NEGR    R2                  ; .15 == 1 ? if yes, make positive

            MVO@    R5, R6              ; save RetAddr

            MVII    #@@Negate, R5       ; make Quotient negative on exit

            BMI     @@DenMinus          ; == 32,768 ? if yes, special handling
@@Fast:
            MOVR    R2, R0              ; Divisor ..
@@DenPlus:
            BZE     @@DenZero           ; == 0 ? if yes, undefined -- return 0

            SUBR    R0, R0              ; Count = 0
@@Count:
            RRC     R0, 1               ; Count++
            SLL     R2, 1               ; Denominator <<= 1

            CMPR    R1, R2              ; Divisor * 2^X .. Dividend ?
            BNC     @@Count             ; < ?  if yes, check next multiple
            BNZE    @@Divide            ; > ?  if yes, past highest multiple

            CLRR    R1                  ; Remainder = 0
            INCR    R0                  ; Quotient.X = 1
@@Divide:
            SLR     R2, 1               ; Denominator >>= 1
@@DenMinus:
            CMPR    R2, R1              ; Remainder >= Divisor * 2^X ?
            BNC     @@B0                ; no,  so set Quotient.X = 0

            SUBR    R2, R1              ; yes, so set Quotient.X = 1
                                        ; (Remainder -= Divisor * 2^X)
@@B0:
            RLC     R0, 1               ; --Count == 0 ? (Quotient.X <- C)
            BNC     @@Divide            ; no, so get more bits for Quotient
@@DenZero:
            JR      R5                  ; return to caller
@@Negate:
            NEGR    R0                  ; make Quotient negative (or positive)

            MVI@    R6, R7              ; return to caller (or Negate)

            ENDP

