.TITLE DIVIDE ; JEFFREY KODOSKY ARL SEPT76 ; ; SUBR ; ENTRY: 2 ARGS ; ; EXIT: 1 ARG ((QUOTIENT )(REMAINDER )) ; ERRORS: I4, UNDEFINED ARITHMETIC OPERATION ; CALLS: (QUOTIENT) ; (REMAINDER) .GLOBL DIVIDE,ZDIVIDE,QUOTIENT,ZQUOTIENT,RECIP,ZRECIP .GLOBL REMAINDER,ZREMAINDER,QDVI,QDVR,QRI,QIR .GLOBL QMLR,QATM2N,QSBR,QGET,APVAL,QI4ERR,ZSW,QI2ATM .GLOBL QR2ATM,QCONS DIVIDE: MOV #1,DVFLAG BR DIV02 ;JOIN COMMON CODE ZDIVIDE=.-DIVIDE ; ; ; SUBR: RECIPROCAL ; ENTRY: 1 ARG ; EXIT: 1 ARG (QUOTIENT 1 ) ; ERRORS: I4, UNDEFINED ARITHMETIC OPERATION ; CALLS: (QUOTIENT) RECIP: MOV #1,-(SP);NUMERATOR IS INTEGER 1 CLR DVFLAG ;ACT LIKE CALL TO QUOTIENT BR DIV03 ;JOIN COMMON CODE ZRECIP=.-RECIP ; ; ; SUBR: QUOTIENT ; ENTRY: 2 ARGS ; ; EXIT: 1 ARG / ; ERRORS: I4, UNDEFINED ARITHMETIC OPERATION ; CALLS: DVI ; DVR ; IR ; ATM2N ; GET QUOTIENT:CLR (PC)+ DVFLAG: .WORD 0 DIV02: QATM2N ;GET NUMERATOR BCS DIV16 ;JUMP IF ITS FLOATING POINT DIV03: QATM2N ;GET DENOMINATOR BCS DIV10 ;JUMP IF ITS FLOATING POINT MOV 2(SP),-(SP) ;COPY NUMERATOR BEQ DIV07 ;NUMERATOR = ZERO IS SPECIAL CASE MOV 2(SP),-(SP) ;COPY DENOMINATOR BEQ DIV31 ;DENOMINATOR = ZERO IS SPECIAL CASE QDVI ;TRY INTEGER DIVIDE FIRST BCC 1$ JMP DIV60 ;JUMP IF Q=-NEGMAX,R=0 1$: TST R1 ;IS REMAINDER = ZERO? BNE 2$ JMP DIV50 ;IF SO THEN Q IS INTEGER 2$: MOV R1,@SP ;ELSE SAVE REMAINDER MOV 4(SP),-(SP) ;COPY N QIR ;MAKE IT REAL MOV 6(SP),-(SP) ;COPY D QIR ;MAKE IT REAL QDVR ;DO REAL DIVIDE MOV (SP)+,4(SP) MOV (SP)+,4(SP) JMP DIV62 DIV07: TST 2(SP) ;CHECK FOR 0/0 BNE DIV50 QI4ERR ;WHICH IS ALWAYS AN ERROR DIV10: MOV @SP,-(SP) ;MOVE D DOWN MOV 4(SP),2(SP) MOV 6(SP),-(SP) ;COPY N BEQ DIV24 ;N=0 IS SPECIAL CASE QIR ;CONVERT N TO REAL MOV (SP)+,6(SP) MOV (SP)+,6(SP) BR DIV19 DIV16: QATM2N ;GET DENOMINATOR BCS .+4 QIR ;AND MAKE IT REAL BIT #77777,4(SP) BEQ DIV22 ;JUMP IF NUMERATOR IS 0 OR INF DIV19: BIT #77777,@SP BEQ DIV28 ;JUMP IF DENOMINATOR IS 0 OR INF .REPT 4 MOV 6(SP),-(SP) ;COPY N AND D .ENDR QDVR ;REAL DIVIDE BCC DIV40 MOV (SP)+,6(SP) ;Q IS INF, MOVE IT DOWN MOV (SP)+,6(SP) BR DIV37 DIV22: TST 6(SP) BEQ DIV25 ;JUMP IF N=0 BIT #77777,@SP ;N=INF, CHECK D BNE DIV33 ;JUMP IF D NOT 0 OR INF TST 2(SP) BEQ DIV36 ;N=INF & D=0--->Q=INF,R=0 QI4ERR ;INF/INF IS ALWAYS AN ERROR DIV24: TST (SP)+ DIV25: TST (SP)+ ;N=0 CHECK D BNE DIV54 ;JUMP IF D NON-ZERO TST @SP BNE DIV54 QI4ERR ;ELSE ERROR: 0/0 DIV28: TST 2(SP) ;N NOT 0 OR INF, D=0 OR INF BNE DIV72 ;D=INF--->Q=0,R=N BR DIV35 ;ELSE D=0--->Q=INF,R=0 DIV31: ROL 6(SP) ;TRANSFER SIGN OF N TO Q=INF ROR 4(SP) BR DIV36 DIV33: ROL @SP ;SIGN OF Q=INF =SIGN N + SIGN D BCC DIV36 COM 4(SP) DIV35: BIC #77777,4(SP) DIV36: MOV #-1,6(SP) ;MAKE CLEAN INF; R=0 DIV37: ROOM 3 ;CHECK IF INF IS ALLOWED MOV APVAL,-(R5) MOV ZSW,-(R5) QGET TST (R5)+ BNE DIV68 ;ERROR IF NOT QI4ERR ZQUOTIENT=.-QUOTIENT ; ; ; SUBR: REMAINDER ; ENTRY: 2 ARGS ; ; EXIT: 1 ARG (DIFFERENCE (TIMES (FIX ; (QUOTIENT )) )) ; ERRORS: I4, UNDEFINED ARITHMETIC OPERATION ; CALLS: (QUOTIENT) ; MLR ; RI ; IR ; SBR ; I2ATM ; R2ATM ; CONS REMAINDER:MOV #-1,DVFLAG BR DIV02 ;JOIN COMMON QUOTIENT CODE DIV40: TST DVFLAG ;IS R TO BE CALCULATED? BNE DIV43 ;JUMP IF SO MOV (SP)+,6(SP) ;ELSE MOVE UP QUOTIENT MOV (SP)+,6(SP) BR DIV75 ;AND RETURN IT DIV43: MOV @SP,(PC)+ ;SAVE Q QHI: .WORD 0 MOV 2(SP),(PC)+ QLO: .WORD 0 QRI ;FIX Q QIR ;INT(Q) QMLR QSBR ;N - INT[Q]*D MOV 2(SP),-(SP) MOV 2(SP),-(SP) MOV QHI,4(SP) MOV QLO,6(SP) TST DVFLAG BPL DIV83 ;JUMP IF DIVIDE CALL QR2ATM ;ELSE JUST RETURN REMAINDER BR DIV53 DIV50: TST DVFLAG BGT DIV55 ;JUMP IF DIVIDE CALL BEQ DIV52 ;JUMP IF RETURNING ONLY QUOTIENT CLR @SP ;ELSE RETURN ZERO REMAINDER ONLY DIV52: QI2ATM DIV53: CMP (SP)+,(SP)+ JMP @-(R4) DIV54: CLR @SP DIV55: MOV (SP)+,2(SP) ;Q=INTEGER, R=0 CLR @SP CLR -(R5) QI2ATM BR DIV90 DIV60: CLR 4(SP) MOV #^F32768.,2(SP) CLR @SP DIV62: TST DVFLAG BGT DIV80 ;JUMP IF DIVIDE CALL BMI DIV52 ;JUMP IF RETURNING REMAINDER ONLY DIV64: TST (SP)+ ;ELSE RETURN QUOTIENT ONLY BR DIV76 DIV68: TST DVFLAG BEQ DIV75 ;JUMP IF RETURNING JUST QUOTIENT MOV (SP)+,@SP ;CHECK R FOR DIVIDE/REMAINDER CALL BEQ DIV62 QI4ERR ;REMAINDER UNDEFINED FOR INF/D AND D NOT 0 DIV72: TST DVFLAG BMI DIV75 ;JUMP IF R CALL BGT DIV88 ;JUMP IF D CALL ADD #6,SP ;ELSE RETURN ZERO Q CLR @SP QI2ATM .WORD 0 DIV75: CMP (SP)+,(SP)+ DIV76: QR2ATM .WORD 0 DIV80: CLR -(R5) QI2ATM BR DIV84 DIV83: CLR -(R5) QR2ATM DIV84: QCONS QR2ATM BR DIV92 DIV88: CMP (SP)+,(SP)+ CLR -(R5) QR2ATM CLR -(SP) DIV90: QCONS QI2ATM DIV92: QCONS .WORD 0 ZREMAINDER=.-REMAINDER .END