Home | History | Annotate | Download | only in ia32
      1 /*++
      2 
      3 Copyright (c) 1998  Intel Corporation
      4 
      5 Module Name:
      6 
      7     math.c
      8 
      9 Abstract:
     10 
     11 
     12 
     13 
     14 Revision History
     15 
     16 --*/
     17 
     18 #include "lib.h"
     19 
     20 
     21 //
     22 // Declare runtime functions
     23 //
     24 
     25 #ifdef RUNTIME_CODE
     26 #ifndef __GNUC__
     27 #pragma RUNTIME_CODE(LShiftU64)
     28 #pragma RUNTIME_CODE(RShiftU64)
     29 #pragma RUNTIME_CODE(MultU64x32)
     30 #pragma RUNTIME_CODE(DivU64x32)
     31 #endif
     32 #endif
     33 
     34 //
     35 //
     36 //
     37 
     38 UINT64
     39 LShiftU64 (
     40     IN UINT64   Operand,
     41     IN UINTN    Count
     42     )
     43 // Left shift 64bit by 32bit and get a 64bit result
     44 {
     45 #ifdef __GNUC__
     46     return Operand << Count;
     47 #else
     48     UINT64      Result;
     49     _asm {
     50         mov     eax, dword ptr Operand[0]
     51         mov     edx, dword ptr Operand[4]
     52         mov     ecx, Count
     53         and     ecx, 63
     54 
     55         shld    edx, eax, cl
     56         shl     eax, cl
     57 
     58         cmp     ecx, 32
     59         jc      short ls10
     60 
     61         mov     edx, eax
     62         xor     eax, eax
     63 
     64 ls10:
     65         mov     dword ptr Result[0], eax
     66         mov     dword ptr Result[4], edx
     67     }
     68 
     69     return Result;
     70 #endif
     71 }
     72 
     73 UINT64
     74 RShiftU64 (
     75     IN UINT64   Operand,
     76     IN UINTN    Count
     77     )
     78 // Right shift 64bit by 32bit and get a 64bit result
     79 {
     80 #ifdef __GNUC__
     81     return Operand >> Count;
     82 #else
     83     UINT64      Result;
     84     _asm {
     85         mov     eax, dword ptr Operand[0]
     86         mov     edx, dword ptr Operand[4]
     87         mov     ecx, Count
     88         and     ecx, 63
     89 
     90         shrd    eax, edx, cl
     91         shr     edx, cl
     92 
     93         cmp     ecx, 32
     94         jc      short rs10
     95 
     96         mov     eax, edx
     97         xor     edx, edx
     98 
     99 rs10:
    100         mov     dword ptr Result[0], eax
    101         mov     dword ptr Result[4], edx
    102     }
    103 
    104     return Result;
    105 #endif
    106 }
    107 
    108 
    109 UINT64
    110 MultU64x32 (
    111     IN UINT64   Multiplicand,
    112     IN UINTN    Multiplier
    113     )
    114 // Multiple 64bit by 32bit and get a 64bit result
    115 {
    116 #ifdef __GNUC__
    117     return Multiplicand * Multiplier;
    118 #else
    119     UINT64      Result;
    120     _asm {
    121         mov     eax, dword ptr Multiplicand[0]
    122         mul     Multiplier
    123         mov     dword ptr Result[0], eax
    124         mov     dword ptr Result[4], edx
    125         mov     eax, dword ptr Multiplicand[4]
    126         mul     Multiplier
    127         add     dword ptr Result[4], eax
    128     }
    129 
    130     return Result;
    131 #endif
    132 }
    133 
    134 UINT64
    135 DivU64x32 (
    136     IN UINT64   Dividend,
    137     IN UINTN    Divisor,
    138     OUT UINTN   *Remainder OPTIONAL
    139     )
    140 // divide 64bit by 32bit and get a 64bit result
    141 // N.B. only works for 31bit divisors!!
    142 {
    143 #ifdef __GNUC__
    144     if (Remainder)
    145 	*Remainder = Dividend % Divisor;
    146     return Dividend / Divisor;
    147 #else
    148     UINT32      Rem;
    149     UINT32      bit;
    150 
    151     ASSERT (Divisor != 0);
    152     ASSERT ((Divisor >> 31) == 0);
    153 
    154     //
    155     // For each bit in the dividend
    156     //
    157 
    158     Rem = 0;
    159     for (bit=0; bit < 64; bit++) {
    160         _asm {
    161             shl     dword ptr Dividend[0], 1    ; shift rem:dividend left one
    162             rcl     dword ptr Dividend[4], 1
    163             rcl     dword ptr Rem, 1
    164 
    165             mov     eax, Rem
    166             cmp     eax, Divisor                ; Is Rem >= Divisor?
    167             cmc                                 ; No - do nothing
    168             sbb     eax, eax                    ; Else,
    169             sub     dword ptr Dividend[0], eax  ;   set low bit in dividen
    170             and     eax, Divisor                ; and
    171             sub     Rem, eax                    ;   subtract divisor
    172         }
    173     }
    174 
    175     if (Remainder) {
    176         *Remainder = Rem;
    177     }
    178 
    179     return Dividend;
    180 #endif
    181 }
    182