mirror of https://github.com/acidanthera/audk.git
452 lines
7.5 KiB
C
452 lines
7.5 KiB
C
/*++
|
|
|
|
Copyright (c) 2006, Intel Corporation.
|
|
All rights reserved. This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
Module Name:
|
|
|
|
x64math.c
|
|
|
|
Abstract:
|
|
|
|
Math routines for x64.
|
|
|
|
--*/
|
|
|
|
UINT64
|
|
LeftShiftU64 (
|
|
IN UINT64 Operand,
|
|
IN UINT64 Count
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Left-shift a 64 bit value.
|
|
|
|
Arguments:
|
|
|
|
Operand - 64-bit value to shift
|
|
Count - shift count
|
|
|
|
Returns:
|
|
|
|
Operand << Count
|
|
|
|
--*/
|
|
{
|
|
if (Count > 63) {
|
|
return 0;
|
|
}
|
|
|
|
return Operand << Count;
|
|
}
|
|
|
|
UINT64
|
|
RightShiftU64 (
|
|
IN UINT64 Operand,
|
|
IN UINT64 Count
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Right-shift a 64 bit value.
|
|
|
|
Arguments:
|
|
|
|
Operand - 64-bit value to shift
|
|
Count - shift count
|
|
|
|
Returns:
|
|
|
|
Operand >> Count
|
|
|
|
--*/
|
|
{
|
|
if (Count > 63) {
|
|
return 0;
|
|
}
|
|
|
|
return Operand >> Count;
|
|
}
|
|
|
|
INT64
|
|
ARightShift64 (
|
|
IN INT64 Operand,
|
|
IN UINT64 Count
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Right-shift a 64 bit signed value.
|
|
|
|
Arguments:
|
|
|
|
Operand - 64-bit value to shift
|
|
Count - shift count
|
|
|
|
Returns:
|
|
|
|
Operand >> Count
|
|
|
|
--*/
|
|
{
|
|
if (Count > 63) {
|
|
|
|
if (Operand & 0x8000000000000000ULL) {
|
|
return (INT64)~0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
return Operand >> Count;
|
|
}
|
|
|
|
#if 0
|
|
//
|
|
// The compiler generates true assembly for these, so we don't need them.
|
|
//
|
|
INT32
|
|
ARightShift32 (
|
|
IN INT32 Operand,
|
|
IN UINTN Count
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Right shift a 32-bit value
|
|
|
|
Arguments:
|
|
|
|
Operand - value to shift
|
|
Count - shift count
|
|
|
|
Returns:
|
|
|
|
Operand >> Count
|
|
|
|
--*/
|
|
{
|
|
return Operand >> (Count & 0x1f);
|
|
}
|
|
|
|
INT32
|
|
MulS32x32 (
|
|
INT32 Value1,
|
|
INT32 Value2,
|
|
INT32 *ResultHigh
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Multiply two signed 32-bit numbers.
|
|
|
|
Arguments:
|
|
|
|
Value1 - first value to multiply
|
|
Value2 - value to multiply Value1 by
|
|
ResultHigh - overflow
|
|
|
|
Returns:
|
|
|
|
Value1 * Value2
|
|
|
|
Notes:
|
|
|
|
The 64-bit result is the concatenation of *ResultHigh and the return value
|
|
|
|
The product fits in 32 bits if
|
|
(*ResultHigh == 0x00000000 AND *ResultLow_bit31 == 0)
|
|
OR
|
|
(*ResultHigh == 0xffffffff AND *ResultLow_bit31 == 1)
|
|
|
|
--*/
|
|
{
|
|
INT64 Rres64;
|
|
INT32 Result;
|
|
|
|
Res64 = (INT64) Value1 * (INT64) Value2;
|
|
*ResultHigh = (Res64 >> 32) & 0xffffffff;
|
|
Result = Res64 & 0xffffffff;
|
|
return Result;
|
|
}
|
|
|
|
UINT32
|
|
MulU32x32 (
|
|
UINT32 Value1,
|
|
UINT32 Value2,
|
|
UINT32 *ResultHigh
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Multiply two unsigned 32-bit values.
|
|
|
|
Arguments:
|
|
|
|
Value1 - first number
|
|
Value2 - number to multiply by Value1
|
|
ResultHigh - overflow
|
|
|
|
Returns:
|
|
|
|
Value1 * Value2
|
|
|
|
Notes:
|
|
|
|
The 64-bit result is the concatenation of *ResultHigh and the return value.
|
|
The product fits in 32 bits if *ResultHigh == 0x00000000
|
|
|
|
--*/
|
|
{
|
|
UINT64 Res64;
|
|
UINT32 Result;
|
|
|
|
Res64 = (INT64) Value1 * (INT64) Value2;
|
|
*ResultHigh = (Res64 >> 32) & 0xffffffff;
|
|
Result = Res64 & 0xffffffff;
|
|
return Result;
|
|
}
|
|
|
|
INT32
|
|
DivS32x32 (
|
|
INT32 Value1,
|
|
INT32 Value2,
|
|
INT32 *Remainder,
|
|
UINTN *error
|
|
)
|
|
//
|
|
// signed 32-bit by signed 32-bit divide; the 32-bit remainder is
|
|
// in *Remainder and the quotient is the return value; *error = 1 if the
|
|
// divisor is 0, and it is 1 otherwise
|
|
//
|
|
{
|
|
INT32 Result;
|
|
|
|
*error = 0;
|
|
|
|
if (Value2 == 0x0) {
|
|
*error = 1;
|
|
Result = 0x80000000;
|
|
*Remainder = 0x80000000;
|
|
} else {
|
|
Result = Value1 / Value2;
|
|
*Remainder = Value1 - Result * Value2;
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
UINT32
|
|
DivU32x32 (
|
|
UINT32 Value1,
|
|
UINT32 Value2,
|
|
UINT32 *Remainder,
|
|
UINTN *Error
|
|
)
|
|
//
|
|
// unsigned 32-bit by unsigned 32-bit divide; the 32-bit remainder is
|
|
// in *Remainder and the quotient is the return value; *error = 1 if the
|
|
// divisor is 0, and it is 1 otherwise
|
|
//
|
|
{
|
|
UINT32 Result;
|
|
|
|
*Error = 0;
|
|
|
|
if (Value2 == 0x0) {
|
|
*Error = 1;
|
|
Result = 0x80000000;
|
|
*Remainder = 0x80000000;
|
|
} else {
|
|
Result = Value1 / Value2;
|
|
*Remainder = Value1 - Result * Value2;
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
#endif
|
|
|
|
INT64
|
|
MulS64x64 (
|
|
INT64 Value1,
|
|
INT64 Value2,
|
|
INT64 *ResultHigh
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Multiply two signed 32-bit numbers.
|
|
|
|
Arguments:
|
|
|
|
Value1 - first value to multiply
|
|
Value2 - value to multiply Value1 by
|
|
ResultHigh - overflow
|
|
|
|
Returns:
|
|
|
|
Value1 * Value2
|
|
|
|
Notes:
|
|
|
|
The 64-bit result is the concatenation of *ResultHigh and the return value
|
|
|
|
The product fits in 32 bits if
|
|
(*ResultHigh == 0x00000000 AND *ResultLow_bit31 == 0)
|
|
OR
|
|
(*ResultHigh == 0xffffffff AND *ResultLow_bit31 == 1)
|
|
|
|
--*/
|
|
{
|
|
INT64 Result;
|
|
|
|
Result = Value1 * Value2;
|
|
|
|
return Result;
|
|
}
|
|
|
|
UINT64
|
|
MulU64x64 (
|
|
UINT64 Value1,
|
|
UINT64 Value2,
|
|
UINT64 *ResultHigh
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Multiply two unsigned 32-bit values.
|
|
|
|
Arguments:
|
|
|
|
Value1 - first number
|
|
Value2 - number to multiply by Value1
|
|
ResultHigh - overflow
|
|
|
|
Returns:
|
|
|
|
Value1 * Value2
|
|
|
|
Notes:
|
|
|
|
The 64-bit result is the concatenation of *ResultHigh and the return value.
|
|
The product fits in 32 bits if *ResultHigh == 0x00000000
|
|
|
|
--*/
|
|
{
|
|
UINT64 Result;
|
|
|
|
Result = Value1 * Value2;
|
|
|
|
return Result;
|
|
}
|
|
|
|
INT64
|
|
DivS64x64 (
|
|
INT64 Value1,
|
|
INT64 Value2,
|
|
INT64 *Remainder,
|
|
UINTN *Error
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Divide two 64-bit signed values.
|
|
|
|
Arguments:
|
|
|
|
Value1 - dividend
|
|
Value2 - divisor
|
|
Remainder - remainder of Value1/Value2
|
|
Error - to flag errors (divide-by-0)
|
|
|
|
Returns:
|
|
|
|
Value1 / Valu2
|
|
|
|
Note:
|
|
|
|
The 64-bit remainder is in *Remainder and the quotient is the return value.
|
|
*Error = 1 if the divisor is 0, and it is 1 otherwise
|
|
|
|
--*/
|
|
{
|
|
INT64 Result;
|
|
|
|
*Error = 0;
|
|
|
|
if (Value2 == 0x0) {
|
|
*Error = 1;
|
|
Result = 0x8000000000000000;
|
|
*Remainder = 0x8000000000000000;
|
|
} else {
|
|
Result = Value1 / Value2;
|
|
*Remainder = Value1 - Result * Value2;
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
UINT64
|
|
DivU64x64 (
|
|
UINT64 Value1,
|
|
UINT64 Value2,
|
|
UINT64 *Remainder,
|
|
UINTN *Error
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Divide two 64-bit unsigned values.
|
|
|
|
Arguments:
|
|
|
|
Value1 - dividend
|
|
Value2 - divisor
|
|
Remainder - remainder of Value1/Value2
|
|
Error - to flag errors (divide-by-0)
|
|
|
|
Returns:
|
|
|
|
Value1 / Valu2
|
|
|
|
Note:
|
|
|
|
The 64-bit remainder is in *Remainder and the quotient is the return value.
|
|
*Error = 1 if the divisor is 0, and it is 1 otherwise
|
|
|
|
--*/
|
|
{
|
|
UINT64 Result;
|
|
|
|
*Error = 0;
|
|
|
|
if (Value2 == 0x0) {
|
|
*Error = 1;
|
|
Result = 0x8000000000000000;
|
|
*Remainder = 0x8000000000000000;
|
|
} else {
|
|
Result = Value1 / Value2;
|
|
*Remainder = Value1 - Result * Value2;
|
|
}
|
|
|
|
return Result;
|
|
}
|