diff options
Diffstat (limited to 'include/iprt/uint32.h')
-rw-r--r-- | include/iprt/uint32.h | 1058 |
1 files changed, 1058 insertions, 0 deletions
diff --git a/include/iprt/uint32.h b/include/iprt/uint32.h new file mode 100644 index 00000000..18070a80 --- /dev/null +++ b/include/iprt/uint32.h @@ -0,0 +1,1058 @@ +/** @file + * IPRT - RTUINT32U methods for old 16-bit compilers (mainly for division). + */ + +/* + * Copyright (C) 2011-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + +#ifndef IPRT_INCLUDED_uint32_h +#define IPRT_INCLUDED_uint32_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/cdefs.h> +#include <iprt/types.h> +#include <iprt/asm.h> + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_uint32 RTUInt32 - 32-bit Unsigned Integer Methods for 16-bit compilers. + * @ingroup grp_rt + * @{ + */ + +#define RTUINT32_HAVE_32BIT_BASICS + + +/** + * Test if a 32-bit unsigned integer value is zero. + * + * @returns true if they are, false if they aren't. + * @param pValue The input and output value. + */ +DECLINLINE(bool) RTUInt32IsZero(PRTUINT32U pValue) +{ + return pValue->s.Lo == 0 + && pValue->s.Hi == 0; +} + + +/** + * Set a 32-bit unsigned integer value to zero. + * + * @returns pResult + * @param pResult The result variable. + */ +DECLINLINE(PRTUINT32U) RTUInt32SetZero(PRTUINT32U pResult) +{ + pResult->s.Hi = 0; + pResult->s.Lo = 0; + return pResult; +} + + +/** + * Set a 32-bit unsigned integer value to the maximum value. + * + * @returns pResult + * @param pResult The result variable. + */ +DECLINLINE(PRTUINT32U) RTUInt32SetMax(PRTUINT32U pResult) +{ + pResult->s.Hi = UINT16_MAX; + pResult->s.Lo = UINT16_MAX; + return pResult; +} + + + + +/** + * Adds two 32-bit unsigned integer values. + * + * @returns pResult + * @param pResult The result variable. + * @param pValue1 The first value. + * @param pValue2 The second value. + */ +DECLINLINE(PRTUINT32U) RTUInt32Add(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ +#ifdef RTUINT32_HAVE_32BIT_BASICS + pResult->u = pValue1->u + pValue2->u; +#else + pResult->s.Hi = pValue1->s.Hi + pValue2->s.Hi; + pResult->s.Lo = pValue1->s.Lo + pValue2->s.Lo; + if (pResult->s.Lo < pValue1->s.Lo) + pResult->s.Hi++; +#endif + return pResult; +} + + +/** + * Adds a 32-bit and a 16-bit unsigned integer values. + * + * @returns pResult + * @param pResult The result variable. + * @param pValue1 The first value. + * @param uValue2 The second value, 16-bit. + */ +DECLINLINE(PRTUINT32U) RTUInt32AddU16(PRTUINT32U pResult, PCRTUINT32U pValue1, uint16_t uValue2) +{ +#ifdef RTUINT32_HAVE_32BIT_BASICS + pResult->u = pValue1->u + uValue2; +#else + pResult->s.Hi = pValue1->s.Hi; + pResult->s.Lo = pValue1->s.Lo + uValue2; + if (pResult->s.Lo < pValue1->s.Lo) + pResult->s.Hi++; +#endif + return pResult; +} + + +/** + * Subtracts a 32-bit unsigned integer value from another. + * + * @returns pResult + * @param pResult The result variable. + * @param pValue1 The minuend value. + * @param pValue2 The subtrahend value. + */ +DECLINLINE(PRTUINT32U) RTUInt32Sub(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ +#ifdef RTUINT32_HAVE_32BIT_BASICS + pResult->u = pValue1->u - pValue2->u; +#else + pResult->s.Lo = pValue1->s.Lo - pValue2->s.Lo; + pResult->s.Hi = pValue1->s.Hi - pValue2->s.Hi; + if (pResult->s.Lo > pValue1->s.Lo) + pResult->s.Hi--; +#endif + return pResult; +} + + +/** + * Multiplies two 32-bit unsigned integer values. + * + * @returns pResult + * @param pResult The result variable. + * @param pValue1 The first value. + * @param pValue2 The second value. + */ +DECLINLINE(PRTUINT32U) RTUInt32Mul(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ + pResult->u = (uint32_t)pValue1->s.Lo * pValue2->s.Lo; + pResult->s.Hi += pValue1->s.Hi * pValue2->s.Lo; + pResult->s.Hi += pValue1->s.Lo * pValue2->s.Hi; + + return pResult; +} + + +/** + * Multiplies an 32-bit unsigned integer by a 16-bit unsigned integer value. + * + * @returns pResult + * @param pResult The result variable. + * @param pValue1 The first value. + * @param uValue2 The second value, 16-bit. + */ +DECLINLINE(PRTUINT32U) RTUInt32MulByU16(PRTUINT32U pResult, PCRTUINT32U pValue1, uint16_t uValue2) +{ + pResult->u = (uint32_t)pValue1->s.Lo * uValue2; + pResult->s.Hi += pValue1->s.Hi * uValue2; + return pResult; +} + + +DECLINLINE(PRTUINT32U) RTUInt32DivRem(PRTUINT32U pQuotient, PRTUINT32U pRemainder, PCRTUINT32U pValue1, PCRTUINT32U pValue2); + +/** + * Divides a 32-bit unsigned integer value by another. + * + * @returns pResult + * @param pResult The result variable. + * @param pValue1 The dividend value. + * @param pValue2 The divisor value. + */ +DECLINLINE(PRTUINT32U) RTUInt32Div(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ + RTUINT32U Ignored; + return RTUInt32DivRem(pResult, &Ignored, pValue1, pValue2); +} + + +/** + * Divides a 32-bit unsigned integer value by another, returning the remainder. + * + * @returns pResult + * @param pResult The result variable (remainder). + * @param pValue1 The dividend value. + * @param pValue2 The divisor value. + */ +DECLINLINE(PRTUINT32U) RTUInt32Mod(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ + RTUINT32U Ignored; + RTUInt32DivRem(&Ignored, pResult, pValue1, pValue2); + return pResult; +} + + +/** + * Bitwise AND of two 32-bit unsigned integer values. + * + * @returns pResult + * @param pResult The result variable. + * @param pValue1 The first value. + * @param pValue2 The second value. + */ +DECLINLINE(PRTUINT32U) RTUInt32And(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ + pResult->s.Hi = pValue1->s.Hi & pValue2->s.Hi; + pResult->s.Lo = pValue1->s.Lo & pValue2->s.Lo; + return pResult; +} + + +/** + * Bitwise OR of two 32-bit unsigned integer values. + * + * @returns pResult + * @param pResult The result variable. + * @param pValue1 The first value. + * @param pValue2 The second value. + */ +DECLINLINE(PRTUINT32U) RTUInt32Or( PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ + pResult->s.Hi = pValue1->s.Hi | pValue2->s.Hi; + pResult->s.Lo = pValue1->s.Lo | pValue2->s.Lo; + return pResult; +} + + +/** + * Bitwise XOR of two 32-bit unsigned integer values. + * + * @returns pResult + * @param pResult The result variable. + * @param pValue1 The first value. + * @param pValue2 The second value. + */ +DECLINLINE(PRTUINT32U) RTUInt32Xor(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ + pResult->s.Hi = pValue1->s.Hi ^ pValue2->s.Hi; + pResult->s.Lo = pValue1->s.Lo ^ pValue2->s.Lo; + return pResult; +} + + +/** + * Shifts a 32-bit unsigned integer value @a cBits to the left. + * + * @returns pResult + * @param pResult The result variable. + * @param pValue The value to shift. + * @param cBits The number of bits to shift it. + */ +DECLINLINE(PRTUINT32U) RTUInt32ShiftLeft(PRTUINT32U pResult, PCRTUINT32U pValue, int cBits) +{ + cBits &= 31; +#ifdef RTUINT32_HAVE_32BIT_BASICS + pResult->u = pValue->u << cBits; +#else + if (cBits < 16) + { + pResult->s.Lo = pValue->s.Lo << cBits; + pResult->s.Hi = (pValue->s.Hi << cBits) | (pValue->s.Lo >> (16 - cBits)); + } + else + { + pResult->s.Lo = 0; + pResult->s.Hi = pValue->s.Lo << (cBits - 16); + } +#endif + return pResult; +} + + +/** + * Shifts a 32-bit unsigned integer value @a cBits to the right. + * + * @returns pResult + * @param pResult The result variable. + * @param pValue The value to shift. + * @param cBits The number of bits to shift it. + */ +DECLINLINE(PRTUINT32U) RTUInt32ShiftRight(PRTUINT32U pResult, PCRTUINT32U pValue, int cBits) +{ + cBits &= 31; +#ifdef RTUINT32_HAVE_32BIT_BASICS + pResult->u = pValue->u >> cBits; +#else + if (cBits < 16) + { + pResult->s.Hi = pValue->s.Hi >> cBits; + pResult->s.Lo = (pValue->s.Lo >> cBits) | (pValue->s.Hi << (16 - cBits)); + } + else + { + pResult->s.Hi = 0; + pResult->s.Lo = pValue->s.Hi >> (cBits - 16); + } +#endif + return pResult; +} + + +/** + * Boolean not (result 0 or 1). + * + * @returns pResult. + * @param pResult The result variable. + * @param pValue The value. + */ +DECLINLINE(PRTUINT32U) RTUInt32BooleanNot(PRTUINT32U pResult, PCRTUINT32U pValue) +{ + pResult->s.Lo = pValue->s.Lo || pValue->s.Hi ? 0 : 1; + pResult->s.Hi = 0; + return pResult; +} + + +/** + * Bitwise not (flips each bit of the 32 bits). + * + * @returns pResult. + * @param pResult The result variable. + * @param pValue The value. + */ +DECLINLINE(PRTUINT32U) RTUInt32BitwiseNot(PRTUINT32U pResult, PCRTUINT32U pValue) +{ + pResult->s.Hi = ~pValue->s.Hi; + pResult->s.Lo = ~pValue->s.Lo; + return pResult; +} + + +/** + * Assigns one 32-bit unsigned integer value to another. + * + * @returns pResult + * @param pResult The result variable. + * @param pValue The value to assign. + */ +DECLINLINE(PRTUINT32U) RTUInt32Assign(PRTUINT32U pResult, PCRTUINT32U pValue) +{ + pResult->s.Hi = pValue->s.Hi; + pResult->s.Lo = pValue->s.Lo; + return pResult; +} + + +/** + * Assigns a boolean value to 32-bit unsigned integer. + * + * @returns pValueResult + * @param pValueResult The result variable. + * @param fValue The boolean value. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignBoolean(PRTUINT32U pValueResult, bool fValue) +{ + pValueResult->s.Lo = fValue; + pValueResult->s.Hi = 0; + return pValueResult; +} + + +/** + * Assigns a 8-bit unsigned integer value to 32-bit unsigned integer. + * + * @returns pValueResult + * @param pValueResult The result variable. + * @param u8Value The 8-bit unsigned integer value. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignU8(PRTUINT32U pValueResult, uint8_t u8Value) +{ + pValueResult->s.Lo = u8Value; + pValueResult->s.Hi = 0; + return pValueResult; +} + + +/** + * Assigns a 16-bit unsigned integer value to 32-bit unsigned integer. + * + * @returns pValueResult + * @param pValueResult The result variable. + * @param u16Value The 16-bit unsigned integer value. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignU16(PRTUINT32U pValueResult, uint16_t u16Value) +{ + pValueResult->s.Lo = u16Value; + pValueResult->s.Hi = 0; + return pValueResult; +} + + +/** + * Adds two 32-bit unsigned integer values, storing the result in the first. + * + * @returns pValue1Result. + * @param pValue1Result The first value and result. + * @param pValue2 The second value. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignAdd(PRTUINT32U pValue1Result, PCRTUINT32U pValue2) +{ +#ifdef RTUINT32_HAVE_32BIT_BASICS + pValue1Result->u += pValue2->u; +#else + uint16_t const uTmp = pValue1Result->s.Lo; + pValue1Result->s.Lo += pValue2->s.Lo; + if (pValue1Result->s.Lo < uTmp) + pValue1Result->s.Hi++; + pValue1Result->s.Hi += pValue2->s.Hi; +#endif + return pValue1Result; +} + + +/** + * Subtracts two 32-bit unsigned integer values, storing the result in the + * first. + * + * @returns pValue1Result. + * @param pValue1Result The minuend value and result. + * @param pValue2 The subtrahend value. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignSub(PRTUINT32U pValue1Result, PCRTUINT32U pValue2) +{ +#ifdef RTUINT32_HAVE_32BIT_BASICS + pValue1Result->u -= pValue2->u; +#else + uint32_t const uTmp = pValue1Result->s.Lo; + pValue1Result->s.Lo -= pValue2->s.Lo; + if (pValue1Result->s.Lo > uTmp) + pValue1Result->s.Hi--; + pValue1Result->s.Hi -= pValue2->s.Hi; +#endif + return pValue1Result; +} + + +/** + * Multiplies two 32-bit unsigned integer values, storing the result in the + * first. + * + * @returns pValue1Result. + * @param pValue1Result The first value and result. + * @param pValue2 The second value. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignMul(PRTUINT32U pValue1Result, PCRTUINT32U pValue2) +{ + RTUINT32U Result; + RTUInt32Mul(&Result, pValue1Result, pValue2); + *pValue1Result = Result; + return pValue1Result; +} + + +/** + * Divides a 32-bit unsigned integer value by another, storing the result in + * the first. + * + * @returns pValue1Result. + * @param pValue1Result The dividend value and result. + * @param pValue2 The divisor value. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignDiv(PRTUINT32U pValue1Result, PCRTUINT32U pValue2) +{ + RTUINT32U Result; + RTUINT32U Ignored; + RTUInt32DivRem(&Result, &Ignored, pValue1Result, pValue2); + *pValue1Result = Result; + return pValue1Result; +} + + +/** + * Divides a 32-bit unsigned integer value by another, storing the remainder in + * the first. + * + * @returns pValue1Result. + * @param pValue1Result The dividend value and result (remainder). + * @param pValue2 The divisor value. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignMod(PRTUINT32U pValue1Result, PCRTUINT32U pValue2) +{ + RTUINT32U Ignored; + RTUINT32U Result; + RTUInt32DivRem(&Ignored, &Result, pValue1Result, pValue2); + *pValue1Result = Result; + return pValue1Result; +} + + +/** + * Performs a bitwise AND of two 32-bit unsigned integer values and assigned + * the result to the first one. + * + * @returns pValue1Result. + * @param pValue1Result The first value and result. + * @param pValue2 The second value. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignAnd(PRTUINT32U pValue1Result, PCRTUINT32U pValue2) +{ + pValue1Result->s.Hi &= pValue2->s.Hi; + pValue1Result->s.Lo &= pValue2->s.Lo; + return pValue1Result; +} + + +/** + * Performs a bitwise AND of a 32-bit unsigned integer value and a mask made up + * of the first N bits, assigning the result to the the 32-bit value. + * + * @returns pValueResult. + * @param pValueResult The value and result. + * @param cBits The number of bits to AND (counting from the first + * bit). + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignAndNFirstBits(PRTUINT32U pValueResult, unsigned cBits) +{ +#ifdef RTUINT32_HAVE_32BIT_BASICS + if (cBits < 32) + pValueResult->u &= RT_BIT_32(cBits) - 1; +#else + if (cBits <= 16) + { + if (cBits != 16) + pValueResult->s.Lo &= (UINT16_C(1) << cBits) - 1; + pValueResult->s.Hi = 0; + } + else if (cBits < 16) + pValueResult->s.Hi &= (UINT16_C(1) << (cBits - 16)) - 1; +#endif + return pValueResult; +} + + +/** + * Performs a bitwise OR of two 32-bit unsigned integer values and assigned + * the result to the first one. + * + * @returns pValue1Result. + * @param pValue1Result The first value and result. + * @param pValue2 The second value. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignOr(PRTUINT32U pValue1Result, PCRTUINT32U pValue2) +{ + pValue1Result->s.Hi |= pValue2->s.Hi; + pValue1Result->s.Lo |= pValue2->s.Lo; + return pValue1Result; +} + + +/** + * ORs in a bit and assign the result to the input value. + * + * @returns pValue1Result. + * @param pValue1Result The first value and result. + * @param iBit The bit to set (0 based). + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignOrBit(PRTUINT32U pValue1Result, unsigned iBit) +{ +#ifdef RTUINT32_HAVE_32BIT_BASICS + pValue1Result->u |= RT_BIT_32(iBit); +#else + if (iBit >= 32) + pValue1Result->s.Hi |= UINT16_C(1) << (iBit - 32); + else + pValue1Result->s.Lo |= UINT16_C(1) << iBit; +#endif + return pValue1Result; +} + + + +/** + * Performs a bitwise XOR of two 32-bit unsigned integer values and assigned + * the result to the first one. + * + * @returns pValue1Result. + * @param pValue1Result The first value and result. + * @param pValue2 The second value. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignXor(PRTUINT32U pValue1Result, PCRTUINT32U pValue2) +{ + pValue1Result->s.Hi ^= pValue2->s.Hi; + pValue1Result->s.Lo ^= pValue2->s.Lo; + return pValue1Result; +} + + +/** + * Performs a bitwise left shift on a 32-bit unsigned integer value, assigning + * the result to it. + * + * @returns pValueResult. + * @param pValueResult The first value and result. + * @param cBits The number of bits to shift. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignShiftLeft(PRTUINT32U pValueResult, int cBits) +{ +#ifndef RTUINT32_HAVE_32BIT_BASICS + RTUINT32U const InVal = *pValueResult; +#endif + if (cBits > 0) + { + /* (left shift) */ + cBits &= 31; +#ifdef RTUINT32_HAVE_32BIT_BASICS + pValueResult->u <<= cBits; +#else + if (cBits >= 16) + { + pValueResult->s.Lo = 0; + pValueResult->s.Hi = InVal.s.Lo << (cBits - 16); + } + else + { + pValueResult->s.Hi = InVal.s.Hi << cBits; + pValueResult->s.Hi |= InVal.s.Lo >> (16 - cBits); + pValueResult->s.Lo = InVal.s.Lo << cBits; + } +#endif + } + else if (cBits < 0) + { + /* (right shift) */ + cBits = -cBits; + cBits &= 31; +#ifdef RTUINT32_HAVE_32BIT_BASICS + pValueResult->u >>= cBits; +#else + if (cBits >= 16) + { + pValueResult->s.Hi = 0; + pValueResult->s.Lo = InVal.s.Hi >> (cBits - 16); + } + else + { + pValueResult->s.Lo = InVal.s.Lo >> cBits; + pValueResult->s.Lo |= InVal.s.Hi << (16 - cBits); + pValueResult->s.Hi = InVal.s.Hi >> cBits; + } +#endif + } + return pValueResult; +} + + +/** + * Performs a bitwise left shift on a 32-bit unsigned integer value, assigning + * the result to it. + * + * @returns pValueResult. + * @param pValueResult The first value and result. + * @param cBits The number of bits to shift. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignShiftRight(PRTUINT32U pValueResult, int cBits) +{ + return RTUInt32AssignShiftLeft(pValueResult, -cBits); +} + + +/** + * Performs a bitwise NOT on a 32-bit unsigned integer value, assigning the + * result to it. + * + * @returns pValueResult + * @param pValueResult The value and result. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignBitwiseNot(PRTUINT32U pValueResult) +{ + pValueResult->s.Hi = ~pValueResult->s.Hi; + pValueResult->s.Lo = ~pValueResult->s.Lo; + return pValueResult; +} + + +/** + * Performs a boolean NOT on a 32-bit unsigned integer value, assigning the + * result to it. + * + * @returns pValueResult + * @param pValueResult The value and result. + */ +DECLINLINE(PRTUINT32U) RTUInt32AssignBooleanNot(PRTUINT32U pValueResult) +{ + return RTUInt32AssignBoolean(pValueResult, RTUInt32IsZero(pValueResult)); +} + + +/** + * Compares two 32-bit unsigned integer values. + * + * @retval 0 if equal. + * @retval -1 if the first value is smaller than the second. + * @retval 1 if the first value is larger than the second. + * + * @param pValue1 The first value. + * @param pValue2 The second value. + */ +DECLINLINE(int) RTUInt32Compare(PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ + if (pValue1->s.Hi != pValue2->s.Hi) + return pValue1->s.Hi > pValue2->s.Hi ? 1 : -1; + if (pValue1->s.Lo != pValue2->s.Lo) + return pValue1->s.Lo > pValue2->s.Lo ? 1 : -1; + return 0; +} + + +/** + * Tests if a 64-bit unsigned integer value is smaller than another. + * + * @returns true if the first value is smaller, false if not. + * @param pValue1 The first value. + * @param pValue2 The second value. + */ +DECLINLINE(bool) RTUInt32IsSmaller(PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ +#ifdef RTUINT32_HAVE_32BIT_BASICS + return pValue1->u < pValue2->u; +#else + return pValue1->s.Hi < pValue2->s.Hi + || ( pValue1->s.Hi == pValue2->s.Hi + && pValue1->s.Lo < pValue2->s.Lo); +#endif +} + + +/** + * Tests if a 32-bit unsigned integer value is larger than another. + * + * @returns true if the first value is larger, false if not. + * @param pValue1 The first value. + * @param pValue2 The second value. + */ +DECLINLINE(bool) RTUInt32IsLarger(PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ +#ifdef RTUINT32_HAVE_32BIT_BASICS + return pValue1->u > pValue2->u; +#else + return pValue1->s.Hi > pValue2->s.Hi + || ( pValue1->s.Hi == pValue2->s.Hi + && pValue1->s.Lo > pValue2->s.Lo); +#endif +} + + +/** + * Tests if a 64-bit unsigned integer value is larger or equal than another. + * + * @returns true if the first value is larger or equal, false if not. + * @param pValue1 The first value. + * @param pValue2 The second value. + */ +DECLINLINE(bool) RTUInt32IsLargerOrEqual(PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ +#ifdef RTUINT32_HAVE_32BIT_BASICS + return pValue1->u >= pValue2->u; +#else + return pValue1->s.Hi > pValue2->s.Hi + || ( pValue1->s.Hi == pValue2->s.Hi + && pValue1->s.Lo >= pValue2->s.Lo); +#endif +} + + +/** + * Tests if two 64-bit unsigned integer values not equal. + * + * @returns true if equal, false if not equal. + * @param pValue1 The first value. + * @param pValue2 The second value. + */ +DECLINLINE(bool) RTUInt32IsEqual(PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ +#ifdef RTUINT32_HAVE_32BIT_BASICS + return pValue1->u == pValue2->u; +#else + return pValue1->s.Hi == pValue2->s.Hi + && pValue1->s.Lo == pValue2->s.Lo; +#endif +} + + +/** + * Tests if two 64-bit unsigned integer values are not equal. + * + * @returns true if not equal, false if equal. + * @param pValue1 The first value. + * @param pValue2 The second value. + */ +DECLINLINE(bool) RTUInt32IsNotEqual(PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ + return !RTUInt32IsEqual(pValue1, pValue2); +} + + +/** + * Sets a bit in a 32-bit unsigned integer type. + * + * @returns pValueResult. + * @param pValueResult The input and output value. + * @param iBit The bit to set. + */ +DECLINLINE(PRTUINT32U) RTUInt32BitSet(PRTUINT32U pValueResult, unsigned iBit) +{ +#ifdef RTUINT32_HAVE_32BIT_BASICS + if (iBit < 32) + pValueResult->u |= RT_BIT_32(iBit); +#else + if (iBit < 16) + pValueResult->s.Lo |= UINT16_C(1) << iBit; + else if (iBit < 32) + pValueResult->s.Hi |= UINT16_C(1) << (iBit - 32); +#endif + return pValueResult; +} + + +/** + * Sets a bit in a 32-bit unsigned integer type. + * + * @returns pValueResult. + * @param pValueResult The input and output value. + * @param iBit The bit to set. + */ +DECLINLINE(PRTUINT32U) RTUInt32BitClear(PRTUINT32U pValueResult, unsigned iBit) +{ +#ifdef RTUINT32_HAVE_32BIT_BASICS + if (iBit < 32) + pValueResult->u &= ~RT_BIT_32(iBit); + +#else + if (iBit < 16) + pValueResult->s.Lo &= ~RT_BIT_32(iBit); + else if (iBit < 32) + pValueResult->s.Hi &= ~RT_BIT_32(iBit - 32); +#endif + return pValueResult; +} + + +/** + * Tests if a bit in a 32-bit unsigned integer value is set. + * + * @returns pValueResult. + * @param pValueResult The input and output value. + * @param iBit The bit to test. + */ +DECLINLINE(bool) RTUInt32BitTest(PRTUINT32U pValueResult, unsigned iBit) +{ + bool fRc; +#ifdef RTUINT32_HAVE_32BIT_BASICS + if (iBit < 32) + fRc = RT_BOOL(pValueResult->u & RT_BIT_32(iBit)); +#else + if (iBit < 16) + fRc = RT_BOOL(pValueResult->s.Lo & (UINT16_C(1) << iBit)); + else if (iBit < 32) + fRc = RT_BOOL(pValueResult->s.Hi & (UINT16_C(1) << (iBit - 64))); +#endif + else + fRc = false; + return fRc; +} + + +/** + * Set a range of bits a 32-bit unsigned integer value. + * + * @returns pValueResult. + * @param pValueResult The input and output value. + * @param iFirstBit The first bit to test. + * @param cBits The number of bits to set. + */ +DECLINLINE(PRTUINT32U) RTUInt32BitSetRange(PRTUINT32U pValueResult, unsigned iFirstBit, unsigned cBits) +{ + /* bounds check & fix. */ + if (iFirstBit < 32) + { +#ifdef RTUINT32_HAVE_32BIT_BASICS + if (iFirstBit + cBits < 32) + pValueResult->u |= (RT_BIT_32(cBits) - 1) << iFirstBit; + else + pValueResult->u = UINT32_MAX << iFirstBit; +#else + if (iFirstBit + cBits > 32) + cBits = 32 - iFirstBit; + if (iFirstBit + cBits < 16) + pValueResult->s.Lo |= ((UINT16_C(1) << cBits) - 1) << iFirstBit; + else if (iFirstBit + cBits < 32 && iFirstBit >= 16) + pValueResult->s.Hi |= ((UINT16_C(1) << cBits) - 1) << (iFirstBit - 16); + else + while (cBits-- > 0) + RTUInt32BitSet(pValueResult, iFirstBit++); +#endif + } + return pValueResult; +} + + +/** + * Test if all the bits of a 32-bit unsigned integer value are set. + * + * @returns true if they are, false if they aren't. + * @param pValue The input and output value. + */ +DECLINLINE(bool) RTUInt32BitAreAllSet(PRTUINT32U pValue) +{ + return pValue->s.Hi == UINT16_MAX + && pValue->s.Lo == UINT16_MAX; +} + + +/** + * Test if all the bits of a 32-bit unsigned integer value are clear. + * + * @returns true if they are, false if they aren't. + * @param pValue The input and output value. + */ +DECLINLINE(bool) RTUInt32BitAreAllClear(PRTUINT32U pValue) +{ + return RTUInt32IsZero(pValue); +} + + +DECLINLINE(unsigned) RTUInt32BitCount(PCRTUINT32U pValue) +{ + unsigned cBits; + if (pValue->s.Hi != 0) + cBits = 16 + ASMBitLastSetU16(pValue->s.Hi); + else + cBits = ASMBitLastSetU16(pValue->s.Lo); + return cBits; +} + + +/** + * Divides a 32-bit unsigned integer value by another, returning both quotient + * and remainder. + * + * @returns pQuotient, NULL if pValue2 is 0. + * @param pQuotient Where to return the quotient. + * @param pRemainder Where to return the remainder. + * @param pValue1 The dividend value. + * @param pValue2 The divisor value. + */ +DECLINLINE(PRTUINT32U) RTUInt32DivRem(PRTUINT32U pQuotient, PRTUINT32U pRemainder, PCRTUINT32U pValue1, PCRTUINT32U pValue2) +{ + int iDiff; + + /* + * Sort out all the special cases first. + */ + /* Divide by zero or 1? */ + if (!pValue2->s.Hi) + { + if (!pValue2->s.Lo) + return NULL; + + if (pValue2->s.Lo == 1) + { + RTUInt32SetZero(pRemainder); + *pQuotient = *pValue1; + return pQuotient; + } + /** @todo RTUInt32DivModByU32 */ + } + + /* Dividend is smaller? */ + iDiff = RTUInt32Compare(pValue1, pValue2); + if (iDiff < 0) + { + *pRemainder = *pValue1; + RTUInt32SetZero(pQuotient); + } + + /* The values are equal? */ + else if (iDiff == 0) + { + RTUInt32SetZero(pRemainder); + RTUInt32AssignU8(pQuotient, 1); + } + else + { + /* + * Prepare. + */ + unsigned iBitAdder = RTUInt32BitCount(pValue1) - RTUInt32BitCount(pValue2); + RTUINT32U NormDivisor = *pValue2; + if (iBitAdder) + { + RTUInt32ShiftLeft(&NormDivisor, pValue2, iBitAdder); + if (RTUInt32IsLarger(&NormDivisor, pValue1)) + { + RTUInt32AssignShiftRight(&NormDivisor, 1); + iBitAdder--; + } + } + else + NormDivisor = *pValue2; + + RTUInt32SetZero(pQuotient); + *pRemainder = *pValue1; + + /* + * Do the division. + */ + if (RTUInt32IsLargerOrEqual(pRemainder, pValue2)) + { + for (;;) + { + if (RTUInt32IsLargerOrEqual(pRemainder, &NormDivisor)) + { + RTUInt32AssignSub(pRemainder, &NormDivisor); + RTUInt32AssignOrBit(pQuotient, iBitAdder); + } + if (RTUInt32IsSmaller(pRemainder, pValue2)) + break; + RTUInt32AssignShiftRight(&NormDivisor, 1); + iBitAdder--; + } + } + } + return pQuotient; +} + + +/** @} */ + +RT_C_DECLS_END + +#endif /* !IPRT_INCLUDED_uint32_h */ + |