1 /** @file
2   Leaf math worker functions that require 64-bit arithmetic support from the
3   compiler.
4 
5   Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions of the BSD License
8   which accompanies this distribution.  The full text of the license may be found at
9   http://opensource.org/licenses/bsd-license.php.
10 
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include "BaseLibInternals.h"
17 
18 /**
19   Shifts a 64-bit integer left between 0 and 63 bits. The low bits
20   are filled with zeros. The shifted value is returned.
21 
22   This function shifts the 64-bit value Operand to the left by Count bits. The
23   low Count bits are set to zero. The shifted value is returned.
24 
25   @param  Operand The 64-bit operand to shift left.
26   @param  Count   The number of bits to shift left.
27 
28   @return Operand << Count.
29 
30 **/
31 UINT64
32 EFIAPI
InternalMathLShiftU64(IN UINT64 Operand,IN UINTN Count)33 InternalMathLShiftU64 (
34   IN      UINT64                    Operand,
35   IN      UINTN                     Count
36   )
37 {
38   return Operand << Count;
39 }
40 
41 /**
42   Shifts a 64-bit integer right between 0 and 63 bits. This high bits
43   are filled with zeros. The shifted value is returned.
44 
45   This function shifts the 64-bit value Operand to the right by Count bits. The
46   high Count bits are set to zero. The shifted value is returned.
47 
48   @param  Operand The 64-bit operand to shift right.
49   @param  Count   The number of bits to shift right.
50 
51   @return Operand >> Count.
52 
53 **/
54 UINT64
55 EFIAPI
InternalMathRShiftU64(IN UINT64 Operand,IN UINTN Count)56 InternalMathRShiftU64 (
57   IN      UINT64                    Operand,
58   IN      UINTN                     Count
59   )
60 {
61   return Operand >> Count;
62 }
63 
64 /**
65   Shifts a 64-bit integer right between 0 and 63 bits. The high bits
66   are filled with original integer's bit 63. The shifted value is returned.
67 
68   This function shifts the 64-bit value Operand to the right by Count bits. The
69   high Count bits are set to bit 63 of Operand.  The shifted value is returned.
70 
71   @param  Operand The 64-bit operand to shift right.
72   @param  Count   The number of bits to shift right.
73 
74   @return Operand arithmetically shifted right by Count.
75 
76 **/
77 UINT64
78 EFIAPI
InternalMathARShiftU64(IN UINT64 Operand,IN UINTN Count)79 InternalMathARShiftU64 (
80   IN      UINT64                    Operand,
81   IN      UINTN                     Count
82   )
83 {
84   INTN  TestValue;
85 
86   //
87   // Test if this compiler supports arithmetic shift
88   //
89   TestValue = (INTN)((INT64)(1ULL << 63) >> 63);
90   if (TestValue == -1) {
91     //
92     // Arithmetic shift is supported
93     //
94     return (UINT64)((INT64)Operand >> Count);
95   }
96 
97   //
98   // Arithmetic is not supported
99   //
100   return (Operand >> Count) |
101          ((INTN)Operand < 0 ? ~((UINTN)-1 >> Count) : 0);
102 }
103 
104 
105 /**
106   Rotates a 64-bit integer left between 0 and 63 bits, filling
107   the low bits with the high bits that were rotated.
108 
109   This function rotates the 64-bit value Operand to the left by Count bits. The
110   low Count bits are fill with the high Count bits of Operand. The rotated
111   value is returned.
112 
113   @param  Operand The 64-bit operand to rotate left.
114   @param  Count   The number of bits to rotate left.
115 
116   @return Operand <<< Count.
117 
118 **/
119 UINT64
120 EFIAPI
InternalMathLRotU64(IN UINT64 Operand,IN UINTN Count)121 InternalMathLRotU64 (
122   IN      UINT64                    Operand,
123   IN      UINTN                     Count
124   )
125 {
126   return (Operand << Count) | (Operand >> (64 - Count));
127 }
128 
129 /**
130   Rotates a 64-bit integer right between 0 and 63 bits, filling
131   the high bits with the high low bits that were rotated.
132 
133   This function rotates the 64-bit value Operand to the right by Count bits.
134   The high Count bits are fill with the low Count bits of Operand. The rotated
135   value is returned.
136 
137   @param  Operand The 64-bit operand to rotate right.
138   @param  Count   The number of bits to rotate right.
139 
140   @return Operand >>> Count.
141 
142 **/
143 UINT64
144 EFIAPI
InternalMathRRotU64(IN UINT64 Operand,IN UINTN Count)145 InternalMathRRotU64 (
146   IN      UINT64                    Operand,
147   IN      UINTN                     Count
148   )
149 {
150   return (Operand >> Count) | (Operand << (64 - Count));
151 }
152 
153 /**
154   Switches the endianess of a 64-bit integer.
155 
156   This function swaps the bytes in a 64-bit unsigned value to switch the value
157   from little endian to big endian or vice versa. The byte swapped value is
158   returned.
159 
160   @param  Operand A 64-bit unsigned value.
161 
162   @return The byte swapped Operand.
163 
164 **/
165 UINT64
166 EFIAPI
InternalMathSwapBytes64(IN UINT64 Operand)167 InternalMathSwapBytes64 (
168   IN      UINT64                    Operand
169   )
170 {
171   UINT64  LowerBytes;
172   UINT64  HigherBytes;
173 
174   LowerBytes  = (UINT64) SwapBytes32 ((UINT32) Operand);
175   HigherBytes = (UINT64) SwapBytes32 ((UINT32) (Operand >> 32));
176 
177   return (LowerBytes << 32 | HigherBytes);
178 }
179 
180 /**
181   Multiplies a 64-bit unsigned integer by a 32-bit unsigned integer
182   and generates a 64-bit unsigned result.
183 
184   This function multiplies the 64-bit unsigned value Multiplicand by the 32-bit
185   unsigned value Multiplier and generates a 64-bit unsigned result. This 64-
186   bit unsigned result is returned.
187 
188   @param  Multiplicand  A 64-bit unsigned value.
189   @param  Multiplier    A 32-bit unsigned value.
190 
191   @return Multiplicand * Multiplier
192 
193 **/
194 UINT64
195 EFIAPI
InternalMathMultU64x32(IN UINT64 Multiplicand,IN UINT32 Multiplier)196 InternalMathMultU64x32 (
197   IN      UINT64                    Multiplicand,
198   IN      UINT32                    Multiplier
199   )
200 {
201   return Multiplicand * Multiplier;
202 }
203 
204 
205 /**
206   Multiplies a 64-bit unsigned integer by a 64-bit unsigned integer
207   and generates a 64-bit unsigned result.
208 
209   This function multiplies the 64-bit unsigned value Multiplicand by the 64-bit
210   unsigned value Multiplier and generates a 64-bit unsigned result. This 64-
211   bit unsigned result is returned.
212 
213   @param  Multiplicand  A 64-bit unsigned value.
214   @param  Multiplier    A 64-bit unsigned value.
215 
216   @return Multiplicand * Multiplier.
217 
218 **/
219 UINT64
220 EFIAPI
InternalMathMultU64x64(IN UINT64 Multiplicand,IN UINT64 Multiplier)221 InternalMathMultU64x64 (
222   IN      UINT64                    Multiplicand,
223   IN      UINT64                    Multiplier
224   )
225 {
226   return Multiplicand * Multiplier;
227 }
228 
229 /**
230   Divides a 64-bit unsigned integer by a 32-bit unsigned integer and
231   generates a 64-bit unsigned result.
232 
233   This function divides the 64-bit unsigned value Dividend by the 32-bit
234   unsigned value Divisor and generates a 64-bit unsigned quotient. This
235   function returns the 64-bit unsigned quotient.
236 
237   @param  Dividend  A 64-bit unsigned value.
238   @param  Divisor   A 32-bit unsigned value.
239 
240   @return Dividend / Divisor.
241 
242 **/
243 UINT64
244 EFIAPI
InternalMathDivU64x32(IN UINT64 Dividend,IN UINT32 Divisor)245 InternalMathDivU64x32 (
246   IN      UINT64                    Dividend,
247   IN      UINT32                    Divisor
248   )
249 {
250   return Dividend / Divisor;
251 }
252 
253 /**
254   Divides a 64-bit unsigned integer by a 32-bit unsigned integer and
255   generates a 32-bit unsigned remainder.
256 
257   This function divides the 64-bit unsigned value Dividend by the 32-bit
258   unsigned value Divisor and generates a 32-bit remainder. This function
259   returns the 32-bit unsigned remainder.
260 
261   @param  Dividend  A 64-bit unsigned value.
262   @param  Divisor   A 32-bit unsigned value.
263 
264   @return Dividend % Divisor.
265 
266 **/
267 UINT32
268 EFIAPI
InternalMathModU64x32(IN UINT64 Dividend,IN UINT32 Divisor)269 InternalMathModU64x32 (
270   IN      UINT64                    Dividend,
271   IN      UINT32                    Divisor
272   )
273 {
274   return (UINT32)(Dividend % Divisor);
275 }
276 
277 /**
278   Divides a 64-bit unsigned integer by a 32-bit unsigned integer and
279   generates a 64-bit unsigned result and an optional 32-bit unsigned remainder.
280 
281   This function divides the 64-bit unsigned value Dividend by the 32-bit
282   unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder
283   is not NULL, then the 32-bit unsigned remainder is returned in Remainder.
284   This function returns the 64-bit unsigned quotient.
285 
286   @param  Dividend  A 64-bit unsigned value.
287   @param  Divisor   A 32-bit unsigned value.
288   @param  Remainder A pointer to a 32-bit unsigned value. This parameter is
289                     optional and may be NULL.
290 
291   @return Dividend / Divisor.
292 
293 **/
294 UINT64
295 EFIAPI
InternalMathDivRemU64x32(IN UINT64 Dividend,IN UINT32 Divisor,OUT UINT32 * Remainder OPTIONAL)296 InternalMathDivRemU64x32 (
297   IN      UINT64                    Dividend,
298   IN      UINT32                    Divisor,
299   OUT     UINT32                    *Remainder OPTIONAL
300   )
301 {
302   if (Remainder != NULL) {
303     *Remainder = (UINT32)(Dividend % Divisor);
304   }
305   return Dividend / Divisor;
306 }
307 
308 /**
309   Divides a 64-bit unsigned integer by a 64-bit unsigned integer and
310   generates a 64-bit unsigned result and an optional 64-bit unsigned remainder.
311 
312   This function divides the 64-bit unsigned value Dividend by the 64-bit
313   unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder
314   is not NULL, then the 64-bit unsigned remainder is returned in Remainder.
315   This function returns the 64-bit unsigned quotient.
316 
317   @param  Dividend  A 64-bit unsigned value.
318   @param  Divisor   A 64-bit unsigned value.
319   @param  Remainder A pointer to a 64-bit unsigned value. This parameter is
320                     optional and may be NULL.
321 
322   @return Dividend / Divisor
323 
324 **/
325 UINT64
326 EFIAPI
InternalMathDivRemU64x64(IN UINT64 Dividend,IN UINT64 Divisor,OUT UINT64 * Remainder OPTIONAL)327 InternalMathDivRemU64x64 (
328   IN      UINT64                    Dividend,
329   IN      UINT64                    Divisor,
330   OUT     UINT64                    *Remainder OPTIONAL
331   )
332 {
333   if (Remainder != NULL) {
334     *Remainder = Dividend % Divisor;
335   }
336   return Dividend / Divisor;
337 }
338 
339 /**
340   Divides a 64-bit signed integer by a 64-bit signed integer and
341   generates a 64-bit signed result and an optional 64-bit signed remainder.
342 
343   This function divides the 64-bit signed value Dividend by the 64-bit
344   signed value Divisor and generates a 64-bit signed quotient. If Remainder
345   is not NULL, then the 64-bit signed remainder is returned in Remainder.
346   This function returns the 64-bit signed quotient.
347 
348   @param  Dividend  A 64-bit signed value.
349   @param  Divisor   A 64-bit signed value.
350   @param  Remainder A pointer to a 64-bit signed value. This parameter is
351                     optional and may be NULL.
352 
353   @return Dividend / Divisor.
354 
355 **/
356 INT64
357 EFIAPI
InternalMathDivRemS64x64(IN INT64 Dividend,IN INT64 Divisor,OUT INT64 * Remainder OPTIONAL)358 InternalMathDivRemS64x64 (
359   IN      INT64                     Dividend,
360   IN      INT64                     Divisor,
361   OUT     INT64                     *Remainder  OPTIONAL
362   )
363 {
364   if (Remainder != NULL) {
365     *Remainder = Dividend % Divisor;
366   }
367   return Dividend / Divisor;
368 }
369