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