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