*      TTL     FAST FLOATING POINT ASCII TO FLOAT (FFPAFP)
************************************
* (C) COPYRIGHT 1980 MOTORLA INC.  *
************************************

**********************************************************
*                        FFPAFP                          *
*                    ASCII TO FLOAT                      *
*                                                        *
*      INPUT:  A0 - POINTER TO ASCII STRING OF FORMAT    *
*                   DESCRIBED BELOW                      *
*                                                        *
*      OUTPUT: D7 - FAST FLOATING POINT EQUIVALENT       *
*              A0 - POINTS TO THE CHARACTER WHICH        *
*                   TERMINATED THE SCAN                  *
*                                                        *
*      CONDITION CODES:                                  *
*                N - SET IF RESULT IS NEGATIVE           *
*                Z - SET IF RESULT IS ZERO               *
*                V - SET IF RESULT OVERFLOWED            *
*                C - SET IF INVALID FORMAT DETECTED      *
*                X - UNDEFINED                           *
*                                                        *
*      REGISTERS D3 THRU D6 ARE CHANGED                  *
*                                                        *
*      CODE SIZE: 246 BYTES     STACK WORK: 8 BYTES      *
*                                                        *
*      INPUT FORMAT:                                     *
*                                                        *
*     {SIGN}{DIGITS}{'.'}{DIGITS}{'E'}{SIGN}{DIGITS}     *
*     <*********MANTISSA********><*****EXPONENT****>     *
*                                                        *
*                   SYNTAX RULES                         *
*          BOTH SIGNS ARE OPTIONAL AND ARE '+' OR '-'.   *
*          THE MANTISSA MUST BE PRESENT.                 *
*          THE EXPONENT NEED NOT BE PRESENT.             *
*          THE MANTISSA MAY LEAD WITH A DECIMAL POINT.   *
*          THE MANTISSA NEED NOT HAVE A DECIMAL POINT.   *
*                                                        *
*      EXAMPLES:  ALL OF THESE VALUES REPRESENT THE      *
*                 NUMBER ONE-HUNDRED-TWENTY.             *
*                                                        *
*                       120            .120E3            *
*                       120.          +.120E+03          *
*                      +120.          0.000120E6         *
*                   0000120.00  1200000E-4               *
*                               1200000.00E-0004         *
*                                                        *
*      FLOATING POINT RANGE:                             *
*                                                        *
*          FAST FLOATING POINT SUPPORTS THE VALUE ZERO   *
*          AND NON-ZERO VALUES WITHIN THE FOLLOWING      *
*          BOUNDS -                                      *
*                                                        *
*                   18                             20    *
*    9.22337177 X 10   > +NUMBER >  5.42101070 X 10      *
*                                                        *
*                   18                             -20   *
*   -9.22337177 X 10   > -NUMBER > -2.71050535 X 10      *
*                                                        *
*      PRECISION:                                        *
*                                                        *
*          THIS CONVERSION RESULTS IN A 24 BIT PRECISION *
*          WITH GUARANTEED ERROR LESS THAN OR EQUAL TO   *
*          ONE-HALF LEAST SIGNIFICANT BIT.               *
*                                                        *
*                                                        *
*      NOTES:                                            *
*          1) THIS ROUTINE CALLS THE DUAL-BINARY TO FLOAT*
*             ROUTINE AND CAN BE USED AS AN ILLUSTRATION *
*             OF HOW TO 'FRONT-END' THAT ROUTINE WITH    *
*             A CUSTOMIZED SCANNER.                      *
*          2) UNDERFLOWS RETURN A ZERO WITHOUT ANY       *
*             INDICATORS SET.                            *
*          3) OVERFLOWS WILL RETURN THE MAXIMUM VALUE    *
*             POSSIBLE WITH PROPER SIGN AND THE 'V' BIT  *
*             SET IN THE CCR.                            *
*          4) IF THE 'C' BIT IN THE CCR INDICATES AN     *
*             INVALID PATTERN DETECTED, THEN A0 WILL     *
*             POINT TO THE INVALID CHARACTER.            *
*                                                        *
*      LOGIC SUMMARY:                                    *
*                                                        *
*          A) PROCESS LEADING SIGN                       *
*          B) PROCESS PRE-DECIMALPOINT DIGITS AND        *
*             INCREMENT 10 POWER BIAS FOR EACH           *
*             DIGIT BYPASSED DUE TO 32 BIT OVERFLOW      *
*          C) PROCESS POST-DECIMALPOINT DIGITS           *
*             DECREMENTING THE 10 POWER BIAS FOR EACH    *
*          D) PROCESS THE EXPONENT                       *
*          E) ADD THE 10 POWER BIAS TO THE EXPONENT      *
*          F) CALL 'FFPDBF' ROUTINE TO FINISH CONVERSION *
*                                                        *
*   TIMES: (8 MHZ NO WAIT STATES)                        *
*          374 MICROSECONDS CONVERTING THE STRING        *
*                                                        *
*                                                        *
**********************************************************
         PAGE
*FFPAFP   IDNT      1,1       FFP ASCII TO FLOAT

*         OPT       PCS

         XDEF      FFPAFP    ENTRY POINT
         XREF      FFPDBF


FFPAFP   MOVEQ     #0,D7     CLEAR MANTISSA BUILD
         MOVEQ     #0,D6     CLEAR SIGN+BASE10 BUILD

* CHECK FOR LEADING SIGN
         BSR       FPANXT    OBTAIN NEXT CHARACTER
         BEQ.S     FPANMB    BRANCH DIGIT FOUND
         BCS.S     FPANOS    BRANCH NO SIGN ENCOUNTERED

* LEADING SIGN ENCOUNTERED
         CMP.B     #'-',D5   COMPARE FOR MINUS
         SEQ.B     D6        SET ONES IF SO
         SWAP.W    D6        SIGN TO HIGH WORD IN D6

* TEST FOR DIGIT OR PERIOD
         BSR       FPANXT    OBTAIN NEXT CHARACTER
         BEQ.S     FPANMB    BRANCH DIGIT TO BUILD MANTISSA
FPANOS   CMP.B     #'.',D5   ? LEADING DECIMALPOINT
         BNE.S     FPABAD    BRANCH INVALID PATTERN IF NOT

* INSURE AT LEAST ONE DIGIT
         BSR       FPANXT    OBTAIN NEXT CHARACTER
         BEQ.S     FPADOF    BRANCH IF FRACTION DIGIT

* INVALID PATTERN DETECTED
FPABAD   SUBQ.L    #1,A0     POINT TO INVALID CHARACTER
*        ORI       #$01,CCR  SET CARRY BIT ON
         DC.L      $003C0001 ****ASSEMBLER ERROR****
         RTS                 RETURN

* PRE-DECIMALPOINT MANTISSA BUILD
FPANXD   BSR       FPANXT    NEXT CHARACTER
         BNE.S     FPANOD    BRANCH NOT A DIGIT
FPANMB   BSR.S     FPAX10    MULTIPLY TIMES TEN
         BCC.S     FPANXD    LOOP FOR MORE DIGITS

* PRE-DECIMALPOINT MANTISSA OVERFLOW, COUNT TILL END OR DECIMAL REACHED
FPAMOV   ADDQ.W    #1,D6     INCREMENT TEN POWER BY ONE
         BSR.S     FPANXT    OBTAIN NEXT PATTERN
         BEQ.S     FPAMOV    LOOP UNTIL NON-DIGIT
         CMP.B     #'.',D5   ? DECIMAL POINT REACHED
         BNE.S     FPATSE    NO, NO CHECK FOR EXPONENT

* FLUSH REMAINING FRACTIONAL DIGITS
FPASRD   BSR.S     FPANXT    NEXT CHARACTER
         BEQ.S     FPASRD    IGNORE IT IF STILL DIGIT
FPATSE   CMP.B     #'E',D5   ? EXPONENT HERE
         BNE.S     FPACNV    NO, FINISHED - GO CONVERT

* NOW PROCESS THE EXPONENT
         BSR.S     FPANXT    OBTAIN FIRST DIGIT
         BEQ.S     FPANTE    BRANCH GOT IT
         BCS.S     FPABAD    BRANCH INVALID FORMAT, NO SIGN OR DIGITS
         ROL.L     #8,D6     HIGH BYTE OF D6 INTO LOW
         CMP.B     #'-',D5   ? MINUS SIGN
         SEQ.B     D6        SET ONES OR ZERO
         ROR.L     #8,D6     D6 HIGH BYTE IS EXPONENTS SIGN
         BSR.S     FPANXT    NOW TO FIRST DIGIT
         BNE.S     FPABAD    BRANCH INVALID - DIGIT EXPECTED

* PROCESS EXPONENT'S DIGITS
FPANTE   MOVE.W    D5,D4     COPY DIGIT JUST LOADED
FPANXE   BSR.S     FPANXT    EXAMINE NEXT CHARACTER
         BNE.S     FPAFNE    BRANCH END OF EXPONENT
         MULU.W    #10,D4    PREVIOUS VALUE TIMES TEN
         CMP.W     #2000,D4  ? TOO LARGE
         BHI.S     FPABAD    BRANCH EXPONENT WAY OF BASE
         ADD.W     D5,D4     ADD LATEST DIGIT
         BRA.S     FPANXE    LOOP FOR NEXT CHARACTER

* ADJUST FOR SIGN AND ADD TO ORIGINAL INDEX
FPAFNE   TST.L     D6        ? WAS EXPONENT NEGATIVE
         BPL.S     FPAADP    BRANCH IF SO
         NEG.W     D4        CONVERT TO NEGATIVE VALUE
FPAADP   ADD.W     D4,D6     FINAL RESULT
FPACNV   SUBQ.L    #1,A0     POINT TO TERMINATOR
         JMP       FFPDBF    NOW CONVERT TO FLOAT

* PRE-DECIMALPOINT NON-DIGIT ENCOUNTERED
FPANOD   CMP.B     #'.',D5   ? DECIMAL POINT HERE
         BNE.S     FPATSE    NOPE, TRY FOR THE 'E'

* POST-DECIMALPOINT PROCESSING
FPADPN   BSR.S     FPANXT    OBTAIN NEXT CHARACTER
         BNE.S     FPATSE    NOT A DIGIT, TEST FOR E'
FPADOF   BSR.S     FPAX10    TIMES TEN PREVIOUS VALUE
         BCS.S     FPASRD    FLUSH IF OVERFLOW NOW
         SUBQ.W    #1,D6     ADJUST 10 POWER BIAS
         BRA.S     FPADPN    AND TO NEXT CHARACTER

*   *
*   * FPAX10 SUBROUTINE - PROCESS NEXT DIGIT
*   *  OUTPUT: C=0 NO OVERFLOW, C=1 OVERFLOW (D7 UNALTERED)
*   *
FPAX10   MOVE.L    D7,D3     COPY VALUE
         LSL.L     #1,D3     TIMES TWO
         BCS.S     FPAXRT    RETURN IF OVERFLOW
         LSL.L     #1,D3     TIMES FOUR
         BCS.S     FPAXRT    RETURN IF OVERFLOW
         LSL.L     #1,D3     TIMES EIGHT
         BCS.S     FPAXRT    RETURN IF OVERFLOW
         ADD.L     D7,D3     ADD ONE TO MAKE X 9
         BCS.S     FPAXRT    RETURN IF OVERFLOW
         ADD.L     D7,D3     ADD ONE TO MAKE X 10
         BCS.S     FPAXRT    RETURN IF OVERFLOW
         ADD.L     D5,D3     ADD NEW UNITS DIGIT
         BCS.S     FPAXRT    RETURN IF OVERFLOW
         MOVE.L    D3,D7     UPDATE RESULT
FPAXRT   RTS                 RETURN


*
* FPANXT SUBROUTINE - RETURN NEXT INPUT PATTERN
*
*    INPUT:  A0
*
*    OUTPUT:  A0 INCREMENTED BY ONE
*             IF Z=1 THEN DIGIT ENCOUNTERED AND D5.L SET TO BINARY VALUE
*             IF Z=0 THEN D6.B SET TO CHARACTER ENCOUNTERED
*                         AND C=0 IF PLUS OR MINUS SIGN
*                             C=1 IF NOT PLUS OR MINUS SIGN
*

FPANXT   MOVEQ     #0,D5     ZERO RETURN REGISTER
         MOVE.B    (A0)+,D5  LOAD CHARACTER
         CMP.B     #'+',D5   ? PLUS SIGN
         BEQ.S     FPASGN    BRANCH IF SIGN
         CMP.B     #'-',D5   ? MINUS SIGN
         BEQ.S     FPASGN    BRANCH IF SIGN
         CMP.B     #'0',D5   ? LOWER THAN A DIGIT
         BCS.S     FPAOTR    BRANCH IF NON-SIGNDIGIT
         CMP.B     #'9',D5   ? HIGHER THAN A DIGIT
         BHI.S     FPAOTR    BRANCH IF NON-SIGNDIGIT
* IT IS DIGIT
         AND.B     #$0F,D5   TO BINARY
*        MOVE.W    #$0004,CCR SET Z=1 AND C=0
         DC.L      $44FC0004 ***ASSEMBLER ERROR***
         RTS                 RETURN
* IT IS SIGN
FPASGN   EQU       *
*        MOVE.W    #$0000,CCR SET Z=0 AND C=0
         DC.L      $44FC0000 ***ASSEMBLER ERROR***
         RTS                 RETURN
* IT IS NEITHER SIGN NOR DIGIT
FPAOTR   EQU       *
*        MOVE.W    #$0001,CCR SET Z=0 AND C=1
         DC.L      $44FC0001 ***ASSEMBLER ERROR***
         RTS                 RETURN

         END
