X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdePkg%2FLibrary%2FBaseLib%2FBitField.c;h=862af53e9c3f5e26115bf912b0ea394f98148dfa;hb=2f88bd3a1296c522317f1c21377876de63de5be7;hp=eb5fcd938c9a6ed9a3e00e4a3d59623e3c1dd73f;hpb=94952554cc604750f3df3d4e8ae068703481d258;p=mirror_edk2.git diff --git a/MdePkg/Library/BaseLib/BitField.c b/MdePkg/Library/BaseLib/BitField.c index eb5fcd938c..862af53e9c 100644 --- a/MdePkg/Library/BaseLib/BitField.c +++ b/MdePkg/Library/BaseLib/BitField.c @@ -1,14 +1,8 @@ /** @file Bit field functions of BaseLib. - Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
- This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php. - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -29,9 +23,9 @@ UINTN EFIAPI InternalBaseLibBitFieldReadUint ( - IN UINTN Operand, - IN UINTN StartBit, - IN UINTN EndBit + IN UINTN Operand, + IN UINTN StartBit, + IN UINTN EndBit ) { // @@ -62,22 +56,25 @@ InternalBaseLibBitFieldReadUint ( UINTN EFIAPI InternalBaseLibBitFieldOrUint ( - IN UINTN Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINTN OrData + IN UINTN Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINTN OrData ) { // - // Higher bits in OrData those are not used must be zero. + // Higher bits in OrData those are not used must be zero. + // + // EndBit - StartBit + 1 might be 32 while the result right shifting 32 on a 32bit integer is undefined, + // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly. // - ASSERT ((OrData >> (EndBit - StartBit + 1)) == 0); - + ASSERT ((OrData >> (EndBit - StartBit)) == ((OrData >> (EndBit - StartBit)) & 1)); + // // ~((UINTN)-2 << EndBit) is a mask in which bit[0] thru bit[EndBit] // are 1's while bit[EndBit + 1] thru the most significant bit are 0's. // - return Operand | ((OrData << StartBit) & ~((UINTN) -2 << EndBit)); + return Operand | ((OrData << StartBit) & ~((UINTN)-2 << EndBit)); } /** @@ -101,16 +98,19 @@ InternalBaseLibBitFieldOrUint ( UINTN EFIAPI InternalBaseLibBitFieldAndUint ( - IN UINTN Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINTN AndData + IN UINTN Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINTN AndData ) { // - // Higher bits in AndData those are not used must be zero. + // Higher bits in AndData those are not used must be zero. + // + // EndBit - StartBit + 1 might be 32 while the result right shifting 32 on a 32bit integer is undefined, + // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly. // - ASSERT ((AndData >> (EndBit - StartBit + 1)) == 0); + ASSERT ((AndData >> (EndBit - StartBit)) == ((AndData >> (EndBit - StartBit)) & 1)); // // ~((UINTN)-2 << EndBit) is a mask in which bit[0] thru bit[EndBit] @@ -141,9 +141,9 @@ InternalBaseLibBitFieldAndUint ( UINT8 EFIAPI BitFieldRead8 ( - IN UINT8 Operand, - IN UINTN StartBit, - IN UINTN EndBit + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit ) { ASSERT (EndBit < 8); @@ -177,10 +177,10 @@ BitFieldRead8 ( UINT8 EFIAPI BitFieldWrite8 ( - IN UINT8 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT8 Value + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value ) { ASSERT (EndBit < 8); @@ -215,10 +215,10 @@ BitFieldWrite8 ( UINT8 EFIAPI BitFieldOr8 ( - IN UINT8 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT8 OrData + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData ) { ASSERT (EndBit < 8); @@ -253,10 +253,10 @@ BitFieldOr8 ( UINT8 EFIAPI BitFieldAnd8 ( - IN UINT8 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT8 AndData + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData ) { ASSERT (EndBit < 8); @@ -269,7 +269,7 @@ BitFieldAnd8 ( bitwise OR, and returns the result. Performs a bitwise AND between the bit field specified by StartBit and EndBit - in Operand and the value specified by AndData, followed by a bitwise + in Operand and the value specified by AndData, followed by a bitwise OR with value specified by OrData. All other bits in Operand are preserved. The new 8-bit value is returned. @@ -294,11 +294,11 @@ BitFieldAnd8 ( UINT8 EFIAPI BitFieldAndThenOr8 ( - IN UINT8 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT8 AndData, - IN UINT8 OrData + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData ) { ASSERT (EndBit < 8); @@ -333,9 +333,9 @@ BitFieldAndThenOr8 ( UINT16 EFIAPI BitFieldRead16 ( - IN UINT16 Operand, - IN UINTN StartBit, - IN UINTN EndBit + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit ) { ASSERT (EndBit < 16); @@ -369,10 +369,10 @@ BitFieldRead16 ( UINT16 EFIAPI BitFieldWrite16 ( - IN UINT16 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT16 Value + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value ) { ASSERT (EndBit < 16); @@ -407,10 +407,10 @@ BitFieldWrite16 ( UINT16 EFIAPI BitFieldOr16 ( - IN UINT16 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT16 OrData + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData ) { ASSERT (EndBit < 16); @@ -445,10 +445,10 @@ BitFieldOr16 ( UINT16 EFIAPI BitFieldAnd16 ( - IN UINT16 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT16 AndData + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData ) { ASSERT (EndBit < 16); @@ -461,7 +461,7 @@ BitFieldAnd16 ( bitwise OR, and returns the result. Performs a bitwise AND between the bit field specified by StartBit and EndBit - in Operand and the value specified by AndData, followed by a bitwise + in Operand and the value specified by AndData, followed by a bitwise OR with value specified by OrData. All other bits in Operand are preserved. The new 16-bit value is returned. @@ -486,11 +486,11 @@ BitFieldAnd16 ( UINT16 EFIAPI BitFieldAndThenOr16 ( - IN UINT16 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT16 AndData, - IN UINT16 OrData + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData ) { ASSERT (EndBit < 16); @@ -525,9 +525,9 @@ BitFieldAndThenOr16 ( UINT32 EFIAPI BitFieldRead32 ( - IN UINT32 Operand, - IN UINTN StartBit, - IN UINTN EndBit + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit ) { ASSERT (EndBit < 32); @@ -561,10 +561,10 @@ BitFieldRead32 ( UINT32 EFIAPI BitFieldWrite32 ( - IN UINT32 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT32 Value + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value ) { ASSERT (EndBit < 32); @@ -599,10 +599,10 @@ BitFieldWrite32 ( UINT32 EFIAPI BitFieldOr32 ( - IN UINT32 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT32 OrData + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData ) { ASSERT (EndBit < 32); @@ -637,10 +637,10 @@ BitFieldOr32 ( UINT32 EFIAPI BitFieldAnd32 ( - IN UINT32 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT32 AndData + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData ) { ASSERT (EndBit < 32); @@ -653,7 +653,7 @@ BitFieldAnd32 ( bitwise OR, and returns the result. Performs a bitwise AND between the bit field specified by StartBit and EndBit - in Operand and the value specified by AndData, followed by a bitwise + in Operand and the value specified by AndData, followed by a bitwise OR with value specified by OrData. All other bits in Operand are preserved. The new 32-bit value is returned. @@ -678,11 +678,11 @@ BitFieldAnd32 ( UINT32 EFIAPI BitFieldAndThenOr32 ( - IN UINT32 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT32 AndData, - IN UINT32 OrData + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData ) { ASSERT (EndBit < 32); @@ -717,9 +717,9 @@ BitFieldAndThenOr32 ( UINT64 EFIAPI BitFieldRead64 ( - IN UINT64 Operand, - IN UINTN StartBit, - IN UINTN EndBit + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit ) { ASSERT (EndBit < 64); @@ -753,10 +753,10 @@ BitFieldRead64 ( UINT64 EFIAPI BitFieldWrite64 ( - IN UINT64 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT64 Value + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value ) { ASSERT (EndBit < 64); @@ -791,10 +791,10 @@ BitFieldWrite64 ( UINT64 EFIAPI BitFieldOr64 ( - IN UINT64 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT64 OrData + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData ) { UINT64 Value1; @@ -802,10 +802,16 @@ BitFieldOr64 ( ASSERT (EndBit < 64); ASSERT (StartBit <= EndBit); - ASSERT (RShiftU64 (OrData, EndBit - StartBit + 1) == 0); + // + // Higher bits in OrData those are not used must be zero. + // + // EndBit - StartBit + 1 might be 64 while the result right shifting 64 on RShiftU64() API is invalid, + // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly. + // + ASSERT (RShiftU64 (OrData, EndBit - StartBit) == (RShiftU64 (OrData, EndBit - StartBit) & 1)); Value1 = LShiftU64 (OrData, StartBit); - Value2 = LShiftU64 ((UINT64) - 2, EndBit); + Value2 = LShiftU64 ((UINT64)-2, EndBit); return Operand | (Value1 & ~Value2); } @@ -837,18 +843,24 @@ BitFieldOr64 ( UINT64 EFIAPI BitFieldAnd64 ( - IN UINT64 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT64 AndData + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData ) { UINT64 Value1; UINT64 Value2; - + ASSERT (EndBit < 64); ASSERT (StartBit <= EndBit); - ASSERT (RShiftU64 (AndData, EndBit - StartBit + 1) == 0); + // + // Higher bits in AndData those are not used must be zero. + // + // EndBit - StartBit + 1 might be 64 while the right shifting 64 on RShiftU64() API is invalid, + // So the logic is updated to right shift (EndBit - StartBit) bits and compare the last bit directly. + // + ASSERT (RShiftU64 (AndData, EndBit - StartBit) == (RShiftU64 (AndData, EndBit - StartBit) & 1)); Value1 = LShiftU64 (~AndData, StartBit); Value2 = LShiftU64 ((UINT64)-2, EndBit); @@ -861,7 +873,7 @@ BitFieldAnd64 ( bitwise OR, and returns the result. Performs a bitwise AND between the bit field specified by StartBit and EndBit - in Operand and the value specified by AndData, followed by a bitwise + in Operand and the value specified by AndData, followed by a bitwise OR with value specified by OrData. All other bits in Operand are preserved. The new 64-bit value is returned. @@ -886,11 +898,11 @@ BitFieldAnd64 ( UINT64 EFIAPI BitFieldAndThenOr64 ( - IN UINT64 Operand, - IN UINTN StartBit, - IN UINTN EndBit, - IN UINT64 AndData, - IN UINT64 OrData + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData ) { ASSERT (EndBit < 64); @@ -902,3 +914,88 @@ BitFieldAndThenOr64 ( OrData ); } + +/** + Reads a bit field from a 32-bit value, counts and returns + the number of set bits. + + Counts the number of set bits in the bit field specified by + StartBit and EndBit in Operand. The count is returned. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The number of bits set between StartBit and EndBit. + +**/ +UINT8 +EFIAPI +BitFieldCountOnes32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + UINT32 Count; + + ASSERT (EndBit < 32); + ASSERT (StartBit <= EndBit); + + Count = BitFieldRead32 (Operand, StartBit, EndBit); + Count -= ((Count >> 1) & 0x55555555); + Count = (Count & 0x33333333) + ((Count >> 2) & 0x33333333); + Count += Count >> 4; + Count &= 0x0F0F0F0F; + Count += Count >> 8; + Count += Count >> 16; + + return (UINT8)Count & 0x3F; +} + +/** + Reads a bit field from a 64-bit value, counts and returns + the number of set bits. + + Counts the number of set bits in the bit field specified by + StartBit and EndBit in Operand. The count is returned. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The number of bits set between StartBit and EndBit. + +**/ +UINT8 +EFIAPI +BitFieldCountOnes64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + UINT64 BitField; + UINT8 Count; + + ASSERT (EndBit < 64); + ASSERT (StartBit <= EndBit); + + BitField = BitFieldRead64 (Operand, StartBit, EndBit); + Count = BitFieldCountOnes32 ((UINT32)BitField, 0, 31); + Count += BitFieldCountOnes32 ((UINT32)RShiftU64 (BitField, 32), 0, 31); + + return Count; +}