kolibrios/programs/develop/open watcom/trunk/clib/convert/lltoa.c
Sergey Semyonov (Serge) 43bd1e645f Clib char & math functions
git-svn-id: svn://kolibrios.org@554 a494cfbc-eb01-0410-851d-a64ba20cac60
2007-06-26 11:19:49 +00:00

213 lines
9.0 KiB
C

/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Long long integer to ASCII conversion routines.
*
****************************************************************************/
#include "variety.h"
#include "widechar.h"
#include "watcom.h"
#include "clibi64.h"
#include <stdlib.h>
extern const char __based(__segname("_CONST")) __Alphabet[];
#if defined(__386__) || defined(M_I86)
unsigned long long __ulldiv( unsigned long long, unsigned _WCNEAR *);
#if defined(__386__)
#pragma aux __ulldiv = \
"xor ecx,ecx" /* set high word of quotient to 0 */ \
"cmp edx,dword ptr[ebx]" /* if quotient will be >= 4G */ \
"jb less4g" /* then */ \
"mov ecx,eax" /* - save low word of dividend */ \
"mov eax,edx" /* - get high word of dividend */ \
"xor edx,edx" /* - zero high part */ \
"div dword ptr[ebx]" /* - divide into high part of dividend */ \
"xchg eax,ecx" /* - swap high part of quot,low word of dvdnd */ \
"less4g:" \
"div dword ptr[ebx]" /* calculate low part */ \
"mov [ebx],edx" /* store remainder */ \
parm [eax edx] [ebx] value [eax ecx];
#elif defined(M_I86) && defined(__BIG_DATA__)
#pragma aux __ulldiv = \
"mov di,dx" /* initial dividend = ax:bx:cx:dx(di); save dx */ \
"test ax,ax" /* less work to do if ax == 0 */ \
"jz skip1" \
"mov dx,ax" /* dx:ax = ax:bx */ \
"mov ax,bx" \
"xor bx,bx" /* set word 3 of quotient to 0 */ \
"cmp dx,word ptr ss:[si]" /* if quotient will be >= 64K */ \
"jb div2" /* then */ \
"mov bx,ax" /* restore word 2 of dividend */ \
"mov ax,dx" /* restore word 3 of dividend */ \
"xor dx,dx" /* - zero high part */ \
"div word ptr ss:[si]" /* - divide into word 3 of dividend */ \
"xchg ax,bx" /* - swap word 3,word 2 of dvdnd */ \
"div2:" \
"div word ptr ss:[si]" /* - divide into word 2 of dividend */ \
"xchg ax,cx" /* - swap word 2,word 1 of dvdnd */ \
"div3:" \
"div word ptr ss:[si]" /* - divide into word 1 of dividend */ \
"xchg ax,di" /* - swap word 1,word 0 of dvdnd */ \
"div4:" \
"div word ptr ss:[si]" /* calculate low part */ \
"mov ss:[si],dx" /* store remainder */ \
"mov dx,ax" /* dx is word 0 */ \
"mov ax,bx" /* ax:bx:cx:dx = bx:cx:di:ax */ \
"mov bx,cx" \
"mov cx,di" \
"jmp end_div" \
"skip1:" /* ax==0 */ \
"test bx,bx" /* even less work to do if bx == 0 too */ \
"jz skip2" \
"mov dx,bx" /* dx:ax = bx:cx */ \
"mov ax,cx" \
"xor bx,bx" /* set word 3 of quotient to 0 */ \
"xor cx,cx" /* set word 2 of quotient to 0 */ \
"cmp dx,word ptr ss:[si]" /* if quotient will be < 64K */ \
"jb div3" /* then need to do two divisions */ \
"mov cx,ax" /* restore word 1 of dividend */ \
"mov ax,dx" /* restore word 2 of dividend */ \
"xor dx,dx" /* zero high part */ \
"jmp div2" /* do three divisions*/ \
"skip2:" /* ax==bx==0 */ \
"mov dx,cx" /* dx:ax = cx:di */ \
"mov ax,di" \
"xor cx,cx" /* set word 2 of quotient to 0 */ \
"xor di,di" /* set word 1 of quotient to 0 */ \
"cmp dx,word ptr ss:[si]" /* if quotient will be < 64K */ \
"jb div4" /* then only one division to do */ \
"mov di,ax" /* restore word 0 of dividend */ \
"mov ax,dx" /* restore word 1 of dividend */ \
"xor dx,dx" /* zero high part */ \
"jmp div3" /* do two divisions */ \
"end_div:" \
parm [ax bx cx dx] [si] modify [di] value [ax bx cx dx];
#elif defined(M_I86) && defined(__SMALL_DATA__)
#pragma aux __ulldiv = \
"mov di,dx" /* initial dividend = ax:bx:cx:dx(di); save dx */ \
"test ax,ax" /* less work to do if ax == 0 */ \
"jz skip1" \
"mov dx,ax" /* dx:ax = ax:bx */ \
"mov ax,bx" \
"xor bx,bx" /* set word 3 of quotient to 0 */ \
"cmp dx,word ptr[si]" /* if quotient will be >= 64K */ \
"jb div2" /* then */ \
"mov bx,ax" /* restore word 2 of dividend */ \
"mov ax,dx" /* restore word 3 of dividend */ \
"xor dx,dx" /* - zero high part */ \
"div word ptr[si]" /* - divide into word 3 of dividend */ \
"xchg ax,bx" /* - swap word 3,word 2 of dvdnd */ \
"div2:" \
"div word ptr[si]" /* - divide into word 2 of dividend */ \
"xchg ax,cx" /* - swap word 2,word 1 of dvdnd */ \
"div3:" \
"div word ptr[si]" /* - divide into word 1 of dividend */ \
"xchg ax,di" /* - swap word 1,word 0 of dvdnd */ \
"div4:" \
"div word ptr[si]" /* calculate low part */ \
"mov [si],dx" /* store remainder */ \
"mov dx,ax" /* dx is word 0 */ \
"mov ax,bx" /* ax:bx:cx:dx = bx:cx:di:ax */ \
"mov bx,cx" \
"mov cx,di" \
"jmp end_div" \
"skip1:" /* dx==0 */ \
"test bx,bx" /* even less work to do if bx == 0 too */ \
"jz skip2" \
"mov dx,bx" /* dx:ax = bx:cx */ \
"mov ax,cx" \
"xor bx,bx" /* set word 3 of quotient to 0 */ \
"xor cx,cx" /* set word 2 of quotient to 0 */ \
"cmp dx,word ptr[si]" /* if quotient will be < 64K */ \
"jb div3" /* then need to do two divisions */ \
"mov cx,ax" /* restore word 1 of dividend */ \
"mov ax,dx" /* restore word 2 of dividend */ \
"xor dx,dx" /* zero high part */ \
"jmp div2" /* do three divisions*/ \
"skip2:" /* ax==bx==0 */ \
"mov dx,cx" /* dx:ax = cx:di */ \
"mov ax,di" \
"xor cx,cx" /* set word 2 of quotient to 0 */ \
"xor di,di" /* set word 1 of quotient to 0 */ \
"cmp dx,word ptr[si]" /* if quotient will be < 64K */ \
"jb div4" /* then only one division to do */ \
"mov di,ax" /* restore word 0 of dividend */ \
"mov ax,dx" /* restore word 1 of dividend */ \
"xor dx,dx" /* zero high part */ \
"jmp div3" /* do two divisions */ \
"end_div:" \
parm [ax bx cx dx] [si] modify [di] value [ax bx cx dx];
#endif
#endif
_WCRTLINK CHAR_TYPE *__F_NAME(ulltoa,_ulltow)(
unsigned long long int value,
CHAR_TYPE *buffer,
int radix )
{
CHAR_TYPE *p = buffer;
char *q;
unsigned rem;
auto char buf[66]; // only holds ASCII so 'char' is OK
buf[0] = '\0';
q = &buf[1];
do {
#if defined(__386__) || defined(M_I86)
rem = radix;
value = __ulldiv( value, (unsigned _WCNEAR *) &rem );
#else
rem = value % radix;
value = value / radix;
#endif
*q = __Alphabet[ rem ];
++q;
} while( value );
while( *p++ = (CHAR_TYPE)*--q );
return( buffer );
}
_WCRTLINK CHAR_TYPE *__F_NAME(lltoa,_lltow)(
long long int value,
CHAR_TYPE *buffer,
int radix )
{
register CHAR_TYPE *p = buffer;
if( radix == 10 ) {
if( value < 0 ) {
*p++ = '-';
value = -value;
}
}
__F_NAME(ulltoa,_ulltow)( value, p, radix );
return( buffer );
}