1 /** @file
2   Bit field functions of BaseLib.
3 
4   Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5   SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "BaseLibInternals.h"
10 
11 /**
12   Worker function that returns a bit field from Operand.
13 
14   Returns the bitfield specified by the StartBit and the EndBit from Operand.
15 
16   @param  Operand   Operand on which to perform the bitfield operation.
17   @param  StartBit  The ordinal of the least significant bit in the bit field.
18   @param  EndBit    The ordinal of the most significant bit in the bit field.
19 
20   @return The bit field read.
21 
22 **/
23 UINTN
24 EFIAPI
InternalBaseLibBitFieldReadUint(IN UINTN Operand,IN UINTN StartBit,IN UINTN EndBit)25 InternalBaseLibBitFieldReadUint (
26   IN      UINTN                     Operand,
27   IN      UINTN                     StartBit,
28   IN      UINTN                     EndBit
29   )
30 {
31   //
32   // ~((UINTN)-2 << EndBit) is a mask in which bit[0] thru bit[EndBit]
33   // are 1's while bit[EndBit + 1] thru the most significant bit are 0's.
34   //
35   return (Operand & ~((UINTN)-2 << EndBit)) >> StartBit;
36 }
37 
38 /**
39   Worker function that reads a bit field from Operand, performs a bitwise OR,
40   and returns the result.
41 
42   Performs a bitwise OR between the bit field specified by StartBit and EndBit
43   in Operand and the value specified by AndData. All other bits in Operand are
44   preserved. The new value is returned.
45 
46   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
47 
48   @param  Operand   Operand on which to perform the bitfield operation.
49   @param  StartBit  The ordinal of the least significant bit in the bit field.
50   @param  EndBit    The ordinal of the most significant bit in the bit field.
51   @param  OrData    The value to OR with the read value from the value.
52 
53   @return The new value.
54 
55 **/
56 UINTN
57 EFIAPI
InternalBaseLibBitFieldOrUint(IN UINTN Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINTN OrData)58 InternalBaseLibBitFieldOrUint (
59   IN      UINTN                     Operand,
60   IN      UINTN                     StartBit,
61   IN      UINTN                     EndBit,
62   IN      UINTN                     OrData
63   )
64 {
65   //
66   // Higher bits in OrData those are not used must be zero.
67   //
68   // EndBit - StartBit + 1 might be 32 while the result right shifting 32 on a 32bit integer is undefined,
69   // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly.
70   //
71   ASSERT ((OrData >> (EndBit - StartBit)) == ((OrData >> (EndBit - StartBit)) & 1));
72 
73   //
74   // ~((UINTN)-2 << EndBit) is a mask in which bit[0] thru bit[EndBit]
75   // are 1's while bit[EndBit + 1] thru the most significant bit are 0's.
76   //
77   return Operand | ((OrData << StartBit) & ~((UINTN) -2 << EndBit));
78 }
79 
80 /**
81   Worker function that reads a bit field from Operand, performs a bitwise AND,
82   and returns the result.
83 
84   Performs a bitwise AND between the bit field specified by StartBit and EndBit
85   in Operand and the value specified by AndData. All other bits in Operand are
86   preserved. The new value is returned.
87 
88   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
89 
90   @param  Operand   Operand on which to perform the bitfield operation.
91   @param  StartBit  The ordinal of the least significant bit in the bit field.
92   @param  EndBit    The ordinal of the most significant bit in the bit field.
93   @param  AndData    The value to And with the read value from the value.
94 
95   @return The new value.
96 
97 **/
98 UINTN
99 EFIAPI
InternalBaseLibBitFieldAndUint(IN UINTN Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINTN AndData)100 InternalBaseLibBitFieldAndUint (
101   IN      UINTN                     Operand,
102   IN      UINTN                     StartBit,
103   IN      UINTN                     EndBit,
104   IN      UINTN                     AndData
105   )
106 {
107   //
108   // Higher bits in AndData those are not used must be zero.
109   //
110   // EndBit - StartBit + 1 might be 32 while the result right shifting 32 on a 32bit integer is undefined,
111   // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly.
112   //
113   ASSERT ((AndData >> (EndBit - StartBit)) == ((AndData >> (EndBit - StartBit)) & 1));
114 
115   //
116   // ~((UINTN)-2 << EndBit) is a mask in which bit[0] thru bit[EndBit]
117   // are 1's while bit[EndBit + 1] thru the most significant bit are 0's.
118   //
119   return Operand & ~((~AndData << StartBit) & ~((UINTN)-2 << EndBit));
120 }
121 
122 /**
123   Returns a bit field from an 8-bit value.
124 
125   Returns the bitfield specified by the StartBit and the EndBit from Operand.
126 
127   If 8-bit operations are not supported, then ASSERT().
128   If StartBit is greater than 7, then ASSERT().
129   If EndBit is greater than 7, then ASSERT().
130   If EndBit is less than StartBit, then ASSERT().
131 
132   @param  Operand   Operand on which to perform the bitfield operation.
133   @param  StartBit  The ordinal of the least significant bit in the bit field.
134                     Range 0..7.
135   @param  EndBit    The ordinal of the most significant bit in the bit field.
136                     Range 0..7.
137 
138   @return The bit field read.
139 
140 **/
141 UINT8
142 EFIAPI
BitFieldRead8(IN UINT8 Operand,IN UINTN StartBit,IN UINTN EndBit)143 BitFieldRead8 (
144   IN      UINT8                     Operand,
145   IN      UINTN                     StartBit,
146   IN      UINTN                     EndBit
147   )
148 {
149   ASSERT (EndBit < 8);
150   ASSERT (StartBit <= EndBit);
151   return (UINT8)InternalBaseLibBitFieldReadUint (Operand, StartBit, EndBit);
152 }
153 
154 /**
155   Writes a bit field to an 8-bit value, and returns the result.
156 
157   Writes Value to the bit field specified by the StartBit and the EndBit in
158   Operand. All other bits in Operand are preserved. The new 8-bit value is
159   returned.
160 
161   If 8-bit operations are not supported, then ASSERT().
162   If StartBit is greater than 7, then ASSERT().
163   If EndBit is greater than 7, then ASSERT().
164   If EndBit is less than StartBit, then ASSERT().
165   If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
166 
167   @param  Operand   Operand on which to perform the bitfield operation.
168   @param  StartBit  The ordinal of the least significant bit in the bit field.
169                     Range 0..7.
170   @param  EndBit    The ordinal of the most significant bit in the bit field.
171                     Range 0..7.
172   @param  Value     The new value of the bit field.
173 
174   @return The new 8-bit value.
175 
176 **/
177 UINT8
178 EFIAPI
BitFieldWrite8(IN UINT8 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 Value)179 BitFieldWrite8 (
180   IN      UINT8                     Operand,
181   IN      UINTN                     StartBit,
182   IN      UINTN                     EndBit,
183   IN      UINT8                     Value
184   )
185 {
186   ASSERT (EndBit < 8);
187   ASSERT (StartBit <= EndBit);
188   return BitFieldAndThenOr8 (Operand, StartBit, EndBit, 0, Value);
189 }
190 
191 /**
192   Reads a bit field from an 8-bit value, performs a bitwise OR, and returns the
193   result.
194 
195   Performs a bitwise OR between the bit field specified by StartBit
196   and EndBit in Operand and the value specified by OrData. All other bits in
197   Operand are preserved. The new 8-bit value is returned.
198 
199   If 8-bit operations are not supported, then ASSERT().
200   If StartBit is greater than 7, then ASSERT().
201   If EndBit is greater than 7, then ASSERT().
202   If EndBit is less than StartBit, then ASSERT().
203   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
204 
205   @param  Operand   Operand on which to perform the bitfield operation.
206   @param  StartBit  The ordinal of the least significant bit in the bit field.
207                     Range 0..7.
208   @param  EndBit    The ordinal of the most significant bit in the bit field.
209                     Range 0..7.
210   @param  OrData    The value to OR with the read value from the value.
211 
212   @return The new 8-bit value.
213 
214 **/
215 UINT8
216 EFIAPI
BitFieldOr8(IN UINT8 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 OrData)217 BitFieldOr8 (
218   IN      UINT8                     Operand,
219   IN      UINTN                     StartBit,
220   IN      UINTN                     EndBit,
221   IN      UINT8                     OrData
222   )
223 {
224   ASSERT (EndBit < 8);
225   ASSERT (StartBit <= EndBit);
226   return (UINT8)InternalBaseLibBitFieldOrUint (Operand, StartBit, EndBit, OrData);
227 }
228 
229 /**
230   Reads a bit field from an 8-bit value, performs a bitwise AND, and returns
231   the result.
232 
233   Performs a bitwise AND between the bit field specified by StartBit and EndBit
234   in Operand and the value specified by AndData. All other bits in Operand are
235   preserved. The new 8-bit value is returned.
236 
237   If 8-bit operations are not supported, then ASSERT().
238   If StartBit is greater than 7, then ASSERT().
239   If EndBit is greater than 7, then ASSERT().
240   If EndBit is less than StartBit, then ASSERT().
241   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
242 
243   @param  Operand   Operand on which to perform the bitfield operation.
244   @param  StartBit  The ordinal of the least significant bit in the bit field.
245                     Range 0..7.
246   @param  EndBit    The ordinal of the most significant bit in the bit field.
247                     Range 0..7.
248   @param  AndData   The value to AND with the read value from the value.
249 
250   @return The new 8-bit value.
251 
252 **/
253 UINT8
254 EFIAPI
BitFieldAnd8(IN UINT8 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 AndData)255 BitFieldAnd8 (
256   IN      UINT8                     Operand,
257   IN      UINTN                     StartBit,
258   IN      UINTN                     EndBit,
259   IN      UINT8                     AndData
260   )
261 {
262   ASSERT (EndBit < 8);
263   ASSERT (StartBit <= EndBit);
264   return (UINT8)InternalBaseLibBitFieldAndUint (Operand, StartBit, EndBit, AndData);
265 }
266 
267 /**
268   Reads a bit field from an 8-bit value, performs a bitwise AND followed by a
269   bitwise OR, and returns the result.
270 
271   Performs a bitwise AND between the bit field specified by StartBit and EndBit
272   in Operand and the value specified by AndData, followed by a bitwise
273   OR with value specified by OrData. All other bits in Operand are
274   preserved. The new 8-bit value is returned.
275 
276   If 8-bit operations are not supported, then ASSERT().
277   If StartBit is greater than 7, then ASSERT().
278   If EndBit is greater than 7, then ASSERT().
279   If EndBit is less than StartBit, then ASSERT().
280   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
281   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
282 
283   @param  Operand   Operand on which to perform the bitfield operation.
284   @param  StartBit  The ordinal of the least significant bit in the bit field.
285                     Range 0..7.
286   @param  EndBit    The ordinal of the most significant bit in the bit field.
287                     Range 0..7.
288   @param  AndData   The value to AND with the read value from the value.
289   @param  OrData    The value to OR with the result of the AND operation.
290 
291   @return The new 8-bit value.
292 
293 **/
294 UINT8
295 EFIAPI
BitFieldAndThenOr8(IN UINT8 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT8 AndData,IN UINT8 OrData)296 BitFieldAndThenOr8 (
297   IN      UINT8                     Operand,
298   IN      UINTN                     StartBit,
299   IN      UINTN                     EndBit,
300   IN      UINT8                     AndData,
301   IN      UINT8                     OrData
302   )
303 {
304   ASSERT (EndBit < 8);
305   ASSERT (StartBit <= EndBit);
306   return BitFieldOr8 (
307            BitFieldAnd8 (Operand, StartBit, EndBit, AndData),
308            StartBit,
309            EndBit,
310            OrData
311            );
312 }
313 
314 /**
315   Returns a bit field from a 16-bit value.
316 
317   Returns the bitfield specified by the StartBit and the EndBit from Operand.
318 
319   If 16-bit operations are not supported, then ASSERT().
320   If StartBit is greater than 15, then ASSERT().
321   If EndBit is greater than 15, then ASSERT().
322   If EndBit is less than StartBit, then ASSERT().
323 
324   @param  Operand   Operand on which to perform the bitfield operation.
325   @param  StartBit  The ordinal of the least significant bit in the bit field.
326                     Range 0..15.
327   @param  EndBit    The ordinal of the most significant bit in the bit field.
328                     Range 0..15.
329 
330   @return The bit field read.
331 
332 **/
333 UINT16
334 EFIAPI
BitFieldRead16(IN UINT16 Operand,IN UINTN StartBit,IN UINTN EndBit)335 BitFieldRead16 (
336   IN      UINT16                    Operand,
337   IN      UINTN                     StartBit,
338   IN      UINTN                     EndBit
339   )
340 {
341   ASSERT (EndBit < 16);
342   ASSERT (StartBit <= EndBit);
343   return (UINT16)InternalBaseLibBitFieldReadUint (Operand, StartBit, EndBit);
344 }
345 
346 /**
347   Writes a bit field to a 16-bit value, and returns the result.
348 
349   Writes Value to the bit field specified by the StartBit and the EndBit in
350   Operand. All other bits in Operand are preserved. The new 16-bit value is
351   returned.
352 
353   If 16-bit operations are not supported, then ASSERT().
354   If StartBit is greater than 15, then ASSERT().
355   If EndBit is greater than 15, then ASSERT().
356   If EndBit is less than StartBit, then ASSERT().
357   If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
358 
359   @param  Operand   Operand on which to perform the bitfield operation.
360   @param  StartBit  The ordinal of the least significant bit in the bit field.
361                     Range 0..15.
362   @param  EndBit    The ordinal of the most significant bit in the bit field.
363                     Range 0..15.
364   @param  Value     The new value of the bit field.
365 
366   @return The new 16-bit value.
367 
368 **/
369 UINT16
370 EFIAPI
BitFieldWrite16(IN UINT16 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 Value)371 BitFieldWrite16 (
372   IN      UINT16                    Operand,
373   IN      UINTN                     StartBit,
374   IN      UINTN                     EndBit,
375   IN      UINT16                    Value
376   )
377 {
378   ASSERT (EndBit < 16);
379   ASSERT (StartBit <= EndBit);
380   return BitFieldAndThenOr16 (Operand, StartBit, EndBit, 0, Value);
381 }
382 
383 /**
384   Reads a bit field from a 16-bit value, performs a bitwise OR, and returns the
385   result.
386 
387   Performs a bitwise OR between the bit field specified by StartBit
388   and EndBit in Operand and the value specified by OrData. All other bits in
389   Operand are preserved. The new 16-bit value is returned.
390 
391   If 16-bit operations are not supported, then ASSERT().
392   If StartBit is greater than 15, then ASSERT().
393   If EndBit is greater than 15, then ASSERT().
394   If EndBit is less than StartBit, then ASSERT().
395   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
396 
397   @param  Operand   Operand on which to perform the bitfield operation.
398   @param  StartBit  The ordinal of the least significant bit in the bit field.
399                     Range 0..15.
400   @param  EndBit    The ordinal of the most significant bit in the bit field.
401                     Range 0..15.
402   @param  OrData    The value to OR with the read value from the value.
403 
404   @return The new 16-bit value.
405 
406 **/
407 UINT16
408 EFIAPI
BitFieldOr16(IN UINT16 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 OrData)409 BitFieldOr16 (
410   IN      UINT16                    Operand,
411   IN      UINTN                     StartBit,
412   IN      UINTN                     EndBit,
413   IN      UINT16                    OrData
414   )
415 {
416   ASSERT (EndBit < 16);
417   ASSERT (StartBit <= EndBit);
418   return (UINT16)InternalBaseLibBitFieldOrUint (Operand, StartBit, EndBit, OrData);
419 }
420 
421 /**
422   Reads a bit field from a 16-bit value, performs a bitwise AND, and returns
423   the result.
424 
425   Performs a bitwise AND between the bit field specified by StartBit and EndBit
426   in Operand and the value specified by AndData. All other bits in Operand are
427   preserved. The new 16-bit value is returned.
428 
429   If 16-bit operations are not supported, then ASSERT().
430   If StartBit is greater than 15, then ASSERT().
431   If EndBit is greater than 15, then ASSERT().
432   If EndBit is less than StartBit, then ASSERT().
433   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
434 
435   @param  Operand   Operand on which to perform the bitfield operation.
436   @param  StartBit  The ordinal of the least significant bit in the bit field.
437                     Range 0..15.
438   @param  EndBit    The ordinal of the most significant bit in the bit field.
439                     Range 0..15.
440   @param  AndData   The value to AND with the read value from the value.
441 
442   @return The new 16-bit value.
443 
444 **/
445 UINT16
446 EFIAPI
BitFieldAnd16(IN UINT16 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 AndData)447 BitFieldAnd16 (
448   IN      UINT16                    Operand,
449   IN      UINTN                     StartBit,
450   IN      UINTN                     EndBit,
451   IN      UINT16                    AndData
452   )
453 {
454   ASSERT (EndBit < 16);
455   ASSERT (StartBit <= EndBit);
456   return (UINT16)InternalBaseLibBitFieldAndUint (Operand, StartBit, EndBit, AndData);
457 }
458 
459 /**
460   Reads a bit field from a 16-bit value, performs a bitwise AND followed by a
461   bitwise OR, and returns the result.
462 
463   Performs a bitwise AND between the bit field specified by StartBit and EndBit
464   in Operand and the value specified by AndData, followed by a bitwise
465   OR with value specified by OrData. All other bits in Operand are
466   preserved. The new 16-bit value is returned.
467 
468   If 16-bit operations are not supported, then ASSERT().
469   If StartBit is greater than 15, then ASSERT().
470   If EndBit is greater than 15, then ASSERT().
471   If EndBit is less than StartBit, then ASSERT().
472   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
473   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
474 
475   @param  Operand   Operand on which to perform the bitfield operation.
476   @param  StartBit  The ordinal of the least significant bit in the bit field.
477                     Range 0..15.
478   @param  EndBit    The ordinal of the most significant bit in the bit field.
479                     Range 0..15.
480   @param  AndData   The value to AND with the read value from the value.
481   @param  OrData    The value to OR with the result of the AND operation.
482 
483   @return The new 16-bit value.
484 
485 **/
486 UINT16
487 EFIAPI
BitFieldAndThenOr16(IN UINT16 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT16 AndData,IN UINT16 OrData)488 BitFieldAndThenOr16 (
489   IN      UINT16                    Operand,
490   IN      UINTN                     StartBit,
491   IN      UINTN                     EndBit,
492   IN      UINT16                    AndData,
493   IN      UINT16                    OrData
494   )
495 {
496   ASSERT (EndBit < 16);
497   ASSERT (StartBit <= EndBit);
498   return BitFieldOr16 (
499            BitFieldAnd16 (Operand, StartBit, EndBit, AndData),
500            StartBit,
501            EndBit,
502            OrData
503            );
504 }
505 
506 /**
507   Returns a bit field from a 32-bit value.
508 
509   Returns the bitfield specified by the StartBit and the EndBit from Operand.
510 
511   If 32-bit operations are not supported, then ASSERT().
512   If StartBit is greater than 31, then ASSERT().
513   If EndBit is greater than 31, then ASSERT().
514   If EndBit is less than StartBit, then ASSERT().
515 
516   @param  Operand   Operand on which to perform the bitfield operation.
517   @param  StartBit  The ordinal of the least significant bit in the bit field.
518                     Range 0..31.
519   @param  EndBit    The ordinal of the most significant bit in the bit field.
520                     Range 0..31.
521 
522   @return The bit field read.
523 
524 **/
525 UINT32
526 EFIAPI
BitFieldRead32(IN UINT32 Operand,IN UINTN StartBit,IN UINTN EndBit)527 BitFieldRead32 (
528   IN      UINT32                    Operand,
529   IN      UINTN                     StartBit,
530   IN      UINTN                     EndBit
531   )
532 {
533   ASSERT (EndBit < 32);
534   ASSERT (StartBit <= EndBit);
535   return (UINT32)InternalBaseLibBitFieldReadUint (Operand, StartBit, EndBit);
536 }
537 
538 /**
539   Writes a bit field to a 32-bit value, and returns the result.
540 
541   Writes Value to the bit field specified by the StartBit and the EndBit in
542   Operand. All other bits in Operand are preserved. The new 32-bit value is
543   returned.
544 
545   If 32-bit operations are not supported, then ASSERT().
546   If StartBit is greater than 31, then ASSERT().
547   If EndBit is greater than 31, then ASSERT().
548   If EndBit is less than StartBit, then ASSERT().
549   If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
550 
551   @param  Operand   Operand on which to perform the bitfield operation.
552   @param  StartBit  The ordinal of the least significant bit in the bit field.
553                     Range 0..31.
554   @param  EndBit    The ordinal of the most significant bit in the bit field.
555                     Range 0..31.
556   @param  Value     The new value of the bit field.
557 
558   @return The new 32-bit value.
559 
560 **/
561 UINT32
562 EFIAPI
BitFieldWrite32(IN UINT32 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 Value)563 BitFieldWrite32 (
564   IN      UINT32                    Operand,
565   IN      UINTN                     StartBit,
566   IN      UINTN                     EndBit,
567   IN      UINT32                    Value
568   )
569 {
570   ASSERT (EndBit < 32);
571   ASSERT (StartBit <= EndBit);
572   return BitFieldAndThenOr32 (Operand, StartBit, EndBit, 0, Value);
573 }
574 
575 /**
576   Reads a bit field from a 32-bit value, performs a bitwise OR, and returns the
577   result.
578 
579   Performs a bitwise OR between the bit field specified by StartBit
580   and EndBit in Operand and the value specified by OrData. All other bits in
581   Operand are preserved. The new 32-bit value is returned.
582 
583   If 32-bit operations are not supported, then ASSERT().
584   If StartBit is greater than 31, then ASSERT().
585   If EndBit is greater than 31, then ASSERT().
586   If EndBit is less than StartBit, then ASSERT().
587   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
588 
589   @param  Operand   Operand on which to perform the bitfield operation.
590   @param  StartBit  The ordinal of the least significant bit in the bit field.
591                     Range 0..31.
592   @param  EndBit    The ordinal of the most significant bit in the bit field.
593                     Range 0..31.
594   @param  OrData    The value to OR with the read value from the value.
595 
596   @return The new 32-bit value.
597 
598 **/
599 UINT32
600 EFIAPI
BitFieldOr32(IN UINT32 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 OrData)601 BitFieldOr32 (
602   IN      UINT32                    Operand,
603   IN      UINTN                     StartBit,
604   IN      UINTN                     EndBit,
605   IN      UINT32                    OrData
606   )
607 {
608   ASSERT (EndBit < 32);
609   ASSERT (StartBit <= EndBit);
610   return (UINT32)InternalBaseLibBitFieldOrUint (Operand, StartBit, EndBit, OrData);
611 }
612 
613 /**
614   Reads a bit field from a 32-bit value, performs a bitwise AND, and returns
615   the result.
616 
617   Performs a bitwise AND between the bit field specified by StartBit and EndBit
618   in Operand and the value specified by AndData. All other bits in Operand are
619   preserved. The new 32-bit value is returned.
620 
621   If 32-bit operations are not supported, then ASSERT().
622   If StartBit is greater than 31, then ASSERT().
623   If EndBit is greater than 31, then ASSERT().
624   If EndBit is less than StartBit, then ASSERT().
625   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
626 
627   @param  Operand   Operand on which to perform the bitfield operation.
628   @param  StartBit  The ordinal of the least significant bit in the bit field.
629                     Range 0..31.
630   @param  EndBit    The ordinal of the most significant bit in the bit field.
631                     Range 0..31.
632   @param  AndData   The value to AND with the read value from the value.
633 
634   @return The new 32-bit value.
635 
636 **/
637 UINT32
638 EFIAPI
BitFieldAnd32(IN UINT32 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 AndData)639 BitFieldAnd32 (
640   IN      UINT32                    Operand,
641   IN      UINTN                     StartBit,
642   IN      UINTN                     EndBit,
643   IN      UINT32                    AndData
644   )
645 {
646   ASSERT (EndBit < 32);
647   ASSERT (StartBit <= EndBit);
648   return (UINT32)InternalBaseLibBitFieldAndUint (Operand, StartBit, EndBit, AndData);
649 }
650 
651 /**
652   Reads a bit field from a 32-bit value, performs a bitwise AND followed by a
653   bitwise OR, and returns the result.
654 
655   Performs a bitwise AND between the bit field specified by StartBit and EndBit
656   in Operand and the value specified by AndData, followed by a bitwise
657   OR with value specified by OrData. All other bits in Operand are
658   preserved. The new 32-bit value is returned.
659 
660   If 32-bit operations are not supported, then ASSERT().
661   If StartBit is greater than 31, then ASSERT().
662   If EndBit is greater than 31, then ASSERT().
663   If EndBit is less than StartBit, then ASSERT().
664   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
665   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
666 
667   @param  Operand   Operand on which to perform the bitfield operation.
668   @param  StartBit  The ordinal of the least significant bit in the bit field.
669                     Range 0..31.
670   @param  EndBit    The ordinal of the most significant bit in the bit field.
671                     Range 0..31.
672   @param  AndData   The value to AND with the read value from the value.
673   @param  OrData    The value to OR with the result of the AND operation.
674 
675   @return The new 32-bit value.
676 
677 **/
678 UINT32
679 EFIAPI
BitFieldAndThenOr32(IN UINT32 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT32 AndData,IN UINT32 OrData)680 BitFieldAndThenOr32 (
681   IN      UINT32                    Operand,
682   IN      UINTN                     StartBit,
683   IN      UINTN                     EndBit,
684   IN      UINT32                    AndData,
685   IN      UINT32                    OrData
686   )
687 {
688   ASSERT (EndBit < 32);
689   ASSERT (StartBit <= EndBit);
690   return BitFieldOr32 (
691            BitFieldAnd32 (Operand, StartBit, EndBit, AndData),
692            StartBit,
693            EndBit,
694            OrData
695            );
696 }
697 
698 /**
699   Returns a bit field from a 64-bit value.
700 
701   Returns the bitfield specified by the StartBit and the EndBit from Operand.
702 
703   If 64-bit operations are not supported, then ASSERT().
704   If StartBit is greater than 63, then ASSERT().
705   If EndBit is greater than 63, then ASSERT().
706   If EndBit is less than StartBit, then ASSERT().
707 
708   @param  Operand   Operand on which to perform the bitfield operation.
709   @param  StartBit  The ordinal of the least significant bit in the bit field.
710                     Range 0..63.
711   @param  EndBit    The ordinal of the most significant bit in the bit field.
712                     Range 0..63.
713 
714   @return The bit field read.
715 
716 **/
717 UINT64
718 EFIAPI
BitFieldRead64(IN UINT64 Operand,IN UINTN StartBit,IN UINTN EndBit)719 BitFieldRead64 (
720   IN      UINT64                    Operand,
721   IN      UINTN                     StartBit,
722   IN      UINTN                     EndBit
723   )
724 {
725   ASSERT (EndBit < 64);
726   ASSERT (StartBit <= EndBit);
727   return RShiftU64 (Operand & ~LShiftU64 ((UINT64)-2, EndBit), StartBit);
728 }
729 
730 /**
731   Writes a bit field to a 64-bit value, and returns the result.
732 
733   Writes Value to the bit field specified by the StartBit and the EndBit in
734   Operand. All other bits in Operand are preserved. The new 64-bit value is
735   returned.
736 
737   If 64-bit operations are not supported, then ASSERT().
738   If StartBit is greater than 63, then ASSERT().
739   If EndBit is greater than 63, then ASSERT().
740   If EndBit is less than StartBit, then ASSERT().
741   If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
742 
743   @param  Operand   Operand on which to perform the bitfield operation.
744   @param  StartBit  The ordinal of the least significant bit in the bit field.
745                     Range 0..63.
746   @param  EndBit    The ordinal of the most significant bit in the bit field.
747                     Range 0..63.
748   @param  Value     The new value of the bit field.
749 
750   @return The new 64-bit value.
751 
752 **/
753 UINT64
754 EFIAPI
BitFieldWrite64(IN UINT64 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT64 Value)755 BitFieldWrite64 (
756   IN      UINT64                    Operand,
757   IN      UINTN                     StartBit,
758   IN      UINTN                     EndBit,
759   IN      UINT64                    Value
760   )
761 {
762   ASSERT (EndBit < 64);
763   ASSERT (StartBit <= EndBit);
764   return BitFieldAndThenOr64 (Operand, StartBit, EndBit, 0, Value);
765 }
766 
767 /**
768   Reads a bit field from a 64-bit value, performs a bitwise OR, and returns the
769   result.
770 
771   Performs a bitwise OR between the bit field specified by StartBit
772   and EndBit in Operand and the value specified by OrData. All other bits in
773   Operand are preserved. The new 64-bit value is returned.
774 
775   If 64-bit operations are not supported, then ASSERT().
776   If StartBit is greater than 63, then ASSERT().
777   If EndBit is greater than 63, then ASSERT().
778   If EndBit is less than StartBit, then ASSERT().
779   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
780 
781   @param  Operand   Operand on which to perform the bitfield operation.
782   @param  StartBit  The ordinal of the least significant bit in the bit field.
783                     Range 0..63.
784   @param  EndBit    The ordinal of the most significant bit in the bit field.
785                     Range 0..63.
786   @param  OrData    The value to OR with the read value from the value
787 
788   @return The new 64-bit value.
789 
790 **/
791 UINT64
792 EFIAPI
BitFieldOr64(IN UINT64 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT64 OrData)793 BitFieldOr64 (
794   IN      UINT64                    Operand,
795   IN      UINTN                     StartBit,
796   IN      UINTN                     EndBit,
797   IN      UINT64                    OrData
798   )
799 {
800   UINT64  Value1;
801   UINT64  Value2;
802 
803   ASSERT (EndBit < 64);
804   ASSERT (StartBit <= EndBit);
805   //
806   // Higher bits in OrData those are not used must be zero.
807   //
808   // EndBit - StartBit + 1 might be 64 while the result right shifting 64 on RShiftU64() API is invalid,
809   // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly.
810   //
811   ASSERT (RShiftU64 (OrData, EndBit - StartBit) == (RShiftU64 (OrData, EndBit - StartBit) & 1));
812 
813   Value1 = LShiftU64 (OrData, StartBit);
814   Value2 = LShiftU64 ((UINT64) - 2, EndBit);
815 
816   return Operand | (Value1 & ~Value2);
817 }
818 
819 /**
820   Reads a bit field from a 64-bit value, performs a bitwise AND, and returns
821   the result.
822 
823   Performs a bitwise AND between the bit field specified by StartBit and EndBit
824   in Operand and the value specified by AndData. All other bits in Operand are
825   preserved. The new 64-bit value is returned.
826 
827   If 64-bit operations are not supported, then ASSERT().
828   If StartBit is greater than 63, then ASSERT().
829   If EndBit is greater than 63, then ASSERT().
830   If EndBit is less than StartBit, then ASSERT().
831   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
832 
833   @param  Operand   Operand on which to perform the bitfield operation.
834   @param  StartBit  The ordinal of the least significant bit in the bit field.
835                     Range 0..63.
836   @param  EndBit    The ordinal of the most significant bit in the bit field.
837                     Range 0..63.
838   @param  AndData   The value to AND with the read value from the value.
839 
840   @return The new 64-bit value.
841 
842 **/
843 UINT64
844 EFIAPI
BitFieldAnd64(IN UINT64 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT64 AndData)845 BitFieldAnd64 (
846   IN      UINT64                    Operand,
847   IN      UINTN                     StartBit,
848   IN      UINTN                     EndBit,
849   IN      UINT64                    AndData
850   )
851 {
852   UINT64  Value1;
853   UINT64  Value2;
854 
855   ASSERT (EndBit < 64);
856   ASSERT (StartBit <= EndBit);
857   //
858   // Higher bits in AndData those are not used must be zero.
859   //
860   // EndBit - StartBit + 1 might be 64 while the right shifting 64 on RShiftU64() API is invalid,
861   // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly.
862   //
863   ASSERT (RShiftU64 (AndData, EndBit - StartBit) == (RShiftU64 (AndData, EndBit - StartBit) & 1));
864 
865   Value1 = LShiftU64 (~AndData, StartBit);
866   Value2 = LShiftU64 ((UINT64)-2, EndBit);
867 
868   return Operand & ~(Value1 & ~Value2);
869 }
870 
871 /**
872   Reads a bit field from a 64-bit value, performs a bitwise AND followed by a
873   bitwise OR, and returns the result.
874 
875   Performs a bitwise AND between the bit field specified by StartBit and EndBit
876   in Operand and the value specified by AndData, followed by a bitwise
877   OR with value specified by OrData. All other bits in Operand are
878   preserved. The new 64-bit value is returned.
879 
880   If 64-bit operations are not supported, then ASSERT().
881   If StartBit is greater than 63, then ASSERT().
882   If EndBit is greater than 63, then ASSERT().
883   If EndBit is less than StartBit, then ASSERT().
884   If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
885   If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT().
886 
887   @param  Operand   Operand on which to perform the bitfield operation.
888   @param  StartBit  The ordinal of the least significant bit in the bit field.
889                     Range 0..63.
890   @param  EndBit    The ordinal of the most significant bit in the bit field.
891                     Range 0..63.
892   @param  AndData   The value to AND with the read value from the value.
893   @param  OrData    The value to OR with the result of the AND operation.
894 
895   @return The new 64-bit value.
896 
897 **/
898 UINT64
899 EFIAPI
BitFieldAndThenOr64(IN UINT64 Operand,IN UINTN StartBit,IN UINTN EndBit,IN UINT64 AndData,IN UINT64 OrData)900 BitFieldAndThenOr64 (
901   IN      UINT64                    Operand,
902   IN      UINTN                     StartBit,
903   IN      UINTN                     EndBit,
904   IN      UINT64                    AndData,
905   IN      UINT64                    OrData
906   )
907 {
908   ASSERT (EndBit < 64);
909   ASSERT (StartBit <= EndBit);
910   return BitFieldOr64 (
911            BitFieldAnd64 (Operand, StartBit, EndBit, AndData),
912            StartBit,
913            EndBit,
914            OrData
915            );
916 }
917 
918 /**
919   Reads a bit field from a 32-bit value, counts and returns
920   the number of set bits.
921 
922   Counts the number of set bits in the  bit field specified by
923   StartBit and EndBit in Operand. The count is returned.
924 
925   If StartBit is greater than 31, then ASSERT().
926   If EndBit is greater than 31, then ASSERT().
927   If EndBit is less than StartBit, then ASSERT().
928 
929   @param  Operand   Operand on which to perform the bitfield operation.
930   @param  StartBit  The ordinal of the least significant bit in the bit field.
931                     Range 0..31.
932   @param  EndBit    The ordinal of the most significant bit in the bit field.
933                     Range 0..31.
934 
935   @return The number of bits set between StartBit and EndBit.
936 
937 **/
938 UINT8
939 EFIAPI
BitFieldCountOnes32(IN UINT32 Operand,IN UINTN StartBit,IN UINTN EndBit)940 BitFieldCountOnes32 (
941   IN       UINT32                   Operand,
942   IN       UINTN                    StartBit,
943   IN       UINTN                    EndBit
944   )
945 {
946   UINT32 Count;
947 
948   ASSERT (EndBit < 32);
949   ASSERT (StartBit <= EndBit);
950 
951   Count = BitFieldRead32 (Operand, StartBit, EndBit);
952   Count -= ((Count >> 1) & 0x55555555);
953   Count = (Count & 0x33333333) + ((Count >> 2) & 0x33333333);
954   Count += Count >> 4;
955   Count &= 0x0F0F0F0F;
956   Count += Count >> 8;
957   Count += Count >> 16;
958 
959   return (UINT8) Count & 0x3F;
960 }
961 
962 /**
963    Reads a bit field from a 64-bit value, counts and returns
964    the number of set bits.
965 
966    Counts the number of set bits in the  bit field specified by
967    StartBit and EndBit in Operand. The count is returned.
968 
969    If StartBit is greater than 63, then ASSERT().
970    If EndBit is greater than 63, then ASSERT().
971    If EndBit is less than StartBit, then ASSERT().
972 
973    @param  Operand   Operand on which to perform the bitfield operation.
974    @param  StartBit  The ordinal of the least significant bit in the bit field.
975    Range 0..63.
976    @param  EndBit    The ordinal of the most significant bit in the bit field.
977    Range 0..63.
978 
979    @return The number of bits set between StartBit and EndBit.
980 
981 **/
982 UINT8
983 EFIAPI
BitFieldCountOnes64(IN UINT64 Operand,IN UINTN StartBit,IN UINTN EndBit)984 BitFieldCountOnes64 (
985   IN       UINT64                   Operand,
986   IN       UINTN                    StartBit,
987   IN       UINTN                    EndBit
988   )
989 {
990   UINT64 BitField;
991   UINT8 Count;
992 
993   ASSERT (EndBit < 64);
994   ASSERT (StartBit <= EndBit);
995 
996   BitField = BitFieldRead64 (Operand, StartBit, EndBit);
997   Count = BitFieldCountOnes32 ((UINT32) BitField, 0, 31);
998   Count += BitFieldCountOnes32 ((UINT32) RShiftU64(BitField, 32), 0, 31);
999 
1000   return Count;
1001 }
1002 
1003