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