* *``````````````````````````````* * 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 *