185 lines
3.8 KiB
C
185 lines
3.8 KiB
C
/*
|
|
*mantold.c - conversion of a decimal mantissa to _ULDBL12
|
|
|
|
* Copyright (c) 1991-1991, Microsoft Corporation. All rights reserved.
|
|
|
|
*Purpose:
|
|
* Conversion of a decimal mantissa into _ULDBL12 format (i.e. long
|
|
* double with two additional bytes of significand)
|
|
|
|
*Revision History:
|
|
* 7-17-91 GDP Initial version (ported from assembly)
|
|
* 05-26-92 GWK Windbg srcs
|
|
|
|
*/
|
|
|
|
#include "mathsup.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
*int __addl(u_long x, u_long y, u_long *sum) - u_long addition
|
|
|
|
*Purpose: add two u_long numbers and return carry
|
|
|
|
*Entry: u_long x, u_long y : the numbers to be added
|
|
* u_long *sum : where to store the result
|
|
|
|
*Exit: *sum receives the value of x+y
|
|
* the value of the carry is returned
|
|
|
|
*Exceptions:
|
|
|
|
*/
|
|
|
|
int __addl(u_long x, u_long y, u_long *sum)
|
|
{
|
|
u_long r;
|
|
int carry=0;
|
|
r = x+y;
|
|
if (r < x || r < y)
|
|
carry++;
|
|
*sum = r;
|
|
return carry;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
*void __add_12(_ULDBL12 *x, _ULDBL12 *y) - _ULDBL12 addition
|
|
|
|
*Purpose: add two _ULDBL12 numbers. The numbers are added
|
|
* as 12-byte integers. Overflow is ignored.
|
|
|
|
*Entry: x,y: pointers to the operands
|
|
|
|
*Exit: *x receives the sum
|
|
|
|
*Exceptions:
|
|
|
|
*/
|
|
|
|
void __add_12(_ULDBL12 *x, _ULDBL12 *y)
|
|
{
|
|
int c0,c1,c2;
|
|
c0 = __addl(*UL_LO_12(x),*UL_LO_12(y),UL_LO_12(x));
|
|
if (c0) {
|
|
c1 = __addl(*UL_MED_12(x),(u_long)1,UL_MED_12(x));
|
|
if (c1) {
|
|
(*UL_HI_12(x))++;
|
|
}
|
|
}
|
|
c2 = __addl(*UL_MED_12(x),*UL_MED_12(y),UL_MED_12(x));
|
|
if (c2) {
|
|
(*UL_HI_12(x))++;
|
|
}
|
|
/* ignore next carry -- assume no overflow will occur */
|
|
(void) __addl(*UL_HI_12(x),*UL_HI_12(y),UL_HI_12(x));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
*void __shl_12(_ULDBL12 *x) - _ULDBL12 shift left
|
|
*void __shr_12(_ULDBL12 *x) - _ULDBL12 shift right
|
|
|
|
*Purpose: Shift a _ULDBL12 number one bit to the left (right). The number
|
|
* is shifted as a 12-byte integer. The MSB is lost.
|
|
|
|
*Entry: x: a pointer to the operand
|
|
|
|
*Exit: *x is shifted one bit to the left (or right)
|
|
|
|
*Exceptions:
|
|
|
|
*/
|
|
|
|
void __shl_12(_ULDBL12 *p)
|
|
{
|
|
u_long c0,c1;
|
|
|
|
c0 = *UL_LO_12(p) & MSB_ULONG ? 1: 0;
|
|
c1 = *UL_MED_12(p) & MSB_ULONG ? 1: 0;
|
|
*UL_LO_12(p) <<= 1;
|
|
*UL_MED_12(p) = *UL_MED_12(p)<<1 | c0;
|
|
*UL_HI_12(p) = *UL_HI_12(p)<<1 | c1;
|
|
}
|
|
|
|
void __shr_12(_ULDBL12 *p)
|
|
{
|
|
u_long c2,c1;
|
|
c2 = *UL_HI_12(p) & 0x1 ? MSB_ULONG: 0;
|
|
c1 = *UL_MED_12(p) & 0x1 ? MSB_ULONG: 0;
|
|
*UL_HI_12(p) >>= 1;
|
|
*UL_MED_12(p) = *UL_MED_12(p)>>1 | c2;
|
|
*UL_LO_12(p) = *UL_LO_12(p)>>1 | c1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
*void __mtold12(char *manptr,unsigned manlen,_ULDBL12 *ld12) -
|
|
* convert a mantissa into a _ULDBL12
|
|
|
|
*Purpose: convert a mantissa into a _ULDBL12. The mantissa is
|
|
* in the form of an array of manlen BCD digits and is
|
|
* considered to be an integer.
|
|
|
|
*Entry: manptr: the array containing the packed BCD digits of the mantissa
|
|
* manlen: the size of the array
|
|
* ld12: a pointer to the long double where the result will be stored
|
|
|
|
*Exit:
|
|
* ld12 gets the result of the conversion
|
|
|
|
*Exceptions:
|
|
|
|
*/
|
|
|
|
void __mtold12(char *manptr,
|
|
unsigned manlen,
|
|
_ULDBL12 *ld12)
|
|
{
|
|
_ULDBL12 tmp;
|
|
u_short expn = LD_BIASM1+80;
|
|
|
|
*UL_LO_12(ld12) = 0;
|
|
*UL_MED_12(ld12) = 0;
|
|
*UL_HI_12(ld12) = 0;
|
|
for (;manlen>0;manlen--,manptr++){
|
|
tmp = *ld12;
|
|
__shl_12(ld12);
|
|
__shl_12(ld12);
|
|
__add_12(ld12,&tmp);
|
|
__shl_12(ld12); /* multiply by 10 */
|
|
*UL_LO_12(&tmp) = (u_long)*manptr;
|
|
*UL_MED_12(&tmp) = 0;
|
|
*UL_HI_12(&tmp) = 0;
|
|
__add_12(ld12,&tmp);
|
|
}
|
|
|
|
/* normalize mantissa -- first shift word by word */
|
|
while (*UL_HI_12(ld12) == 0) {
|
|
*UL_HI_12(ld12) = *UL_MED_12(ld12) >> 16;
|
|
*UL_MED_12(ld12) = *UL_MED_12(ld12) << 16 | *UL_LO_12(ld12) >> 16;
|
|
(*UL_LO_12(ld12)) <<= 16;
|
|
expn -= 16;
|
|
}
|
|
while ((*UL_HI_12(ld12) & 0x8000) == 0) {
|
|
__shl_12(ld12);
|
|
expn--;
|
|
}
|
|
*U_EXP_12(ld12) = expn;
|
|
}
|