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