mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
575 lines
9.3 KiB
575 lines
9.3 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
r10math.c
|
|
|
|
Abstract:
|
|
|
|
This file contains a set of routines which will do arithmetic on
|
|
the 80-bit floating point format supported by the 80x87 family of
|
|
processors.
|
|
|
|
Author:
|
|
|
|
Jim Schaad (jimsch) 06-27-92
|
|
|
|
Environment:
|
|
|
|
Win32 - user mode
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
* This is the constant 0 in the 80-bit format.
|
|
*/
|
|
|
|
FLOAT10 Real10_Zero = {0, 0, 0, 0, 0, 0, 0, 0, 0, 4};
|
|
|
|
|
|
|
|
int
|
|
R10Not(
|
|
FLOAT10 ld
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will compute the NOT of an 80-bit value.
|
|
|
|
Arguments:
|
|
|
|
ld - Supplies the long double to be NOT-ed
|
|
|
|
Return Value:
|
|
|
|
1 if ld is 0.0 and 0 otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
return 0; /* NOTENOTE jimsch return !ld */
|
|
|
|
} /* R10Not() */
|
|
|
|
|
|
|
|
|
|
void
|
|
R10Uminus(
|
|
FLOAT10 * pldDest,
|
|
FLOAT10 ldLeft
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine computes the uninary minus of a 80-bit real number.
|
|
|
|
Arguments:
|
|
|
|
pldDest - Supplies a pointer to the destination FLOAT10 buffer
|
|
ldLeft - Supplies the value to be negated.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
#ifdef i386
|
|
// NOTENOTE jimsch - need to try/except this code
|
|
_asm {
|
|
lea eax, ldLeft
|
|
fld tbyte ptr [eax] ; Load ldLeft on the float point chip;
|
|
fchs ;
|
|
mov eax, pldDest ;
|
|
fstp tbyte ptr [eax] ;
|
|
}
|
|
#else
|
|
#endif
|
|
|
|
return;
|
|
|
|
} /* R10Uminus() */
|
|
|
|
|
|
|
|
bool_t
|
|
R10Equal(
|
|
FLOAT10 ldLeft,
|
|
FLOAT10 ldRight
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will compare two 80-bit reals and return TRUE if
|
|
ldLeft == ldRight. This routine using an unorder compare on NANs.
|
|
|
|
Arguments:
|
|
|
|
ldLeft - Supplies long double to compare
|
|
ldRight - Supplies long double to compare
|
|
|
|
Return Value:
|
|
|
|
TRUE if the items are equal else FALSE
|
|
|
|
--*/
|
|
|
|
{
|
|
#ifdef i386
|
|
short sw;
|
|
|
|
_asm {
|
|
lea eax, ldLeft ;
|
|
fld tbyte ptr [eax] ;
|
|
|
|
lea eax, ldRight ;
|
|
fld tbyte ptr [eax] ;
|
|
|
|
fucompp ;
|
|
fstsw sw ;
|
|
}
|
|
|
|
if ((sw & 0x4700) == 0x04000) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
} /* R10Equal() */
|
|
|
|
|
|
|
|
bool_t
|
|
R10Lt(
|
|
FLOAT10 ldLeft,
|
|
FLOAT10 ldRight
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will compare two 80-bit reals and return TRUE if
|
|
ldLeft < ldRight. This routine uses an unordered compare on NANs
|
|
|
|
Arguments:
|
|
|
|
ldLeft - Supplies long double to compare
|
|
ldRight - Supplies long double to compare
|
|
|
|
Return Value:
|
|
|
|
TRUE if the items are equal else FALSE
|
|
|
|
--*/
|
|
|
|
{
|
|
#ifdef i386
|
|
short sw;
|
|
|
|
_asm {
|
|
lea eax, ldLeft ;
|
|
fld tbyte ptr [eax] ;
|
|
|
|
lea eax, ldRight ;
|
|
fld tbyte ptr [eax] ;
|
|
|
|
fucompp ;
|
|
fstsw sw ;
|
|
}
|
|
|
|
if ((sw & 0x4700) == 0x00000) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
} /* R10Lt() */
|
|
|
|
|
|
|
|
void
|
|
R10Plus(
|
|
FLOAT10 * pldResult,
|
|
FLOAT10 ldLeft,
|
|
FLOAT10 ldRight
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function adds ldLeft and ldRight together and stores the result in
|
|
pldResult
|
|
|
|
Arguments:
|
|
|
|
pldResult - Supplies pointer to destination
|
|
ldLeft - Supplies parameter 1
|
|
ldRight - Supplies parameter 2
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
#ifdef i386
|
|
_asm {
|
|
lea eax, ldLeft ;
|
|
fld tbyte ptr [eax] ;
|
|
|
|
lea eax, ldRight ;
|
|
fld tbyte ptr [eax] ;
|
|
|
|
faddp st(1),st
|
|
|
|
mov eax, pldResult ;
|
|
fstp tbyte ptr [eax] ;
|
|
}
|
|
|
|
#else
|
|
memcpy(pldResult, &ldLeft, sizeof(FLOAT10));
|
|
#endif
|
|
return;
|
|
} /* R10Plus() */
|
|
|
|
|
|
|
|
void
|
|
R10Minus(
|
|
FLOAT10 * pldResult,
|
|
FLOAT10 ldLeft,
|
|
FLOAT10 ldRight
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function subtraces ldRight from ldLeft together and stores
|
|
the result in pldResult
|
|
|
|
Arguments:
|
|
|
|
pldResult - Supplies pointer to destination
|
|
ldLeft - Supplies parameter 1
|
|
ldRight - Supplies parameter 2
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
#ifdef i386
|
|
_asm {
|
|
lea eax, ldLeft ;
|
|
fld tbyte ptr [eax] ;
|
|
|
|
lea eax, ldRight ;
|
|
fld tbyte ptr [eax] ;
|
|
|
|
fsubp st(1),st
|
|
|
|
mov eax, pldResult ;
|
|
fstp tbyte ptr [eax] ;
|
|
}
|
|
|
|
#else // i386
|
|
memcpy(pldResult, &ldLeft, sizeof(FLOAT10));
|
|
#endif // i386
|
|
return;
|
|
} /* R10Minus() */
|
|
|
|
|
|
|
|
void
|
|
R10Times(
|
|
FLOAT10 * pldResult,
|
|
FLOAT10 ldLeft,
|
|
FLOAT10 ldRight
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function multiplies ldRight and ldLeft together and stores
|
|
the result in pldResult
|
|
|
|
Arguments:
|
|
|
|
pldResult - Supplies pointer to destination
|
|
ldLeft - Supplies parameter 1
|
|
ldRight - Supplies parameter 2
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
#ifdef i386
|
|
_asm {
|
|
lea eax, ldLeft ;
|
|
fld tbyte ptr [eax] ;
|
|
|
|
lea eax, ldRight ;
|
|
fld tbyte ptr [eax] ;
|
|
|
|
fmulp st(1),st ;
|
|
|
|
mov eax, pldResult ;
|
|
fstp tbyte ptr [eax] ;
|
|
}
|
|
#else // i386
|
|
memcpy(pldResult, &ldLeft, sizeof(FLOAT10));
|
|
#endif // i386
|
|
return;
|
|
} /* R10Times() */
|
|
|
|
|
|
void
|
|
R10Divide(
|
|
FLOAT10 * pldResult,
|
|
FLOAT10 ldLeft,
|
|
FLOAT10 ldRight
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function multiplies ldRight and ldLeft together and stores
|
|
the result in pldResult
|
|
|
|
Arguments:
|
|
|
|
pldResult - Supplies pointer to destination
|
|
ldLeft - Supplies parameter 1
|
|
ldRight - Supplies parameter 2
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
#ifdef i386
|
|
_asm {
|
|
lea eax, ldLeft ;
|
|
fld tbyte ptr [eax] ;
|
|
|
|
lea eax, ldRight ;
|
|
fld tbyte ptr [eax] ;
|
|
|
|
fdivp st(1),st ;
|
|
|
|
mov eax, pldResult ;
|
|
fstp tbyte ptr [eax] ;
|
|
}
|
|
#else // i386
|
|
memcpy(pldResult, &ldLeft, sizeof(FLOAT10));
|
|
#endif // i386
|
|
return;
|
|
} /* R10Divide() */
|
|
|
|
|
|
double
|
|
R10CastToDouble(
|
|
FLOAT10 ld
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert the 80-bit real to a 64-bit real and return it
|
|
|
|
Arguments:
|
|
|
|
ld - Supplies the 80-bit real to convert
|
|
|
|
Return Value:
|
|
|
|
Returns the value ld in 64-bit format
|
|
|
|
--*/
|
|
|
|
{
|
|
#ifdef i386
|
|
double d;
|
|
_asm {
|
|
lea eax, ld
|
|
fld tbyte ptr [eax]
|
|
lea eax, d
|
|
fstp qword ptr [eax]
|
|
}
|
|
return d;
|
|
#else
|
|
return 0.0;
|
|
#endif
|
|
} /* R10CastToDouble() */
|
|
|
|
|
|
float
|
|
R10CastToFloat(
|
|
FLOAT10 ld
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts a 80-bit real number to a 32-bit real number
|
|
|
|
Arguments:
|
|
|
|
ld - Supplies 80-bit number to be converted
|
|
|
|
Return Value:
|
|
|
|
Returns the 32-bit equivalent value
|
|
|
|
--*/
|
|
|
|
{
|
|
#ifdef i386
|
|
float d;
|
|
_asm {
|
|
lea eax, ld
|
|
fld tbyte ptr [eax]
|
|
lea eax, d
|
|
fstp dword ptr [eax]
|
|
}
|
|
return d;
|
|
#else
|
|
return (float) 0.0;
|
|
#endif
|
|
} /* R10CastToFloat() */
|
|
|
|
|
|
|
|
long
|
|
R10CastToLong(
|
|
FLOAT10 ld
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts a 80-bit real number to a 32-bit long
|
|
|
|
Arguments:
|
|
|
|
ld - Supplies 80-bit number to be converted
|
|
|
|
Return Value:
|
|
|
|
returns 32-bit equvalent to ld
|
|
|
|
--*/
|
|
|
|
{
|
|
#ifdef i386
|
|
long d;
|
|
_asm {
|
|
lea eax, ld
|
|
fld tbyte ptr [eax]
|
|
lea eax, d
|
|
fistp dword ptr [eax]
|
|
}
|
|
return d;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
} /* R10CastToLong() */
|
|
|
|
|
|
|
|
void
|
|
R10AssignDouble(
|
|
FLOAT10 * pld,
|
|
double d
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will assign a double to a 80-bit real
|
|
|
|
Arguments:
|
|
|
|
pld - Supplies pointer to destiniation buffer
|
|
d - Supplies the double to be assigned
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
#ifdef i386
|
|
_asm {
|
|
lea eax, d
|
|
fld qword ptr [eax]
|
|
mov eax, pld
|
|
fstp tbyte ptr [eax]
|
|
}
|
|
#else
|
|
return;
|
|
#endif
|
|
} /* R10AssignDouble() */
|
|
|
|
|
|
|
|
void
|
|
R10AssignFloat(
|
|
FLOAT10 * pld,
|
|
float f
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will assign a float to a 80-bit real
|
|
|
|
Arguments:
|
|
|
|
pld - Supplies pointer to destiniation buffer
|
|
f - Supplies the float to be assigned
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
return;
|
|
} /* R10AssignFloat() */
|
|
|
|
|