*``````````````````````````````*
* 16-BIT DIVISION:             *
*                              *
* SDIV16, UDIV16, SREM16, AND  *
* UREM16.                      *
*-                            -*
* SDIV16: DIVIDED 2 SIGNED BIT *
* WORDS AND RETURN A 16-BIT    *
* SIGNED QUOTIENT.             *
*                              *
* UDIV16: DIVIDE 2 UNSIGNED    *
* 16BIT WORDS AND RETURN A     *
* 16BIT UNSIGNED QUOTIENT.     *
*                              *
* SREM16: DIVIDE 2 SIGNED      *
* 16BIT WORDS AND RETURN A     *
* 16BIT SIGNED REMAINDER.      *
*                              *
* UREM16: DIVIDE 2 UNSIGNED    *
* 16BIT WORKDS AND RETURN A    *
* 16BIT UNSIGNED REMAINDER.    *
*-                            -*
* CLOBBERS:                    *
*                              *
* FLAGS:  ????----  REG: AXYM  *
*-                            -*
* CYCLES: ???                  *
* SIZE:                        *
*-                            -*
* USAGE:                       *
*                              *
** ALL ROUTINES USE THE SAME   *
** FORMAT.                     *
*                              *
*  LDA #>10000                 *
*  PHA                         *
*  LDA #<10000 ; DIVIDEND      *
*  PHA                         *
*  LDA #>1000 ; DIVISOR        *
*  PHA                         *
*  LDA #<1000                  *
*  PHA                         *
*  JSR UDIV16                  *
*-                            -*
* ENTRY                        *
*                              *
* TOP OF STACK                 *
*                              *
* LOW BYTE OF RETURN ADDRESS   *
* HI BYTE OF RETURN ADDRESS    *
* LOW BYTE OF DIVISOR          *
* HIGH BYTE OF DIVISOR         *
* LOW BYTE OF DIVIDEND         *
* HIGH BYTE OF DIVIDEND        *
*-                            -*
* EXIT                         *
*                              *
* TOP OF STACK                 *
*                              *
* LOW BYTE OF RETURN ADDRESS   *
* HI BYTE OF RETURN ADDRESS    *
*                              *
* IF NO ERRORS, CARRY = 0,     *
* ELSE CARRY=1, QUOTIENT=0,    *
* AND REMAINDER=0              *
*                              *
* .Y = COUNTER; TRASH          *
* .X = COUNTER; TRASH          *
* .A = LOW BYTE OF RET ADDR    *
*                              *
* [RETURN] = RESULT (2 BYTES)  *
* [RETLEN] = 2 (RESULT LENGTH) *
*-                            -*
* ADAPTED FROM LEVANTHAL AND   *
* WINTHROP'S /6502 ASSEMBLY    *
* LANGUAGE ROUTINES/.          *
* AS SUCH, IT MAY FALL UNDER A *
* DIFFERENT LICENSE UNTIL IT   *
* IS RADICALLY REWORKED.       *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
UDIVD16
         LDA   #0
         BEQ   UDIVMD
UREMD16
         LDA   #2
UDIVMD
         STA   _RSLTI
*
** GET RETURN ADDRESS
*
         PLA
         STA   RETADR
         PLA
         STA   RETADR+1
*
** GET PARAMETERS
*
         PLA
         STA   _DVSOR
         PLA
         STA   _DVSOR+1
         PLA
         STA   _DVEND
         PLA
         STA   _DVEND+1
*
         JSR   UDIV
         BCC   DIVOK      ; BR IF NO ERR
DIVERR   JMP   EREXIT
DIVOK    JMP   OKEXIT
*
** SIGNED DIVISION
*
SDIVD16
         LDA   #0         ; RESULT IS QUOTIENT
         BEQ   SDIVMD      ;   (INDEX=0)
*
** SIGNED REMAINDER
*
SREMD16
         LDA   #2         ; RES = REMAINDER (I=2)
         BNE   SDIVMD
*
SDIVMD
         STA   _RSLTI     ;RESULT INDEX;0=Q,2=R
*
** GET RETURN ADDRESS
*
         PLA
         STA   RETADR
         PLA
         STA   RETADR+1
*
** GET PARAMETERS
*
         PLA
         STA   _DVSOR
         PLA
         STA   _DVSOR+1
         PLA
         STA   _DVEND
         PLA
         STA   _DVEND+1
*
*
** DETERMINE SIGN OF QUOTIENT BY
** PERFORMING AN EXCLUSIVE OR OF
** THE HIGH BYTES. IF THE SIGNS
** ARE THE SAME THEN BIT 7 WILL
** BE 0 AND THE QUOTIENT IS
** POSITIVE. IF THE SIGNS ARE
** DIFFERENT THEN THE QUOTIENT
** IS NEGATIVE.
*
         LDA   _DVEND+1
         EOR   _DVSOR+1
         STA   _SQUOT
*
** SIGN OF REMAINDER IS THE SIGN
** OF THE DIVIDEND
*
         LDA   _DVEND+1
         STA   _SREMD
*
** TAKE THE ABSOLUTE VALUE OF
** THE DIVISOR
*
         LDA   _DVSOR+1
         BPL   CHKDE       ; BR IF ALREADY POS
         LDA   #0         ; SUB DVSOR FROM ZERO
         SEC
         SBC   _DVSOR
         STA   _DVSOR
         LDA   #0
         SBC   _DVSOR+1
         STA   _DVSOR+1
*
** TAKE ABS VALUE OF THE DIVIDEND
*
CHKDE
         LDA   _DVEND+1
         BPL   DODIV      ; BR IF DVEND IS POS
         LDA   #0         ; SUB DVEND FROM ZERO
         SEC
         SBC   _DVEND
         STA   _DVEND
         LDA   #0
         SBC   _DVEND+1
         STA   _DVEND+1
*
** DIVIDE ABS VALUES
*
DODIV
         JSR   UDIV
         BCS   EREXIT     ; EXIT IF DIV BY 0
*
** NEGATE QUOTIENT IF IT IS NEGATIVE
*
         LDA   _SQUOT
         BPL   DOREM      ; BR IF Q IS POS
         LDA   #0
         SEC
         SBC   _DVEND
         STA   _DVEND
         LDA   #0
         SBC   _DVEND+1
         STA   _DVEND+1
*
DOREM
*
** NEGATE REMAINDER IF IT IS NEG
*
         LDA   _SREMD
         BPL   OKEXIT     ; BR IF REM IS POS
         LDA   #0
         SEC
         SBC   _DVEND+2
         STA   _DVEND+2
         LDA   #0
         SBC   _DVEND+3
         STA   _DVEND+3
         JMP   OKEXIT
*
** ERROR EXIT (CARRY=1, RSLTS ARE 0)
*
EREXIT
         LDA   #0
         STA   _DVEND
         STA   _DVEND+1   ;QUOTIENT = 0
         STA   _DVEND+2
         STA   _DVEND+3   ; REMAINDER=0
         STA   RETURN
         STA   RETURN+1
         LDA   #2
         STA   RETLEN
         SEC              ; CARRY=1 IF ERROR
         BCS   DVEXIT
*
** GOOD EXIT (CARRY = 0)
*
OKEXIT
         CLC              ; CARRY = 0, NO ERRORS
*
DVEXIT
*
** STORE RESULT
*
         LDX   _RSLTI     ;GET INDEX TO RESULT
                          ; 0=QUOTIENT, 2=REMAINDER
*
** STORE RESULT
*
         LDA   _DVEND,X
         TAY
         LDA   _DVEND+1,X
         TAX
         STY   RETURN
         STX   RETURN+1
         LDA   #2
         STA   RETLEN
*
** RESTORE RETURN ADDRESS
*
         LDA   RETADR+1
         PHA
         LDA   RETADR
         PHA
*
         RTS
*
********************************
* UDIV ROUTINE
********************************
UDIV
*
** ZERO UPPER WORD DIVIDEND
** THIS WILL BE CALLED
** DIVIDEND(1) BELOW
*
         LDA   #0
         STA   _DVEND+2
         STA   _DVEND+3
*
** FIRST CHECK FOR DIV BY 0
*
         LDA   _DVSOR
         ORA   _DVSOR+1
         BNE   OKUDIV     ; BR IF DVSOR NOT 0
         SEC
         RTS
*
** PERFORM THE DIVISION BY
** TRIAL SUBTRACTIONS
*
OKUDIV
         LDX   #16        ; LOOP THROUGH 16 BITS
DIVLP
         ROL   _DVEND     ;SHFT CARRY INTO BIT 0 OF DVEND
         ROL   _DVEND+1   ;WHICH WILL BE THE QUOTIENT AND
         ROL   _DVEND+2   ;SHFT DVEND AT THE SAME TIME
         ROL   _DVEND+3
CHKLT
         SEC
         LDA   _DVEND+2
         SBC   _DVSOR
         TAY              ; SAVE LOW BYTE IN Y
         LDA   _DVEND+3
         SBC   _DVSOR+1   ;SUB HIGHBYTES W RES IN A
         BCC   DECCNT     ; BR IF DVEND < DVSOR AND CARRY
         STY   _DVEND+2   ; ELSE
         STA   _DVEND+3   ;VEN(1)=DVEND(1)-DVSOR
*
DECCNT
         DEX
         BNE   DIVLP
*
         ROL   _DVEND     ;SHFT IN LAST CAR FOR QUOT
         ROL   _DVEND+1
         CLC              ; NO ERRORS, CLEAR CARRY
         RTS
*
** DATA
*
_DVSOR   DS    2          ; DIVISOR
_DVEND   DS    4          ; DIVIDEND[0] AND QUOTIENT
                          ; DIVIDEND[1] AND REMAINDER
_SQUOT   DS    1          ; SIGN OF QUOTIENT
_SREMD   DS    1          ; SIGN OF REMAINDER
_RSLTI   DS    1          ; RESULT INDEX
*
