Subversion Repositories HelenOS

Rev

Rev 2726 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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