* device/lib/printf_large.c: 6 bytes less __data mem (6 more __idata)
[fw/sdcc] / device / lib / printf_fast.c
1 /* Fast printf routine for use with sdcc/mcs51
2  * Copyright (c) 2004, Paul Stoffregen, paul@pjrc.com
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18
19 /******************************************************************/
20 /**                                                              **/
21 /**    Major features.  These determine what capabilities your   **/
22 /**    compiled printf_fast will have.                           **/
23 /**                                                              **/
24 /******************************************************************/
25
26 // Include support for 32 bit base 10 integers (%ld and %lu).  Without
27 // this, you won't be able to print 32 bit integers as base 10.  They
28 // will appear in hexadecimal.
29 #define LONG
30
31 // Include support for floating point numbers (%f).  Don't forget to
32 // enable LONG above, if you want to print floats greater than
33 // 65535.997.  You can have 6 good digits after the decimal point,
34 // or an 8th if a small error is ok.  +/- 2^32 to 1/10^8 isn't the
35 // full dynamic range of 32 bit floats, but it covers the most
36 // commonly used range.  Adds about 500-600 bytes of code.
37 //#define FLOAT
38
39 // Include support for minimum field widths (%8d, %20s, %12.5f)
40 #define FIELD_WIDTH
41
42 // Include fast integer conversion.  Without this, a compact but slower
43 // algorithm is used to convert integers (%d, %u, int part of %f).
44 // Even the slow algorithm is much faster than a typical C implementation
45 // based on repetitive division by 10.  If you enable this, you get an
46 // extremely fast version (only 8 table lookups and 8 adds to convert a
47 // 32 bit integer), but it costs extra code space for larger lookup
48 // tables and optimized non-looping code.
49 #define FAST_INTEGER
50
51
52 /******************************************************************/
53 /**                                                              **/
54 /**    Minor tweaks.  These provide small code savings, with     **/
55 /**    a partial loss of functionality.                          **/
56 /**                                                              **/
57 /******************************************************************/
58
59
60 // If you enabled FLOAT, enabling this replaces the normal %f float
61 // output with a very compact version that always prints 4 fractional
62 // digits and does not have round off.  Zero will print as "0.0000",
63 // and 1.999997 will print as "1.9999" (not rounded up to 2).  The
64 // 4th digit is not accurate (+/- 2).  This simpler version also
65 // avoids using 5 bytes of internal data memory.  Code size is about
66 // 240 bytes less.
67 //#define FLOAT_FIXED4
68
69 // If you used FLOAT (not FLOAT_FIXED4), this will remove the smart
70 // default number of digits code.  When you use "%f" without a field
71 // width, normally the smart default width code chooses a good number
72 // of digits based on size of the number.  If you enabled FIELD_WIDTH
73 // and use a number, like "%.5f", this smart default code is never
74 // used anyway.  Saves about 40 bytes of code.
75 //#define FLOAT_DEFAULT_FRAC_DIGITS 6
76
77 // If you used FLOAT (not FLOAT_FIXED4) and you do not specify a
78 // field width, normally trailing zeros are trimmed.  Using this
79 // removes that feature (saves only a few bytes).
80 //#define DO_NOT_TRIM_TRAILING_ZEROS
81
82 // Omit saving and restoring registers when calling putchar().  If you
83 // are desparate for a little more code space, this will give you a
84 // small savings.  You MUST define putchar() with #pragma callee_saves,
85 // or implement it in assembly and avoid changing the registers.
86 //#define PUTCHAR_CALLEE_SAVES
87
88
89 /* extern void putchar(char ); */
90
91 // Warning: using static/global variables makes these functions NON-reentrant!
92 // reentrant keyword is only used for parameter passing method
93
94 static bit long_flag, short_flag, print_zero_flag, negative_flag;
95
96 #ifdef FIELD_WIDTH
97 static bit field_width_flag;
98 static bit leading_zero_flag;
99 static data unsigned char field_width;
100 #endif
101
102 #ifdef FLOAT
103 #define SDCC_FLOAT_LIB
104 #include <float.h>
105 static bit continue_float;
106 #ifndef FLOAT_FIXED4
107 static data unsigned char frac_field_width;
108 static data unsigned char float_frac_bcd[4];
109 // TODO: can float_frac_bcd be overlaid with temps used by trig functions
110 #endif
111 #endif
112
113 #ifndef FAST_INTEGER
114 #ifdef LONG
115 static data unsigned int i2bcd_tmp;  // slow 32 int conversion needs temp space
116 #endif
117 #endif
118
119
120
121 #ifndef PRINTF_FAST
122 #define PRINTF_FAST printf_fast
123 #endif
124
125
126 #if !defined(SDCC_mcs51) || defined(SDCC_USE_XSTACK) || defined(_SDCC_NO_ASM_LIB_FUNCS)
127 // Does printf_fast really work on ds390 and ds400?
128 // If it does, enable them in the line above
129 #if defined(SDCC_USE_XSTACK)
130 #warning "printf_fast not built, does not support --xstack"
131 #elif defined(_SDCC_NO_ASM_LIB_FUNCS)
132 #warning "printf_fast not built, _SDCC_NO_ASM_LIB_FUNCS defined"
133 #endif
134 #else // defines are compatible with printf_fast
135
136
137 void PRINTF_FAST(code char *fmt, ...) reentrant
138 {
139         fmt;    /* suppress unreferenced variable warning */
140
141         _asm
142
143 printf_begin:
144         mov     a, _bp          // r0 will point to va_args (stack)
145         add     a, #253
146         mov     r0, a           // r0 points to MSB of fmt
147         mov     dph, @r0
148         dec     r0
149         mov     dpl, @r0        // dptr has address of fmt
150         dec     r0
151
152
153 printf_main_loop:
154         clr     a
155         movc    a, @a+dptr      // get next byte of fmt string
156         inc     dptr
157         //cjne  a, #'%', printf_normal
158         cjne    a, #37, printf_normal
159
160 printf_format:
161         clr     _long_flag
162         clr     _short_flag
163         clr     _print_zero_flag
164         clr     _negative_flag
165 #ifdef FIELD_WIDTH
166         clr     _field_width_flag
167         clr     _leading_zero_flag
168         mov     r1, #_field_width
169         mov     @r1, #0
170 #endif
171 #ifdef FLOAT
172         clr     _continue_float
173 #endif
174
175 printf_format_loop:
176         clr     a
177         movc    a, @a+dptr      // get next byte of data format
178         inc     dptr
179
180         /* parse and consume the field width digits, even if */
181         /* we don't build the code to make use of them */
182         add     a, #198
183         jc      printf_nondigit1
184         add     a, #10
185         jnc     printf_nondigit2
186 #ifdef FIELD_WIDTH
187 printf_digit:
188         jnz     printf_digit_2
189         cjne    a, _field_width, printf_digit_2
190         setb    _leading_zero_flag
191 printf_digit_2:
192         setb    _field_width_flag
193         mov     r2, a
194         mov     a, @r1
195         mov     b, #10
196         mul     ab
197         add     a, r2
198         mov     @r1, a
199 #endif
200         sjmp    printf_format_loop
201 printf_nondigit1:
202         add     a, #10
203 printf_nondigit2:
204         add     a, #48
205
206
207 printf_format_l:
208         //cjne  a, #'l', printf_format_h
209         cjne    a, #108, printf_format_h
210         setb    _long_flag
211         sjmp    printf_format_loop
212
213 printf_format_h:
214         //cjne  a, #'h', printf_format_s
215         cjne    a, #104, printf_format_s
216         setb    _short_flag
217         sjmp    printf_format_loop
218
219 printf_format_s:
220         //cjne  a, #'s', printf_format_d
221         cjne    a, #115, printf_format_d
222         ljmp    printf_string
223
224 printf_format_d:
225         //cjne  a, #'d', printf_format_u
226         cjne    a, #100, printf_format_u
227         lcall   printf_get_int
228         ljmp    printf_int
229
230 printf_format_u:
231         //cjne  a, #'u', printf_format_c
232         cjne    a, #117, printf_format_c
233         lcall   printf_get_int
234         ljmp    printf_uint
235
236 printf_format_c:
237         //cjne  a, #'c', printf_format_x
238         cjne    a, #99, printf_format_x
239         dec     r0
240         mov     a, @r0          // Acc has the character to print
241         dec     r0
242         sjmp    printf_char
243
244 printf_format_x:
245         //cjne  a, #'x', printf_format_f
246         cjne    a, #120, printf_format_f
247         ljmp    printf_hex
248
249 printf_format_f:
250 #ifdef FLOAT
251         //cjne  a, #'f', printf_format_dot
252         cjne    a, #102, printf_format_dot
253         ljmp    print_float
254 #endif
255
256 printf_format_dot:
257         //cjne  a, #'.', printf_normal
258         cjne    a, #46, printf_normal
259 #ifdef FLOAT
260 #ifdef FLOAT_FIXED4
261         mov     r1, #ar3        // parse frac field, but discard if FIXED4
262 #else
263         mov     r1, #_frac_field_width
264         mov     @r1, #0
265 #endif
266 #endif
267         sjmp    printf_format_loop
268
269 printf_normal:
270         jz      printf_eot
271 printf_char:
272         lcall   printf_putchar
273         ljmp    printf_main_loop
274
275 printf_eot:
276         ljmp    printf_end
277
278
279
280
281
282
283         /* print a string... just grab each byte with __gptrget */
284         /* the user much pass a 24 bit generic pointer */
285
286 printf_string:
287         push    dph             // save addr in fmt onto stack
288         push    dpl
289         mov     b, @r0          // b has type of address (generic *)
290         dec     r0
291         mov     dph, @r0
292         dec     r0
293         mov     dpl, @r0        // dptr has address of user's string
294         dec     r0
295
296 #ifdef FIELD_WIDTH
297         jnb     _field_width_flag, printf_str_loop
298         clr     _leading_zero_flag      // never leading zeros for strings
299         push    dpl
300         push    dph
301 printf_str_fw_loop:
302         lcall   __gptrget
303         jz      printf_str_space
304         inc     dptr
305         dec     _field_width
306         mov     a, _field_width
307         jnz     printf_str_fw_loop
308 printf_str_space:
309         lcall   printf_space
310         pop     dph
311         pop     dpl
312 #endif // FIELD_WIDTH
313
314 printf_str_loop:
315         lcall   __gptrget
316         jz      printf_str_done
317         inc     dptr
318         lcall   printf_putchar
319         sjmp    printf_str_loop
320 printf_str_done:
321         pop     dpl             // restore addr withing fmt
322         pop     dph
323         ljmp    printf_main_loop
324
325
326
327
328
329
330
331
332         /* printing in hex is easy because sdcc pushes the LSB first */
333
334 printf_hex:
335         lcall   printf_hex8
336         jb      _short_flag, printf_hex_end
337         lcall   printf_hex8
338         jnb     _long_flag, printf_hex_end
339         lcall   printf_hex8
340         lcall   printf_hex8
341 printf_hex_end:
342         lcall   printf_zero
343         ljmp    printf_main_loop
344 printf_hex8:
345         mov     a, @r0
346         lcall   printf_phex_msn
347         mov     a, @r0
348         dec     r0
349         ljmp    printf_phex_lsn
350
351
352 #ifndef LONG
353 printf_ld_in_hex:
354         //mov   a, #'0'
355         mov     a, #48
356         lcall   printf_putchar
357         //mov   a, #'x'
358         mov     a, #120
359         lcall   printf_putchar
360         mov     a, r0
361         add     a, #4
362         mov     r0, a
363         sjmp    printf_hex
364 #endif
365
366
367         /* printing an integer is not so easy.  For a signed int */
368         /* check if it is negative and print the minus sign and */
369         /* invert it to a positive integer */
370
371 printf_int:
372         mov     a, r5
373         jnb     acc.7, printf_uint      /* check if negative */
374         setb    _negative_flag
375         mov     a, r1                   /* invert integer */
376         cpl     a
377         add     a, #1
378         mov     r1, a
379         jb      _short_flag, printf_uint
380         mov     a, r2
381         cpl     a
382         addc    a, #0
383         mov     r2, a
384         jnb     _long_flag, printf_uint
385         mov     a, r3
386         cpl     a
387         addc    a, #0
388         mov     r3, a
389         mov     a, r4
390         cpl     a
391         addc    a, #0
392         mov     r4, a
393
394
395         /* printing integers is a lot of work... because it takes so */
396         /* long, the first thing to do is make sure we're doing as */
397         /* little work as possible, then convert the binary int to */
398         /* packed BCD, and finally print each digit of the BCD number */
399
400 printf_uint:
401
402         jb      _short_flag, printf_uint_ck8
403         jnb     _long_flag, printf_uint_ck16
404 printf_uint_ck32:
405         /* it's a 32 bit int... but if the upper 16 bits are zero */
406         /* we can treat it like a 16 bit integer and convert much faster */
407 #ifdef LONG
408         mov     a, r3
409         jnz     printf_uint_begin
410         mov     a, r4
411         jnz     printf_uint_begin
412 #else
413         mov     a, r3
414         jnz     printf_ld_in_hex        // print long integer as hex
415         mov     a, r4                   // rather than just the low 16 bits
416         jnz     printf_ld_in_hex
417 #endif
418         clr     _long_flag
419 printf_uint_ck16:
420         /* it's a 16 bit int... but if the upper 8 bits are zero */
421         /* we can treat it like a 8 bit integer and convert much faster */
422         mov     a, r2
423         jnz     printf_uint_begin
424         setb    _short_flag
425 printf_uint_ck8:
426         /* it's an 8 bit int... if it's zero, it's a lot faster to just */
427         /* print the digit zero and skip all the hard work! */
428         mov     a, r1
429         jnz     printf_uint_begin
430 #ifdef FIELD_WIDTH
431         jnb     _field_width_flag, printf_uint_zero
432         mov     a, _field_width
433         jz      printf_uint_zero
434         dec     _field_width
435         lcall   printf_space
436 #endif
437 printf_uint_zero:
438         //mov   a, #'0'
439         mov     a, #48
440         lcall   printf_putchar
441 #ifdef FLOAT
442         jnb     _continue_float, 0001$
443         ret
444 0001$:
445 #endif
446         ljmp    printf_main_loop
447
448
449
450 printf_uint_begin:
451         push    dpl
452         push    dph
453         lcall   printf_int2bcd          // bcd number in r3/r2/r7/r6/r5
454 printf_uint_2:
455
456 #ifdef FIELD_WIDTH
457         jnb     _field_width_flag, printf_uifw_end
458 #ifdef LONG
459 printf_uifw_32:
460         mov     r1, #10
461         jnb     _long_flag, printf_uifw_16
462         mov     a, r3
463         anl     a, #0xF0
464         jnz     printf_uifw_sub
465         dec     r1
466         mov     a, r3
467         anl     a, #0x0F
468         jnz     printf_uifw_sub
469         dec     r1
470         mov     a, r2
471         anl     a, #0xF0
472         jnz     printf_uifw_sub
473         dec     r1
474         mov     a, r2
475         anl     a, #0x0F
476         jnz     printf_uifw_sub
477         dec     r1
478         mov     a, r7
479         anl     a, #0xF0
480         jnz     printf_uifw_sub
481 #endif // LONG
482 printf_uifw_16:
483         mov     r1, #5
484         jb      _short_flag, printf_uifw_8
485         mov     a, r7
486         anl     a, #0x0F
487         jnz     printf_uifw_sub
488         dec     r1
489         mov     a, r6
490         anl     a, #0xF0
491         jnz     printf_uifw_sub
492 printf_uifw_8:
493         mov     r1, #3
494         mov     a, r6
495         anl     a, #0x0F
496         jnz     printf_uifw_sub
497         dec     r1
498         mov     a, r5
499         anl     a, #0xF0
500         jnz     printf_uifw_sub
501         dec     r1
502 printf_uifw_sub:
503         ;r1 has the number of digits for the number
504         mov     a, _field_width
505         mov     c, _negative_flag
506         subb    a, r1
507         jc      printf_uifw_end
508         mov     _field_width, a
509
510 #ifndef PUTCHAR_CALLEE_SAVES
511 #ifdef LONG
512         push    ar3
513         push    ar2
514 #endif
515         push    ar7
516         push    ar6
517         push    ar5
518 #endif
519         lcall   printf_space
520 #ifndef PUTCHAR_CALLEE_SAVES
521         pop     ar5
522         pop     ar6
523         pop     ar7
524 #ifdef LONG
525         pop     ar2
526         pop     ar3
527 #endif
528 #endif
529
530
531 printf_uifw_end:
532 #endif // FIELD_WIDTH
533
534
535 printf_uint_doit:
536         jnb     _negative_flag, printf_uint_pos
537 #ifdef PUTCHAR_CALLEE_SAVES
538         //mov   a, #'-'
539         mov     a, #45
540         lcall   printf_putchar
541 #else
542 #ifdef LONG
543         push    ar3
544         push    ar2
545 #endif
546         push    ar7
547         push    ar6
548         push    ar5
549         //mov   a, #'-'
550         mov     a, #45
551         lcall   printf_putchar
552         pop     ar5
553         pop     ar6
554         pop     ar7
555 #ifdef LONG
556         pop     ar2
557         pop     ar3
558 #endif
559 #endif // PUTCHAR_CALLEE_SAVES
560
561 printf_uint_pos:
562         jb      _short_flag, printf_uint8
563 #ifdef LONG
564         jnb     _long_flag, printf_uint16
565 printf_uint32:
566         push    ar5
567         push    ar6
568         push    ar7
569         mov     dpl, r2
570         mov     a, r3
571         mov     dph, a
572         lcall   printf_phex_msn
573         mov     a, dph
574         lcall   printf_phex_lsn
575         mov     a, dpl
576         lcall   printf_phex_msn
577         mov     a, dpl
578         lcall   printf_phex_lsn
579         pop     acc
580         mov     dpl, a
581         lcall   printf_phex_msn
582         mov     a, dpl
583         pop     dph
584         pop     dpl
585         sjmp    printf_uint16a
586 #endif // LONG
587
588 printf_uint16:
589         mov     dpl, r5
590         mov     dph, r6
591         mov     a, r7
592 printf_uint16a:
593         lcall   printf_phex_lsn
594         mov     a, dph
595         lcall   printf_phex_msn
596         mov     a, dph
597         sjmp    printf_uint8a
598
599 printf_uint8:
600         mov     dpl, r5
601         mov     a, r6
602 printf_uint8a:
603         lcall   printf_phex_lsn
604         mov     a, dpl
605         lcall   printf_phex_msn
606         mov     a, dpl
607         lcall   printf_phex_lsn
608         lcall   printf_zero
609         pop     dph
610         pop     dpl
611 #ifdef FLOAT
612         jnb     _continue_float, 0002$
613         ret
614 0002$:
615 #endif
616         ljmp    printf_main_loop
617
618
619
620
621
622
623
624
625 #ifdef FLOAT
626 #ifdef FLOAT_FIXED4
627         // Print a float the easy way.  First, extract the integer part and
628         // use the integer printing code.  Then extract the fractional part,
629         // convert each bit to 4 digit BCD, and print the BCD sum.  Absolutely
630         // no field width control, always 4 digits printed past the decimal
631         // point.  No round off.  1.9999987 prints as 1.9999, not 2.0000.
632 print_float:
633 #ifdef FIELD_WIDTH
634         jnb     _field_width_flag, print_float_begin
635         mov     a, _field_width
636         add     a, #251
637         mov     _field_width, a
638         jc      print_float_begin
639         mov     _field_width, #0
640 #endif
641 print_float_begin:
642         push    ar0             // keep r0 safe, will need it again
643         lcall   printf_get_float
644         clr     c
645         mov     a, #158                 // check for large float we can't print
646         subb    a, r7
647         jnc     print_float_size_ok
648 printf_float_too_big:
649         // TODO: should print some sort of overflow error??
650         pop     ar0
651         ljmp    printf_format_loop
652 print_float_size_ok:
653         push    dpl
654         lcall   fs_rshift_a
655         pop     dpl
656         setb    _continue_float
657 #ifndef LONG
658         mov     a, r3
659         orl     a, r4
660         jnz     printf_float_too_big
661 #endif
662         lcall   printf_uint             // print the integer portion
663         //mov   a, #'.'
664         mov     a, #0x2E
665         lcall   printf_putchar
666         // now that the integer part is printed, we need to refetch the
667         // float from the va_args and extract the fractional part
668         pop     ar0
669         lcall   printf_get_float
670         push    ar0
671         push    dpl
672         push    dph
673         mov     a, r7
674         cjne    a, #126, print_float_frac_lshift
675         sjmp    print_float_frac // input between 0.5 to 0.9999
676 print_float_frac_lshift:
677         jc      print_float_frac_rshift
678         //Acc (exponent) is greater than 126 (input >= 1.0)
679         add     a, #130
680         mov     r5, a
681 print_float_lshift_loop:
682         clr     c
683         mov     a, r2
684         rlc     a
685         mov     r2, a
686         mov     a, r3
687         rlc     a
688         mov     r3, a
689         mov     a, r4
690         rlc     a
691         mov     r4, a
692         djnz    r5, print_float_lshift_loop
693         sjmp    print_float_frac
694 print_float_frac_rshift:
695         //Acc (exponent) is less than 126 (input < 0.5)
696         cpl     a
697         add     a, #127
698         lcall   fs_rshift_a
699 print_float_frac:
700         // now we've got the fractional part, so now is the time to
701         // convert to BCD... just convert each bit to BCD using a
702         // lookup table and BCD sum them together
703         mov     r7, #14
704         clr     a
705         mov     r6, a
706         mov     r5, a
707         mov     dptr, #_frac2bcd        // FLOAT_FIXED4 version (14 entries)
708 print_float_frac_loop:
709         mov     a, r3
710         rlc     a
711         mov     r3, a
712         mov     a, r4
713         rlc     a
714         mov     r4, a
715         jnc     print_float_frac_skip
716         clr     a
717         movc    a, @a+dptr
718         add     a, r5
719         da      a
720         mov     r5, a
721         mov     a, #1
722         movc    a, @a+dptr
723         addc    a, r6
724         da      a
725         mov     r6, a
726 print_float_frac_skip:
727         inc     dptr
728         inc     dptr
729         djnz    r7, print_float_frac_loop
730         // the BCD sum is in dptr, so all we've got to do is output
731         // all 4 digits.  No trailing zero suppression, no nice round
732         // off (impossible to change the integer part since we already
733         // printed it).
734         mov     dph, r6
735         mov     dpl, r5
736         setb    _print_zero_flag
737         mov     a, dph
738         lcall   printf_phex_msn
739         mov     a, dph
740         lcall   printf_phex_lsn
741         mov     a, dpl
742         lcall   printf_phex_msn
743         mov     a, dpl
744         lcall   printf_phex_lsn
745         pop     dph
746         pop     dpl
747         pop     ar0
748         ljmp    printf_main_loop
749
750 #else // not FLOAT_FIXED4
751
752
753
754
755 print_float:
756         // Print a float the not-as-easy way, with a configurable number of
757         // fractional digits (up to 8) and proper round-off (up to 7 digits).
758         // First, extract the fractional part, convert to BCD, and then add
759         // the scaled round-off.  Store the rounded fractional digits and
760         // their carry.  Then extract the integer portion, increment it if
761         // the rounding caused a carry.  Use the integer printing to output
762         // the integer, and then output the stored fractional digits.  This
763         // approach requires 5 bytes of internal RAM to store the 8 fractional
764         // digits and the number of them we'll actually print.  This code is
765         // a couple hundred bytes larger and a bit slower than the FIXED4
766         // version, but it gives very nice results.
767 print_float_1:
768 #ifdef FIELD_WIDTH
769         jnb     _field_width_flag, print_float_default_width
770         // The caller specified exact field width, so use it.  Need to
771         // convert the whole float digits into the integer portion only.
772         mov     a, _field_width
773         setb    c
774         subb    a, _frac_field_width
775         mov     _field_width, a
776         jnc     print_float_begin
777         mov     _field_width, #0
778         sjmp    print_float_begin
779 #endif
780 print_float_default_width:
781         // The caller didn't specify field width (or FIELD_WIDTH is
782         // not defined so it's ignored).  We've still got to know
783         // how many fractional digits are going to print, so we can
784         // round off properly.
785 #ifdef FLOAT_DEFAULT_FRAC_DIGITS
786         mov     _frac_field_width, #FLOAT_DEFAULT_FRAC_DIGITS
787 #else
788         // default fractional field width (between 0 to 7)
789         // attempt to scale the default number of fractional digits
790         // based on the magnitude of the float
791         mov     ar1, r0         // r0 points to first byte of float
792         dec     r1              // r1 points to second byte of float
793         mov     r6, dpl
794         mov     r7, dph
795         mov     dptr, #_float_range_table
796         mov     r5, #7
797 print_float_default_loop:
798         clr     a
799         movc    a, @a+dptr
800         add     a, @r1
801         inc     dptr
802         clr     a
803         movc    a, @a+dptr
804         addc    a, @r0
805         jnc     print_float_default_done
806         inc     dptr
807         djnz    r5, print_float_default_loop
808 print_float_default_done:
809         mov     _frac_field_width, r5
810         mov     dpl, r6
811         mov     dph, r7
812 #endif // not FLOAT_DEFAULT_FRAC_DIGITS
813
814 print_float_begin:
815         push    ar0                     // keep r0 safe, will need it again
816         lcall   printf_get_float
817         push    dpl
818         push    dph
819         mov     a, r7
820         cjne    a, #126, print_float_frac_lshift
821         sjmp    print_float_frac        // input between 0.5 to 0.9999
822
823 print_float_frac_lshift:
824         jc      print_float_frac_rshift
825         //Acc (exponent) is greater than 126 (input >= 1.0)
826         add     a, #130
827         mov     r5, a
828 print_float_lshift_loop:
829         clr     c
830         mov     a, r2
831         rlc     a
832         mov     r2, a
833         mov     a, r3
834         rlc     a
835         mov     r3, a
836         mov     a, r4
837         rlc     a
838         mov     r4, a
839         djnz    r5, print_float_lshift_loop
840         sjmp    print_float_frac
841 print_float_frac_rshift:
842         //Acc (exponent) is less than 126 (input < 0.5)
843         cpl     a
844         add     a, #127
845         lcall   fs_rshift_a
846 print_float_frac:
847         // Convert the fraction in r4/r3/r2/r1 into 8 BCD digits in r0/r7/r6/r5
848         mov     b, #27
849         clr     a
850         mov     r0, a
851         mov     r7, a
852         mov     r6, a
853         mov     r5, a
854         mov     dptr, #_frac2bcd        // FLOAT version (27 entries)
855 print_float_frac_loop:
856         mov     a, r1
857         rlc     a
858         mov     r1, a
859         mov     a, r2
860         rlc     a
861         mov     r2, a
862         mov     a, r3
863         rlc     a
864         mov     r3, a
865         mov     a, r4
866         rlc     a
867         mov     r4, a
868         jnc     print_float_frac_skip
869         clr     a
870         movc    a, @a+dptr
871         add     a, r5
872         da      a
873         mov     r5, a
874         mov     a, #1
875         movc    a, @a+dptr
876         addc    a, r6
877         da      a
878         mov     r6, a
879         mov     a, #2
880         movc    a, @a+dptr
881         addc    a, r7
882         da      a
883         mov     r7, a
884         mov     a, #3
885         movc    a, @a+dptr
886         addc    a, r0
887         da      a
888         mov     r0, a
889 print_float_frac_skip:
890         inc     dptr
891         inc     dptr
892         inc     dptr
893         inc     dptr
894         djnz    b, print_float_frac_loop
895 print_float_frac_roundoff:
896         // Now it's time to round-off the BCD digits to the desired precision.
897         clr     a
898         mov     r4, #0x50               // r4/r3/r2/r1 = 0.5 (bcd rounding)
899         mov     r3, a
900         mov     r2, a
901         mov     r1, a
902         mov     a, _frac_field_width
903         rl      a
904         rl      a
905         anl     a, #0xFC
906         mov     dph, r0                 // fs_rshift_a will overwrite r0 & dpl
907         lcall   fs_rshift_a             // divide r4/r3/r2/r1 by 10^frac_field_width
908         mov     a, r5
909         add     a, r1                   // add rounding to fractional part
910         da      a
911         mov     _float_frac_bcd+3, a    // and store it for later use
912         mov     a, r6
913         addc    a, r2
914         da      a
915         mov     _float_frac_bcd+2, a
916         mov     a, r7
917         addc    a, r3
918         da      a
919         mov     _float_frac_bcd+1, a
920         mov     a, dph
921         addc    a, r4
922         da      a
923         mov     _float_frac_bcd+0, a
924         mov     sign_b, c               // keep fractional carry in sign_b
925         pop     dph
926         pop     dpl
927 print_float_int:
928         // Time to work on the integer portion... fetch the float again, check
929         // size (exponent), scale to integer, add the fraction's carry, and
930         // let the integer printing code do all the work.
931         pop     ar0
932         lcall   printf_get_float
933         push    ar0
934         clr     c
935         mov     a, #158                 // check for large float we can't print
936         subb    a, r7
937         jnc     print_float_size_ok
938 printf_float_too_big:
939         // TODO: should print some sort of overflow error??
940         pop     ar0
941         ljmp    printf_format_loop
942 print_float_size_ok:
943         push    dpl
944         lcall   fs_rshift_a
945         pop     dpl
946         jnb     sign_b, print_float_do_int
947         // if we get here, the fractional round off caused the
948         // integer part to increment.  Add 1 for a proper result
949         mov     a, r1
950         add     a, #1
951         mov     r1, a
952         clr     a
953         addc    a, r2
954         mov     r2, a
955 #ifdef LONG
956         clr     a
957         addc    a, r3
958         mov     r3, a
959         clr     a
960         addc    a, r4
961         mov     r4, a
962 #endif
963         jc      printf_float_too_big
964 print_float_do_int:
965 #ifndef LONG
966         mov     a, r3
967         orl     a, r4
968         jnz     printf_float_too_big
969 #endif
970         setb    _continue_float
971         lcall   printf_uint             // print the integer portion
972
973
974 print_float_frac_width:
975         // Now all we have to do is output the fractional digits that
976         // were previous computed and stored in memory.
977 #ifdef FIELD_WIDTH
978         jb      _field_width_flag, print_float_do_frac
979 #endif
980 #ifndef DO_NOT_TRIM_TRAILING_ZEROS 
981         // if the user did not explicitly set a
982         // field width, trim off trailing zeros
983 print_float_frac_trim:
984         mov     a, _frac_field_width
985         jz      print_float_do_frac
986         lcall   get_float_frac_digit
987         jnz     print_float_do_frac
988         djnz    _frac_field_width, print_float_frac_trim
989 #endif
990
991 print_float_do_frac:
992         mov     a, _frac_field_width
993         jz      print_float_done
994         //mov   a, #'.'
995         mov     a, #0x2E
996         lcall   printf_putchar
997         mov     r0, #0
998         setb    _print_zero_flag
999 print_float_do_frac_loop:
1000         inc     r0
1001         mov     a, r0
1002         lcall   get_float_frac_digit
1003         lcall   printf_phex_lsn
1004         mov     a, r0
1005         cjne    a, _frac_field_width, print_float_do_frac_loop
1006
1007 print_float_done:
1008         pop     ar0
1009         ljmp    printf_main_loop
1010
1011
1012
1013         // acc=1 for tenths, acc=2 for hundredths, etc
1014 get_float_frac_digit:
1015         dec     a
1016         clr     c
1017         rrc     a
1018         mov     psw.5, c
1019         add     a, #_float_frac_bcd
1020         mov     r1, a
1021         mov     a, @r1
1022         jb      psw.5, get_float_frac_digit_done
1023         swap    a
1024 get_float_frac_digit_done:
1025         anl     a, #15
1026         ret
1027
1028
1029
1030
1031 #endif // end of normal FLOAT code (not FLOAT_FIXED4)
1032
1033
1034 // These helper functions are used, regardless of which type of
1035 // FLOAT code is used.
1036
1037 #if 0
1038 pm2_print_float:
1039          mov    a, r7
1040          lcall  pm2_entry_phex
1041          mov    a, #0x20
1042          lcall  pm2_entry_cout
1043          lcall  _print_r4321
1044          mov    a, #0x20
1045          lcall  pm2_entry_cout
1046          ret
1047 #endif
1048
1049         // Fetch a float from the va_args and put it into
1050         // r7(exp) r4/r3/r2(mant) and also clear r1 and preset
1051         // the flags
1052 printf_get_float:
1053         mov     a, @r0
1054         dec     r0
1055         mov     r1, a
1056         mov     a, @r0
1057         dec     r0
1058         mov     r4, a
1059         rlc     a
1060         mov     a, r1
1061         rlc     a
1062         mov     _negative_flag, c
1063         mov     r7, a
1064         jz      printf_get_float_2
1065         orl     ar4, #0x80
1066 printf_get_float_2:
1067         mov     a, @r0
1068         dec     r0
1069         mov     r3, a
1070         mov     a, @r0
1071         dec     r0
1072         mov     r2, a
1073         mov     r1, #0
1074         clr     _short_flag
1075         setb    _long_flag
1076         ret
1077 #endif // FLOAT
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091         /* read an integer into r1/r2/r3/r4, and msb into r5 */
1092 printf_get_int:
1093         mov     a, @r0
1094         mov     r1, a
1095         mov     r5, a
1096         dec     r0
1097         jb      _short_flag, printf_get_done
1098         mov     r2, ar1
1099         mov     a, @r0
1100         mov     r1, a
1101         dec     r0
1102         jnb     _long_flag, printf_get_done
1103         mov     r4, ar2
1104         mov     r3, ar1
1105         mov     a, @r0
1106         mov     r2, a
1107         dec     r0
1108         mov     a, @r0
1109         mov     r1, a
1110         dec     r0
1111 printf_get_done:
1112         ret
1113
1114
1115
1116
1117
1118 #ifdef FAST_INTEGER
1119
1120         /* convert binary number in r4/r3/r2/r1 into bcd packed number
1121          * in r3/r2/r7/r6/r5.  The input number is destroyed in the
1122          * process, to avoid needing extra memory for the result (and
1123          * r1 gets used for temporary storage).  dptr is overwritten,
1124          * but r0 is not changed.
1125          */
1126
1127 printf_int2bcd:
1128         mov     a, r1
1129         mov     b, #100
1130         div     ab
1131         mov     r6, a
1132         mov     a, #10
1133         xch     a, b
1134         div     ab
1135         swap    a
1136         orl     a, b
1137         mov     r5, a
1138
1139         jnb     _short_flag, printf_i2bcd_16    // if 8 bit int, we're done
1140         ret
1141
1142 printf_i2bcd_16:
1143         mov     a, r2
1144         anl     a, #0x0F
1145         mov     r1, a
1146         mov     dptr, #_int2bcd_2
1147         movc    a, @a+dptr
1148         add     a, r5
1149         da      a
1150         mov     r5, a
1151         mov     a, r1
1152         orl     a, #16
1153         movc    a, @a+dptr
1154         addc    a, r6
1155         da      a
1156         mov     r6, a
1157
1158         mov     a, r2
1159         swap    a
1160         anl     a, #0x0F
1161         mov     r1, a
1162         mov     dptr, #_int2bcd_3
1163         movc    a, @a+dptr
1164         add     a, r5
1165         da      a
1166         mov     r5, a
1167         mov     a, r1
1168         orl     a, #16
1169         movc    a, @a+dptr
1170         addc    a, r6
1171         da      a
1172         mov     r6, a
1173         mov     a, r1
1174         orl     a, #32
1175         movc    a, @a+dptr
1176         addc    a, #0
1177         da      a
1178         mov     r7, a
1179
1180         jb      _long_flag, printf_i2bcd_32     // if 16 bit int, we're done
1181         ret
1182
1183 printf_i2bcd_32:
1184
1185 #ifdef LONG
1186         mov     a, r3
1187         anl     a, #0x0F
1188         mov     r1, a
1189         mov     dptr, #_int2bcd_4
1190         movc    a, @a+dptr
1191         add     a, r5
1192         da      a
1193         mov     r5, a
1194         mov     a, r1
1195         orl     a, #16
1196         movc    a, @a+dptr
1197         addc    a, r6
1198         da      a
1199         mov     r6, a
1200         mov     a, r1
1201         orl     a, #32
1202         movc    a, @a+dptr
1203         addc    a, r7
1204         da      a
1205         mov     r7, a
1206         clr     a
1207         addc    a, #0
1208         mov     r2, a
1209
1210         mov     a, r3
1211         swap    a
1212         anl     a, #0x0F
1213         mov     r1, a
1214         mov     dptr, #_int2bcd_5
1215         movc    a, @a+dptr
1216         add     a, r5
1217         da      a
1218         mov     r5, a
1219         mov     a, r1
1220         orl     a, #16
1221         movc    a, @a+dptr
1222         addc    a, r6
1223         da      a
1224         mov     r6, a
1225         mov     a, r1
1226         orl     a, #32
1227         movc    a, @a+dptr
1228         addc    a, r7
1229         da      a
1230         mov     r7, a
1231         mov     a, r1
1232         orl     a, #48
1233         movc    a, @a+dptr
1234         addc    a, r2
1235         da      a
1236         mov     r2, a
1237
1238         mov     a, r4
1239         anl     a, #0x0F
1240         mov     r1, a
1241         mov     dptr, #_int2bcd_6
1242         mov     r3, #0
1243         lcall   printf_bcd_add10        // saves 27 bytes, costs 5 cycles
1244
1245         mov     a, r4
1246         swap    a
1247         anl     a, #0x0F
1248         mov     r1, a
1249         mov     dptr, #_int2bcd_7
1250 printf_bcd_add10:
1251         movc    a, @a+dptr
1252         add     a, r5
1253         da      a
1254         mov     r5, a
1255         mov     a, r1
1256         orl     a, #16
1257         movc    a, @a+dptr
1258         addc    a, r6
1259         da      a
1260         mov     r6, a
1261         mov     a, r1
1262         orl     a, #32
1263         movc    a, @a+dptr
1264         addc    a, r7
1265         da      a
1266         mov     r7, a
1267         mov     a, r1
1268         orl     a, #48
1269         movc    a, @a+dptr
1270         addc    a, r2
1271         da      a
1272         mov     r2, a
1273         mov     a, r1
1274         orl     a, #64
1275         movc    a, @a+dptr
1276         addc    a, r3
1277         da      a
1278         mov     r3, a
1279 #endif // LONG
1280         ret
1281
1282
1283 #else // not FAST_INTEGER
1284
1285         /* convert binary number in r4/r3/r2/r1 into bcd packed number
1286          * in r3/r2/r7/r6/r5.  The input number is destroyed in the
1287          * process, to avoid needing extra memory for the result (and
1288          * r1 gets used for temporary storage).  dptr is overwritten,
1289          * but r0 is not changed.
1290          */
1291
1292 #ifdef LONG
1293
1294 printf_int2bcd:
1295         mov     a, #8
1296         jb      _short_flag, printf_int2bcd_begin
1297         mov     a, #16
1298         jnb     _long_flag, printf_int2bcd_begin
1299         mov     a, #32
1300 printf_int2bcd_begin:
1301         mov     b, a
1302         clr     a
1303         mov     r5, a
1304         mov     r6, a
1305         mov     r7, a
1306         mov     (_i2bcd_tmp + 0), a
1307         mov     (_i2bcd_tmp + 1), a
1308         mov     dptr, #_int2bcd
1309 printf_i2bcd_loop:
1310         mov     a, r4
1311         rrc     a
1312         mov     r4, a
1313         mov     a, r3
1314         rrc     a
1315         mov     r3, a
1316         mov     a, r2
1317         rrc     a
1318         mov     r2, a
1319         mov     a, r1
1320         rrc     a
1321         mov     r1, a
1322         jnc     print_i2bcd_skip
1323         clr     a
1324         movc    a, @a+dptr
1325         add     a, r5
1326         da      a
1327         mov     r5, a
1328         mov     a, #1
1329         movc    a, @a+dptr
1330         addc    a, r6
1331         da      a
1332         mov     r6, a
1333         mov     a, #2
1334         movc    a, @a+dptr
1335         addc    a, r7
1336         da      a
1337         mov     r7, a
1338         mov     a, #3
1339         movc    a, @a+dptr
1340         addc    a, (_i2bcd_tmp + 0)
1341         da      a
1342         mov     (_i2bcd_tmp + 0), a
1343         mov     a, #4
1344         movc    a, @a+dptr
1345         addc    a, (_i2bcd_tmp + 1)
1346         da      a
1347         mov     (_i2bcd_tmp + 1), a
1348 print_i2bcd_skip:
1349         inc     dptr
1350         inc     dptr
1351         inc     dptr
1352         inc     dptr
1353         inc     dptr
1354         djnz    b, printf_i2bcd_loop
1355         mov     r2, (_i2bcd_tmp + 0)
1356         mov     r3, (_i2bcd_tmp + 1)
1357         ret
1358
1359 #else //  not LONG
1360
1361 printf_int2bcd:
1362         mov     a, #8
1363         jb      _short_flag, printf_int2bcd_begin
1364         mov     a, #16
1365 printf_int2bcd_begin:
1366         mov     b, a
1367         clr     a
1368         mov     r5, a
1369         mov     r6, a
1370         mov     r7, a
1371         mov     dptr, #_int2bcd
1372 printf_i2bcd_loop:
1373         mov     a, r2
1374         rrc     a
1375         mov     r2, a
1376         mov     a, r1
1377         rrc     a
1378         mov     r1, a
1379         jnc     printf_i2bcd_add_skip
1380         clr     a
1381         movc    a, @a+dptr
1382         add     a, r5
1383         da      a
1384         mov     r5, a
1385         mov     a, #1
1386         movc    a, @a+dptr
1387         addc    a, r6
1388         da      a
1389         mov     r6, a
1390         mov     a, #2
1391         movc    a, @a+dptr
1392         addc    a, r7
1393         da      a
1394         mov     r7, a
1395 printf_i2bcd_add_skip:
1396         inc     dptr
1397         inc     dptr
1398         inc     dptr
1399         djnz    b, printf_i2bcd_loop
1400         ret
1401
1402 #endif // not LONG
1403
1404
1405 #endif // not FAST_INTEGER
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419 #ifdef FIELD_WIDTH
1420 printf_space_loop:
1421         //mov   a, #' '
1422         mov     a, #32
1423         jnb     _leading_zero_flag, printf_space_output
1424         //mov   a, #'0'
1425         mov     a, #48
1426 printf_space_output:
1427         lcall   printf_putchar
1428         dec     _field_width
1429 printf_space:
1430         mov     a, _field_width
1431         jnz     printf_space_loop
1432         ret
1433 #endif
1434
1435
1436
1437
1438
1439         /* print a hex digit, either upper 4 bit (msn) or lower 4 bits (lsn) */
1440
1441 printf_phex_msn:
1442         swap    a
1443 printf_phex_lsn:
1444         anl     a, #15
1445         jnz     printf_phex_ok
1446         jnb     _print_zero_flag, printf_ret
1447 printf_phex_ok:
1448         setb    _print_zero_flag
1449         add     a, #0x90
1450         da      a
1451         addc    a, #0x40
1452         da      a
1453 printf_putchar:
1454 #ifdef PUTCHAR_CALLEE_SAVES
1455         push    dph
1456         push    dpl
1457         mov     dpl, a
1458         lcall   _putchar
1459         pop     dpl
1460         pop     dph
1461 #else
1462         push    dph
1463         push    dpl
1464         push    ar0
1465         mov     dpl, a
1466         lcall   _putchar
1467         pop     ar0
1468         pop     dpl
1469         pop     dph
1470 #endif
1471 printf_ret:
1472         ret
1473
1474         /* print a zero if all the calls to print the digits ended up */
1475         /* being leading zeros */
1476
1477 printf_zero:
1478         jb      _print_zero_flag, printf_ret
1479         //mov   a, #'0'
1480         mov     a, #48
1481         ljmp    printf_putchar
1482   
1483 printf_end:
1484         _endasm;
1485 }
1486
1487
1488 #ifdef FAST_INTEGER
1489 /*
1490  * #! /usr/bin/perl
1491  * for ($d=0; $d < 8; $d++) {
1492  *      $n = 16 ** $d;
1493  *      for ($p=0; $p < 5; $p++) {
1494  *              last unless (((16 ** $d) * 15) / (10 ** ($p * 2))) % 100;
1495  *              printf "code unsigned char int2bcd_%d_%d[15] = {", $d, $p;
1496  *              for ($i=0; $i < 16; $i++) {
1497  *                      printf "0x%02d",
1498  *                         (((16 ** $d) * $i) / (10 ** ($p * 2))) % 100;
1499  *                      print ", " if $i < 15;
1500  *              }
1501  *              print "};\n";
1502  *      }
1503  * }
1504  */
1505
1506 #if 0
1507 static code unsigned char int2bcd_0[] = {
1508 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1509 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15};
1510
1511 static code unsigned char int2bcd_1[] = {
1512 0x00, 0x16, 0x32, 0x48, 0x64, 0x80, 0x96, 0x12,
1513 0x28, 0x44, 0x60, 0x76, 0x92, 0x08, 0x24, 0x40,
1514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1515 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02};
1516 #endif
1517
1518 static code unsigned char int2bcd_2[] = {
1519 0x00, 0x56, 0x12, 0x68, 0x24, 0x80, 0x36, 0x92,
1520 0x48, 0x04, 0x60, 0x16, 0x72, 0x28, 0x84, 0x40,
1521 0x00, 0x02, 0x05, 0x07, 0x10, 0x12, 0x15, 0x17,
1522 0x20, 0x23, 0x25, 0x28, 0x30, 0x33, 0x35, 0x38};
1523
1524 static code unsigned char int2bcd_3[] = {
1525 0x00, 0x96, 0x92, 0x88, 0x84, 0x80, 0x76, 0x72,
1526 0x68, 0x64, 0x60, 0x56, 0x52, 0x48, 0x44, 0x40,
1527 0x00, 0x40, 0x81, 0x22, 0x63, 0x04, 0x45, 0x86,
1528 0x27, 0x68, 0x09, 0x50, 0x91, 0x32, 0x73, 0x14,
1529 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02,
1530 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06};
1531
1532 #ifdef LONG
1533 static code unsigned char int2bcd_4[] = {
1534 0x00, 0x36, 0x72, 0x08, 0x44, 0x80, 0x16, 0x52,
1535 0x88, 0x24, 0x60, 0x96, 0x32, 0x68, 0x04, 0x40,
1536 0x00, 0x55, 0x10, 0x66, 0x21, 0x76, 0x32, 0x87,
1537 0x42, 0x98, 0x53, 0x08, 0x64, 0x19, 0x75, 0x30,
1538 0x00, 0x06, 0x13, 0x19, 0x26, 0x32, 0x39, 0x45,
1539 0x52, 0x58, 0x65, 0x72, 0x78, 0x85, 0x91, 0x98};
1540
1541 static code unsigned char int2bcd_5[] = {
1542 0x00, 0x76, 0x52, 0x28, 0x04, 0x80, 0x56, 0x32,
1543 0x08, 0x84, 0x60, 0x36, 0x12, 0x88, 0x64, 0x40,
1544 0x00, 0x85, 0x71, 0x57, 0x43, 0x28, 0x14, 0x00,
1545 0x86, 0x71, 0x57, 0x43, 0x29, 0x14, 0x00, 0x86,
1546 0x00, 0x04, 0x09, 0x14, 0x19, 0x24, 0x29, 0x34,
1547 0x38, 0x43, 0x48, 0x53, 0x58, 0x63, 0x68, 0x72,
1548 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1549 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15};
1550
1551 static code unsigned char int2bcd_6[] = {
1552 0x00, 0x16, 0x32, 0x48, 0x64, 0x80, 0x96, 0x12,
1553 0x28, 0x44, 0x60, 0x76, 0x92, 0x08, 0x24, 0x40,
1554 0x00, 0x72, 0x44, 0x16, 0x88, 0x60, 0x32, 0x05,
1555 0x77, 0x49, 0x21, 0x93, 0x65, 0x38, 0x10, 0x82,
1556 0x00, 0x77, 0x55, 0x33, 0x10, 0x88, 0x66, 0x44,
1557 0x21, 0x99, 0x77, 0x54, 0x32, 0x10, 0x88, 0x65,
1558 0x00, 0x16, 0x33, 0x50, 0x67, 0x83, 0x00, 0x17,
1559 0x34, 0x50, 0x67, 0x84, 0x01, 0x18, 0x34, 0x51,
1560 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
1561 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02};
1562
1563 static code unsigned char int2bcd_7[] = {
1564 0x00, 0x56, 0x12, 0x68, 0x24, 0x80, 0x36, 0x92,
1565 0x48, 0x04, 0x60, 0x16, 0x72, 0x28, 0x84, 0x40,
1566 0x00, 0x54, 0x09, 0x63, 0x18, 0x72, 0x27, 0x81,
1567 0x36, 0x91, 0x45, 0x00, 0x54, 0x09, 0x63, 0x18,
1568 0x00, 0x43, 0x87, 0x30, 0x74, 0x17, 0x61, 0x04,
1569 0x48, 0x91, 0x35, 0x79, 0x22, 0x66, 0x09, 0x53,
1570 0x00, 0x68, 0x36, 0x05, 0x73, 0x42, 0x10, 0x79,
1571 0x47, 0x15, 0x84, 0x52, 0x21, 0x89, 0x58, 0x26,
1572 0x00, 0x02, 0x05, 0x08, 0x10, 0x13, 0x16, 0x18,
1573 0x21, 0x24, 0x26, 0x29, 0x32, 0x34, 0x37, 0x40};
1574 #endif // LONG
1575
1576 #else // not FAST_INTEGER
1577
1578 /*
1579  * #! /usr/bin/perl
1580  * print "code unsigned char int2bcd[] = {\n";
1581  * for ($i=0, $n=1; $i<32; $i++, $n*=2) {
1582  *      $r = sprintf "%010u", $n;
1583  *      $r =~ /([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])/;
1584  *      printf "0x%02d, 0x%02d, 0x%02d, 0x%02d, 0x%02d", $5, $4, $3, $2, $1;
1585  *      print ',' if $i < 31;
1586  *      printf "\t\t// %10u\n", $n;
1587  * }
1588  * print "}\ncode unsigned char int2bcd[] = {\n";
1589  * for ($i=0, $n=1; $i<16; $i++, $n*=2) {
1590  *      $r = sprintf "%06u", $n;
1591  *      $r =~ /([0-9][0-9])([0-9][0-9])([0-9][0-9])/;
1592  *      printf "0x%02d, 0x%02d, 0x%02d", $3, $2, $1;
1593  *      print ',' if $i < 15;
1594  *      printf "\t\t// %10u\n", $n;
1595  * }
1596  * print "};\n";
1597 */
1598
1599 #ifdef LONG
1600 static code unsigned char int2bcd[] = {
1601 0x01, 0x00, 0x00, 0x00, 0x00,           //          1
1602 0x02, 0x00, 0x00, 0x00, 0x00,           //          2
1603 0x04, 0x00, 0x00, 0x00, 0x00,           //          4
1604 0x08, 0x00, 0x00, 0x00, 0x00,           //          8
1605 0x16, 0x00, 0x00, 0x00, 0x00,           //         16
1606 0x32, 0x00, 0x00, 0x00, 0x00,           //         32
1607 0x64, 0x00, 0x00, 0x00, 0x00,           //         64
1608 0x28, 0x01, 0x00, 0x00, 0x00,           //        128
1609 0x56, 0x02, 0x00, 0x00, 0x00,           //        256
1610 0x12, 0x05, 0x00, 0x00, 0x00,           //        512
1611 0x24, 0x10, 0x00, 0x00, 0x00,           //       1024
1612 0x48, 0x20, 0x00, 0x00, 0x00,           //       2048
1613 0x96, 0x40, 0x00, 0x00, 0x00,           //       4096
1614 0x92, 0x81, 0x00, 0x00, 0x00,           //       8192
1615 0x84, 0x63, 0x01, 0x00, 0x00,           //      16384
1616 0x68, 0x27, 0x03, 0x00, 0x00,           //      32768
1617 0x36, 0x55, 0x06, 0x00, 0x00,           //      65536
1618 0x72, 0x10, 0x13, 0x00, 0x00,           //     131072
1619 0x44, 0x21, 0x26, 0x00, 0x00,           //     262144
1620 0x88, 0x42, 0x52, 0x00, 0x00,           //     524288
1621 0x76, 0x85, 0x04, 0x01, 0x00,           //    1048576
1622 0x52, 0x71, 0x09, 0x02, 0x00,           //    2097152
1623 0x04, 0x43, 0x19, 0x04, 0x00,           //    4194304
1624 0x08, 0x86, 0x38, 0x08, 0x00,           //    8388608
1625 0x16, 0x72, 0x77, 0x16, 0x00,           //   16777216
1626 0x32, 0x44, 0x55, 0x33, 0x00,           //   33554432
1627 0x64, 0x88, 0x10, 0x67, 0x00,           //   67108864
1628 0x28, 0x77, 0x21, 0x34, 0x01,           //  134217728
1629 0x56, 0x54, 0x43, 0x68, 0x02,           //  268435456
1630 0x12, 0x09, 0x87, 0x36, 0x05,           //  536870912
1631 0x24, 0x18, 0x74, 0x73, 0x10,           // 1073741824
1632 0x48, 0x36, 0x48, 0x47, 0x21            // 2147483648
1633 };
1634 #else // not LONG
1635 static code unsigned char int2bcd[] = {
1636 0x01, 0x00, 0x00,               //          1
1637 0x02, 0x00, 0x00,               //          2
1638 0x04, 0x00, 0x00,               //          4
1639 0x08, 0x00, 0x00,               //          8
1640 0x16, 0x00, 0x00,               //         16
1641 0x32, 0x00, 0x00,               //         32
1642 0x64, 0x00, 0x00,               //         64
1643 0x28, 0x01, 0x00,               //        128
1644 0x56, 0x02, 0x00,               //        256
1645 0x12, 0x05, 0x00,               //        512
1646 0x24, 0x10, 0x00,               //       1024
1647 0x48, 0x20, 0x00,               //       2048
1648 0x96, 0x40, 0x00,               //       4096
1649 0x92, 0x81, 0x00,               //       8192
1650 0x84, 0x63, 0x01,               //      16384
1651 0x68, 0x27, 0x03                //      32768
1652 };
1653 #endif // not LONG
1654
1655 #endif // not FAST_INTEGER
1656
1657
1658
1659
1660 #ifdef FLOAT
1661 #ifndef FLOAT_FIXED4
1662
1663 /*
1664  * #! /usr/bin/perl
1665  * for ($i=0, $f=0.5; $i<24; $i++) {
1666  *      $r = sprintf "%.8f", $f;
1667  *      $r =~ /0\.([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])/;
1668  *      printf "0x%02d, 0x%02d, 0x%02d, 0x%02d", $4, $3, $2, $1;
1669  *      print ',' if $i < 23;
1670  *      $sum += $r;
1671  *      printf "\t\t// %.15f  %.8f\n", $f, $sum;
1672  *      $f /= 2;
1673  * }
1674  */
1675
1676 static code unsigned char frac2bcd[] = {
1677 0x00, 0x00, 0x00, 0x50,         // 0.500000000000000  0.50000000
1678 0x00, 0x00, 0x00, 0x25,         // 0.250000000000000  0.75000000
1679 0x00, 0x00, 0x50, 0x12,         // 0.125000000000000  0.87500000
1680 0x00, 0x00, 0x25, 0x06,         // 0.062500000000000  0.93750000
1681 0x00, 0x50, 0x12, 0x03,         // 0.031250000000000  0.96875000
1682 0x00, 0x25, 0x56, 0x01,         // 0.015625000000000  0.98437500
1683 0x50, 0x12, 0x78, 0x00,         // 0.007812500000000  0.99218750
1684 0x25, 0x06, 0x39, 0x00,         // 0.003906250000000  0.99609375
1685 0x12, 0x53, 0x19, 0x00,         // 0.001953125000000  0.99804687
1686 0x56, 0x76, 0x09, 0x00,         // 0.000976562500000  0.99902343
1687 0x28, 0x88, 0x04, 0x00,         // 0.000488281250000  0.99951171
1688 0x14, 0x44, 0x02, 0x00,         // 0.000244140625000  0.99975585
1689 0x07, 0x22, 0x01, 0x00,         // 0.000122070312500  0.99987792
1690 0x04, 0x61, 0x00, 0x00,         // 0.000061035156250  0.99993896
1691 0x52, 0x30, 0x00, 0x00,         // 0.000030517578125  0.99996948
1692 0x26, 0x15, 0x00, 0x00,         // 0.000015258789062  0.99998474
1693 0x63, 0x07, 0x00, 0x00,         // 0.000007629394531  0.99999237
1694 0x81, 0x03, 0x00, 0x00,         // 0.000003814697266  0.99999618
1695 0x91, 0x01, 0x00, 0x00,         // 0.000001907348633  0.99999809
1696 0x95, 0x00, 0x00, 0x00,         // 0.000000953674316  0.99999904
1697 0x48, 0x00, 0x00, 0x00,         // 0.000000476837158  0.99999952
1698 0x24, 0x00, 0x00, 0x00,         // 0.000000238418579  0.99999976
1699 0x12, 0x00, 0x00, 0x00,         // 0.000000119209290  0.99999988
1700 0x06, 0x00, 0x00, 0x00,         // 0.000000059604645  0.99999994
1701 0x03, 0x00, 0x00, 0x00,         // 0.000000029802322  0.99999997
1702 0x01, 0x00, 0x00, 0x00,         // 0.000000014901161  0.99999998
1703 0x01, 0x00, 0x00, 0x00          // 0.000000007450581  0.99999999
1704 };
1705
1706 #ifndef FLOAT_DEFAULT_FRAC_DIGITS
1707 // TODO: Perhaps these should be tweaked a bit to take round up
1708 // effects into account... or maybe give more default digits??
1709 // Range                #digits
1710 // 0.0001 - 0.0009999   7
1711 // 0.001 - 0.009999     6       0.001 = 0x3A83126F  3A83
1712 // 0.01 - 0.09999       5       0.01  = 0x3C23D70A  3C23
1713 // 0.1 - 9.9999         4       0.1   = 0x3DCCCCCD, 3DCC
1714 // 10.0 - 99.99         3       10.0  = 0x41200000  4120
1715 // 100.0 - 999.99       2       100.0 = 0x42C80000  42C8
1716 // 1000 - 9999.9        1       1000  = 0x447A0000  447A
1717 // 10000+               0       10000 = 0x461C4000  461C
1718 static code unsigned int float_range_table[] = {
1719 65536 - 0x3A83,
1720 65536 - 0x3C23,
1721 65536 - 0x3DCC,
1722 65536 - 0x4120,
1723 65536 - 0x42C8,
1724 65536 - 0x447A,
1725 65536 - 0x461C
1726 };
1727 #endif
1728
1729 #else // using FLOAT_FIXED4
1730
1731 /*
1732 * #! /usr/bin/perl
1733 *     for ($i=0, $f=0.5; $i<14; $i++) {
1734 *     $r = sprintf "%.4f", $f;
1735 *     $r =~ /0\.([0-9][0-9])([0-9][0-9])/;
1736 *     printf "0x%02d, 0x%02d", $2, $1;
1737 *     print ',' if $i < 13;
1738 *     $sum += $r;
1739 *     printf "\t\t// %.15f  %.4f\n", $f, $sum;
1740 *     $f /= 2;
1741 * }
1742 */
1743
1744 static code unsigned char frac2bcd[] = {
1745 0x00, 0x50,             // 0.500000000000000  0.5000
1746 0x00, 0x25,             // 0.250000000000000  0.7500
1747 0x50, 0x12,             // 0.125000000000000  0.8750
1748 0x25, 0x06,             // 0.062500000000000  0.9375
1749 0x12, 0x03,             // 0.031250000000000  0.9687
1750 0x56, 0x01,             // 0.015625000000000  0.9843
1751 0x78, 0x00,             // 0.007812500000000  0.9921
1752 0x39, 0x00,             // 0.003906250000000  0.9960
1753 0x20, 0x00,             // 0.001953125000000  0.9980
1754 0x10, 0x00,             // 0.000976562500000  0.9990
1755 0x05, 0x00,             // 0.000488281250000  0.9995
1756 0x02, 0x00,             // 0.000244140625000  0.9997
1757 0x01, 0x00,             // 0.000122070312500  0.9998
1758 0x01, 0x00              // 0.000061035156250  0.9999
1759 };
1760
1761 #endif // FLOAT_FIXED4
1762 #endif // FLOAT
1763
1764
1765 #endif // defines compatible with printf_fast
1766