AppleIIAsm-Collection/disks/disk3_math/T.MATH16.DIV16
nathanriggs 16c1731e54 Strings 0.2.0 update
- bugfixes
- implemented required library
- commenting updates
- .min of every routine
2018-12-22 20:35:05 -05:00

336 lines
7.6 KiB
Plaintext

*
*``````````````````````````````*
* 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 ; DIVIDND *
* 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 *
*- -*
* ADAPTED FROM LEVANTHAL AND *
* WINTHROP'S /6502 ASSEMBLY *
* LANGUAGE ROUTINES/. *
* AS SUCH, THIS MAY NOT FALL *
* UNDER THE APACHE 2.0 LICENSE *
* AGREEMENT, SINCE THE BOOK *
* WAS WRITTEN BEFORE THE *
* LICENSE! *
* *
* THAT SAID, LEVENTHAL WROTE *
* THAT THE PURPOSE OF THE BOOK *
* WAS TO COPY THE SOURCE CODE, *
* AS REINVENTING THE WHEEL IS *
* TEDIOUS, AND HE PLACED NO *
* RESTRICTIONS ON ITS USE. *
*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,*
*
UDIV16
LDA #0
BEQ UDIVMD
UREM16
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
*
SDIV16
LDA #0 ; RESULT IS QUOTIENT
BEQ SDIVMD ; (INDEX=0)
*
** SIGNED REMAINDER
*
SREM16
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
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 IN STACK
*
LDA _DVEND,X
TAY
LDA _DVEND+1,X
TAX
*
** RESTORE RETURN ADDRESS
*
LDA _RETADR+1
PHA
LDA _RETADR
PHA
*
RTS
*
*
********************************
* UDIVE 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
*
** MAKING THESE GLOBAL FOR NOW WHILE I TRY TO
** UNDERSTAND THIS ALGORITHM ENOUGH TO MAKE
** IT USE LOCAL VARIABLES
*
_DVSOR DS 2 ; DIVISOR
_DVEND DS 4 ; DIVIDEND[0] AND QUOTIENT
; DIVIDEND[1] AND REMAINDER
_RETADR DS 2
_SQUOT DS 1 ; SIGN OF QUOTIENT
_SREMD DS 1 ; SIGN OF REMAINDER
_RSLTI DS 1 ; RESULT INDEX