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