URL
                    https://opencores.org/ocsvn/ft816float/ft816float/trunk
                
            Subversion Repositories ft816float
[/] [ft816float/] [trunk/] [software/] [FAC1ToString.asm] - Rev 8
Go to most recent revision | Compare with Previous | Blame | View Log
; ============================================================================; FAC1ToString.asm; __; \\__/ o\ (C) 2014 Robert Finch, Stratford; \ __ / All rights reserved.; \/_// robfinch<remove>@finitron.ca; ||;;; This source file is free software: you can redistribute it and/or modify; it under the terms of the GNU Lesser General Public License as published; by the Free Software Foundation, either version 3 of the License, or; (at your option) any later version.;; This source file is distributed in the hope that it will be useful,; but WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License; along with this program. If not, see <http://www.gnu.org/licenses/>.;; ============================================================================;; This code is a heavily modified version of the floating point to string; conversion routine which is a part of Lee Davison's EhBASIC.;Cvaral = $95 ; current var address low byteCvarah = Cvaral+1 ; current var address high bytenumexp = $A8 ; string to float number exponent countexpcnt = $AA ; string to float exponent countSendl = $BA ; BASIC pointer temp low byteSendh = $BB ; BASIC pointer temp low byteDecss = $3A0 ; number to decimal string startDecssp1 = Decss+1 ; number to decimal string startFP_ADD EQU 1FP_SUB EQU 2FP_MUL EQU 3FP_DIV EQU 4FP_FIX2FLT EQU 5FP_FLT2FIX EQU 6FP_ABS EQU 7FP_NEG EQU 16FP_SWAP EQU 17FIXED_MUL EQU $83FIXED_ADD EQU $81FIXED_SUB EQU $82;parameter FIXED_DIV = 8'h84;;parameter FIXED_ABS = 8'h87;;parameter FIXED_NEG = 8'h90;FP_CMDREG EQU $FEA20EFP_STATREG EQU $FEA20EFAC1 EQU $FEA200FAC1_5 EQU $FEA200FAC1_4 EQU $FEA202FAC1_3 EQU $FEA204FAC1_2 EQU $FEA206FAC1_1 EQU $FEA208FAC1_msw EQU $FEA208FAC1_e EQU $FEA20AFAC2 EQU $FEA210CPU W65C816SNDX 16MEM 16public FAC1ToString:; The first chunk of code determines if the number is positive or negative; and spits out the appropriate sign. Next it takes the absolute value of; the accumulator so following code only has to deal with positive numbers.LDY #$00 ; set index = 1LDA FAC1_msw ; test FAC1 sign (b15) (Can't use BIT)BPL .0002 ; branch if +veLDA #'-' ; else character = "-"STA Decss,Y ; save leading character (" " or "-")LDA #FP_NEG ; make the FAC positiveJSR FPCommandWaitBRA .0001.0002:LDA #$20 ; character = " " (assume +ve)STA Decss,Y.0001:STY Sendl ; save index; This little bit of code check for a zero exponent which indicates a; value of zero.LDA FAC1_e ; get FAC1 exponentTAXBNE LAB_2989 ; branch if FAC1<>0; exponent was $00 so FAC1 is 0LDA #'0' ; set character = "0"BRL LAB_2A89 ; save last character, [EOT] and exit; This loop attempts to make small values more significant, so that there are; fewer leading zeros in the value. (The exponent is decremented so that it; corresponds). Because of the potential for extremely small values looping is; limited. The problem is the 16 bit exponent can allow for much smaller; values than an 8 bit exponent would and we don't want to loop for thousands; of iterations in order to display a value that's almost zero.; FAC1 is some non zero valueLAB_2989STY Sendl ; save off .YLDY #1639 ; max number of retriesLDA #$00 ; clear (number exponent count)STA numexpLOOP_MBMILLION:CPX #$8000 ; compare FAC1 exponent with $8000 (>1.00000)BCS LAB_299A ; branch if FAC1=>1; FAC1<1PEA A_MILLION ; multiply FAC * 1,000,000JSR LOAD_FAC2 ;PLA ; get rid of parameterJSR FMULLDA numexpSECSBC #6 ; set number exponent count (-6)STA numexpLDA FAC1_eTAXDEYBPL LOOP_MBMILLIONLAB_299ALDY Sendl ; get back .Y; These two loops coerce the value of the FAC to be between 100,000 and; 1,000,000. This gives a maximum of six digits before the decimal point; in scientific notation.; This loop divides by 10 until the value in the FAC is less than 1,000,000;LOOP_DB10:PEA MAX_BEFORE_SCI ; set pointer low byte to 999999.4375 (max before sci note)JSR LOAD_FAC2 ; compare FAC1 with (AY)PLA ; get rid of parameterLDA FP_CMDREGBIT #$08 ; test equals bitBNE LAB_29C3 ; exit if FAC1 = (AY)BIT #$04 ; test greater than bitBEQ LOOP_MB10 ; go do *10 if FAC1 < (AY)LAB_29B9JSR DivideByTen ; divide by 10INC numexp ; increment number exponent countBRA LOOP_DB10 ; go test again (branch always); This loop multiplies the value by 10 until it's greater than; 100,000.; FAC1 < (AY)LOOP_MB10PEA CONST_9375 ; set pointer to 99999.9375JSR LOAD_FAC2 ; compare FAC1 with (AY)PLA ; get rid of parameterLDA FP_CMDREGBIT #$08BNE LAB_29B2 ; branch if FAC1 = (AY) (allow decimal places)BIT #$04BNE LAB_29C0 ; branch if FAC1 > (AY) (no decimal places); FAC1 <= (AY)LAB_29B2JSR MultiplyByTen ; multiply by 10DEC numexp ; decrement number exponent countBRA LOOP_MB10 ; go test again (branch always); now we have just the digits to doLAB_29C0; JSR AddPoint5 ; add 0.5 to FAC1 (round FAC1)LAB_29C3; JSR FloatToFixed ; convert FAC1 floating-to-fixedLDX #$01 ; set default digits before dp = 1LDA numexp ; get number exponent countCLC ; clear carry for addADC #$07 ; up to 6 digits before pointBMI LAB_29D8 ; if -ve then 1 digit before dpCMP #$08 ; A>=8 if n>=1E6BCS LAB_29D9 ; branch if >= $08; carry is clearTAX ; copy to ADEX ; take 1 from digit countLDA #$02 ;.set exponent adjustLAB_29D8SEC ; set carry for subtractLAB_29D9SBC #$02 ; -2STA expcnt ;.save exponent adjustSTX numexp ; save digits before dp countTXA ; copy to ABEQ LAB_29E4 ; branch if no digits before dpBPL LAB_29F7 ; branch if digits before dpLAB_29E4LDY Sendl ; get output string indexLDA #'.' ; character "."INY ; increment indexSTA Decss,Y ; save to output stringTXA ;.BEQ LAB_29F5 ;.LDA #'0' ; character "0"INY ; increment indexSTA Decss,Y ; save to output stringLAB_29F5STY Sendl ; save output string indexLAB_29F7LDX #'0' ; holds onto the digit value; Now loop subtracting 100,000 as many times as we can. The value was coerced; to be between 100,000 and 1,000,000. Count the number of times subtraction; can be done successfully.;LAB_29FBPEA CONST_100000JSR LOAD_FAC2 ; load FAC2 with 100,000PLA ; get rid of parameterLDA FP_STATREGBIT #$04 ; Is FAC1 > 100,000 ?BEQ .0005 ; branch if notLDA #FP_SWAP ; subtract is FAC2-FAC1!JSR FPCommandWait;LDA #FP_SUB ; subtract 100,000 from the mantissa.JSR FPCommandWaitINX ; increment the value of the digitBRA LAB_29FB ; try again.0005:TXALDY Sendl ; get output string indexINY ; increment output string indexTXASTA Decss,Y ; save to output stringDEC numexp ; decrement # of characters before the dpBNE LAB_2A3B ; branch if still characters to do; else output the pointLDA #'.' ; character "."INY ; increment output string indexSTA Decss,Y ; save to output stringLAB_2A3BSTY Sendl ; save output string index; We subtracted until the value was < 100,000 so multiply the; remainder upwards to get the next digit.JSR MultiplyByTen ; If not, multiply by 10CPY #27 ; converted (+/- . incl)BCC LAB_29F7; now remove trailing zeroes.RemoveTrailingZerosLDA Decss,Y ; get character from output stringAND #$FF ; mask to a byteDEY ; decrement output string indexCMP #'0' ; compare with "0"BEQ .RemoveTrailingZeros ; loop until non "0" character foundCMP #'.' ; compare with "."BEQ LAB_2A58 ; branch if was dp; restore last characterINY ; increment output string indexLAB_2A58LDA #'+' ; character "+"LDX expcnt ; get exponent countLBEQ LAB_2A8C ; if zero go set null terminator and exit; exponent isn't zero so write exponentBPL LAB_2A68 ; branch if exponent count +veLDA #$00 ; clear ASEC ; set carry for subtractSBC expcnt ; subtract exponent count adjust (convert -ve to +ve)TAX ; copy exponent count to XLDA #'-' ; character "-"; We must keep moving forwards through the string because the acc is storing; two bytes.LAB_2A68PHALDA #'E' ; character "E"STA Decss+1,Y ; save exponent sign to output stringPLASTA Decss+2,Y ; save to output stringTXA ; get exponent count back; do highest exponent digitSTZ SendlLDX #'0'-1 ; one less than "0" characterSEC ; set carry for subtract.0001:INX ; count how many times we can subtract 10,000SBC #10000BCS .0001ADC #10000CPX #'0'BEQ .0005INC SendlPHATXASTA Decss+3,YPLAINY; do the next exponent digit.0005:LDX #'0'-1SEC.0002:INXSBC #1000BCS .0002ADC #1000LSR SendlBCS .00010CPX #'0'BEQ .0006.00010:INC SendlPHATXASTA Decss+3,YPLAINY; and the next.0006:LDX #'0'-1SEC.0003:INXSBC #100BCS .0003ADC #100LSR SendlBCS .00011CPX #'0'BEQ .0007.00011:INC SendlPHATXASTA Decss+3,YPLAINY.0007:LDX #'0'-1SEC.0004:INXSBC #10BCS .0004ADC #10LSR SendlBCS .00012CPX #'0'BEQ .0008.00012:INC SendlPHATXASTA Decss+3,YPLAINY.0008:ADC #'0'STA Decss+3,YLDA #$00 ; set null terminatorSTA Decss+4,Y ; save to output stringRTS ; go set string pointer (AY) and exit (branch always)LAB_2A89STA Decss,Y ; save last character to output string; set null terminator and exitLAB_2A8CLDA #$00 ; set null terminatorSTA Decss+1,Y ; save after last characterLAB_2A91; LDA #<Decssp1 ; set result string low pointer; LDY #>Decssp1 ; set result string high pointerRTSLAB_25FB:LDA #FP_SWAPJSR FPCommandWaitLDY #0TYX.0002:LDA (3,S),YSTA FAC1,XINYINYINXINXCPX #12BNE .0002LDA #FP_FIX2FLTJSR FPCommandWaitFMUL:LDA #FP_MULJMP FPCommandWaitLOAD_FAC2:PHXPHYLDY #0TYX.0002:LDA (7,s),YSTA FAC2,XINYINYINXINXCPX #12BNE .0002PLYPLXRTSFloatToFixed:LDA #FP_FLT2FIXJMP FPCommandWaitAddPoint5:PEA CONST_POINT5JSR LOAD_FAC2PLALDA #FP_ADDJMP FPCommandWaitMultiplyByTen:PEA TEN_AS_FLOATJSR LOAD_FAC2PLALDA #FP_MULJMP FPCommandWaitpublic DivideByTen:PEA TEN_AS_FLOATJSR LOAD_FAC2PLAJSR SwapFACsLDA #FP_DIVJMP FPCommandWaitSwapFACs:LDA #FP_SWAP; Issue a command to the FP unit and wait for it to complete;public FPCommandWait:PHA.0001:LDA FP_STATREG ; get the status registerBIT #$80 ; check for busy bitBNE .0001 ; if busy go backPLA ; to pop accSTA FP_CMDREG ; store the commandRTS; Display the FAC1 as a hex number;public DispFAC1:LDA FAC1_eJSR DispWordLDA FAC1_1JSR DispWordLDA FAC1_2JSR DispWordLDA FAC1_3JSR DispWordLDA FAC1_4JSR DispWordLDA FAC1_5JSR DispWordLDA #' 'JSR OutCharRTS;; 1,000,000 as a floating point number;A_MILLION: ; $F4240dw $0000dw $0000dw $0000dW $0000dw $7A12dw $8013CONST_100000:;186A0dw $0000dw $0000dw $0000dw $0000dw $61A8dw $8010; The constant 999999.4375 as hex; 01.11_1010_0001_0001_1111_1011_1000_00000000000000000000000000MAX_BEFORE_SCI:dw $0000dw $0000dw $0000dw $FB80dw $7A11dw $8013TEN_AS_FLOAT:dw $0000dw $0000dw $0000dw $0000dw $5000dw $8003; 99999.9375; 01.10_0001_1010_0111_1111_1100_000000000000000000000000000000;CONST_9375:dw $0000dw $0000dw $0000dw $FC00dw $61A7dw $8010; 0.5CONST_POINT5:dw $0000dw $0000dw $0000dw $0000dw $4000dw $7FFF; This table is used in converting numbers to ASCII.LAB_2A9ALAB_2A9B = LAB_2A9A+1LAB_2A9C = LAB_2A9B+1; .word $FFFF,$F21F,$494C,$589C,$0000; .word $0000,$0163,$4578,$5D8A,$0000; .word $FFFF,$FFDC,$790D,$903F,$0000; .word $0000,$0003,$8D7E,$A4C6,$8000; .word $FFFF,$FFFF,$A50C,$EF85,$C000; .word $0000,$0000,$0918,$4E72,$A000; .word $FFFF,$FFFF,$FF17,$2B5A,$F000; .word $0000,$0000,$0017,$4876,$E800; .word $FFFF,$FFFF,$FFFD,$ABF4,$1C00; .word $0000,$0000,$0000,$3B9A,$CA00; .word $FFFF,$FFFF,$FFFF,$FF67,$6980; .word $0000,$0000,$0000,$05F5,$E100 ; 100000000; .word $0000,$0000,$0098,$9680 ; 10000000; .word $4240,$000F,$0000,$0000,$0000,$804E ; 1000000.word $86A0,$0001,$0000,$0000,$0000,$804E ; 100000.word $2710,$0000,$0000,$0000,$0000,$804E ; 10000.word $03E8,$0000,$0000,$0000,$0000,$804E ; 1000.word $0064,$0000,$0000,$0000,$0000,$804E ; 100FIXED10:.word $000A,$0000,$0000,$0000,$0000,$804E ; 10.word $0001,$0000,$0000,$0000,$0000,$804E ; 1MEM 16NDX 16
Go to most recent revision | Compare with Previous | Blame | View Log

