VirtualBox

Changeset 94511 in vbox


Ignore:
Timestamp:
Apr 7, 2022 1:17:57 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
150856
Message:

IPRT: Added RTUInt128MulEx and RTUInt128MulU64Ex as well as a limited RTUInt256Xxx Api. bugref:9898

Location:
trunk
Files:
5 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/mangling.h

    r94311 r94511  
    40554055# define RTUInt128MulByU64                              RT_MANGLER(RTUInt128MulByU64)
    40564056# define RTUInt128MulByU64_EndProc                      RT_MANGLER(RTUInt128MulByU64_EndProc)
     4057# define RTUInt128MulByU64Ex                            RT_MANGLER(RTUInt128MulByU64Ex)
     4058# define RTUInt128MulByU64Ex_EndProc                    RT_MANGLER(RTUInt128MulByU64Ex_EndProc)
    40574059# define RTUtf16Copy                                    RT_MANGLER(RTUtf16Copy)
    40584060# define RTUtf16CopyAscii                               RT_MANGLER(RTUtf16CopyAscii)
  • trunk/include/iprt/uint128.h

    r93115 r94511  
    5151 * @param   pValue          The input and output value.
    5252 */
    53 DECLINLINE(bool) RTUInt128IsZero(PRTUINT128U pValue)
     53DECLINLINE(bool) RTUInt128IsZero(PCRTUINT128U pValue)
    5454{
    5555#if ARCH_BITS >= 64
     
    307307    pResult->s.Hi += (uint64_t)uHiValue1 * uHiValue2;
    308308#endif
     309    return pResult;
     310}
     311
     312
     313/**
     314 * Multiplies an 128-bit unsigned integer by a 64-bit unsigned integer value,
     315 * returning a 256-bit result (top 64 bits are zero).
     316 *
     317 * @returns pResult
     318 * @param   pResult             The result variable.
     319 * @param   pValue1             The first value.
     320 * @param   uValue2             The second value, 64-bit.
     321 */
     322#if defined(RT_ARCH_AMD64)
     323RTDECL(PRTUINT256U) RTUInt128MulByU64Ex(PRTUINT256U pResult, PCRTUINT128U pValue1, uint64_t uValue2);
     324#else
     325DECLINLINE(PRTUINT256U) RTUInt128MulByU64Ex(PRTUINT256U pResult, PCRTUINT128U pValue1, uint64_t uValue2)
     326{
     327    /* multiply the two qwords in pValue1 by uValue2. */
     328    uint64_t uTmp = 0;
     329    pResult->QWords.qw0 = ASMMult2xU64Ret2xU64(pValue1->s.Lo, uValue2, &uTmp);
     330    pResult->QWords.qw1 = ASMMult2xU64Ret2xU64(pValue1->s.Hi, uValue2, &pResult->QWords.qw2);
     331    pResult->QWords.qw3 = 0;
     332    pResult->QWords.qw1 += uTmp;
     333    if (pResult->QWords.qw1 < uTmp)
     334        pResult->QWords.qw2++; /* This cannot overflow AFAIK: 0xffff*0xffff = 0xFFFE0001 */
     335
     336    return pResult;
     337}
     338#endif
     339
     340
     341/**
     342 * Multiplies two 128-bit unsigned integer values, returning a 256-bit result.
     343 *
     344 * @returns pResult
     345 * @param   pResult             The result variable.
     346 * @param   pValue1             The first value.
     347 * @param   pValue2             The second value.
     348 */
     349DECLINLINE(PRTUINT256U) RTUInt128MulEx(PRTUINT256U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
     350{
     351    RTUInt128MulByU64Ex(pResult, pValue1, pValue2->s.Lo);
     352    if (pValue2->s.Hi)
     353    {
     354        /* Multiply the two qwords in pValue1 by the high part of uValue2. */
     355        uint64_t uTmpHi = 0;
     356        uint64_t uTmpLo = ASMMult2xU64Ret2xU64(pValue1->s.Lo, pValue2->s.Hi, &uTmpHi);
     357        pResult->QWords.qw1 += uTmpLo;
     358        if (pResult->QWords.qw1 < uTmpLo)
     359            if (++pResult->QWords.qw2 == 0)
     360                pResult->QWords.qw3++;  /* (cannot overflow, was == 0) */
     361        pResult->QWords.qw2 += uTmpHi;
     362        if (pResult->QWords.qw2 < uTmpHi)
     363            pResult->QWords.qw3++;      /* (cannot overflow, was <= 1) */
     364
     365        uTmpLo = ASMMult2xU64Ret2xU64(pValue1->s.Hi, pValue2->s.Hi, &uTmpHi);
     366        pResult->QWords.qw2 += uTmpLo;
     367        if (pResult->QWords.qw2 < uTmpLo)
     368            pResult->QWords.qw3++;      /* (cannot overflow, was <= 2) */
     369        pResult->QWords.qw3 += uTmpHi;
     370    }
     371
    309372    return pResult;
    310373}
     
    12811344
    12821345
     1346/**
     1347 * Number of significant bits in the value.
     1348 *
     1349 * This is the same a ASMBitLastSetU64 and ASMBitLastSetU32.
     1350 *
     1351 * @returns 0 if zero, 1-base index of the last bit set.
     1352 * @param   pValue              The value to examine.
     1353 */
    12831354DECLINLINE(uint32_t) RTUInt128BitCount(PCRTUINT128U pValue)
    12841355{
  • trunk/include/iprt/uint256.h

    r94493 r94511  
    11/** @file
    2  * IPRT - RTUINT128U & uint128_t methods.
     2 * IPRT - RTUINT256U methods.
    33 */
    44
     
    2424 */
    2525
    26 #ifndef IPRT_INCLUDED_uint128_h
    27 #define IPRT_INCLUDED_uint128_h
     26#ifndef IPRT_INCLUDED_uint256_h
     27#define IPRT_INCLUDED_uint256_h
    2828#ifndef RT_WITHOUT_PRAGMA_ONCE
    2929# pragma once
     
    3939RT_C_DECLS_BEGIN
    4040
    41 /** @defgroup grp_rt_uint128 RTUInt128 - 128-bit Unsigned Integer Methods
     41/** @defgroup grp_rt_uint256 RTUInt256 - 256-bit Unsigned Integer Methods
    4242 * @ingroup grp_rt
    4343 * @{
     
    4646
    4747/**
    48  * Test if a 128-bit unsigned integer value is zero.
     48 * Test if a 256-bit unsigned integer value is zero.
    4949 *
    5050 * @returns true if they are, false if they aren't.
    5151 * @param   pValue          The input and output value.
    5252 */
    53 DECLINLINE(bool) RTUInt128IsZero(PRTUINT128U pValue)
     53DECLINLINE(bool) RTUInt256IsZero(PCRTUINT256U pValue)
    5454{
    5555#if ARCH_BITS >= 64
    56     return pValue->s.Hi == 0
    57         && pValue->s.Lo == 0;
     56    return pValue->QWords.qw0 == 0
     57        && pValue->QWords.qw1 == 0
     58        && pValue->QWords.qw2 == 0
     59        && pValue->QWords.qw3 == 0;
    5860#else
    5961    return pValue->DWords.dw0 == 0
    6062        && pValue->DWords.dw1 == 0
    6163        && pValue->DWords.dw2 == 0
    62         && pValue->DWords.dw3 == 0;
     64        && pValue->DWords.dw3 == 0
     65        && pValue->DWords.dw4 == 0
     66        && pValue->DWords.dw5 == 0
     67        && pValue->DWords.dw6 == 0
     68        && pValue->DWords.dw7 == 0;
    6369#endif
    6470}
     
    6672
    6773/**
    68  * Set a 128-bit unsigned integer value to zero.
    69  *
    70  * @returns pResult
    71  * @param   pResult             The result variable.
    72  */
    73 DECLINLINE(PRTUINT128U) RTUInt128SetZero(PRTUINT128U pResult)
     74 * Set a 256-bit unsigned integer value to zero.
     75 *
     76 * @returns pResult
     77 * @param   pResult             The result variable.
     78 */
     79DECLINLINE(PRTUINT256U) RTUInt256SetZero(PRTUINT256U pResult)
    7480{
    7581#if ARCH_BITS >= 64
    76     pResult->s.Hi = 0;
    77     pResult->s.Lo = 0;
     82    pResult->QWords.qw0 = 0;
     83    pResult->QWords.qw1 = 0;
     84    pResult->QWords.qw2 = 0;
     85    pResult->QWords.qw3 = 0;
    7886#else
    7987    pResult->DWords.dw0 = 0;
     
    8189    pResult->DWords.dw2 = 0;
    8290    pResult->DWords.dw3 = 0;
     91    pResult->DWords.dw4 = 0;
     92    pResult->DWords.dw5 = 0;
     93    pResult->DWords.dw6 = 0;
     94    pResult->DWords.dw7 = 0;
    8395#endif
    8496    return pResult;
     
    8799
    88100/**
    89  * Set a 128-bit unsigned integer value to the maximum value.
    90  *
    91  * @returns pResult
    92  * @param   pResult             The result variable.
    93  */
    94 DECLINLINE(PRTUINT128U) RTUInt128SetMax(PRTUINT128U pResult)
     101 * Set a 256-bit unsigned integer value to the maximum value.
     102 *
     103 * @returns pResult
     104 * @param   pResult             The result variable.
     105 */
     106DECLINLINE(PRTUINT256U) RTUInt256SetMax(PRTUINT256U pResult)
    95107{
    96108#if ARCH_BITS >= 64
    97     pResult->s.Hi = UINT64_MAX;
    98     pResult->s.Lo = UINT64_MAX;
     109    pResult->QWords.qw0 = UINT64_MAX;
     110    pResult->QWords.qw1 = UINT64_MAX;
     111    pResult->QWords.qw2 = UINT64_MAX;
     112    pResult->QWords.qw3 = UINT64_MAX;
    99113#else
    100114    pResult->DWords.dw0 = UINT32_MAX;
     
    102116    pResult->DWords.dw2 = UINT32_MAX;
    103117    pResult->DWords.dw3 = UINT32_MAX;
     118    pResult->DWords.dw4 = UINT32_MAX;
     119    pResult->DWords.dw5 = UINT32_MAX;
     120    pResult->DWords.dw6 = UINT32_MAX;
     121    pResult->DWords.dw7 = UINT32_MAX;
    104122#endif
    105123    return pResult;
     
    110128
    111129/**
    112  * Adds two 128-bit unsigned integer values.
     130 * Adds two 256-bit unsigned integer values.
    113131 *
    114132 * @returns pResult
     
    117135 * @param   pValue2             The second value.
    118136 */
    119 DECLINLINE(PRTUINT128U) RTUInt128Add(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    120 {
    121     pResult->s.Hi = pValue1->s.Hi + pValue2->s.Hi;
    122     pResult->s.Lo = pValue1->s.Lo + pValue2->s.Lo;
    123     if (pResult->s.Lo < pValue1->s.Lo)
    124         pResult->s.Hi++;
    125     return pResult;
    126 }
    127 
    128 
    129 /**
    130  * Adds a 128-bit and a 64-bit unsigned integer values.
     137DECLINLINE(PRTUINT256U) RTUInt256Add(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
     138{
     139    unsigned uCarry;
     140    pResult->QWords.qw0 = pValue1->QWords.qw0 + pValue2->QWords.qw0;
     141    uCarry = pResult->QWords.qw0 < pValue1->QWords.qw0;
     142
     143    pResult->QWords.qw1 = pValue1->QWords.qw1 + pValue2->QWords.qw1 + uCarry;
     144    uCarry = uCarry ? pResult->QWords.qw1 <= pValue1->QWords.qw1 : pResult->QWords.qw1 < pValue1->QWords.qw1;
     145
     146    pResult->QWords.qw2 = pValue1->QWords.qw2 + pValue2->QWords.qw2 + uCarry;
     147    uCarry = uCarry ? pResult->QWords.qw2 <= pValue1->QWords.qw2 : pResult->QWords.qw2 < pValue1->QWords.qw2;
     148
     149    pResult->QWords.qw3 = pValue1->QWords.qw3 + pValue2->QWords.qw3 + uCarry;
     150    return pResult;
     151}
     152
     153
     154/**
     155 * Adds a 256-bit and a 64-bit unsigned integer values.
    131156 *
    132157 * @returns pResult
     
    135160 * @param   uValue2             The second value, 64-bit.
    136161 */
    137 DECLINLINE(PRTUINT128U) RTUInt128AddU64(PRTUINT128U pResult, PCRTUINT128U pValue1, uint64_t uValue2)
    138 {
    139     pResult->s.Hi = pValue1->s.Hi;
    140     pResult->s.Lo = pValue1->s.Lo + uValue2;
    141     if (pResult->s.Lo < pValue1->s.Lo)
    142         pResult->s.Hi++;
    143     return pResult;
    144 }
    145 
    146 
    147 /**
    148  * Subtracts a 128-bit unsigned integer value from another.
     162DECLINLINE(PRTUINT256U) RTUInt256AddU64(PRTUINT256U pResult, PCRTUINT256U pValue1, uint64_t uValue2)
     163{
     164    pResult->QWords.qw3 = pValue1->QWords.qw3;
     165    pResult->QWords.qw2 = pValue1->QWords.qw2;
     166    pResult->QWords.qw1 = pValue1->QWords.qw1;
     167    pResult->QWords.qw0 = pValue1->QWords.qw0 + uValue2;
     168    if (pResult->QWords.qw0 < uValue2)
     169        if (pResult->QWords.qw1++ == UINT64_MAX)
     170            if (pResult->QWords.qw2++ == UINT64_MAX)
     171                pResult->QWords.qw3++;
     172    return pResult;
     173}
     174
     175
     176/**
     177 * Subtracts a 256-bit unsigned integer value from another.
    149178 *
    150179 * @returns pResult
     
    153182 * @param   pValue2             The subtrahend value.
    154183 */
    155 DECLINLINE(PRTUINT128U) RTUInt128Sub(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    156 {
    157     pResult->s.Lo = pValue1->s.Lo - pValue2->s.Lo;
    158     pResult->s.Hi = pValue1->s.Hi - pValue2->s.Hi;
    159     if (pResult->s.Lo > pValue1->s.Lo)
    160         pResult->s.Hi--;
    161     return pResult;
    162 }
    163 
    164 
    165 /**
    166  * Multiplies two 128-bit unsigned integer values.
     184DECLINLINE(PRTUINT256U) RTUInt256Sub(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
     185{
     186    unsigned uBorrow;
     187    pResult->QWords.qw0 = pValue1->QWords.qw0 - pValue2->QWords.qw0;
     188    uBorrow = pResult->QWords.qw0 > pValue1->QWords.qw0;
     189
     190    pResult->QWords.qw1 = pValue1->QWords.qw1 - pValue2->QWords.qw1 - uBorrow;
     191    uBorrow = uBorrow ? pResult->QWords.qw1 >= pValue1->QWords.qw1 : pResult->QWords.qw1 > pValue1->QWords.qw1;
     192
     193    pResult->QWords.qw2 = pValue1->QWords.qw2 - pValue2->QWords.qw2 - uBorrow;
     194    uBorrow = uBorrow ? pResult->QWords.qw2 >= pValue1->QWords.qw2 : pResult->QWords.qw2 > pValue1->QWords.qw2;
     195
     196    pResult->QWords.qw3 = pValue1->QWords.qw3 - pValue2->QWords.qw3 - uBorrow;
     197    return pResult;
     198}
     199
     200
     201/**
     202 * Multiplies two 256-bit unsigned integer values.
    167203 *
    168204 * @returns pResult
     
    171207 * @param   pValue2             The second value.
    172208 */
    173 DECLINLINE(PRTUINT128U) RTUInt128Mul(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    174 {
    175     RTUINT64U uTmp;
    176 
    177     /* multiply all dwords in v1 by v2.dw0. */
    178     pResult->s.Lo = (uint64_t)pValue1->DWords.dw0 * pValue2->DWords.dw0;
    179 
    180     uTmp.u = (uint64_t)pValue1->DWords.dw1 * pValue2->DWords.dw0;
    181     pResult->DWords.dw3 = 0;
    182     pResult->DWords.dw2 = uTmp.DWords.dw1;
    183     pResult->DWords.dw1 += uTmp.DWords.dw0;
    184     if (pResult->DWords.dw1 < uTmp.DWords.dw0)
    185         if (pResult->DWords.dw2++ == UINT32_MAX)
    186             pResult->DWords.dw3++;
    187 
    188     pResult->s.Hi += (uint64_t)pValue1->DWords.dw2 * pValue2->DWords.dw0;
    189     pResult->DWords.dw3     += pValue1->DWords.dw3 * pValue2->DWords.dw0;
    190 
    191     /* multiply dw0, dw1 & dw2 in v1 by v2.dw1. */
    192     uTmp.u = (uint64_t)pValue1->DWords.dw0 * pValue2->DWords.dw1;
    193     pResult->DWords.dw1 += uTmp.DWords.dw0;
    194     if (pResult->DWords.dw1 < uTmp.DWords.dw0)
    195         if (pResult->DWords.dw2++ == UINT32_MAX)
    196             pResult->DWords.dw3++;
    197 
    198     pResult->DWords.dw2 += uTmp.DWords.dw1;
    199     if (pResult->DWords.dw2 < uTmp.DWords.dw1)
    200         pResult->DWords.dw3++;
    201 
    202     pResult->s.Hi += (uint64_t)pValue1->DWords.dw1 * pValue2->DWords.dw1;
    203     pResult->DWords.dw3     += pValue1->DWords.dw2 * pValue2->DWords.dw1;
    204 
    205     /* multiply dw0 & dw1 in v1 by v2.dw2. */
    206     pResult->s.Hi += (uint64_t)pValue1->DWords.dw0 * pValue2->DWords.dw2;
    207     pResult->DWords.dw3     += pValue1->DWords.dw1 * pValue2->DWords.dw2;
    208 
    209     /* multiply dw0 in v1 by v2.dw3. */
    210     pResult->DWords.dw3     += pValue1->DWords.dw0 * pValue2->DWords.dw3;
    211 
    212     return pResult;
    213 }
    214 
    215 
    216 /**
    217  * Multiplies an 128-bit unsigned integer by a 64-bit unsigned integer value.
     209RTDECL(PRTUINT256U) RTUInt256Mul(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2);
     210
     211/**
     212 * Multiplies an 256-bit unsigned integer by a 64-bit unsigned integer value.
    218213 *
    219214 * @returns pResult
     
    222217 * @param   uValue2             The second value, 64-bit.
    223218 */
    224 #if defined(RT_ARCH_AMD64)
    225 RTDECL(PRTUINT128U) RTUInt128MulByU64(PRTUINT128U pResult, PCRTUINT128U pValue1, uint64_t uValue2);
    226 #else
    227 DECLINLINE(PRTUINT128U) RTUInt128MulByU64(PRTUINT128U pResult, PCRTUINT128U pValue1, uint64_t uValue2)
    228 {
    229     uint32_t const uLoValue2 = (uint32_t)uValue2;
    230     uint32_t const uHiValue2 = (uint32_t)(uValue2 >> 32);
    231     RTUINT64U uTmp;
    232 
    233     /* multiply all dwords in v1 by uLoValue1. */
    234     pResult->s.Lo = (uint64_t)pValue1->DWords.dw0 * uLoValue2;
    235 
    236     uTmp.u = (uint64_t)pValue1->DWords.dw1 * uLoValue2;
    237     pResult->DWords.dw3 = 0;
    238     pResult->DWords.dw2 = uTmp.DWords.dw1;
    239     pResult->DWords.dw1 += uTmp.DWords.dw0;
    240     if (pResult->DWords.dw1 < uTmp.DWords.dw0)
    241         if (pResult->DWords.dw2++ == UINT32_MAX)
    242             pResult->DWords.dw3++;
    243 
    244     pResult->s.Hi += (uint64_t)pValue1->DWords.dw2 * uLoValue2;
    245     pResult->DWords.dw3     += pValue1->DWords.dw3 * uLoValue2;
    246 
    247     /* multiply dw0, dw1 & dw2 in v1 by uHiValue2. */
    248     uTmp.u = (uint64_t)pValue1->DWords.dw0 * uHiValue2;
    249     pResult->DWords.dw1 += uTmp.DWords.dw0;
    250     if (pResult->DWords.dw1 < uTmp.DWords.dw0)
    251         if (pResult->DWords.dw2++ == UINT32_MAX)
    252             pResult->DWords.dw3++;
    253 
    254     pResult->DWords.dw2 += uTmp.DWords.dw1;
    255     if (pResult->DWords.dw2 < uTmp.DWords.dw1)
    256         pResult->DWords.dw3++;
    257 
    258     pResult->s.Hi += (uint64_t)pValue1->DWords.dw1 * uHiValue2;
    259     pResult->DWords.dw3     += pValue1->DWords.dw2 * uHiValue2;
    260 
    261     return pResult;
    262 }
    263 #endif
    264 
    265 
    266 /**
    267  * Multiplies two 64-bit unsigned integer values with 128-bit precision.
    268  *
    269  * @returns pResult
    270  * @param   pResult             The result variable.
    271  * @param   uValue1             The first value. 64-bit.
    272  * @param   uValue2             The second value, 64-bit.
    273  */
    274 DECLINLINE(PRTUINT128U) RTUInt128MulU64ByU64(PRTUINT128U pResult, uint64_t uValue1, uint64_t uValue2)
    275 {
    276 #ifdef RT_ARCH_AMD64
    277     pResult->s.Lo = ASMMult2xU64Ret2xU64(uValue1, uValue2, &pResult->s.Hi);
    278 #else
    279     uint32_t const uLoValue1 = (uint32_t)uValue1;
    280     uint32_t const uHiValue1 = (uint32_t)(uValue1 >> 32);
    281     uint32_t const uLoValue2 = (uint32_t)uValue2;
    282     uint32_t const uHiValue2 = (uint32_t)(uValue2 >> 32);
    283     RTUINT64U uTmp;
    284 
    285     /* Multiply uLoValue1 and uHiValue1 by uLoValue1. */
    286     pResult->s.Lo = (uint64_t)uLoValue1 * uLoValue2;
    287 
    288     uTmp.u = (uint64_t)uHiValue1 * uLoValue2;
    289     pResult->DWords.dw3 = 0;
    290     pResult->DWords.dw2 = uTmp.DWords.dw1;
    291     pResult->DWords.dw1 += uTmp.DWords.dw0;
    292     if (pResult->DWords.dw1 < uTmp.DWords.dw0)
    293         if (pResult->DWords.dw2++ == UINT32_MAX)
    294             pResult->DWords.dw3++;
    295 
    296     /* Multiply uLoValue1 and uHiValue1 by uHiValue2. */
    297     uTmp.u = (uint64_t)uLoValue1 * uHiValue2;
    298     pResult->DWords.dw1 += uTmp.DWords.dw0;
    299     if (pResult->DWords.dw1 < uTmp.DWords.dw0)
    300         if (pResult->DWords.dw2++ == UINT32_MAX)
    301             pResult->DWords.dw3++;
    302 
    303     pResult->DWords.dw2 += uTmp.DWords.dw1;
    304     if (pResult->DWords.dw2 < uTmp.DWords.dw1)
    305         pResult->DWords.dw3++;
    306 
    307     pResult->s.Hi += (uint64_t)uHiValue1 * uHiValue2;
    308 #endif
    309     return pResult;
    310 }
    311 
    312 
    313 DECLINLINE(PRTUINT128U) RTUInt128DivRem(PRTUINT128U pQuotient, PRTUINT128U pRemainder, PCRTUINT128U pValue1, PCRTUINT128U pValue2);
    314 
    315 /**
    316  * Divides a 128-bit unsigned integer value by another.
    317  *
    318  * @returns pResult
    319  * @param   pResult             The result variable.
    320  * @param   pValue1             The dividend value.
    321  * @param   pValue2             The divisor value.
    322  */
    323 DECLINLINE(PRTUINT128U) RTUInt128Div(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    324 {
    325     RTUINT128U Ignored;
    326     return RTUInt128DivRem(pResult, &Ignored, pValue1, pValue2);
    327 }
    328 
    329 
    330 /**
    331  * Divides a 128-bit unsigned integer value by another, returning the remainder.
    332  *
    333  * @returns pResult
    334  * @param   pResult             The result variable (remainder).
    335  * @param   pValue1             The dividend value.
    336  * @param   pValue2             The divisor value.
    337  */
    338 DECLINLINE(PRTUINT128U) RTUInt128Mod(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    339 {
    340     RTUINT128U Ignored;
    341     RTUInt128DivRem(&Ignored, pResult, pValue1, pValue2);
    342     return pResult;
    343 }
    344 
    345 
    346 /**
    347  * Bitwise AND of two 128-bit unsigned integer values.
    348  *
    349  * @returns pResult
    350  * @param   pResult             The result variable.
    351  * @param   pValue1             The first value.
    352  * @param   pValue2             The second value.
    353  */
    354 DECLINLINE(PRTUINT128U) RTUInt128And(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    355 {
    356     pResult->s.Hi = pValue1->s.Hi & pValue2->s.Hi;
    357     pResult->s.Lo = pValue1->s.Lo & pValue2->s.Lo;
    358     return pResult;
    359 }
    360 
    361 
    362 /**
    363  * Bitwise OR of two 128-bit unsigned integer values.
    364  *
    365  * @returns pResult
    366  * @param   pResult             The result variable.
    367  * @param   pValue1             The first value.
    368  * @param   pValue2             The second value.
    369  */
    370 DECLINLINE(PRTUINT128U) RTUInt128Or( PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    371 {
    372     pResult->s.Hi = pValue1->s.Hi | pValue2->s.Hi;
    373     pResult->s.Lo = pValue1->s.Lo | pValue2->s.Lo;
    374     return pResult;
    375 }
    376 
    377 
    378 /**
    379  * Bitwise XOR of two 128-bit unsigned integer values.
    380  *
    381  * @returns pResult
    382  * @param   pResult             The result variable.
    383  * @param   pValue1             The first value.
    384  * @param   pValue2             The second value.
    385  */
    386 DECLINLINE(PRTUINT128U) RTUInt128Xor(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    387 {
    388     pResult->s.Hi = pValue1->s.Hi ^ pValue2->s.Hi;
    389     pResult->s.Lo = pValue1->s.Lo ^ pValue2->s.Lo;
    390     return pResult;
    391 }
    392 
    393 
    394 /**
    395  * Shifts a 128-bit unsigned integer value @a cBits to the left.
    396  *
    397  * @returns pResult
    398  * @param   pResult             The result variable.
    399  * @param   pValue              The value to shift.
    400  * @param   cBits               The number of bits to shift it.
    401  */
    402 DECLINLINE(PRTUINT128U) RTUInt128ShiftLeft(PRTUINT128U pResult, PCRTUINT128U pValue, int cBits)
    403 {
    404     cBits &= 127;
    405     if (cBits < 64)
    406     {
    407         pResult->s.Lo = pValue->s.Lo << cBits;
    408         pResult->s.Hi = (pValue->s.Hi << cBits) | (pValue->s.Lo >> (64 - cBits));
    409     }
    410     else
    411     {
    412         pResult->s.Lo = 0;
    413         pResult->s.Hi = pValue->s.Lo << (cBits - 64);
    414     }
    415     return pResult;
    416 }
    417 
    418 
    419 /**
    420  * Shifts a 128-bit unsigned integer value @a cBits to the right.
    421  *
    422  * @returns pResult
    423  * @param   pResult             The result variable.
    424  * @param   pValue              The value to shift.
    425  * @param   cBits               The number of bits to shift it.
    426  */
    427 DECLINLINE(PRTUINT128U) RTUInt128ShiftRight(PRTUINT128U pResult, PCRTUINT128U pValue, int cBits)
    428 {
    429     cBits &= 127;
    430     if (cBits < 64)
    431     {
    432         pResult->s.Hi = pValue->s.Hi >> cBits;
    433         pResult->s.Lo = (pValue->s.Lo >> cBits) | (pValue->s.Hi << (64 - cBits));
    434     }
    435     else
    436     {
    437         pResult->s.Hi = 0;
    438         pResult->s.Lo = pValue->s.Hi >> (cBits - 64);
    439     }
    440     return pResult;
    441 }
    442 
    443 
    444 /**
    445  * Boolean not (result 0 or 1).
    446  *
    447  * @returns pResult.
    448  * @param   pResult             The result variable.
    449  * @param   pValue              The value.
    450  */
    451 DECLINLINE(PRTUINT128U) RTUInt128BooleanNot(PRTUINT128U pResult, PCRTUINT128U pValue)
    452 {
    453     pResult->s.Lo = pValue->s.Lo || pValue->s.Hi ? 0 : 1;
    454     pResult->s.Hi = 0;
    455     return pResult;
    456 }
    457 
    458 
    459 /**
    460  * Bitwise not (flips each bit of the 128 bits).
    461  *
    462  * @returns pResult.
    463  * @param   pResult             The result variable.
    464  * @param   pValue              The value.
    465  */
    466 DECLINLINE(PRTUINT128U) RTUInt128BitwiseNot(PRTUINT128U pResult, PCRTUINT128U pValue)
    467 {
    468     pResult->s.Hi = ~pValue->s.Hi;
    469     pResult->s.Lo = ~pValue->s.Lo;
    470     return pResult;
    471 }
    472 
    473 
    474 /**
    475  * Assigns one 128-bit unsigned integer value to another.
    476  *
    477  * @returns pResult
    478  * @param   pResult             The result variable.
    479  * @param   pValue              The value to assign.
    480  */
    481 DECLINLINE(PRTUINT128U) RTUInt128Assign(PRTUINT128U pResult, PCRTUINT128U pValue)
    482 {
    483 #if ARCH_BITS >= 64
    484     pResult->s.Hi = pValue->s.Hi;
    485     pResult->s.Lo = pValue->s.Lo;
    486 #else
    487     pResult->DWords.dw0 = pValue->DWords.dw0;
    488     pResult->DWords.dw1 = pValue->DWords.dw1;
    489     pResult->DWords.dw2 = pValue->DWords.dw2;
    490     pResult->DWords.dw3 = pValue->DWords.dw3;
    491 #endif
    492     return pResult;
    493 }
    494 
    495 
    496 /**
    497  * Assigns a boolean value to 128-bit unsigned integer.
    498  *
    499  * @returns pValueResult
    500  * @param   pValueResult        The result variable.
    501  * @param   fValue              The boolean value.
    502  */
    503 DECLINLINE(PRTUINT128U) RTUInt128AssignBoolean(PRTUINT128U pValueResult, bool fValue)
    504 {
    505 #if ARCH_BITS >= 64
    506     pValueResult->s.Lo = fValue;
    507     pValueResult->s.Hi = 0;
    508 #else
    509     pValueResult->DWords.dw0 = fValue;
    510     pValueResult->DWords.dw1 = 0;
    511     pValueResult->DWords.dw2 = 0;
    512     pValueResult->DWords.dw3 = 0;
    513 #endif
    514     return pValueResult;
    515 }
    516 
    517 
    518 /**
    519  * Assigns a 8-bit unsigned integer value to 128-bit unsigned integer.
    520  *
    521  * @returns pValueResult
    522  * @param   pValueResult        The result variable.
    523  * @param   u8Value             The 8-bit unsigned integer value.
    524  */
    525 DECLINLINE(PRTUINT128U) RTUInt128AssignU8(PRTUINT128U pValueResult, uint8_t u8Value)
    526 {
    527 #if ARCH_BITS >= 64
    528     pValueResult->s.Lo = u8Value;
    529     pValueResult->s.Hi = 0;
    530 #else
    531     pValueResult->DWords.dw0 = u8Value;
    532     pValueResult->DWords.dw1 = 0;
    533     pValueResult->DWords.dw2 = 0;
    534     pValueResult->DWords.dw3 = 0;
    535 #endif
    536     return pValueResult;
    537 }
    538 
    539 
    540 /**
    541  * Assigns a 16-bit unsigned integer value to 128-bit unsigned integer.
    542  *
    543  * @returns pValueResult
    544  * @param   pValueResult        The result variable.
    545  * @param   u16Value            The 16-bit unsigned integer value.
    546  */
    547 DECLINLINE(PRTUINT128U) RTUInt128AssignU16(PRTUINT128U pValueResult, uint16_t u16Value)
    548 {
    549 #if ARCH_BITS >= 64
    550     pValueResult->s.Lo = u16Value;
    551     pValueResult->s.Hi = 0;
    552 #else
    553     pValueResult->DWords.dw0 = u16Value;
    554     pValueResult->DWords.dw1 = 0;
    555     pValueResult->DWords.dw2 = 0;
    556     pValueResult->DWords.dw3 = 0;
    557 #endif
    558     return pValueResult;
    559 }
    560 
    561 
    562 /**
    563  * Assigns a 32-bit unsigned integer value to 128-bit unsigned integer.
    564  *
    565  * @returns pValueResult
    566  * @param   pValueResult        The result variable.
    567  * @param   u32Value            The 32-bit unsigned integer value.
    568  */
    569 DECLINLINE(PRTUINT128U) RTUInt128AssignU32(PRTUINT128U pValueResult, uint32_t u32Value)
    570 {
    571 #if ARCH_BITS >= 64
    572     pValueResult->s.Lo = u32Value;
    573     pValueResult->s.Hi = 0;
    574 #else
    575     pValueResult->DWords.dw0 = u32Value;
    576     pValueResult->DWords.dw1 = 0;
    577     pValueResult->DWords.dw2 = 0;
    578     pValueResult->DWords.dw3 = 0;
    579 #endif
    580     return pValueResult;
    581 }
    582 
    583 
    584 /**
    585  * Assigns a 64-bit unsigned integer value to 128-bit unsigned integer.
    586  *
    587  * @returns pValueResult
    588  * @param   pValueResult        The result variable.
    589  * @param   u64Value            The 64-bit unsigned integer value.
    590  */
    591 DECLINLINE(PRTUINT128U) RTUInt128AssignU64(PRTUINT128U pValueResult, uint64_t u64Value)
    592 {
    593     pValueResult->s.Lo = u64Value;
    594     pValueResult->s.Hi = 0;
    595     return pValueResult;
    596 }
    597 
    598 
    599 /**
    600  * Adds two 128-bit unsigned integer values, storing the result in the first.
    601  *
    602  * @returns pValue1Result.
    603  * @param   pValue1Result   The first value and result.
    604  * @param   pValue2         The second value.
    605  */
    606 DECLINLINE(PRTUINT128U) RTUInt128AssignAdd(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
    607 {
    608     uint64_t const uTmp = pValue1Result->s.Lo;
    609     pValue1Result->s.Lo += pValue2->s.Lo;
    610     if (pValue1Result->s.Lo < uTmp)
    611         pValue1Result->s.Hi++;
    612     pValue1Result->s.Hi += pValue2->s.Hi;
    613     return pValue1Result;
    614 }
    615 
    616 
    617 /**
    618  * Adds a 64-bit unsigned integer value to a 128-bit unsigned integer values,
    619  * storing the result in the 128-bit one.
    620  *
    621  * @returns pValue1Result.
    622  * @param   pValue1Result   The first value and result.
    623  * @param   uValue2         The second value, 64-bit.
    624  */
    625 DECLINLINE(PRTUINT128U) RTUInt128AssignAddU64(PRTUINT128U pValue1Result, uint64_t uValue2)
    626 {
    627     pValue1Result->s.Lo += uValue2;
    628     if (pValue1Result->s.Lo < uValue2)
    629         pValue1Result->s.Hi++;
    630     return pValue1Result;
    631 }
    632 
    633 
    634 /**
    635  * Subtracts two 128-bit unsigned integer values, storing the result in the
    636  * first.
    637  *
    638  * @returns pValue1Result.
    639  * @param   pValue1Result   The minuend value and result.
    640  * @param   pValue2         The subtrahend value.
    641  */
    642 DECLINLINE(PRTUINT128U) RTUInt128AssignSub(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
    643 {
    644     uint64_t const uTmp = pValue1Result->s.Lo;
    645     pValue1Result->s.Lo -= pValue2->s.Lo;
    646     if (pValue1Result->s.Lo > uTmp)
    647         pValue1Result->s.Hi--;
    648     pValue1Result->s.Hi -= pValue2->s.Hi;
    649     return pValue1Result;
    650 }
    651 
    652 
    653 /**
    654  * Negates a 128 number, storing the result in the input.
    655  *
    656  * @returns pValueResult.
    657  * @param   pValueResult    The value to negate.
    658  */
    659 DECLINLINE(PRTUINT128U) RTUInt128AssignNeg(PRTUINT128U pValueResult)
    660 {
    661     /* result = 0 - value */
    662     if (pValueResult->s.Lo != 0)
    663     {
    664         pValueResult->s.Lo = UINT64_C(0) - pValueResult->s.Lo;
    665         pValueResult->s.Hi = UINT64_MAX  - pValueResult->s.Hi;
    666     }
    667     else
    668         pValueResult->s.Hi = UINT64_C(0) - pValueResult->s.Hi;
    669     return pValueResult;
    670 }
    671 
    672 
    673 /**
    674  * Multiplies two 128-bit unsigned integer values, storing the result in the
    675  * first.
    676  *
    677  * @returns pValue1Result.
    678  * @param   pValue1Result   The first value and result.
    679  * @param   pValue2         The second value.
    680  */
    681 DECLINLINE(PRTUINT128U) RTUInt128AssignMul(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
    682 {
    683     RTUINT128U Result;
    684     RTUInt128Mul(&Result, pValue1Result, pValue2);
    685     *pValue1Result = Result;
    686     return pValue1Result;
    687 }
    688 
    689 
    690 /**
    691  * Divides a 128-bit unsigned integer value by another, storing the result in
    692  * the first.
    693  *
    694  * @returns pValue1Result.
    695  * @param   pValue1Result   The dividend value and result.
    696  * @param   pValue2         The divisor value.
    697  */
    698 DECLINLINE(PRTUINT128U) RTUInt128AssignDiv(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
    699 {
    700     RTUINT128U Result;
    701     RTUINT128U Ignored;
    702     RTUInt128DivRem(&Result, &Ignored, pValue1Result, pValue2);
    703     *pValue1Result = Result;
    704     return pValue1Result;
    705 }
    706 
    707 
    708 /**
    709  * Divides a 128-bit unsigned integer value by another, storing the remainder in
    710  * the first.
    711  *
    712  * @returns pValue1Result.
    713  * @param   pValue1Result   The dividend value and result (remainder).
    714  * @param   pValue2         The divisor value.
    715  */
    716 DECLINLINE(PRTUINT128U) RTUInt128AssignMod(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
    717 {
    718     RTUINT128U Ignored;
    719     RTUINT128U Result;
    720     RTUInt128DivRem(&Ignored, &Result, pValue1Result, pValue2);
    721     *pValue1Result = Result;
    722     return pValue1Result;
    723 }
    724 
    725 
    726 /**
    727  * Performs a bitwise AND of two 128-bit unsigned integer values and assigned
    728  * the result to the first one.
    729  *
    730  * @returns pValue1Result.
    731  * @param   pValue1Result   The first value and result.
    732  * @param   pValue2         The second value.
    733  */
    734 DECLINLINE(PRTUINT128U) RTUInt128AssignAnd(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
    735 {
    736 #if ARCH_BITS >= 64
    737     pValue1Result->s.Hi &= pValue2->s.Hi;
    738     pValue1Result->s.Lo &= pValue2->s.Lo;
    739 #else
    740     pValue1Result->DWords.dw0 &= pValue2->DWords.dw0;
    741     pValue1Result->DWords.dw1 &= pValue2->DWords.dw1;
    742     pValue1Result->DWords.dw2 &= pValue2->DWords.dw2;
    743     pValue1Result->DWords.dw3 &= pValue2->DWords.dw3;
    744 #endif
    745     return pValue1Result;
    746 }
    747 
    748 
    749 /**
    750  * Performs a bitwise AND of a 128-bit unsigned integer value and a mask made
    751  * up of the first N bits, assigning the result to the the 128-bit value.
    752  *
    753  * @returns pValueResult.
    754  * @param   pValueResult    The value and result.
    755  * @param   cBits           The number of bits to AND (counting from the first
    756  *                          bit).
    757  */
    758 DECLINLINE(PRTUINT128U) RTUInt128AssignAndNFirstBits(PRTUINT128U pValueResult, unsigned cBits)
    759 {
    760     if (cBits <= 64)
    761     {
    762         if (cBits != 64)
    763             pValueResult->s.Lo &= (RT_BIT_64(cBits) - 1);
    764         pValueResult->s.Hi = 0;
    765     }
    766     else if (cBits < 128)
    767         pValueResult->s.Hi &= (RT_BIT_64(cBits - 64) - 1);
    768 /** @todo \#if ARCH_BITS >= 64 */
    769     return pValueResult;
    770 }
    771 
    772 
    773 /**
    774  * Performs a bitwise OR of two 128-bit unsigned integer values and assigned
    775  * the result to the first one.
    776  *
    777  * @returns pValue1Result.
    778  * @param   pValue1Result   The first value and result.
    779  * @param   pValue2         The second value.
    780  */
    781 DECLINLINE(PRTUINT128U) RTUInt128AssignOr(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
    782 {
    783 #if ARCH_BITS >= 64
    784     pValue1Result->s.Hi |= pValue2->s.Hi;
    785     pValue1Result->s.Lo |= pValue2->s.Lo;
    786 #else
    787     pValue1Result->DWords.dw0 |= pValue2->DWords.dw0;
    788     pValue1Result->DWords.dw1 |= pValue2->DWords.dw1;
    789     pValue1Result->DWords.dw2 |= pValue2->DWords.dw2;
    790     pValue1Result->DWords.dw3 |= pValue2->DWords.dw3;
    791 #endif
    792     return pValue1Result;
    793 }
    794 
    795 
    796 /**
    797  * ORs in a bit and assign the result to the input value.
    798  *
    799  * @returns pValue1Result.
    800  * @param   pValue1Result   The first value and result.
    801  * @param   iBit            The bit to set (0 based).
    802  */
    803 DECLINLINE(PRTUINT128U) RTUInt128AssignOrBit(PRTUINT128U pValue1Result, uint32_t iBit)
    804 {
    805 #if ARCH_BITS >= 64
    806     if (iBit >= 64)
    807         pValue1Result->s.Hi |= RT_BIT_64(iBit - 64);
    808     else
    809         pValue1Result->s.Lo |= RT_BIT_64(iBit);
    810 #else
    811     if (iBit >= 64)
    812     {
    813         if (iBit >= 96)
    814             pValue1Result->DWords.dw3 |= RT_BIT_32(iBit - 96);
    815         else
    816             pValue1Result->DWords.dw2 |= RT_BIT_32(iBit - 64);
    817     }
    818     else
    819     {
    820         if (iBit >= 32)
    821             pValue1Result->DWords.dw1 |= RT_BIT_32(iBit - 32);
    822         else
    823             pValue1Result->DWords.dw0 |= RT_BIT_32(iBit);
    824     }
    825 #endif
    826     return pValue1Result;
    827 }
    828 
    829 
    830 
    831 /**
    832  * Performs a bitwise XOR of two 128-bit unsigned integer values and assigned
    833  * the result to the first one.
    834  *
    835  * @returns pValue1Result.
    836  * @param   pValue1Result   The first value and result.
    837  * @param   pValue2         The second value.
    838  */
    839 DECLINLINE(PRTUINT128U) RTUInt128AssignXor(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
    840 {
    841 #if ARCH_BITS >= 64
    842     pValue1Result->s.Hi ^= pValue2->s.Hi;
    843     pValue1Result->s.Lo ^= pValue2->s.Lo;
    844 #else
    845     pValue1Result->DWords.dw0 ^= pValue2->DWords.dw0;
    846     pValue1Result->DWords.dw1 ^= pValue2->DWords.dw1;
    847     pValue1Result->DWords.dw2 ^= pValue2->DWords.dw2;
    848     pValue1Result->DWords.dw3 ^= pValue2->DWords.dw3;
    849 #endif
    850     return pValue1Result;
    851 }
    852 
    853 
    854 /**
    855  * Performs a bitwise left shift on a 128-bit unsigned integer value, assigning
    856  * the result to it.
    857  *
    858  * @returns pValueResult.
    859  * @param   pValueResult    The first value and result.
    860  * @param   cBits           The number of bits to shift.
    861  */
    862 DECLINLINE(PRTUINT128U) RTUInt128AssignShiftLeft(PRTUINT128U pValueResult, int cBits)
    863 {
    864     RTUINT128U const InVal = *pValueResult;
    865 /** @todo \#if ARCH_BITS >= 64 */
    866     if (cBits > 0)
    867     {
    868         /* (left shift) */
    869         if (cBits >= 128)
    870             RTUInt128SetZero(pValueResult);
    871         else if (cBits >= 64)
    872         {
    873             pValueResult->s.Lo  = 0;
    874             pValueResult->s.Hi  = InVal.s.Lo << (cBits - 64);
    875         }
    876         else
    877         {
    878             pValueResult->s.Hi  = InVal.s.Hi << cBits;
    879             pValueResult->s.Hi |= InVal.s.Lo >> (64 - cBits);
    880             pValueResult->s.Lo  = InVal.s.Lo << cBits;
    881         }
    882     }
    883     else if (cBits < 0)
    884     {
    885         /* (right shift) */
    886         cBits = -cBits;
    887         if (cBits >= 128)
    888             RTUInt128SetZero(pValueResult);
    889         else if (cBits >= 64)
    890         {
    891             pValueResult->s.Hi  = 0;
    892             pValueResult->s.Lo  = InVal.s.Hi >> (cBits - 64);
    893         }
    894         else
    895         {
    896             pValueResult->s.Lo  = InVal.s.Lo >> cBits;
    897             pValueResult->s.Lo |= InVal.s.Hi << (64 - cBits);
    898             pValueResult->s.Hi  = InVal.s.Hi >> cBits;
    899         }
    900     }
    901     return pValueResult;
    902 }
    903 
    904 
    905 /**
    906  * Performs a bitwise left shift on a 128-bit unsigned integer value, assigning
    907  * the result to it.
    908  *
    909  * @returns pValueResult.
    910  * @param   pValueResult    The first value and result.
    911  * @param   cBits           The number of bits to shift.
    912  */
    913 DECLINLINE(PRTUINT128U) RTUInt128AssignShiftRight(PRTUINT128U pValueResult, int cBits)
    914 {
    915     return RTUInt128AssignShiftLeft(pValueResult, -cBits);
    916 }
    917 
    918 
    919 /**
    920  * Performs a bitwise NOT on a 128-bit unsigned integer value, assigning the
    921  * result to it.
    922  *
    923  * @returns pValueResult
    924  * @param   pValueResult    The value and result.
    925  */
    926 DECLINLINE(PRTUINT128U) RTUInt128AssignBitwiseNot(PRTUINT128U pValueResult)
    927 {
    928 #if ARCH_BITS >= 64
    929     pValueResult->s.Hi = ~pValueResult->s.Hi;
    930     pValueResult->s.Lo = ~pValueResult->s.Lo;
    931 #else
    932     pValueResult->DWords.dw0 = ~pValueResult->DWords.dw0;
    933     pValueResult->DWords.dw1 = ~pValueResult->DWords.dw1;
    934     pValueResult->DWords.dw2 = ~pValueResult->DWords.dw2;
    935     pValueResult->DWords.dw3 = ~pValueResult->DWords.dw3;
    936 #endif
    937     return pValueResult;
    938 }
    939 
    940 
    941 /**
    942  * Performs a boolean NOT on a 128-bit unsigned integer value, assigning the
    943  * result to it.
    944  *
    945  * @returns pValueResult
    946  * @param   pValueResult    The value and result.
    947  */
    948 DECLINLINE(PRTUINT128U) RTUInt128AssignBooleanNot(PRTUINT128U pValueResult)
    949 {
    950     return RTUInt128AssignBoolean(pValueResult, RTUInt128IsZero(pValueResult));
    951 }
    952 
    953 
    954 /**
    955  * Compares two 128-bit unsigned integer values.
    956  *
    957  * @retval  0 if equal.
    958  * @retval  -1 if the first value is smaller than the second.
    959  * @retval  1  if the first value is larger than the second.
    960  *
    961  * @param   pValue1             The first value.
    962  * @param   pValue2             The second value.
    963  */
    964 DECLINLINE(int) RTUInt128Compare(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    965 {
    966 #if ARCH_BITS >= 64
    967     if (pValue1->s.Hi != pValue2->s.Hi)
    968         return pValue1->s.Hi > pValue2->s.Hi ? 1 : -1;
    969     if (pValue1->s.Lo != pValue2->s.Lo)
    970         return pValue1->s.Lo > pValue2->s.Lo ? 1 : -1;
    971     return 0;
    972 #else
    973     if (pValue1->DWords.dw3 != pValue2->DWords.dw3)
    974         return pValue1->DWords.dw3 > pValue2->DWords.dw3 ? 1 : -1;
    975     if (pValue1->DWords.dw2 != pValue2->DWords.dw2)
    976         return pValue1->DWords.dw2 > pValue2->DWords.dw2 ? 1 : -1;
    977     if (pValue1->DWords.dw1 != pValue2->DWords.dw1)
    978         return pValue1->DWords.dw1 > pValue2->DWords.dw1 ? 1 : -1;
    979     if (pValue1->DWords.dw0 != pValue2->DWords.dw0)
    980         return pValue1->DWords.dw0 > pValue2->DWords.dw0 ? 1 : -1;
    981     return 0;
    982 #endif
    983 }
    984 
    985 
    986 /**
    987  * Tests if a 128-bit unsigned integer value is smaller than another.
    988  *
    989  * @returns true if the first value is smaller, false if not.
    990  * @param   pValue1             The first value.
    991  * @param   pValue2             The second value.
    992  */
    993 DECLINLINE(bool) RTUInt128IsSmaller(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    994 {
    995 #if ARCH_BITS >= 64
    996     return pValue1->s.Hi < pValue2->s.Hi
    997         || (   pValue1->s.Hi == pValue2->s.Hi
    998             && pValue1->s.Lo  < pValue2->s.Lo);
    999 #else
    1000     return pValue1->DWords.dw3 < pValue2->DWords.dw3
    1001         || (   pValue1->DWords.dw3 == pValue2->DWords.dw3
    1002             && (   pValue1->DWords.dw2  < pValue2->DWords.dw2
    1003                 || (   pValue1->DWords.dw2 == pValue2->DWords.dw2
    1004                     && (   pValue1->DWords.dw1  < pValue2->DWords.dw1
    1005                         || (   pValue1->DWords.dw1 == pValue2->DWords.dw1
    1006                             && pValue1->DWords.dw0  < pValue2->DWords.dw0)))));
    1007 #endif
    1008 }
    1009 
    1010 
    1011 /**
    1012  * Tests if a 128-bit unsigned integer value is larger than another.
    1013  *
    1014  * @returns true if the first value is larger, false if not.
    1015  * @param   pValue1             The first value.
    1016  * @param   pValue2             The second value.
    1017  */
    1018 DECLINLINE(bool) RTUInt128IsLarger(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    1019 {
    1020 #if ARCH_BITS >= 64
    1021     return pValue1->s.Hi > pValue2->s.Hi
    1022         || (   pValue1->s.Hi == pValue2->s.Hi
    1023             && pValue1->s.Lo  > pValue2->s.Lo);
    1024 #else
    1025     return pValue1->DWords.dw3 > pValue2->DWords.dw3
    1026         || (   pValue1->DWords.dw3 == pValue2->DWords.dw3
    1027             && (   pValue1->DWords.dw2  > pValue2->DWords.dw2
    1028                 || (   pValue1->DWords.dw2 == pValue2->DWords.dw2
    1029                     && (   pValue1->DWords.dw1  > pValue2->DWords.dw1
    1030                         || (   pValue1->DWords.dw1 == pValue2->DWords.dw1
    1031                             && pValue1->DWords.dw0  > pValue2->DWords.dw0)))));
    1032 #endif
    1033 }
    1034 
    1035 
    1036 /**
    1037  * Tests if a 128-bit unsigned integer value is larger or equal than another.
    1038  *
    1039  * @returns true if the first value is larger or equal, false if not.
    1040  * @param   pValue1             The first value.
    1041  * @param   pValue2             The second value.
    1042  */
    1043 DECLINLINE(bool) RTUInt128IsLargerOrEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    1044 {
    1045 #if ARCH_BITS >= 64
    1046     return pValue1->s.Hi > pValue2->s.Hi
    1047         || (   pValue1->s.Hi == pValue2->s.Hi
    1048             && pValue1->s.Lo >= pValue2->s.Lo);
    1049 #else
    1050     return pValue1->DWords.dw3 > pValue2->DWords.dw3
    1051         || (   pValue1->DWords.dw3 == pValue2->DWords.dw3
    1052             && (   pValue1->DWords.dw2  > pValue2->DWords.dw2
    1053                 || (   pValue1->DWords.dw2 == pValue2->DWords.dw2
    1054                     && (   pValue1->DWords.dw1  > pValue2->DWords.dw1
    1055                         || (   pValue1->DWords.dw1 == pValue2->DWords.dw1
    1056                             && pValue1->DWords.dw0 >= pValue2->DWords.dw0)))));
    1057 #endif
    1058 }
    1059 
    1060 
    1061 /**
    1062  * Tests if two 128-bit unsigned integer values not equal.
    1063  *
    1064  * @returns true if equal, false if not equal.
    1065  * @param   pValue1             The first value.
    1066  * @param   pValue2             The second value.
    1067  */
    1068 DECLINLINE(bool) RTUInt128IsEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    1069 {
    1070 #if ARCH_BITS >= 64
    1071     return pValue1->s.Hi == pValue2->s.Hi
    1072         && pValue1->s.Lo == pValue2->s.Lo;
    1073 #else
    1074     return pValue1->DWords.dw0 == pValue2->DWords.dw0
    1075         && pValue1->DWords.dw1 == pValue2->DWords.dw1
    1076         && pValue1->DWords.dw2 == pValue2->DWords.dw2
    1077         && pValue1->DWords.dw3 == pValue2->DWords.dw3;
    1078 #endif
    1079 }
    1080 
    1081 
    1082 /**
    1083  * Tests if two 128-bit unsigned integer values are not equal.
    1084  *
    1085  * @returns true if not equal, false if equal.
    1086  * @param   pValue1             The first value.
    1087  * @param   pValue2             The second value.
    1088  */
    1089 DECLINLINE(bool) RTUInt128IsNotEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    1090 {
    1091     return !RTUInt128IsEqual(pValue1, pValue2);
    1092 }
    1093 
    1094 
    1095 /**
    1096  * Sets a bit in a 128-bit unsigned integer type.
    1097  *
    1098  * @returns pValueResult.
    1099  * @param   pValueResult    The input and output value.
    1100  * @param   iBit            The bit to set.
    1101  */
    1102 DECLINLINE(PRTUINT128U) RTUInt128BitSet(PRTUINT128U pValueResult, unsigned iBit)
    1103 {
    1104     if (iBit < 64)
    1105     {
    1106 #if ARCH_BITS >= 64
    1107         pValueResult->s.Lo |= RT_BIT_64(iBit);
    1108 #else
    1109         if (iBit < 32)
    1110             pValueResult->DWords.dw0 |= RT_BIT_32(iBit);
    1111         else
    1112             pValueResult->DWords.dw1 |= RT_BIT_32(iBit - 32);
    1113 #endif
    1114     }
    1115     else if (iBit < 128)
    1116     {
    1117 #if ARCH_BITS >= 64
    1118         pValueResult->s.Hi |= RT_BIT_64(iBit - 64);
    1119 #else
    1120         if (iBit < 96)
    1121             pValueResult->DWords.dw2 |= RT_BIT_32(iBit - 64);
    1122         else
    1123             pValueResult->DWords.dw3 |= RT_BIT_32(iBit - 96);
    1124 #endif
    1125     }
    1126     return pValueResult;
    1127 }
    1128 
    1129 
    1130 /**
    1131  * Sets a bit in a 128-bit unsigned integer type.
    1132  *
    1133  * @returns pValueResult.
    1134  * @param   pValueResult    The input and output value.
    1135  * @param   iBit            The bit to set.
    1136  */
    1137 DECLINLINE(PRTUINT128U) RTUInt128BitClear(PRTUINT128U pValueResult, unsigned iBit)
    1138 {
    1139     if (iBit < 64)
    1140     {
    1141 #if ARCH_BITS >= 64
    1142         pValueResult->s.Lo &= ~RT_BIT_64(iBit);
    1143 #else
    1144         if (iBit < 32)
    1145             pValueResult->DWords.dw0 &= ~RT_BIT_32(iBit);
    1146         else
    1147             pValueResult->DWords.dw1 &= ~RT_BIT_32(iBit - 32);
    1148 #endif
    1149     }
    1150     else if (iBit < 128)
    1151     {
    1152 #if ARCH_BITS >= 64
    1153         pValueResult->s.Hi &= ~RT_BIT_64(iBit - 64);
    1154 #else
    1155         if (iBit < 96)
    1156             pValueResult->DWords.dw2 &= ~RT_BIT_32(iBit - 64);
    1157         else
    1158             pValueResult->DWords.dw3 &= ~RT_BIT_32(iBit - 96);
    1159 #endif
    1160     }
    1161     return pValueResult;
    1162 }
    1163 
    1164 
    1165 /**
    1166  * Tests if a bit in a 128-bit unsigned integer value is set.
    1167  *
    1168  * @returns pValueResult.
    1169  * @param   pValueResult    The input and output value.
    1170  * @param   iBit            The bit to test.
    1171  */
    1172 DECLINLINE(bool) RTUInt128BitTest(PRTUINT128U pValueResult, unsigned iBit)
    1173 {
    1174     bool fRc;
    1175     if (iBit < 64)
    1176     {
    1177 #if ARCH_BITS >= 64
    1178         fRc = RT_BOOL(pValueResult->s.Lo & RT_BIT_64(iBit));
    1179 #else
    1180         if (iBit < 32)
    1181             fRc = RT_BOOL(pValueResult->DWords.dw0 & RT_BIT_32(iBit));
    1182         else
    1183             fRc = RT_BOOL(pValueResult->DWords.dw1 & RT_BIT_32(iBit - 32));
    1184 #endif
    1185     }
    1186     else if (iBit < 128)
    1187     {
    1188 #if ARCH_BITS >= 64
    1189         fRc = RT_BOOL(pValueResult->s.Hi & RT_BIT_64(iBit - 64));
    1190 #else
    1191         if (iBit < 96)
    1192             fRc = RT_BOOL(pValueResult->DWords.dw2 & RT_BIT_32(iBit - 64));
    1193         else
    1194             fRc = RT_BOOL(pValueResult->DWords.dw3 & RT_BIT_32(iBit - 96));
    1195 #endif
    1196     }
    1197     else
    1198         fRc = false;
    1199     return fRc;
    1200 }
    1201 
    1202 
    1203 /**
    1204  * Set a range of bits a 128-bit unsigned integer value.
    1205  *
    1206  * @returns pValueResult.
    1207  * @param   pValueResult    The input and output value.
    1208  * @param   iFirstBit       The first bit to test.
    1209  * @param   cBits           The number of bits to set.
    1210  */
    1211 DECLINLINE(PRTUINT128U) RTUInt128BitSetRange(PRTUINT128U pValueResult, unsigned iFirstBit, unsigned cBits)
    1212 {
    1213     /* bounds check & fix. */
    1214     if (iFirstBit < 128)
    1215     {
    1216         if (iFirstBit + cBits > 128)
    1217             cBits = 128 - iFirstBit;
    1218 
    1219 #if ARCH_BITS >= 64
    1220         if (iFirstBit + cBits < 64)
    1221             pValueResult->s.Lo |= (RT_BIT_64(cBits) - 1) << iFirstBit;
    1222         else if (iFirstBit + cBits < 128 && iFirstBit >= 64)
    1223             pValueResult->s.Hi |= (RT_BIT_64(cBits) - 1) << (iFirstBit - 64);
    1224         else
    1225 #else
    1226         if (iFirstBit + cBits < 32)
    1227             pValueResult->DWords.dw0 |= (RT_BIT_32(cBits) - 1) << iFirstBit;
    1228         else if (iFirstBit + cBits < 64 && iFirstBit >= 32)
    1229             pValueResult->DWords.dw1 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 32);
    1230         else if (iFirstBit + cBits < 96 && iFirstBit >= 64)
    1231             pValueResult->DWords.dw2 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 64);
    1232         else if (iFirstBit + cBits < 128 && iFirstBit >= 96)
    1233             pValueResult->DWords.dw3 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 96);
    1234         else
    1235 #endif
    1236             while (cBits-- > 0)
    1237                 RTUInt128BitSet(pValueResult, iFirstBit++);
    1238     }
    1239     return pValueResult;
    1240 }
    1241 
    1242 
    1243 /**
    1244  * Test if all the bits of a 128-bit unsigned integer value are set.
    1245  *
    1246  * @returns true if they are, false if they aren't.
    1247  * @param   pValue          The input and output value.
    1248  */
    1249 DECLINLINE(bool) RTUInt128BitAreAllSet(PRTUINT128U pValue)
    1250 {
    1251 #if ARCH_BITS >= 64
    1252     return pValue->s.Hi == UINT64_MAX
    1253         && pValue->s.Lo == UINT64_MAX;
    1254 #else
    1255     return pValue->DWords.dw0 == UINT32_MAX
    1256         && pValue->DWords.dw1 == UINT32_MAX
    1257         && pValue->DWords.dw2 == UINT32_MAX
    1258         && pValue->DWords.dw3 == UINT32_MAX;
    1259 #endif
    1260 }
    1261 
    1262 
    1263 /**
    1264  * Test if all the bits of a 128-bit unsigned integer value are clear.
    1265  *
    1266  * @returns true if they are, false if they aren't.
    1267  * @param   pValue          The input and output value.
    1268  */
    1269 DECLINLINE(bool) RTUInt128BitAreAllClear(PRTUINT128U pValue)
    1270 {
    1271 #if ARCH_BITS >= 64
    1272     return pValue->s.Hi == 0
    1273         && pValue->s.Lo == 0;
    1274 #else
    1275     return pValue->DWords.dw0 == 0
    1276         && pValue->DWords.dw1 == 0
    1277         && pValue->DWords.dw2 == 0
    1278         && pValue->DWords.dw3 == 0;
    1279 #endif
    1280 }
    1281 
    1282 
    1283 DECLINLINE(uint32_t) RTUInt128BitCount(PCRTUINT128U pValue)
    1284 {
    1285     uint32_t cBits;
    1286     if (pValue->s.Hi != 0)
    1287     {
    1288         if (pValue->DWords.dw3)
    1289             cBits = 96 + ASMBitLastSetU32(pValue->DWords.dw3);
    1290         else
    1291             cBits = 64 + ASMBitLastSetU32(pValue->DWords.dw2);
    1292     }
    1293     else
    1294     {
    1295         if (pValue->DWords.dw1)
    1296             cBits = 32 + ASMBitLastSetU32(pValue->DWords.dw1);
    1297         else
    1298             cBits =  0 + ASMBitLastSetU32(pValue->DWords.dw0);
    1299     }
    1300     return cBits;
    1301 }
    1302 
    1303 
    1304 /**
    1305  * Divides a 128-bit unsigned integer value by another, returning both quotient
     219RTDECL(PRTUINT256U) RTUInt256MulByU64(PRTUINT256U pResult, PCRTUINT256U pValue1, uint64_t uValue2);
     220
     221/**
     222 * Divides a 256-bit unsigned integer value by another, returning both quotient
    1306223 * and remainder.
    1307224 *
     
    1312229 * @param   pValue2             The divisor value.
    1313230 */
    1314 DECLINLINE(PRTUINT128U) RTUInt128DivRem(PRTUINT128U pQuotient, PRTUINT128U pRemainder, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
    1315 {
    1316     int iDiff;
    1317 
    1318     /*
    1319      * Sort out all the special cases first.
    1320      */
    1321     /* Divide by zero or 1? */
    1322     if (!pValue2->s.Hi)
    1323     {
    1324         if (!pValue2->s.Lo)
    1325             return NULL;
    1326 
    1327         if (pValue2->s.Lo == 1)
     231RTDECL(PRTUINT256U) RTUInt256DivRem(PRTUINT256U pQuotient, PRTUINT256U pRemainder, PCRTUINT256U pValue1, PCRTUINT256U pValue2);
     232
     233/**
     234 * Divides a 256-bit unsigned integer value by another.
     235 *
     236 * @returns pResult
     237 * @param   pResult             The result variable.
     238 * @param   pValue1             The dividend value.
     239 * @param   pValue2             The divisor value.
     240 */
     241DECLINLINE(PRTUINT256U) RTUInt256Div(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
     242{
     243    RTUINT256U Ignored;
     244    return RTUInt256DivRem(pResult, &Ignored, pValue1, pValue2);
     245}
     246
     247
     248/**
     249 * Divides a 256-bit unsigned integer value by another, returning the remainder.
     250 *
     251 * @returns pResult
     252 * @param   pResult             The result variable (remainder).
     253 * @param   pValue1             The dividend value.
     254 * @param   pValue2             The divisor value.
     255 */
     256DECLINLINE(PRTUINT256U) RTUInt256Mod(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
     257{
     258    RTUINT256U Ignored;
     259    RTUInt256DivRem(&Ignored, pResult, pValue1, pValue2);
     260    return pResult;
     261}
     262
     263
     264/**
     265 * Bitwise AND of two 256-bit unsigned integer values.
     266 *
     267 * @returns pResult
     268 * @param   pResult             The result variable.
     269 * @param   pValue1             The first value.
     270 * @param   pValue2             The second value.
     271 */
     272DECLINLINE(PRTUINT256U) RTUInt256And(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
     273{
     274    pResult->QWords.qw0 = pValue1->QWords.qw0 & pValue2->QWords.qw0;
     275    pResult->QWords.qw1 = pValue1->QWords.qw1 & pValue2->QWords.qw1;
     276    pResult->QWords.qw2 = pValue1->QWords.qw2 & pValue2->QWords.qw2;
     277    pResult->QWords.qw3 = pValue1->QWords.qw3 & pValue2->QWords.qw3;
     278    return pResult;
     279}
     280
     281
     282/**
     283 * Bitwise OR of two 256-bit unsigned integer values.
     284 *
     285 * @returns pResult
     286 * @param   pResult             The result variable.
     287 * @param   pValue1             The first value.
     288 * @param   pValue2             The second value.
     289 */
     290DECLINLINE(PRTUINT256U) RTUInt256Or( PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
     291{
     292    pResult->QWords.qw0 = pValue1->QWords.qw0 | pValue2->QWords.qw0;
     293    pResult->QWords.qw1 = pValue1->QWords.qw1 | pValue2->QWords.qw1;
     294    pResult->QWords.qw2 = pValue1->QWords.qw2 | pValue2->QWords.qw2;
     295    pResult->QWords.qw3 = pValue1->QWords.qw3 | pValue2->QWords.qw3;
     296    return pResult;
     297}
     298
     299
     300/**
     301 * Bitwise XOR of two 256-bit unsigned integer values.
     302 *
     303 * @returns pResult
     304 * @param   pResult             The result variable.
     305 * @param   pValue1             The first value.
     306 * @param   pValue2             The second value.
     307 */
     308DECLINLINE(PRTUINT256U) RTUInt256Xor(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
     309{
     310    pResult->QWords.qw0 = pValue1->QWords.qw0 ^ pValue2->QWords.qw0;
     311    pResult->QWords.qw1 = pValue1->QWords.qw1 ^ pValue2->QWords.qw1;
     312    pResult->QWords.qw2 = pValue1->QWords.qw2 ^ pValue2->QWords.qw2;
     313    pResult->QWords.qw3 = pValue1->QWords.qw3 ^ pValue2->QWords.qw3;
     314    return pResult;
     315}
     316
     317
     318/**
     319 * Shifts a 256-bit unsigned integer value @a cBits to the left.
     320 *
     321 * @returns pResult
     322 * @param   pResult             The result variable.
     323 * @param   pValue              The value to shift.
     324 * @param   cBits               The number of bits to shift it.  This is masked
     325 *                              by 255 before shifting.
     326 */
     327DECLINLINE(PRTUINT256U) RTUInt256ShiftLeft(PRTUINT256U pResult, PCRTUINT256U pValue, unsigned cBits)
     328{
     329    /* This is a bit bulky & impractical since we cannot access the data using
     330       an array because it is organized according to host endianness. Sigh. */
     331    cBits &= 255;
     332    if (!(cBits & 0x3f))
     333    {
     334        if (cBits == 0)
     335            *pResult = *pValue;
     336        else
    1328337        {
    1329             RTUInt128SetZero(pRemainder);
    1330             *pQuotient = *pValue1;
    1331             return pQuotient;
    1332         }
    1333         /** @todo RTUint128DivModBy64 */
    1334     }
    1335 
    1336     /* Dividend is smaller? */
    1337     iDiff = RTUInt128Compare(pValue1, pValue2);
    1338     if (iDiff < 0)
    1339     {
    1340         *pRemainder = *pValue1;
    1341         RTUInt128SetZero(pQuotient);
    1342     }
    1343 
    1344     /* The values are equal? */
    1345     else if (iDiff == 0)
    1346     {
    1347         RTUInt128SetZero(pRemainder);
    1348         RTUInt128AssignU64(pQuotient, 1);
    1349     }
    1350     else
    1351     {
    1352         /*
    1353          * Prepare.
    1354          */
    1355         uint32_t   iBitAdder = RTUInt128BitCount(pValue1) - RTUInt128BitCount(pValue2);
    1356         RTUINT128U NormDivisor = *pValue2;
    1357         if (iBitAdder)
    1358         {
    1359             RTUInt128ShiftLeft(&NormDivisor, pValue2, iBitAdder);
    1360             if (RTUInt128IsLarger(&NormDivisor, pValue1))
     338            pResult->QWords.qw0 = 0;
     339            if (cBits == 64)
    1361340            {
    1362                 RTUInt128AssignShiftRight(&NormDivisor, 1);
    1363                 iBitAdder--;
     341                pResult->QWords.qw1 = pValue->QWords.qw0;
     342                pResult->QWords.qw2 = pValue->QWords.qw1;
     343                pResult->QWords.qw3 = pValue->QWords.qw2;
     344            }
     345            else
     346            {
     347                pResult->QWords.qw1 = 0;
     348                if (cBits == 128)
     349                {
     350                    pResult->QWords.qw2 = pValue->QWords.qw0;
     351                    pResult->QWords.qw3 = pValue->QWords.qw1;
     352                }
     353                else
     354                {
     355                    pResult->QWords.qw2 = 0;
     356                    pResult->QWords.qw3 = pValue->QWords.qw0;
     357                }
    1364358            }
    1365359        }
     360    }
     361    else if (cBits < 128)
     362    {
     363        if (cBits < 64)
     364        {
     365            pResult->QWords.qw0  = pValue->QWords.qw0 << cBits;
     366            pResult->QWords.qw1  = pValue->QWords.qw0 >> (64 - cBits);
     367            pResult->QWords.qw1 |= pValue->QWords.qw1 << cBits;
     368            pResult->QWords.qw2  = pValue->QWords.qw1 >> (64 - cBits);
     369            pResult->QWords.qw2 |= pValue->QWords.qw2 << cBits;
     370            pResult->QWords.qw3  = pValue->QWords.qw2 >> (64 - cBits);
     371            pResult->QWords.qw3 |= pValue->QWords.qw3 << cBits;
     372        }
    1366373        else
    1367             NormDivisor = *pValue2;
    1368 
    1369         RTUInt128SetZero(pQuotient);
    1370         *pRemainder = *pValue1;
    1371 
    1372         /*
    1373          * Do the division.
    1374          */
    1375         if (RTUInt128IsLargerOrEqual(pRemainder, pValue2))
    1376374        {
    1377             for (;;)
     375            cBits -= 64;
     376            pResult->QWords.qw0  = 0;
     377            pResult->QWords.qw1  = pValue->QWords.qw0 << cBits;
     378            pResult->QWords.qw2  = pValue->QWords.qw0 >> (64 - cBits);
     379            pResult->QWords.qw2 |= pValue->QWords.qw1 << cBits;
     380            pResult->QWords.qw3  = pValue->QWords.qw1 >> (64 - cBits);
     381            pResult->QWords.qw3 |= pValue->QWords.qw2 << cBits;
     382        }
     383    }
     384    else
     385    {
     386        if (cBits < 192)
     387        {
     388            cBits -= 128;
     389            pResult->QWords.qw0  = 0;
     390            pResult->QWords.qw1  = 0;
     391            pResult->QWords.qw2  = pValue->QWords.qw0 << cBits;
     392            pResult->QWords.qw3  = pValue->QWords.qw0 >> (64 - cBits);
     393            pResult->QWords.qw3 |= pValue->QWords.qw1 << cBits;
     394        }
     395        else
     396        {
     397            cBits -= 192;
     398            pResult->QWords.qw0  = 0;
     399            pResult->QWords.qw1  = 0;
     400            pResult->QWords.qw2  = 0;
     401            pResult->QWords.qw3  = pValue->QWords.qw0 << cBits;
     402        }
     403    }
     404    return pResult;
     405}
     406
     407
     408/**
     409 * Shifts a 256-bit unsigned integer value @a cBits to the right.
     410 *
     411 * @returns pResult
     412 * @param   pResult             The result variable.
     413 * @param   pValue              The value to shift.
     414 * @param   cBits               The number of bits to shift it.  This is masked
     415 *                              by 255 before shifting.
     416 */
     417DECLINLINE(PRTUINT256U) RTUInt256ShiftRight(PRTUINT256U pResult, PCRTUINT256U pValue, unsigned cBits)
     418{
     419    /* This is a bit bulky & impractical since we cannot access the data using
     420       an array because it is organized according to host endianness. Sigh. */
     421    cBits &= 255;
     422    if (!(cBits & 0x3f))
     423    {
     424        if (cBits == 0)
     425            *pResult = *pValue;
     426        else
     427        {
     428            if (cBits == 64)
    1378429            {
    1379                 if (RTUInt128IsLargerOrEqual(pRemainder, &NormDivisor))
     430                pResult->QWords.qw0 = pValue->QWords.qw1;
     431                pResult->QWords.qw1 = pValue->QWords.qw2;
     432                pResult->QWords.qw2 = pValue->QWords.qw3;
     433            }
     434            else
     435            {
     436                if (cBits == 128)
    1380437                {
    1381                     RTUInt128AssignSub(pRemainder, &NormDivisor);
    1382                     RTUInt128AssignOrBit(pQuotient, iBitAdder);
     438                    pResult->QWords.qw0 = pValue->QWords.qw2;
     439                    pResult->QWords.qw1 = pValue->QWords.qw3;
    1383440                }
    1384                 if (RTUInt128IsSmaller(pRemainder, pValue2))
    1385                     break;
    1386                 RTUInt128AssignShiftRight(&NormDivisor, 1);
    1387                 iBitAdder--;
     441                else
     442                {
     443                    pResult->QWords.qw0 = pValue->QWords.qw3;
     444                    pResult->QWords.qw1 = 0;
     445                }
     446                pResult->QWords.qw2 = 0;
    1388447            }
     448            pResult->QWords.qw3 = 0;
    1389449        }
    1390450    }
    1391     return pQuotient;
     451    else if (cBits < 128)
     452    {
     453        if (cBits < 64)
     454        {
     455            pResult->QWords.qw0  = pValue->QWords.qw0 >> cBits;
     456            pResult->QWords.qw0 |= pValue->QWords.qw1 << (64 - cBits);
     457            pResult->QWords.qw1  = pValue->QWords.qw1 >> cBits;
     458            pResult->QWords.qw1 |= pValue->QWords.qw2 << (64 - cBits);
     459            pResult->QWords.qw2  = pValue->QWords.qw2 >> cBits;
     460            pResult->QWords.qw2 |= pValue->QWords.qw3 << (64 - cBits);
     461            pResult->QWords.qw3  = pValue->QWords.qw3 >> cBits;
     462        }
     463        else
     464        {
     465            cBits -= 64;
     466            pResult->QWords.qw0  = pValue->QWords.qw1 >> cBits;
     467            pResult->QWords.qw0 |= pValue->QWords.qw2 << (64 - cBits);
     468            pResult->QWords.qw1  = pValue->QWords.qw2 >> cBits;
     469            pResult->QWords.qw1 |= pValue->QWords.qw3 << (64 - cBits);
     470            pResult->QWords.qw2  = pValue->QWords.qw3 >> cBits;
     471            pResult->QWords.qw3  = 0;
     472        }
     473    }
     474    else
     475    {
     476        if (cBits < 192)
     477        {
     478            cBits -= 128;
     479            pResult->QWords.qw0  = pValue->QWords.qw2 >> cBits;
     480            pResult->QWords.qw0 |= pValue->QWords.qw3 << (64 - cBits);
     481            pResult->QWords.qw1  = pValue->QWords.qw3 >> cBits;
     482            pResult->QWords.qw2  = 0;
     483            pResult->QWords.qw3  = 0;
     484        }
     485        else
     486        {
     487            cBits -= 192;
     488            pResult->QWords.qw0  = pValue->QWords.qw3 >> cBits;
     489            pResult->QWords.qw1  = 0;
     490            pResult->QWords.qw2  = 0;
     491            pResult->QWords.qw3  = 0;
     492        }
     493    }
     494    return pResult;
     495}
     496
     497
     498/**
     499 * Boolean not (result 0 or 1).
     500 *
     501 * @returns pResult.
     502 * @param   pResult             The result variable.
     503 * @param   pValue              The value.
     504 */
     505DECLINLINE(PRTUINT256U) RTUInt256BooleanNot(PRTUINT256U pResult, PCRTUINT256U pValue)
     506{
     507    pResult->QWords.qw0 = RTUInt256IsZero(pValue);
     508    pResult->QWords.qw1 = 0;
     509    pResult->QWords.qw2 = 0;
     510    pResult->QWords.qw3 = 0;
     511    return pResult;
     512}
     513
     514
     515/**
     516 * Bitwise not (flips each bit of the 256 bits).
     517 *
     518 * @returns pResult.
     519 * @param   pResult             The result variable.
     520 * @param   pValue              The value.
     521 */
     522DECLINLINE(PRTUINT256U) RTUInt256BitwiseNot(PRTUINT256U pResult, PCRTUINT256U pValue)
     523{
     524    pResult->QWords.qw0 = ~pValue->QWords.qw0;
     525    pResult->QWords.qw1 = ~pValue->QWords.qw1;
     526    pResult->QWords.qw2 = ~pValue->QWords.qw2;
     527    pResult->QWords.qw3 = ~pValue->QWords.qw3;
     528    return pResult;
     529}
     530
     531
     532/**
     533 * Assigns one 256-bit unsigned integer value to another.
     534 *
     535 * @returns pResult
     536 * @param   pResult             The result variable.
     537 * @param   pValue              The value to assign.
     538 */
     539DECLINLINE(PRTUINT256U) RTUInt256Assign(PRTUINT256U pResult, PCRTUINT256U pValue)
     540{
     541    pResult->QWords.qw0 = pValue->QWords.qw0;
     542    pResult->QWords.qw1 = pValue->QWords.qw1;
     543    pResult->QWords.qw2 = pValue->QWords.qw2;
     544    pResult->QWords.qw3 = pValue->QWords.qw3;
     545    return pResult;
     546}
     547
     548
     549/**
     550 * Assigns a boolean value to 256-bit unsigned integer.
     551 *
     552 * @returns pValueResult
     553 * @param   pValueResult        The result variable.
     554 * @param   fValue              The boolean value.
     555 */
     556DECLINLINE(PRTUINT256U) RTUInt256AssignBoolean(PRTUINT256U pValueResult, bool fValue)
     557{
     558    pValueResult->QWords.qw0 = fValue;
     559    pValueResult->QWords.qw1 = 0;
     560    pValueResult->QWords.qw2 = 0;
     561    pValueResult->QWords.qw3 = 0;
     562    return pValueResult;
     563}
     564
     565
     566/**
     567 * Assigns a 8-bit unsigned integer value to 256-bit unsigned integer.
     568 *
     569 * @returns pValueResult
     570 * @param   pValueResult        The result variable.
     571 * @param   u8Value             The 8-bit unsigned integer value.
     572 */
     573DECLINLINE(PRTUINT256U) RTUInt256AssignU8(PRTUINT256U pValueResult, uint8_t u8Value)
     574{
     575    pValueResult->QWords.qw0 = u8Value;
     576    pValueResult->QWords.qw1 = 0;
     577    pValueResult->QWords.qw2 = 0;
     578    pValueResult->QWords.qw3 = 0;
     579    return pValueResult;
     580}
     581
     582
     583/**
     584 * Assigns a 16-bit unsigned integer value to 256-bit unsigned integer.
     585 *
     586 * @returns pValueResult
     587 * @param   pValueResult        The result variable.
     588 * @param   u16Value            The 16-bit unsigned integer value.
     589 */
     590DECLINLINE(PRTUINT256U) RTUInt256AssignU16(PRTUINT256U pValueResult, uint16_t u16Value)
     591{
     592    pValueResult->QWords.qw0 = u16Value;
     593    pValueResult->QWords.qw1 = 0;
     594    pValueResult->QWords.qw2 = 0;
     595    pValueResult->QWords.qw3 = 0;
     596    return pValueResult;
     597}
     598
     599
     600/**
     601 * Assigns a 32-bit unsigned integer value to 256-bit unsigned integer.
     602 *
     603 * @returns pValueResult
     604 * @param   pValueResult        The result variable.
     605 * @param   u32Value            The 32-bit unsigned integer value.
     606 */
     607DECLINLINE(PRTUINT256U) RTUInt256AssignU32(PRTUINT256U pValueResult, uint32_t u32Value)
     608{
     609    pValueResult->QWords.qw0 = u32Value;
     610    pValueResult->QWords.qw1 = 0;
     611    pValueResult->QWords.qw2 = 0;
     612    pValueResult->QWords.qw3 = 0;
     613    return pValueResult;
     614}
     615
     616
     617/**
     618 * Assigns a 64-bit unsigned integer value to 256-bit unsigned integer.
     619 *
     620 * @returns pValueResult
     621 * @param   pValueResult        The result variable.
     622 * @param   u64Value            The 64-bit unsigned integer value.
     623 */
     624DECLINLINE(PRTUINT256U) RTUInt256AssignU64(PRTUINT256U pValueResult, uint64_t u64Value)
     625{
     626    pValueResult->QWords.qw0 = u64Value;
     627    pValueResult->QWords.qw1 = 0;
     628    pValueResult->QWords.qw2 = 0;
     629    pValueResult->QWords.qw3 = 0;
     630    return pValueResult;
     631}
     632
     633
     634/**
     635 * Adds two 256-bit unsigned integer values, storing the result in the first.
     636 *
     637 * @returns pValue1Result.
     638 * @param   pValue1Result   The first value and result.
     639 * @param   pValue2         The second value.
     640 */
     641DECLINLINE(PRTUINT256U) RTUInt256AssignAdd(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
     642{
     643    RTUINT256U const uTmpValue1 = *pValue1Result; /* lazy bird */
     644    return RTUInt256Add(pValue1Result, &uTmpValue1, pValue2);
     645}
     646
     647
     648/**
     649 * Adds a 64-bit unsigned integer value to a 256-bit unsigned integer values,
     650 * storing the result in the 256-bit one.
     651 *
     652 * @returns pValue1Result.
     653 * @param   pValue1Result   The first value and result.
     654 * @param   uValue2         The second value, 64-bit.
     655 */
     656DECLINLINE(PRTUINT256U) RTUInt256AssignAddU64(PRTUINT256U pValue1Result, uint64_t uValue2)
     657{
     658    RTUINT256U const uTmpValue1 = *pValue1Result; /* lazy bird */
     659    return RTUInt256AddU64(pValue1Result, &uTmpValue1, uValue2);
     660}
     661
     662
     663/**
     664 * Subtracts two 256-bit unsigned integer values, storing the result in the
     665 * first.
     666 *
     667 * @returns pValue1Result.
     668 * @param   pValue1Result   The minuend value and result.
     669 * @param   pValue2         The subtrahend value.
     670 */
     671DECLINLINE(PRTUINT256U) RTUInt256AssignSub(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
     672{
     673    RTUINT256U const uTmpValue1 = *pValue1Result; /* lazy bird */
     674    return RTUInt256Sub(pValue1Result, &uTmpValue1, pValue2);
     675}
     676
     677
     678#if 0
     679/**
     680 * Negates a 256 number, storing the result in the input.
     681 *
     682 * @returns pValueResult.
     683 * @param   pValueResult    The value to negate.
     684 */
     685DECLINLINE(PRTUINT256U) RTUInt256AssignNeg(PRTUINT256U pValueResult)
     686{
     687    /* result = 0 - value */
     688    if (pValueResult->s.Lo != 0)
     689    {
     690        pValueResult->s.Lo = UINT64_C(0) - pValueResult->s.Lo;
     691        pValueResult->s.Hi = UINT64_MAX  - pValueResult->s.Hi;
     692    }
     693    else
     694        pValueResult->s.Hi = UINT64_C(0) - pValueResult->s.Hi;
     695    return pValueResult;
     696}
     697#endif
     698
     699
     700/**
     701 * Multiplies two 256-bit unsigned integer values, storing the result in the
     702 * first.
     703 *
     704 * @returns pValue1Result.
     705 * @param   pValue1Result   The first value and result.
     706 * @param   pValue2         The second value.
     707 */
     708DECLINLINE(PRTUINT256U) RTUInt256AssignMul(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
     709{
     710    RTUINT256U Result;
     711    RTUInt256Mul(&Result, pValue1Result, pValue2);
     712    *pValue1Result = Result;
     713    return pValue1Result;
     714}
     715
     716
     717/**
     718 * Divides a 256-bit unsigned integer value by another, storing the result in
     719 * the first.
     720 *
     721 * @returns pValue1Result.
     722 * @param   pValue1Result   The dividend value and result.
     723 * @param   pValue2         The divisor value.
     724 */
     725DECLINLINE(PRTUINT256U) RTUInt256AssignDiv(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
     726{
     727    RTUINT256U Result;
     728    RTUINT256U Ignored;
     729    RTUInt256DivRem(&Result, &Ignored, pValue1Result, pValue2);
     730    *pValue1Result = Result;
     731    return pValue1Result;
     732}
     733
     734
     735/**
     736 * Divides a 256-bit unsigned integer value by another, storing the remainder in
     737 * the first.
     738 *
     739 * @returns pValue1Result.
     740 * @param   pValue1Result   The dividend value and result (remainder).
     741 * @param   pValue2         The divisor value.
     742 */
     743DECLINLINE(PRTUINT256U) RTUInt256AssignMod(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
     744{
     745    RTUINT256U Ignored;
     746    RTUINT256U Result;
     747    RTUInt256DivRem(&Ignored, &Result, pValue1Result, pValue2);
     748    *pValue1Result = Result;
     749    return pValue1Result;
     750}
     751
     752
     753/**
     754 * Performs a bitwise AND of two 256-bit unsigned integer values and assigned
     755 * the result to the first one.
     756 *
     757 * @returns pValue1Result.
     758 * @param   pValue1Result   The first value and result.
     759 * @param   pValue2         The second value.
     760 */
     761DECLINLINE(PRTUINT256U) RTUInt256AssignAnd(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
     762{
     763    pValue1Result->QWords.qw0 &= pValue2->QWords.qw0;
     764    pValue1Result->QWords.qw1 &= pValue2->QWords.qw1;
     765    pValue1Result->QWords.qw2 &= pValue2->QWords.qw2;
     766    pValue1Result->QWords.qw3 &= pValue2->QWords.qw3;
     767    return pValue1Result;
     768}
     769
     770
     771#if 0
     772/**
     773 * Performs a bitwise AND of a 256-bit unsigned integer value and a mask made
     774 * up of the first N bits, assigning the result to the the 256-bit value.
     775 *
     776 * @returns pValueResult.
     777 * @param   pValueResult    The value and result.
     778 * @param   cBits           The number of bits to AND (counting from the first
     779 *                          bit).
     780 */
     781DECLINLINE(PRTUINT256U) RTUInt256AssignAndNFirstBits(PRTUINT256U pValueResult, unsigned cBits)
     782{
     783    if (cBits <= 64)
     784    {
     785        if (cBits != 64)
     786            pValueResult->s.Lo &= (RT_BIT_64(cBits) - 1);
     787        pValueResult->s.Hi = 0;
     788    }
     789    else if (cBits < 256)
     790        pValueResult->s.Hi &= (RT_BIT_64(cBits - 64) - 1);
     791/** @todo \#if ARCH_BITS >= 64 */
     792    return pValueResult;
     793}
     794#endif
     795
     796
     797/**
     798 * Performs a bitwise OR of two 256-bit unsigned integer values and assigned
     799 * the result to the first one.
     800 *
     801 * @returns pValue1Result.
     802 * @param   pValue1Result   The first value and result.
     803 * @param   pValue2         The second value.
     804 */
     805DECLINLINE(PRTUINT256U) RTUInt256AssignOr(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
     806{
     807    pValue1Result->QWords.qw0 |= pValue2->QWords.qw0;
     808    pValue1Result->QWords.qw1 |= pValue2->QWords.qw1;
     809    pValue1Result->QWords.qw2 |= pValue2->QWords.qw2;
     810    pValue1Result->QWords.qw3 |= pValue2->QWords.qw3;
     811    return pValue1Result;
     812}
     813
     814
     815DECLINLINE(PRTUINT256U) RTUInt256BitSet(PRTUINT256U pValueResult, unsigned iBit);
     816
     817/**
     818 * ORs in a bit and assign the result to the input value.
     819 *
     820 * @returns pValue1Result.
     821 * @param   pValue1Result   The first value and result.
     822 * @param   iBit            The bit to set (0 based).
     823 */
     824DECLINLINE(PRTUINT256U) RTUInt256AssignOrBit(PRTUINT256U pValue1Result, uint32_t iBit)
     825{
     826    return RTUInt256BitSet(pValue1Result, (unsigned)iBit);
     827}
     828
     829
     830/**
     831 * Performs a bitwise XOR of two 256-bit unsigned integer values and assigned
     832 * the result to the first one.
     833 *
     834 * @returns pValue1Result.
     835 * @param   pValue1Result   The first value and result.
     836 * @param   pValue2         The second value.
     837 */
     838DECLINLINE(PRTUINT256U) RTUInt256AssignXor(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
     839{
     840    pValue1Result->QWords.qw0 ^= pValue2->QWords.qw0;
     841    pValue1Result->QWords.qw1 ^= pValue2->QWords.qw1;
     842    pValue1Result->QWords.qw2 ^= pValue2->QWords.qw2;
     843    pValue1Result->QWords.qw3 ^= pValue2->QWords.qw3;
     844    return pValue1Result;
     845}
     846
     847
     848/**
     849 * Performs a bitwise left shift on a 256-bit unsigned integer value, assigning
     850 * the result to it.
     851 *
     852 * @returns pValueResult.
     853 * @param   pValueResult    The first value and result.
     854 * @param   cBits           The number of bits to shift - signed.  Negative
     855 *                          values are translated to right shifts.  If the
     856 *                          absolute value is 256 or higher, the value is set to
     857 *                          zero.
     858 *
     859 * @note    This works differently from RTUInt256ShiftLeft and
     860 *          RTUInt256ShiftRight in that the shift count is signed and not masked
     861 *          by 255.
     862 */
     863DECLINLINE(PRTUINT256U) RTUInt256AssignShiftLeft(PRTUINT256U pValueResult, int cBits)
     864{
     865    if (cBits == 0)
     866        return pValueResult;
     867    if (cBits > 0)
     868    {
     869        /* (left shift) */
     870        if (cBits < 256)
     871        {
     872            RTUINT256U const InVal = *pValueResult;
     873            return RTUInt256ShiftLeft(pValueResult, &InVal, cBits);
     874        }
     875    }
     876    else if (cBits > -256)
     877    {
     878        /* (right shift) */
     879        cBits = -cBits;
     880        RTUINT256U const InVal = *pValueResult;
     881        return RTUInt256ShiftRight(pValueResult, &InVal, cBits);
     882    }
     883    return RTUInt256SetZero(pValueResult);
     884}
     885
     886
     887/**
     888 * Performs a bitwise left shift on a 256-bit unsigned integer value, assigning
     889 * the result to it.
     890 *
     891 * @returns pValueResult.
     892 * @param   pValueResult    The first value and result.
     893 * @param   cBits           The number of bits to shift - signed.  Negative
     894 *                          values are translated to left shifts.  If the
     895 *                          absolute value is 256 or higher, the value is set to
     896 *                          zero.
     897 *
     898 * @note    This works differently from RTUInt256ShiftRight and
     899 *          RTUInt256ShiftLeft in that the shift count is signed and not masked
     900 *          by 255.
     901 */
     902DECLINLINE(PRTUINT256U) RTUInt256AssignShiftRight(PRTUINT256U pValueResult, int cBits)
     903{
     904    if (cBits == 0)
     905        return pValueResult;
     906    if (cBits > 0)
     907    {
     908        /* (right shift) */
     909        if (cBits < 256)
     910        {
     911            RTUINT256U const InVal = *pValueResult;
     912            return RTUInt256ShiftRight(pValueResult, &InVal, cBits);
     913        }
     914    }
     915    else if (cBits > -256)
     916    {
     917        /* (left shift) */
     918        cBits = -cBits;
     919        RTUINT256U const InVal = *pValueResult;
     920        return RTUInt256ShiftLeft(pValueResult, &InVal, cBits);
     921    }
     922    return RTUInt256SetZero(pValueResult);
     923}
     924
     925
     926/**
     927 * Performs a bitwise NOT on a 256-bit unsigned integer value, assigning the
     928 * result to it.
     929 *
     930 * @returns pValueResult
     931 * @param   pValueResult    The value and result.
     932 */
     933DECLINLINE(PRTUINT256U) RTUInt256AssignBitwiseNot(PRTUINT256U pValueResult)
     934{
     935    pValueResult->QWords.qw0 = ~pValueResult->QWords.qw0;
     936    pValueResult->QWords.qw1 = ~pValueResult->QWords.qw1;
     937    pValueResult->QWords.qw2 = ~pValueResult->QWords.qw2;
     938    pValueResult->QWords.qw3 = ~pValueResult->QWords.qw3;
     939    return pValueResult;
     940}
     941
     942
     943/**
     944 * Performs a boolean NOT on a 256-bit unsigned integer value, assigning the
     945 * result to it.
     946 *
     947 * @returns pValueResult
     948 * @param   pValueResult    The value and result.
     949 */
     950DECLINLINE(PRTUINT256U) RTUInt256AssignBooleanNot(PRTUINT256U pValueResult)
     951{
     952    return RTUInt256AssignBoolean(pValueResult, RTUInt256IsZero(pValueResult));
     953}
     954
     955
     956/**
     957 * Compares two 256-bit unsigned integer values.
     958 *
     959 * @retval  0 if equal.
     960 * @retval  -1 if the first value is smaller than the second.
     961 * @retval  1  if the first value is larger than the second.
     962 *
     963 * @param   pValue1             The first value.
     964 * @param   pValue2             The second value.
     965 */
     966DECLINLINE(int) RTUInt256Compare(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
     967{
     968    if (pValue1->QWords.qw3 != pValue2->QWords.qw3)
     969        return pValue1->QWords.qw3 > pValue2->QWords.qw3 ? 1 : -1;
     970    if (pValue1->QWords.qw2 != pValue2->QWords.qw2)
     971        return pValue1->QWords.qw2 > pValue2->QWords.qw2 ? 1 : -1;
     972    if (pValue1->QWords.qw1 != pValue2->QWords.qw1)
     973        return pValue1->QWords.qw1 > pValue2->QWords.qw1 ? 1 : -1;
     974    if (pValue1->QWords.qw0 != pValue2->QWords.qw0)
     975        return pValue1->QWords.qw3 > pValue2->QWords.qw3 ? 1 : -1;
     976    return 0;
     977}
     978
     979
     980/**
     981 * Tests if a 256-bit unsigned integer value is smaller than another.
     982 *
     983 * @returns true if the first value is smaller, false if not.
     984 * @param   pValue1             The first value.
     985 * @param   pValue2             The second value.
     986 */
     987DECLINLINE(bool) RTUInt256IsSmaller(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
     988{
     989    return pValue1->QWords.qw3 < pValue2->QWords.qw3
     990        || (   pValue1->QWords.qw3 == pValue2->QWords.qw3
     991            && (   pValue1->QWords.qw2  < pValue2->QWords.qw2
     992                || (   pValue1->QWords.qw2 == pValue2->QWords.qw2
     993                    && (   pValue1->QWords.qw1  < pValue2->QWords.qw1
     994                        || (   pValue1->QWords.qw1 == pValue2->QWords.qw1
     995                            && pValue1->QWords.qw0  < pValue2->QWords.qw0)))));
     996}
     997
     998
     999/**
     1000 * Tests if a 256-bit unsigned integer value is larger than another.
     1001 *
     1002 * @returns true if the first value is larger, false if not.
     1003 * @param   pValue1             The first value.
     1004 * @param   pValue2             The second value.
     1005 */
     1006DECLINLINE(bool) RTUInt256IsLarger(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
     1007{
     1008    return pValue1->QWords.qw3 > pValue2->QWords.qw3
     1009        || (   pValue1->QWords.qw3 == pValue2->QWords.qw3
     1010            && (   pValue1->QWords.qw2  > pValue2->QWords.qw2
     1011                || (   pValue1->QWords.qw2 == pValue2->QWords.qw2
     1012                    && (   pValue1->QWords.qw1  > pValue2->QWords.qw1
     1013                        || (   pValue1->QWords.qw1 == pValue2->QWords.qw1
     1014                            && pValue1->QWords.qw0  > pValue2->QWords.qw0)))));
     1015}
     1016
     1017
     1018/**
     1019 * Tests if a 256-bit unsigned integer value is larger or equal than another.
     1020 *
     1021 * @returns true if the first value is larger or equal, false if not.
     1022 * @param   pValue1             The first value.
     1023 * @param   pValue2             The second value.
     1024 */
     1025DECLINLINE(bool) RTUInt256IsLargerOrEqual(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
     1026{
     1027    return pValue1->QWords.qw3 > pValue2->QWords.qw3
     1028        || (   pValue1->QWords.qw3 == pValue2->QWords.qw3
     1029            && (   pValue1->QWords.qw2  > pValue2->QWords.qw2
     1030                || (   pValue1->QWords.qw2 == pValue2->QWords.qw2
     1031                    && (   pValue1->QWords.qw1  > pValue2->QWords.qw1
     1032                        || (   pValue1->QWords.qw1 == pValue2->QWords.qw1
     1033                            && pValue1->QWords.qw0 >= pValue2->DWords.dw0)))));
     1034}
     1035
     1036
     1037/**
     1038 * Tests if two 256-bit unsigned integer values not equal.
     1039 *
     1040 * @returns true if equal, false if not equal.
     1041 * @param   pValue1             The first value.
     1042 * @param   pValue2             The second value.
     1043 */
     1044DECLINLINE(bool) RTUInt256IsEqual(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
     1045{
     1046    return pValue1->QWords.qw0 == pValue2->QWords.qw0
     1047        && pValue1->QWords.qw1 == pValue2->QWords.qw1
     1048        && pValue1->QWords.qw2 == pValue2->QWords.qw2
     1049        && pValue1->QWords.qw3 == pValue2->QWords.qw3;
     1050}
     1051
     1052
     1053/**
     1054 * Tests if two 256-bit unsigned integer values are not equal.
     1055 *
     1056 * @returns true if not equal, false if equal.
     1057 * @param   pValue1             The first value.
     1058 * @param   pValue2             The second value.
     1059 */
     1060DECLINLINE(bool) RTUInt256IsNotEqual(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
     1061{
     1062    return !RTUInt256IsEqual(pValue1, pValue2);
     1063}
     1064
     1065
     1066/**
     1067 * Sets a bit in a 256-bit unsigned integer type.
     1068 *
     1069 * @returns pValueResult.
     1070 * @param   pValueResult    The input and output value.
     1071 * @param   iBit            The bit to set.
     1072 */
     1073DECLINLINE(PRTUINT256U) RTUInt256BitSet(PRTUINT256U pValueResult, unsigned iBit)
     1074{
     1075    if (iBit < 256)
     1076    {
     1077        unsigned idxQWord = iBit >> 6;
     1078#ifdef RT_BIG_ENDIAN
     1079        idxQWord = RT_ELEMENTS(pValueResult->au64) - idxQWord;
     1080#endif
     1081        iBit &= 0x3f;
     1082        pValueResult->au64[idxQWord] |= RT_BIT_64(iBit);
     1083    }
     1084    return pValueResult;
     1085}
     1086
     1087
     1088/**
     1089 * Sets a bit in a 256-bit unsigned integer type.
     1090 *
     1091 * @returns pValueResult.
     1092 * @param   pValueResult    The input and output value.
     1093 * @param   iBit            The bit to set.
     1094 */
     1095DECLINLINE(PRTUINT256U) RTUInt256BitClear(PRTUINT256U pValueResult, unsigned iBit)
     1096{
     1097    if (iBit < 256)
     1098    {
     1099        unsigned idxQWord = iBit >> 6;
     1100#ifdef RT_BIG_ENDIAN
     1101        idxQWord = RT_ELEMENTS(pValueResult->au64) - idxQWord;
     1102#endif
     1103        iBit &= 0x3f;
     1104        pValueResult->au64[idxQWord] &= ~RT_BIT_64(iBit);
     1105    }
     1106    return pValueResult;
     1107}
     1108
     1109
     1110/**
     1111 * Tests if a bit in a 256-bit unsigned integer value is set.
     1112 *
     1113 * @returns pValueResult.
     1114 * @param   pValueResult    The input and output value.
     1115 * @param   iBit            The bit to test.
     1116 */
     1117DECLINLINE(bool) RTUInt256BitTest(PRTUINT256U pValueResult, unsigned iBit)
     1118{
     1119    bool fRc;
     1120    if (iBit < 256)
     1121    {
     1122        unsigned idxQWord = iBit >> 6;
     1123#ifdef RT_BIG_ENDIAN
     1124        idxQWord = RT_ELEMENTS(pValueResult->au64) - idxQWord;
     1125#endif
     1126        iBit &= 0x3f;
     1127        fRc = RT_BOOL(pValueResult->au64[idxQWord] & RT_BIT_64(iBit));
     1128    }
     1129    else
     1130        fRc = false;
     1131    return fRc;
     1132}
     1133
     1134
     1135/**
     1136 * Set a range of bits a 256-bit unsigned integer value.
     1137 *
     1138 * @returns pValueResult.
     1139 * @param   pValueResult    The input and output value.
     1140 * @param   iFirstBit       The first bit to test.
     1141 * @param   cBits           The number of bits to set.
     1142 */
     1143DECLINLINE(PRTUINT256U) RTUInt256BitSetRange(PRTUINT256U pValueResult, unsigned iFirstBit, unsigned cBits)
     1144{
     1145    /* bounds check & fix. */
     1146    if (iFirstBit < 256)
     1147    {
     1148        if (iFirstBit + cBits > 256)
     1149            cBits = 256 - iFirstBit;
     1150
     1151        /* Work the au64 array: */
     1152#ifdef RT_BIG_ENDIAN
     1153        int       idxQWord = RT_ELEMENTS(pValueResult->au64) - (iFirstBit >> 6);
     1154        int const idxInc   = -1;
     1155#else
     1156        int       idxQWord = iFirstBit >> 6;
     1157        int const idxInc   = 1;
     1158#endif
     1159        while (cBits > 0)
     1160        {
     1161            unsigned iQWordFirstBit = iFirstBit & 0x3f;
     1162            unsigned cQWordBits     = cBits + iQWordFirstBit >= 64 ? 64 - iQWordFirstBit : cBits;
     1163            pValueResult->au64[idxQWord] |= cQWordBits < 64 ? (RT_BIT_64(cQWordBits) - 1) << iQWordFirstBit : UINT64_MAX;
     1164
     1165            idxQWord  += idxInc;
     1166            iFirstBit += cQWordBits;
     1167            cBits     -= cQWordBits;
     1168        }
     1169    }
     1170    return pValueResult;
     1171}
     1172
     1173
     1174/**
     1175 * Test if all the bits of a 256-bit unsigned integer value are set.
     1176 *
     1177 * @returns true if they are, false if they aren't.
     1178 * @param   pValue          The input and output value.
     1179 */
     1180DECLINLINE(bool) RTUInt256BitAreAllSet(PRTUINT256U pValue)
     1181{
     1182    return pValue->QWords.qw0 == UINT64_MAX
     1183        && pValue->QWords.qw1 == UINT64_MAX
     1184        && pValue->QWords.qw2 == UINT64_MAX
     1185        && pValue->QWords.qw3 == UINT64_MAX;
     1186}
     1187
     1188
     1189/**
     1190 * Test if all the bits of a 256-bit unsigned integer value are clear.
     1191 *
     1192 * @returns true if they are, false if they aren't.
     1193 * @param   pValue          The input and output value.
     1194 */
     1195DECLINLINE(bool) RTUInt256BitAreAllClear(PRTUINT256U pValue)
     1196{
     1197    return RTUInt256IsZero(pValue);
     1198}
     1199
     1200
     1201/**
     1202 * Number of significant bits in the value.
     1203 *
     1204 * This is the same a ASMBitLastSetU64 and ASMBitLastSetU32.
     1205 *
     1206 * @returns 0 if zero, 1-base index of the last bit set.
     1207 * @param   pValue              The value to examine.
     1208 */
     1209DECLINLINE(uint32_t) RTUInt256BitCount(PCRTUINT256U pValue)
     1210{
     1211    uint64_t u64;
     1212    uint32_t cBits;
     1213    if ((u64 = pValue->QWords.qw3) != 0)
     1214        cBits = 192;
     1215    else if ((u64 = pValue->QWords.qw2) != 0)
     1216        cBits = 128;
     1217    else if ((u64 = pValue->QWords.qw1) != 0)
     1218        cBits = 64;
     1219    else
     1220    {
     1221        u64 = pValue->QWords.qw0;
     1222        cBits = 0;
     1223    }
     1224    return cBits + ASMBitLastSetU64(u64);
    13921225}
    13931226
     
    13971230RT_C_DECLS_END
    13981231
    1399 #endif /* !IPRT_INCLUDED_uint128_h */
    1400 
     1232#endif /* !IPRT_INCLUDED_uint256_h */
     1233
  • trunk/src/VBox/Runtime/Makefile.kmk

    r94471 r94511  
    907907        common/math/bignum-amd64-x86.asm \
    908908        common/math/RTUInt128MulByU64.asm \
     909        common/math/RTUInt128MulByU64Ex.asm \
    909910       common/string/RTStrEnd.asm
    910911
     
    30913092        common/math/bignum-amd64-x86.asm \
    30923093        common/math/RTUInt128MulByU64.asm \
     3094        common/math/RTUInt128MulByU64Ex.asm \
    30933095        common/string/RTStrEnd.asm
    30943096RuntimeR0Drv_SOURCES.x86   = \
  • trunk/src/VBox/Runtime/common/math/RTUInt128MulByU64Ex.asm

    r94493 r94511  
    3434
    3535;;
    36 ; Multiplies a 128-bit number with a 64-bit one.
     36; Multiplies a 128-bit number with a 64-bit one, returning a 256-bit result.
    3737;
    3838; @returns puResult.
     
    4141; @param    uValue2        x86:[ebp + 16]  gcc:rdx  msc:r8
    4242;
    43 RT_BEGINPROC RTUInt128MulByU64
     43RT_BEGINPROC RTUInt128MulByU64Ex
    4444;        SEH64_SET_FRAME_xSP 0
    4545SEH64_END_PROLOGUE
     
    6161        mov     rax, [puValue1]
    6262        mul     uValue2
    63         mov     [puResult], rax
    64         mov     r11, rdx                ; Store the lower half of the result.
     63        mov     [puResult], rax         ; Store the 1st 64-bit part of the result.
     64        mov     r11, rdx                ; Save the upper 64 bits for later.
    6565
    6666        ; puValue1->s.Hi * uValue2
     
    6868        mul     uValue2
    6969        add     r11, rax                ; Calc the second half of the result.
    70         mov     [puResult + 8], r11     ; Store the high half of the result.
     70        adc     rdx, 0
     71        mov     [puResult + 8], r11     ; Store the 2nd 64-bit part of the result.
     72        mov     [puResult + 16], rdx    ; Store the 3rd 64-bit part of the result.
     73        xor     r10, r10
     74        mov     [puResult + 24], r10    ; Store the 4th 64-bit part of the result.
    7175
    7276        mov     rax, puResult
     
    7882
    7983        ret
    80 ENDPROC RTUInt128MulByU64
     84ENDPROC RTUInt128MulByU64Ex
    8185
  • trunk/src/VBox/Runtime/common/string/strformatfloat.cpp

    r94336 r94511  
    177177        *pszTmp++ = '1';
    178178        *pszTmp++ = 'm';
    179         pszTmp += RTStrFormatNumber(pszTmp, uFraction, 16, 2 + RTFLOAT64U_FRACTION_BITS / 4, 0,
     179        pszTmp += RTStrFormatNumber(pszTmp, uFraction, 16, 2 + (RTFLOAT64U_FRACTION_BITS + 3) / 4, 0,
    180180                                    RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
    181181
     
    191191        *pszTmp++ = '0';
    192192        *pszTmp++ = 'm';
    193         pszTmp += RTStrFormatNumber(pszTmp, uFraction, 16, 2 + RTFLOAT64U_FRACTION_BITS / 4, 0,
     193        pszTmp += RTStrFormatNumber(pszTmp, uFraction, 16, 2 + (RTFLOAT64U_FRACTION_BITS + 3) / 4, 0,
    194194                                    RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
    195195        if (fFlags & RTSTR_F_SPECIAL)
     
    224224 */
    225225static ssize_t rtStrFormatR80Worker(char *pszBuf, size_t cbBuf, bool const fSign, bool const fInteger,
    226                                     uint64_t const uFraction, uint16_t const uExponent, uint32_t fFlags)
     226                                    uint64_t const uFraction, uint16_t uExponent, uint32_t fFlags)
    227227{
    228228    char szTmp[160];
     
    250250                 : rtStrFormatCopyOutStr(pszBuf, cbBuf, RT_STR_TUPLE("+0"));
    251251        fDenormal = true;
     252        if (fInteger)
     253            uExponent = 1;
    252254    }
    253255    else if (uExponent == RTFLOAT80U_EXP_MAX)
     
    296298    *pszTmp++ = fInteger ? '1' : '0';
    297299    *pszTmp++ = 'm';
    298     pszTmp += RTStrFormatNumber(pszTmp, uFraction, 16, 2 + RTFLOAT80U_FRACTION_BITS / 4, 0,
     300    pszTmp += RTStrFormatNumber(pszTmp, uFraction, 16, 2 + (RTFLOAT80U_FRACTION_BITS + 3) / 4, 0,
    299301                                RTSTR_F_SPECIAL | RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
    300302
  • trunk/src/VBox/Runtime/testcase/tstRTBigNum.cpp

    r93115 r94511  
    3030*********************************************************************************************************************************/
    3131#include <iprt/bignum.h>
     32#include <iprt/uint256.h>
    3233#include <iprt/uint128.h>
    3334#include <iprt/uint64.h>
     
    15021503        RTTESTI_CHECK(RTUInt128IsEqual(&uResult, &s_aTests[i].uResult));
    15031504    }
     1505
     1506    /* extended versions */
     1507    RTTestSub(g_hTest, "RTUInt128MulEx");
     1508    static struct
     1509    {
     1510        RTUINT128U uFactor1, uFactor2;
     1511        RTUINT256U uResult;
     1512    } const s_aTestsEx[] =
     1513    {
     1514    { RTUINT128_INIT_C(~0, ~0),     RTUINT128_INIT_C(~0, 0),    RTUINT256_INIT_C(~1, ~0, 1, 0) },
     1515    { RTUINT128_INIT_C(~0, ~0),     RTUINT128_INIT_C(~0, ~0),   RTUINT256_INIT_C(~0, ~1, 0, 1) },
     1516        { RTUINT128_INIT_C(0, 0),       RTUINT128_INIT_C(0, 1),     RTUINT256_INIT_C(0, 0, 0, 0) },
     1517        { RTUINT128_INIT_C(0, 1),       RTUINT128_INIT_C(0, 1),     RTUINT256_INIT_C(0, 0, 0, 1) },
     1518        { RTUINT128_INIT_C(0, 2),       RTUINT128_INIT_C(0, 2),     RTUINT256_INIT_C(0, 0, 0, 4) },
     1519        { RTUINT128_INIT_C(2, 0),       RTUINT128_INIT_C(0, 4),     RTUINT256_INIT_C(0, 0, 8, 0) },
     1520        { RTUINT128_INIT_C(~0, ~0),     RTUINT128_INIT_C(0, 0),     RTUINT256_INIT_C(0, 0, 0, 0) },
     1521        { RTUINT128_INIT_C(~0, ~0),     RTUINT128_INIT_C(0, ~0),    RTUINT256_INIT_C(0, ~1, ~0, 1) },
     1522        { RTUINT128_INIT_C(~0, ~0),     RTUINT128_INIT_C(~0, 0),    RTUINT256_INIT_C(~1, ~0, 1, 0) },
     1523        { RTUINT128_INIT_C(~0, ~0),     RTUINT128_INIT_C(~0, ~0),   RTUINT256_INIT_C(~0, ~1, 0, 1) },
     1524    };
     1525    for (uint32_t i = 0; i < RT_ELEMENTS(s_aTestsEx); i++)
     1526    {
     1527        RTUINT256U uResult;
     1528        PRTUINT256U pResult = RTUInt128MulEx(&uResult, &s_aTestsEx[i].uFactor1, &s_aTestsEx[i].uFactor2);
     1529        if (pResult != &uResult)
     1530            RTTestIFailed("test #%i returns %p instead of %p", i, pResult, &uResult);
     1531        else if (!RTUInt256IsEqual(&uResult, &s_aTestsEx[i].uResult))
     1532            RTTestIFailed("test #%i failed: \nExp: %016RX64`%016RX64`%016RX64`%016RX64\nGot: %016RX64`%016RX64`%016RX64`%016RX64",
     1533                          i, s_aTestsEx[i].uResult.QWords.qw3, s_aTestsEx[i].uResult.QWords.qw2, s_aTestsEx[i].uResult.QWords.qw1,
     1534                          s_aTestsEx[i].uResult.QWords.qw0, uResult.QWords.qw3, uResult.QWords.qw2, uResult.QWords.qw1,
     1535                          uResult.QWords.qw0 );
     1536
     1537        if (s_aTestsEx[i].uFactor2.s.Hi == 0)
     1538        {
     1539            RTUInt256AssignBitwiseNot(&uResult);
     1540            pResult = RTUInt128MulByU64Ex(&uResult, &s_aTestsEx[i].uFactor1, s_aTestsEx[i].uFactor2.s.Lo);
     1541            RTTESTI_CHECK(pResult == &uResult);
     1542            RTTESTI_CHECK(RTUInt256IsEqual(&uResult, &s_aTestsEx[i].uResult));
     1543        }
     1544
     1545        if (s_aTestsEx[i].uFactor1.s.Hi == 0)
     1546        {
     1547            RTUInt256AssignBitwiseNot(&uResult);
     1548            pResult = RTUInt128MulByU64Ex(&uResult, &s_aTestsEx[i].uFactor2, s_aTestsEx[i].uFactor1.s.Lo);
     1549            RTTESTI_CHECK(pResult == &uResult);
     1550            RTTESTI_CHECK(RTUInt256IsEqual(&uResult, &s_aTestsEx[i].uResult));
     1551        }
     1552
     1553#if 0
     1554        uResult = s_aTestsEx[i].uFactor1;
     1555        pResult = RTUInt128AssignMul(&uResult, &s_aTestsEx[i].uFactor2);
     1556        RTTESTI_CHECK(pResult == &uResult);
     1557        RTTESTI_CHECK(RTUInt128IsEqual(&uResult, &s_aTestsEx[i].uResult));
     1558#endif
     1559    }
     1560
    15041561}
    15051562
     
    16811738            RTTestIFailed("%u / %u -> %u rem %u, expected %u rem %u",
    16821739                          uDividend, uDivisor, Quotient.u, Remainder.u, uQuotient, uRemainder);
     1740    }
     1741}
     1742
     1743
     1744static void testUInt256Shift(void)
     1745{
     1746    {
     1747        RTTestSub(g_hTest, "RTUInt256ShiftLeft");
     1748        static struct
     1749        {
     1750            RTUINT256U uValue, uResult;
     1751            unsigned   cShift;
     1752        } const s_aTests[] =
     1753        {
     1754            { RTUINT256_INIT_C(0, 0, 0, 0), RTUINT256_INIT_C(0, 0, 0, 0), 1   },
     1755            { RTUINT256_INIT_C(0, 0, 0, 0), RTUINT256_INIT_C(0, 0, 0, 0), 128 },
     1756            { RTUINT256_INIT_C(0, 0, 0, 0), RTUINT256_INIT_C(0, 0, 0, 0), 127 },
     1757            { RTUINT256_INIT_C(0, 0, 0, 0), RTUINT256_INIT_C(0, 0, 0, 0), 255 },
     1758            { RTUINT256_INIT_C(0, 0, 0, 1), RTUINT256_INIT_C(1, 0, 0, 0), 192 },
     1759            { RTUINT256_INIT_C(0, 0, 0, 1), RTUINT256_INIT_C(0, 1, 0, 0), 128 },
     1760            { RTUINT256_INIT_C(0, 0, 0, 1), RTUINT256_INIT_C(0, 0, 1, 0), 64 },
     1761            { RTUINT256_INIT_C(0, 0, 0, 1), RTUINT256_INIT_C(0, 0, 0, 1), 0},
     1762            { RTUINT256_INIT_C(0, 0, 0, 1), RTUINT256_INIT_C(4, 0, 0, 0), 194 },
     1763            { RTUINT256_INIT_C(0, 0, 0, 1), RTUINT256_INIT_C(0, 0, 0x10, 0), 68},
     1764            { RTUINT256_INIT_C(0, 0, 0, 1), RTUINT256_INIT_C(0, 2, 0, 0), 129},
     1765            { RTUINT256_INIT_C(0, 0, 0, 1), RTUINT256_INIT_C(0, 0, 0, 0x8000000000000000), 63 },
     1766            { RTUINT256_INIT_C(0xfefdfcfbfaf9f8f7, 0xf6f5f4f3f2f1f0ff, 0x3f3e3d3c3b3a3938, 0x3736353433323130),
     1767              RTUINT256_INIT_C(0xfdfcfbfaf9f8f7f6, 0xf5f4f3f2f1f0ff3f, 0x3e3d3c3b3a393837, 0x3635343332313000), 8 },
     1768            { RTUINT256_INIT_C(0xfefdfcfbfaf9f8f7, 0xf6f5f4f3f2f1f0ff, 0x3f3e3d3c3b3a3938, 0x3736353433323130),
     1769              RTUINT256_INIT_C(0x6f5f4f3f2f1f0ff3, 0xf3e3d3c3b3a39383, 0x7363534333231300, 0), 68 },
     1770            { RTUINT256_INIT_C(0xfefdfcfbfaf9f8f7, 0xf6f5f4f3f2f1f0ff, 0x3f3e3d3c3b3a3938, 0x3736353433323130),
     1771              RTUINT256_INIT_C(0x3e3d3c3b3a393837, 0x3635343332313000, 0, 0), 136 },
     1772            { RTUINT256_INIT_C(0xfefdfcfbfaf9f8f7, 0xf6f5f4f3f2f1f0ff, 0x3f3e3d3c3b3a3938, 0x3736353433323130),
     1773              RTUINT256_INIT_C(0x6353433323130000, 0, 0, 0), 204 },
     1774        };
     1775        for (uint32_t i = 0; i < RT_ELEMENTS(s_aTests); i++)
     1776        {
     1777            RTUINT256U uResult;
     1778            PRTUINT256U pResult = RTUInt256ShiftLeft(&uResult, &s_aTests[i].uValue, s_aTests[i].cShift);
     1779            if (pResult != &uResult)
     1780                RTTestIFailed("test #%i returns %p instead of %p", i, pResult, &uResult);
     1781            else if (RTUInt256IsNotEqual(&uResult, &s_aTests[i].uResult))
     1782                RTTestIFailed("test #%i failed: \nExp: %016RX64`%016RX64'%016RX64`%016RX64\nGot: %016RX64`%016RX64'%016RX64`%016RX64",
     1783                              i, s_aTests[i].uResult.QWords.qw3, s_aTests[i].uResult.QWords.qw2, s_aTests[i].uResult.QWords.qw1,
     1784                              s_aTests[i].uResult.QWords.qw0, uResult.QWords.qw3, uResult.QWords.qw2, uResult.QWords.qw1,
     1785                              uResult.QWords.qw0);
     1786
     1787            uResult = s_aTests[i].uValue;
     1788            pResult = RTUInt256AssignShiftLeft(&uResult, s_aTests[i].cShift);
     1789            RTTESTI_CHECK(pResult == &uResult);
     1790            RTTESTI_CHECK(RTUInt256IsEqual(&uResult, &s_aTests[i].uResult));
     1791        }
     1792    }
     1793    {
     1794        RTTestSub(g_hTest, "RTUInt256ShiftRight");
     1795        static struct
     1796        {
     1797            RTUINT256U uValue, uResult;
     1798            unsigned   cShift;
     1799        } const s_aTests[] =
     1800        {
     1801            { RTUINT256_INIT_C(0, 0, 0, 0), RTUINT256_INIT_C(0, 0, 0, 0), 1   },
     1802            { RTUINT256_INIT_C(0, 0, 0, 0), RTUINT256_INIT_C(0, 0, 0, 0), 128 },
     1803            { RTUINT256_INIT_C(0, 0, 0, 0), RTUINT256_INIT_C(0, 0, 0, 0), 127 },
     1804            { RTUINT256_INIT_C(0, 0, 0, 0), RTUINT256_INIT_C(0, 0, 0, 0), 255 },
     1805            { RTUINT256_INIT_C(1, 0, 0, 1), RTUINT256_INIT_C(0, 0, 0, 1), 192},
     1806            { RTUINT256_INIT_C(1, 0, 0, 1), RTUINT256_INIT_C(0, 0, 1, 0), 128},
     1807            { RTUINT256_INIT_C(1, 0, 0, 1), RTUINT256_INIT_C(0, 1, 0, 0), 64},
     1808            { RTUINT256_INIT_C(1, 0, 0, 1), RTUINT256_INIT_C(1, 0, 0, 1), 0},
     1809            { RTUINT256_INIT_C(1, 0, 0, 1), RTUINT256_INIT_C(0, 0, 0, 4), 190},
     1810            { RTUINT256_INIT_C(1, 0, 0, 1), RTUINT256_INIT_C(0, 0, 1, 0), 128},
     1811            { RTUINT256_INIT_C(1, 0, 0, 1), RTUINT256_INIT_C(0, 8, 0, 0), 61},
     1812            { RTUINT256_INIT_C(0xfefdfcfbfaf9f8f7, 0xf6f5f4f3f2f1f0ff, 0x3f3e3d3c3b3a3938, 0x3736353433323130),
     1813              RTUINT256_INIT_C(0x00fefdfcfbfaf9f8, 0xf7f6f5f4f3f2f1f0, 0xff3f3e3d3c3b3a39, 0x3837363534333231), 8 },
     1814            { RTUINT256_INIT_C(0xfefdfcfbfaf9f8f7, 0xf6f5f4f3f2f1f0ff, 0x3f3e3d3c3b3a3938, 0x3736353433323130),
     1815              RTUINT256_INIT_C(0, 0x0fefdfcfbfaf9f8f, 0x7f6f5f4f3f2f1f0f, 0xf3f3e3d3c3b3a393), 68 },
     1816            { RTUINT256_INIT_C(0xfefdfcfbfaf9f8f7, 0xf6f5f4f3f2f1f0ff, 0x3f3e3d3c3b3a3938, 0x3736353433323130),
     1817              RTUINT256_INIT_C(0, 0, 0x0fefdfcfbfaf9f8f, 0x7f6f5f4f3f2f1f0f), 132 },
     1818            { RTUINT256_INIT_C(0xfefdfcfbfaf9f8f7, 0xf6f5f4f3f2f1f0ff, 0x3f3e3d3c3b3a3938, 0x3736353433323130),
     1819              RTUINT256_INIT_C(0, 0, 0, 0xfefdfcfbfaf9f8f7), 192 },
     1820            { RTUINT256_INIT_C(0xfefdfcfbfaf9f8f7, 0xf6f5f4f3f2f1f0ff, 0x3f3e3d3c3b3a3938, 0x3736353433323130),
     1821              RTUINT256_INIT_C(0, 0, 0, 0x000fefdfcfbfaf9f), 204 },
     1822            { RTUINT256_INIT_C(0xfefdfcfbfaf9f8f7, 0xf6f5f4f3f2f1f0ff, 0x3f3e3d3c3b3a3938, 0x3736353433323130),
     1823              RTUINT256_INIT_C(0, 0, 0, 1), 255 },
     1824        };
     1825        for (uint32_t i = 0; i < RT_ELEMENTS(s_aTests); i++)
     1826        {
     1827            RTUINT256U uResult;
     1828            PRTUINT256U pResult = RTUInt256ShiftRight(&uResult, &s_aTests[i].uValue, s_aTests[i].cShift);
     1829            if (pResult != &uResult)
     1830                RTTestIFailed("test #%i returns %p instead of %p", i, pResult, &uResult);
     1831            else if (RTUInt256IsNotEqual(&uResult, &s_aTests[i].uResult))
     1832                RTTestIFailed("test #%i failed: \nExp: %016RX64`%016RX64'%016RX64`%016RX64\nGot: %016RX64`%016RX64'%016RX64`%016RX64",
     1833                              i, s_aTests[i].uResult.QWords.qw3, s_aTests[i].uResult.QWords.qw2, s_aTests[i].uResult.QWords.qw1,
     1834                              s_aTests[i].uResult.QWords.qw0, uResult.QWords.qw3, uResult.QWords.qw2, uResult.QWords.qw1,
     1835                              uResult.QWords.qw0);
     1836
     1837            uResult = s_aTests[i].uValue;
     1838            pResult = RTUInt256AssignShiftRight(&uResult, s_aTests[i].cShift);
     1839            RTTESTI_CHECK(pResult == &uResult);
     1840            RTTESTI_CHECK(RTUInt256IsEqual(&uResult, &s_aTests[i].uResult));
     1841        }
    16831842    }
    16841843}
     
    17481907            testUInt64Division();
    17491908
     1909            /* Test some UInt256 bits given what we do above already. */
     1910            testUInt256Shift();
     1911
    17501912            /* Test the RTBigInt operations. */
    17511913            testCompare();
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette