ipfmath.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 375 行

C
375
字号
/*++

Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.


Module Name:

  Ipfmath.c

Abstract:

  Math routines for IPF.

--*/

#include "Efi.h"

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 & (0x01 << 63)) {
      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
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;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?