OpenCores
URL https://opencores.org/ocsvn/ft816float/ft816float/trunk

Subversion Repositories ft816float

[/] [ft816float/] [trunk/] [software/] [FAC1ToString.asm] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 robfinch
; ============================================================================
2
; FAC1ToString.asm
3
;        __
4
;   \\__/ o\    (C) 2014  Robert Finch, Stratford
5
;    \  __ /    All rights reserved.
6
;     \/_//     robfinch@finitron.ca
7
;       ||
8
;
9
;
10
; This source file is free software: you can redistribute it and/or modify
11
; it under the terms of the GNU Lesser General Public License as published
12
; by the Free Software Foundation, either version 3 of the License, or
13
; (at your option) any later version.
14
;
15
; This source file is distributed in the hope that it will be useful,
16
; but WITHOUT ANY WARRANTY; without even the implied warranty of
17
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
; GNU General Public License for more details.
19
;
20
; You should have received a copy of the GNU General Public License
21
; along with this program.  If not, see .
22
;
23
; ============================================================================
24
;
25
; This code is a heavily modified version of the floating point to string
26
; conversion routine which is a part of Lee Davison's EhBASIC.
27
;
28
Cvaral          = $95           ; current var address low byte
29
Cvarah          = Cvaral+1      ; current var address high byte
30
numexp          = $A8           ; string to float number exponent count
31
expcnt          = $AA           ; string to float exponent count
32
Sendl                   = $BA   ; BASIC pointer temp low byte
33
Sendh                   = $BB   ; BASIC pointer temp low byte
34
 
35
Decss           = $3A0          ; number to decimal string start
36
Decssp1         = Decss+1       ; number to decimal string start
37
FP_ADD          EQU             1
38
FP_SUB          EQU             2
39
FP_MUL          EQU             3
40
FP_DIV          EQU             4
41
FP_FIX2FLT      EQU             5
42
FP_FLT2FIX      EQU             6
43
FP_ABS          EQU             7
44
FP_NEG          EQU             16
45
FP_SWAP         EQU             17
46
FIXED_MUL       EQU             $83
47
FIXED_ADD       EQU             $81
48
FIXED_SUB       EQU             $82
49
;parameter FIXED_DIV = 8'h84;
50
;parameter FIXED_ABS = 8'h87;
51
;parameter FIXED_NEG = 8'h90;
52
FP_CMDREG       EQU             $FEA20E
53
FP_STATREG      EQU             $FEA20E
54
FAC1            EQU             $FEA200
55
FAC1_5          EQU             $FEA200
56
FAC1_4          EQU             $FEA202
57
FAC1_3          EQU             $FEA204
58
FAC1_2          EQU             $FEA206
59
FAC1_1          EQU             $FEA208
60
FAC1_msw        EQU             $FEA208
61
FAC1_e          EQU             $FEA20A
62
FAC2            EQU             $FEA210
63
 
64
        CPU             W65C816S
65
        NDX             16
66
        MEM             16
67
 
68
 
69
public FAC1ToString:
70
 
71
; The first chunk of code determines if the number is positive or negative
72
; and spits out the appropriate sign. Next it takes the absolute value of
73
; the accumulator so following code only has to deal with positive numbers.
74
 
75
        LDY     #$00                    ; set index = 1
76
        LDA     FAC1_msw                ; test FAC1 sign (b15) (Can't use BIT)
77
        BPL     .0002           ; branch if +ve
78
        LDA     #'-'                    ; else character = "-"
79
        STA     Decss,Y         ; save leading character (" " or "-")
80
        LDA     #FP_NEG         ; make the FAC positive
81
        JSR     FPCommandWait
82
        BRA     .0001
83
.0002:
84
        LDA     #$20                    ; character = " " (assume +ve)
85
        STA     Decss,Y
86
.0001:
87
        STY     Sendl                   ; save index
88
 
89
; This little bit of code check for a zero exponent which indicates a
90
; value of zero.
91
 
92
        LDA     FAC1_e          ; get FAC1 exponent
93
        TAX
94
        BNE     LAB_2989                ; branch if FAC1<>0
95
                                        ; exponent was $00 so FAC1 is 0
96
        LDA     #'0'                    ; set character = "0"
97
        BRL     LAB_2A89                ; save last character, [EOT] and exit
98
 
99
; This loop attempts to make small values more significant, so that there are
100
; fewer leading zeros in the value. (The exponent is decremented so that it
101
; corresponds). Because of the potential for extremely small values looping is
102
; limited. The problem is the 16 bit exponent can allow for much smaller
103
; values than an 8 bit exponent would and we don't want to loop for thousands
104
; of iterations in order to display a value that's almost zero.
105
 
106
                                        ; FAC1 is some non zero value
107
LAB_2989
108
        STY     Sendl                   ; save off .Y
109
        LDY #1639                       ; max number of retries
110
        LDA     #$00                    ; clear (number exponent count)
111
        STA numexp
112
LOOP_MBMILLION:
113
        CPX     #$8000                  ; compare FAC1 exponent with $8000 (>1.00000)
114
        BCS     LAB_299A                ; branch if FAC1=>1
115
                                        ; FAC1<1
116
        PEA     A_MILLION               ; multiply FAC * 1,000,000
117
        JSR     LOAD_FAC2               ;
118
        PLA                                     ; get rid of parameter
119
        JSR     FMUL
120
        LDA numexp
121
        SEC
122
        SBC     #6                              ; set number exponent count (-6)
123
        STA numexp
124
        LDA FAC1_e
125
        TAX
126
        DEY
127
        BPL     LOOP_MBMILLION
128
 
129
LAB_299A
130
        LDY     Sendl           ; get back .Y
131
 
132
; These two loops coerce the value of the FAC to be between 100,000 and
133
; 1,000,000. This gives a maximum of six digits before the decimal point
134
; in scientific notation.
135
 
136
; This loop divides by 10 until the value in the FAC is less than 1,000,000
137
;
138
LOOP_DB10:
139
        PEA     MAX_BEFORE_SCI  ; set pointer low byte to 999999.4375 (max before sci note)
140
        JSR     LOAD_FAC2               ; compare FAC1 with (AY)
141
        PLA                                     ; get rid of parameter
142
        LDA FP_CMDREG
143
        BIT     #$08                    ; test equals bit
144
        BNE     LAB_29C3                ; exit if FAC1 = (AY)
145
        BIT     #$04                    ; test greater than bit
146
        BEQ     LOOP_MB10               ; go do *10 if FAC1 < (AY)
147
 
148
LAB_29B9
149
        JSR     DivideByTen             ; divide by 10
150
        INC     numexp                  ; increment number exponent count
151
        BRA     LOOP_DB10               ; go test again (branch always)
152
 
153
; This loop multiplies the value by 10 until it's greater than
154
; 100,000.
155
                                        ; FAC1 < (AY)
156
LOOP_MB10
157
        PEA CONST_9375          ; set pointer to 99999.9375
158
        JSR     LOAD_FAC2               ; compare FAC1 with (AY)
159
        PLA                                     ; get rid of parameter
160
        LDA FP_CMDREG
161
        BIT #$08
162
        BNE     LAB_29B2                ; branch if FAC1 = (AY) (allow decimal places)
163
        BIT #$04
164
        BNE     LAB_29C0                ; branch if FAC1 > (AY) (no decimal places)
165
                                        ; FAC1 <= (AY)
166
LAB_29B2
167
        JSR     MultiplyByTen   ; multiply by 10
168
        DEC     numexp          ; decrement number exponent count
169
        BRA     LOOP_MB10               ; go test again (branch always)
170
 
171
; now we have just the digits to do
172
 
173
LAB_29C0
174
;       JSR     AddPoint5               ; add 0.5 to FAC1 (round FAC1)
175
LAB_29C3
176
;       JSR     FloatToFixed    ; convert FAC1 floating-to-fixed
177
        LDX     #$01                    ; set default digits before dp = 1
178
        LDA     numexp          ; get number exponent count
179
        CLC                             ; clear carry for add
180
        ADC     #$07                    ; up to 6 digits before point
181
        BMI     LAB_29D8                ; if -ve then 1 digit before dp
182
 
183
        CMP     #$08                    ; A>=8 if n>=1E6
184
        BCS     LAB_29D9                ; branch if >= $08
185
 
186
                                        ; carry is clear
187
        TAX                             ; copy to A
188
        DEX                             ; take 1 from digit count
189
        LDA     #$02                    ;.set exponent adjust
190
 
191
LAB_29D8
192
        SEC                             ; set carry for subtract
193
LAB_29D9
194
        SBC     #$02                    ; -2
195
        STA     expcnt          ;.save exponent adjust
196
        STX     numexp          ; save digits before dp count
197
        TXA                             ; copy to A
198
        BEQ     LAB_29E4                ; branch if no digits before dp
199
 
200
        BPL     LAB_29F7                ; branch if digits before dp
201
 
202
LAB_29E4
203
        LDY     Sendl                   ; get output string index
204
        LDA     #'.'                    ; character "."
205
        INY                             ; increment index
206
        STA     Decss,Y         ; save to output string
207
        TXA                             ;.
208
        BEQ     LAB_29F5                ;.
209
 
210
        LDA     #'0'                    ; character "0"
211
        INY                             ; increment index
212
        STA     Decss,Y         ; save to output string
213
LAB_29F5
214
        STY     Sendl                   ; save output string index
215
 
216
LAB_29F7
217
        LDX     #'0'                    ; holds onto the digit value
218
 
219
; Now loop subtracting 100,000 as many times as we can. The value was coerced
220
; to be between 100,000 and 1,000,000. Count the number of times subtraction
221
; can be done successfully.
222
;
223
LAB_29FB
224
        PEA CONST_100000
225
        JSR LOAD_FAC2   ; load FAC2 with 100,000
226
        PLA                             ; get rid of parameter
227
        LDA FP_STATREG
228
        BIT #$04                ; Is FAC1 > 100,000 ?
229
        BEQ     .0005           ; branch if not
230
        LDA #FP_SWAP    ; subtract is FAC2-FAC1!
231
        JSR FPCommandWait;
232
        LDA #FP_SUB             ; subtract 100,000 from the mantissa.
233
        JSR FPCommandWait
234
        INX                             ; increment the value of the digit
235
        BRA     LAB_29FB        ; try again
236
.0005:
237
        TXA
238
        LDY     Sendl                   ; get output string index
239
        INY                             ; increment output string index
240
        TXA
241
        STA     Decss,Y         ; save to output string
242
        DEC     numexp          ; decrement # of characters before the dp
243
        BNE     LAB_2A3B                ; branch if still characters to do
244
                                ; else output the point
245
        LDA     #'.'                    ; character "."
246
        INY                             ; increment output string index
247
        STA     Decss,Y         ; save to output string
248
LAB_2A3B
249
        STY     Sendl           ; save output string index
250
        ; We subtracted until the value was < 100,000 so multiply the
251
        ; remainder upwards to get the next digit.
252
        JSR     MultiplyByTen   ; If not, multiply by 10
253
        CPY #27                 ; converted (+/- . incl)
254
        BCC     LAB_29F7
255
                                        ; now remove trailing zeroes
256
.RemoveTrailingZeros
257
        LDA     Decss,Y         ; get character from output string
258
        AND     #$FF            ; mask to a byte
259
        DEY                             ; decrement output string index
260
        CMP     #'0'                    ; compare with "0"
261
        BEQ     .RemoveTrailingZeros    ; loop until non "0" character found
262
 
263
        CMP     #'.'                    ; compare with "."
264
        BEQ     LAB_2A58                ; branch if was dp
265
 
266
                                        ; restore last character
267
        INY                             ; increment output string index
268
LAB_2A58
269
        LDA     #'+'                    ; character "+"
270
        LDX     expcnt          ; get exponent count
271
        LBEQ    LAB_2A8C                ; if zero go set null terminator and exit
272
 
273
                                        ; exponent isn't zero so write exponent
274
        BPL     LAB_2A68                ; branch if exponent count +ve
275
 
276
        LDA     #$00                    ; clear A
277
        SEC                             ; set carry for subtract
278
        SBC     expcnt          ; subtract exponent count adjust (convert -ve to +ve)
279
        TAX                             ; copy exponent count to X
280
        LDA     #'-'                    ; character "-"
281
 
282
; We must keep moving forwards through the string because the acc is storing
283
; two bytes.
284
 
285
LAB_2A68
286
        PHA
287
        LDA     #'E'                    ; character "E"
288
        STA     Decss+1,Y               ; save exponent sign to output string
289
        PLA
290
        STA     Decss+2,Y               ; save to output string
291
        TXA                             ; get exponent count back
292
 
293
; do highest exponent digit
294
        STZ Sendl
295
        LDX     #'0'-1          ; one less than "0" character
296
        SEC                             ; set carry for subtract
297
.0001:
298
        INX                             ; count how many times we can subtract 10,000
299
        SBC     #10000
300
        BCS .0001
301
        ADC #10000
302
        CPX #'0'
303
        BEQ .0005
304
        INC Sendl
305
        PHA
306
        TXA
307
        STA Decss+3,Y
308
        PLA
309
        INY
310
; do the next exponent digit
311
.0005:
312
        LDX #'0'-1
313
        SEC
314
.0002:
315
        INX
316
        SBC #1000
317
        BCS .0002
318
        ADC #1000
319
        LSR Sendl
320
        BCS .00010
321
        CPX #'0'
322
        BEQ .0006
323
.00010:
324
        INC Sendl
325
        PHA
326
        TXA
327
        STA Decss+3,Y
328
        PLA
329
        INY
330
; and the next
331
.0006:
332
        LDX     #'0'-1
333
        SEC
334
.0003:
335
        INX
336
        SBC #100
337
        BCS .0003
338
        ADC #100
339
        LSR Sendl
340
        BCS .00011
341
        CPX #'0'
342
        BEQ .0007
343
.00011:
344
        INC Sendl
345
        PHA
346
        TXA
347
        STA Decss+3,Y
348
        PLA
349
        INY
350
 
351
.0007:
352
        LDX #'0'-1
353
        SEC
354
.0004:
355
        INX
356
        SBC #10
357
        BCS .0004
358
        ADC #10
359
        LSR Sendl
360
        BCS .00012
361
        CPX #'0'
362
        BEQ .0008
363
.00012:
364
        INC Sendl
365
        PHA
366
        TXA
367
        STA Decss+3,Y
368
        PLA
369
        INY
370
 
371
.0008:
372
        ADC #'0'
373
        STA Decss+3,Y
374
        LDA     #$00                    ; set null terminator
375
        STA     Decss+4,Y               ; save to output string
376
        RTS                                     ; go set string pointer (AY) and exit (branch always)
377
 
378
LAB_2A89
379
        STA     Decss,Y         ; save last character to output string
380
                                        ; set null terminator and exit
381
LAB_2A8C
382
        LDA     #$00                    ; set null terminator
383
        STA     Decss+1,Y               ; save after last character
384
 
385
LAB_2A91
386
;       LDA     #
387
;       LDY     #>Decssp1               ; set result string high pointer
388
        RTS
389
 
390
LAB_25FB:
391
        LDA             #FP_SWAP
392
        JSR             FPCommandWait
393
        LDY             #0
394
        TYX
395
.0002:
396
        LDA             (3,S),Y
397
        STA             FAC1,X
398
        INY
399
        INY
400
        INX
401
        INX
402
        CPX             #12
403
        BNE             .0002
404
        LDA             #FP_FIX2FLT
405
        JSR             FPCommandWait
406
FMUL:
407
        LDA             #FP_MUL
408
        JMP             FPCommandWait
409
 
410
LOAD_FAC2:
411
        PHX
412
        PHY
413
        LDY             #0
414
        TYX
415
.0002:
416
        LDA             (7,s),Y
417
        STA             FAC2,X
418
        INY
419
        INY
420
        INX
421
        INX
422
        CPX             #12
423
        BNE             .0002
424
        PLY
425
        PLX
426
        RTS
427
 
428
FloatToFixed:
429
        LDA             #FP_FLT2FIX
430
        JMP             FPCommandWait
431
 
432
AddPoint5:
433
        PEA             CONST_POINT5
434
        JSR             LOAD_FAC2
435
        PLA
436
        LDA             #FP_ADD
437
        JMP             FPCommandWait
438
 
439
MultiplyByTen:
440
        PEA             TEN_AS_FLOAT
441
        JSR             LOAD_FAC2
442
        PLA
443
        LDA             #FP_MUL
444
        JMP             FPCommandWait
445
 
446
public DivideByTen:
447
        PEA             TEN_AS_FLOAT
448
        JSR             LOAD_FAC2
449
        PLA
450
        JSR             SwapFACs
451
        LDA             #FP_DIV
452
        JMP             FPCommandWait
453
 
454
SwapFACs:
455
        LDA             #FP_SWAP
456
 
457
; Issue a command to the FP unit and wait for it to complete
458
;
459
public FPCommandWait:
460
        PHA
461
.0001:
462
        LDA             FP_STATREG      ; get the status register
463
        BIT             #$80            ; check for busy bit
464
        BNE             .0001           ; if busy go back
465
        PLA                                     ; to pop acc
466
        STA             FP_CMDREG       ; store the command
467
        RTS
468
 
469
; Display the FAC1 as a hex number
470
;
471
public DispFAC1:
472
        LDA FAC1_e
473
        JSR DispWord
474
        LDA     FAC1_1
475
        JSR     DispWord
476
        LDA FAC1_2
477
        JSR     DispWord
478
        LDA FAC1_3
479
        JSR DispWord
480
        LDA FAC1_4
481
        JSR DispWord
482
        LDA FAC1_5
483
        JSR DispWord
484
        LDA #' '
485
        JSR OutChar
486
        RTS
487
;
488
; 1,000,000 as a floating point number
489
;
490
A_MILLION:      ; $F4240
491
        dw              $0000
492
        dw              $0000
493
        dw              $0000
494
        dW              $0000
495
        dw              $7A12
496
        dw              $8013
497
 
498
CONST_100000:
499
        ;186A0
500
        dw              $0000
501
        dw              $0000
502
        dw              $0000
503
        dw              $0000
504
        dw              $61A8
505
        dw              $8010
506
; The constant 999999.4375 as hex
507
; 01.11_1010_0001_0001_1111_1011_1000_00000000000000000000000000
508
MAX_BEFORE_SCI:
509
        dw  $0000
510
        dw  $0000
511
        dw      $0000
512
        dw      $FB80
513
        dw      $7A11
514
        dw      $8013
515
 
516
TEN_AS_FLOAT:
517
        dw      $0000
518
        dw      $0000
519
        dw      $0000
520
        dw      $0000
521
        dw      $5000
522
        dw      $8003
523
 
524
; 99999.9375
525
; 01.10_0001_1010_0111_1111_1100_000000000000000000000000000000
526
;
527
CONST_9375:
528
        dw      $0000
529
        dw      $0000
530
        dw      $0000
531
        dw      $FC00
532
        dw      $61A7
533
        dw      $8010
534
 
535
; 0.5
536
CONST_POINT5:
537
        dw      $0000
538
        dw      $0000
539
        dw      $0000
540
        dw      $0000
541
        dw      $4000
542
        dw      $7FFF
543
 
544
; This table is used in converting numbers to ASCII.
545
 
546
LAB_2A9A
547
LAB_2A9B = LAB_2A9A+1
548
LAB_2A9C = LAB_2A9B+1
549
;       .word   $FFFF,$F21F,$494C,$589C,$0000
550
;       .word   $0000,$0163,$4578,$5D8A,$0000
551
;       .word   $FFFF,$FFDC,$790D,$903F,$0000
552
;       .word   $0000,$0003,$8D7E,$A4C6,$8000
553
;       .word   $FFFF,$FFFF,$A50C,$EF85,$C000
554
;       .word   $0000,$0000,$0918,$4E72,$A000
555
;       .word   $FFFF,$FFFF,$FF17,$2B5A,$F000
556
;       .word   $0000,$0000,$0017,$4876,$E800
557
;       .word   $FFFF,$FFFF,$FFFD,$ABF4,$1C00
558
;       .word   $0000,$0000,$0000,$3B9A,$CA00
559
;       .word   $FFFF,$FFFF,$FFFF,$FF67,$6980
560
;       .word   $0000,$0000,$0000,$05F5,$E100           ; 100000000
561
;       .word   $0000,$0000,$0098,$9680         ; 10000000
562
;       .word   $4240,$000F,$0000,$0000,$0000,$804E             ; 1000000
563
        .word   $86A0,$0001,$0000,$0000,$0000,$804E             ; 100000
564
        .word   $2710,$0000,$0000,$0000,$0000,$804E             ; 10000
565
        .word   $03E8,$0000,$0000,$0000,$0000,$804E             ; 1000
566
        .word   $0064,$0000,$0000,$0000,$0000,$804E             ; 100
567
FIXED10:
568
        .word   $000A,$0000,$0000,$0000,$0000,$804E             ; 10
569
        .word   $0001,$0000,$0000,$0000,$0000,$804E             ; 1
570
 
571
                 MEM    16
572
                 NDX    16

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.