Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /****************************************************************************
  2. *
  3. *                            Open Watcom Project
  4. *
  5. *    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
  6. *
  7. *  ========================================================================
  8. *
  9. *    This file contains Original Code and/or Modifications of Original
  10. *    Code as defined in and that are subject to the Sybase Open Watcom
  11. *    Public License version 1.0 (the 'License'). You may not use this file
  12. *    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
  13. *    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
  14. *    provided with the Original Code and Modifications, and is also
  15. *    available at www.sybase.com/developer/opensource.
  16. *
  17. *    The Original Code and all software distributed under the License are
  18. *    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  19. *    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
  20. *    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
  21. *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
  22. *    NON-INFRINGEMENT. Please see the License for the specific language
  23. *    governing rights and limitations under the License.
  24. *
  25. *  ========================================================================
  26. *
  27. * Description:  Long long integer to ASCII conversion routines.
  28. *
  29. ****************************************************************************/
  30.  
  31.  
  32. #include "variety.h"
  33. #include "widechar.h"
  34. #include "watcom.h"
  35. #include "clibi64.h"
  36. #include <stdlib.h>
  37.  
  38. extern const char __based(__segname("_CONST")) __Alphabet[];
  39.  
  40. #if defined(__386__) || defined(M_I86)
  41. unsigned long long __ulldiv( unsigned long long, unsigned _WCNEAR *);
  42. #if defined(__386__)
  43.     #pragma aux __ulldiv = \
  44.         "xor ecx,ecx"     /* set high word of quotient to 0 */ \
  45.         "cmp edx,dword ptr[ebx]" /* if quotient will be >= 4G */ \
  46.         "jb less4g"       /* then */ \
  47.         "mov ecx,eax"     /* - save low word of dividend */ \
  48.         "mov eax,edx"     /* - get high word of dividend */ \
  49.         "xor edx,edx"     /* - zero high part */ \
  50.         "div dword ptr[ebx]"  /* - divide into high part of dividend */ \
  51.         "xchg eax,ecx"    /* - swap high part of quot,low word of dvdnd */ \
  52.       "less4g:"           \
  53.         "div dword ptr[ebx]" /* calculate low part */ \
  54.         "mov [ebx],edx"   /* store remainder */ \
  55.         parm [eax edx] [ebx] value [eax ecx];
  56. #elif defined(M_I86)  && defined(__BIG_DATA__)
  57.     #pragma aux __ulldiv = \
  58.         "mov di,dx"        /* initial dividend = ax:bx:cx:dx(di); save dx */ \
  59.         "test ax,ax"       /* less work to do if ax == 0 */ \
  60.         "jz skip1"  \
  61.         "mov dx,ax"        /* dx:ax = ax:bx */ \
  62.         "mov ax,bx" \
  63.         "xor bx,bx"           /* set word 3 of quotient to 0 */ \
  64.         "cmp dx,word ptr ss:[si]" /* if quotient will be >= 64K */ \
  65.         "jb div2"             /* then */ \
  66.         "mov bx,ax"       /* restore word 2 of dividend */ \
  67.         "mov ax,dx"       /* restore word 3 of dividend */ \
  68.         "xor dx,dx"       /* - zero high part */ \
  69.         "div word ptr ss:[si]"  /* - divide into word 3 of dividend */ \
  70.         "xchg ax,bx"      /* - swap word 3,word 2 of dvdnd */ \
  71.       "div2:"           \
  72.         "div word ptr ss:[si]"  /* - divide into word 2 of dividend */ \
  73.         "xchg ax,cx"      /* - swap word 2,word 1 of dvdnd */ \
  74.       "div3:"           \
  75.         "div word ptr ss:[si]"  /* - divide into word 1 of dividend */ \
  76.         "xchg ax,di"      /* - swap word 1,word 0 of dvdnd */ \
  77.       "div4:"           \
  78.         "div word ptr ss:[si]" /* calculate low part */ \
  79.         "mov  ss:[si],dx"      /* store remainder */ \
  80.         "mov dx,ax"        /* dx is word 0 */ \
  81.         "mov ax,bx"        /* ax:bx:cx:dx = bx:cx:di:ax */ \
  82.         "mov bx,cx" \
  83.         "mov cx,di" \
  84.         "jmp end_div" \
  85.       "skip1:"      /* ax==0 */  \
  86.         "test bx,bx"       /* even less work to do if bx == 0 too */ \
  87.         "jz skip2" \
  88.         "mov dx,bx"        /* dx:ax = bx:cx */ \
  89.         "mov ax,cx" \
  90.         "xor bx,bx"        /* set word 3 of quotient to 0 */ \
  91.         "xor cx,cx"        /* set word 2 of quotient to 0 */ \
  92.         "cmp dx,word ptr ss:[si]" /* if quotient will be < 64K */ \
  93.         "jb div3"             /* then need to do two divisions */ \
  94.         "mov cx,ax"        /* restore word 1 of dividend */ \
  95.         "mov ax,dx"        /* restore word 2 of dividend */ \
  96.         "xor dx,dx"        /* zero high part */ \
  97.         "jmp div2"         /* do three divisions*/ \
  98.       "skip2:"      /* ax==bx==0 */ \
  99.         "mov dx,cx"        /* dx:ax = cx:di */ \
  100.         "mov ax,di" \
  101.         "xor cx,cx"        /* set word 2 of quotient to 0 */ \
  102.         "xor di,di"        /* set word 1 of quotient to 0 */ \
  103.         "cmp dx,word ptr ss:[si]" /* if quotient will be < 64K */ \
  104.         "jb div4"             /* then only one division to do */ \
  105.         "mov di,ax"        /* restore word 0 of dividend */ \
  106.         "mov ax,dx"        /* restore word 1 of dividend */ \
  107.         "xor dx,dx"        /* zero high part */ \
  108.         "jmp div3"         /* do two divisions */ \
  109.       "end_div:" \
  110.         parm [ax bx cx dx] [si] modify [di] value [ax bx cx dx];
  111. #elif defined(M_I86) && defined(__SMALL_DATA__)
  112.     #pragma aux __ulldiv = \
  113.         "mov di,dx"        /* initial dividend = ax:bx:cx:dx(di); save dx */ \
  114.         "test ax,ax"       /* less work to do if ax == 0 */ \
  115.         "jz skip1"  \
  116.         "mov dx,ax"        /* dx:ax = ax:bx */ \
  117.         "mov ax,bx" \
  118.         "xor bx,bx"           /* set word 3 of quotient to 0 */ \
  119.         "cmp dx,word ptr[si]" /* if quotient will be >= 64K */ \
  120.         "jb div2"             /* then */ \
  121.         "mov bx,ax"       /* restore word 2 of dividend */ \
  122.         "mov ax,dx"       /* restore word 3 of dividend */ \
  123.         "xor dx,dx"       /* - zero high part */ \
  124.         "div word ptr[si]"  /* - divide into word 3 of dividend */ \
  125.         "xchg ax,bx"      /* - swap word 3,word 2 of dvdnd */ \
  126.       "div2:"           \
  127.         "div word ptr[si]"  /* - divide into word 2 of dividend */ \
  128.         "xchg ax,cx"      /* - swap word 2,word 1 of dvdnd */ \
  129.       "div3:"           \
  130.         "div word ptr[si]"  /* - divide into word 1 of dividend */ \
  131.         "xchg ax,di"      /* - swap word 1,word 0 of dvdnd */ \
  132.       "div4:"           \
  133.         "div word ptr[si]" /* calculate low part */ \
  134.         "mov [si],dx"      /* store remainder */ \
  135.         "mov dx,ax"        /* dx is word 0 */ \
  136.         "mov ax,bx"        /* ax:bx:cx:dx = bx:cx:di:ax */ \
  137.         "mov bx,cx" \
  138.         "mov cx,di" \
  139.         "jmp end_div" \
  140.       "skip1:"      /* dx==0 */  \
  141.         "test bx,bx"       /* even less work to do if bx == 0 too */ \
  142.         "jz skip2" \
  143.         "mov dx,bx"        /* dx:ax = bx:cx */ \
  144.         "mov ax,cx" \
  145.         "xor bx,bx"        /* set word 3 of quotient to 0 */ \
  146.         "xor cx,cx"        /* set word 2 of quotient to 0 */ \
  147.         "cmp dx,word ptr[si]" /* if quotient will be < 64K */ \
  148.         "jb div3"             /* then need to do two divisions */ \
  149.         "mov cx,ax"        /* restore word 1 of dividend */ \
  150.         "mov ax,dx"        /* restore word 2 of dividend */ \
  151.         "xor dx,dx"        /* zero high part */ \
  152.         "jmp div2"         /* do three divisions*/ \
  153.       "skip2:"      /* ax==bx==0 */ \
  154.         "mov dx,cx"        /* dx:ax = cx:di */ \
  155.         "mov ax,di" \
  156.         "xor cx,cx"        /* set word 2 of quotient to 0 */ \
  157.         "xor di,di"        /* set word 1 of quotient to 0 */ \
  158.         "cmp dx,word ptr[si]" /* if quotient will be < 64K */ \
  159.         "jb div4"             /* then only one division to do */ \
  160.         "mov di,ax"        /* restore word 0 of dividend */ \
  161.         "mov ax,dx"        /* restore word 1 of dividend */ \
  162.         "xor dx,dx"        /* zero high part */ \
  163.         "jmp div3"         /* do two divisions */ \
  164.       "end_div:" \
  165.         parm [ax bx cx dx] [si] modify [di] value [ax bx cx dx];
  166. #endif
  167. #endif
  168.  
  169. _WCRTLINK CHAR_TYPE *__F_NAME(ulltoa,_ulltow)(
  170.         unsigned long long int value,
  171.         CHAR_TYPE *buffer,
  172.         int radix )
  173.     {
  174.         CHAR_TYPE *p = buffer;
  175.         char *q;
  176.         unsigned rem;
  177.         auto char buf[66];      // only holds ASCII so 'char' is OK
  178.  
  179.         buf[0] = '\0';
  180.         q = &buf[1];
  181.         do {
  182. #if defined(__386__) || defined(M_I86)
  183.             rem = radix;
  184.             value = __ulldiv( value, (unsigned _WCNEAR *) &rem );
  185. #else
  186.             rem = value % radix;
  187.             value = value / radix;
  188. #endif
  189.             *q = __Alphabet[ rem ];
  190.             ++q;
  191.         } while( value );
  192.         while( *p++ = (CHAR_TYPE)*--q );
  193.         return( buffer );
  194.     }
  195.  
  196.  
  197. _WCRTLINK CHAR_TYPE *__F_NAME(lltoa,_lltow)(
  198.         long long int value,
  199.         CHAR_TYPE *buffer,
  200.         int radix )
  201.     {
  202.         register CHAR_TYPE *p = buffer;
  203.  
  204.         if( radix == 10 ) {
  205.             if( value < 0 ) {
  206.                 *p++ = '-';
  207.                 value = -value;
  208.             }
  209.         }
  210.         __F_NAME(ulltoa,_ulltow)( value, p, radix );
  211.         return( buffer );
  212.     }
  213.