VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 7 weeks ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 41.9 KB
Line 
1/** @file
2 * IPRT - RTUINT64U methods for old 32-bit and 16-bit compilers.
3 */
4
5/*
6 * Copyright (C) 2011-2024 Oracle and/or its affiliates.
7 *
8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
10 *
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 *
24 * The contents of this file may alternatively be used under the terms
25 * of the Common Development and Distribution License Version 1.0
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
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.
32 *
33 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
34 */
35
36#ifndef IPRT_INCLUDED_uint64_h
37#define IPRT_INCLUDED_uint64_h
38#ifndef RT_WITHOUT_PRAGMA_ONCE
39# pragma once
40#endif
41
42#include <iprt/cdefs.h>
43#include <iprt/types.h>
44#include <iprt/asm.h>
45
46RT_C_DECLS_BEGIN
47
48/** @defgroup grp_rt_uint64 RTUInt64 - 64-bit Unsigned Integer Methods for ancient compilers
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.
58 * @param pValue The value to examine.
59 */
60DECLINLINE(bool) RTUInt64IsZero(PCRTUINT64U pValue)
61{
62#if ARCH_BITS >= 32
63 return pValue->s.Lo == 0
64 && pValue->s.Hi == 0;
65#else
66 return pValue->Words.w0 == 0
67 && pValue->Words.w1 == 0
68 && pValue->Words.w2 == 0
69 && pValue->Words.w3 == 0;
70#endif
71}
72
73
74/**
75 * Checks if the sign-bit is set.
76 *
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/**
91 * Set a 128-bit unsigned integer value to zero.
92 *
93 * @returns pResult
94 * @param pResult The result variable.
95 */
96DECLINLINE(PRTUINT64U) RTUInt64SetZero(PRTUINT64U pResult)
97{
98#if ARCH_BITS >= 32
99 pResult->s.Hi = 0;
100 pResult->s.Lo = 0;
101#else
102 pResult->Words.w0 = 0;
103 pResult->Words.w1 = 0;
104 pResult->Words.w2 = 0;
105 pResult->Words.w3 = 0;
106#endif
107 return pResult;
108}
109
110
111/**
112 * Set a 32-bit unsigned integer value to the maximum value.
113 *
114 * @returns pResult
115 * @param pResult The result variable.
116 */
117DECLINLINE(PRTUINT64U) RTUInt64SetMax(PRTUINT64U pResult)
118{
119#if ARCH_BITS >= 32
120 pResult->s.Hi = UINT32_MAX;
121 pResult->s.Lo = UINT32_MAX;
122#else
123 pResult->Words.w0 = UINT16_MAX;
124 pResult->Words.w1 = UINT16_MAX;
125 pResult->Words.w2 = UINT16_MAX;
126 pResult->Words.w3 = UINT16_MAX;
127#endif
128 return pResult;
129}
130
131
132
133
134/**
135 * Adds two 64-bit unsigned integer values.
136 *
137 * @returns pResult
138 * @param pResult The result variable.
139 * @param pValue1 The first value.
140 * @param pValue2 The second value.
141 */
142DECLINLINE(PRTUINT64U) RTUInt64Add(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
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/**
153 * Adds a 64-bit and a 32-bit unsigned integer values.
154 *
155 * @returns pResult
156 * @param pResult The result variable.
157 * @param pValue1 The first value.
158 * @param uValue2 The second value, 32-bit.
159 */
160DECLINLINE(PRTUINT64U) RTUInt64AddU32(PRTUINT64U pResult, PCRTUINT64U pValue1, uint32_t uValue2)
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/**
171 * Subtracts a 64-bit unsigned integer value from another.
172 *
173 * @returns pResult
174 * @param pResult The result variable.
175 * @param pValue1 The minuend value.
176 * @param pValue2 The subtrahend value.
177 */
178DECLINLINE(PRTUINT64U) RTUInt64Sub(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
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/**
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/**
206 * Multiplies two 64-bit unsigned integer values.
207 *
208 * @returns pResult
209 * @param pResult The result variable.
210 * @param pValue1 The first value.
211 * @param pValue2 The second value.
212 */
213DECLINLINE(PRTUINT64U) RTUInt64Mul(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
214{
215 RTUINT32U uTmp;
216
217 /* multiply all words in v1 by v2.w0. */
218 pResult->s.Lo = (uint32_t)pValue1->Words.w0 * pValue2->Words.w0;
219
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++;
227
228 pResult->s.Hi += (uint32_t)pValue1->Words.w2 * pValue2->Words.w0;
229 pResult->Words.w3 += pValue1->Words.w3 * pValue2->Words.w0;
230
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++;
237
238 pResult->Words.w2 += uTmp.Words.w1;
239 if (pResult->Words.w2 < uTmp.Words.w1)
240 pResult->Words.w3++;
241
242 pResult->s.Hi += (uint32_t)pValue1->Words.w1 * pValue2->Words.w1;
243 pResult->Words.w3 += pValue1->Words.w2 * pValue2->Words.w1;
244
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;
248
249 /* multiply w0 in v1 by v2.w3. */
250 pResult->Words.w3 += pValue1->Words.w0 * pValue2->Words.w3;
251
252 return pResult;
253}
254
255
256/**
257 * Multiplies an 64-bit unsigned integer by a 32-bit unsigned integer value.
258 *
259 * @returns pResult
260 * @param pResult The result variable.
261 * @param pValue1 The first value.
262 * @param uValue2 The second value, 32-bit.
263 */
264DECLINLINE(PRTUINT64U) RTUInt64MulByU32(PRTUINT64U pResult, PCRTUINT64U pValue1, uint32_t uValue2)
265{
266 uint16_t const uLoValue2 = (uint16_t)uValue2;
267 uint16_t const uHiValue2 = (uint16_t)(uValue2 >> 16);
268 RTUINT32U uTmp;
269
270 /* multiply all words in v1 by uLoValue1. */
271 pResult->s.Lo = (uint32_t)pValue1->Words.w0 * uLoValue2;
272
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++;
280
281 pResult->s.Hi += (uint32_t)pValue1->Words.w2 * uLoValue2;
282 pResult->Words.w3 += pValue1->Words.w3 * uLoValue2;
283
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++;
290
291 pResult->Words.w2 += uTmp.Words.w1;
292 if (pResult->Words.w2 < uTmp.Words.w1)
293 pResult->Words.w3++;
294
295 pResult->s.Hi += (uint32_t)pValue1->Words.w1 * uHiValue2;
296 pResult->Words.w3 += pValue1->Words.w2 * uHiValue2;
297
298 return pResult;
299}
300
301
302/**
303 * Multiplies two 32-bit unsigned integer values with 64-bit precision.
304 *
305 * @returns pResult
306 * @param pResult The result variable.
307 * @param uValue1 The first value. 32-bit.
308 * @param uValue2 The second value, 32-bit.
309 */
310DECLINLINE(PRTUINT64U) RTUInt64MulU32ByU32(PRTUINT64U pResult, uint32_t uValue1, uint32_t uValue2)
311{
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;
317
318 /* Multiply uLoValue1 and uHiValue1 by uLoValue1. */
319 pResult->s.Lo = (uint32_t)uLoValue1 * uLoValue2;
320
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++;
328
329 /* Multiply uLoValue1 and uHiValue1 by uHiValue2. */
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++;
335
336 pResult->Words.w2 += uTmp.Words.w1;
337 if (pResult->Words.w2 < uTmp.Words.w1)
338 pResult->Words.w3++;
339
340 pResult->s.Hi += (uint32_t)uHiValue1 * uHiValue2;
341 return pResult;
342}
343
344
345DECLINLINE(PRTUINT64U) RTUInt64DivRem(PRTUINT64U pQuotient, PRTUINT64U pRemainder, PCRTUINT64U pValue1, PCRTUINT64U pValue2);
346DECLINLINE(PRTUINT64U) RTUInt64DivRemSigned(PRTUINT64U pQuotient, PRTUINT64U pRemainder, PCRTUINT64U pValue1, PCRTUINT64U pValue2);
347
348/**
349 * Divides a 64-bit unsigned integer value by another.
350 *
351 * @returns pResult
352 * @param pResult The result variable.
353 * @param pValue1 The dividend value.
354 * @param pValue2 The divisor value.
355 */
356DECLINLINE(PRTUINT64U) RTUInt64Div(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
357{
358 RTUINT64U Ignored;
359 return RTUInt64DivRem(pResult, &Ignored, pValue1, pValue2);
360}
361
362
363/**
364 * Divides a 64-bit unsigned integer value by another, returning the remainder.
365 *
366 * @returns pResult
367 * @param pResult The result variable (remainder).
368 * @param pValue1 The dividend value.
369 * @param pValue2 The divisor value.
370 */
371DECLINLINE(PRTUINT64U) RTUInt64Mod(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
372{
373 RTUINT64U Ignored;
374 RTUInt64DivRem(&Ignored, pResult, pValue1, pValue2);
375 return pResult;
376}
377
378
379/**
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/**
411 * Bitwise AND of two 64-bit unsigned integer values.
412 *
413 * @returns pResult
414 * @param pResult The result variable.
415 * @param pValue1 The first value.
416 * @param pValue2 The second value.
417 */
418DECLINLINE(PRTUINT64U) RTUInt64And(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
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/**
427 * Bitwise OR of two 64-bit unsigned integer values.
428 *
429 * @returns pResult
430 * @param pResult The result variable.
431 * @param pValue1 The first value.
432 * @param pValue2 The second value.
433 */
434DECLINLINE(PRTUINT64U) RTUInt64Or( PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
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/**
443 * Bitwise XOR of two 64-bit unsigned integer values.
444 *
445 * @returns pResult
446 * @param pResult The result variable.
447 * @param pValue1 The first value.
448 * @param pValue2 The second value.
449 */
450DECLINLINE(PRTUINT64U) RTUInt64Xor(PRTUINT64U pResult, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
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/**
459 * Shifts a 64-bit unsigned integer value @a cBits to the left.
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 */
466DECLINLINE(PRTUINT64U) RTUInt64ShiftLeft(PRTUINT64U pResult, PCRTUINT64U pValue, int cBits)
467{
468 cBits &= 63;
469 if (cBits < 32)
470 {
471 pResult->s.Lo = pValue->s.Lo << cBits;
472 pResult->s.Hi = (pValue->s.Hi << cBits) | (pValue->s.Lo >> (32 - cBits));
473 }
474 else
475 {
476 pResult->s.Lo = 0;
477 pResult->s.Hi = pValue->s.Lo << (cBits - 32);
478 }
479 return pResult;
480}
481
482
483/**
484 * Shifts a 64-bit unsigned integer value @a cBits to the right.
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 */
491DECLINLINE(PRTUINT64U) RTUInt64ShiftRight(PRTUINT64U pResult, PCRTUINT64U pValue, int cBits)
492{
493 cBits &= 63;
494 if (cBits < 32)
495 {
496 pResult->s.Hi = pValue->s.Hi >> cBits;
497 pResult->s.Lo = (pValue->s.Lo >> cBits) | (pValue->s.Hi << (32 - cBits));
498 }
499 else
500 {
501 pResult->s.Hi = 0;
502 pResult->s.Lo = pValue->s.Hi >> (cBits - 32);
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 */
515DECLINLINE(PRTUINT64U) RTUInt64BooleanNot(PRTUINT64U pResult, PCRTUINT64U pValue)
516{
517 pResult->s.Lo = pValue->s.Lo || pValue->s.Hi ? 0 : 1;
518 pResult->s.Hi = 0;
519 return pResult;
520}
521
522
523/**
524 * Bitwise not (flips each bit of the 64 bits).
525 *
526 * @returns pResult.
527 * @param pResult The result variable.
528 * @param pValue The value.
529 */
530DECLINLINE(PRTUINT64U) RTUInt64BitwiseNot(PRTUINT64U pResult, PCRTUINT64U pValue)
531{
532 pResult->s.Hi = ~pValue->s.Hi;
533 pResult->s.Lo = ~pValue->s.Lo;
534 return pResult;
535}
536
537
538/**
539 * Assigns one 64-bit unsigned integer value to another.
540 *
541 * @returns pResult
542 * @param pResult The result variable.
543 * @param pValue The value to assign.
544 */
545DECLINLINE(PRTUINT64U) RTUInt64Assign(PRTUINT64U pResult, PCRTUINT64U pValue)
546{
547#if ARCH_BITS >= 32
548 pResult->s.Hi = pValue->s.Hi;
549 pResult->s.Lo = pValue->s.Lo;
550#else
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;
555#endif
556 return pResult;
557}
558
559
560/**
561 * Assigns a boolean value to 64-bit unsigned integer.
562 *
563 * @returns pValueResult
564 * @param pValueResult The result variable.
565 * @param fValue The boolean value.
566 */
567DECLINLINE(PRTUINT64U) RTUInt64AssignBoolean(PRTUINT64U pValueResult, bool fValue)
568{
569#if ARCH_BITS >= 32
570 pValueResult->s.Lo = fValue;
571 pValueResult->s.Hi = 0;
572#else
573 pValueResult->Words.w0 = fValue;
574 pValueResult->Words.w1 = 0;
575 pValueResult->Words.w2 = 0;
576 pValueResult->Words.w3 = 0;
577#endif
578 return pValueResult;
579}
580
581
582/**
583 * Assigns a 8-bit unsigned integer value to 64-bit unsigned integer.
584 *
585 * @returns pValueResult
586 * @param pValueResult The result variable.
587 * @param u8Value The 8-bit unsigned integer value.
588 */
589DECLINLINE(PRTUINT64U) RTUInt64AssignU8(PRTUINT64U pValueResult, uint8_t u8Value)
590{
591#if ARCH_BITS >= 32
592 pValueResult->s.Lo = u8Value;
593 pValueResult->s.Hi = 0;
594#else
595 pValueResult->Words.w0 = u8Value;
596 pValueResult->Words.w1 = 0;
597 pValueResult->Words.w2 = 0;
598 pValueResult->Words.w3 = 0;
599#endif
600 return pValueResult;
601}
602
603
604/**
605 * Assigns a 16-bit unsigned integer value to 64-bit unsigned integer.
606 *
607 * @returns pValueResult
608 * @param pValueResult The result variable.
609 * @param u16Value The 16-bit unsigned integer value.
610 */
611DECLINLINE(PRTUINT64U) RTUInt64AssignU16(PRTUINT64U pValueResult, uint16_t u16Value)
612{
613#if ARCH_BITS >= 32
614 pValueResult->s.Lo = u16Value;
615 pValueResult->s.Hi = 0;
616#else
617 pValueResult->Words.w0 = u16Value;
618 pValueResult->Words.w1 = 0;
619 pValueResult->Words.w2 = 0;
620 pValueResult->Words.w3 = 0;
621#endif
622 return pValueResult;
623}
624
625
626/**
627 * Assigns a 32-bit unsigned integer value to 64-bit unsigned integer.
628 *
629 * @returns pValueResult
630 * @param pValueResult The result variable.
631 * @param u32Value The 32-bit unsigned integer value.
632 */
633DECLINLINE(PRTUINT64U) RTUInt64AssignU32(PRTUINT64U pValueResult, uint32_t u32Value)
634{
635#if ARCH_BITS >= 32
636 pValueResult->s.Lo = u32Value;
637 pValueResult->s.Hi = 0;
638#else
639 pValueResult->Words.w0 = (uint16_t)u32Value;
640 pValueResult->Words.w1 = u32Value >> 16;
641 pValueResult->Words.w2 = 0;
642 pValueResult->Words.w3 = 0;
643#endif
644 return pValueResult;
645}
646
647
648/**
649 * Adds two 64-bit unsigned integer values, storing the result in the first.
650 *
651 * @returns pValue1Result.
652 * @param pValue1Result The first value and result.
653 * @param pValue2 The second value.
654 */
655DECLINLINE(PRTUINT64U) RTUInt64AssignAdd(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
656{
657 uint32_t const uTmp = pValue1Result->s.Lo;
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}
664
665
666/**
667 * Subtracts two 64-bit unsigned integer values, storing the result in the
668 * first.
669 *
670 * @returns pValue1Result.
671 * @param pValue1Result The minuend value and result.
672 * @param pValue2 The subtrahend value.
673 */
674DECLINLINE(PRTUINT64U) RTUInt64AssignSub(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
675{
676 uint32_t const uTmp = pValue1Result->s.Lo;
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/**
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/**
702 * Multiplies two 64-bit unsigned integer values, storing the result in the
703 * first.
704 *
705 * @returns pValue1Result.
706 * @param pValue1Result The first value and result.
707 * @param pValue2 The second value.
708 */
709DECLINLINE(PRTUINT64U) RTUInt64AssignMul(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
710{
711 RTUINT64U Result;
712 RTUInt64Mul(&Result, pValue1Result, pValue2);
713 *pValue1Result = Result;
714 return pValue1Result;
715}
716
717
718/**
719 * Divides a 64-bit unsigned integer value by another, storing the result in
720 * the first.
721 *
722 * @returns pValue1Result.
723 * @param pValue1Result The dividend value and result.
724 * @param pValue2 The divisor value.
725 */
726DECLINLINE(PRTUINT64U) RTUInt64AssignDiv(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
727{
728 RTUINT64U Result;
729 RTUINT64U Ignored;
730 RTUInt64DivRem(&Result, &Ignored, pValue1Result, pValue2);
731 *pValue1Result = Result;
732 return pValue1Result;
733}
734
735
736/**
737 * Divides a 64-bit unsigned integer value by another, storing the remainder in
738 * the first.
739 *
740 * @returns pValue1Result.
741 * @param pValue1Result The dividend value and result (remainder).
742 * @param pValue2 The divisor value.
743 */
744DECLINLINE(PRTUINT64U) RTUInt64AssignMod(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
745{
746 RTUINT64U Ignored;
747 RTUINT64U Result;
748 RTUInt64DivRem(&Ignored, &Result, pValue1Result, pValue2);
749 *pValue1Result = Result;
750 return pValue1Result;
751}
752
753
754/**
755 * Performs a bitwise AND of two 64-bit unsigned integer values and assigned
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 */
762DECLINLINE(PRTUINT64U) RTUInt64AssignAnd(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
763{
764#if ARCH_BITS >= 32
765 pValue1Result->s.Hi &= pValue2->s.Hi;
766 pValue1Result->s.Lo &= pValue2->s.Lo;
767#else
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;
772#endif
773 return pValue1Result;
774}
775
776
777/**
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.
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 */
786DECLINLINE(PRTUINT64U) RTUInt64AssignAndNFirstBits(PRTUINT64U pValueResult, unsigned cBits)
787{
788 if (cBits <= 32)
789 {
790 if (cBits != 32)
791 pValueResult->s.Lo &= (RT_BIT_32(cBits) - 1);
792 pValueResult->s.Hi = 0;
793 }
794 else if (cBits < 64)
795 pValueResult->s.Hi &= (RT_BIT_32(cBits - 32) - 1);
796 return pValueResult;
797}
798
799
800/**
801 * Performs a bitwise OR of two 64-bit unsigned integer values and assigned
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 */
808DECLINLINE(PRTUINT64U) RTUInt64AssignOr(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
809{
810#if ARCH_BITS >= 32
811 pValue1Result->s.Hi |= pValue2->s.Hi;
812 pValue1Result->s.Lo |= pValue2->s.Lo;
813#else
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;
818#endif
819 return pValue1Result;
820}
821
822
823/**
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 */
830DECLINLINE(PRTUINT64U) RTUInt64AssignOrBit(PRTUINT64U pValue1Result, unsigned iBit)
831{
832#if ARCH_BITS >= 32
833 if (iBit >= 32)
834 pValue1Result->s.Hi |= RT_BIT_32(iBit - 32);
835 else
836 pValue1Result->s.Lo |= RT_BIT_32(iBit);
837#else
838 if (iBit >= 32)
839 {
840 if (iBit >= 48)
841 pValue1Result->Words.w3 |= UINT16_C(1) << (iBit - 48);
842 else
843 pValue1Result->Words.w2 |= UINT16_C(1) << (iBit - 32);
844 }
845 else
846 {
847 if (iBit >= 16)
848 pValue1Result->Words.w1 |= UINT16_C(1) << (iBit - 16);
849 else
850 pValue1Result->Words.w0 |= UINT16_C(1) << (iBit);
851 }
852#endif
853 return pValue1Result;
854}
855
856
857
858/**
859 * Performs a bitwise XOR of two 64-bit unsigned integer values and assigned
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 */
866DECLINLINE(PRTUINT64U) RTUInt64AssignXor(PRTUINT64U pValue1Result, PCRTUINT64U pValue2)
867{
868#if ARCH_BITS >= 32
869 pValue1Result->s.Hi ^= pValue2->s.Hi;
870 pValue1Result->s.Lo ^= pValue2->s.Lo;
871#else
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;
876#endif
877 return pValue1Result;
878}
879
880
881/**
882 * Performs a bitwise left shift on a 64-bit unsigned integer value, assigning
883 * the result to it.
884 *
885 * @returns pValueResult.
886 * @param pValueResult The first value and result.
887 * @param cBits The number of bits to shift.
888 */
889DECLINLINE(PRTUINT64U) RTUInt64AssignShiftLeft(PRTUINT64U pValueResult, int cBits)
890{
891 RTUINT64U const InVal = *pValueResult;
892 if (cBits > 0)
893 {
894 /* (left shift) */
895 cBits &= 63;
896 if (cBits >= 32)
897 {
898 pValueResult->s.Lo = 0;
899 pValueResult->s.Hi = InVal.s.Lo << (cBits - 32);
900 }
901 else
902 {
903 pValueResult->s.Hi = InVal.s.Hi << cBits;
904 pValueResult->s.Hi |= InVal.s.Lo >> (32 - cBits);
905 pValueResult->s.Lo = InVal.s.Lo << cBits;
906 }
907 }
908 else if (cBits < 0)
909 {
910 /* (right shift) */
911 cBits = -cBits;
912 cBits &= 63;
913 if (cBits >= 32)
914 {
915 pValueResult->s.Hi = 0;
916 pValueResult->s.Lo = InVal.s.Hi >> (cBits - 32);
917 }
918 else
919 {
920 pValueResult->s.Lo = InVal.s.Lo >> cBits;
921 pValueResult->s.Lo |= InVal.s.Hi << (32 - cBits);
922 pValueResult->s.Hi = InVal.s.Hi >> cBits;
923 }
924 }
925 return pValueResult;
926}
927
928
929/**
930 * Performs a bitwise left shift on a 64-bit unsigned integer value, assigning
931 * the result to it.
932 *
933 * @returns pValueResult.
934 * @param pValueResult The first value and result.
935 * @param cBits The number of bits to shift.
936 */
937DECLINLINE(PRTUINT64U) RTUInt64AssignShiftRight(PRTUINT64U pValueResult, int cBits)
938{
939 return RTUInt64AssignShiftLeft(pValueResult, -cBits);
940}
941
942
943/**
944 * Performs a bitwise NOT on a 64-bit unsigned integer value, assigning the
945 * result to it.
946 *
947 * @returns pValueResult
948 * @param pValueResult The value and result.
949 */
950DECLINLINE(PRTUINT64U) RTUInt64AssignBitwiseNot(PRTUINT64U pValueResult)
951{
952#if ARCH_BITS >= 32
953 pValueResult->s.Hi = ~pValueResult->s.Hi;
954 pValueResult->s.Lo = ~pValueResult->s.Lo;
955#else
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;
960#endif
961 return pValueResult;
962}
963
964
965/**
966 * Performs a boolean NOT on a 64-bit unsigned integer value, assigning the
967 * result to it.
968 *
969 * @returns pValueResult
970 * @param pValueResult The value and result.
971 */
972DECLINLINE(PRTUINT64U) RTUInt64AssignBooleanNot(PRTUINT64U pValueResult)
973{
974 return RTUInt64AssignBoolean(pValueResult, RTUInt64IsZero(pValueResult));
975}
976
977
978/**
979 * Compares two 64-bit unsigned integer values.
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 */
988DECLINLINE(int) RTUInt64Compare(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
989{
990#if ARCH_BITS >= 32
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
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;
1005 return 0;
1006#endif
1007}
1008
1009
1010/**
1011 * Tests if a 64-bit unsigned integer value is smaller than another.
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 */
1017DECLINLINE(bool) RTUInt64IsSmaller(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
1018{
1019#if ARCH_BITS >= 32
1020 return pValue1->s.Hi < pValue2->s.Hi
1021 || ( pValue1->s.Hi == pValue2->s.Hi
1022 && pValue1->s.Lo < pValue2->s.Lo);
1023#else
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)))));
1031#endif
1032}
1033
1034
1035/**
1036 * Tests if a 32-bit unsigned integer value is larger than another.
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 */
1042DECLINLINE(bool) RTUInt64IsLarger(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
1043{
1044#if ARCH_BITS >= 32
1045 return pValue1->s.Hi > pValue2->s.Hi
1046 || ( pValue1->s.Hi == pValue2->s.Hi
1047 && pValue1->s.Lo > pValue2->s.Lo);
1048#else
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)))));
1056#endif
1057}
1058
1059
1060/**
1061 * Tests if a 64-bit unsigned integer value is larger or equal than another.
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 */
1067DECLINLINE(bool) RTUInt64IsLargerOrEqual(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
1068{
1069#if ARCH_BITS >= 32
1070 return pValue1->s.Hi > pValue2->s.Hi
1071 || ( pValue1->s.Hi == pValue2->s.Hi
1072 && pValue1->s.Lo >= pValue2->s.Lo);
1073#else
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)))));
1081#endif
1082}
1083
1084
1085/**
1086 * Tests if two 64-bit unsigned integer values not equal.
1087 *
1088 * @returns true if equal, false if not equal.
1089 * @param pValue1 The first value.
1090 * @param pValue2 The second value.
1091 */
1092DECLINLINE(bool) RTUInt64IsEqual(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
1093{
1094#if ARCH_BITS >= 32
1095 return pValue1->s.Hi == pValue2->s.Hi
1096 && pValue1->s.Lo == pValue2->s.Lo;
1097#else
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;
1102#endif
1103}
1104
1105
1106/**
1107 * Tests if two 64-bit unsigned integer values are not equal.
1108 *
1109 * @returns true if not equal, false if equal.
1110 * @param pValue1 The first value.
1111 * @param pValue2 The second value.
1112 */
1113DECLINLINE(bool) RTUInt64IsNotEqual(PCRTUINT64U pValue1, PCRTUINT64U pValue2)
1114{
1115 return !RTUInt64IsEqual(pValue1, pValue2);
1116}
1117
1118
1119/**
1120 * Sets a bit in a 64-bit unsigned integer type.
1121 *
1122 * @returns pValueResult.
1123 * @param pValueResult The input and output value.
1124 * @param iBit The bit to set.
1125 */
1126DECLINLINE(PRTUINT64U) RTUInt64BitSet(PRTUINT64U pValueResult, unsigned iBit)
1127{
1128 if (iBit < 32)
1129 {
1130#if ARCH_BITS >= 32
1131 pValueResult->s.Lo |= RT_BIT_32(iBit);
1132#else
1133 if (iBit < 16)
1134 pValueResult->Words.w0 |= UINT16_C(1) << iBit;
1135 else
1136 pValueResult->Words.w1 |= UINT16_C(1) << (iBit - 32);
1137#endif
1138 }
1139 else if (iBit < 64)
1140 {
1141#if ARCH_BITS >= 32
1142 pValueResult->s.Hi |= RT_BIT_32(iBit - 32);
1143#else
1144 if (iBit < 48)
1145 pValueResult->Words.w2 |= UINT16_C(1) << (iBit - 64);
1146 else
1147 pValueResult->Words.w3 |= UINT16_C(1) << (iBit - 96);
1148#endif
1149 }
1150 return pValueResult;
1151}
1152
1153
1154/**
1155 * Sets a bit in a 64-bit unsigned integer type.
1156 *
1157 * @returns pValueResult.
1158 * @param pValueResult The input and output value.
1159 * @param iBit The bit to set.
1160 */
1161DECLINLINE(PRTUINT64U) RTUInt64BitClear(PRTUINT64U pValueResult, unsigned iBit)
1162{
1163 if (iBit < 32)
1164 {
1165#if ARCH_BITS >= 32
1166 pValueResult->s.Lo &= ~RT_BIT_32(iBit);
1167#else
1168 if (iBit < 48)
1169 pValueResult->Words.w0 &= ~(UINT16_C(1) << (iBit));
1170 else
1171 pValueResult->Words.w1 &= ~(UINT16_C(1) << (iBit - 32));
1172#endif
1173 }
1174 else if (iBit < 64)
1175 {
1176#if ARCH_BITS >= 32
1177 pValueResult->s.Hi &= ~RT_BIT_32(iBit - 32);
1178#else
1179 if (iBit < 48)
1180 pValueResult->Words.w2 &= ~(UINT16_C(1) << (iBit - 64));
1181 else
1182 pValueResult->Words.w3 &= ~(UINT16_C(1) << (iBit - 96));
1183#endif
1184 }
1185 return pValueResult;
1186}
1187
1188
1189/**
1190 * Tests if a bit in a 64-bit unsigned integer value is set.
1191 *
1192 * @returns pValueResult.
1193 * @param pValueResult The input and output value.
1194 * @param iBit The bit to test.
1195 */
1196DECLINLINE(bool) RTUInt64BitTest(PRTUINT64U pValueResult, unsigned iBit)
1197{
1198 bool fRc;
1199 if (iBit < 32)
1200 {
1201#if ARCH_BITS >= 32
1202 fRc = RT_BOOL(pValueResult->s.Lo & RT_BIT_32(iBit));
1203#else
1204 if (iBit < 16)
1205 fRc = RT_BOOL(pValueResult->Words.w0 & (UINT16_C(1) << (iBit)));
1206 else
1207 fRc = RT_BOOL(pValueResult->Words.w1 & (UINT16_C(1) << (iBit - 16)));
1208#endif
1209 }
1210 else if (iBit < 64)
1211 {
1212#if ARCH_BITS >= 32
1213 fRc = RT_BOOL(pValueResult->s.Hi & RT_BIT_32(iBit - 32));
1214#else
1215 if (iBit < 48)
1216 fRc = RT_BOOL(pValueResult->Words.w2 & (UINT16_C(1) << (iBit - 32)));
1217 else
1218 fRc = RT_BOOL(pValueResult->Words.w3 & (UINT16_C(1) << (iBit - 48)));
1219#endif
1220 }
1221 else
1222 fRc = false;
1223 return fRc;
1224}
1225
1226
1227/**
1228 * Set a range of bits a 64-bit unsigned integer value.
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 */
1235DECLINLINE(PRTUINT64U) RTUInt64BitSetRange(PRTUINT64U pValueResult, unsigned iFirstBit, unsigned cBits)
1236{
1237 /* bounds check & fix. */
1238 if (iFirstBit < 64)
1239 {
1240 if (iFirstBit + cBits > 64)
1241 cBits = 64 - iFirstBit;
1242
1243#if ARCH_BITS >= 32
1244 if (iFirstBit + cBits < 32)
1245 pValueResult->s.Lo |= (RT_BIT_32(cBits) - 1) << iFirstBit;
1246 else if (iFirstBit + cBits < 64 && iFirstBit >= 32)
1247 pValueResult->s.Hi |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 32);
1248 else
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
1259#endif
1260 while (cBits-- > 0)
1261 RTUInt64BitSet(pValueResult, iFirstBit++);
1262 }
1263 return pValueResult;
1264}
1265
1266
1267/**
1268 * Test if all the bits of a 64-bit unsigned integer value are set.
1269 *
1270 * @returns true if they are, false if they aren't.
1271 * @param pValue The input and output value.
1272 */
1273DECLINLINE(bool) RTUInt64BitAreAllSet(PRTUINT64U pValue)
1274{
1275#if ARCH_BITS >= 32
1276 return pValue->s.Hi == UINT32_MAX
1277 && pValue->s.Lo == UINT32_MAX;
1278#else
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;
1283#endif
1284}
1285
1286
1287/**
1288 * Test if all the bits of a 64-bit unsigned integer value are clear.
1289 *
1290 * @returns true if they are, false if they aren't.
1291 * @param pValue The input and output value.
1292 */
1293DECLINLINE(bool) RTUInt64BitAreAllClear(PRTUINT64U pValue)
1294{
1295 return RTUInt64IsZero(pValue);
1296}
1297
1298
1299DECLINLINE(unsigned) RTUInt64BitCount(PCRTUINT64U pValue)
1300{
1301 unsigned cBits;
1302 if (pValue->s.Hi != 0)
1303 {
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);
1309 else
1310 cBits = 32 + ASMBitLastSetU16(pValue->Words.w2);
1311#endif
1312 }
1313 else
1314 {
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);
1320 else
1321 cBits = 0 + ASMBitLastSetU16(pValue->Words.w0);
1322#endif
1323 }
1324 return cBits;
1325}
1326
1327
1328/**
1329 * Divides a 64-bit unsigned integer value by another, returning both quotient
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 */
1338DECLINLINE(PRTUINT64U) RTUInt64DivRem(PRTUINT64U pQuotient, PRTUINT64U pRemainder, PCRTUINT64U pValue1, PCRTUINT64U pValue2)
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 {
1353 RTUInt64SetZero(pRemainder);
1354 *pQuotient = *pValue1;
1355 return pQuotient;
1356 }
1357 /** @todo RTUInt64DivModByU32 */
1358 }
1359
1360 /* Dividend is smaller? */
1361 iDiff = RTUInt64Compare(pValue1, pValue2);
1362 if (iDiff < 0)
1363 {
1364 *pRemainder = *pValue1;
1365 RTUInt64SetZero(pQuotient);
1366 }
1367
1368 /* The values are equal? */
1369 else if (iDiff == 0)
1370 {
1371 RTUInt64SetZero(pRemainder);
1372 RTUInt64AssignU8(pQuotient, 1);
1373 }
1374 else
1375 {
1376 /*
1377 * Prepare.
1378 */
1379 unsigned iBitAdder = RTUInt64BitCount(pValue1) - RTUInt64BitCount(pValue2);
1380 RTUINT64U NormDivisor = *pValue2;
1381 if (iBitAdder)
1382 {
1383 RTUInt64ShiftLeft(&NormDivisor, pValue2, iBitAdder);
1384 if (RTUInt64IsLarger(&NormDivisor, pValue1))
1385 {
1386 RTUInt64AssignShiftRight(&NormDivisor, 1);
1387 iBitAdder--;
1388 }
1389 }
1390 else
1391 NormDivisor = *pValue2;
1392
1393 RTUInt64SetZero(pQuotient);
1394 *pRemainder = *pValue1;
1395
1396 /*
1397 * Do the division.
1398 */
1399 if (RTUInt64IsLargerOrEqual(pRemainder, pValue2))
1400 {
1401 for (;;)
1402 {
1403 if (RTUInt64IsLargerOrEqual(pRemainder, &NormDivisor))
1404 {
1405 RTUInt64AssignSub(pRemainder, &NormDivisor);
1406 RTUInt64AssignOrBit(pQuotient, iBitAdder);
1407 }
1408 if (RTUInt64IsSmaller(pRemainder, pValue2))
1409 break;
1410 RTUInt64AssignShiftRight(&NormDivisor, 1);
1411 iBitAdder--;
1412 }
1413 }
1414 }
1415 return pQuotient;
1416}
1417
1418
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
1479/** @} */
1480
1481RT_C_DECLS_END
1482
1483#endif /* !IPRT_INCLUDED_uint64_h */
1484
Note: See TracBrowser for help on using the repository browser.

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