xref: /DragonStub/lib/x86_64/math.c (revision 09027207f7c18af6caa45a744fc15c90b2a829db)
1530d68baSNigel Croxon /*++
2530d68baSNigel Croxon 
3530d68baSNigel Croxon Copyright (c) 1998  Intel Corporation
4530d68baSNigel Croxon 
5530d68baSNigel Croxon Module Name:
6530d68baSNigel Croxon 
7530d68baSNigel Croxon     math.c
8530d68baSNigel Croxon 
9530d68baSNigel Croxon Abstract:
10530d68baSNigel Croxon 
11530d68baSNigel Croxon 
12530d68baSNigel Croxon 
13530d68baSNigel Croxon 
14530d68baSNigel Croxon Revision History
15530d68baSNigel Croxon 
16530d68baSNigel Croxon --*/
17530d68baSNigel Croxon 
18530d68baSNigel Croxon #include "lib.h"
19530d68baSNigel Croxon 
20530d68baSNigel Croxon 
21530d68baSNigel Croxon //
22530d68baSNigel Croxon // Declare runtime functions
23530d68baSNigel Croxon //
24530d68baSNigel Croxon 
25530d68baSNigel Croxon #ifdef RUNTIME_CODE
26530d68baSNigel Croxon #ifndef __GNUC__
27530d68baSNigel Croxon #pragma RUNTIME_CODE(LShiftU64)
28530d68baSNigel Croxon #pragma RUNTIME_CODE(RShiftU64)
29530d68baSNigel Croxon #pragma RUNTIME_CODE(MultU64x32)
30530d68baSNigel Croxon #pragma RUNTIME_CODE(DivU64x32)
31530d68baSNigel Croxon #endif
32530d68baSNigel Croxon #endif
33530d68baSNigel Croxon 
34530d68baSNigel Croxon //
35530d68baSNigel Croxon //
36530d68baSNigel Croxon //
37530d68baSNigel Croxon 
38530d68baSNigel Croxon UINT64
LShiftU64(IN UINT64 Operand,IN UINTN Count)39530d68baSNigel Croxon LShiftU64 (
40530d68baSNigel Croxon     IN UINT64   Operand,
41530d68baSNigel Croxon     IN UINTN    Count
42530d68baSNigel Croxon     )
43530d68baSNigel Croxon // Left shift 64bit by 32bit and get a 64bit result
44530d68baSNigel Croxon {
45*09027207SNigel Croxon #if defined(__GNUC__) || defined(_MSC_EXTENSIONS)
46530d68baSNigel Croxon     return Operand << Count;
47530d68baSNigel Croxon #else
48530d68baSNigel Croxon     UINT64      Result;
49530d68baSNigel Croxon     _asm {
50530d68baSNigel Croxon         mov     eax, dword ptr Operand[0]
51530d68baSNigel Croxon         mov     edx, dword ptr Operand[4]
52530d68baSNigel Croxon         mov     ecx, Count
53530d68baSNigel Croxon         and     ecx, 63
54530d68baSNigel Croxon 
55530d68baSNigel Croxon         shld    edx, eax, cl
56530d68baSNigel Croxon         shl     eax, cl
57530d68baSNigel Croxon 
58530d68baSNigel Croxon         cmp     ecx, 32
59530d68baSNigel Croxon         jc      short ls10
60530d68baSNigel Croxon 
61530d68baSNigel Croxon         mov     edx, eax
62530d68baSNigel Croxon         xor     eax, eax
63530d68baSNigel Croxon 
64530d68baSNigel Croxon ls10:
65530d68baSNigel Croxon         mov     dword ptr Result[0], eax
66530d68baSNigel Croxon         mov     dword ptr Result[4], edx
67530d68baSNigel Croxon     }
68530d68baSNigel Croxon 
69530d68baSNigel Croxon     return Result;
70530d68baSNigel Croxon #endif
71530d68baSNigel Croxon }
72530d68baSNigel Croxon 
73530d68baSNigel Croxon UINT64
RShiftU64(IN UINT64 Operand,IN UINTN Count)74530d68baSNigel Croxon RShiftU64 (
75530d68baSNigel Croxon     IN UINT64   Operand,
76530d68baSNigel Croxon     IN UINTN    Count
77530d68baSNigel Croxon     )
78530d68baSNigel Croxon // Right shift 64bit by 32bit and get a 64bit result
79530d68baSNigel Croxon {
80*09027207SNigel Croxon #if defined(__GNUC__) || defined(_MSC_EXTENSIONS)
81530d68baSNigel Croxon     return Operand >> Count;
82530d68baSNigel Croxon #else
83530d68baSNigel Croxon     UINT64      Result;
84530d68baSNigel Croxon     _asm {
85530d68baSNigel Croxon         mov     eax, dword ptr Operand[0]
86530d68baSNigel Croxon         mov     edx, dword ptr Operand[4]
87530d68baSNigel Croxon         mov     ecx, Count
88530d68baSNigel Croxon         and     ecx, 63
89530d68baSNigel Croxon 
90530d68baSNigel Croxon         shrd    eax, edx, cl
91530d68baSNigel Croxon         shr     edx, cl
92530d68baSNigel Croxon 
93530d68baSNigel Croxon         cmp     ecx, 32
94530d68baSNigel Croxon         jc      short rs10
95530d68baSNigel Croxon 
96530d68baSNigel Croxon         mov     eax, edx
97530d68baSNigel Croxon         xor     edx, edx
98530d68baSNigel Croxon 
99530d68baSNigel Croxon rs10:
100530d68baSNigel Croxon         mov     dword ptr Result[0], eax
101530d68baSNigel Croxon         mov     dword ptr Result[4], edx
102530d68baSNigel Croxon     }
103530d68baSNigel Croxon 
104530d68baSNigel Croxon     return Result;
105530d68baSNigel Croxon #endif
106530d68baSNigel Croxon }
107530d68baSNigel Croxon 
108530d68baSNigel Croxon 
109530d68baSNigel Croxon UINT64
MultU64x32(IN UINT64 Multiplicand,IN UINTN Multiplier)110530d68baSNigel Croxon MultU64x32 (
111530d68baSNigel Croxon     IN UINT64   Multiplicand,
112530d68baSNigel Croxon     IN UINTN    Multiplier
113530d68baSNigel Croxon     )
114530d68baSNigel Croxon // Multiple 64bit by 32bit and get a 64bit result
115530d68baSNigel Croxon {
116*09027207SNigel Croxon #if defined(__GNUC__) || defined(_MSC_EXTENSIONS)
117530d68baSNigel Croxon     return Multiplicand * Multiplier;
118530d68baSNigel Croxon #else
119530d68baSNigel Croxon     UINT64      Result;
120530d68baSNigel Croxon     _asm {
121530d68baSNigel Croxon         mov     eax, dword ptr Multiplicand[0]
122530d68baSNigel Croxon         mul     Multiplier
123530d68baSNigel Croxon         mov     dword ptr Result[0], eax
124530d68baSNigel Croxon         mov     dword ptr Result[4], edx
125530d68baSNigel Croxon         mov     eax, dword ptr Multiplicand[4]
126530d68baSNigel Croxon         mul     Multiplier
127530d68baSNigel Croxon         add     dword ptr Result[4], eax
128530d68baSNigel Croxon     }
129530d68baSNigel Croxon 
130530d68baSNigel Croxon     return Result;
131530d68baSNigel Croxon #endif
132530d68baSNigel Croxon }
133530d68baSNigel Croxon 
134530d68baSNigel Croxon UINT64
DivU64x32(IN UINT64 Dividend,IN UINTN Divisor,OUT UINTN * Remainder OPTIONAL)135530d68baSNigel Croxon DivU64x32 (
136530d68baSNigel Croxon     IN UINT64   Dividend,
137530d68baSNigel Croxon     IN UINTN    Divisor,
138530d68baSNigel Croxon     OUT UINTN   *Remainder OPTIONAL
139530d68baSNigel Croxon     )
140530d68baSNigel Croxon // divide 64bit by 32bit and get a 64bit result
141530d68baSNigel Croxon // N.B. only works for 31bit divisors!!
142530d68baSNigel Croxon {
143*09027207SNigel Croxon #if defined(__GNUC__) || defined(_MSC_EXTENSIONS)
144530d68baSNigel Croxon     if (Remainder)
145530d68baSNigel Croxon 	*Remainder = Dividend % Divisor;
146530d68baSNigel Croxon     return Dividend / Divisor;
147530d68baSNigel Croxon #else
148530d68baSNigel Croxon     UINT32      Rem;
149530d68baSNigel Croxon     UINT32      bit;
150530d68baSNigel Croxon 
151530d68baSNigel Croxon     ASSERT (Divisor != 0);
152530d68baSNigel Croxon     ASSERT ((Divisor >> 31) == 0);
153530d68baSNigel Croxon 
154530d68baSNigel Croxon     //
155530d68baSNigel Croxon     // For each bit in the dividend
156530d68baSNigel Croxon     //
157530d68baSNigel Croxon 
158530d68baSNigel Croxon     Rem = 0;
159530d68baSNigel Croxon     for (bit=0; bit < 64; bit++) {
160530d68baSNigel Croxon         _asm {
161530d68baSNigel Croxon             shl     dword ptr Dividend[0], 1    ; shift rem:dividend left one
162530d68baSNigel Croxon             rcl     dword ptr Dividend[4], 1
163530d68baSNigel Croxon             rcl     dword ptr Rem, 1
164530d68baSNigel Croxon 
165530d68baSNigel Croxon             mov     eax, Rem
166530d68baSNigel Croxon             cmp     eax, Divisor                ; Is Rem >= Divisor?
167530d68baSNigel Croxon             cmc                                 ; No - do nothing
168530d68baSNigel Croxon             sbb     eax, eax                    ; Else,
169530d68baSNigel Croxon             sub     dword ptr Dividend[0], eax  ;   set low bit in dividen
170530d68baSNigel Croxon             and     eax, Divisor                ; and
171530d68baSNigel Croxon             sub     Rem, eax                    ;   subtract divisor
172530d68baSNigel Croxon         }
173530d68baSNigel Croxon     }
174530d68baSNigel Croxon 
175530d68baSNigel Croxon     if (Remainder) {
176530d68baSNigel Croxon         *Remainder = Rem;
177530d68baSNigel Croxon     }
178530d68baSNigel Croxon 
179530d68baSNigel Croxon     return Dividend;
180530d68baSNigel Croxon #endif
181530d68baSNigel Croxon }
182