VirtualBox

source: vbox/trunk/include/iprt/uint64.h

Last change on this file was 98514, checked in by vboxsync, 16 months ago

iprt/uint64.h: scm fix. bugref:10261

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 41.9 KB
RevLine 
[35488]1/** @file
[60482]2 * IPRT - RTUINT64U methods for old 32-bit and 16-bit compilers.
[35488]3 */
4
5/*
[98103]6 * Copyright (C) 2011-2023 Oracle and/or its affiliates.
[35488]7 *
[96407]8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
[35488]10 *
[96407]11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation, in version 3 of the
14 * License.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <https://www.gnu.org/licenses>.
23 *
[35488]24 * The contents of this file may alternatively be used under the terms
25 * of the Common Development and Distribution License Version 1.0
[96407]26 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
27 * in the VirtualBox distribution, in which case the provisions of the
[35488]28 * CDDL are applicable instead of those of the GPL.
29 *
30 * You may elect to license modified versions of this file under the
31 * terms and conditions of either the GPL or the CDDL or both.
[96407]32 *
33 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
[35488]34 */
35
[76557]36#ifndef IPRT_INCLUDED_uint64_h
37#define IPRT_INCLUDED_uint64_h
[76507]38#ifndef RT_WITHOUT_PRAGMA_ONCE
39# pragma once
40#endif
[35488]41
42#include <iprt/cdefs.h>
43#include <iprt/types.h>
[52335]44#include <iprt/asm.h>
[35488]45
46RT_C_DECLS_BEGIN
47
[60482]48/** @defgroup grp_rt_uint64 RTUInt64 - 64-bit Unsigned Integer Methods for ancient compilers
[35488]49 * @ingroup grp_rt
50 * @{
51 */
52
53
54/**
55 * Test if a 128-bit unsigned integer value is zero.
56 *
57 * @returns true if they are, false if they aren't.
[98498]58 * @param pValue The value to examine.
[35488]59 */
[98498]60DECLINLINE(bool) RTUInt64IsZero(PCRTUINT64U pValue)
[35488]61{
[60482]62#if ARCH_BITS >= 32
63 return pValue->s.Lo == 0
64 && pValue->s.Hi == 0;
[35488]65#else
[60482]66 return pValue->Words.w0 == 0
67 && pValue->Words.w1 == 0
68 && pValue->Words.w2 == 0
69 && pValue->Words.w3 == 0;
[35488]70#endif
71}
72
73
74/**
[98514]75 * Checks if the sign-bit is set.
76 *
[98498]77 * @returns Sign bit.
78 * @param pValue The value to examine.
79 */
80DECLINLINE(bool) RTUInt64IsSigned(PCRTUINT64U pValue)
81{
82#if ARCH_BITS >= 32
83 return RT_BOOL(pValue->DWords.dw1 & RT_BIT_32(31));
84#else
85 return RT_BOOL(pValue->Words.w3 & ((uint16_t)1 << 15));
86#endif
87}
88
89
90/**
[35488]91 * Set a 128-bit unsigned integer value to zero.
92 *
93 * @returns pResult
94 * @param pResult The result variable.
95 */
[60482]96DECLINLINE(PRTUINT64U) RTUInt64SetZero(PRTUINT64U pResult)
[35488]97{
[60482]98#if ARCH_BITS >= 32
[35488]99 pResult->s.Hi = 0;
100 pResult->s.Lo = 0;
101#else
[60482]102 pResult->Words.w0 = 0;
103 pResult->Words.w1 = 0;
104 pResult->Words.w2 = 0;
105 pResult->Words.w3 = 0;
[35488]106#endif
107 return pResult;
108}
109
110
111/**
[60482]112 * Set a 32-bit unsigned integer value to the maximum value.
[35488]113 *
114 * @returns pResult
115 * @param pResult The result variable.
116 */
[60482]117DECLINLINE(PRTUINT64U) RTUInt64SetMax(PRTUINT64U pResult)
[35488]118{
[60482]119#if ARCH_BITS >= 32
120 pResult->s.Hi = UINT32_MAX;
121 pResult->s.Lo = UINT32_MAX;
[35488]122#else
[60482]123 pResult->Words.w0 = UINT16_MAX;
124 pResult->Words.w1 = UINT16_MAX;
125 pResult->Words.w2 = UINT16_MAX;
126 pResult->Words.w3 = UINT16_MAX;
[35488]127#endif
128 return pResult;
129}
130
131
132
133
134/**
[60482]135 * Adds two 64-bit unsigned integer values.
[52335]136 *
137 * @returns pResult
138 * @param pResult The result variable.
139 * @param pValue1 The first value.
140 * @param pValue2 The second value.
141 */
[60482]142DECLINLINE(PRTUINT64U) RTUInt64Add(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[52335]143{
144 pResult->s.Hi = pValue1->s.Hi + pValue2->s.Hi;
145 pResult->s.Lo = pValue1->s.Lo + pValue2->s.Lo;
146 if (pResult->s.Lo < pValue1->s.Lo)
147 pResult->s.Hi++;
148 return pResult;
149}
150
151
152/**
[60482]153 * Adds a 64-bit and a 32-bit unsigned integer values.
[52335]154 *
155 * @returns pResult
156 * @param pResult The result variable.
157 * @param pValue1 The first value.
[60482]158 * @param uValue2 The second value, 32-bit.
[52335]159 */
[60482]160DECLINLINE(PRTUINT64U) RTUInt64AddU32(PRTUINT64U pResult, PCRTUINT64U pValue1, uint32_t uValue2)
[52335]161{
162 pResult->s.Hi = pValue1->s.Hi;
163 pResult->s.Lo = pValue1->s.Lo + uValue2;
164 if (pResult->s.Lo < pValue1->s.Lo)
165 pResult->s.Hi++;
166 return pResult;
167}
168
169
170/**
[60482]171 * Subtracts a 64-bit unsigned integer value from another.
[52335]172 *
173 * @returns pResult
174 * @param pResult The result variable.
175 * @param pValue1 The minuend value.
176 * @param pValue2 The subtrahend value.
177 */
[60482]178DECLINLINE(PRTUINT64U) RTUInt64Sub(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[52335]179{
180 pResult->s.Lo = pValue1->s.Lo - pValue2->s.Lo;
181 pResult->s.Hi = pValue1->s.Hi - pValue2->s.Hi;
182 if (pResult->s.Lo > pValue1->s.Lo)
183 pResult->s.Hi--;
184 return pResult;
185}
186
187
188/**
[98498]189 * Calculates the negated number (special case of subtraction)
190 *
191 * @returns pResult
192 * @param pResult The result variable.
193 * @param pValue The value to negate.
194 */
195DECLINLINE(PRTUINT64U) RTUInt64Neg(PRTUINT64U pResult, PCRTUINT64U pValue)
196{
197 pResult->s.Lo = UINT32_C(0) - pValue->s.Lo;
198 pResult->s.Hi = UINT32_C(0) - pValue->s.Hi;
199 if (pResult->s.Lo > UINT32_C(0))
200 pResult->s.Hi--;
201 return pResult;
202}
203
204
205/**
[60482]206 * Multiplies two 64-bit unsigned integer values.
[52335]207 *
208 * @returns pResult
209 * @param pResult The result variable.
210 * @param pValue1 The first value.
211 * @param pValue2 The second value.
212 */
[60482]213DECLINLINE(PRTUINT64U) RTUInt64Mul(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[52335]214{
[60482]215 RTUINT32U uTmp;
[52335]216
[60482]217 /* multiply all words in v1 by v2.w0. */
218 pResult->s.Lo = (uint32_t)pValue1->Words.w0 * pValue2->Words.w0;
[52335]219
[60482]220 uTmp.u = (uint32_t)pValue1->Words.w1 * pValue2->Words.w0;
221 pResult->Words.w3 = 0;
222 pResult->Words.w2 = uTmp.Words.w1;
223 pResult->Words.w1 += uTmp.Words.w0;
224 if (pResult->Words.w1 < uTmp.Words.w0)
225 if (pResult->Words.w2++ == UINT16_MAX)
226 pResult->Words.w3++;
[52335]227
[60482]228 pResult->s.Hi += (uint32_t)pValue1->Words.w2 * pValue2->Words.w0;
229 pResult->Words.w3 += pValue1->Words.w3 * pValue2->Words.w0;
[52335]230
[60482]231 /* multiply w0, w1 & w2 in v1 by v2.w1. */
232 uTmp.u = (uint32_t)pValue1->Words.w0 * pValue2->Words.w1;
233 pResult->Words.w1 += uTmp.Words.w0;
234 if (pResult->Words.w1 < uTmp.Words.w0)
235 if (pResult->Words.w2++ == UINT16_MAX)
236 pResult->Words.w3++;
[52335]237
[60482]238 pResult->Words.w2 += uTmp.Words.w1;
239 if (pResult->Words.w2 < uTmp.Words.w1)
240 pResult->Words.w3++;
[52335]241
[60482]242 pResult->s.Hi += (uint32_t)pValue1->Words.w1 * pValue2->Words.w1;
243 pResult->Words.w3 += pValue1->Words.w2 * pValue2->Words.w1;
[52335]244
[60482]245 /* multiply w0 & w1 in v1 by v2.w2. */
246 pResult->s.Hi += (uint32_t)pValue1->Words.w0 * pValue2->Words.w2;
247 pResult->Words.w3 += pValue1->Words.w1 * pValue2->Words.w2;
[52335]248
[60482]249 /* multiply w0 in v1 by v2.w3. */
250 pResult->Words.w3 += pValue1->Words.w0 * pValue2->Words.w3;
[52335]251
252 return pResult;
253}
254
255
256/**
[60482]257 * Multiplies an 64-bit unsigned integer by a 32-bit unsigned integer value.
[52335]258 *
259 * @returns pResult
260 * @param pResult The result variable.
261 * @param pValue1 The first value.
[60482]262 * @param uValue2 The second value, 32-bit.
[52335]263 */
[60482]264DECLINLINE(PRTUINT64U) RTUInt64MulByU32(PRTUINT64U pResult, PCRTUINT64U pValue1, uint32_t uValue2)
[52335]265{
[60482]266 uint16_t const uLoValue2 = (uint16_t)uValue2;
267 uint16_t const uHiValue2 = (uint16_t)(uValue2 >> 16);
268 RTUINT32U uTmp;
[52335]269
[60482]270 /* multiply all words in v1 by uLoValue1. */
271 pResult->s.Lo = (uint32_t)pValue1->Words.w0 * uLoValue2;
[52335]272
[60482]273 uTmp.u = (uint32_t)pValue1->Words.w1 * uLoValue2;
274 pResult->Words.w3 = 0;
275 pResult->Words.w2 = uTmp.Words.w1;
276 pResult->Words.w1 += uTmp.Words.w0;
277 if (pResult->Words.w1 < uTmp.Words.w0)
278 if (pResult->Words.w2++ == UINT16_MAX)
279 pResult->Words.w3++;
[52335]280
[60482]281 pResult->s.Hi += (uint32_t)pValue1->Words.w2 * uLoValue2;
282 pResult->Words.w3 += pValue1->Words.w3 * uLoValue2;
[52335]283
[60482]284 /* multiply w0, w1 & w2 in v1 by uHiValue2. */
285 uTmp.u = (uint32_t)pValue1->Words.w0 * uHiValue2;
286 pResult->Words.w1 += uTmp.Words.w0;
287 if (pResult->Words.w1 < uTmp.Words.w0)
288 if (pResult->Words.w2++ == UINT16_MAX)
289 pResult->Words.w3++;
[52335]290
[60482]291 pResult->Words.w2 += uTmp.Words.w1;
292 if (pResult->Words.w2 < uTmp.Words.w1)
293 pResult->Words.w3++;
[52335]294
[60482]295 pResult->s.Hi += (uint32_t)pValue1->Words.w1 * uHiValue2;
296 pResult->Words.w3 += pValue1->Words.w2 * uHiValue2;
[52335]297
298 return pResult;
299}
300
301
302/**
[60482]303 * Multiplies two 32-bit unsigned integer values with 64-bit precision.
[52335]304 *
305 * @returns pResult
306 * @param pResult The result variable.
[60482]307 * @param uValue1 The first value. 32-bit.
308 * @param uValue2 The second value, 32-bit.
[52335]309 */
[60482]310DECLINLINE(PRTUINT64U) RTUInt64MulU32ByU32(PRTUINT64U pResult, uint32_t uValue1, uint32_t uValue2)
[52335]311{
[60482]312 uint16_t const uLoValue1 = (uint16_t)uValue1;
313 uint16_t const uHiValue1 = (uint16_t)(uValue1 >> 16);
314 uint16_t const uLoValue2 = (uint16_t)uValue2;
315 uint16_t const uHiValue2 = (uint16_t)(uValue2 >> 16);
316 RTUINT32U uTmp;
[52335]317
318 /* Multiply uLoValue1 and uHiValue1 by uLoValue1. */
[60482]319 pResult->s.Lo = (uint32_t)uLoValue1 * uLoValue2;
[52335]320
[60482]321 uTmp.u = (uint32_t)uHiValue1 * uLoValue2;
322 pResult->Words.w3 = 0;
323 pResult->Words.w2 = uTmp.Words.w1;
324 pResult->Words.w1 += uTmp.Words.w0;
325 if (pResult->Words.w1 < uTmp.Words.w0)
326 if (pResult->Words.w2++ == UINT16_MAX)
327 pResult->Words.w3++;
[52335]328
329 /* Multiply uLoValue1 and uHiValue1 by uHiValue2. */
[60482]330 uTmp.u = (uint32_t)uLoValue1 * uHiValue2;
331 pResult->Words.w1 += uTmp.Words.w0;
332 if (pResult->Words.w1 < uTmp.Words.w0)
333 if (pResult->Words.w2++ == UINT16_MAX)
334 pResult->Words.w3++;
[52335]335
[60482]336 pResult->Words.w2 += uTmp.Words.w1;
337 if (pResult->Words.w2 < uTmp.Words.w1)
338 pResult->Words.w3++;
[52335]339
[60482]340 pResult->s.Hi += (uint32_t)uHiValue1 * uHiValue2;
[52335]341 return pResult;
342}
343
344
[60482]345DECLINLINE(PRTUINT64U) RTUInt64DivRem(PRTUINT64U pQuotient, PRTUINT64U pRemainder, PCRTUINT64U pValue1, PCRTUINT64U pValue2);
[98498]346DECLINLINE(PRTUINT64U) RTUInt64DivRemSigned(PRTUINT64U pQuotient, PRTUINT64U pRemainder, PCRTUINT64U pValue1, PCRTUINT64U pValue2);
[52335]347
348/**
[60482]349 * Divides a 64-bit unsigned integer value by another.
[52335]350 *
351 * @returns pResult
352 * @param pResult The result variable.
353 * @param pValue1 The dividend value.
354 * @param pValue2 The divisor value.
355 */
[60482]356DECLINLINE(PRTUINT64U) RTUInt64Div(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[52335]357{
[60482]358 RTUINT64U Ignored;
359 return RTUInt64DivRem(pResult, &Ignored, pValue1, pValue2);
[52335]360}
361
362
363/**
[60482]364 * Divides a 64-bit unsigned integer value by another, returning the remainder.
[52335]365 *
366 * @returns pResult
367 * @param pResult The result variable (remainder).
368 * @param pValue1 The dividend value.
369 * @param pValue2 The divisor value.
370 */
[60482]371DECLINLINE(PRTUINT64U) RTUInt64Mod(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[52335]372{
[60482]373 RTUINT64U Ignored;
374 RTUInt64DivRem(&Ignored, pResult, pValue1, pValue2);
[52335]375 return pResult;
376}
377
378
379/**
[98498]380 * Divides a 64-bit signed integer value by another.
381 *
382 * @returns pResult
383 * @param pResult The result variable.
384 * @param pValue1 The dividend value.
385 * @param pValue2 The divisor value.
386 */
387DECLINLINE(PRTUINT64U) RTUInt64DivSigned(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
388{
389 RTUINT64U Ignored;
390 return RTUInt64DivRemSigned(pResult, &Ignored, pValue1, pValue2);
391}
392
393
394/**
395 * Divides a 64-bit unsigned integer value by another, returning the remainder.
396 *
397 * @returns pResult
398 * @param pResult The result variable (remainder).
399 * @param pValue1 The dividend value.
400 * @param pValue2 The divisor value.
401 */
402DECLINLINE(PRTUINT64U) RTUInt64ModSigned(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
403{
404 RTUINT64U Ignored;
405 RTUInt64DivRemSigned(&Ignored, pResult, pValue1, pValue2);
406 return pResult;
407}
408
409
410/**
[60482]411 * Bitwise AND of two 64-bit unsigned integer values.
[52335]412 *
413 * @returns pResult
414 * @param pResult The result variable.
415 * @param pValue1 The first value.
416 * @param pValue2 The second value.
417 */
[60482]418DECLINLINE(PRTUINT64U) RTUInt64And(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[52335]419{
420 pResult->s.Hi = pValue1->s.Hi & pValue2->s.Hi;
421 pResult->s.Lo = pValue1->s.Lo & pValue2->s.Lo;
422 return pResult;
423}
424
425
426/**
[60482]427 * Bitwise OR of two 64-bit unsigned integer values.
[52335]428 *
429 * @returns pResult
430 * @param pResult The result variable.
431 * @param pValue1 The first value.
432 * @param pValue2 The second value.
433 */
[60482]434DECLINLINE(PRTUINT64U) RTUInt64Or( PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[52335]435{
436 pResult->s.Hi = pValue1->s.Hi | pValue2->s.Hi;
437 pResult->s.Lo = pValue1->s.Lo | pValue2->s.Lo;
438 return pResult;
439}
440
441
442/**
[60482]443 * Bitwise XOR of two 64-bit unsigned integer values.
[52335]444 *
445 * @returns pResult
446 * @param pResult The result variable.
447 * @param pValue1 The first value.
448 * @param pValue2 The second value.
449 */
[60482]450DECLINLINE(PRTUINT64U) RTUInt64Xor(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[52335]451{
452 pResult->s.Hi = pValue1->s.Hi ^ pValue2->s.Hi;
453 pResult->s.Lo = pValue1->s.Lo ^ pValue2->s.Lo;
454 return pResult;
455}
456
457
458/**
[60482]459 * Shifts a 64-bit unsigned integer value @a cBits to the left.
[52335]460 *
461 * @returns pResult
462 * @param pResult The result variable.
463 * @param pValue The value to shift.
464 * @param cBits The number of bits to shift it.
465 */
[60482]466DECLINLINE(PRTUINT64U) RTUInt64ShiftLeft(PRTUINT64U pResult, PCRTUINT64U pValue, int cBits)
[52335]467{
[60482]468 cBits &= 63;
469 if (cBits < 32)
[52335]470 {
471 pResult->s.Lo = pValue->s.Lo << cBits;
[60482]472 pResult->s.Hi = (pValue->s.Hi << cBits) | (pValue->s.Lo >> (32 - cBits));
[52335]473 }
474 else
475 {
476 pResult->s.Lo = 0;
[60482]477 pResult->s.Hi = pValue->s.Lo << (cBits - 32);
[52335]478 }
479 return pResult;
480}
481
482
483/**
[60482]484 * Shifts a 64-bit unsigned integer value @a cBits to the right.
[52335]485 *
486 * @returns pResult
487 * @param pResult The result variable.
488 * @param pValue The value to shift.
489 * @param cBits The number of bits to shift it.
490 */
[60482]491DECLINLINE(PRTUINT64U) RTUInt64ShiftRight(PRTUINT64U pResult, PCRTUINT64U pValue, int cBits)
[52335]492{
[60482]493 cBits &= 63;
494 if (cBits < 32)
[52335]495 {
496 pResult->s.Hi = pValue->s.Hi >> cBits;
[60482]497 pResult->s.Lo = (pValue->s.Lo >> cBits) | (pValue->s.Hi << (32 - cBits));
[52335]498 }
499 else
500 {
501 pResult->s.Hi = 0;
[60482]502 pResult->s.Lo = pValue->s.Hi >> (cBits - 32);
[52335]503 }
504 return pResult;
505}
506
507
508/**
509 * Boolean not (result 0 or 1).
510 *
511 * @returns pResult.
512 * @param pResult The result variable.
513 * @param pValue The value.
514 */
[60482]515DECLINLINE(PRTUINT64U) RTUInt64BooleanNot(PRTUINT64U pResult, PCRTUINT64U pValue)
[52335]516{
[60482]517 pResult->s.Lo = pValue->s.Lo || pValue->s.Hi ? 0 : 1;
[52335]518 pResult->s.Hi = 0;
519 return pResult;
520}
521
522
523/**
[60482]524 * Bitwise not (flips each bit of the 64 bits).
[52335]525 *
526 * @returns pResult.
527 * @param pResult The result variable.
528 * @param pValue The value.
529 */
[60482]530DECLINLINE(PRTUINT64U) RTUInt64BitwiseNot(PRTUINT64U pResult, PCRTUINT64U pValue)
[52335]531{
532 pResult->s.Hi = ~pValue->s.Hi;
533 pResult->s.Lo = ~pValue->s.Lo;
534 return pResult;
535}
536
537
538/**
[60482]539 * Assigns one 64-bit unsigned integer value to another.
[35488]540 *
541 * @returns pResult
542 * @param pResult The result variable.
543 * @param pValue The value to assign.
544 */
[60482]545DECLINLINE(PRTUINT64U) RTUInt64Assign(PRTUINT64U pResult, PCRTUINT64U pValue)
[35488]546{
[60482]547#if ARCH_BITS >= 32
[35488]548 pResult->s.Hi = pValue->s.Hi;
549 pResult->s.Lo = pValue->s.Lo;
550#else
[60482]551 pResult->Words.w0 = pValue->Words.w0;
552 pResult->Words.w1 = pValue->Words.w1;
553 pResult->Words.w2 = pValue->Words.w2;
554 pResult->Words.w3 = pValue->Words.w3;
[35488]555#endif
556 return pResult;
557}
558
559
560/**
[60482]561 * Assigns a boolean value to 64-bit unsigned integer.
[35488]562 *
[57944]563 * @returns pValueResult
564 * @param pValueResult The result variable.
[35488]565 * @param fValue The boolean value.
566 */
[60482]567DECLINLINE(PRTUINT64U) RTUInt64AssignBoolean(PRTUINT64U pValueResult, bool fValue)
[35488]568{
[60482]569#if ARCH_BITS >= 32
[35488]570 pValueResult->s.Lo = fValue;
571 pValueResult->s.Hi = 0;
572#else
[60482]573 pValueResult->Words.w0 = fValue;
574 pValueResult->Words.w1 = 0;
575 pValueResult->Words.w2 = 0;
576 pValueResult->Words.w3 = 0;
[35488]577#endif
578 return pValueResult;
579}
580
581
582/**
[60482]583 * Assigns a 8-bit unsigned integer value to 64-bit unsigned integer.
[35488]584 *
[57944]585 * @returns pValueResult
586 * @param pValueResult The result variable.
[35488]587 * @param u8Value The 8-bit unsigned integer value.
588 */
[60482]589DECLINLINE(PRTUINT64U) RTUInt64AssignU8(PRTUINT64U pValueResult, uint8_t u8Value)
[35488]590{
[60482]591#if ARCH_BITS >= 32
[35488]592 pValueResult->s.Lo = u8Value;
593 pValueResult->s.Hi = 0;
594#else
[60482]595 pValueResult->Words.w0 = u8Value;
596 pValueResult->Words.w1 = 0;
597 pValueResult->Words.w2 = 0;
598 pValueResult->Words.w3 = 0;
[35488]599#endif
600 return pValueResult;
601}
602
603
604/**
[60482]605 * Assigns a 16-bit unsigned integer value to 64-bit unsigned integer.
[35488]606 *
[57944]607 * @returns pValueResult
608 * @param pValueResult The result variable.
[35488]609 * @param u16Value The 16-bit unsigned integer value.
610 */
[60482]611DECLINLINE(PRTUINT64U) RTUInt64AssignU16(PRTUINT64U pValueResult, uint16_t u16Value)
[35488]612{
[60482]613#if ARCH_BITS >= 32
[35488]614 pValueResult->s.Lo = u16Value;
615 pValueResult->s.Hi = 0;
616#else
[60482]617 pValueResult->Words.w0 = u16Value;
618 pValueResult->Words.w1 = 0;
619 pValueResult->Words.w2 = 0;
620 pValueResult->Words.w3 = 0;
[35488]621#endif
622 return pValueResult;
623}
624
625
626/**
[60482]627 * Assigns a 32-bit unsigned integer value to 64-bit unsigned integer.
[35488]628 *
[57944]629 * @returns pValueResult
630 * @param pValueResult The result variable.
[35488]631 * @param u32Value The 32-bit unsigned integer value.
632 */
[60482]633DECLINLINE(PRTUINT64U) RTUInt64AssignU32(PRTUINT64U pValueResult, uint32_t u32Value)
[35488]634{
[60482]635#if ARCH_BITS >= 32
[35488]636 pValueResult->s.Lo = u32Value;
637 pValueResult->s.Hi = 0;
638#else
[60482]639 pValueResult->Words.w0 = (uint16_t)u32Value;
640 pValueResult->Words.w1 = u32Value >> 16;
641 pValueResult->Words.w2 = 0;
642 pValueResult->Words.w3 = 0;
[35488]643#endif
644 return pValueResult;
645}
646
647
648/**
[60482]649 * Adds two 64-bit unsigned integer values, storing the result in the first.
[35488]650 *
[52335]651 * @returns pValue1Result.
652 * @param pValue1Result The first value and result.
653 * @param pValue2 The second value.
654 */
[60482]655DECLINLINE(PRTUINT64U) RTUInt64AssignAdd(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
[52335]656{
[60482]657 uint32_t const uTmp = pValue1Result->s.Lo;
[52335]658 pValue1Result->s.Lo += pValue2->s.Lo;
659 if (pValue1Result->s.Lo < uTmp)
660 pValue1Result->s.Hi++;
661 pValue1Result->s.Hi += pValue2->s.Hi;
662 return pValue1Result;
663}
[35488]664
665
666/**
[60482]667 * Subtracts two 64-bit unsigned integer values, storing the result in the
[52335]668 * first.
669 *
670 * @returns pValue1Result.
671 * @param pValue1Result The minuend value and result.
672 * @param pValue2 The subtrahend value.
673 */
[60482]674DECLINLINE(PRTUINT64U) RTUInt64AssignSub(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
[52335]675{
[60482]676 uint32_t const uTmp = pValue1Result->s.Lo;
[52335]677 pValue1Result->s.Lo -= pValue2->s.Lo;
678 if (pValue1Result->s.Lo > uTmp)
679 pValue1Result->s.Hi--;
680 pValue1Result->s.Hi -= pValue2->s.Hi;
681 return pValue1Result;
682}
683
684
685/**
[98498]686 * Negates a 64-bit unsigned integer value, returning the result in place.
687 *
688 * @returns pValueResult.
689 * @param pValueResult The value and result.
690 */
691DECLINLINE(PRTUINT64U) RTUInt64AssignNeg(PRTUINT64U pValueResult)
692{
693 pValueResult->s.Lo = UINT32_C(0) - pValueResult->s.Lo;
694 pValueResult->s.Hi = UINT32_C(0) - pValueResult->s.Hi;
695 if (pValueResult->s.Lo > UINT32_C(0))
696 pValueResult->s.Hi--;
697 return pValueResult;
698}
699
700
701/**
[60482]702 * Multiplies two 64-bit unsigned integer values, storing the result in the
[52335]703 * first.
704 *
705 * @returns pValue1Result.
706 * @param pValue1Result The first value and result.
707 * @param pValue2 The second value.
708 */
[60482]709DECLINLINE(PRTUINT64U) RTUInt64AssignMul(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
[52335]710{
[60482]711 RTUINT64U Result;
712 RTUInt64Mul(&Result, pValue1Result, pValue2);
[52335]713 *pValue1Result = Result;
714 return pValue1Result;
715}
716
717
718/**
[60482]719 * Divides a 64-bit unsigned integer value by another, storing the result in
[52335]720 * the first.
721 *
722 * @returns pValue1Result.
723 * @param pValue1Result The dividend value and result.
724 * @param pValue2 The divisor value.
725 */
[60482]726DECLINLINE(PRTUINT64U) RTUInt64AssignDiv(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
[52335]727{
[60482]728 RTUINT64U Result;
729 RTUINT64U Ignored;
730 RTUInt64DivRem(&Result, &Ignored, pValue1Result, pValue2);
[52335]731 *pValue1Result = Result;
732 return pValue1Result;
733}
734
735
736/**
[60482]737 * Divides a 64-bit unsigned integer value by another, storing the remainder in
[52335]738 * the first.
739 *
740 * @returns pValue1Result.
741 * @param pValue1Result The dividend value and result (remainder).
742 * @param pValue2 The divisor value.
743 */
[60482]744DECLINLINE(PRTUINT64U) RTUInt64AssignMod(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
[52335]745{
[60482]746 RTUINT64U Ignored;
747 RTUINT64U Result;
748 RTUInt64DivRem(&Ignored, &Result, pValue1Result, pValue2);
[52335]749 *pValue1Result = Result;
750 return pValue1Result;
751}
752
753
754/**
[60482]755 * Performs a bitwise AND of two 64-bit unsigned integer values and assigned
[35488]756 * the result to the first one.
757 *
758 * @returns pValue1Result.
759 * @param pValue1Result The first value and result.
760 * @param pValue2 The second value.
761 */
[60482]762DECLINLINE(PRTUINT64U) RTUInt64AssignAnd(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
[35488]763{
[60482]764#if ARCH_BITS >= 32
[35488]765 pValue1Result->s.Hi &= pValue2->s.Hi;
766 pValue1Result->s.Lo &= pValue2->s.Lo;
767#else
[60482]768 pValue1Result->Words.w0 &= pValue2->Words.w0;
769 pValue1Result->Words.w1 &= pValue2->Words.w1;
770 pValue1Result->Words.w2 &= pValue2->Words.w2;
771 pValue1Result->Words.w3 &= pValue2->Words.w3;
[35488]772#endif
773 return pValue1Result;
774}
775
776
777/**
[60482]778 * Performs a bitwise AND of a 64-bit unsigned integer value and a mask made
779 * up of the first N bits, assigning the result to the the 64-bit value.
[35490]780 *
781 * @returns pValueResult.
782 * @param pValueResult The value and result.
783 * @param cBits The number of bits to AND (counting from the first
784 * bit).
785 */
[60482]786DECLINLINE(PRTUINT64U) RTUInt64AssignAndNFirstBits(PRTUINT64U pValueResult, unsigned cBits)
[35490]787{
[60482]788 if (cBits <= 32)
[35490]789 {
[60482]790 if (cBits != 32)
791 pValueResult->s.Lo &= (RT_BIT_32(cBits) - 1);
[35490]792 pValueResult->s.Hi = 0;
793 }
[60482]794 else if (cBits < 64)
795 pValueResult->s.Hi &= (RT_BIT_32(cBits - 32) - 1);
[35490]796 return pValueResult;
797}
798
799
800/**
[60482]801 * Performs a bitwise OR of two 64-bit unsigned integer values and assigned
[35488]802 * the result to the first one.
803 *
804 * @returns pValue1Result.
805 * @param pValue1Result The first value and result.
806 * @param pValue2 The second value.
807 */
[60482]808DECLINLINE(PRTUINT64U) RTUInt64AssignOr(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
[35488]809{
[60482]810#if ARCH_BITS >= 32
[35488]811 pValue1Result->s.Hi |= pValue2->s.Hi;
812 pValue1Result->s.Lo |= pValue2->s.Lo;
813#else
[60482]814 pValue1Result->Words.w0 |= pValue2->Words.w0;
815 pValue1Result->Words.w1 |= pValue2->Words.w1;
816 pValue1Result->Words.w2 |= pValue2->Words.w2;
817 pValue1Result->Words.w3 |= pValue2->Words.w3;
[35488]818#endif
819 return pValue1Result;
820}
821
822
823/**
[52335]824 * ORs in a bit and assign the result to the input value.
825 *
826 * @returns pValue1Result.
827 * @param pValue1Result The first value and result.
828 * @param iBit The bit to set (0 based).
829 */
[60482]830DECLINLINE(PRTUINT64U) RTUInt64AssignOrBit(PRTUINT64U pValue1Result, unsigned iBit)
[52335]831{
[60482]832#if ARCH_BITS >= 32
833 if (iBit >= 32)
834 pValue1Result->s.Hi |= RT_BIT_32(iBit - 32);
[52335]835 else
[60482]836 pValue1Result->s.Lo |= RT_BIT_32(iBit);
[52335]837#else
[60482]838 if (iBit >= 32)
[52335]839 {
[60482]840 if (iBit >= 48)
841 pValue1Result->Words.w3 |= UINT16_C(1) << (iBit - 48);
[52335]842 else
[60482]843 pValue1Result->Words.w2 |= UINT16_C(1) << (iBit - 32);
[52335]844 }
845 else
846 {
[60482]847 if (iBit >= 16)
848 pValue1Result->Words.w1 |= UINT16_C(1) << (iBit - 16);
[52335]849 else
[60482]850 pValue1Result->Words.w0 |= UINT16_C(1) << (iBit);
[52335]851 }
852#endif
853 return pValue1Result;
854}
855
856
857
858/**
[60482]859 * Performs a bitwise XOR of two 64-bit unsigned integer values and assigned
[35488]860 * the result to the first one.
861 *
862 * @returns pValue1Result.
863 * @param pValue1Result The first value and result.
864 * @param pValue2 The second value.
865 */
[60482]866DECLINLINE(PRTUINT64U) RTUInt64AssignXor(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
[35488]867{
[60482]868#if ARCH_BITS >= 32
[35488]869 pValue1Result->s.Hi ^= pValue2->s.Hi;
870 pValue1Result->s.Lo ^= pValue2->s.Lo;
871#else
[60482]872 pValue1Result->Words.w0 ^= pValue2->Words.w0;
873 pValue1Result->Words.w1 ^= pValue2->Words.w1;
874 pValue1Result->Words.w2 ^= pValue2->Words.w2;
875 pValue1Result->Words.w3 ^= pValue2->Words.w3;
[35488]876#endif
877 return pValue1Result;
878}
879
880
881/**
[60482]882 * Performs a bitwise left shift on a 64-bit unsigned integer value, assigning
[35488]883 * the result to it.
884 *
[57944]885 * @returns pValueResult.
886 * @param pValueResult The first value and result.
[35488]887 * @param cBits The number of bits to shift.
888 */
[60482]889DECLINLINE(PRTUINT64U) RTUInt64AssignShiftLeft(PRTUINT64U pValueResult, int cBits)
[35488]890{
[60482]891 RTUINT64U const InVal = *pValueResult;
[35488]892 if (cBits > 0)
893 {
894 /* (left shift) */
[98498]895 cBits &= 63;
[60484]896 if (cBits >= 32)
[35488]897 {
898 pValueResult->s.Lo = 0;
[60482]899 pValueResult->s.Hi = InVal.s.Lo << (cBits - 32);
[35488]900 }
901 else
902 {
903 pValueResult->s.Hi = InVal.s.Hi << cBits;
[60482]904 pValueResult->s.Hi |= InVal.s.Lo >> (32 - cBits);
[35488]905 pValueResult->s.Lo = InVal.s.Lo << cBits;
906 }
907 }
908 else if (cBits < 0)
909 {
910 /* (right shift) */
911 cBits = -cBits;
[98498]912 cBits &= 63;
[60484]913 if (cBits >= 32)
[35488]914 {
915 pValueResult->s.Hi = 0;
[60482]916 pValueResult->s.Lo = InVal.s.Hi >> (cBits - 32);
[35488]917 }
918 else
919 {
920 pValueResult->s.Lo = InVal.s.Lo >> cBits;
[60482]921 pValueResult->s.Lo |= InVal.s.Hi << (32 - cBits);
[35488]922 pValueResult->s.Hi = InVal.s.Hi >> cBits;
923 }
924 }
925 return pValueResult;
926}
927
928
929/**
[60482]930 * Performs a bitwise left shift on a 64-bit unsigned integer value, assigning
[35488]931 * the result to it.
932 *
[57944]933 * @returns pValueResult.
934 * @param pValueResult The first value and result.
[35488]935 * @param cBits The number of bits to shift.
936 */
[60482]937DECLINLINE(PRTUINT64U) RTUInt64AssignShiftRight(PRTUINT64U pValueResult, int cBits)
[35488]938{
[60482]939 return RTUInt64AssignShiftLeft(pValueResult, -cBits);
[35488]940}
941
942
943/**
[60482]944 * Performs a bitwise NOT on a 64-bit unsigned integer value, assigning the
[35488]945 * result to it.
946 *
947 * @returns pValueResult
948 * @param pValueResult The value and result.
949 */
[60482]950DECLINLINE(PRTUINT64U) RTUInt64AssignBitwiseNot(PRTUINT64U pValueResult)
[35488]951{
[60482]952#if ARCH_BITS >= 32
[35488]953 pValueResult->s.Hi = ~pValueResult->s.Hi;
954 pValueResult->s.Lo = ~pValueResult->s.Lo;
955#else
[60482]956 pValueResult->Words.w0 = ~pValueResult->Words.w0;
957 pValueResult->Words.w1 = ~pValueResult->Words.w1;
958 pValueResult->Words.w2 = ~pValueResult->Words.w2;
959 pValueResult->Words.w3 = ~pValueResult->Words.w3;
[35488]960#endif
961 return pValueResult;
962}
963
964
965/**
[60482]966 * Performs a boolean NOT on a 64-bit unsigned integer value, assigning the
[35488]967 * result to it.
968 *
969 * @returns pValueResult
970 * @param pValueResult The value and result.
971 */
[60482]972DECLINLINE(PRTUINT64U) RTUInt64AssignBooleanNot(PRTUINT64U pValueResult)
[35488]973{
[60482]974 return RTUInt64AssignBoolean(pValueResult, RTUInt64IsZero(pValueResult));
[35488]975}
976
977
978/**
[60482]979 * Compares two 64-bit unsigned integer values.
[35488]980 *
981 * @retval 0 if equal.
982 * @retval -1 if the first value is smaller than the second.
983 * @retval 1 if the first value is larger than the second.
984 *
985 * @param pValue1 The first value.
986 * @param pValue2 The second value.
987 */
[60482]988DECLINLINE(int) RTUInt64Compare(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[35488]989{
[60482]990#if ARCH_BITS >= 32
[35488]991 if (pValue1->s.Hi != pValue2->s.Hi)
992 return pValue1->s.Hi > pValue2->s.Hi ? 1 : -1;
993 if (pValue1->s.Lo != pValue2->s.Lo)
994 return pValue1->s.Lo > pValue2->s.Lo ? 1 : -1;
995 return 0;
996#else
[60482]997 if (pValue1->Words.w3 != pValue2->Words.w3)
998 return pValue1->Words.w3 > pValue2->Words.w3 ? 1 : -1;
999 if (pValue1->Words.w2 != pValue2->Words.w2)
1000 return pValue1->Words.w2 > pValue2->Words.w2 ? 1 : -1;
1001 if (pValue1->Words.w1 != pValue2->Words.w1)
1002 return pValue1->Words.w1 > pValue2->Words.w1 ? 1 : -1;
1003 if (pValue1->Words.w0 != pValue2->Words.w0)
1004 return pValue1->Words.w0 > pValue2->Words.w0 ? 1 : -1;
[35488]1005 return 0;
1006#endif
1007}
1008
1009
1010/**
[60482]1011 * Tests if a 64-bit unsigned integer value is smaller than another.
[52335]1012 *
1013 * @returns true if the first value is smaller, false if not.
1014 * @param pValue1 The first value.
1015 * @param pValue2 The second value.
1016 */
[60482]1017DECLINLINE(bool) RTUInt64IsSmaller(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[52335]1018{
[60482]1019#if ARCH_BITS >= 32
[52335]1020 return pValue1->s.Hi < pValue2->s.Hi
1021 || ( pValue1->s.Hi == pValue2->s.Hi
1022 && pValue1->s.Lo < pValue2->s.Lo);
1023#else
[60482]1024 return pValue1->Words.w3 < pValue2->Words.w3
1025 || ( pValue1->Words.w3 == pValue2->Words.w3
1026 && ( pValue1->Words.w2 < pValue2->Words.w2
1027 || ( pValue1->Words.w2 == pValue2->Words.w2
1028 && ( pValue1->Words.w1 < pValue2->Words.w1
1029 || ( pValue1->Words.w1 == pValue2->Words.w1
1030 && pValue1->Words.w0 < pValue2->Words.w0)))));
[52335]1031#endif
1032}
1033
1034
1035/**
[60482]1036 * Tests if a 32-bit unsigned integer value is larger than another.
[52335]1037 *
1038 * @returns true if the first value is larger, false if not.
1039 * @param pValue1 The first value.
1040 * @param pValue2 The second value.
1041 */
[60482]1042DECLINLINE(bool) RTUInt64IsLarger(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[52335]1043{
[60482]1044#if ARCH_BITS >= 32
[52335]1045 return pValue1->s.Hi > pValue2->s.Hi
1046 || ( pValue1->s.Hi == pValue2->s.Hi
1047 && pValue1->s.Lo > pValue2->s.Lo);
1048#else
[60482]1049 return pValue1->Words.w3 > pValue2->Words.w3
1050 || ( pValue1->Words.w3 == pValue2->Words.w3
1051 && ( pValue1->Words.w2 > pValue2->Words.w2
1052 || ( pValue1->Words.w2 == pValue2->Words.w2
1053 && ( pValue1->Words.w1 > pValue2->Words.w1
1054 || ( pValue1->Words.w1 == pValue2->Words.w1
1055 && pValue1->Words.w0 > pValue2->Words.w0)))));
[52335]1056#endif
1057}
1058
1059
1060/**
[60482]1061 * Tests if a 64-bit unsigned integer value is larger or equal than another.
[52335]1062 *
1063 * @returns true if the first value is larger or equal, false if not.
1064 * @param pValue1 The first value.
1065 * @param pValue2 The second value.
1066 */
[60482]1067DECLINLINE(bool) RTUInt64IsLargerOrEqual(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[52335]1068{
[60482]1069#if ARCH_BITS >= 32
[52335]1070 return pValue1->s.Hi > pValue2->s.Hi
1071 || ( pValue1->s.Hi == pValue2->s.Hi
1072 && pValue1->s.Lo >= pValue2->s.Lo);
1073#else
[60482]1074 return pValue1->Words.w3 > pValue2->Words.w3
1075 || ( pValue1->Words.w3 == pValue2->Words.w3
1076 && ( pValue1->Words.w2 > pValue2->Words.w2
1077 || ( pValue1->Words.w2 == pValue2->Words.w2
1078 && ( pValue1->Words.w1 > pValue2->Words.w1
1079 || ( pValue1->Words.w1 == pValue2->Words.w1
1080 && pValue1->Words.w0 >= pValue2->Words.w0)))));
[52335]1081#endif
1082}
1083
1084
1085/**
[60482]1086 * Tests if two 64-bit unsigned integer values not equal.
[35488]1087 *
1088 * @returns true if equal, false if not equal.
1089 * @param pValue1 The first value.
1090 * @param pValue2 The second value.
1091 */
[60482]1092DECLINLINE(bool) RTUInt64IsEqual(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[35488]1093{
[60482]1094#if ARCH_BITS >= 32
[35488]1095 return pValue1->s.Hi == pValue2->s.Hi
1096 && pValue1->s.Lo == pValue2->s.Lo;
1097#else
[60482]1098 return pValue1->Words.w0 == pValue2->Words.w0
1099 && pValue1->Words.w1 == pValue2->Words.w1
1100 && pValue1->Words.w2 == pValue2->Words.w2
1101 && pValue1->Words.w3 == pValue2->Words.w3;
[35488]1102#endif
1103}
1104
1105
1106/**
[60482]1107 * Tests if two 64-bit unsigned integer values are not equal.
[35488]1108 *
1109 * @returns true if not equal, false if equal.
1110 * @param pValue1 The first value.
1111 * @param pValue2 The second value.
1112 */
[60482]1113DECLINLINE(bool) RTUInt64IsNotEqual(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[35488]1114{
[60482]1115 return !RTUInt64IsEqual(pValue1, pValue2);
[35488]1116}
1117
1118
1119/**
[60482]1120 * Sets a bit in a 64-bit unsigned integer type.
[35488]1121 *
1122 * @returns pValueResult.
1123 * @param pValueResult The input and output value.
1124 * @param iBit The bit to set.
1125 */
[60482]1126DECLINLINE(PRTUINT64U) RTUInt64BitSet(PRTUINT64U pValueResult, unsigned iBit)
[35488]1127{
[60482]1128 if (iBit < 32)
[35488]1129 {
[60482]1130#if ARCH_BITS >= 32
1131 pValueResult->s.Lo |= RT_BIT_32(iBit);
[35488]1132#else
[60482]1133 if (iBit < 16)
1134 pValueResult->Words.w0 |= UINT16_C(1) << iBit;
[35488]1135 else
[60482]1136 pValueResult->Words.w1 |= UINT16_C(1) << (iBit - 32);
[35488]1137#endif
1138 }
[60482]1139 else if (iBit < 64)
[35488]1140 {
[60482]1141#if ARCH_BITS >= 32
[60484]1142 pValueResult->s.Hi |= RT_BIT_32(iBit - 32);
[35488]1143#else
[60482]1144 if (iBit < 48)
1145 pValueResult->Words.w2 |= UINT16_C(1) << (iBit - 64);
[35488]1146 else
[60482]1147 pValueResult->Words.w3 |= UINT16_C(1) << (iBit - 96);
[35488]1148#endif
1149 }
1150 return pValueResult;
1151}
1152
1153
1154/**
[60482]1155 * Sets a bit in a 64-bit unsigned integer type.
[35488]1156 *
1157 * @returns pValueResult.
1158 * @param pValueResult The input and output value.
1159 * @param iBit The bit to set.
1160 */
[60482]1161DECLINLINE(PRTUINT64U) RTUInt64BitClear(PRTUINT64U pValueResult, unsigned iBit)
[35488]1162{
[60482]1163 if (iBit < 32)
[35488]1164 {
[60482]1165#if ARCH_BITS >= 32
1166 pValueResult->s.Lo &= ~RT_BIT_32(iBit);
[35488]1167#else
[60482]1168 if (iBit < 48)
1169 pValueResult->Words.w0 &= ~(UINT16_C(1) << (iBit));
[35488]1170 else
[60482]1171 pValueResult->Words.w1 &= ~(UINT16_C(1) << (iBit - 32));
[35488]1172#endif
1173 }
[60482]1174 else if (iBit < 64)
[35488]1175 {
[60482]1176#if ARCH_BITS >= 32
1177 pValueResult->s.Hi &= ~RT_BIT_32(iBit - 32);
[35488]1178#else
[60482]1179 if (iBit < 48)
1180 pValueResult->Words.w2 &= ~(UINT16_C(1) << (iBit - 64));
[35488]1181 else
[60482]1182 pValueResult->Words.w3 &= ~(UINT16_C(1) << (iBit - 96));
[35488]1183#endif
1184 }
1185 return pValueResult;
1186}
1187
1188
1189/**
[60482]1190 * Tests if a bit in a 64-bit unsigned integer value is set.
[35488]1191 *
1192 * @returns pValueResult.
1193 * @param pValueResult The input and output value.
1194 * @param iBit The bit to test.
1195 */
[60482]1196DECLINLINE(bool) RTUInt64BitTest(PRTUINT64U pValueResult, unsigned iBit)
[35488]1197{
1198 bool fRc;
[60482]1199 if (iBit < 32)
[35488]1200 {
[60482]1201#if ARCH_BITS >= 32
1202 fRc = RT_BOOL(pValueResult->s.Lo & RT_BIT_32(iBit));
[35488]1203#else
[60482]1204 if (iBit < 16)
1205 fRc = RT_BOOL(pValueResult->Words.w0 & (UINT16_C(1) << (iBit)));
[35488]1206 else
[60482]1207 fRc = RT_BOOL(pValueResult->Words.w1 & (UINT16_C(1) << (iBit - 16)));
[35488]1208#endif
1209 }
[60482]1210 else if (iBit < 64)
[35488]1211 {
[60482]1212#if ARCH_BITS >= 32
[60484]1213 fRc = RT_BOOL(pValueResult->s.Hi & RT_BIT_32(iBit - 32));
[35488]1214#else
[60482]1215 if (iBit < 48)
1216 fRc = RT_BOOL(pValueResult->Words.w2 & (UINT16_C(1) << (iBit - 32)));
[35488]1217 else
[60482]1218 fRc = RT_BOOL(pValueResult->Words.w3 & (UINT16_C(1) << (iBit - 48)));
[35488]1219#endif
1220 }
1221 else
1222 fRc = false;
1223 return fRc;
1224}
1225
1226
1227/**
[60482]1228 * Set a range of bits a 64-bit unsigned integer value.
[35488]1229 *
1230 * @returns pValueResult.
1231 * @param pValueResult The input and output value.
1232 * @param iFirstBit The first bit to test.
1233 * @param cBits The number of bits to set.
1234 */
[60482]1235DECLINLINE(PRTUINT64U) RTUInt64BitSetRange(PRTUINT64U pValueResult, unsigned iFirstBit, unsigned cBits)
[35488]1236{
1237 /* bounds check & fix. */
[60482]1238 if (iFirstBit < 64)
[35488]1239 {
[60482]1240 if (iFirstBit + cBits > 64)
1241 cBits = 64 - iFirstBit;
[35488]1242
[60482]1243#if ARCH_BITS >= 32
[35488]1244 if (iFirstBit + cBits < 32)
[60482]1245 pValueResult->s.Lo |= (RT_BIT_32(cBits) - 1) << iFirstBit;
[35488]1246 else if (iFirstBit + cBits < 64 && iFirstBit >= 32)
[60482]1247 pValueResult->s.Hi |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 32);
[35488]1248 else
[60482]1249#else
1250 if (iFirstBit + cBits < 16)
1251 pValueResult->Words.w0 |= ((UINT16_C(1) << cBits) - 1) << iFirstBit;
1252 else if (iFirstBit + cBits < 32 && iFirstBit >= 16)
1253 pValueResult->Words.w1 |= ((UINT16_C(1) << cBits) - 1) << (iFirstBit - 16);
1254 else if (iFirstBit + cBits < 48 && iFirstBit >= 32)
1255 pValueResult->Words.w2 |= ((UINT16_C(1) << cBits) - 1) << (iFirstBit - 32);
1256 else if (iFirstBit + cBits < 64 && iFirstBit >= 48)
1257 pValueResult->Words.w3 |= ((UINT16_C(1) << cBits) - 1) << (iFirstBit - 48);
1258 else
[35488]1259#endif
1260 while (cBits-- > 0)
[60482]1261 RTUInt64BitSet(pValueResult, iFirstBit++);
[35488]1262 }
1263 return pValueResult;
1264}
1265
1266
1267/**
[60482]1268 * Test if all the bits of a 64-bit unsigned integer value are set.
[35488]1269 *
1270 * @returns true if they are, false if they aren't.
1271 * @param pValue The input and output value.
1272 */
[60482]1273DECLINLINE(bool) RTUInt64BitAreAllSet(PRTUINT64U pValue)
[35488]1274{
[60482]1275#if ARCH_BITS >= 32
1276 return pValue->s.Hi == UINT32_MAX
1277 && pValue->s.Lo == UINT32_MAX;
[35488]1278#else
[60482]1279 return pValue->Words.w0 == UINT16_MAX
1280 && pValue->Words.w1 == UINT16_MAX
1281 && pValue->Words.w2 == UINT16_MAX
1282 && pValue->Words.w3 == UINT16_MAX;
[35488]1283#endif
1284}
1285
1286
1287/**
[60482]1288 * Test if all the bits of a 64-bit unsigned integer value are clear.
[35488]1289 *
1290 * @returns true if they are, false if they aren't.
1291 * @param pValue The input and output value.
1292 */
[60482]1293DECLINLINE(bool) RTUInt64BitAreAllClear(PRTUINT64U pValue)
[35488]1294{
[60482]1295 return RTUInt64IsZero(pValue);
[35488]1296}
1297
[52335]1298
[60482]1299DECLINLINE(unsigned) RTUInt64BitCount(PCRTUINT64U pValue)
[52335]1300{
[60482]1301 unsigned cBits;
[52335]1302 if (pValue->s.Hi != 0)
1303 {
[60482]1304#if ARCH_BITS >= 32
1305 cBits = 32 + ASMBitLastSetU32(pValue->s.Hi);
1306#else
1307 if (pValue->Words.w3)
1308 cBits = 48 + ASMBitLastSetU16(pValue->Words.w3);
[52335]1309 else
[60482]1310 cBits = 32 + ASMBitLastSetU16(pValue->Words.w2);
1311#endif
[52335]1312 }
1313 else
1314 {
[60482]1315#if ARCH_BITS >= 32
1316 cBits = ASMBitLastSetU32(pValue->s.Lo);
1317#else
1318 if (pValue->Words.w1)
1319 cBits = 16 + ASMBitLastSetU16(pValue->Words.w1);
[52335]1320 else
[60482]1321 cBits = 0 + ASMBitLastSetU16(pValue->Words.w0);
1322#endif
[52335]1323 }
1324 return cBits;
1325}
1326
1327
1328/**
[60482]1329 * Divides a 64-bit unsigned integer value by another, returning both quotient
[52335]1330 * and remainder.
1331 *
1332 * @returns pQuotient, NULL if pValue2 is 0.
1333 * @param pQuotient Where to return the quotient.
1334 * @param pRemainder Where to return the remainder.
1335 * @param pValue1 The dividend value.
1336 * @param pValue2 The divisor value.
1337 */
[60482]1338DECLINLINE(PRTUINT64U) RTUInt64DivRem(PRTUINT64U pQuotient, PRTUINT64U pRemainder, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
[52335]1339{
1340 int iDiff;
1341
1342 /*
1343 * Sort out all the special cases first.
1344 */
1345 /* Divide by zero or 1? */
1346 if (!pValue2->s.Hi)
1347 {
1348 if (!pValue2->s.Lo)
1349 return NULL;
1350
1351 if (pValue2->s.Lo == 1)
1352 {
[60482]1353 RTUInt64SetZero(pRemainder);
[52335]1354 *pQuotient = *pValue1;
1355 return pQuotient;
1356 }
[60482]1357 /** @todo RTUInt64DivModByU32 */
[52335]1358 }
1359
1360 /* Dividend is smaller? */
[60482]1361 iDiff = RTUInt64Compare(pValue1, pValue2);
[52335]1362 if (iDiff < 0)
1363 {
1364 *pRemainder = *pValue1;
[60482]1365 RTUInt64SetZero(pQuotient);
[52335]1366 }
1367
1368 /* The values are equal? */
1369 else if (iDiff == 0)
1370 {
[60482]1371 RTUInt64SetZero(pRemainder);
1372 RTUInt64AssignU8(pQuotient, 1);
[52335]1373 }
1374 else
1375 {
1376 /*
1377 * Prepare.
1378 */
[60482]1379 unsigned iBitAdder = RTUInt64BitCount(pValue1) - RTUInt64BitCount(pValue2);
1380 RTUINT64U NormDivisor = *pValue2;
[52335]1381 if (iBitAdder)
1382 {
[60482]1383 RTUInt64ShiftLeft(&NormDivisor, pValue2, iBitAdder);
1384 if (RTUInt64IsLarger(&NormDivisor, pValue1))
[52335]1385 {
[60482]1386 RTUInt64AssignShiftRight(&NormDivisor, 1);
[52335]1387 iBitAdder--;
1388 }
1389 }
1390 else
1391 NormDivisor = *pValue2;
1392
[60482]1393 RTUInt64SetZero(pQuotient);
[52335]1394 *pRemainder = *pValue1;
1395
1396 /*
1397 * Do the division.
1398 */
[60482]1399 if (RTUInt64IsLargerOrEqual(pRemainder, pValue2))
[52335]1400 {
1401 for (;;)
1402 {
[60482]1403 if (RTUInt64IsLargerOrEqual(pRemainder, &NormDivisor))
[52335]1404 {
[60482]1405 RTUInt64AssignSub(pRemainder, &NormDivisor);
1406 RTUInt64AssignOrBit(pQuotient, iBitAdder);
[52335]1407 }
[60482]1408 if (RTUInt64IsSmaller(pRemainder, pValue2))
[52335]1409 break;
[60482]1410 RTUInt64AssignShiftRight(&NormDivisor, 1);
[52335]1411 iBitAdder--;
1412 }
1413 }
1414 }
1415 return pQuotient;
1416}
1417
1418
[98498]1419/**
1420 * Divides a 64-bit signed integer value by another, returning both quotient and
1421 * remainder.
1422 *
1423 * @returns pQuotient, NULL if pValue2 is 0.
1424 * @param pQuotient Where to return the quotient.
1425 * @param pRemainder Where to return the remainder.
1426 * @param pValue1 The dividend value.
1427 * @param pValue2 The divisor value.
1428 */
1429DECLINLINE(PRTUINT64U) RTUInt64DivRemSigned(PRTUINT64U pQuotient, PRTUINT64U pRemainder, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
1430{
1431 /*
1432 * If both values are positive, we can do a straight unsigned division.
1433 */
1434 if (!RTUInt64IsSigned(pValue1))
1435 {
1436 if (!RTUInt64IsSigned(pValue2))
1437 return RTUInt64DivRem(pQuotient, pRemainder, pValue1, pValue2);
1438
1439 /*
1440 * Negative divisor, Positive dividend:
1441 * negate the divisor, do unsigned division, and negate the quotient.
1442 */
1443 {
1444 RTUINT64U NegDivisor;
1445 RTUInt64DivRem(pQuotient, pRemainder, pValue1, RTUInt64Neg(&NegDivisor, pValue2));
1446 RTUInt64AssignNeg(pQuotient);
1447 }
1448 }
1449 else
1450 {
1451 /* Negate the dividend to get a positive value. */
1452 RTUINT64U NegDividend;
1453 RTUInt64Neg(&NegDividend, pValue1);
1454
1455 if (!RTUInt64IsSigned(pValue2))
1456 {
1457 /*
1458 * Negative dividend, positive divisor:
1459 * Negate the dividend (above), do unsigned division, and negate both quotient and remainder
1460 */
1461 RTUInt64DivRem(pQuotient, pRemainder, &NegDividend, pValue2);
1462 RTUInt64AssignNeg(pQuotient);
1463 }
1464 else
1465 {
1466 /*
1467 * Negative dividend, negative divisor:
1468 * Negate both dividend (above) and divisor, do unsigned division, and negate the remainder.
1469 */
1470 RTUINT64U NegDivisor;
1471 RTUInt64DivRem(pQuotient, pRemainder, &NegDividend, RTUInt64Neg(&NegDivisor, pValue2));
1472 }
1473 RTUInt64AssignNeg(pRemainder);
1474 }
1475 return pQuotient;
1476}
1477
1478
[35488]1479/** @} */
1480
1481RT_C_DECLS_END
1482
[76585]1483#endif /* !IPRT_INCLUDED_uint64_h */
[35488]1484
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use