1# Copyright (c) 2015-2022 Intel Corporation. 2# 3# Redistribution and use in source and binary forms, with or without 4# modification, are permitted provided that the following conditions are met: 5# 6# * Redistributions of source code must retain the above copyright notice, 7# this list of conditions and the following disclaimer. 8# * Redistributions in binary form must reproduce the above copyright notice, 9# this list of conditions and the following disclaimer in the documentation 10# and/or other materials provided with the distribution. 11# * Neither the name of Intel Corporation nor the names of its contributors 12# may be used to endorse or promote products derived from this software 13# without specific prior written permission. 14# 15# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 19# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 22# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 26"""Helper functions to work with bitfields. 27 28Documentation frequently writes bitfields as the inclusive range [msb:lsb]; 29this module provides functions to work with bitfields using msb and lsb rather 30than manually computing shifts and masks from those.""" 31 32def bitfield_max(msb, lsb=None): 33 """Return the largest value that fits in the bitfield [msb:lsb] (or [msb] if lsb is None)""" 34 if lsb is None: 35 lsb = msb 36 return (1 << (msb - lsb + 1)) - 1 37 38def bitmask(msb, lsb=None): 39 """Creates a mask with bits [msb:lsb] (or [msb] if lsb is None) set.""" 40 if lsb is None: 41 lsb = msb 42 return bitfield_max(msb, lsb) << lsb 43 44def bitfield(value, msb, lsb=None): 45 """Shift value to fit in the bitfield [msb:lsb] (or [msb] if lsb is None). 46 47 Raise OverflowError if value does not fit in that bitfield.""" 48 if lsb is None: 49 lsb = msb 50 if value > bitfield_max(msb, lsb): 51 if msb == lsb: 52 field = "[{0}]".format(msb) 53 else: 54 field = "[{0}:{1}]".format(msb, lsb) 55 raise OverflowError("Value {value:#x} too big for bitfield {field}".format(**locals())) 56 return value << lsb 57 58def getbits(value, msb, lsb=None): 59 """From the specified value, extract the bitfield [msb:lsb] (or [msb] if lsb is None)""" 60 if lsb is None: 61 lsb = msb 62 return (value >> lsb) & bitfield_max(msb, lsb) 63 64def setbits(value, fieldvalue, msb, lsb=None): 65 """In the specified value, set the bitfield [msb:lsb] (or [msb] if lsb is None) to fieldvalue""" 66 value &= ~bitmask(msb, lsb) 67 value |= bitfield(fieldvalue, msb, lsb) 68 return value 69