*******************************************************************************
* HC11FP *
* *
* Copyright 1986 *
* by *
* Gordon Doughman *
* *
* The source code for this floating point package for the MC68HC11 *
* may be freely distributed under the rules of public domain. However *
* it is a copyrighted work and as such may not be sold as a product *
* or be included as part of a product for sale without the express *
* permission of the author. Any object code produced by the source *
* code may be included as part of a product for sale. *
* *
* If there are any questions or comments about the floating point *
* package please feel free to contact me. *
* *
* Gordon Doughman *
* Motorola Semiconductor *
* 3490 South Dixie Drive *
* Dayton, OH 45439 *
* (513) 294-2231 *
* *
*******************************************************************************
* *
* MATH11 *
* *
* Revisions to FP11 floating point code *
* Modifications Copyright 1988, Scott Wagner *
* *
* The following improvements have been made to the HC11FP code: *
* 1) Execution time and stack space requirements of the basic *
* arithmetic operations (+-*/) have been reduced. *
* 2) The efficiency of the trigonometric functions has been *
* improved. *
* 3) New functions FLTATAN, FLTLN, FLTLGT, FLTETOX, FLT10TX *
* and FLTXTOY have been added. *
* 4) The polynomial expansion routine POLYNOM is available to *
* evaluate series of arbitrary order. The coefficient table *
* supplied by the user determines the polynomial order. *
* 5) All floating point numbers are now stored in memory in the *
* IEEE floating point format for compatibility with other *
* compilers. *
* *
* These modifications to the HC11FP package are provided under the *
* rules of public domain stated above. Please direct comments about *
* these modifications to: *
* Scott Wagner *
* Rochester Instrument Systems *
* 255 North Union Street *
* Rochester, New York 14605 *
* *
*******************************************************************************
*
*
*
ORG $0000
*
FPACC1EX RMB 1 FLOATING POINT ACCUMULATOR #1..
FPACC1MN RMB 3
MANTSGN1 RMB 1 MANTISSA SIGN FOR FPACC1 (0=+, FF=-).
FPACC2EX RMB 1 FLOATING POINT ACCUMULATOR #2.
FPACC2MN RMB 3
MANTSGN2 RMB 1 MANTISSA SIGN FOR FPACC2 (0=+, FF=-).
*
*
FLTFMTER EQU 1 /* floating point format error in ASCFLT */
OVFERR EQU 2 /* floating point overflow error */
UNFERR EQU 3 /* floating point underflow error */
DIV0ERR EQU 4 /* division by 0 error */
TOLGSMER EQU 5 /* number too large or small to convert to int. */
NSQRTERR EQU 6 /* tried to take the square root of negative # */
TAN90ERR EQU 7 /* TANgent of 90 degrees attempted */
LNNEGERR EQU 8 /* LOG or LN of negative number or 0 */
*
*
TTL ASCFLT
******************************************************************************
* *
* ASCII TO FLOATING POINT ROUTINE *
* *
* This routine will accept most any ASCII floating point format *
* and return a 32-bit floating point number. The following are *
* some examples of legal ASCII floating point numbers. *
* *
* 20.095 *
* 0.125 *
* 7.2984E10 *
* 167.824E5 *
* 5.9357E-7 *
* 500 *
* *
* The floating point number returned is in "FPACC1". *
* *
* *
* The exponent is biased by 128 to facilitate floating point *
* comparisons. A pointer to the ASCII string is passed to the *
* routine in the X-register. *
* *
* *
******************************************************************************
*
*
* ORG $0000
*
* FPACC1EX RMB 1 FLOATING POINT ACCUMULATOR #1..
* FPACC1MN RMB 3
* MANTSGN1 RMB 1 MANTISSA SIGN FOR FPACC1 (0=+, FF=-).
* FPACC2EX RMB 1 FLOATING POINT ACCUMULATOR #2.
* FPACC2MN RMB 3
* MANTSGN2 RMB 1 MANTISSA SIGN FOR FPACC2 (0=+, FF=-).
*
*
* FLTFMTER EQU 1
*
*
* LOCAL VARIABLES (ON STACK POINTED TO BY Y)
*
EXPSIGN EQU 0 EXPONENT SIGN (0=+, FF=-).
PWR10EXP EQU 1 POWER 10 EXPONENT.
*
*
ORG $C000 (TEST FOR EVB)
*
ASCFLT EQU *
PSHX SAVE POINTER TO ASCII STRING.
JSR PSHFPAC2 SAVE FPACC2.
LDX #0 PUSH ZEROS ON STACK TO INITIALIZE LOCALS.
PSHX ALLOCATE 2 BYTES FOR LOCALS.
STX FPACC1EX CLEAR FPACC1.
STX FPACC1EX+2
CLR MANTSGN1 MAKE THE MANTISSA SIGN POSITIVE INITIALLY.
TSY POINT TO LOCALS.
LDX 6,Y GET POINTER TO ASCII STRING.
ASCFLT1 LDAA 0,X GET 1ST CHARACTER IN STRING.
JSR NUMERIC IS IT A NUMBER.
BCS ASCFLT4 YES. GO PROCESS IT.
*
* LEADING MINUS SIGN ENCOUNTERED?
*
ASCFLT2 CMPA #'- NO. IS IT A MINUS SIGN?
BNE ASCFLT3 NO. GO CHECK FOR DECIMAL POINT.
COM MANTSGN1 YES. SET MANTISSA SIGN. LEADING MINUS BEFORE?
INX POINT TO NEXT CHARACTER.
LDAA 0,X GET IT.
JSR NUMERIC IS IT A NUMBER?
BCS ASCFLT4 YES. GO PROCESS IT.
*
* LEADING DECIMAL POINT?
*
ASCFLT3 CMPA #'. IS IT A DECIMAL POINT?
BNE ASCFLT5 NO. FORMAT ERROR.
INX YES. POINT TO NEXT CHARACTER.
LDAA 0,X GET IT.
JSR NUMERIC MUST HAVE AT LEAST ONE DIGIT AFTER D.P.
BCC ASCFLT5 GO REPORT ERROR.
JMP ASCFLT11 GO BUILD FRACTION.
*
* FLOATING POINT FORMAT ERROR
*
ASCFLT5 INS DE-ALLOCATE LOCALS.
INS
JSR PULFPAC2 RESTORE FPACC2.
PULX GET POINTER TO TERMINATING CHARACTER IN STRING.
LDAA #FLTFMTER FORMAT ERROR.
SEC SET ERROR FLAG.
RTS RETURN.
*
* PRE DECIMAL POINT MANTISSA BUILD
*
ASCFLT4 LDAA 0,X
JSR NUMERIC
BCC ASCFLT10
JSR ADDNXTD
INX
BCC ASCFLT4
*
* PRE DECIMAL POINT MANTISSA OVERFLOW
*
ASCFLT6 INC FPACC1EX INC FOR EACH DIGIT ENCOUNTERED PRIOR TO D.P.
LDAA 0,X GET NEXT CHARACTER.
INX POINT TO NEXT.
JSR NUMERIC IS IT S DIGIT?
BCS ASCFLT6 YES. KEEP BUILDING POWER 10 MANTISSA.
CMPA #'. NO. IS IT A DECIMAL POINT?
BNE ASCFLT7 NO. GO CHECK FOR THE EXPONENT.
*
* ANY FRACTIONAL DIGITS ARE NOT SIGNIFIGANT
*
ASCFLT8 LDAA 0,X GET THE NEXT CHARACTER.
JSR NUMERIC IS IT A DIGIT?
BCC ASCFLT7 NO. GO CHECK FOR AN EXPONENT.
INX POINT TO THE NEXT CHARACTER.
BRA ASCFLT8 FLUSH REMAINING DIGITS.
ASCFLT7 CMPA #'E NO. IS IT THE EXPONENT?
BEQ ASCFLT13 YES. GO PROCESS IT.
JMP FINISH NO. GO FINISH THE CONVERSION.
*
* PROCESS THE EXPONENT
*
ASCFLT13 INX POINT TO NEXT CHARACTER.
LDAA 0,X GET THE NEXT CHARACTER.
JSR NUMERIC SEE IF IT'S A DIGIT.
BCS ASCFLT9 YES. GET THE EXPONENT.
CMPA #'- NO. IS IT A MINUS SIGN?
BEQ ASCFLT15 YES. GO FLAG A NEGATIVE EXPONENT.
CMPA #'+ NO. IS IT A PLUS SIGN?
BEQ ASCFLT16 YES. JUST IGNORE IT.
BRA ASCFLT5 NO. FORMAT ERROR.
ASCFLT15 COM EXPSIGN,Y FLAG A NEGATIVE EXPONENT. IS IT 1ST?
ASCFLT16 INX POINT TO NEXT CHARACTER.
LDAA 0,X GET NEXT CHARACTER.
JSR NUMERIC IS IT A NUMBER?
BCC ASCFLT5 NO. FORMAT ERROR.
ASCFLT9 SUBA #$30 MAKE IT BINARY.
STAA PWR10EXP,Y BUILD THE POWER 10 EXPONENT.
INX POINT TO NEXT CHARACTER.
LDAA 0,X GET IT.
JSR NUMERIC IS IT NUMERIC?
BCC ASCFLT14 NO. GO FINISH UP THE CONVERSION.
LDAB PWR10EXP,Y YES. GET PREVIOUS DIGIT.
LSLB MULT. BY 2.
LSLB NOW BY 4.
ADDB PWR10EXP,Y BY 5.
LSLB BY 10.
SUBA #$30 MAKE SECOND DIGIT BINARY.
ABA ADD IT TO FIRST DIGIT.
STAA PWR10EXP,Y
CMPA #38 IS THE EXPONENT OUT OF RANGE?
BHI ASCFLT5 YES. REPORT ERROR.
ASCFLT14 LDAA PWR10EXP,Y GET POWER 10 EXPONENT.
TST EXPSIGN,Y WAS IT NEGATIVE?
BPL ASCFLT12 NO. GO ADD IT TO BUILT 10 PWR EXPONENT.
NEGA
ASCFLT12 ADDA FPACC1EX FINAL TOTAL PWR 10 EXPONENT.
STAA FPACC1EX SAVE RESULT.
BRA FINISH GO FINISH UP CONVERSION.
*
* PRE-DECIMAL POINT NON-DIGIT FOUND, IS IT A DECIMAL POINT?
*
ASCFLT10 CMPA #'. IS IT A DECIMAL POINT?
BNE ASCFLT7 NO. GO CHECK FOR THE EXPONENT.
INX YES. POINT TO NEXT CHARACTER.
*
* POST DECIMAL POINT PROCESSING
*
ASCFLT11 LDAA 0,X GET NEXT CHARACTER.
JSR NUMERIC IS IT NUMERIC?
BCC ASCFLT7 NO. GO CHECK FOR EXPONENT.
BSR ADDNXTD YES. ADD IN THE DIGIT.
INX POINT TO THE NEXT CHARACTER.
BCS ASCFLT8 IF OVER FLOW, FLUSH REMAINING DIGITS.
DEC FPACC1EX ADJUST THE 10 POWER EXPONENT.
BRA ASCFLT11 PROCESS ALL FRACTIONAL DIGITS.
*
*
*
ADDNXTD LDAA FPACC1MN GET UPPER 8 BITS.
STAA FPACC2MN COPY INTO FPAC2.
LDD FPACC1MN+1 GET LOWER 16 BITS OF MANTISSA.
STD FPACC2MN+1 COPY INTO FPACC2.
LSLD MULT. BY 2.
ROL FPACC1MN OVERFLOW?
BCS ADDNXTD1 YES. DON'T ADD THE DIGIT IN.
LSLD MULT BY 4.
ROL FPACC1MN OVERFLOW?
BCS ADDNXTD1 YES. DON'T ADD THE DIGIT IN.
ADDD FPACC2MN+1 BY 5.
PSHA SAVE A.
LDAA FPACC1MN GET UPPER 8 BITS.
ADCA #0 ADDIN POSSABLE CARRY FROM LOWER 16 BITS.
ADDA FPACC2MN ADD IN UPPER 8 BITS.
STAA FPACC1MN SAVE IT.
PULA RESTORE A.
BCS ADDNXTD1 OVERFLOW? IF SO DON'T ADD IT IN.
LSLD BY 10.
ROL FPACC1MN
STD FPACC1MN+1 SAVE THE LOWER 16 BITS.
BCS ADDNXTD1 OVERFLOW? IF SO DON'T ADD IT IN.
LDAB 0,X GET CURRENT DIGIT.
SUBB #$30 MAKE IT BINARY.
CLRA 16-BIT.
ADDD FPACC1MN+1 ADD IT IN TO TOTAL.
STD FPACC1MN+1 SAVE THE RESULT.
LDAA FPACC1MN GET UPPER 8 BITS.
ADCA #0 ADD IN POSSIBLE CARRY. OVERFLOW?
BCS ADDNXTD1 YES. COPY OLD MANTISSA FROM FPACC2.
STAA FPACC1MN NO. EVERYHING OK.
RTS RETURN.
ADDNXTD1 LDD FPACC2MN+1 RESTORE THE ORIGINAL MANTISSA BECAUSE
STD FPACC1MN+1 OF OVERFLOW.
LDAA FPACC2MN
STAA FPACC1MN
RTS RETURN.
*
*
*
* NOW FINISH UP CONVERSION BY MULTIPLYING THE RESULTANT MANTISSA
* BY 10 FOR EACH POSITIVE POWER OF 10 EXPONENT RECIEVED OR BY .1
* (DIVIDE BY 10) FOR EACH NEGATIVE POWER OF 10 EXPONENT RECIEVED.
*
*
FINISH EQU *
STX 6,Y SAVE POINTER TO TERMINATING CHARACTER IN STRING.
LDX #FPACC1EX POINT TO FPACC1.
JSR CHCK0 SEE IF THE NUMBER IS ZERO.
BEQ FINISH3 QUIT IF IT IS.
LDAA FPACC1EX GET THE POWER 10 EXPONENT.
STAA PWR10EXP,Y SAVE IT.
LDAA #$80+24 SET UP INITIAL EXPONENT (# OF BITS + BIAS).
STAA FPACC1EX
JSR FPNORM GO NORMALIZE THE MANTISSA.
TST PWR10EXP,Y IS THE POWER 10 EXPONENT POSITIVE OR ZERO?
BEQ FINISH3 IT'S ZERO, WE'RE DONE.
BPL FINISH1 IT'S POSITIVE MULTIPLY BY 10.
LDX #CONSTP1 NO. GET CONSTANT .1 (DIVIDE BY 10).
JSR GETFPAC2 GET CONSTANT INTO FPACC2.
NEG PWR10EXP,Y MAKE THE POWER 10 EXPONENT POSITIVE.
BRA FINISH2 GO DO THE MULTIPLIES.
FINISH1 LDX #CONST10 GET CONSTANT '10' TO MULTIPLY BY.
JSR GETFPAC2 GET CONSTANT INTO FPACC2.
FINISH2 JSR FLTMUL GO MULTIPLY FPACC1 BY FPACC2, RESULT IN FPACC1.
DEC PWR10EXP,Y DECREMENT THE POWER 10 EXPONENT.
BNE FINISH2 GO CHECK TO SEE IF WE'RE DONE.
FINISH3 INS DE-ALLOCATE LOCALS.
INS
JSR PULFPAC2 RESTORE FPACC2.
PULX GET POINTER TO TERMINATING CHARACTER IN STRING.
RTS RETURN WITH NUMBER IN FPACC1.
*
*
NUMERIC EQU *
CMPA #'0 IS IT LESS THAN AN ASCII 0?
BLO NUMERIC1 YES. NOT NUMERIC.
CMPA #'9 IS IT GREATER THAN AN ASCII 9?
BHI NUMERIC1 YES. NOT NUMERIC.
SEC IT WAS NUMERIC. SET THE CARRY.
RTS RETURN.
NUMERIC1 CLC NON-NUMERIC CHARACTER. CLEAR THE CARRY.
RTS RETURN.
*
FPNORM EQU *
LDX #FPACC1EX POINT TO FPACC1.
BSR CHCK0 CHECK TO SEE IF IT'S 0.
BEQ FPNORM3 YES. JUST RETURN.
TST FPACC1MN IS THE NUMBER ALREADY NORMALIZED?
BMI FPNORM3 YES. JUST RETURN..
FPNORM1 LDD FPACC1MN+1 GET THE LOWER 16 BITS OF THE MANTISSA.
FPNORM2 DEC FPACC1EX DECREMENT THE EXPONENT FOR EACH SHIFT.
BEQ FPNORM4 EXPONENT WENT TO 0. UNDERFLOW.
LSLD SHIFT THE LOWER 16 BITS.
ROL FPACC1MN ROTATE THE UPPER 8 BITS. NUMBER NORMALIZED?
BPL FPNORM2 NO. KEEP SHIFTING TO THE LEFT.
STD FPACC1MN+1 PUT THE LOWER 16 BITS BACK INTO FPACC1.
FPNORM3 CLC SHOW NO ERRORS.
RTS YES. RETURN.
FPNORM4 SEC FLAG ERROR.
RTS RETURN.
*
CHCK0 EQU * CHECKS FOR ZERO IN FPACC POINTED TO BY X.
PSHB SAVE D.
PSHA
LDD 0,X GET FPACC EXPONENT & HIGH 8 BITS.
BNE CHCK01 NOT ZERO. RETURN.
LDD 2,X CHECK LOWER 16 BITS.
CHCK01 PULA RESTORE D.
PULB
RTS RETURN WITH CC SET.
*
CONSTP1 FCB $3E,$CC,$CC,$CD 0.1 DECIMAL
CONST10 FCB $42,$20,$00,$00 10.0 DECIMAL
*
*
TTL FLTMUL
******************************************************************************
* *
* FPMULT: FLOATING POINT MULTIPLY *
* *
* THIS FLOATING POINT MULTIPLY ROUTINE MULTIPLIES "FPACC1" BY *
* "FPACC2" AND PLACES THE RESULT IN TO FPACC1. FPACC2 REMAINS *
* UNCHANGED. *
* WORSE CASE = 480 CYCLES = 240 uS @ 2MHz *
* *
******************************************************************************
*
*
FLTMUL EQU *
TST FPACC1EX CHECK TO SEE IF FPACC1 IS ZERO.
BEQ FPMULT3 IT IS. ANSWER IS 0.
TST FPACC2EX CHECK TO SEE IF FPACC2 IS ZERO.
BNE FPMULT8 IT IS NOT. GO DO MULTIPLY
FPMULT3 LDD #0 ZERO RESULT
STAA MANTSGN1
STD FPACC1EX
STD FPACC1MN+1
BRA FPMULT6 RETURN.
FPMULT8 LDAA MANTSGN1 GET FPACC1 EXPONENT.
EORA MANTSGN2 SET THE SIGN OF THE RESULT.
STAA MANTSGN1 SAVE THE SIGN OF THE RESULT.
LDAA FPACC1EX GET FPACC1 EXPONENT.
ADDA FPACC2EX ADD IT TO FPACC2 EXPONENT.
BPL FPMULT1 IF RESULT IS MINUS AND
BCC FPMULT2 THE CARRY IS SET THEN:
RTNMAX LDAA #OVFERR OVERFLOW ERROR.
RTNDIV0 LDX #$FFFF MAXIMUM MAGNITUDE RESULT
BRA FPMULT7 DO IT AND RETURN.
FPMULT1 BCS FPMULT2 IF RESULT IS PLUS & THE CARRY IS SET THEN ALL OK.
RTNZERO LDAA #UNFERR ELSE UNDERFLOW ERROR OCCURED.
LDX #0 ZERO RESULT
STX FPACC1MN+2 THIS CLEARS MANTSGN1 BYTE
FPMULT7 STX FPACC1EX
STX FPACC1MN+1
SEC FLAG ERROR.
BRA FPMULT6 RETURN.
FPMULT2 ADDA #$80 ADD 128 BIAS BACK IN THAT WE LOST.
STAA FPACC1EX SAVE THE NEW EXPONENT.
LDX #0
PSHX CREATE PARTIAL PRODUCT REGISTER AND COUNTER.
PSHX
TSX POINT TO THE VARIABLES.
JSR UMULT GO MULTIPLY THE "INTEGER" MANTISSAS.
TST 0,X DOES RESULT NEED TO BE NORMALIZED?
BMI FPMROUND NO - GO ROUND RESULT
ROL 3,X FIRST NORMALIZE RESULT
ROL 2,X
ROL 1,X
ROL 0,X
DEC FPACC1EX NOW DECREMENT EXPONENT
FPMROUND TST 3,X CHECK MSB OF BYTE 4 (TO BE DISCARDED LATER)
BPL FPMULT4 NO ROUNDING NECESSARY
LDAA 2,X ROUND LSB UP
INCA INCREMENT RESULT LSB
STAA 2,X PUT LSB BACK
BNE FPMULT4 IF NO CARRY TO RESULT BYTES 1 AND 2
LDAB #1 SET D REGISTER TO 1 (ACCA IS ALREADY 0)
ADDD 0,X INCREMENT BYTES 1 AND 2
BCC FPMULT5 NO OVERFLOW FROM BYTES 1 AND 2
RORA RESULT CHANGES FROM $7FFFFF TO $800000
INC FPACC1EX EXPONENT INCREMENTED (BACK TO WHERE IT WAS)
FPMULT5 STD 0,X PUT BYTES 1 AND 2 BACK
FPMULT4 PULX RETRIEVE BYTES 1 AND 2
STX FPACC1MN STORE IN MANTISSA HIGH BYTES
PULA RETRIEVE BYTE 3 (LSB)
STAA FPACC1MN+2 STORE IN MANTISSA LOW BYTE
INS DISCARD BYTE 4
TST FPACC1EX WAS THERE AN UNDERFLOW ERROR?
BEQ RTNZERO YES. RETURN ERROR.
CLRA SHOW NO ERRORS.
FPMULT6 RTS
*
*
UMULT EQU *
LDAA FPACC2MN+2 GET MULTIPLIER LSB
LDAB FPACC1MN+2 GET MULTIPLICAND LSB
MUL
STAA 1,X TEMPORARILY SAVE RESULT MSB; DISCARD LSB (BYTE 6)
LDAA FPACC2MN+1 GET MULTIPLIER NSB
LDAB FPACC1MN+2 GET MULTIPLICAND LSB
MUL
ADDD 0,X ADD IN LAST PARTIAL RESULT
STD 0,X TEMPORARILY SAVE RESULT
LDAA FPACC2MN+2 GET MULTIPLIER LSB
LDAB FPACC1MN+1 GET MULTIPLICAND NSB
MUL
ADDD 0,X ADD IN LAST PARTIAL RESULT
STAA 3,X SAVE PARTIAL PRODUCT BYTE 4; DISCARD LSB (BYTE 5)
BCC UMULT1 IF NO CARRY OUT TO PRODUCT BYTE 3
INC 2,X CARRY TO PRODUCT BYTE 3
UMULT1 CLR 0,X ZERO PRODUCT BYTES 1 & 2 (USED FOR TEMP. STORAGE)
CLR 1,X
LDAA FPACC2MN GET MULTIPLIER MSB
LDAB FPACC1MN+2 GET MULTIPLICAND LSB
MUL
ADDD 2,X ADD IN LAST PARTIAL RESULT
STD 2,X SAVE IN PARTIAL PRODUCT BYTES 3 AND 4
REMCOMP LDAA FPACC2MN+1 GET MULTIPLIER NSB
LDAB FPACC1MN+1 GET MULTIPLICAND NSB
MUL
ADDD 2,X ADD IN LAST PARTIAL RESULT
STD 2,X SAVE IN PARTIAL PRODUCT BYTES 3 AND 4
BCC UMULT2 IF NO CARRY OUT TO PRODUCT BYTE 2
INC 1,X CARRY TO PRODUCT BYTE 2
UMULT2 LDAA FPACC2MN+2 GET MULTIPLIER LSB
LDAB FPACC1MN GET MULTIPLICAND MSB
MUL
ADDD 2,X ADD IN LAST PARTIAL RESULT
STD 2,X SAVE IN PARTIAL PRODUCT BYTES 3 AND 4
BCC UMULT3 IF NO CARRY OUT TO PRODUCT BYTE 2
INC 1,X CARRY TO PRODUCT BYTE 2
UMULT3 LDAA FPACC2MN GET MULTIPLIER MSB
LDAB FPACC1MN+1 GET MULTIPLICAND NSB
MUL
ADDD 1,X ADD IN LAST PARTIAL RESULT
STD 1,X SAVE IN PARTIAL PRODUCT BYTES 2 AND 3
BCC UMULT4 IF NO CARRY OUT TO PRODUCT BYTE 1
INC 0,X CARRY TO PRODUCT BYTE 1
UMULT4 LDAA FPACC2MN+1 GET MULTIPLIER NSB
LDAB FPACC1MN GET MULTIPLICAND MSB
MUL
ADDD 1,X ADD IN LAST PARTIAL RESULT
STD 1,X SAVE IN PARTIAL PRODUCT BYTES 2 AND 3
BCC UMULT5 IF NO CARRY OUT TO PRODUCT BYTE 1
INC 0,X CARRY TO PRODUCT BYTE 1
UMULT5 LDAA FPACC2MN GET MULTIPLIER MSB
LDAB FPACC1MN GET MULTIPLICAND MSB
MUL
ADDD 0,X ADD IN LAST PARTIAL RESULT
STD 0,X SAVE IN PARTIAL PRODUCT BYTES 2 AND 3
RTS RETURN TO DO NORMALIZATION AND ROUNDING
*
*
*
TTL FLTSUB
******************************************************************************
* *
* FLOATING POINT SUBTRACT SUBROUTINE *
* *
* This subroutine performs floating point subtraction ( FPACC1-FPACC2) *
* by inverting the sign of FPACC2 and then calling FLTADD since *
* FLTADD performs complete signed addition. Upon returning from *
* FLTADD the sign of FPACC2 is again inverted to leave it unchanged *
* from its original value. *
* *
* WORSE CASE = 601 CYCLES = 301 uS @ 2MHz *
* *
******************************************************************************
*
*
FLTSUB EQU *
BSR FLTSUB1 INVERT SIGN.
BSR FLTADD GO DO FLOATING POINT ADD.
FLTSUB1 LDAB MANTSGN2 GET FPACC2 MANTISSA SIGN.
EORB #$FF INVERT THE SIGN.
STAB MANTSGN2 PUT BACK.
RTS RETURN.
*
*
*
TTL FLTADD
******************************************************************************
* *
* FLOATING POINT ADDITION *
* *
* This subroutine performs floating point addition of the two numbers *
* in FPACC1 and FPACC2. The result of the addition is placed in *
* FPACC1 while FPACC2 remains unchanged. This subroutine performs *
* full signed addition so either number may be of the same or opposite *
* sign. *
* WORSE CASE = 563 CYCLES = 282 uS @ 2MHz *
* *
******************************************************************************
*
*
FLTADD EQU *
LDAA FPACC1EX LOAD FP1 EXPONENT
BNE FLTADD1 IF NOT ZERO
TFR2TO1 LDD FPACC2EX GET FPACC2 EXPONENT & HIGH 8 BIT OF MANTISSA.
STD FPACC1EX PUT IT IN FPACC1.
LDD FPACC2MN+1 GET FPACC2 LOW 16 BITS OF MANTISSA.
STD FPACC1MN+1 PUT IT IN FPACC1.
LDAA MANTSGN2 TRANSFER THE SIGN.
STAA MANTSGN1
FLTADDR RTS RETURN.
FLTADD1 TST FPACC2EX CHECK FP2 EXPONENT
BEQ FLTADDR RETURN IF ZERO
LDAB MANTSGN1 LOAD SIGN FROM 1
EORB MANTSGN2 DECIDE TO ADD OR SUBTRACT
SUBA FPACC2EX COMPARE EXPONENTS
BCS FLTADD2 IF FPACC2 > FPACC1
CMPA #24 IF FPACC1 >> FPACC2
BHI FLTADDR RETURN
PSHY SAVE Y REGISTER
PSHA SAVE SHIFT COUNTER
LDX #FPACC2MN ADDEND TO BE DENORMALIZED POINTED TO BY X
LDY #FPACC1MN ADDEND TO BE LEFT NORMALIZED POINTED TO BY Y
BRA FLTADD3 GO DO NORMALIZATION
FLTADD2 NEGA CHANGE SIGN OF A FOR SHIFT COUNTER
CMPA #24 IF FPACC2 >> FPACC1
BHI TFR2TO1 PUT FPACC2 INTO FPACC1 AND RETURN
PSHY SAVE Y REGISTER
PSHA SAVE SHIFT COUNTER
LDAA FPACC2EX LOAD EXPONENT FROM 2
STAA FPACC1EX ... AND TRANSFER IT TO 1
LDAA MANTSGN2 LOAD SIGN FROM 2
STAA MANTSGN1 ... AND TRANSFER IT TO 1
LDX #FPACC1MN ADDEND TO BE DENORMALIZED POINTED TO BY X
LDY #FPACC2MN ADDEND TO BE LEFT NORMALIZED POINTED TO BY Y
FLTADD3 TBA PUT ADD/SUBTRACT FLAG BYTE IN BOTH A AND B
PSHA CREATE 3 BYTE STACK WORKSPACE SET TO $00 FOR ...
PSHA ... ADDITION AND $FF FOR SUBTRACTION.
PSHA
EORA 0,X LOAD MANTISSA MSB; COMPLEMENT IF SUBTRACTION
PSHA PUT IN STACK WORKSPACE
TBA PUT ADD/SUBTRACT FLAG INTO A AGAIN
EORA 1,X LOAD MANTISSA NSB; COMPLEMENT IF SUBTRACTION
PSHA PUT IN STACK WORKSPACE
TBA PUT ADD/SUBTRACT FLAG INTO A AGAIN
EORA 2,X LOAD MANTISSA LSB; COMPLEMENT IF SUBTRACTION
PSHA PUT IN STACK WORKSPACE
TSX PUT POINTER TO WORKSPACE IN X
LDAA 6,X GET SHIFT COUNTER
STAB 6,X SAVE ADD/SUBTRACT FLAG
TAB B REGISTER WILL BE BYTE DISPLACEMENT COUNTER
ANDA #$07 REMOVE BYTE DISPLACEMENT FROM A
INCA PRE-INCREMENT SHIFT COUNTER
ANDB #$18 REMOVE SHIFT DISPLACEMENT FROM B
LSRB RIGHT JUSTIFY BYTE DISPLACEMENT COUNTER
LSRB
LSRB
ABX DO BYTE DISPLACEMENT BY ADDING TO POINTER
LDAB 3,X LOAD ADD/SUBTRACT FLAG (OK SINCE FLAG IN 4 BYTES)
FLTADD4 DECA DECREMENT BYTE SHIFT COUNTER
BEQ FLTADD5 IF DONE SHIFTING
RORB SHIFT ADD/SUBTRACT FLAG INTO CARRY
ROR 2,X SHIFT MANTISSA MSB
ROR 1,X SHIFT MANTISSA NSB
ROR 0,X SHIFT MANTISSA LSB
BRA FLTADD4 GO AROUND AGAIN
FLTADD5 RORB SHIFT ADD/SUBTRACT FLAG INTO CARRY
LDAA 2,Y LOAD NORMALIZED ADDEND LSB
ADCA 0,X ADD IN DENORMALIZED ADDEND LSB
STAA FPACC1MN+2 STORE NORMALIZED SUM LSB
LDAA 1,Y LOAD NORMALIZED ADDEND NSB
ADCA 1,X ADD IN DENORMALIZED ADDEND NSB
STAA FPACC1MN+1 STORE NORMALIZED SUM NSB
LDAA 0,Y LOAD NORMALIZED ADDEND NSB
ADCA 2,X ADD IN DENORMALIZED ADDEND NSB
STAA FPACC1MN STORE NORMALIZED SUM MSB
TSX RESTORE WORKSPACE POINTER
LDAA 6,X GET BACK ADD/SUBTRACT FLAG
BMI FLTADD6 OPERATION WAS SUBTRACTION
BCC FLTADD7 IF ADD AND NO CARRY, DO NOTHING
ROR FPACC1MN CARRY WAS SET; ROTATE TO NORMALIZE OVERFLOW
ROR FPACC1MN+1
ROR FPACC1MN+2
INC FPACC1EX NOW INCREMENT EXPONENT TO ACCOMODATE SHIFT
BNE FLTADD7 SUCCESSFUL COMPLETION
LDD #RTNMAX OVERFLOW - RETURN MAXIMUM NUMBER
BRA FLTADD11
FLTADD6 BCS FLTADD8 NO SIGN CHANGE
COM MANTSGN1 CHANGE SIGN OF RESULT
NEG FPACC1MN+2 CHANGE SIGN OF LSB
BCC FLTADD12 IF LSB WAS ZERO
INC FPACC1MN+1 CARRY FROM LSB
BNE FLTADD12 IF NSB NOT ZERO
INC FPACC1MN CARRY FROM NSB
FLTADD12 NEG FPACC1MN+1 CHANGE SIGN OF NSB
BCC FLTADD13 IF NSB WAS ZERO
INC FPACC1MN CARRY FROM NSB
FLTADD13 NEG FPACC1MN CHANGE SIGN OF MSB
FLTADD8 TST FPACC1MN IS MANTISSA NORMALIZED?
BMI FLTADD7 YES - DONE
BNE FLTADD9 DO BIT SHIFT
LDAA FPACC1EX DECREMENT EXPONENT BY 8 FOR BYTE SHIFT
SUBA #8
BLS FLTADD10 IF UNDERFLOW
STAA FPACC1EX REPLACE DECREMENTED EXPONENT
LDD FPACC1MN+1 DO BYTE SHIFT
BEQ FLTADD10 IF RESULT MANTISSA IS ZERO
CLR FPACC1MN+2 CLEAR BYTE 3
STD FPACC1MN STORE BYTES 1 AND 2
BRA FLTADD8
FLTADD9 DEC FPACC1EX DECREMENT EXPONENT TO ACCOMODATE SHIFT
BEQ FLTADD10 IF UNDERFLOW
LSL FPACC1MN+2 DO BIT SHIFT
ROL FPACC1MN+1
ROL FPACC1MN
BPL FLTADD9
FLTADD7 LDY 7,X PULL Y FROM STACK
LDAB #9 RESTORE STACK - ADD 7 TO X (STACK BASE)
ABX DO ADDITION
TXS NEW STACK BASE (EFFECTIVELY PULLED STACK)
CLRA NO ERRORS
RTS RETURN
*
FLTADD10 LDD #RTNZERO UNDERFLOW - RETURN ZERO
FLTADD11 LDY 7,X PULL Y FROM STACK
STD 7,X PUT RETURN ADDRESS ON STACK
LDAB #7 RESTORE STACK - ADD 5 TO X (STACK BASE)
ABX DO ADDITION
TXS NEW STACK BASE (EFFECTIVELY PULLED STACK)
RTS RETURN THROUGH OVERFLOW OR UNDERFLOW
*
*
*
TTL FLTDIV
******************************************************************************
* *
* FLOATING POINT DIVIDE *
* *
* This subroutine performs signed floating point divide. The *
* operation performed is FPACC1/FPACC2. The divisor (FPACC2) is left *
* unaltered and the answer is placed in FPACC1. There are several *
* error conditions that can be returned by this routine. They are: *
* a) division by zero. b) overflow. c) underflow. As with all *
* other routines, an error is indicated by the carry being set and *
* the error code being in the A-reg. *
* *
* WORSE CASE = 495 CYCLES = 248 uS @ 2MHz *
* *
******************************************************************************
*
*
FLTDIV EQU *
LDAA MANTSGN2 GET FPACC2 MANTISSA SIGN.
EORA MANTSGN1 SET THE SIGN OF THE RESULT.
STAA MANTSGN1 SAVE THE RESULT.
TST FPACC2EX IS THE DIVISOR 0?
BNE FLTDIV1 NO. GO SEE IF THE DIVIDEND IS ZERO.
LDAA #DIV0ERR YES. RETURN A DIVIDE BY ZERO ERROR.
JMP RTNDIV0 FLAG ERROR AND RETURN.
FLTDIV1 TST FPACC1EX IS THE DIVIDEND 0?
BNE FLTDIV2 NO. GO PERFORM THE DIVIDE.
CLRA YES. ANSWER IS ZERO. NO ERRORS.
CLR MANTSGN1 SIGN OF ZERO IS POSITIVE.
RTS RETURN.
FLTDIV2 LDAA FPACC1EX NOW COMPUTE EXPONENT - GET NUMERATOR EXPONENT
SUBA FPACC2EX SUBTRACT DENOMINATOR EXPONENT
BCC FLTDIV8 IF CARRY CLEAR, RESULT MUST BE POSITIVE
BMI FLTDIV6 RESULT IN RANGE
JMP RTNZERO RETURN ZERO
FLTDIV8 BMI FLTDIV7 OVERFLOW - RETURN MAX. NUMBER
FLTDIV6 ADDA #$80 PUT BACK EXPONENT BIAS
STAA FPACC1EX STORE CORRECTED QUOTIENT EXPONENT
LDD FPACC1MN TO DO DIVIDE, NUMERATOR MANTISSA MUST BE LESS ...
SUBD FPACC2MN ... THAN DENOMINATOR MANTISSA.
BMI FLTDIV3 BRANCH IF NUMERATOR LESS THAN DENOMINATOR MANTISSA
BNE FLTDIV4 TEST LSBs ONLY IF NUMERATOR = DENOMINATOR
LDAA FPACC1MN+2 CHECK LSBs SINCE BYTES 1 AND 2 OF ...
SUBA FPACC2MN+2 NUMERATOR AND DENOMINATOR ARE SAME.
BMI FLTDIV3 BRANCH IF NUMERATOR LESS THAN DENOMINATOR MANTISSA
FLTDIV4 LDD FPACC1MN DIVIDE NUMERATOR BY 2 SO IT IS SMALLER THAN DENOM
LSRD SHIFT TO DIVIDE BYTES 1 AND 2
ROR FPACC1MN+2 SHIFT BYTE 3
STD FPACC1MN PUT BYTES 1 AND 2 BACK
INC FPACC1EX NOW INCREMENT EXPONENT
BNE FLTDIV3 CHECK FOR OVERFLOW
FLTDIV7 JMP RTNMAX RETURN MAXIMUM MAGNITUDE NUMBER
FLTDIV3 LDD FPACC1MN GET PARTIAL NUMERATOR
LDX FPACC2MN GET PARTIAL DENOMINATOR
INX PARTIAL QUOTIENT MUST BE LESS THAN FULL QUOTIENT
BNE FLTDIV5 IF X REGISTER ROLLED OVER, WE BLEW IT ...
DEX ... SO RESTORE X REGISTER TO WHERE IT WAS
FLTDIV5 FDIV COMPUTE PARTIAL QUOTIENT
PSHY SAVE Y REGISTER
LDY FPACC1MN TEMPORARY STORAGE FOR NUMERATOR
STX FPACC1MN PARTIAL QUOTIENT TO MULTIPLY BY DENOMINATOR
PSHX SAVE PARTIAL QUOTIENT
LDX #0 SET UP WORK SPACE ON THE STACK.
PSHX
PSHX
TSX SET UP POINTER TO WORK SPACE.
LDAA FPACC2MN+2 MULTIPLY DENOMINATOR LS BYTE ...
LDAB FPACC1MN+1 ... BY NUMERATOR LS BYTE
MUL
STAA 3,X SAVE PARTIAL RESULT ON STACK
JSR REMCOMP JUMP INTO FLOATING MULTIPLY TO FINISH OPERATION
STY FPACC1MN RESTORE NUMERATOR
LDD FPACC1MN+1 MOVE NUMERATOR BYTES 2 AND 3 TO D
SUBD 1,X SUBTRACT TO COMPUTE REMAINDER (ASSUME BYTE 1 SAME)
LDX FPACC2MN LOAD DENOMINATOR
FDIV DIVIDE REMAINDER BY DENOMINATOR
STX FPACC1MN+1 STORE SECOND PARTIAL PRODUCT
CLR FPACC1MN MS BYTE OF SECOND PARTIAL PRODUCT IS ZERO
PULX SCRAP STACK WORKSPACE
PULX
PULA RETRIEVE FIRST PARTIAL PRODUCT
PULB
PULY RETRIEVE Y REGISTER
ADDD FPACC1MN ADD TO SECOND PARTIAL PRODUCT TO GET QUOTIENT
STD FPACC1MN SAVE QUOTIENT IN FLOATING ACCUMULATOR
CLRA NO ERRORS
RTS DONE - RETURN
*
*
*
TTL FLTASC
******************************************************************************
* *
* FLOATING POINT TO ASCII CONVERSION SUBROUTINE *
* *
* This subroutine performs floating point to ASCII conversion of *
* the number in FPACC1. The ascii string is placed in a buffer *
* pointed to by the X index register. The buffer must be at least *
* 14 bytes long to contain the ASCII conversion. The resulting *
* ASCII string is terminated by a zero (0) byte. Upon exit the *
* X Index register will be pointing to the first character of the *
* string. FPACC1 and FPACC2 will remain unchanged. *
* *
******************************************************************************
*
*
FLTASC EQU *
PSHX SAVE THE POINTER TO THE STRING BUFFER.
LDX #FPACC1EX POINT TO FPACC1.
JSR CHCK0 IS FPACC1 0?
BNE FLTASC1 NO. GO CONVERT THE NUMBER.
PULX RESTORE POINTER.
LDD #$3000 GET ASCII CHARACTER + TERMINATING BYTE.
STD 0,X PUT IT IN THE BUFFER.
RTS RETURN.
FLTASC1 LDX FPACC1EX SAVE FPACC1.
PSHX
LDX FPACC1MN+1
PSHX
LDAA MANTSGN1
PSHA
JSR PSHFPAC2 SAVE FPACC2.
LDX #0
PSHX ALLOCATE LOCALS.
PSHX
PSHX SAVE SPACE FOR STRING BUFFER POINTER.
TSY POINT TO LOCALS.
LDX 15,Y GET POINTER FROM STACK.
LDAA #$20 PUT A SPACE IN THE BUFFER IF NUMBER NOT NEGATIVE.
TST MANTSGN1 IS IT NEGATIVE?
BEQ FLTASC2 NO. GO PUT SPACE.
CLR MANTSGN1 MAKE NUMBER POSITIVE FOR REST OF CONVERSION.
LDAA #'- YES. PUT MINUS SIGN IN BUFFER.
FLTASC2 STAA 0,X
INX POINT TO NEXT LOCATION.
STX 0,Y SAVE POINTER.
FLTASC5 LDX #N9999999 POINT TO CONSTANT 9999999.
JSR GETFPAC2 GET INTO FPACC2.
JSR FLTCMP COMPARE THE NUMBERS. IS FPACC1 > 9999999?
BHI FLTASC3 YES. GO DIVIDE FPACC1 BY 10.
LDX #P9999999 POINT TO CONSTANT 999999.9
JSR GETFPAC2 MOVE IT INTO FPACC2.
JSR FLTCMP COMPARE NUMBERS. IS FPACC1 > 999999.9?
BHI FLTASC4 YES. GO CONTINUE THE CONVERSION.
DEC 2,Y DECREMENT THE MULT./DIV. COUNT.
LDX #CONST10 NO. MULTIPLY BY 10. POINT TO CONSTANT.
FLTASC6 JSR GETFPAC2 MOVE IT INTO FPACC2.
JSR FLTMUL
BRA FLTASC5 GO DO COMPARE AGAIN.
FLTASC3 INC 2,Y INCREMENT THE MULT./DIV. COUNT.
LDX #CONSTP1 POINT TO CONSTANT ".1".
BRA FLTASC6 GO DIVIDE FPACC1 BY 10.
FLTASC4 LDX #CONSTP5 POINT TO CONSTANT OF ".5".
JSR GETFPAC2 MOVE IT INTO FPACC2.
JSR FLTADD ADD .5 TO NUMBER IN FPACC1 TO ROUND IT.
LDAB FPACC1EX GET FPACC1 EXPONENT.
SUBB #$81 TAKE OUT BIAS +1.
NEGB MAKE IT NEGATIVE.
ADDB #23 ADD IN THE NUMBER OF MANTISSA BITS -1.
BRA FLTASC17 GO CHECK TO SEE IF WE NEED TO SHIFT AT ALL.
FLTASC7 LSR FPACC1MN SHIFT MANTISSA TO THE RIGHT BY THE RESULT (MAKE
ROR FPACC1MN+1 THE NUMBER AN INTEGER).
ROR FPACC1MN+2
DECB DONE SHIFTING?
FLTASC17 BNE FLTASC7 NO. KEEP GOING.
LDAA #1 GET INITIAL VALUE OF "DIGITS AFTER D.P." COUNT.
STAA 3,Y INITIALIZE IT.
LDAA 2,Y GET DECIMAL EXPONENT.
ADDA #8 ADD THE NUMBER OF DECIMAL +1 TO THE EXPONENT.
* WAS THE ORIGINAL NUMBER > 9999999?
BMI FLTASC8 YES. MUST BE REPRESENTED IN SCIENTIFIC NOTATION.
CMPA #8 WAS THE ORIGINAL NUMBER < 1?
BHS FLTASC8 YES. MUST BE REPRESENTED IN SCIENTIFIC NOTATION.
DECA NO. NUMBER CAN BE REPRESENTED IN 7 DIGITS.
STAA 3,Y MAKE THE DECIMAL EXPONENT THE DIGIT COUNT BEFORE
* THE DECIMAL POINT.
LDAA #2 SETUP TO ZERO THE DECIMAL EXPONENT.
FLTASC8 SUBA #2 SUBTRACT 2 FROM THE DECIMAL EXPONENT.
STAA 2,Y SAVE THE DECIMAL EXPONENT.
TST 3,Y DOES THE NUMBER HAVE AN INTEGER PART? (EXP. >0)
BGT FLTASC9 YES. GO PUT IT OUT.9
LDAA #'. NO. GET DECIMAL POINT.
LDX 0,Y GET POINTER TO BUFFER.
STAA 0,X PUT THE DECIMAL POINT IN THE BUFFER.
INX POINT TO NEXT BUFFER LOCATION.
TST 3,Y IS THE DIGIT COUNT TILL EXPONENT =0?
BEQ FLTASC18 NO. NUMBER IS <.1
LDAA #'0 YES. FORMAT NUMBER AS .0XXXXXXX
STAA 0,X PUT THE 0 IN THE BUFFER.
INX POINT TO THE NEXT LOCATION.
FLTASC18 STX 0,Y SAVE NEW POINTER VALUE.
FLTASC9 LDX #DECDIG POINT TO THE TABLE OF DECIMAL DIGITS.
LDAA #7 INITIALIZE THE THE NUMBER OF DIGITS COUNT.
STAA 5,Y
FLTASC10 CLR 4,Y CLEAR THE DECIMAL DIGIT ACCUMULATOR.
FLTASC11 LDD FPACC1MN+1 GET LOWER 16 BITS OF MANTISSA.
SUBD 1,X SUBTRACT LOWER 16 BITS OF CONSTANT.
STD FPACC1MN+1 SAVE RESULT.
LDAA FPACC1MN GET UPPER 8 BITS.
SBCA 0,X SUBTRACT UPPER 8 BITS.
STAA FPACC1MN SAVE RESULT. UNDERFLOW?
BCS FLTASC12 YES. GO ADD DECIMAL NUMBER BACK IN.
INC 4,Y ADD 1 TO DECIMAL NUMBER.
BRA FLTASC11 TRY ANOTHER SUBTRACTION.
FLTASC12 LDD FPACC1MN+1 GET FPACC1 MANTISSA LOW 16 BITS.
ADDD 1,X ADD LOW 16 BITS BACK IN.
STD FPACC1MN+1 SAVE THE RESULT.
LDAA FPACC1MN GET HIGH 8 BITS.
ADCA 0,X ADD IN HIGH 8 BITS OF CONSTANT.
STAA FPACC1MN SAVE RESULT.
LDAA 4,Y GET DIGIT.
ADDA #$30 MAKE IT ASCII.
PSHX SAVE POINTER TO CONSTANTS.
LDX 0,Y GET POINTER TO BUFFER.
STAA 0,X PUT DIGIT IN BUFFER.
INX POINT TO NEXT BUFFER LOCATION.
DEC 3,Y SHOULD WE PUT A DECIMAL POINT IN THE BUFFER YET?
BNE FLTASC16 NO. CONTINUE THE CONVERSION.
LDAA #'. YES. GET DECIMAL POINT.
STAA 0,X PUT IT IN THE BUFFER.
INX POINT TO THE NEXT BUFFER LOCATION.
FLTASC16 STX 0,Y SAVE UPDATED POINTER.
PULX RESTORE POINTER TO CONSTANTS.
INX POINT TO NEXT CONSTANT.
INX
INX
DEC 5,Y DONE YET?
BNE FLTASC10 NO. CONTINUE CONVERSION OF "MANTISSA".
LDX 0,Y YES. POINT TO BUFFER STRING BUFFER.
FLTASC13 DEX POINT TO LAST CHARACTER PUT IN THE BUFFER.
LDAA 0,X GET IT.
CMPA #$30 WAS IT AN ASCII 0?
BEQ FLTASC13 YES. REMOVE TRAILING ZEROS.
INX POINT TO NEXT AVAILABLE LOCATION IN BUFFER.
LDAB 2,Y DO WE NEED TO PUT OUT AN EXPONENT?
BEQ FLTASC15 NO. WE'RE DONE.
LDAA #'E YES. PUT AN 'E' IN THE BUFFER.
STAA 0,X
INX POINT TO NEXT BUFFER LOCATION.
LDAA #'+ ASSUME EXPONENT IS POSITIVE.
STAA 0,X PUT PLUS SIGN IN THE BUFFER.
TSTB IS IT REALLY MINUS?
BPL FLTASC14 NO. IS'S OK AS IS.
NEGB YES. MAKE IT POSITIVE.
LDAA #'- PUT THE MINUS SIGN IN THE BUFFER.
STAA 0,X
FLTASC14 INX POI