1 |
87 |
robfinch |
; ============================================================================
|
2 |
|
|
; __
|
3 |
|
|
; \\__/ o\ (C) 2022 Robert Finch, Waterloo
|
4 |
|
|
; \ __ / All rights reserved.
|
5 |
|
|
; \/_// robfinch@opencores.org
|
6 |
|
|
; ||
|
7 |
|
|
;
|
8 |
|
|
;
|
9 |
|
|
; BSD 3-Clause License
|
10 |
|
|
; Redistribution and use in source and binary forms, with or without
|
11 |
|
|
; modification, are permitted provided that the following conditions are met:
|
12 |
|
|
;
|
13 |
|
|
; 1. Redistributions of source code must retain the above copyright notice, this
|
14 |
|
|
; list of conditions and the following disclaimer.
|
15 |
|
|
;
|
16 |
|
|
; 2. Redistributions in binary form must reproduce the above copyright notice,
|
17 |
|
|
; this list of conditions and the following disclaimer in the documentation
|
18 |
|
|
; and/or other materials provided with the distribution.
|
19 |
|
|
;
|
20 |
|
|
; 3. Neither the name of the copyright holder nor the names of its
|
21 |
|
|
; contributors may be used to endorse or promote products derived from
|
22 |
|
|
; this software without specific prior written permission.
|
23 |
|
|
;
|
24 |
|
|
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
25 |
|
|
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
26 |
|
|
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
27 |
|
|
; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
28 |
|
|
; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
29 |
|
|
; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
30 |
|
|
; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
31 |
|
|
; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
32 |
|
|
; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
33 |
|
|
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34 |
|
|
;
|
35 |
|
|
; ============================================================================
|
36 |
|
|
;
|
37 |
|
|
;==============================================================================
|
38 |
|
|
; Decimal-Floating point to string conversion routine.
|
39 |
|
|
;==============================================================================
|
40 |
|
|
|
41 |
|
|
; These variables may need to be relocated depending on the system.
|
42 |
|
|
|
43 |
|
|
fpBuf equ $402C0
|
44 |
|
|
_exp equ $40500
|
45 |
|
|
_digit equ $40504
|
46 |
|
|
_width equ $40508
|
47 |
|
|
_E equ $4050C
|
48 |
|
|
_digits_before_decpt equ $40510
|
49 |
|
|
_precision equ $40514
|
50 |
|
|
_fpBuf equ $40520 ; to $40560
|
51 |
|
|
_fpWork equ $40600
|
52 |
|
|
|
53 |
|
|
code
|
54 |
|
|
;==============================================================================
|
55 |
|
|
; Decimal-Floating point to string conversion routine.
|
56 |
|
|
;
|
57 |
|
|
; Modifies
|
58 |
|
|
; _fpWork work area
|
59 |
|
|
; Register Usage:
|
60 |
|
|
; fp0 = input decimal-float to convert
|
61 |
|
|
; fp1 = constant holder, 1.0, 10.0
|
62 |
|
|
; fp2 = 1.0e value for conversion
|
63 |
|
|
; fp3 = holds digit value during significand conversion
|
64 |
|
|
; a0 = pointer to string buffer, updated to point to NULL at end of string
|
65 |
|
|
; a1 = pointer to "Nan" or "Inf" message string
|
66 |
|
|
; d0 = temporary
|
67 |
|
|
; d1 = digit value during exponent, significand conversion
|
68 |
|
|
; d6 = exponent
|
69 |
|
|
;==============================================================================
|
70 |
|
|
align 4
|
71 |
|
|
_dfOne dc.l $25ff0000,$00000000,$00000000
|
72 |
|
|
_dfTen dc.l $2600C000,$00000000,$00000000
|
73 |
|
|
_dfMil dc.l $2606DDFA,$1C000000,$00000000
|
74 |
|
|
|
75 |
|
|
_msgNan dc.b "NaN",0
|
76 |
|
|
_msgInf dc.b "Inf",0
|
77 |
|
|
even
|
78 |
|
|
|
79 |
|
|
;------------------------------------------------------------------------------
|
80 |
|
|
; Check for the special Nan and infinity values. Output the appropriate string.
|
81 |
|
|
;
|
82 |
|
|
; Modifies
|
83 |
|
|
; _fpWork area
|
84 |
|
|
; d0,a1,a0
|
85 |
|
|
; Parameters:
|
86 |
|
|
; fp0 = dbl
|
87 |
|
|
;------------------------------------------------------------------------------
|
88 |
|
|
|
89 |
|
|
_CheckNan:
|
90 |
|
|
fmove.p fp0,_fpWork
|
91 |
|
|
move.b _fpWork,d0 ; get sign+combo
|
92 |
|
|
andi.b #$7C,d0 ; mask for combo bits
|
93 |
|
|
cmpi.b #$7C,d0 ; is it the Nan combo?
|
94 |
|
|
bne .notNan
|
95 |
|
|
lea _msgNan,a1 ; output "Nan"
|
96 |
|
|
bra .outStr
|
97 |
|
|
.notNan
|
98 |
|
|
cmpi.b #$78,d0 ; is it infinity combo?
|
99 |
|
|
bne .notInf
|
100 |
|
|
lea _msgInf,a1
|
101 |
|
|
.outStr
|
102 |
|
|
move.b (a1)+,(a0)+ ; output "Inf"
|
103 |
|
|
move.b (a1)+,(a0)+
|
104 |
|
|
move.b (a1)+,(a0)+
|
105 |
|
|
clr.b (a0)
|
106 |
|
|
.twoup
|
107 |
|
|
addq #4,sp ; pop return address for two up return
|
108 |
|
|
.notInf
|
109 |
|
|
rts
|
110 |
|
|
|
111 |
|
|
;------------------------------------------------------------------------------
|
112 |
|
|
; Check for a zero value. Output a single "0" if zero,
|
113 |
|
|
;
|
114 |
|
|
; Modifies:
|
115 |
|
|
; a0
|
116 |
|
|
; Parameters:
|
117 |
|
|
; fp0 = dbl
|
118 |
|
|
;------------------------------------------------------------------------------
|
119 |
|
|
|
120 |
|
|
_CheckZero:
|
121 |
|
|
ftst fp0 ; check if number is zero
|
122 |
|
|
fbne .0003
|
123 |
|
|
move.b #'0',(a0)+ ; if zero output "0"
|
124 |
|
|
clr.b (a0)
|
125 |
|
|
addq #4,sp ; pop return address for two up return
|
126 |
|
|
.0003
|
127 |
|
|
rts
|
128 |
|
|
|
129 |
|
|
;------------------------------------------------------------------------------
|
130 |
|
|
; Check for a negative number. This includes Nans and Infinities. Output a "-"
|
131 |
|
|
; if negative.
|
132 |
|
|
;
|
133 |
|
|
; Modifies
|
134 |
|
|
; a0
|
135 |
|
|
; Parameters:
|
136 |
|
|
; fp0 = dbl
|
137 |
|
|
;------------------------------------------------------------------------------
|
138 |
|
|
|
139 |
|
|
_CheckNegative:
|
140 |
|
|
ftst fp0 ; is number negative?
|
141 |
|
|
fbge .0002
|
142 |
|
|
move.b #'-',(a0)+ ; yes, output '-'
|
143 |
|
|
fneg fp0 ; make fp0 positive
|
144 |
|
|
.0002
|
145 |
|
|
rts
|
146 |
|
|
|
147 |
|
|
;------------------------------------------------------------------------------
|
148 |
|
|
; Make the input value larger so that digits may appear before the decimal
|
149 |
|
|
; point.
|
150 |
|
|
;
|
151 |
|
|
; Modifies:
|
152 |
|
|
; fp0,fp1,d6
|
153 |
|
|
; Parameters:
|
154 |
|
|
; fp0 = dbl
|
155 |
|
|
;------------------------------------------------------------------------------
|
156 |
|
|
|
157 |
|
|
; if (dbl < 1.0) {
|
158 |
|
|
; while (dbl < 1.0) {
|
159 |
|
|
; dbl *= 1000000.0;
|
160 |
|
|
; exp -= 6;
|
161 |
|
|
; }
|
162 |
|
|
; }
|
163 |
|
|
|
164 |
|
|
_MakeBig:
|
165 |
|
|
fmove.w #1,fp1
|
166 |
|
|
.0002
|
167 |
|
|
fcmp fp1,fp0 ; is fp0 > 1?
|
168 |
|
|
fbge .0001 ; yes, return
|
169 |
|
|
fscale.l #6,fp0 ; multiply fp0 by a million
|
170 |
|
|
subi.w #6,d6 ; decrement exponent by six
|
171 |
|
|
bra .0002 ; keep trying until number is > 1
|
172 |
|
|
.0001
|
173 |
|
|
fmove.p fp0,_fpWork+24 ; debugging
|
174 |
|
|
rts
|
175 |
|
|
|
176 |
|
|
;------------------------------------------------------------------------------
|
177 |
|
|
; Create a number dbl2 on the same order of magnitude as dbl, but
|
178 |
|
|
; less than dbl. The number will be 1.0e
|
179 |
|
|
;
|
180 |
|
|
; Modifies:
|
181 |
|
|
; d6,fp2
|
182 |
|
|
; Parameters:
|
183 |
|
|
; fp0 = dbl
|
184 |
|
|
;------------------------------------------------------------------------------
|
185 |
|
|
|
186 |
|
|
; // The following is similar to using log10() and pow() functions.
|
187 |
|
|
; // Now dbl is >= 1.0
|
188 |
|
|
; // Create a number dbl2 on the same order of magnitude as dbl, but
|
189 |
|
|
; // less than dbl.
|
190 |
|
|
; dbl2 = 1.0;
|
191 |
|
|
; dbla = dbl2;
|
192 |
|
|
; if (dbl > dbl2) { // dbl > 1.0 ?
|
193 |
|
|
; while (dbl2 <= dbl) {
|
194 |
|
|
; dbla = dbl2;
|
195 |
|
|
; dbl2 *= 10.0; // increase power of 10
|
196 |
|
|
; exp++;
|
197 |
|
|
; }
|
198 |
|
|
; // The above loop goes one too far, we want the last value less
|
199 |
|
|
; // than dbl.
|
200 |
|
|
; dbl2 = dbla;
|
201 |
|
|
; exp--;
|
202 |
|
|
; }
|
203 |
|
|
|
204 |
|
|
_LessThanDbl:
|
205 |
|
|
fmove.w #1,fp2 ; setup fp2 = 1
|
206 |
|
|
fcmp fp2,fp0 ; if (dbl > dbl2)
|
207 |
|
|
fble .0004
|
208 |
|
|
.0006
|
209 |
|
|
fcmp fp0,fp2 ; while (dbl2 <= dbl)
|
210 |
|
|
fbgt .0005
|
211 |
|
|
fscale.w #1,fp2 ; dbl2 *= 10 (increase exponent by one)
|
212 |
|
|
addi.w #1,d6 ; exp++
|
213 |
|
|
bra .0006
|
214 |
|
|
.0005
|
215 |
|
|
fscale.l #-1,fp2 ; dbl2 /= 10 (decrease exponent by one)
|
216 |
|
|
subi.w #1,d6 ; exp--;
|
217 |
|
|
.0004
|
218 |
|
|
fmove.p fp0,_fpWork ; debugging
|
219 |
|
|
fmove.p fp2,_fpWork+12
|
220 |
|
|
rts
|
221 |
|
|
|
222 |
|
|
;------------------------------------------------------------------------------
|
223 |
|
|
; Compute the number of digits before the decimal point.
|
224 |
|
|
;
|
225 |
|
|
; Modifies:
|
226 |
|
|
; d0,d6,_digits_before_decpt
|
227 |
|
|
; Parameters:
|
228 |
|
|
; d6 = exponent
|
229 |
|
|
;------------------------------------------------------------------------------
|
230 |
|
|
|
231 |
|
|
; if (exp >= 0 && exp < 6) {
|
232 |
|
|
; digits_before_decpt = exp+1;
|
233 |
|
|
; exp = 0;
|
234 |
|
|
; }
|
235 |
|
|
; else if (exp >= -6)
|
236 |
|
|
; digits_before_decpt = 1;
|
237 |
|
|
; else
|
238 |
|
|
; digits_before_decpt = -1;
|
239 |
|
|
|
240 |
|
|
_ComputeDigitsBeforeDecpt:
|
241 |
|
|
tst.w d6
|
242 |
|
|
bmi .0007
|
243 |
|
|
cmpi.w #6,d6
|
244 |
|
|
bge .0007
|
245 |
|
|
move.w d6,d0
|
246 |
|
|
addi.w #1,d0
|
247 |
|
|
move.w d0,_digits_before_decpt
|
248 |
|
|
clr.w d6
|
249 |
|
|
rts
|
250 |
|
|
.0007
|
251 |
|
|
cmpi.w #-6,d6
|
252 |
|
|
blt .0009
|
253 |
|
|
move.w #1,_digits_before_decpt
|
254 |
|
|
rts
|
255 |
|
|
.0009
|
256 |
|
|
move.w #-1,_digits_before_decpt
|
257 |
|
|
rts
|
258 |
|
|
|
259 |
|
|
;------------------------------------------------------------------------------
|
260 |
|
|
; Spit out a leading zero before the decimal point for a small number.
|
261 |
|
|
;
|
262 |
|
|
; Parameters:
|
263 |
|
|
; d6 = exponent
|
264 |
|
|
;------------------------------------------------------------------------------
|
265 |
|
|
|
266 |
|
|
; if (exp < -6) {
|
267 |
|
|
; buf[ndx] = '0';
|
268 |
|
|
; ndx++;
|
269 |
|
|
; buf[ndx] = '.';
|
270 |
|
|
; ndx++;
|
271 |
|
|
; }
|
272 |
|
|
|
273 |
|
|
_LeadingZero:
|
274 |
|
|
cmpi.w #-6,d6
|
275 |
|
|
bge .0010
|
276 |
|
|
move.b #'0',(a0)+
|
277 |
|
|
move.b #'.',(a0)+
|
278 |
|
|
.0010
|
279 |
|
|
rts
|
280 |
|
|
|
281 |
|
|
;------------------------------------------------------------------------------
|
282 |
|
|
; Extract the digits of the significand.
|
283 |
|
|
;
|
284 |
|
|
; Modifies:
|
285 |
|
|
; _precision variable
|
286 |
|
|
; Register Usage
|
287 |
|
|
; d1 = digit
|
288 |
|
|
; fp0 = dbl
|
289 |
|
|
; fp2 = dbl2
|
290 |
|
|
; fp3 = digit as decimal float
|
291 |
|
|
; fp7 = dbla
|
292 |
|
|
; Parameters:
|
293 |
|
|
; fp0
|
294 |
|
|
;------------------------------------------------------------------------------
|
295 |
|
|
|
296 |
|
|
; // Now loop processing one digit at a time.
|
297 |
|
|
; for (nn = 0; nn < 25 && precision > 0; nn++) {
|
298 |
|
|
; digit = 0;
|
299 |
|
|
; dbla = dbl;
|
300 |
|
|
; // dbl is on the same order of magnitude as dbl2 so
|
301 |
|
|
; // a repeated subtract can be used to find the digit.
|
302 |
|
|
; while (dbl >= dbl2) {
|
303 |
|
|
; dbl -= dbl2;
|
304 |
|
|
; digit++;
|
305 |
|
|
; }
|
306 |
|
|
; buf[ndx] = digit + '0';
|
307 |
|
|
; // Now go back and perform just a single subtract and
|
308 |
|
|
; // a multiply to find out how much to reduce dbl by.
|
309 |
|
|
; // This should improve the accuracy
|
310 |
|
|
; if (digit > 2)
|
311 |
|
|
; dbl = dbla - dbl2 * digit;
|
312 |
|
|
; ndx++;
|
313 |
|
|
; digits_before_decpt--;
|
314 |
|
|
; if (digits_before_decpt==0) {
|
315 |
|
|
; buf[ndx] = '.';
|
316 |
|
|
; ndx++;
|
317 |
|
|
; }
|
318 |
|
|
; else if (digits_before_decpt < 0)
|
319 |
|
|
; precision--;
|
320 |
|
|
; // Shift the next digit to be tested into position.
|
321 |
|
|
; dbl *= 10.0;
|
322 |
|
|
; }
|
323 |
|
|
|
324 |
|
|
_SpitOutDigits:
|
325 |
|
|
move.w #24,d0 ; d0 = nn
|
326 |
|
|
fmove.l #10,fp1 ; fp1 = 10.0
|
327 |
|
|
.0017
|
328 |
|
|
tst.l _precision
|
329 |
|
|
ble .0011
|
330 |
|
|
moveq #0,d1 ; digit = 0
|
331 |
|
|
fmove fp0,fp7 ; dbla = dbl
|
332 |
|
|
.0013
|
333 |
|
|
fcmp fp2,fp0
|
334 |
|
|
fblt .0012
|
335 |
|
|
fsub fp2,fp0 ; dbl -= dbl2
|
336 |
|
|
addi.b #1,d1 ; digit++
|
337 |
|
|
bra .0013
|
338 |
|
|
.0012
|
339 |
|
|
addi.b #'0',d1 ; convert digit to ascii
|
340 |
|
|
move.b d1,(a0)+ ; and store
|
341 |
|
|
subi.b #'0',d1 ; d1 = binary digit again
|
342 |
|
|
.0014
|
343 |
|
|
subi.w #1,_digits_before_decpt
|
344 |
|
|
bne .0015
|
345 |
|
|
move.b #'.',(a0)+
|
346 |
|
|
.0015
|
347 |
|
|
tst.w _digits_before_decpt
|
348 |
|
|
bge .0016
|
349 |
|
|
subi.l #1,_precision
|
350 |
|
|
.0016
|
351 |
|
|
fscale.l #-1,fp2 ; dbl *= 10.0
|
352 |
|
|
dbra d0,.0017
|
353 |
|
|
.0011
|
354 |
|
|
rts
|
355 |
|
|
|
356 |
|
|
;------------------------------------------------------------------------------
|
357 |
|
|
; If the number ends in a decimal point, trim off the point.
|
358 |
|
|
;
|
359 |
|
|
; Registers Modified:
|
360 |
|
|
; none
|
361 |
|
|
; Parameters:
|
362 |
|
|
; a0 = pointer to end of number
|
363 |
|
|
; Returns:
|
364 |
|
|
; a0 = updated to point just past last digit.
|
365 |
|
|
;------------------------------------------------------------------------------
|
366 |
|
|
|
367 |
|
|
_TrimTrailingPoint:
|
368 |
|
|
cmpi.b #'.',-1(a0)
|
369 |
|
|
bne .0001
|
370 |
|
|
clr.b -(a0)
|
371 |
|
|
rts
|
372 |
|
|
.0001
|
373 |
|
|
cmpi.b #'.',(a0)
|
374 |
|
|
bne .0002
|
375 |
|
|
cmpi.b #0,1(a0)
|
376 |
|
|
bne .0002
|
377 |
|
|
clr.b (a0)
|
378 |
|
|
subq #1,a0
|
379 |
|
|
.0002
|
380 |
|
|
rts
|
381 |
|
|
|
382 |
|
|
;------------------------------------------------------------------------------
|
383 |
|
|
; If the number ends in .0 get rid of the .0
|
384 |
|
|
;
|
385 |
|
|
; Registers Modified:
|
386 |
|
|
; none
|
387 |
|
|
; Parameters:
|
388 |
|
|
; a0 = pointer to last digits of number
|
389 |
|
|
; Returns:
|
390 |
|
|
; a0 = updated to point just past last digit.
|
391 |
|
|
;------------------------------------------------------------------------------
|
392 |
|
|
|
393 |
|
|
_TrimDotZero:
|
394 |
|
|
tst.b (a0)
|
395 |
|
|
bne .0004
|
396 |
|
|
cmpi.b #'0',-1(a0)
|
397 |
|
|
bne .0004
|
398 |
|
|
cmpi.b #'.',-2(a0)
|
399 |
|
|
bne .0004
|
400 |
|
|
clr.b -2(a0)
|
401 |
|
|
subq #2,a0
|
402 |
|
|
.0004
|
403 |
|
|
rts
|
404 |
|
|
|
405 |
|
|
;------------------------------------------------------------------------------
|
406 |
|
|
; Trim trailing zeros from the number. Generally there is no need to display
|
407 |
|
|
; trailing zeros.
|
408 |
|
|
; Turns a number like 652.000000000000000000000 into 650.0
|
409 |
|
|
;
|
410 |
|
|
; Registers Modified:
|
411 |
|
|
; none
|
412 |
|
|
; Parameters:
|
413 |
|
|
; a0 = pointer to last digits of number
|
414 |
|
|
; Returns:
|
415 |
|
|
; a0 = updated to point just past last digit.
|
416 |
|
|
;------------------------------------------------------------------------------
|
417 |
|
|
|
418 |
|
|
; // Trim trailing zeros from the number
|
419 |
|
|
; do {
|
420 |
|
|
; ndx--;
|
421 |
|
|
; } while(buf[ndx]=='0');
|
422 |
|
|
; ndx++;
|
423 |
|
|
|
424 |
|
|
_TrimTrailingZeros:
|
425 |
|
|
.0018
|
426 |
|
|
cmpi.b #'0',-(a0) ; if the last digit was a zero, backup
|
427 |
|
|
beq .0018
|
428 |
|
|
addq #1,a0 ; now advance by one
|
429 |
|
|
move.b #0,(a0) ; NULL terminate string
|
430 |
|
|
rts
|
431 |
|
|
|
432 |
|
|
;------------------------------------------------------------------------------
|
433 |
|
|
; Output 'e+' or 'e-'
|
434 |
|
|
;
|
435 |
|
|
; Registers Modified:
|
436 |
|
|
; d6.w (if negative)
|
437 |
|
|
; Parameters:
|
438 |
|
|
; a0 = pointer to last digits of number
|
439 |
|
|
; Returns:
|
440 |
|
|
; a0 = updated to point just past '+' or '-'.
|
441 |
|
|
;------------------------------------------------------------------------------
|
442 |
|
|
|
443 |
|
|
; // Spit out +/-E
|
444 |
|
|
; buf[ndx] = E;
|
445 |
|
|
; ndx++;
|
446 |
|
|
; if (exp < 0) {
|
447 |
|
|
; buf[ndx]='-';
|
448 |
|
|
; ndx++;
|
449 |
|
|
; exp = -exp;
|
450 |
|
|
; }
|
451 |
|
|
; else {
|
452 |
|
|
; buf[ndx]='+';
|
453 |
|
|
; ndx++;
|
454 |
|
|
; }
|
455 |
|
|
|
456 |
|
|
_SpitOutE:
|
457 |
|
|
move.b _E,(a0)+
|
458 |
|
|
tst.w d6
|
459 |
|
|
bge .0021
|
460 |
|
|
move.b #'-',(a0)+
|
461 |
|
|
neg.w d6
|
462 |
|
|
bra .0022
|
463 |
|
|
.0021
|
464 |
|
|
move.b #'+',(a0)+
|
465 |
|
|
.0022
|
466 |
|
|
rts
|
467 |
|
|
|
468 |
|
|
;------------------------------------------------------------------------------
|
469 |
|
|
; Extract a single digit of the exponent. Extract works from the leftmost digit
|
470 |
|
|
; to the rightmost.
|
471 |
|
|
;
|
472 |
|
|
; Register Usage
|
473 |
|
|
; d2 = history of zeros
|
474 |
|
|
; d3 = digit
|
475 |
|
|
; Modifies
|
476 |
|
|
; d2,d3,d6,a0
|
477 |
|
|
; Parameter
|
478 |
|
|
; d1.w = power of ten
|
479 |
|
|
; d6.w = exponent
|
480 |
|
|
;------------------------------------------------------------------------------
|
481 |
|
|
|
482 |
|
|
_ExtExpDigit:
|
483 |
|
|
ext.l d6 ; make d6 a long
|
484 |
|
|
divu d1,d6 ; divide by power of ten
|
485 |
|
|
move.b d6,d3 ; d3 = quotient (0 to 9)
|
486 |
|
|
swap d6 ; d6 = remainder, setup for next digit
|
487 |
|
|
or.b d3,d2
|
488 |
|
|
tst.b d3
|
489 |
|
|
bne .0003
|
490 |
|
|
tst.b d2
|
491 |
|
|
beq .0004
|
492 |
|
|
.0003
|
493 |
|
|
addi.b #'0',d3 ; convert to ascii
|
494 |
|
|
move.b d3,(a0)+
|
495 |
|
|
.0004
|
496 |
|
|
rts
|
497 |
|
|
|
498 |
|
|
;------------------------------------------------------------------------------
|
499 |
|
|
; Extract all the digits of the exponent.
|
500 |
|
|
;
|
501 |
|
|
; Register Usage
|
502 |
|
|
; d1 = power of 10
|
503 |
|
|
; d2 = history of zeros
|
504 |
|
|
; Parameters
|
505 |
|
|
; a0 = pointer to string buffer
|
506 |
|
|
; d6 = exponent
|
507 |
|
|
;------------------------------------------------------------------------------
|
508 |
|
|
|
509 |
|
|
; // If the number is times 10^0 don't output the exponent
|
510 |
|
|
; if (exp==0) {
|
511 |
|
|
; buf[ndx]='\0';
|
512 |
|
|
; goto prt;
|
513 |
|
|
; }
|
514 |
|
|
|
515 |
|
|
_ExtExpDigits:
|
516 |
|
|
tst.w d6 ; is exponent zero?
|
517 |
|
|
beq .0002
|
518 |
|
|
bsr _SpitOutE ; exponent is non-zero e+
|
519 |
|
|
clr.b d2 ; d2 = history of zeros
|
520 |
|
|
move.w #1000,d1
|
521 |
|
|
bsr _ExtExpDigit
|
522 |
|
|
move.w #100,d1
|
523 |
|
|
bsr _ExtExpDigit
|
524 |
|
|
move.w #10,d1
|
525 |
|
|
bsr _ExtExpDigit
|
526 |
|
|
move.w #1,d1
|
527 |
|
|
bsr _ExtExpDigit
|
528 |
|
|
.0002:
|
529 |
|
|
move.b #0,(a0) ; NULL terminate string
|
530 |
|
|
rts ; and return
|
531 |
|
|
|
532 |
|
|
;------------------------------------------------------------------------------
|
533 |
|
|
; Pad the left side of the output string.
|
534 |
|
|
;
|
535 |
|
|
; Modifies:
|
536 |
|
|
; d0,d1,d2,d3
|
537 |
|
|
;------------------------------------------------------------------------------
|
538 |
|
|
|
539 |
|
|
; // pad left
|
540 |
|
|
; if (width > 0) {
|
541 |
|
|
; if (ndx < width) {
|
542 |
|
|
; for (nn = 39; nn >= width-ndx; nn--)
|
543 |
|
|
; buf[nn] = buf[nn-(width-ndx)];
|
544 |
|
|
; for (; nn >= 0; nn--)
|
545 |
|
|
; buf[nn] = ' ';
|
546 |
|
|
; }
|
547 |
|
|
; }
|
548 |
|
|
|
549 |
|
|
_PadLeft:
|
550 |
|
|
tst.b _width
|
551 |
|
|
ble .0041
|
552 |
|
|
move.l a0,d0
|
553 |
|
|
sub.l #_fpBuf,d0 ; d0 = ndx
|
554 |
|
|
cmp.b _width,d0
|
555 |
|
|
bge .0041
|
556 |
|
|
move.w #49,d1 ; d1 = nn
|
557 |
|
|
.0040
|
558 |
|
|
move.b _width,d2
|
559 |
|
|
ext.w d2
|
560 |
|
|
sub.w d0,d2 ; d2 = width-ndx
|
561 |
|
|
cmp.w d2,d1
|
562 |
|
|
blt .0039
|
563 |
|
|
move.w d1,d3 ; d3 = nn
|
564 |
|
|
sub.w d2,d3 ; d3 = nn-(width-ndx)
|
565 |
|
|
move.b (a0,d3.w),(a0,d1.w)
|
566 |
|
|
subi.w #1,d1
|
567 |
|
|
bra .0040
|
568 |
|
|
.0039
|
569 |
|
|
tst.w d1
|
570 |
|
|
bmi .0041
|
571 |
|
|
move.b #' ',(a0,d1.w)
|
572 |
|
|
subi.w #1,d1
|
573 |
|
|
bra .0039
|
574 |
|
|
.0041
|
575 |
|
|
rts
|
576 |
|
|
|
577 |
|
|
;------------------------------------------------------------------------------
|
578 |
|
|
; Pad the right side of the output string.
|
579 |
|
|
;
|
580 |
|
|
; Modifies:
|
581 |
|
|
; d0
|
582 |
|
|
; Returns:
|
583 |
|
|
; d0 = length of string
|
584 |
|
|
;------------------------------------------------------------------------------
|
585 |
|
|
|
586 |
|
|
; // pad right
|
587 |
|
|
; if (width < 0) {
|
588 |
|
|
; width = -width;
|
589 |
|
|
; while (ndx < width) {
|
590 |
|
|
; buf[ndx]=' ';
|
591 |
|
|
; ndx++;
|
592 |
|
|
; }
|
593 |
|
|
; buf[ndx]='\0';
|
594 |
|
|
; }
|
595 |
|
|
; return (ndx);
|
596 |
|
|
|
597 |
|
|
_PadRight:
|
598 |
|
|
tst.b _width
|
599 |
|
|
bpl .0042
|
600 |
|
|
neg.b _width
|
601 |
|
|
move.l a0,d0
|
602 |
|
|
sub.l #_fpBuf,d0 ; d0 = ndx
|
603 |
|
|
.0044
|
604 |
|
|
cmp.b _width,d0
|
605 |
|
|
bge .0043
|
606 |
|
|
move.b #' ',(a0,d0.w)
|
607 |
|
|
addi.w #1,d0
|
608 |
|
|
bra .0044
|
609 |
|
|
.0043
|
610 |
|
|
move.b #0,(a0,d0.w)
|
611 |
|
|
.0042
|
612 |
|
|
ext.w d0
|
613 |
|
|
ext.l d0
|
614 |
|
|
rts
|
615 |
|
|
|
616 |
|
|
;------------------------------------------------------------------------------
|
617 |
|
|
; Output a string representation of a decimal floating point number to a
|
618 |
|
|
; buffer.
|
619 |
|
|
;
|
620 |
|
|
; Register Usage
|
621 |
|
|
; a0 = pointer to string buffer
|
622 |
|
|
; d6 = exponent
|
623 |
|
|
; Parameters:
|
624 |
|
|
; fp0 = number to convert
|
625 |
|
|
;------------------------------------------------------------------------------
|
626 |
|
|
|
627 |
|
|
_sprtflt:
|
628 |
|
|
bsr _CheckNegative ; is number negative?
|
629 |
|
|
bsr _CheckZero ; check for zero
|
630 |
|
|
bsr _CheckNan ; check for Nan or infinity
|
631 |
|
|
; Now the fun begins
|
632 |
|
|
clr.l d6
|
633 |
|
|
bsr _MakeBig
|
634 |
|
|
bsr _LessThanDbl
|
635 |
|
|
bsr _ComputeDigitsBeforeDecpt
|
636 |
|
|
bsr _LeadingZero
|
637 |
|
|
bsr _SpitOutDigits
|
638 |
|
|
bsr _TrimTrailingZeros
|
639 |
|
|
bsr _TrimTrailingPoint
|
640 |
|
|
bsr _TrimDotZero
|
641 |
|
|
bsr _ExtExpDigits ; extract exponent digits
|
642 |
|
|
bsr _PadLeft ; pad the number to the left or right
|
643 |
|
|
bra _PadRight
|
644 |
|
|
|
645 |
|
|
;------------------------------------------------------------------------------
|
646 |
|
|
; Trap #15, function 39 - convert floating-point to string and display
|
647 |
|
|
;
|
648 |
|
|
; Parameters
|
649 |
|
|
; a0 = pointer to buffer
|
650 |
|
|
; fp0 = number to print
|
651 |
|
|
; d1 = width of print field
|
652 |
|
|
; d2 = precision
|
653 |
|
|
; d3 = 'E' or 'e'
|
654 |
|
|
;------------------------------------------------------------------------------
|
655 |
|
|
|
656 |
|
|
prtflt:
|
657 |
|
|
movem.l d0/d1/d2/d3/d6/a1,-(a7)
|
658 |
|
|
; fmove.p fp0,-(a7)
|
659 |
|
|
move.l a1,a0 ; a0 = pointer to buffer to use
|
660 |
|
|
move.b d1,_width
|
661 |
|
|
move.l d2,_precision
|
662 |
|
|
move.b d3,_E
|
663 |
|
|
bsr _sprtflt
|
664 |
|
|
bsr DisplayString
|
665 |
|
|
; fmove.p (a7)+,fp0
|
666 |
|
|
movem.l (a7)+,d0/d1/d2/d3/d6/a1
|
667 |
|
|
rts
|
668 |
|
|
|