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