


             NAM  TSTFPP
*
*
*           24 BIT REENTRANT FLOATING POINT PACKAGE
*
*           WITH AUXILIARY CONTROL/TEST PROGRAM
*
*
*           PROGRAMMER:
*
*           DR. BENTON D. WEATHERS
*           SANGAMO ELECTRIC COMPANY
*           BOX  3347
*           SPRINGFIELD, ILLINOIS 62714
*
*           217/544-6411 EXT 591
*
             ORG  $0                    DEFINITION OF MEMORY ADDRESSES IN RAM
A1         RMB  3                     RESERVE 3 BYTES OF RAM
A2         RMB  3                     RESERVE THREE BYTES OF RAM
PSH4T1 RMB  2                     WORKING LOCATION FOR PSH4
PSH4T2 RMB  2                     WORKING LOCATION FOR PSH4
L1         RMB  1           LOOP COUNTER
L2         RMB  1           LOOP COUNTER
A3         RMB  3           HOLDS MAIN COPY OF ARG1
ROUADD RMB  2           HOLDS SUBROUTINE ADDRESS
*
INCH     EQU  $FA8B                 SUBROUTINE ADDRESS
OUTCH   EQU  $F9DC                 SUBROUTINE ADDRESS
             PAGE
*
*
*           MAIN CONTROL PROGRAM FOR TESTING
*             THE FLOATING POINT PACKAGE
*
*
             ORG  $8500
             LDS  #$FF                  INITIALIZE STACK POINTER
*
*           MAIN TESTING LOOP
*
LOOP     JSR  QUERY                 NEWLINE, QM ON TTY
             LDAA #'O                   OUTPUT 'O'
             JSR  OUTCH
             LDAA #'C                   OUTPUT 'C'
             JSR  OUTCH
             JSR  INCH                  GET OPERATION CODE
*
*           SEVEN WAY BRANCH
*
             CMPA #'1                   TEST FOR '1'
             BEQ  ADD
             CMPA #'2                   TEST FOR '2'
             BEQ  SUB
             CMPA #'3                   TEST FOR '3'
             BEQ  MUL
             CMPA #'4                   TEST FOR '4'
             BEQ  DIV
             CMPA #'5                   TEST FOR '5'
             BEQ  FLOAT
             CMPA #'6                   TEST FOR '6'
             BEQ  IFIX
             CMPA #'7                   TEST FOR '7'
             BEQ  NEGATE
             CMPA #'8         TEST FOR '8'
             BEQ  CLEAR
*
             LDAA #'X                   INVALID OP-CODE, OUTPUT 'X'
             JSR  OUTCH
             BRA  LOOP                  GO GET NEXT OP-CODE
*
ADD       JSR  SETUP2
             LDX  #FPPADD     LOAD ADDRESS INTO INDEX REG
             BRA  PRINT
*
SUB       JSR  SETUP2
             LDX  #FPPSUB     LOAD ADDRESS
             BRA  PRINT
*
MUL       JSR  SETUP2
             LDX  #FPPMUL
             BRA  PRINT
*
DIV       JSR  SETUP2
             LDX  #FPPDIV
             BRA  PRINT
*
FLOAT   JSR  QUERY
             LDAA #A2
             JSR  READ3B
             LDAA #A1
             LDAB #A2
             JSR  FPPFLT
             BRA  PRIN1
*
IFIX     JSR  SETUP1
             JSR  FPPFIX                FLOATINGPOINT TO INTEGER
             LDAA #'          OUTPUT BLANK CHARACTER
             JSR  OUTCH
             LDAA #A1
             JSR  WRIT3B
             JMP  LOOP
*
NEGATE JSR  SETUP1
             JSR  FPPNEG                FLOATING POINT NEGATE
             BRA  PRIN1
*
CLEAR   LDAA #A1
             JSR  FPPCLR
             BRA  PRIN1
*
*           EXECUTION REPETITION LOOP
PRINT   STX  ROUADD      SAVE THE SUBROUTINE ADDRESS
             LDAA #A3
             LDAB #A1
             JSR  FPPCPY      A3=A1
*
*           INITIALIZE OUTSIDE LOOP
*
             LDAA #2
             STAA L1
LOOP1   DEC  L1          START OF OUTSIDE LOOP
             BNE  LOOPA
             BRA  PRIN1       GET OUT OF EXECUTION LOOP
*
*           INITIALIZE INNER LOOP
*
LOOPA   LDAA #2
             STAA L2
LOOP2   DEC  L2          DECREMENT INNER LOOP COUNTER
             BNE  LOOPB
             BRA  LOOP1       INNER LOOP DONE SO BACK TO OUTER LOOP
*
*           EXECUTION SECTION
*
LOOPB   LDAA #A1
             LDAB #A3
             JSR  FPPCPY      A1=A3
             LDAA #A1
             LDAB #A2
             LDX  ROUADD      SET UP ROUTINE ADDRESS
             JSR  0,X
             BRA  LOOP2
*
*           PRINT RESULTS
*
PRIN1   JSR  NEWLIN
             LDAA #A1                   SET UP ADDRESS OF RESULTS
             JSR  WRIT3B                PRINT RESULTS
             LDAA #'
             JSR  OUTCH
             LDAA #A1
             JSR  FPST                  PRINT RESULT IN DECIMAL FORMAT
             JMP  LOOP                  GO GET NEXT OP-CODE
             PAGE
*
*
*           SETUP1, SETUP2
*
*
SETUP1 JSR  QUERY
             LDAA #A2
             JSR  STFP
             LDAA #A2
             JSR  WRIT3B
             BRA  SUREG                 SET UP POINTERS IN REG'S
*
SETUP2 JSR  QUERY                 NEWLINE, QM ON TTY
             LDAA #A1                   ARG1 TO A1
             JSR  STFP
             LDAA #A1
             JSR  WRIT3B
             JSR  QUERY
             LDAA #A2                   ARG2 TO A2
             JSR  STFP
             LDAA #A2
             JSR  WRIT3B
SUREG   LDAA #A1                   SET UP ADDRESS IN A REG
             LDAB #A2                   SET UP ADDRESS IN B REG
             RTS                        RETURN
*
*
*           READ 3 CONSECUTIVE BYTES (6 CHARACTERS)
*           ON ENTRY THE STORAGE ADDRESS IS IN THE A REG
*           CHARACTER TO HEX CONVERSION IS PERFORMED AND THE
*           BYTES PUT AWAY.
*
READ3B PSHA                       PUT THE MEMORY ADDRESS ON THE STACK
             CLRA
             PSHA
*
*           SET UP THE OUTER LOOP TO GO FROM 3 TO 1
*
             LDAA #3
             PSHA
READ31 LDAA #2                    SET UP INNER LOOP TO GO TWICE
             PSHA
             CLRB                       USE B REG TO MERGE HEX CHARACTERS
READ32 JSR  INCH                  GET CHARACTER FROM TTY
             CMPA #'0                   IS CHR CODE LT ASC '0'
             BLT  READ33                YES
             CMPA #'9                   IS CHR CODE GT ASC '9'
             BGT  READ33                YES
             SUBA #'0                   SUBTRACT CODE FOR ASC '0'
             BRA  READ34                GO TO MERGE SECTION
READ33 CMPA #'A                   IS CHAR CODE LT ASC 'A'
             BLT  READ35                YES, INVALID CHARACTER
             CMPA #'F                   IS CHAR CODE GT ASC 'F'
             BGT  READ35                YES, INVALID CODE
             SUBA #'A                   SUBTRACT CODE FOR ASC 'A'
             ADDA #10                   ADD 10
READ34 ASLB                       MERGE A REG WITH B REG
             ASLB
             ASLB
             ASLB
             ABA                        MERGE
             TAB                        PUT RESULT IN B REG
             TSX                        INDEX REG TO TOP OF STACK
             DEC  0,X                   DECREMENT INNER LOOP COUNTER
             TST 0,X                    IS INNER LOOP CNTR POS?
             BGT  READ32                YES, CONTINUE LOOPING
*
*           PUT THE CHARACTER AWAY
*
             LDX  2,X                   GET ADDRESS OFF THE STACK
             STAB 0,X                   STORE MERGED RESULT
             TSX                        INDES TO TOP OF STACK
             INC  3,X                   INC LSB OF MEMORY ADDRESS
             INS                        REMOVE INNER LOOP CNTR FRM STACK
             DEC  1,X         DECREMENT OUTER LOOP COUNTER
             TST  1,X         IS OUTER LOOP CNTR POSITIVE
             BGT  READ31                YES, GO GET NEXT BYTE
             INS                        CLEAN UP STACK
             INS
             INS
             RTS                        RETURN
*
*           INVALID CHARACTER
*
READ35 LDAA #'X                   OUTPUT AN 'X' CHARACTER
             JSR  OUTCH
             BRA  READ32                REREAD CHARACTER
*
*
*           WRITE THREE CONSECUTIVE BYTES
*
*
WRIT3B PSHA                       PUSH DATA POINTER ONTO STACK
             CLRA
             PSHA
             LDAA #3                    SET OUTER LOOP TO GO 3 TIMES
             PSHA
             DES                        ALLOCATE SPACE ON STACK FOR L2 CNTR
WRIT31 TSX                        INDEX TO TOP OF STACK
             LDX  2,X                   GET DATA POINTER
             LDAB 0,X                   DATA TO B REG
             TSX                        INDEX TO TOP OF STACK
             INC  3,X                   INCREMENT BYTE PONNTER
             LDAA #1                    INNER LOOP INITIALIZATION
             STAA 0,X
*
WRIT32 TBA                        UNPACK FOUR BITS, B REG TO A REG
             TST  0,X                   IS INNER LOOP EQUAL TO ZERO?
             BEQ  WRIT35                YES, SKIP SHIFT OPERATION
             LSRA                       LOGIC SHIFT RIGHT FOUR TIMES
             LSRA
             LSRA
             LSRA
WRIT35 ANDA #15                   MASK OUT 4 MOST SIGNIFICANT BITS
*           UNPACKING COMPLETE
             CMPA #10                   IS 4-BIT FIELD LT 10?
             BLT  WRIT33                YES(DIGIT 0 - 9)
             SUBA #10                   NO (LETTER A - F)
             ADDA #'A                   ADD ASCII 'A' CODE TO RESULT
             BRA  WRIT34                GO TO OUTPUT SECTION
WRIT33 ADDA #'0                   ADD ASCII '0' CODE TO RESULT
WRIT34 JSR  OUTCH                 OUTPUT CHARACTER
             TSX                        INDEX TO TOP OF STACK
             DEC  0,X                   INNER LOOP TEST
             TST  0,X                   IS INNR LOOP CNTR GE 0?
             BGE  WRIT32                YES, CONTINUE WITH LOOP
             DEC  1,X                   OUTER LOOP TEST
             TST  1,X                   IS OUTER LOOP CNTR GT 0?
             BGT  WRIT31                YES, GET NEXT BYTE
             INS                        CLEAN UP STACK
             INS
             INS
             INS
             RTS                        RETURN
*
*
*           QUERY SUBROUTINE
*
*
QUERY   JSR  NEWLIN                CAUSE TTY TO SPACE TO NEW LINE
             LDAA #'?                   OUTPUT QUESTION MARK
             JSR  OUTCH
             RTS
*
*
*           NEWLINE
*
*
NEWLIN LDAA #13                   OUTPUT CARRIAGE RETURN
             JSR  OUTCH
             LDAA #10                   OUTPUT LINE FEED
             JSR  OUTCH
             RTS                        RETURN
             PAGE
*
*
*           STRING TO FLOATING POINT ROUTINE
*
*
STFP     PSHA                       PUSH DATA ADDRESS ONTO STACK
             CLRA
             PSHA
             PSHA                       STFPDP=0 (DEC PNT FLAG)
             PSHA                       STFPSG=0 (NEGATIVE SIGN FLAG)
             LDX  #0
             JSR  PSH4                  STFPA1=0.0
             LDX  #$4000
             LDAA #1
             JSR  PSH4                  STFPA2=1.0
             JSR  PSH4                  STFPA3=???
             LDX  #$5000
             LDAA #4
             JSR  PSH4                  STFPA4=10.0
             TSX                        INDEX POINTS TO TOP OF STACK
*
*           STACK OFFSET DEFINITIONS
*
STFPA4 EQU  1
STFPA3 EQU  5
STFPA2 EQU  9
STFPA1 EQU  13
STFPSG EQU  16                    NEGATIVE SIGN FLAG
STFPDP EQU  17                    DECIMAL POINT FLAG
STFPRS EQU  18                    RESULT ADDRESS
*
*           CHARACTER PROCESSING LOOP
*
STFP1   JSR  INCH                  GET A CHARACTER INTO A REG
             CMPA #$A                   LINE FEED CHARACTER
             BEQ  STFP4                 YES
             CMPA #'-                   MINUS SIGN
             BNE  STFP2                 NO
             INC  STFPSG,X              YES, SET NEGATIVE SIGN FLAG
             BRA  STFP1
STFP2   CMPA #'.                   DECIMAL POINT
             BNE  STFP3                 NO
             INC  STFPDP,X              SET DECIMAL POINT FLAG
             BRA  STFP1
STFP3   CMPA #$40        $40 IS CODE FOR 10
             BPL  STFP1
             CMPA #'0
             BMI  STFP1
*
*           DIGIT DETECTED
*
             SUBA #'0                   SUBTRACT CODE FOR ZERO
             STAA STFPA3+1,X            STORE INTEGER IN A3
             CLR  STFPA3,X
             LDAA STFPA3-1,X
             TAB
             JSR  FPPFLT                A3=FLOAT(A3)
             TSX                        RESTORE INDEX
             LDAA STFPA1-1,X
             LDAB STFPA4-1,X
             JSR  FPPMUL                A1=A1*10.0
             TSX
             LDAA STFPA1-1,X
             LDAB STFPA3-1,X
             JSR  FPPADD                A1=A1+A3
             TSX
             TST  STFPDP,X              IS DECIMAL POINT FLAG SET
             BLE  STFP1                 NO
             LDAA STFPA2-1,X            YES, CALCULATE PWR OF 10.
             LDAB STFPA4-1,X
             JSR  FPPMUL                A2=A2*10.
             TSX
             BRA  STFP1
*
*           CLEANUP
*
STFP4   LDAA STFPA1-1,X
             LDAB STFPA2-1,X
             JSR  FPPDIV                A1=A1/A2
             TSX
             TST  STFPSG,X
             BEQ  STFP5
             LDAA STFPA1-1,X            SIGN FLAG SET
             TAB
             JSR  FPPNEG                A1=-A1
             TSX
STFP5   LDAA STFPA1,X              MOVE TO RESULT AREA
             LDAB STFPA1+1,X
             LDX  STFPRS,X
             STAA 0,X
             STAB 1,X
             TSX
             LDAA STFPA1+2,X
             LDX  STFPRS,X
             STAA 2,X
             LDAA #20
STFP6   INS
             DECA
             BGT  STFP6                 LOOP TO CLEAN UP THE STACK
             RTS
             PAGE
*
*
*           FLOATING POINT TO STRING CONVERSION ROUTINE
*
*
FPST     PSHA                       VALUE ADDRESS ONTO STACK
             CLRA
             PSHA
             TSX                        INDEX TO TOP OF STACK
             LDAA #5
             PSHA             SD=5
             PSHA             DP=5
             LDX  0,X                   GET VALUE ONTO THE STACK
             LDAA 2,X                   EXPONENT INTO THE A REG
             LDX  0,X                   MANTISSA INTO THE INDEX REG
             JSR  PSH4                  A1=INPUT VALUE
             LDX  #$5000
             LDAA #4
             JSR  PSH4                  A2=10.
             LDX  #$4E20
             LDAA #14
             JSR  PSH4        A3=10000.
             LDX  #$61A8
             LDAA #$11
             JSR  PSH4        A4=100000.
             JSR  PSH4                  A5=SCRATCH
             TSX              RESTORE INDEX
*
*           STACK OFFSET DEFINITIONS
*
FPSTA5 EQU  1
FPSTA4 EQU  5
FPSTA3 EQU  9
FPSTA2 EQU  13
FPSTA1 EQU  17
FPSTDP EQU  20
FPSTSD EQU  21
FPSTVL EQU  22
*
             TST  FPSTA1,X              TEST INPUT VALUE
             BEQ  FPST1                 BRANCH IF ZERO
             BMI  FPST2                 BRANCH IF NEGATIVE
             BRA  FPST3                 NUMBER IS READY TO BE SCALED
*
*           ZERO VALUE
*
FPST1   LDAA #'0                   PRINT A SINGLE ZERO
             JSR  OUTCH
             JMP  FPST10                GO CLEAN UP STACK
*
*           NEGATIVE NUMBER
*
FPST2   LDAA #'-                   PRINT MINUS SIGN
             JSR  OUTCH
             LDAA FPSTA1-1,X
             TAB
             JSR  FPPNEG                A1=-A1
             TSX
*
*           NORMALIZING LOOP
*
FPST3   LDAA FPSTA1-1,X
             LDAB FPSTA3-1,X
             JSR  FPPCMP                TEST(A1-10000.)
             TSX                        RESET INDEX
             BPL  FPST4                 BRANCH IF ZERO OR POSITIVE
             LDAA FPSTA1-1,X
             LDAB FPSTA2-1,X
             JSR  FPPMUL                A1=A1*10.
             TSX
             DEC  FPSTDP,X              DP=DP-1
             BRA  FPST3                 CONTINUE LOOP
*
FPST4   LDAA FPSTA1-1,X
             LDAB FPSTA4-1,X
             JSR  FPPCMP                TEST (A1-100000.)
             TSX
             BMI  FPST5                 BRANCH IF NEGATIVE
             LDAA FPSTA1-1,X
             LDAB FPSTA2-1,X
             JSR  FPPDIV                A1=A1/10.
             TSX
             INC  FPSTDP,X              DP=DP+1
             BRA  FPST4                 CONTINUE LOOP
*
*           TEST TO SEE IF DP AND LEADING ZEROS ARE NEEDED
*
FPST5   TST  FPSTDP,X              IS DP CNT NEGATIVE
             BPL  FPST7                 NO
             LDAA #'.                   OUTPUT DECIMAL POINT
             JSR  OUTCH
FPST6   LDAA #'0                   OUTPUT LEADING ZEROS
             JSR  OUTCH
             INC  FPSTDP,X
             BMI  FPST6
             LDAA #$FF                  RESET DP CNT TO NEGATIVE VALUE
             STAA FPSTDP,X
*
*           LOOP TO PRINT FIVE SIGNIFICANT DIGITS
*
FPST7   DEC  FPSTSD,X              SD=SD-1
             BMI  FPST9                 GET OUT IF 5 SD HAVE GONE
             TST  FPSTDP,X              SHOULD DECIMAL BE OUTPUT?
             BNE  FPST8                 NO
             LDAA #'.                   OUTPUT DECIMAL POINT
             JSR  OUTCH
FPST8   DEC  FPSTDP,X              DP=DP-1
             LDAA FPSTA5-1,X            DATA SINK
             LDAB FPSTA1-1,X            DATA SOURCE
             JSR  FPPCPY                A5=A1
             TSX
             LDAA FPSTA5-1,X
             LDAB FPSTA3-1,X
             JSR  FPPDIV                A5=A5/A3
             TSX
             LDAA FPSTA5-1,X
             TAB
             JSR  FPPFIX                A5=IFIX(A5)
             TSX
             LDAA FPSTA5+1,X            OUTPUT DIGIT
             ADDA #'0                   ADD CHARACTER CODE FOR ZERO
             JSR  OUTCH
             LDAA FPSTA5-1,X
             TAB
             JSR  FPPFLT                A5=FLOAT(A5)
             TSX
             LDAA FPSTA5-1,X
             LDAB FPSTA3-1,X
             JSR  FPPMUL                A5=A5*A3
             TSX
             LDAA FPSTA1-1,X
             LDAB FPSTA5-1,X
             JSR  FPPSUB                A1=A1-A5
             TSX
             LDAA FPSTA3-1,X
             LDAB FPSTA2-1,X
             JSR  FPPDIV                A3=A3/10.
             TSX
             JMP  FPST7                 CONTINUE LOOP
*
*           OUTPUT TRAILING ZEROS, IF NECESSARY
*
FPST9   TST  FPSTDP,X              ARE TRAILING ZEROS REQUIRED?
             BLE  FPST10                NO
             DEC  FPSTDP,X
             LDAA #'0                   OUTPUT ZERO
             JSR  OUTCH
             BRA  FPST9                 CONTINUE LOOP
*
*           CLEANUP SECTION
*
FPST10 LDAA #24
FPST11 INS                        INCREMENT STACK POINTER
             DECA                       DECREMENT COUNT
             BGT  FPST11                CONTINUE WHILE COUNT IS POSITIVE
             RTS                        RETURN TO CALL
             PAGE
*
*           ROUTINE TO PUSH FOUR BYTES ON THE STACK.  NOT REENTRANT.
*           PUSHES EXPONENT (FROM A REG), LS BYTE, MS BYTE OF MANTISSA
*           FOLLOWED BY A POINTER TO MS BYTE OF THE MANTISSA
*
PSH4     STX  PSH4T1                SAVE THE MANTISSA
             TSX                        INDEX TO TOP OF STACK
             LDX  0,X                   RETURN ADDRESS TO INDEX
             STX  PSH4T2                SAVE THE RETURN ADDRESS
             INS                        BACK UP THE STACK
             INS
             PSHA                       PUSH EXPONENT ONTO STACK
             LDAA PSH4T1+1              LS BYTE OF MANTISSA
             PSHA                       ONTO THE STACK
             LDAA PSH4T1                MS BYTE OF MANTISSA ONTO THE STACK
             PSHA
             TSX                        INDEX TO TOP OF STACK
             STX  PSH4T1                TRANSFER POINTER TO MEMORY
             LDAA PSH4T1+1              GET LS BYTE OF POINTER
             PSHA                       PUSH ONTO STACK
             LDX  PSH4T2                GET THE RETURN ADDRESS
             JMP  0,X                   RETURN TO CALL
             PAGE
*
*
*           FLOATING POINT COMPARE
*
*           THIS PROGRAM IS NOT REENTRANT.  TO MAKE IT REENTRANT, THE
*           INTERRUPT SYSTEM MUST BE DISABLED WHEN THE MEMORY ADDRESS
*           PSH4T1 IS BEING USED.
*
FPPCMP PSHA                       COPY FIRST ARGUMENT ONTO STACK
             CLRA
             PSHA
             TSX
             LDX  0,X
             LDAA 2,X
             PSHA
             LDAA 1,X
             PSHA
             LDAA 0,X
             PSHA
             TSX
             STX  PSH4T1                INDEX TO SCRATCH MEMORY
             LDAA PSH4T1+1              GET 8 BIT ADDRESS BACK TO A REG
*           B REG SET UP BY CALLING PROGRAM, AND NOT DISTURBED
             JSR  FPPSUB                DESTRUCTIVE SUBTRACT
             TSX
             LDAA 0,X                   MSB OF MANTISSA TO A REG
             INS                        CLEAN UP STACK
             INS
             INS
             INS
             INS
             TSTA                       SET STATUS BITS FOR RESULT
             RTS                        RETURN
             PAGE
*
*
*           COPY FLOATING POINT WORD
*
*
FPPCPY PSHB                       SOURCE ADDRESS ONTO STACK
             CLRB
             PSHB
             PSHA                       PUSH SINK ADDRESS ONTO STACK
             PSHB
             TSX
             LDX  2,X                   SOURCE ADDR INTO X
             LDAA 0,X                   MANTIXSA INTO A AND B REG
             LDAB 1,X
             TSX                        NOW, TRANSMIT MANTISSA
             LDX  0,X
             STAA 0,X
             STAB 1,X
             TSX                        NOW GET EXPONENT
             LDX  2,X
             LDAA 2,X
             TSX
             LDX  0,X
             STAA 2,X
             INS
             INS
             INS
             INS
             RTS                        RETURN TO CALL
             PAGE
*
*           FLOATING POINT NUMBER CONSISTS OF 3 CONSECUTIVE BYTES
*             BYTE 0 - MS BYTE OF 16 BIT 2'S COMPLEMENT MANTISSA
*             BYTE 1 - LS BYTE OF MANTISSA
*             BYTE 2 - 8 BIT 2'S COMPLEMENT BINARY EXPONENT
*
*
*
*           FLOATING POINT SUBTRACT
*
*
FPPSUB JSR  FPPASU                SET UP ARGS
             TSX                        SET INDEX TO TOP OF STACK
             INX                        SET INDEX TO ARG2
             INX
             INX
             INX
             INX
             INX
             JSR  FPPNE1                NEGATE ARGUMENT 2
             BRA  FPPAD0
*
*
*           BASIC NEGATION ROUTINE
*
*
FPPNE1 PSHA                       SAVE A REG
             PSHB                       SAVE B REG
             LDAA 0,X                   MANTISSA TO A AND B REG'X
             LDAB 1,X
             COMA                       TAKE TWO'S COMPLEMENT
             NEGB
             BCS  FPPNE2
             INCA
FPPNE2 CMPA #$80                  CHECK FOR SPECIAL CASE $8000
             BNE  FPPNE3
             CMPB #$00
             BNE  FPPNE3
             CLC                        SPECIAL CASE FOUND, CLEAR CARRY
             RORA                       SHIFT MANTISSA RIGHT
             RORB
             INC  2,X                   INCREMENT EXPONENT
FPPNE3 STAA 0,X                   STORE RESULTS
             STAB 1,X
             PULB                       RESTORE B REG
             PULA                       RESTORE A REG
             RTS                        RETURN
             PAGE
*
*
*           SUBROUTINE FOR ROUNDING, AND FOR OVERFLOW NORMALIZATION
*
*
*           ON ENTRY, A NON-ZERO B REG MEANS ROUNDING IS REQUIRED
*
FPPRND TSTB             IS ROUNDING REQUIRED?
             BEQ  FPPRN9      NO, SO RETURN
FPPRN1 TST  0,X         YES, IS NUMBER POSIBIVE OR NEGATIVE?
             BPL  FPPRN2      NUMBER IS POSITIVE OR ZERO
             TST  1,X         NUMBER IS NEGATIVE, IS LSB ZERO?
             BEQ  FPPRN3      YES
             DEC  1,X         NO (NO BORROW GENERATED)
             RTS              RETURN
FPPRN3 DEC  1,X         BORROW WILL BE GENERATED
             DEC  0,X         SO DECREMENT MSB ALSO
             BRA  FPPRN4      GO CHECK FOR OVERFLOW
FPPRN2 INC  1,X         NUMBER IS POSITIVE SO ROUND UP
             BNE  FPPRN9      GET OUT SINCE THERE IS NO CARRY
             INC  0,X         CARRY SET, SO INCRMT MSB
FPPRN4 BVC  FPPRN9      CHK FOR OVFLW, GET OUT IF CLEAR
*
*           OVERFLOW HANDLING ENTRY POINT
*
FPPOVF INC  2,X         INCREMENT EXPONENT
             TST  0,X         POS OR NEG OVFLW, CARRY=0
             BMI  FPPRN5      BRANCH FOR POSITIVE OVERFLOW
             SEC              NEGATIVE OVERFLOW SO SET CARRY
FPPRN5 ROR  0,X         ROTATE RIGHT MSB OF MANTISSA
             ROR  1,X         ROTATE RIGHT LSB OF MANTISSA
             BCS  FPPRN1      SEE IF FURTHER ROUNDING REQUIRED
FPPRN9 RTS              RETURN TO CALL
             PAGE
*
*
*           FLOATING POINT ADDITION
*
*
FPPADD JSR  FPPASU                SETUP ARGUMENTS ON STACK
FPPAD0 TSX  SET INDEX TO TOP OF STACK
             TST  FPPAR2,X              IS ARG2 ZERO?
             BEQ  FPPMO0                YES, RETURN ARG1
             TST  FPPAR1,X              NO, IS ARG1 ZERO
             BEQ  FPPRT2                YES, RETURN ARG2
             LDAA FPPAR1+2,X            FORM DIFFERENCE OF EXPONENTS
             SUBA FPPAR2+2,X
             STAA FPPEXD,X              PUT IT ON THE STACK
             CMPA #15                   IS DIFF GT 15?
             BGT  FPPMO0                YES, RETURN ARG1
             CMPA #0-15                 NO, IS DIFF LT -15?
             BLT  FPPRT2                YES, RETURN ARG2
             TSTA                       NO, IS ARG2 GT ARG1?
             BGT  FPPAD1      SET INDEX TO ARG2 ON STACK
             BEQ  FPPAD2                EXPONENTS ARE EQUAL
             INX
             INX
             INX
             INX
             INX
             NEGA
FPPAD1 INX                        ADJUST INDEX TO ARGUMENT TO BE SHIFTED
             INX
             INX
             INX
             INX
             INX
             BRA  FPPSFT                SHIFT SMALLER ARGUMENT
FPPAD2 TSX                        RESTORE INDEX TO TOP OF STACK
*
*           ADDITION OF MANTISSAS
*
             LDAA FPPAR1+2,X
             STAA FPPRES+2,X            STORE THE EXPONENT
             LDAA FPPAR1+1,X
             ADDA FPPAR2+1,X
             STAA FPPRES+1,X            STORE LSB OF MANTISSA
             LDAB FPPAR1,X    ADD MSB OF MANTISSAS, USE B REG
             ADCB FPPAR2,X
             TPA              SAVE V IN TH A REG
             STAB FPPRES,X    STORE THE RESULT
             TAP              RESTORE THE V BIT
             BVC  FPPNOR      NORMALIZE IF NO OVERFLOW
             INX              SET INDEX TO RESULT
             INX
             INX
             JSR  FPPOVF      GO TO OVERFLOW-ROUNDING ROUTINE
             TSX              RESTORE INDEX REG
             BRA  FPPNOR      GO TO NORMALIZATION ROUTINE
*
*           RETURN ARGUMENT 2 AS RESULT
*
FPPRT2 LDAA FPPAR2,X              MOVE 3 BYTES TO FPPRES ON STACK
             STAA FPPRES,X
             LDAA FPPAR2+1,X
             STAA FPPRES+1,X
             LDAA FPPAR2+2,X
             STAA FPPRES+2,X
             BRA  FPPMOV                MOVE RESULT TO ARG1 MEMORY LOCATION
*
*           ROUTINE TO SHIFT MANTISSA RIGHT AND ADJUST EXPONENT
*
*           A REGISTER CONTAINS SHIFT COUNT, AND INDEX POINTS TO QUANTITY
*             TO BE ADJUSTED
*
FPPSFT CLRB             SET B TO INDICATE NO ROUNDING
FPPSF1 TSTA             SEE IF FURTHER SHIFTING REQUIRED
             BEQ  FPPSF2      NONE REQUIRED, SO GO TO ROUNDING SECTION
             DECA                       DECREMENT COUNT
             INC  2,X                   INCREMENT EXPONENT
             ASR  0,X                   ARITH SHIFT RIGH MSB OF MANTISSA
             ROR  1,X                   ROTATE RIGHT LSB OF MANTISSA
             BCC  FPPSFT      SET B REG ACCORDING TO STATE OF CARRY BIT
             LDAB #1
             BRA  FPPSF1      CONTINUE LOOP
FPPSF2 JSR  FPPRND      SEE IF ROUNDING REQUIRED
             BRA  FPPAD2      GET OUT OF THIS ROUTINE
*
FPPMO0 BRA  FPPMO1                DUMMY TO EXTEND BRANCHING RANGE
*
             PAGE
*
*           NORMALIZATION ROUTINE (SHIFT MANTISSA LEFT UNTIL TWO MS
*             BITS ARE DIFFERENT.  DO NOT NORMALIZE ZERO RESULT)
*
FPPNOR TST  FPPRES,X              IS MSB OF MANTISSA ZERO
             BNE  FPPNO1                NO, SO NORMALIZE
             TST  FPPRES+1,X            IS LSB OF MANTISSA ZERO?
             BEQ  FPPMOV                YES, DO NOT NORMALIZE
*
*           START OF REGULAR NORMALIZATION
*
FPPNO1 LDAA FPPRES,X              IS SIGN BIT CLEAR?
             BGE  FPPNO2                YES, CHECK FOR BIT 6 SET
             ROLA                       NO, IS BIT 6 CLEAR
             BMI  FPPNO3      NO, GO TO SHIFT LEFT ROUTINE
             BRA  FPPMOV      YES, NORMALIZATION COMPLETE
FPPNO2 ROLA                       SIGN BIT CLEAR, IS BIT 6 SET?
             BMI  FPPMOV      YES, NORMALIZATION COMPLETE
*
*           ROUTINE TO SHIFT RESULT LEFT ONE PLACE
*
FPPNO3 ASL  FPPRES+1,X
             ROL  FPPRES,X              ROTATE LEFT MSB OF MANTISSA
             DEC  FPPRES+2,X            DECREMENT EXPONENT
             BRA  FPPNO1                BACK TO START OF LOOP
*
*
*           MOVE RESULT FROM STACK INTO MEMORY
*
FPPMOV LDAA FPPRES,X
             LDAB FPPRES+1,X
             LDX  FPPPA1,X
             STAA 0,X
             STAB 1,X
             TSX
             LDAA FPPRES+2,X
             LDX  FPPPA1,X
             STAA 2,X
*
*           CLEAN UP STACK
*
FPPMO1 LDAA #FPPRTN+2
FPPMO2 INS                        INCREMENT STACK POINTER
             DECA                       DECREMENT COUNT
             BGT  FPPMO2                LOOP TEST
             RTS                        RETURN FROM SUBROUTINE
             PAGE
*
*
*           FLOATING POINT MULTIPLY
*
*
FPPMUL JSR  FPPASU                SET UP ARGUMENTS ON STACK
             TSX                        SET INDEX TO TOP OF STACK
             JSR  FPPSMD                PROCESS ARGUMENTS
             TSX                        SET INDEX TO TOP OF STACK
             STAB FPPSGN,X              STORE THE SIGN FLAG
             LDAA FPPAR1+2,X            ADD EXPONENTS AND
             ADDA FPPAR2+2,X            STORE IN THE
             DECA             ADJST EXPONENT TO ACCOUNT FOR SHIFT WHICH FOLLOW
             STAA FPPCRY,X    SAVE THE RESULT EXPONENT ON STACK
*
*           MULTIPLY MANTISSAS
*
             ASL  FPPAR2+1,X
             ROL  FPPAR2,X    ROTATE ARG2 TO SAVE A BIT OF SIGNIFICANCE
             CLR  FPPAR1+2,X  CLEAR 3RD BYTE OF ARG1
             CLR  FPPRES,X    CLEAR RESULT LOCATION(24 BIT ACCUMULATOR)
             CLR  FPPRES+1,X
             CLR  FPPRES+2,X
             LDAA #15                   INITIALIZE THE
             STAA FPPCNT,X              LOOP COUNT
FPPMU1 ASL  FPPAR2+1,X            SHIFT ARG2 MANTISSA LEFT
             ROL  FPPAR2,X              IS CARRY SET?
             BCC  FPPMU2                NO, SKIP ADD OPERATION
             LDAA FPPRES+2,X
             ADDA FPPAR1+2,X
             STAA FPPRES+2,X
             LDAA FPPRES+1,X
             ADCA FPPAR1+1,X
             STAA FPPRES+1,X
             LDAA FPPRES,X
             ADCA FPPAR1,X
             STAA FPPRES,X
FPPMU2 LSR  FPPAR1,X              SHIFT ARG 1 MANTISSA RIGHT
             ROR  FPPAR1+1,X
             ROR  FPPAR1+2,X
             DEC  FPPCNT,X              DECREMENT LOOP COUNT
             TST  FPPCNT,X              IS LOOP FINISHED?
             BGT  FPPMU1                NO, GO BACK TO START OF LOOP
             TST  FPPRES,X    IS SIGN BIT SET?
             BLE  FPPMU8      YES, OR POSSIBLY ZERO RESULT
FPPMU3 DEC  FPPCRY,X    DECREMENT EXPONENT
             ASL  FPPRES+2,X  SHIFT RESULT MANTISSA LEFT
             ROL  FPPRES+1,X
             ROL  FPPRES,X
             BPL  FPPMU3      CONTINUE UNTIL SIGN BIT SET
FPPMU8 LDAA FPPCRY,X    MOVE EXPONENT
             STAA FPPRES+2,X
FPPMU6 TST  FPPRES,X    CHECK FOR ZERO RESULT
             BPL  FPPMU7      SKIP OVERFLOW OPERATION FOR ZERO RESULT
             INX              ADJUST FOR OVFLW, AND ROUND RESULT
             INX              SET INDEX TO FPPRES
             INX
             JSR  FPPOVF      CALL OVERFLOW ROUTINE
             TSX
FPPMU7 TST  FPPSGN,X              IS THE RESULT NEGATIVE?
             BEQ  FPPMU4                NO,SKIP COMPLEMENTING OPERATION
             INX                        YES, NEGATE RESULT
             INX
             INX                        INDEX TO FPPRES
             JSR  FPPNE1                NEGATION ROUTINE
             TSX                        RESTORE INDEX
FPPMU4 JMP FPPNOR                 GO TO NORMALIZING ROUTINE
             PAGE
*
*
*           FLOATING POINT DIVIDE
*
*
FPPDIV JSR  FPPASU                SET UP ARGS ON STACK
             TSX                        INDEX TO TOP OF STACK
             TST  FPPAR2,X              IS DIVISOR ZERO?
             BEQ  FPPZDV                YES, PROCESS SPECIAL CASE
             JSR  FPPSMD                PROCESS ARGS 1 & 2
             TSX                        SET INDEX TO TOP OF STACK
             STAB FPPSGN,X              STORE THE SIGN FLAG
             LDAA FPPAR1+2,X            FORM DIFFERENCE OF EXPONENTS
             SUBA FPPAR2+2,X
             STAA FPPRES+2,X            PUT EXPONENT AWAY
             LDAA #16                   INITIALIZE THE
             STAA FPPCNT,X              LOOP COUNTER
*
*           LOGIC TO MAKE SURE 16 BITS OF QUOTIENT ARE COMPUTED
*
             LDAA FPPAR1,X    COMPUTE DIFFERENCE FOUND FIRST TIME AROUND LOOP
             LDAB FPPAR1+1,X
             SUBB FPPAR2+1,X
             SBCA FPPAR2,X
             TSTA             IS REMAINDER NEGATIVE?
             BPL  FPPDI4      NO, LEADING BIT IS 1
             ASL  FPPAR1+1,X  YES, LEADING BIT IS ZERO
             ROL  FPPAR1,X    SO SHIFT NUMERATOR MANTISSA LEFT ONE PLACE
             DEC  FPPRES+2,X  DECREMENT EXPONENT OF RESULT
*
*           MAIN DIVISION LOOP
*
FPPDI1 LDAA FPPAR1,X              LOAD REMAINDER
             LDAB FPPAR1+1,X            WHICH STARTS AS THE NUMERATOR
             SUBB FPPAR2+1,X            SUBTRACT DIVISOR
             SBCA FPPAR2,X
             TSTA                       IS REMAINDER NEGATIVE? (CARRY=0)
             BLT  FPPDI2                YES, CARRY IS CLEAR, SKIP
FPPDI4 SEC              NO, SET CARRY
FPPDI2 ROL  FPPRES+1,X            SHIFT CARRY BIT
             ROL  FPPRES,X              INTO THE QUOTIENT
             TSTA                       IS REMAINDER NEGATIVE?
             BLT  FPPDI3                YES, GO SHIFT OLD REM LEFT
             STAA FPPAR1,X              NO, SO STORE NEW REMAINDER
             STAB FPPAR1+1,X
FPPDI3 ASL  FPPAR1+1,X            SHIFT OLD REMAINDER LEFT
             ROL  FPPAR1,X
             DEC  FPPCNT,X              LOOP TEST
             TST  FPPCNT,X
             BGT  FPPDI1                CONTINUE LOOPING
             JMP  FPPMU6
*
FPPZDV LDAA #127                  ZERO DIVISION, SET Q TO MAX
             STAA FPPRES,X              POSITIVE VALUE
             STAA FPPRES+2,X
             LDAA #$FF
             STAA FPPRES+1,X
             JMP  FPPMOV
             PAGE
*
*           PROCESS TWO ARGUMENTS
*
FPPSMD CLRB                       CLEAR THE SIGN INDICATOR
             INX                        SET INDEX TO ARG 2
             INX
             INX
             INX
             INX
             INX
             JSR  FPPPAR                PROCESS ARGUMENT 2
             INX                        SET INDEX TO ARG1
             INX
             INX
             INX
             INX
             JSR  FPPPAR                PROCESS ARGUMENT 1
             RTS                        RETURN
*
*           SUBROUTINE TO PROCESS MUL ARGS
*
*           INDEX POINTS TO FP ARGUMENT
*
FPPPAR TST  0,X                   IS ARG NEGATIVE
             BGE  FPPPA0                NO, SKIP SIGN CHANGE
             COMB                       COMPLEMENT THE RESULT SIGN
             JSR  FPPNE1                NEGATE ARGUMENT
FPPPA0 RTS              RETURN
*
*           ROUTINE TO SET UP ARGUMENTS ON THE STACK
*
*           A REG CONTAINS POINTER TO ARG1
*           B REG CONTAINS POINTER TO ARG2
*
*           THE B REG WILL BE USED TO CONTROL THE TWO PASS LOOP
*
FPPASU PSHA                       LSB OF ADDRESS ONTO STACK
             CLRA                       CLEAR A REGISTER
             PSHA                       MSB OF ARG ADDRESS ONTO STACK
             TSX                        LOAD ADDRESS OF ARG INTO X
             LDX  0,X
             LDAA 2,X                   ARG EXPONENT ONTO STACK
             PSHA
             LDAA 1,X                   LSB OF ARG MANTISSA ONTO STACK
             PSHA
             LDAA 0,X                   MSB OF ARG MANTISSA ONTO THE STACK
             PSHA
             TSTB                       IS THE B REG CLEAR?
             BEQ  FPPAS2                YES, EXIT FROM LOOP
             TBA                        NO, MOVE BREG TO A REG
             CLRB                       CLEAR B REG TO INDICATE LOOP TERMINATI
             BRA  FPPASU                REPEAT SEQUENCE FOR ARG2
FPPAS2 DES                        LEAVE SIX  ADDITIONAL POSITIONS ON STA
             DES
             DES
             DES
             DES
             DES
             TSX                        SET INDEX TO TOP OF STACK
             LDX  FPPRTN,X
             JMP  0,X                   RETURN (RTS CANNOT BE USED HERE)
*
*           STACK LOCATION SYMBOLS
*
FPPCNT EQU  0                     LOOP COUNTER
FPPCRY EQU  FPPCNT+1              CARRY INDICATOR
FPPSGN EQU FPPCRY+1               PRODUCT (QUOTIENT) SIGN
FPPEXD EQU  FPPSGN                EXPONENT DIFFERENCE
FPPRES EQU  FPPEXD+1              RESULT OF OPERATION
FPPAR2 EQU  FPPRES+3              ARG 2 (DATA)
FPPPA2 EQU  FPPAR2+3              ARG 2 (POINTER)
FPPAR1 EQU  FPPPA2+2              ARG 1 (DATA)
FPPPA1 EQU  FPPAR1+3              ARG 1 (POINTER)
FPPRTN EQU  FPPPA1+2              RETURN ADDRESS
*
*
*           FLOAT
*
*
FPPFLT JSR  FPPASU                SET UP ARGS
             TSX                        SET INDEX TO TOP OF STACK
             LDAA #15                   15 TO THE A REG
             STAA FPPRES+2,X            SET THE RESULT EXPONENT
             LDAA FPPAR2,X              MOVE MANTISSA
             STAA FPPRES,X
             LDAA FPPAR2+1,X
             STAA FPPRES+1,X
             JMP  FPPNOR                GO TO NORMALIZING SECTION
*
*
*           IFIX
*
*
FPPFIX JSR  FPPASU                SET UP ARGS
             TSX                        SET UP INDEX TO TOP OF STACK
             LDAA FPPAR2+2,X            GET EXPONENT INTO A REG
FPPFI1 CMPA #15                   COMPARE EXPONENT WITH 15
             BEQ  FPPFI3                EQUAL
             BGT  FPPFI2                LESS THAN
*           EXPONENT IS LESS THAN 15 SO SHIFT RIGHT
             INCA                       INCREMENT EXPONENT
             ASR  FPPAR2,X              SHIFT MANTISSA RIGHT
             ROR  FPPAR2+1,X
             BRA  FPPFI1                CONTINUE LOOPING
*           EXPONENT GREATER THAN 15 SO SHIFT LEFT (ERROR)
FPPFI2 DECA
             ASL  FPPAR2+1,X            SHIFT MANTISSA LEFT
             ROL  FPPAR2,X
             BRA  FPPFI1                CONTINUE LOOPING
*           EXPONENT EQUAL TO 15 SO SHIFT IS COMPLETE
FPPFI3 LDAA FPPAR2,X              TRANSFER RESULTS
             LDAB FPPAR2+1,X
             LDX  FPPPA1,X
             STAA 0,X
             STAB 1,X
             JMP  FPPMO1                GO CLEAN UP STACK
*
*
*           FLOATING POINT NEGATE
*
*
FPPNEG JSR  FPPASU                SET UP ARGUMENTS
             TSX                        SET INDEX TO TOP OF STACK
             INX                        SET INDEX TO ARG2
             INX
             INX
             INX
             INX
             INX
             JSR  FPPNE1
             TSX                        INDEX TO TOP OF STACK
             JMP  FPPRT2                RETURN ARG2
*
*
*           FLOATING POINT CLEAR
*
*
FPPCLR PSHA                       PUT ADDRESS ONTO STACK
             CLRA
             PSHA
             TSX                        INDEX TO TOP OF STACK
             LDX  0,X                   GET ADDRESS INTO INDEX REG
             CLR  0,X                   CLEAR THREE CONSECUTIVE BYTES
             CLR  1,X
       CLR 2,X
       INS CLEAN UP STACK
             INS
             RTS                        RETURN
             END
