- /*------------------------------------------------------------------------- 
-    printf_fast.c - Fast printf routine for use with sdcc/mcs51 
-   
-    Copyright (C) 2004, Paul Stoffregen, paul@pjrc.com 
-   
-    This library is free software; you can redistribute it and/or modify it 
-    under the terms of the GNU General Public License as published by the 
-    Free Software Foundation; either version 2, or (at your option) any 
-    later version. 
-   
-    This library is distributed in the hope that it will be useful, 
-    but WITHOUT ANY WARRANTY; without even the implied warranty of 
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
-    GNU General Public License for more details. 
-   
-    You should have received a copy of the GNU General Public License  
-    along with this library; see the file COPYING. If not, write to the 
-    Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, 
-    MA 02110-1301, USA. 
-   
-    As a special exception, if you link this library with other files, 
-    some of which are compiled with SDCC, to produce an executable, 
-    this library does not by itself cause the resulting executable to 
-    be covered by the GNU General Public License. This exception does 
-    not however invalidate any other reasons why the executable file 
-    might be covered by the GNU General Public License. 
- -------------------------------------------------------------------------*/ 
-   
- /******************************************************************/ 
- /**                                                              **/ 
- /**    Major features.  These determine what capabilities your   **/ 
- /**    compiled printf_fast will have.                           **/ 
- /**                                                              **/ 
- /******************************************************************/ 
-   
- // Include support for 32 bit base 10 integers (%ld and %lu).  Without 
- // this, you won't be able to print 32 bit integers as base 10.  They 
- // will appear in hexadecimal. 
- #define LONG 
-   
- // Include support for floating point numbers (%f).  Don't forget to 
- // enable LONG above, if you want to print floats greater than 
- // 65535.997.  You can have 6 good digits after the decimal point, 
- // or an 8th if a small error is ok.  +/- 2^32 to 1/10^8 isn't the 
- // full dynamic range of 32 bit floats, but it covers the most 
- // commonly used range.  Adds about 500-600 bytes of code. 
- //#define FLOAT 
-   
- // Include support for minimum field widths (%8d, %20s, %12.5f) 
- #define FIELD_WIDTH 
-   
- // Include fast integer conversion.  Without this, a compact but slower 
- // algorithm is used to convert integers (%d, %u, int part of %f). 
- // Even the slow algorithm is much faster than a typical C implementation 
- // based on repetitive division by 10.  If you enable this, you get an 
- // extremely fast version (only 8 table lookups and 8 adds to convert a 
- // 32 bit integer), but it costs extra code space for larger lookup 
- // tables and optimized non-looping code. 
- #define FAST_INTEGER 
-   
-   
- /******************************************************************/ 
- /**                                                              **/ 
- /**    Minor tweaks.  These provide small code savings, with     **/ 
- /**    a partial loss of functionality.                          **/ 
- /**                                                              **/ 
- /******************************************************************/ 
-   
-   
- // If you enabled FLOAT, enabling this replaces the normal %f float 
- // output with a very compact version that always prints 4 fractional 
- // digits and does not have round off.  Zero will print as "0.0000", 
- // and 1.999997 will print as "1.9999" (not rounded up to 2).  The 
- // 4th digit is not accurate (+/- 2).  This simpler version also 
- // avoids using 5 bytes of internal data memory.  Code size is about 
- // 240 bytes less. 
- //#define FLOAT_FIXED4 
-   
- // If you used FLOAT (not FLOAT_FIXED4), this will remove the smart 
- // default number of digits code.  When you use "%f" without a field 
- // width, normally the smart default width code chooses a good number 
- // of digits based on size of the number.  If you enabled FIELD_WIDTH 
- // and use a number, like "%.5f", this smart default code is never 
- // used anyway.  Saves about 40 bytes of code. 
- //#define FLOAT_DEFAULT_FRAC_DIGITS 6 
-   
- // If you used FLOAT (not FLOAT_FIXED4) and you do not specify a 
- // field width, normally trailing zeros are trimmed.  Using this 
- // removes that feature (saves only a few bytes). 
- //#define DO_NOT_TRIM_TRAILING_ZEROS 
-   
- // Omit saving and restoring registers when calling putchar().  If you 
- // are desparate for a little more code space, this will give you a 
- // small savings.  You MUST define putchar() with #pragma callee_saves, 
- // or implement it in assembly and avoid changing the registers. 
- //#define PUTCHAR_CALLEE_SAVES 
-   
-   
- /* extern void putchar(char ); */ 
-   
- // Warning: using static/global variables makes these functions NON-reentrant! 
- // reentrant keyword is only used for parameter passing method 
-   
- static __bit long_flag, short_flag, print_zero_flag, negative_flag; 
-   
- #ifdef FIELD_WIDTH 
- static __bit field_width_flag; 
- static __bit leading_zero_flag; 
- static __data unsigned char field_width; 
- #endif 
-   
- #ifdef FLOAT 
- #define __SDCC_FLOAT_LIB 
- #include <float.h> 
- static __bit continue_float; 
- #ifndef FLOAT_FIXED4 
- static __data unsigned char frac_field_width; 
- static __data unsigned char float_frac_bcd[4]; 
- // TODO: can float_frac_bcd be overlaid with temps used by trig functions 
- #endif 
- #endif 
-   
- #ifndef FAST_INTEGER 
- #ifdef LONG 
- static __data unsigned int i2bcd_tmp;  // slow 32 int conversion needs temp space 
- #endif 
- #endif 
-   
-   
- #ifndef PRINTF_FAST 
- #define PRINTF_FAST printf_fast 
- #endif 
-   
-   
- #if !defined(__SDCC_mcs51) || defined(__SDCC_USE_XSTACK) || defined(_SDCC_NO_ASM_LIB_FUNCS) 
- // Does printf_fast really work on ds390 and ds400? 
- // If it does, enable them in the line above 
- #if defined(__SDCC_USE_XSTACK) 
- #warning "printf_fast not built, does not support --xstack" 
- #elif defined(_SDCC_NO_ASM_LIB_FUNCS) 
- #warning "printf_fast not built, _SDCC_NO_ASM_LIB_FUNCS defined" 
- #endif 
- #else // defines are compatible with printf_fast 
-   
-   
- void PRINTF_FAST(__code const char *fmt, ...) __reentrant 
- { 
-         fmt;    /* suppress unreferenced variable warning */ 
-   
-         __asm 
-   
- printf_begin: 
-         mov     a, _bp          // r0 will point to va_args (stack) 
-         add     a, #253 
-         mov     r0, a           // r0 points to MSB of fmt 
-         mov     dph, @r0 
-         dec     r0 
-         mov     dpl, @r0        // dptr has address of fmt 
-         dec     r0 
-   
- printf_main_loop: 
-         clr     a 
-         movc    a, @a+dptr      // get next byte of fmt string 
-         inc     dptr 
-         //cjne  a, #'%', printf_normal 
-         cjne    a, #37, printf_normal 
-   
- printf_format: 
-         clr     _long_flag 
-         clr     _short_flag 
-         clr     _print_zero_flag 
-         clr     _negative_flag 
- #ifdef FIELD_WIDTH 
-         clr     _field_width_flag 
-         clr     _leading_zero_flag 
-         mov     r1, #_field_width 
-         mov     @r1, #0 
- #endif 
- #ifdef FLOAT 
-         clr     _continue_float 
- #endif 
-   
- printf_format_loop: 
-         clr     a 
-         movc    a, @a+dptr      // get next byte of data format 
-         inc     dptr 
-   
-         /* parse and consume the field width digits, even if */ 
-         /* we don't build the code to make use of them */ 
-         add     a, #198 
-         jc      printf_nondigit1 
-         add     a, #10 
-         jnc     printf_nondigit2 
- #ifdef FIELD_WIDTH 
- printf_digit: 
-         jnz     printf_digit_2 
-         cjne    a, _field_width, printf_digit_2 
-         setb    _leading_zero_flag 
- printf_digit_2: 
-         setb    _field_width_flag 
-         mov     r2, a 
-         mov     a, @r1 
-         mov     b, #10 
-         mul     ab 
-         add     a, r2 
-         mov     @r1, a 
- #endif 
-         sjmp    printf_format_loop 
- printf_nondigit1: 
-         add     a, #10 
- printf_nondigit2: 
-         add     a, #48 
-   
- printf_format_l: 
-         //cjne  a, #'l', printf_format_h 
-         cjne    a, #108, printf_format_h 
-         setb    _long_flag 
-         sjmp    printf_format_loop 
-   
- printf_format_h: 
-         //cjne  a, #'h', printf_format_s 
-         cjne    a, #104, printf_format_s 
-         setb    _short_flag 
-         sjmp    printf_format_loop 
-   
- printf_format_s: 
-         //cjne  a, #'s', printf_format_d 
-         cjne    a, #115, printf_format_d 
-         ljmp    printf_string 
-   
- printf_format_d: 
-         //cjne  a, #'d', printf_format_u 
-         cjne    a, #100, printf_format_u 
-         lcall   printf_get_int 
-         ljmp    printf_int 
-   
- printf_format_u: 
-         //cjne  a, #'u', printf_format_c 
-         cjne    a, #117, printf_format_c 
-         lcall   printf_get_int 
-         ljmp    printf_uint 
-   
- printf_format_c: 
-         //cjne  a, #'c', printf_format_x 
-         cjne    a, #99, printf_format_x 
-         dec     r0 
-         mov     a, @r0          // Acc has the character to print 
-         dec     r0 
-         sjmp    printf_char 
-   
- printf_format_x: 
-         //cjne  a, #'x', printf_format_f 
-         cjne    a, #120, printf_format_f 
-         ljmp    printf_hex 
-   
- printf_format_f: 
- #ifdef FLOAT 
-         //cjne  a, #'f', printf_format_dot 
-         cjne    a, #102, printf_format_dot 
-         ljmp    print_float 
- #endif 
-   
- printf_format_dot: 
-         //cjne  a, #'.', printf_normal 
-         cjne    a, #46, printf_normal 
- #ifdef FLOAT 
- #ifdef FLOAT_FIXED4 
-         mov     r1, #ar3        // parse frac field, but discard if FIXED4 
- #else 
-         mov     r1, #_frac_field_width 
-         mov     @r1, #0 
- #endif 
- #endif 
-         sjmp    printf_format_loop 
-   
- printf_normal: 
-         jz      printf_eot 
- printf_char: 
-         lcall   printf_putchar 
-         ljmp    printf_main_loop 
-   
- printf_eot: 
-         ljmp    printf_end 
-   
-   
-         /* print a string... just grab each byte with __gptrget */ 
-         /* the user much pass a 24 bit generic pointer */ 
-   
- printf_string: 
-         push    dph             // save addr in fmt onto stack 
-         push    dpl 
-         mov     b, @r0          // b has type of address (generic *) 
-         dec     r0 
-         mov     dph, @r0 
-         dec     r0 
-         mov     dpl, @r0        // dptr has address of user's string 
-         dec     r0 
-   
- #ifdef FIELD_WIDTH 
-         jnb     _field_width_flag, printf_str_loop 
-         clr     _leading_zero_flag      // never leading zeros for strings 
-         push    dpl 
-         push    dph 
- printf_str_fw_loop: 
-         lcall   __gptrget 
-         jz      printf_str_space 
-         inc     dptr 
-         dec     _field_width 
-         mov     a, _field_width 
-         jnz     printf_str_fw_loop 
- printf_str_space: 
-         lcall   printf_space 
-         pop     dph 
-         pop     dpl 
- #endif // FIELD_WIDTH 
-   
- printf_str_loop: 
-         lcall   __gptrget 
-         jz      printf_str_done 
-         inc     dptr 
-         lcall   printf_putchar 
-         sjmp    printf_str_loop 
- printf_str_done: 
-         pop     dpl             // restore addr withing fmt 
-         pop     dph 
-         ljmp    printf_main_loop 
-   
-   
-         /* printing in hex is easy because sdcc pushes the LSB first */ 
-   
- printf_hex: 
-         lcall   printf_hex8 
-         jb      _short_flag, printf_hex_end 
-         lcall   printf_hex8 
-         jnb     _long_flag, printf_hex_end 
-         lcall   printf_hex8 
-         lcall   printf_hex8 
- printf_hex_end: 
-         lcall   printf_zero 
-         ljmp    printf_main_loop 
- printf_hex8: 
-         mov     a, @r0 
-         lcall   printf_phex_msn 
-         mov     a, @r0 
-         dec     r0 
-         ljmp    printf_phex_lsn 
-   
-   
- #ifndef LONG 
- printf_ld_in_hex: 
-         //mov   a, #'0' 
-         mov     a, #48 
-         lcall   printf_putchar 
-         //mov   a, #'x' 
-         mov     a, #120 
-         lcall   printf_putchar 
-         mov     a, r0 
-         add     a, #4 
-         mov     r0, a 
-         sjmp    printf_hex 
- #endif 
-   
-   
-         /* printing an integer is not so easy.  For a signed int */ 
-         /* check if it is negative and print the minus sign and */ 
-         /* invert it to a positive integer */ 
-   
- printf_int: 
-         mov     a, r5 
-         jnb     acc.7, printf_uint      /* check if negative */ 
-         setb    _negative_flag 
-         mov     a, r1                   /* invert integer */ 
-         cpl     a 
-         add     a, #1 
-         mov     r1, a 
-         jb      _short_flag, printf_uint 
-         mov     a, r2 
-         cpl     a 
-         addc    a, #0 
-         mov     r2, a 
-         jnb     _long_flag, printf_uint 
-         mov     a, r3 
-         cpl     a 
-         addc    a, #0 
-         mov     r3, a 
-         mov     a, r4 
-         cpl     a 
-         addc    a, #0 
-         mov     r4, a 
-   
-   
-         /* printing integers is a lot of work... because it takes so */ 
-         /* long, the first thing to do is make sure we're doing as */ 
-         /* little work as possible, then convert the binary int to */ 
-         /* packed BCD, and finally print each digit of the BCD number */ 
-   
- printf_uint: 
-   
-         jb      _short_flag, printf_uint_ck8 
-         jnb     _long_flag, printf_uint_ck16 
- printf_uint_ck32: 
-         /* it's a 32 bit int... but if the upper 16 bits are zero */ 
-         /* we can treat it like a 16 bit integer and convert much faster */ 
- #ifdef LONG 
-         mov     a, r3 
-         jnz     printf_uint_begin 
-         mov     a, r4 
-         jnz     printf_uint_begin 
- #else 
-         mov     a, r3 
-         jnz     printf_ld_in_hex        // print long integer as hex 
-         mov     a, r4                   // rather than just the low 16 bits 
-         jnz     printf_ld_in_hex 
- #endif 
-         clr     _long_flag 
- printf_uint_ck16: 
-         /* it's a 16 bit int... but if the upper 8 bits are zero */ 
-         /* we can treat it like a 8 bit integer and convert much faster */ 
-         mov     a, r2 
-         jnz     printf_uint_begin 
-         setb    _short_flag 
- printf_uint_ck8: 
-         /* it's an 8 bit int... if it's zero, it's a lot faster to just */ 
-         /* print the digit zero and skip all the hard work! */ 
-         mov     a, r1 
-         jnz     printf_uint_begin 
- #ifdef FLOAT 
-         /* never use the "just print zero" shortcut if we're printing */ 
-         /* the integer part of a float  (fixes bug 1255403)  */ 
-         jb      _continue_float, printf_uint_begin 
- #endif 
- #ifdef FIELD_WIDTH 
-         jnb     _field_width_flag, printf_uint_zero 
-         mov     a, _field_width 
-         jz      printf_uint_zero 
-         dec     _field_width 
-         lcall   printf_space 
- #endif 
- printf_uint_zero: 
-         //mov   a, #'0' 
-         mov     a, #48 
-         lcall   printf_putchar 
-         ljmp    printf_main_loop 
-   
- printf_uint_begin: 
-         push    dpl 
-         push    dph 
-         lcall   printf_int2bcd          // bcd number in r3/r2/r7/r6/r5 
- printf_uint_2: 
-   
- #ifdef FIELD_WIDTH 
-         jnb     _field_width_flag, printf_uifw_end 
- #ifdef LONG 
- printf_uifw_32: 
-         mov     r1, #10 
-         jnb     _long_flag, printf_uifw_16 
-         mov     a, r3 
-         anl     a, #0xF0 
-         jnz     printf_uifw_sub 
-         dec     r1 
-         mov     a, r3 
-         anl     a, #0x0F 
-         jnz     printf_uifw_sub 
-         dec     r1 
-         mov     a, r2 
-         anl     a, #0xF0 
-         jnz     printf_uifw_sub 
-         dec     r1 
-         mov     a, r2 
-         anl     a, #0x0F 
-         jnz     printf_uifw_sub 
-         dec     r1 
-         mov     a, r7 
-         anl     a, #0xF0 
-         jnz     printf_uifw_sub 
- #endif // LONG 
- printf_uifw_16: 
-         mov     r1, #5 
-         jb      _short_flag, printf_uifw_8 
-         mov     a, r7 
-         anl     a, #0x0F 
-         jnz     printf_uifw_sub 
-         dec     r1 
-         mov     a, r6 
-         anl     a, #0xF0 
-         jnz     printf_uifw_sub 
- printf_uifw_8: 
-         mov     r1, #3 
-         mov     a, r6 
-         anl     a, #0x0F 
-         jnz     printf_uifw_sub 
-         dec     r1 
-         mov     a, r5 
-         anl     a, #0xF0 
-         jnz     printf_uifw_sub 
-         dec     r1 
- printf_uifw_sub: 
-         //r1 has the number of digits for the number 
-         mov     a, _field_width 
-         mov     c, _negative_flag 
-         subb    a, r1 
-         jc      printf_uifw_end 
-         mov     _field_width, a 
-   
- #ifndef PUTCHAR_CALLEE_SAVES 
- #ifdef LONG 
-         push    ar3 
-         push    ar2 
- #endif 
-         push    ar7 
-         push    ar6 
-         push    ar5 
- #endif 
-         lcall   printf_space 
- #ifndef PUTCHAR_CALLEE_SAVES 
-         pop     ar5 
-         pop     ar6 
-         pop     ar7 
- #ifdef LONG 
-         pop     ar2 
-         pop     ar3 
- #endif 
- #endif 
-   
-   
- printf_uifw_end: 
- #endif // FIELD_WIDTH 
-   
-   
- printf_uint_doit: 
-         jnb     _negative_flag, printf_uint_pos 
- #ifdef PUTCHAR_CALLEE_SAVES 
-         //mov   a, #'-' 
-         mov     a, #45 
-         lcall   printf_putchar 
- #else 
- #ifdef LONG 
-         push    ar3 
-         push    ar2 
- #endif 
-         push    ar7 
-         push    ar6 
-         push    ar5 
-         //mov   a, #'-' 
-         mov     a, #45 
-         lcall   printf_putchar 
-         pop     ar5 
-         pop     ar6 
-         pop     ar7 
- #ifdef LONG 
-         pop     ar2 
-         pop     ar3 
- #endif 
- #endif // PUTCHAR_CALLEE_SAVES 
-   
- printf_uint_pos: 
-         jb      _short_flag, printf_uint8 
- #ifdef LONG 
-         jnb     _long_flag, printf_uint16 
- printf_uint32: 
-         push    ar5 
-         push    ar6 
-         push    ar7 
-         mov     dpl, r2 
-         mov     a, r3 
-         mov     dph, a 
-         lcall   printf_phex_msn 
-         mov     a, dph 
-         lcall   printf_phex_lsn 
-         mov     a, dpl 
-         lcall   printf_phex_msn 
-         mov     a, dpl 
-         lcall   printf_phex_lsn 
-         pop     acc 
-         mov     dpl, a 
-         lcall   printf_phex_msn 
-         mov     a, dpl 
-         pop     dph 
-         pop     dpl 
-         sjmp    printf_uint16a 
- #endif // LONG 
-   
- printf_uint16: 
-         mov     dpl, r5 
-         mov     dph, r6 
-         mov     a, r7 
- printf_uint16a: 
-         lcall   printf_phex_lsn 
-         mov     a, dph 
-         lcall   printf_phex_msn 
-         mov     a, dph 
-         sjmp    printf_uint8a 
-   
- printf_uint8: 
-         mov     dpl, r5 
-         mov     a, r6 
- printf_uint8a: 
-         lcall   printf_phex_lsn 
-         mov     a, dpl 
-         lcall   printf_phex_msn 
-         mov     a, dpl 
-         lcall   printf_phex_lsn 
-         lcall   printf_zero 
-         pop     dph 
-         pop     dpl 
- #ifdef FLOAT 
-         jnb     _continue_float, 0002$ 
-         ret 
- 0002$: 
- #endif 
-         ljmp    printf_main_loop 
-   
-   
- #ifdef FLOAT 
- #ifdef FLOAT_FIXED4 
-         // Print a float the easy way.  First, extract the integer part and 
-         // use the integer printing code.  Then extract the fractional part, 
-         // convert each bit to 4 digit BCD, and print the BCD sum.  Absolutely 
-         // no field width control, always 4 digits printed past the decimal 
-         // point.  No round off.  1.9999987 prints as 1.9999, not 2.0000. 
- print_float: 
- #ifdef FIELD_WIDTH 
-         jnb     _field_width_flag, print_float_begin 
-         mov     a, _field_width 
-         add     a, #251 
-         mov     _field_width, a 
-         jc      print_float_begin 
-         mov     _field_width, #0 
- #endif 
- print_float_begin: 
-         push    ar0             // keep r0 safe, will need it again 
-         lcall   printf_get_float 
-         clr     c 
-         mov     a, #158                 // check for large float we can't print 
-         subb    a, r7 
-         jnc     print_float_size_ok 
- printf_float_too_big: 
-         // TODO: should print some sort of overflow error?? 
-         pop     ar0 
-         ljmp    printf_format_loop 
- print_float_size_ok: 
-         push    dpl 
-         lcall   fs_rshift_a 
-         pop     dpl 
-         setb    _continue_float 
- #ifndef LONG 
-         mov     a, r3 
-         orl     a, r4 
-         jnz     printf_float_too_big 
- #endif 
-         lcall   printf_uint             // print the integer portion 
-         //mov   a, #'.' 
-         mov     a, #0x2E 
-         lcall   printf_putchar 
-         // now that the integer part is printed, we need to refetch the 
-         // float from the va_args and extract the fractional part 
-         pop     ar0 
-         lcall   printf_get_float 
-         push    ar0 
-         push    dpl 
-         push    dph 
-         mov     a, r7 
-         cjne    a, #126, print_float_frac_lshift 
-         sjmp    print_float_frac // input between 0.5 to 0.9999 
- print_float_frac_lshift: 
-         jc      print_float_frac_rshift 
-         //Acc (exponent) is greater than 126 (input >= 1.0) 
-         add     a, #130 
-         mov     r5, a 
- print_float_lshift_loop: 
-         clr     c 
-         mov     a, r2 
-         rlc     a 
-         mov     r2, a 
-         mov     a, r3 
-         rlc     a 
-         mov     r3, a 
-         mov     a, r4 
-         rlc     a 
-         mov     r4, a 
-         djnz    r5, print_float_lshift_loop 
-         sjmp    print_float_frac 
- print_float_frac_rshift: 
-         //Acc (exponent) is less than 126 (input < 0.5) 
-         cpl     a 
-         add     a, #127 
-         lcall   fs_rshift_a 
- print_float_frac: 
-         // now we've got the fractional part, so now is the time to 
-         // convert to BCD... just convert each bit to BCD using a 
-         // lookup table and BCD sum them together 
-         mov     r7, #14 
-         clr     a 
-         mov     r6, a 
-         mov     r5, a 
-         mov     dptr, #_frac2bcd        // FLOAT_FIXED4 version (14 entries) 
- print_float_frac_loop: 
-         mov     a, r3 
-         rlc     a 
-         mov     r3, a 
-         mov     a, r4 
-         rlc     a 
-         mov     r4, a 
-         jnc     print_float_frac_skip 
-         clr     a 
-         movc    a, @a+dptr 
-         add     a, r5 
-         da      a 
-         mov     r5, a 
-         mov     a, #1 
-         movc    a, @a+dptr 
-         addc    a, r6 
-         da      a 
-         mov     r6, a 
- print_float_frac_skip: 
-         inc     dptr 
-         inc     dptr 
-         djnz    r7, print_float_frac_loop 
-         // the BCD sum is in dptr, so all we've got to do is output 
-         // all 4 digits.  No trailing zero suppression, no nice round 
-         // off (impossible to change the integer part since we already 
-         // printed it). 
-         mov     dph, r6 
-         mov     dpl, r5 
-         setb    _print_zero_flag 
-         mov     a, dph 
-         lcall   printf_phex_msn 
-         mov     a, dph 
-         lcall   printf_phex_lsn 
-         mov     a, dpl 
-         lcall   printf_phex_msn 
-         mov     a, dpl 
-         lcall   printf_phex_lsn 
-         pop     dph 
-         pop     dpl 
-         pop     ar0 
-         ljmp    printf_main_loop 
-   
- #else // not FLOAT_FIXED4 
-   
-   
- print_float: 
-         // Print a float the not-as-easy way, with a configurable number of 
-         // fractional digits (up to 8) and proper round-off (up to 7 digits). 
-         // First, extract the fractional part, convert to BCD, and then add 
-         // the scaled round-off.  Store the rounded fractional digits and 
-         // their carry.  Then extract the integer portion, increment it if 
-         // the rounding caused a carry.  Use the integer printing to output 
-         // the integer, and then output the stored fractional digits.  This 
-         // approach requires 5 bytes of internal RAM to store the 8 fractional 
-         // digits and the number of them we'll actually print.  This code is 
-         // a couple hundred bytes larger and a bit slower than the FIXED4 
-         // version, but it gives very nice results. 
- print_float_1: 
- #ifdef FIELD_WIDTH 
-         jnb     _field_width_flag, print_float_default_width 
-         // The caller specified exact field width, so use it.  Need to 
-         // convert the whole float digits into the integer portion only. 
-         mov     a, _field_width 
-         setb    c 
-         subb    a, _frac_field_width 
-         mov     _field_width, a 
-         jnc     print_float_begin 
-         mov     _field_width, #0 
-         sjmp    print_float_begin 
- #endif 
- print_float_default_width: 
-         // The caller didn't specify field width (or FIELD_WIDTH is 
-         // not defined so it's ignored).  We've still got to know 
-         // how many fractional digits are going to print, so we can 
-         // round off properly. 
- #ifdef FLOAT_DEFAULT_FRAC_DIGITS 
-         mov     _frac_field_width, #FLOAT_DEFAULT_FRAC_DIGITS 
- #else 
-         // default fractional field width (between 0 to 7) 
-         // attempt to scale the default number of fractional digits 
-         // based on the magnitude of the float 
-         mov     a, @r0 
-         anl     a, #0x7F        // ignore sign bit 
-         mov     r2, a           // r2 is first byte of float 
-         dec     r0 
-         mov     ar3, @r0        // r3 is second byte of float 
-         inc     r0 
-         mov     r6, dpl 
-         mov     r7, dph 
-         mov     dptr, #_float_range_table 
-         mov     r5, #7 
- print_float_default_loop: 
-         clr     a 
-         movc    a, @a+dptr 
-         add     a, r3 
-         inc     dptr 
-         clr     a 
-         movc    a, @a+dptr 
-         addc    a, r2 
-         jnc     print_float_default_done 
-         inc     dptr 
-         djnz    r5, print_float_default_loop 
- print_float_default_done: 
-         mov     _frac_field_width, r5 
-         mov     dpl, r6 
-         mov     dph, r7 
- #endif // not FLOAT_DEFAULT_FRAC_DIGITS 
-   
- print_float_begin: 
-         push    ar0                     // keep r0 safe, will need it again 
-         lcall   printf_get_float 
-         push    dpl 
-         push    dph 
-         mov     a, r7 
-         cjne    a, #126, print_float_frac_lshift 
-         sjmp    print_float_frac        // input between 0.5 to 0.9999 
-   
- print_float_frac_lshift: 
-         jc      print_float_frac_rshift 
-         //Acc (exponent) is greater than 126 (input >= 1.0) 
-         add     a, #130 
-         mov     r5, a 
- print_float_lshift_loop: 
-         clr     c 
-         mov     a, r2 
-         rlc     a 
-         mov     r2, a 
-         mov     a, r3 
-         rlc     a 
-         mov     r3, a 
-         mov     a, r4 
-         rlc     a 
-         mov     r4, a 
-         djnz    r5, print_float_lshift_loop 
-         sjmp    print_float_frac 
- print_float_frac_rshift: 
-         //Acc (exponent) is less than 126 (input < 0.5) 
-         cpl     a 
-         add     a, #127 
-         lcall   fs_rshift_a 
- print_float_frac: 
-         // Convert the fraction in r4/r3/r2/r1 into 8 BCD digits in r0/r7/r6/r5 
-         mov     b, #27 
-         clr     a 
-         mov     r0, a 
-         mov     r7, a 
-         mov     r6, a 
-         mov     r5, a 
-         mov     dptr, #_frac2bcd        // FLOAT version (27 entries) 
- print_float_frac_loop: 
-         mov     a, r1 
-         rlc     a 
-         mov     r1, a 
-         mov     a, r2 
-         rlc     a 
-         mov     r2, a 
-         mov     a, r3 
-         rlc     a 
-         mov     r3, a 
-         mov     a, r4 
-         rlc     a 
-         mov     r4, a 
-         jnc     print_float_frac_skip 
-         clr     a 
-         movc    a, @a+dptr 
-         add     a, r5 
-         da      a 
-         mov     r5, a 
-         mov     a, #1 
-         movc    a, @a+dptr 
-         addc    a, r6 
-         da      a 
-         mov     r6, a 
-         mov     a, #2 
-         movc    a, @a+dptr 
-         addc    a, r7 
-         da      a 
-         mov     r7, a 
-         mov     a, #3 
-         movc    a, @a+dptr 
-         addc    a, r0 
-         da      a 
-         mov     r0, a 
- print_float_frac_skip: 
-         inc     dptr 
-         inc     dptr 
-         inc     dptr 
-         inc     dptr 
-         djnz    b, print_float_frac_loop 
- print_float_frac_roundoff: 
-         // Now it's time to round-off the BCD digits to the desired precision. 
-         clr     a 
-         mov     r4, #0x50               // r4/r3/r2/r1 = 0.5 (bcd rounding) 
-         mov     r3, a 
-         mov     r2, a 
-         mov     r1, a 
-         mov     a, _frac_field_width 
-         rl      a 
-         rl      a 
-         anl     a, #0xFC 
-         mov     dph, r0                 // fs_rshift_a will overwrite r0 & dpl 
-         lcall   fs_rshift_a             // divide r4/r3/r2/r1 by 10^frac_field_width 
-         mov     a, r5 
-         add     a, r1                   // add rounding to fractional part 
-         da      a 
-         mov     _float_frac_bcd+3, a    // and store it for later use 
-         mov     a, r6 
-         addc    a, r2 
-         da      a 
-         mov     _float_frac_bcd+2, a 
-         mov     a, r7 
-         addc    a, r3 
-         da      a 
-         mov     _float_frac_bcd+1, a 
-         mov     a, dph 
-         addc    a, r4 
-         da      a 
-         mov     _float_frac_bcd+0, a 
-         mov     sign_b, c               // keep fractional carry in sign_b 
-         pop     dph 
-         pop     dpl 
- print_float_int: 
-         // Time to work on the integer portion... fetch the float again, check 
-         // size (exponent), scale to integer, add the fraction's carry, and 
-         // let the integer printing code do all the work. 
-         pop     ar0 
-         lcall   printf_get_float 
-         push    ar0 
-         clr     c 
-         mov     a, #158                 // check for large float we can't print 
-         subb    a, r7 
-         jnc     print_float_size_ok 
- printf_float_too_big: 
-         // TODO: should print some sort of overflow error?? 
-         pop     ar0 
-         ljmp    printf_format_loop 
- print_float_size_ok: 
-         push    dpl 
-         lcall   fs_rshift_a 
-         pop     dpl 
-         jnb     sign_b, print_float_do_int 
-         // if we get here, the fractional round off caused the 
-         // integer part to increment.  Add 1 for a proper result 
-         mov     a, r1 
-         add     a, #1 
-         mov     r1, a 
-         clr     a 
-         addc    a, r2 
-         mov     r2, a 
- #ifdef LONG 
-         clr     a 
-         addc    a, r3 
-         mov     r3, a 
-         clr     a 
-         addc    a, r4 
-         mov     r4, a 
- #endif 
-         jc      printf_float_too_big 
- print_float_do_int: 
- #ifndef LONG 
-         mov     a, r3 
-         orl     a, r4 
-         jnz     printf_float_too_big 
- #endif 
-         setb    _continue_float 
-         lcall   printf_uint             // print the integer portion 
-   
-   
- print_float_frac_width: 
-         // Now all we have to do is output the fractional digits that 
-         // were previous computed and stored in memory. 
- #ifdef FIELD_WIDTH 
-         jb      _field_width_flag, print_float_do_frac 
- #endif 
- #ifndef DO_NOT_TRIM_TRAILING_ZEROS  
-         // if the user did not explicitly set a 
-         // field width, trim off trailing zeros 
- print_float_frac_trim: 
-         mov     a, _frac_field_width 
-         jz      print_float_do_frac 
-         lcall   get_float_frac_digit 
-         jnz     print_float_do_frac 
-         djnz    _frac_field_width, print_float_frac_trim 
- #endif 
-   
- print_float_do_frac: 
-         mov     a, _frac_field_width 
-         jz      print_float_done 
-         //mov   a, #'.' 
-         mov     a, #0x2E 
-         lcall   printf_putchar 
-         mov     r0, #0 
-         setb    _print_zero_flag 
- print_float_do_frac_loop: 
-         inc     r0 
-         mov     a, r0 
-         lcall   get_float_frac_digit 
-         lcall   printf_phex_lsn 
-         mov     a, r0 
-         cjne    a, _frac_field_width, print_float_do_frac_loop 
-   
- print_float_done: 
-         pop     ar0 
-         ljmp    printf_main_loop 
-   
-   
-         // acc=1 for tenths, acc=2 for hundredths, etc 
- get_float_frac_digit: 
-         dec     a 
-         clr     c 
-         rrc     a 
-         mov     psw.5, c 
-         add     a, #_float_frac_bcd 
-         mov     r1, a 
-         mov     a, @r1 
-         jb      psw.5, get_float_frac_digit_done 
-         swap    a 
- get_float_frac_digit_done: 
-         anl     a, #15 
-         ret 
-   
- #endif // end of normal FLOAT code (not FLOAT_FIXED4) 
-   
-   
- // These helper functions are used, regardless of which type of 
- // FLOAT code is used. 
-   
- #if 0 
- pm2_print_float: 
-          mov    a, r7 
-          lcall  pm2_entry_phex 
-          mov    a, #0x20 
-          lcall  pm2_entry_cout 
-          lcall  _print_r4321 
-          mov    a, #0x20 
-          lcall  pm2_entry_cout 
-          ret 
- #endif 
-   
-         // Fetch a float from the va_args and put it into 
-         // r7(exp) r4/r3/r2(mant) and also clear r1 and preset 
-         // the flags 
- printf_get_float: 
-         mov     a, @r0 
-         dec     r0 
-         mov     r1, a 
-         mov     a, @r0 
-         dec     r0 
-         mov     r4, a 
-         rlc     a 
-         mov     a, r1 
-         rlc     a 
-         mov     _negative_flag, c 
-         mov     r7, a 
-         jz      printf_get_float_2 
-         orl     ar4, #0x80 
- printf_get_float_2: 
-         mov     a, @r0 
-         dec     r0 
-         mov     r3, a 
-         mov     a, @r0 
-         dec     r0 
-         mov     r2, a 
-         mov     r1, #0 
-         clr     _short_flag 
-         setb    _long_flag 
-         ret 
- #endif // FLOAT 
-   
-   
-         /* read an integer into r1/r2/r3/r4, and msb into r5 */ 
- printf_get_int: 
-         mov     a, @r0 
-         mov     r1, a 
-         mov     r5, a 
-         dec     r0 
-         jb      _short_flag, printf_get_done 
-         mov     r2, ar1 
-         mov     a, @r0 
-         mov     r1, a 
-         dec     r0 
-         jnb     _long_flag, printf_get_done 
-         mov     r4, ar2 
-         mov     r3, ar1 
-         mov     a, @r0 
-         mov     r2, a 
-         dec     r0 
-         mov     a, @r0 
-         mov     r1, a 
-         dec     r0 
- printf_get_done: 
-         ret 
-   
-   
- #ifdef FAST_INTEGER 
-   
-         /* convert binary number in r4/r3/r2/r1 into bcd packed number 
-          * in r3/r2/r7/r6/r5.  The input number is destroyed in the 
-          * process, to avoid needing extra memory for the result (and 
-          * r1 gets used for temporary storage).  dptr is overwritten, 
-          * but r0 is not changed. 
-          */ 
-   
- printf_int2bcd: 
-         mov     a, r1 
-         mov     b, #100 
-         mov     r6, a 
-         mov     a, #10 
-         xch     a, b 
-         swap    a 
-         orl     a, b 
-         mov     r5, a 
-   
-         jnb     _short_flag, printf_i2bcd_16    // if 8 bit int, we're done 
-         ret 
-   
- printf_i2bcd_16: 
-         mov     a, r2 
-         anl     a, #0x0F 
-         mov     r1, a 
-         mov     dptr, #_int2bcd_2 
-         movc    a, @a+dptr 
-         add     a, r5 
-         da      a 
-         mov     r5, a 
-         mov     a, r1 
-         orl     a, #16 
-         movc    a, @a+dptr 
-         addc    a, r6 
-         da      a 
-         mov     r6, a 
-   
-         mov     a, r2 
-         swap    a 
-         anl     a, #0x0F 
-         mov     r1, a 
-         mov     dptr, #_int2bcd_3 
-         movc    a, @a+dptr 
-         add     a, r5 
-         da      a 
-         mov     r5, a 
-         mov     a, r1 
-         orl     a, #16 
-         movc    a, @a+dptr 
-         addc    a, r6 
-         da      a 
-         mov     r6, a 
-         mov     a, r1 
-         orl     a, #32 
-         movc    a, @a+dptr 
-         addc    a, #0 
-         da      a 
-         mov     r7, a 
-   
-         jb      _long_flag, printf_i2bcd_32     // if 16 bit int, we're done 
-         ret 
-   
- printf_i2bcd_32: 
-   
- #ifdef LONG 
-         mov     a, r3 
-         anl     a, #0x0F 
-         mov     r1, a 
-         mov     dptr, #_int2bcd_4 
-         movc    a, @a+dptr 
-         add     a, r5 
-         da      a 
-         mov     r5, a 
-         mov     a, r1 
-         orl     a, #16 
-         movc    a, @a+dptr 
-         addc    a, r6 
-         da      a 
-         mov     r6, a 
-         mov     a, r1 
-         orl     a, #32 
-         movc    a, @a+dptr 
-         addc    a, r7 
-         da      a 
-         mov     r7, a 
-         clr     a 
-         addc    a, #0 
-         mov     r2, a 
-   
-         mov     a, r3 
-         swap    a 
-         anl     a, #0x0F 
-         mov     r1, a 
-         mov     dptr, #_int2bcd_5 
-         movc    a, @a+dptr 
-         add     a, r5 
-         da      a 
-         mov     r5, a 
-         mov     a, r1 
-         orl     a, #16 
-         movc    a, @a+dptr 
-         addc    a, r6 
-         da      a 
-         mov     r6, a 
-         mov     a, r1 
-         orl     a, #32 
-         movc    a, @a+dptr 
-         addc    a, r7 
-         da      a 
-         mov     r7, a 
-         mov     a, r1 
-         orl     a, #48 
-         movc    a, @a+dptr 
-         addc    a, r2 
-         da      a 
-         mov     r2, a 
-   
-         mov     a, r4 
-         anl     a, #0x0F 
-         mov     r1, a 
-         mov     dptr, #_int2bcd_6 
-         mov     r3, #0 
-         lcall   printf_bcd_add10        // saves 27 bytes, costs 5 cycles 
-   
-         mov     a, r4 
-         swap    a 
-         anl     a, #0x0F 
-         mov     r1, a 
-         mov     dptr, #_int2bcd_7 
- printf_bcd_add10: 
-         movc    a, @a+dptr 
-         add     a, r5 
-         da      a 
-         mov     r5, a 
-         mov     a, r1 
-         orl     a, #16 
-         movc    a, @a+dptr 
-         addc    a, r6 
-         da      a 
-         mov     r6, a 
-         mov     a, r1 
-         orl     a, #32 
-         movc    a, @a+dptr 
-         addc    a, r7 
-         da      a 
-         mov     r7, a 
-         mov     a, r1 
-         orl     a, #48 
-         movc    a, @a+dptr 
-         addc    a, r2 
-         da      a 
-         mov     r2, a 
-         mov     a, r1 
-         orl     a, #64 
-         movc    a, @a+dptr 
-         addc    a, r3 
-         da      a 
-         mov     r3, a 
- #endif // LONG 
-         ret 
-   
-   
- #else // not FAST_INTEGER 
-   
-         /* convert binary number in r4/r3/r2/r1 into bcd packed number 
-          * in r3/r2/r7/r6/r5.  The input number is destroyed in the 
-          * process, to avoid needing extra memory for the result (and 
-          * r1 gets used for temporary storage).  dptr is overwritten, 
-          * but r0 is not changed. 
-          */ 
-   
- #ifdef LONG 
-   
- printf_int2bcd: 
-         mov     a, #8 
-         jb      _short_flag, printf_int2bcd_begin 
-         mov     a, #16 
-         jnb     _long_flag, printf_int2bcd_begin 
-         mov     a, #32 
- printf_int2bcd_begin: 
-         mov     b, a 
-         clr     a 
-         mov     r5, a 
-         mov     r6, a 
-         mov     r7, a 
-         mov     (_i2bcd_tmp + 0), a 
-         mov     (_i2bcd_tmp + 1), a 
-         mov     dptr, #_int2bcd 
- printf_i2bcd_loop: 
-         mov     a, r4 
-         rrc     a 
-         mov     r4, a 
-         mov     a, r3 
-         rrc     a 
-         mov     r3, a 
-         mov     a, r2 
-         rrc     a 
-         mov     r2, a 
-         mov     a, r1 
-         rrc     a 
-         mov     r1, a 
-         jnc     print_i2bcd_skip 
-         clr     a 
-         movc    a, @a+dptr 
-         add     a, r5 
-         da      a 
-         mov     r5, a 
-         mov     a, #1 
-         movc    a, @a+dptr 
-         addc    a, r6 
-         da      a 
-         mov     r6, a 
-         mov     a, #2 
-         movc    a, @a+dptr 
-         addc    a, r7 
-         da      a 
-         mov     r7, a 
-         mov     a, #3 
-         movc    a, @a+dptr 
-         addc    a, (_i2bcd_tmp + 0) 
-         da      a 
-         mov     (_i2bcd_tmp + 0), a 
-         mov     a, #4 
-         movc    a, @a+dptr 
-         addc    a, (_i2bcd_tmp + 1) 
-         da      a 
-         mov     (_i2bcd_tmp + 1), a 
- print_i2bcd_skip: 
-         inc     dptr 
-         inc     dptr 
-         inc     dptr 
-         inc     dptr 
-         inc     dptr 
-         djnz    b, printf_i2bcd_loop 
-         mov     r2, (_i2bcd_tmp + 0) 
-         mov     r3, (_i2bcd_tmp + 1) 
-         ret 
-   
- #else //  not LONG 
-   
- printf_int2bcd: 
-         mov     a, #8 
-         jb      _short_flag, printf_int2bcd_begin 
-         mov     a, #16 
- printf_int2bcd_begin: 
-         mov     b, a 
-         clr     a 
-         mov     r5, a 
-         mov     r6, a 
-         mov     r7, a 
-         mov     dptr, #_int2bcd 
- printf_i2bcd_loop: 
-         mov     a, r2 
-         rrc     a 
-         mov     r2, a 
-         mov     a, r1 
-         rrc     a 
-         mov     r1, a 
-         jnc     printf_i2bcd_add_skip 
-         clr     a 
-         movc    a, @a+dptr 
-         add     a, r5 
-         da      a 
-         mov     r5, a 
-         mov     a, #1 
-         movc    a, @a+dptr 
-         addc    a, r6 
-         da      a 
-         mov     r6, a 
-         mov     a, #2 
-         movc    a, @a+dptr 
-         addc    a, r7 
-         da      a 
-         mov     r7, a 
- printf_i2bcd_add_skip: 
-         inc     dptr 
-         inc     dptr 
-         inc     dptr 
-         djnz    b, printf_i2bcd_loop 
-         ret 
-   
- #endif // not LONG 
-   
-   
- #endif // not FAST_INTEGER 
-   
-   
- #ifdef FIELD_WIDTH 
- printf_space_loop: 
-         //mov   a, #' ' 
-         mov     a, #32 
-         jnb     _leading_zero_flag, printf_space_output 
-         //mov   a, #'0' 
-         mov     a, #48 
- printf_space_output: 
-         lcall   printf_putchar 
-         dec     _field_width 
- printf_space: 
-         mov     a, _field_width 
-         jnz     printf_space_loop 
-         ret 
- #endif 
-   
-         /* print a hex digit, either upper 4 bit (msn) or lower 4 bits (lsn) */ 
-   
- printf_phex_msn: 
-         swap    a 
- printf_phex_lsn: 
-         anl     a, #15 
-         jnz     printf_phex_ok 
-         jnb     _print_zero_flag, printf_ret 
- printf_phex_ok: 
-         setb    _print_zero_flag 
-         add     a, #0x90 
-         da      a 
-         addc    a, #0x40 
-         da      a 
- printf_putchar: 
- #ifdef PUTCHAR_CALLEE_SAVES 
-         push    dph 
-         push    dpl 
-         mov     dpl, a 
-         lcall   _putchar 
-         pop     dpl 
-         pop     dph 
- #else 
-         push    dph 
-         push    dpl 
-         push    ar0 
-         mov     dpl, a 
-         lcall   _putchar 
-         pop     ar0 
-         pop     dpl 
-         pop     dph 
- #endif 
- printf_ret: 
-         ret 
-   
-         /* print a zero if all the calls to print the digits ended up */ 
-         /* being leading zeros */ 
-   
- printf_zero: 
-         jb      _print_zero_flag, printf_ret 
-         //mov   a, #'0' 
-         mov     a, #48 
-         ljmp    printf_putchar 
-    
- printf_end: 
-         __endasm; 
- } 
-   
-   
- #ifdef FAST_INTEGER 
- /* 
-  * #! /usr/bin/perl 
-  * for ($d=0; $d < 8; $d++) { 
-  *      $n = 16 ** $d; 
-  *      for ($p=0; $p < 5; $p++) { 
-  *              last unless (((16 ** $d) * 15) / (10 ** ($p * 2))) % 100; 
-  *              printf "code unsigned char int2bcd_%d_%d[15] = {", $d, $p; 
-  *              for ($i=0; $i < 16; $i++) { 
-  *                      printf "0x%02d", 
-  *                         (((16 ** $d) * $i) / (10 ** ($p * 2))) % 100; 
-  *                      print ", " if $i < 15; 
-  *              } 
-  *              print "};\n"; 
-  *      } 
-  * } 
-  */ 
-   
- #if 0 
- static __code unsigned char int2bcd_0[] = { 
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
- 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15}; 
-   
- static __code unsigned char int2bcd_1[] = { 
- 0x00, 0x16, 0x32, 0x48, 0x64, 0x80, 0x96, 0x12, 
- 0x28, 0x44, 0x60, 0x76, 0x92, 0x08, 0x24, 0x40, 
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02}; 
- #endif 
-   
- static __code unsigned char int2bcd_2[] = { 
- 0x00, 0x56, 0x12, 0x68, 0x24, 0x80, 0x36, 0x92, 
- 0x48, 0x04, 0x60, 0x16, 0x72, 0x28, 0x84, 0x40, 
- 0x00, 0x02, 0x05, 0x07, 0x10, 0x12, 0x15, 0x17, 
- 0x20, 0x23, 0x25, 0x28, 0x30, 0x33, 0x35, 0x38}; 
-   
- static __code unsigned char int2bcd_3[] = { 
- 0x00, 0x96, 0x92, 0x88, 0x84, 0x80, 0x76, 0x72, 
- 0x68, 0x64, 0x60, 0x56, 0x52, 0x48, 0x44, 0x40, 
- 0x00, 0x40, 0x81, 0x22, 0x63, 0x04, 0x45, 0x86, 
- 0x27, 0x68, 0x09, 0x50, 0x91, 0x32, 0x73, 0x14, 
- 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 
- 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06}; 
-   
- #ifdef LONG 
- static __code unsigned char int2bcd_4[] = { 
- 0x00, 0x36, 0x72, 0x08, 0x44, 0x80, 0x16, 0x52, 
- 0x88, 0x24, 0x60, 0x96, 0x32, 0x68, 0x04, 0x40, 
- 0x00, 0x55, 0x10, 0x66, 0x21, 0x76, 0x32, 0x87, 
- 0x42, 0x98, 0x53, 0x08, 0x64, 0x19, 0x75, 0x30, 
- 0x00, 0x06, 0x13, 0x19, 0x26, 0x32, 0x39, 0x45, 
- 0x52, 0x58, 0x65, 0x72, 0x78, 0x85, 0x91, 0x98}; 
-   
- static __code unsigned char int2bcd_5[] = { 
- 0x00, 0x76, 0x52, 0x28, 0x04, 0x80, 0x56, 0x32, 
- 0x08, 0x84, 0x60, 0x36, 0x12, 0x88, 0x64, 0x40, 
- 0x00, 0x85, 0x71, 0x57, 0x43, 0x28, 0x14, 0x00, 
- 0x86, 0x71, 0x57, 0x43, 0x29, 0x14, 0x00, 0x86, 
- 0x00, 0x04, 0x09, 0x14, 0x19, 0x24, 0x29, 0x34, 
- 0x38, 0x43, 0x48, 0x53, 0x58, 0x63, 0x68, 0x72, 
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
- 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15}; 
-   
- static __code unsigned char int2bcd_6[] = { 
- 0x00, 0x16, 0x32, 0x48, 0x64, 0x80, 0x96, 0x12, 
- 0x28, 0x44, 0x60, 0x76, 0x92, 0x08, 0x24, 0x40, 
- 0x00, 0x72, 0x44, 0x16, 0x88, 0x60, 0x32, 0x05, 
- 0x77, 0x49, 0x21, 0x93, 0x65, 0x38, 0x10, 0x82, 
- 0x00, 0x77, 0x55, 0x33, 0x10, 0x88, 0x66, 0x44, 
- 0x21, 0x99, 0x77, 0x54, 0x32, 0x10, 0x88, 0x65, 
- 0x00, 0x16, 0x33, 0x50, 0x67, 0x83, 0x00, 0x17, 
- 0x34, 0x50, 0x67, 0x84, 0x01, 0x18, 0x34, 0x51, 
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 
- 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02}; 
-   
- static __code unsigned char int2bcd_7[] = { 
- 0x00, 0x56, 0x12, 0x68, 0x24, 0x80, 0x36, 0x92, 
- 0x48, 0x04, 0x60, 0x16, 0x72, 0x28, 0x84, 0x40, 
- 0x00, 0x54, 0x09, 0x63, 0x18, 0x72, 0x27, 0x81, 
- 0x36, 0x91, 0x45, 0x00, 0x54, 0x09, 0x63, 0x18, 
- 0x00, 0x43, 0x87, 0x30, 0x74, 0x17, 0x61, 0x04, 
- 0x48, 0x91, 0x35, 0x79, 0x22, 0x66, 0x09, 0x53, 
- 0x00, 0x68, 0x36, 0x05, 0x73, 0x42, 0x10, 0x79, 
- 0x47, 0x15, 0x84, 0x52, 0x21, 0x89, 0x58, 0x26, 
- 0x00, 0x02, 0x05, 0x08, 0x10, 0x13, 0x16, 0x18, 
- 0x21, 0x24, 0x26, 0x29, 0x32, 0x34, 0x37, 0x40}; 
- #endif // LONG 
-   
- #else // not FAST_INTEGER 
-   
- /* 
-  * #! /usr/bin/perl 
-  * print "__code unsigned char int2bcd[] = {\n"; 
-  * for ($i=0, $n=1; $i<32; $i++, $n*=2) { 
-  *      $r = sprintf "%010u", $n; 
-  *      $r =~ /([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])/; 
-  *      printf "0x%02d, 0x%02d, 0x%02d, 0x%02d, 0x%02d", $5, $4, $3, $2, $1; 
-  *      print ',' if $i < 31; 
-  *      printf "\t\t// %10u\n", $n; 
-  * } 
-  * print "}\n__code unsigned char int2bcd[] = {\n"; 
-  * for ($i=0, $n=1; $i<16; $i++, $n*=2) { 
-  *      $r = sprintf "%06u", $n; 
-  *      $r =~ /([0-9][0-9])([0-9][0-9])([0-9][0-9])/; 
-  *      printf "0x%02d, 0x%02d, 0x%02d", $3, $2, $1; 
-  *      print ',' if $i < 15; 
-  *      printf "\t\t// %10u\n", $n; 
-  * } 
-  * print "};\n"; 
- */ 
-   
- #ifdef LONG 
- static __code unsigned char int2bcd[] = { 
- 0x01, 0x00, 0x00, 0x00, 0x00,           //          1 
- 0x02, 0x00, 0x00, 0x00, 0x00,           //          2 
- 0x04, 0x00, 0x00, 0x00, 0x00,           //          4 
- 0x08, 0x00, 0x00, 0x00, 0x00,           //          8 
- 0x16, 0x00, 0x00, 0x00, 0x00,           //         16 
- 0x32, 0x00, 0x00, 0x00, 0x00,           //         32 
- 0x64, 0x00, 0x00, 0x00, 0x00,           //         64 
- 0x28, 0x01, 0x00, 0x00, 0x00,           //        128 
- 0x56, 0x02, 0x00, 0x00, 0x00,           //        256 
- 0x12, 0x05, 0x00, 0x00, 0x00,           //        512 
- 0x24, 0x10, 0x00, 0x00, 0x00,           //       1024 
- 0x48, 0x20, 0x00, 0x00, 0x00,           //       2048 
- 0x96, 0x40, 0x00, 0x00, 0x00,           //       4096 
- 0x92, 0x81, 0x00, 0x00, 0x00,           //       8192 
- 0x84, 0x63, 0x01, 0x00, 0x00,           //      16384 
- 0x68, 0x27, 0x03, 0x00, 0x00,           //      32768 
- 0x36, 0x55, 0x06, 0x00, 0x00,           //      65536 
- 0x72, 0x10, 0x13, 0x00, 0x00,           //     131072 
- 0x44, 0x21, 0x26, 0x00, 0x00,           //     262144 
- 0x88, 0x42, 0x52, 0x00, 0x00,           //     524288 
- 0x76, 0x85, 0x04, 0x01, 0x00,           //    1048576 
- 0x52, 0x71, 0x09, 0x02, 0x00,           //    2097152 
- 0x04, 0x43, 0x19, 0x04, 0x00,           //    4194304 
- 0x08, 0x86, 0x38, 0x08, 0x00,           //    8388608 
- 0x16, 0x72, 0x77, 0x16, 0x00,           //   16777216 
- 0x32, 0x44, 0x55, 0x33, 0x00,           //   33554432 
- 0x64, 0x88, 0x10, 0x67, 0x00,           //   67108864 
- 0x28, 0x77, 0x21, 0x34, 0x01,           //  134217728 
- 0x56, 0x54, 0x43, 0x68, 0x02,           //  268435456 
- 0x12, 0x09, 0x87, 0x36, 0x05,           //  536870912 
- 0x24, 0x18, 0x74, 0x73, 0x10,           // 1073741824 
- 0x48, 0x36, 0x48, 0x47, 0x21            // 2147483648 
- }; 
- #else // not LONG 
- static __code unsigned char int2bcd[] = { 
- 0x01, 0x00, 0x00,               //          1 
- 0x02, 0x00, 0x00,               //          2 
- 0x04, 0x00, 0x00,               //          4 
- 0x08, 0x00, 0x00,               //          8 
- 0x16, 0x00, 0x00,               //         16 
- 0x32, 0x00, 0x00,               //         32 
- 0x64, 0x00, 0x00,               //         64 
- 0x28, 0x01, 0x00,               //        128 
- 0x56, 0x02, 0x00,               //        256 
- 0x12, 0x05, 0x00,               //        512 
- 0x24, 0x10, 0x00,               //       1024 
- 0x48, 0x20, 0x00,               //       2048 
- 0x96, 0x40, 0x00,               //       4096 
- 0x92, 0x81, 0x00,               //       8192 
- 0x84, 0x63, 0x01,               //      16384 
- 0x68, 0x27, 0x03                //      32768 
- }; 
- #endif // not LONG 
-   
- #endif // not FAST_INTEGER 
-   
-   
- #ifdef FLOAT 
- #ifndef FLOAT_FIXED4 
-   
- /* 
-  * #! /usr/bin/perl 
-  * for ($i=0, $f=0.5; $i<24; $i++) { 
-  *      $r = sprintf "%.8f", $f; 
-  *      $r =~ /0\.([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])/; 
-  *      printf "0x%02d, 0x%02d, 0x%02d, 0x%02d", $4, $3, $2, $1; 
-  *      print ',' if $i < 23; 
-  *      $sum += $r; 
-  *      printf "\t\t// %.15f  %.8f\n", $f, $sum; 
-  *      $f /= 2; 
-  * } 
-  */ 
-   
- static __code unsigned char frac2bcd[] = { 
- 0x00, 0x00, 0x00, 0x50,         // 0.500000000000000  0.50000000 
- 0x00, 0x00, 0x00, 0x25,         // 0.250000000000000  0.75000000 
- 0x00, 0x00, 0x50, 0x12,         // 0.125000000000000  0.87500000 
- 0x00, 0x00, 0x25, 0x06,         // 0.062500000000000  0.93750000 
- 0x00, 0x50, 0x12, 0x03,         // 0.031250000000000  0.96875000 
- 0x00, 0x25, 0x56, 0x01,         // 0.015625000000000  0.98437500 
- 0x50, 0x12, 0x78, 0x00,         // 0.007812500000000  0.99218750 
- 0x25, 0x06, 0x39, 0x00,         // 0.003906250000000  0.99609375 
- 0x12, 0x53, 0x19, 0x00,         // 0.001953125000000  0.99804687 
- 0x56, 0x76, 0x09, 0x00,         // 0.000976562500000  0.99902343 
- 0x28, 0x88, 0x04, 0x00,         // 0.000488281250000  0.99951171 
- 0x14, 0x44, 0x02, 0x00,         // 0.000244140625000  0.99975585 
- 0x07, 0x22, 0x01, 0x00,         // 0.000122070312500  0.99987792 
- 0x04, 0x61, 0x00, 0x00,         // 0.000061035156250  0.99993896 
- 0x52, 0x30, 0x00, 0x00,         // 0.000030517578125  0.99996948 
- 0x26, 0x15, 0x00, 0x00,         // 0.000015258789062  0.99998474 
- 0x63, 0x07, 0x00, 0x00,         // 0.000007629394531  0.99999237 
- 0x81, 0x03, 0x00, 0x00,         // 0.000003814697266  0.99999618 
- 0x91, 0x01, 0x00, 0x00,         // 0.000001907348633  0.99999809 
- 0x95, 0x00, 0x00, 0x00,         // 0.000000953674316  0.99999904 
- 0x48, 0x00, 0x00, 0x00,         // 0.000000476837158  0.99999952 
- 0x24, 0x00, 0x00, 0x00,         // 0.000000238418579  0.99999976 
- 0x12, 0x00, 0x00, 0x00,         // 0.000000119209290  0.99999988 
- 0x06, 0x00, 0x00, 0x00,         // 0.000000059604645  0.99999994 
- 0x03, 0x00, 0x00, 0x00,         // 0.000000029802322  0.99999997 
- 0x01, 0x00, 0x00, 0x00,         // 0.000000014901161  0.99999998 
- 0x01, 0x00, 0x00, 0x00          // 0.000000007450581  0.99999999 
- }; 
-   
- #ifndef FLOAT_DEFAULT_FRAC_DIGITS 
- // TODO: Perhaps these should be tweaked a bit to take round up 
- // effects into account... or maybe give more default digits?? 
- // Range                #digits 
- // 0.0001 - 0.0009999   7 
- // 0.001 - 0.009999     6       0.001 = 0x3A83126F  3A83 
- // 0.01 - 0.09999       5       0.01  = 0x3C23D70A  3C23 
- // 0.1 - 9.9999         4       0.1   = 0x3DCCCCCD, 3DCC 
- // 10.0 - 99.99         3       10.0  = 0x41200000  4120 
- // 100.0 - 999.99       2       100.0 = 0x42C80000  42C8 
- // 1000 - 9999.9        1       1000  = 0x447A0000  447A 
- // 10000+               0       10000 = 0x461C4000  461C 
- static __code unsigned int float_range_table[] = { 
- 65536 - 0x3A83, 
- 65536 - 0x3C23, 
- 65536 - 0x3DCC, 
- 65536 - 0x4120, 
- 65536 - 0x42C8, 
- 65536 - 0x447A, 
- 65536 - 0x461C 
- }; 
- #endif 
-   
- #else // using FLOAT_FIXED4 
-   
- /* 
- * #! /usr/bin/perl 
- *     for ($i=0, $f=0.5; $i<14; $i++) { 
- *     $r = sprintf "%.4f", $f; 
- *     $r =~ /0\.([0-9][0-9])([0-9][0-9])/; 
- *     printf "0x%02d, 0x%02d", $2, $1; 
- *     print ',' if $i < 13; 
- *     $sum += $r; 
- *     printf "\t\t// %.15f  %.4f\n", $f, $sum; 
- *     $f /= 2; 
- * } 
- */ 
-   
- static __code unsigned char frac2bcd[] = { 
- 0x00, 0x50,             // 0.500000000000000  0.5000 
- 0x00, 0x25,             // 0.250000000000000  0.7500 
- 0x50, 0x12,             // 0.125000000000000  0.8750 
- 0x25, 0x06,             // 0.062500000000000  0.9375 
- 0x12, 0x03,             // 0.031250000000000  0.9687 
- 0x56, 0x01,             // 0.015625000000000  0.9843 
- 0x78, 0x00,             // 0.007812500000000  0.9921 
- 0x39, 0x00,             // 0.003906250000000  0.9960 
- 0x20, 0x00,             // 0.001953125000000  0.9980 
- 0x10, 0x00,             // 0.000976562500000  0.9990 
- 0x05, 0x00,             // 0.000488281250000  0.9995 
- 0x02, 0x00,             // 0.000244140625000  0.9997 
- 0x01, 0x00,             // 0.000122070312500  0.9998 
- 0x01, 0x00              // 0.000061035156250  0.9999 
- }; 
-   
- #endif // FLOAT_FIXED4 
- #endif // FLOAT 
-   
-   
- #endif // defines compatible with printf_fast 
-