/**************************************************************************** * * 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 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 ); }