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