* support/regression/ports/mcs51-xstack-auto/spec.mk: forgot -I(...)/mcs51
[fw/sdcc] / device / lib / printf_large.c
index ac621e036baef50e235a34e4c2bc2a6840b5d24e..ba43fd546cb52ccbf93a8765cf46e7d3c0b022e5 100644 (file)
    what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 
-#ifdef SDCC_STACK_AUTO
-  #ifdef ASM_ALLOWED
-    /* Eventually we should get rid of ASM_ALLOWED completely as it   */
-    /* prevents portability, clobbers this source and brings only 2%  */
-    /* optimization. A better alternative is a completely handcrafted */
-    /* asm version if needed. */
-    #undef ASM_ALLOWED
-  #endif
-#endif
-
 #if defined(__ds390)
 #define USE_FLOATS 1
 #endif
@@ -43,6 +33,7 @@
 #include <ctype.h>
 #include <stdio.h>
 #include <stdbool.h>
+#include <sdcc-lib.h>
 
 #define PTR value.ptr
 
@@ -78,15 +69,7 @@ static const char memory_id[] = "IXCP-";
   static BOOL lower_case;
   static pfn_outputchar output_char;
   static void* p;
-
-  #ifdef ASM_ALLOWED
-    static bool   lsd;
-
-    /* this one NEEDS to be in data */
-    static data value_t value;
-  #else
-    static value_t value;
-  #endif
+  static value_t value;
 #endif
 
 /****************************************************************************/
@@ -121,52 +104,20 @@ static const char memory_id[] = "IXCP-";
 
 /*--------------------------------------------------------------------------*/
 
-#if defined ASM_ALLOWED
-static void calculate_digit( unsigned char radix )
-{
-  unsigned char i;
-
-  for( i = 32; i != 0; i-- )
-  {
-_asm
-  clr  c
-  mov  a,_value+0
-  rlc  a
-  mov  _value+0,a
-  mov  a,_value+1
-  rlc  a
-  mov  _value+1,a
-  mov  a,_value+2
-  rlc  a
-  mov  _value+2,a
-  mov  a,_value+3
-  rlc  a
-  mov  _value+3,a
-  mov  a,_value+4
-  rlc  a
-  mov  _value+4,a
-_endasm;
-    if (radix <= value.byte[4] )
-    {
-      value.byte[4] -= radix;
-      value.byte[0]++;
-    }
-  }
-}
-#elif defined SDCC_STACK_AUTO
+#if defined SDCC_STACK_AUTO
 static void calculate_digit( value_t* value, unsigned char radix )
 {
   unsigned char i;
 
   for( i = 32; i != 0; i-- )
   {
-    value->byte[4] = (value->byte[4] << 1) | (value->ul >> 31) & 0x01;
+    value->byte[4] = (value->byte[4] << 1) | ((value->ul >> 31) & 0x01);
     value->ul <<= 1;
 
     if (radix <= value->byte[4] )
     {
       value->byte[4] -= radix;
-      value->byte[0]++;
+      value->ul |= 1;
     }
   }
 }
@@ -177,13 +128,13 @@ static void calculate_digit( unsigned char radix )
 
   for( i = 32; i != 0; i-- )
   {
-    value.byte[4] = (value.byte[4] << 1) | (value.ul >> 31) & 0x01;
+    value.byte[4] = (value.byte[4] << 1) | ((value.ul >> 31) & 0x01);
     value.ul <<= 1;
 
     if (radix <= value.byte[4] )
     {
       value.byte[4] -= radix;
-      value.byte[0]++;
+      value.ul |= 1;
     }
   }
 }
@@ -214,7 +165,7 @@ static int output_float (float f, unsigned char reqWidth,
                          BOOL left, BOOL zero, BOOL sign, BOOL space)
 #endif
 {
-  char negative=0;
+  BOOL negative=0;
   unsigned long integerPart;
   float decimalPart;
   char fpBuffer[128];
@@ -278,14 +229,19 @@ static int output_float (float f, unsigned char reqWidth,
 
   // fill buffer with the decimalPart (in normal order)
   fpBD=fpBI;
-  if (i=reqDecimals /* that's an assignment */) {
-    do {
+
+  for (i=reqDecimals; i>1; i--) {
       decimalPart *= 10.0;
       // truncate the float
       integerPart=decimalPart;
       fpBuffer[fpBD++]='0' + integerPart;
       decimalPart-=integerPart;
-    } while (--i);
+  }
+  if (i) {
+    decimalPart *= 10.0;
+    // truncate the float
+    integerPart = decimalPart + 0.5;
+    fpBuffer[fpBD++] = '0' + integerPart;
   }
 
   minWidth=fpBI; // we need at least these
@@ -399,9 +355,7 @@ int _print_format (pfn_outputchar pfn, void* pvoid, const char *format, va_list
   BOOL   lower_case;
   value_t value;
 #endif
-#ifndef ASM_ALLOWED
   BOOL   lsd;
-#endif
 
   unsigned char radix;
   int charsOutputted;
@@ -515,6 +469,10 @@ get_conversion_spec:
 #else
         length = strlen(PTR);
 #endif
+        if ( decimals == -1 )
+        {
+          decimals = length;
+        }
         if ( ( !left_justify ) && (length < width) )
         {
           width -= length;
@@ -525,7 +483,7 @@ get_conversion_spec:
           }
         }
 
-        while ( *PTR )
+        while ( *PTR  && (decimals-- > 0))
         {
           output_char( *PTR++, p );
           charsOutputted++;
@@ -622,7 +580,8 @@ get_conversion_spec:
       {
         // Apperently we have to output an integral type
         // with radix "radix"
-        unsigned char store = 0;
+        unsigned char store[6];
+        unsigned char _AUTOMEM *pstore = &store[5];
 
         // store value in byte[0] (LSB) ... byte[3] (MSB)
         if (char_argument)
@@ -630,9 +589,7 @@ get_conversion_spec:
           value.l = va_arg(ap,char);
           if (!signed_argument)
           {
-            value.byte[1] = 0x00;
-            value.byte[2] = 0x00;
-            value.byte[3] = 0x00;
+            value.l &= 0xFF;
           }
         }
         else if (long_argument)
@@ -644,8 +601,7 @@ get_conversion_spec:
           value.l = va_arg(ap,int);
           if (!signed_argument)
           {
-            value.byte[2] = 0x00;
-            value.byte[3] = 0x00;
+            value.l &= 0xFFFF;
           }
         }
 
@@ -667,34 +623,18 @@ get_conversion_spec:
 #else
           calculate_digit(radix);
 #endif
-#if defined ASM_ALLOWED
-_asm
-  jb   _lsd,1$
-  pop  b                ; b = <lsd>
-  mov  a,_value+4       ; a = <msd>
-  swap a
-  orl  b,a              ; b = <msd><lsd>
-  push b
-  sjmp 2$
-1$:
-  mov  a,_value+4       ; a = <lsd>
-  push acc
-2$:
-_endasm;
-#else
           if (!lsd)
           {
-            store = (value.byte[4] << 4) | (value.byte[4] >> 4) | store;
+            *pstore = (value.byte[4] << 4) | (value.byte[4] >> 4) | *pstore;
+            pstore--;
           }
           else
           {
-            store = value.byte[4];
+            *pstore = value.byte[4];
           }
-#endif
           length++;
           lsd = !lsd;
-        } while( (value.byte[0] != 0) || (value.byte[1] != 0) ||
-                 (value.byte[2] != 0) || (value.byte[3] != 0) );
+        } while( value.ul );
 
         if (width == 0)
         {
@@ -761,31 +701,15 @@ _endasm;
         while( length-- )
         {
           lsd = !lsd;
-#ifdef ASM_ALLOWED
-_asm
-  jb   _lsd,3$
-  pop  acc              ; a = <msd><lsd>
-  nop                   ; to disable the "optimizer"
-  push acc
-  swap a
-  anl  a,#0x0F          ; a = <msd>
-  sjmp 4$
-3$:
-  pop  acc
-  anl  a,#0x0F          ; a = <lsd>
-4$:
-  mov  _value+4,a
-_endasm;
-#else
           if (!lsd)
           {
-            value.byte[4] = store >> 4;
+            pstore++;
+            value.byte[4] = *pstore >> 4;
           }
           else
           {
-            value.byte[4] = store & 0x0F;
+            value.byte[4] = *pstore & 0x0F;
           }
-#endif
 #ifdef SDCC_STACK_AUTO
           output_digit( value.byte[4], lower_case, output_char, p );
 #else