VirtualBox

source: vbox/trunk/include/iprt/uint32.h@ 104384

Last change on this file since 104384 was 98103, checked in by vboxsync, 20 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.3 KB
RevLine 
[35488]1/** @file
[60484]2 * IPRT - RTUINT32U methods for old 16-bit compilers (mainly for division).
[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_uint32_h
37#define IPRT_INCLUDED_uint32_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
[60484]48/** @defgroup grp_rt_uint32 RTUInt32 - 32-bit Unsigned Integer Methods for 16-bit compilers.
[35488]49 * @ingroup grp_rt
50 * @{
51 */
52
[60484]53#define RTUINT32_HAVE_32BIT_BASICS
[35488]54
[60484]55
[35488]56/**
[60484]57 * Test if a 32-bit unsigned integer value is zero.
[35488]58 *
59 * @returns true if they are, false if they aren't.
60 * @param pValue The input and output value.
61 */
[60484]62DECLINLINE(bool) RTUInt32IsZero(PRTUINT32U pValue)
[35488]63{
[60482]64 return pValue->s.Lo == 0
65 && pValue->s.Hi == 0;
[35488]66}
67
68
69/**
[60484]70 * Set a 32-bit unsigned integer value to zero.
[35488]71 *
72 * @returns pResult
73 * @param pResult The result variable.
74 */
[60484]75DECLINLINE(PRTUINT32U) RTUInt32SetZero(PRTUINT32U pResult)
[35488]76{
77 pResult->s.Hi = 0;
78 pResult->s.Lo = 0;
79 return pResult;
80}
81
82
83/**
[60482]84 * Set a 32-bit unsigned integer value to the maximum value.
[35488]85 *
86 * @returns pResult
87 * @param pResult The result variable.
88 */
[60484]89DECLINLINE(PRTUINT32U) RTUInt32SetMax(PRTUINT32U pResult)
[35488]90{
[60484]91 pResult->s.Hi = UINT16_MAX;
92 pResult->s.Lo = UINT16_MAX;
[35488]93 return pResult;
94}
95
96
97
98
99/**
[60484]100 * Adds two 32-bit unsigned integer values.
[52335]101 *
102 * @returns pResult
103 * @param pResult The result variable.
104 * @param pValue1 The first value.
105 * @param pValue2 The second value.
106 */
[60484]107DECLINLINE(PRTUINT32U) RTUInt32Add(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[52335]108{
[60484]109#ifdef RTUINT32_HAVE_32BIT_BASICS
110 pResult->u = pValue1->u + pValue2->u;
111#else
[52335]112 pResult->s.Hi = pValue1->s.Hi + pValue2->s.Hi;
113 pResult->s.Lo = pValue1->s.Lo + pValue2->s.Lo;
114 if (pResult->s.Lo < pValue1->s.Lo)
115 pResult->s.Hi++;
[60484]116#endif
[52335]117 return pResult;
118}
119
120
121/**
[60484]122 * Adds a 32-bit and a 16-bit unsigned integer values.
[52335]123 *
124 * @returns pResult
125 * @param pResult The result variable.
126 * @param pValue1 The first value.
[60484]127 * @param uValue2 The second value, 16-bit.
[52335]128 */
[60484]129DECLINLINE(PRTUINT32U) RTUInt32AddU16(PRTUINT32U pResult, PCRTUINT32U pValue1, uint16_t uValue2)
[52335]130{
[60484]131#ifdef RTUINT32_HAVE_32BIT_BASICS
132 pResult->u = pValue1->u + uValue2;
133#else
[52335]134 pResult->s.Hi = pValue1->s.Hi;
135 pResult->s.Lo = pValue1->s.Lo + uValue2;
136 if (pResult->s.Lo < pValue1->s.Lo)
137 pResult->s.Hi++;
[60484]138#endif
[52335]139 return pResult;
140}
141
142
143/**
[60484]144 * Subtracts a 32-bit unsigned integer value from another.
[52335]145 *
146 * @returns pResult
147 * @param pResult The result variable.
148 * @param pValue1 The minuend value.
149 * @param pValue2 The subtrahend value.
150 */
[60484]151DECLINLINE(PRTUINT32U) RTUInt32Sub(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[52335]152{
[60484]153#ifdef RTUINT32_HAVE_32BIT_BASICS
154 pResult->u = pValue1->u - pValue2->u;
155#else
[52335]156 pResult->s.Lo = pValue1->s.Lo - pValue2->s.Lo;
157 pResult->s.Hi = pValue1->s.Hi - pValue2->s.Hi;
158 if (pResult->s.Lo > pValue1->s.Lo)
159 pResult->s.Hi--;
[60484]160#endif
[52335]161 return pResult;
162}
163
164
165/**
[60484]166 * Multiplies two 32-bit unsigned integer values.
[52335]167 *
168 * @returns pResult
169 * @param pResult The result variable.
170 * @param pValue1 The first value.
171 * @param pValue2 The second value.
172 */
[60484]173DECLINLINE(PRTUINT32U) RTUInt32Mul(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[52335]174{
[60484]175 pResult->u = (uint32_t)pValue1->s.Lo * pValue2->s.Lo;
176 pResult->s.Hi += pValue1->s.Hi * pValue2->s.Lo;
177 pResult->s.Hi += pValue1->s.Lo * pValue2->s.Hi;
[52335]178
179 return pResult;
180}
181
182
183/**
[60484]184 * Multiplies an 32-bit unsigned integer by a 16-bit unsigned integer value.
[52335]185 *
186 * @returns pResult
187 * @param pResult The result variable.
188 * @param pValue1 The first value.
[60484]189 * @param uValue2 The second value, 16-bit.
[52335]190 */
[60484]191DECLINLINE(PRTUINT32U) RTUInt32MulByU16(PRTUINT32U pResult, PCRTUINT32U pValue1, uint16_t uValue2)
[52335]192{
[60484]193 pResult->u = (uint32_t)pValue1->s.Lo * uValue2;
194 pResult->s.Hi += pValue1->s.Hi * uValue2;
[52335]195 return pResult;
196}
197
198
[60484]199DECLINLINE(PRTUINT32U) RTUInt32DivRem(PRTUINT32U pQuotient, PRTUINT32U pRemainder, PCRTUINT32U pValue1, PCRTUINT32U pValue2);
[52335]200
201/**
[60484]202 * Divides a 32-bit unsigned integer value by another.
[52335]203 *
204 * @returns pResult
205 * @param pResult The result variable.
206 * @param pValue1 The dividend value.
207 * @param pValue2 The divisor value.
208 */
[60484]209DECLINLINE(PRTUINT32U) RTUInt32Div(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[52335]210{
[60484]211 RTUINT32U Ignored;
212 return RTUInt32DivRem(pResult, &Ignored, pValue1, pValue2);
[52335]213}
214
215
216/**
[60484]217 * Divides a 32-bit unsigned integer value by another, returning the remainder.
[52335]218 *
219 * @returns pResult
220 * @param pResult The result variable (remainder).
221 * @param pValue1 The dividend value.
222 * @param pValue2 The divisor value.
223 */
[60484]224DECLINLINE(PRTUINT32U) RTUInt32Mod(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[52335]225{
[60484]226 RTUINT32U Ignored;
227 RTUInt32DivRem(&Ignored, pResult, pValue1, pValue2);
[52335]228 return pResult;
229}
230
231
232/**
[60484]233 * Bitwise AND of two 32-bit unsigned integer values.
[52335]234 *
235 * @returns pResult
236 * @param pResult The result variable.
237 * @param pValue1 The first value.
238 * @param pValue2 The second value.
239 */
[60484]240DECLINLINE(PRTUINT32U) RTUInt32And(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[52335]241{
242 pResult->s.Hi = pValue1->s.Hi & pValue2->s.Hi;
243 pResult->s.Lo = pValue1->s.Lo & pValue2->s.Lo;
244 return pResult;
245}
246
247
248/**
[60484]249 * Bitwise OR of two 32-bit unsigned integer values.
[52335]250 *
251 * @returns pResult
252 * @param pResult The result variable.
253 * @param pValue1 The first value.
254 * @param pValue2 The second value.
255 */
[60484]256DECLINLINE(PRTUINT32U) RTUInt32Or( PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[52335]257{
258 pResult->s.Hi = pValue1->s.Hi | pValue2->s.Hi;
259 pResult->s.Lo = pValue1->s.Lo | pValue2->s.Lo;
260 return pResult;
261}
262
263
264/**
[60484]265 * Bitwise XOR of two 32-bit unsigned integer values.
[52335]266 *
267 * @returns pResult
268 * @param pResult The result variable.
269 * @param pValue1 The first value.
270 * @param pValue2 The second value.
271 */
[60484]272DECLINLINE(PRTUINT32U) RTUInt32Xor(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[52335]273{
274 pResult->s.Hi = pValue1->s.Hi ^ pValue2->s.Hi;
275 pResult->s.Lo = pValue1->s.Lo ^ pValue2->s.Lo;
276 return pResult;
277}
278
279
280/**
[60484]281 * Shifts a 32-bit unsigned integer value @a cBits to the left.
[52335]282 *
283 * @returns pResult
284 * @param pResult The result variable.
285 * @param pValue The value to shift.
286 * @param cBits The number of bits to shift it.
287 */
[60484]288DECLINLINE(PRTUINT32U) RTUInt32ShiftLeft(PRTUINT32U pResult, PCRTUINT32U pValue, int cBits)
[52335]289{
[60484]290 cBits &= 31;
291#ifdef RTUINT32_HAVE_32BIT_BASICS
292 pResult->u = pValue->u << cBits;
293#else
294 if (cBits < 16)
[52335]295 {
296 pResult->s.Lo = pValue->s.Lo << cBits;
[60484]297 pResult->s.Hi = (pValue->s.Hi << cBits) | (pValue->s.Lo >> (16 - cBits));
[52335]298 }
299 else
300 {
301 pResult->s.Lo = 0;
[60484]302 pResult->s.Hi = pValue->s.Lo << (cBits - 16);
[52335]303 }
[60484]304#endif
[52335]305 return pResult;
306}
307
308
309/**
[60484]310 * Shifts a 32-bit unsigned integer value @a cBits to the right.
[52335]311 *
312 * @returns pResult
313 * @param pResult The result variable.
314 * @param pValue The value to shift.
315 * @param cBits The number of bits to shift it.
316 */
[60484]317DECLINLINE(PRTUINT32U) RTUInt32ShiftRight(PRTUINT32U pResult, PCRTUINT32U pValue, int cBits)
[52335]318{
[60484]319 cBits &= 31;
320#ifdef RTUINT32_HAVE_32BIT_BASICS
321 pResult->u = pValue->u >> cBits;
322#else
323 if (cBits < 16)
[52335]324 {
325 pResult->s.Hi = pValue->s.Hi >> cBits;
[60484]326 pResult->s.Lo = (pValue->s.Lo >> cBits) | (pValue->s.Hi << (16 - cBits));
[52335]327 }
328 else
329 {
330 pResult->s.Hi = 0;
[60484]331 pResult->s.Lo = pValue->s.Hi >> (cBits - 16);
[52335]332 }
[60484]333#endif
[52335]334 return pResult;
335}
336
337
338/**
339 * Boolean not (result 0 or 1).
340 *
341 * @returns pResult.
342 * @param pResult The result variable.
343 * @param pValue The value.
344 */
[60484]345DECLINLINE(PRTUINT32U) RTUInt32BooleanNot(PRTUINT32U pResult, PCRTUINT32U pValue)
[52335]346{
[60482]347 pResult->s.Lo = pValue->s.Lo || pValue->s.Hi ? 0 : 1;
[52335]348 pResult->s.Hi = 0;
349 return pResult;
350}
351
352
353/**
[60484]354 * Bitwise not (flips each bit of the 32 bits).
[52335]355 *
356 * @returns pResult.
357 * @param pResult The result variable.
358 * @param pValue The value.
359 */
[60484]360DECLINLINE(PRTUINT32U) RTUInt32BitwiseNot(PRTUINT32U pResult, PCRTUINT32U pValue)
[52335]361{
362 pResult->s.Hi = ~pValue->s.Hi;
363 pResult->s.Lo = ~pValue->s.Lo;
364 return pResult;
365}
366
367
368/**
[60484]369 * Assigns one 32-bit unsigned integer value to another.
[35488]370 *
371 * @returns pResult
372 * @param pResult The result variable.
373 * @param pValue The value to assign.
374 */
[60484]375DECLINLINE(PRTUINT32U) RTUInt32Assign(PRTUINT32U pResult, PCRTUINT32U pValue)
[35488]376{
377 pResult->s.Hi = pValue->s.Hi;
378 pResult->s.Lo = pValue->s.Lo;
379 return pResult;
380}
381
382
383/**
[60484]384 * Assigns a boolean value to 32-bit unsigned integer.
[35488]385 *
[57944]386 * @returns pValueResult
387 * @param pValueResult The result variable.
[35488]388 * @param fValue The boolean value.
389 */
[60484]390DECLINLINE(PRTUINT32U) RTUInt32AssignBoolean(PRTUINT32U pValueResult, bool fValue)
[35488]391{
392 pValueResult->s.Lo = fValue;
393 pValueResult->s.Hi = 0;
394 return pValueResult;
395}
396
397
398/**
[60484]399 * Assigns a 8-bit unsigned integer value to 32-bit unsigned integer.
[35488]400 *
[57944]401 * @returns pValueResult
402 * @param pValueResult The result variable.
[35488]403 * @param u8Value The 8-bit unsigned integer value.
404 */
[60484]405DECLINLINE(PRTUINT32U) RTUInt32AssignU8(PRTUINT32U pValueResult, uint8_t u8Value)
[35488]406{
407 pValueResult->s.Lo = u8Value;
408 pValueResult->s.Hi = 0;
409 return pValueResult;
410}
411
412
413/**
[60484]414 * Assigns a 16-bit unsigned integer value to 32-bit unsigned integer.
[35488]415 *
[57944]416 * @returns pValueResult
417 * @param pValueResult The result variable.
[35488]418 * @param u16Value The 16-bit unsigned integer value.
419 */
[60484]420DECLINLINE(PRTUINT32U) RTUInt32AssignU16(PRTUINT32U pValueResult, uint16_t u16Value)
[35488]421{
422 pValueResult->s.Lo = u16Value;
423 pValueResult->s.Hi = 0;
424 return pValueResult;
425}
426
427
428/**
[60484]429 * Adds two 32-bit unsigned integer values, storing the result in the first.
[35488]430 *
[52335]431 * @returns pValue1Result.
432 * @param pValue1Result The first value and result.
433 * @param pValue2 The second value.
434 */
[60484]435DECLINLINE(PRTUINT32U) RTUInt32AssignAdd(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
[52335]436{
[60484]437#ifdef RTUINT32_HAVE_32BIT_BASICS
438 pValue1Result->u += pValue2->u;
439#else
440 uint16_t const uTmp = pValue1Result->s.Lo;
[52335]441 pValue1Result->s.Lo += pValue2->s.Lo;
442 if (pValue1Result->s.Lo < uTmp)
443 pValue1Result->s.Hi++;
444 pValue1Result->s.Hi += pValue2->s.Hi;
[60484]445#endif
[52335]446 return pValue1Result;
447}
[35488]448
449
450/**
[60484]451 * Subtracts two 32-bit unsigned integer values, storing the result in the
[52335]452 * first.
453 *
454 * @returns pValue1Result.
455 * @param pValue1Result The minuend value and result.
456 * @param pValue2 The subtrahend value.
457 */
[60484]458DECLINLINE(PRTUINT32U) RTUInt32AssignSub(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
[52335]459{
[60484]460#ifdef RTUINT32_HAVE_32BIT_BASICS
461 pValue1Result->u -= pValue2->u;
462#else
[60482]463 uint32_t const uTmp = pValue1Result->s.Lo;
[52335]464 pValue1Result->s.Lo -= pValue2->s.Lo;
465 if (pValue1Result->s.Lo > uTmp)
466 pValue1Result->s.Hi--;
467 pValue1Result->s.Hi -= pValue2->s.Hi;
[60484]468#endif
[52335]469 return pValue1Result;
470}
471
472
473/**
[60484]474 * Multiplies two 32-bit unsigned integer values, storing the result in the
[52335]475 * first.
476 *
477 * @returns pValue1Result.
478 * @param pValue1Result The first value and result.
479 * @param pValue2 The second value.
480 */
[60484]481DECLINLINE(PRTUINT32U) RTUInt32AssignMul(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
[52335]482{
[60484]483 RTUINT32U Result;
484 RTUInt32Mul(&Result, pValue1Result, pValue2);
[52335]485 *pValue1Result = Result;
486 return pValue1Result;
487}
488
489
490/**
[60484]491 * Divides a 32-bit unsigned integer value by another, storing the result in
[52335]492 * the first.
493 *
494 * @returns pValue1Result.
495 * @param pValue1Result The dividend value and result.
496 * @param pValue2 The divisor value.
497 */
[60484]498DECLINLINE(PRTUINT32U) RTUInt32AssignDiv(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
[52335]499{
[60484]500 RTUINT32U Result;
501 RTUINT32U Ignored;
502 RTUInt32DivRem(&Result, &Ignored, pValue1Result, pValue2);
[52335]503 *pValue1Result = Result;
504 return pValue1Result;
505}
506
507
508/**
[60484]509 * Divides a 32-bit unsigned integer value by another, storing the remainder in
[52335]510 * the first.
511 *
512 * @returns pValue1Result.
513 * @param pValue1Result The dividend value and result (remainder).
514 * @param pValue2 The divisor value.
515 */
[60484]516DECLINLINE(PRTUINT32U) RTUInt32AssignMod(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
[52335]517{
[60484]518 RTUINT32U Ignored;
519 RTUINT32U Result;
520 RTUInt32DivRem(&Ignored, &Result, pValue1Result, pValue2);
[52335]521 *pValue1Result = Result;
522 return pValue1Result;
523}
524
525
526/**
[60484]527 * Performs a bitwise AND of two 32-bit unsigned integer values and assigned
[35488]528 * the result to the first one.
529 *
530 * @returns pValue1Result.
531 * @param pValue1Result The first value and result.
532 * @param pValue2 The second value.
533 */
[60484]534DECLINLINE(PRTUINT32U) RTUInt32AssignAnd(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
[35488]535{
536 pValue1Result->s.Hi &= pValue2->s.Hi;
537 pValue1Result->s.Lo &= pValue2->s.Lo;
538 return pValue1Result;
539}
540
541
542/**
[60484]543 * Performs a bitwise AND of a 32-bit unsigned integer value and a mask made up
544 * of the first N bits, assigning the result to the the 32-bit value.
[35490]545 *
546 * @returns pValueResult.
547 * @param pValueResult The value and result.
548 * @param cBits The number of bits to AND (counting from the first
549 * bit).
550 */
[60484]551DECLINLINE(PRTUINT32U) RTUInt32AssignAndNFirstBits(PRTUINT32U pValueResult, unsigned cBits)
[35490]552{
[60484]553#ifdef RTUINT32_HAVE_32BIT_BASICS
554 if (cBits < 32)
555 pValueResult->u &= RT_BIT_32(cBits) - 1;
556#else
557 if (cBits <= 16)
[35490]558 {
[60484]559 if (cBits != 16)
560 pValueResult->s.Lo &= (UINT16_C(1) << cBits) - 1;
[35490]561 pValueResult->s.Hi = 0;
562 }
[60484]563 else if (cBits < 16)
564 pValueResult->s.Hi &= (UINT16_C(1) << (cBits - 16)) - 1;
565#endif
[35490]566 return pValueResult;
567}
568
569
570/**
[60484]571 * Performs a bitwise OR of two 32-bit unsigned integer values and assigned
[35488]572 * the result to the first one.
573 *
574 * @returns pValue1Result.
575 * @param pValue1Result The first value and result.
576 * @param pValue2 The second value.
577 */
[60484]578DECLINLINE(PRTUINT32U) RTUInt32AssignOr(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
[35488]579{
580 pValue1Result->s.Hi |= pValue2->s.Hi;
581 pValue1Result->s.Lo |= pValue2->s.Lo;
582 return pValue1Result;
583}
584
585
586/**
[52335]587 * ORs in a bit and assign the result to the input value.
588 *
589 * @returns pValue1Result.
590 * @param pValue1Result The first value and result.
591 * @param iBit The bit to set (0 based).
592 */
[60484]593DECLINLINE(PRTUINT32U) RTUInt32AssignOrBit(PRTUINT32U pValue1Result, unsigned iBit)
[52335]594{
[60484]595#ifdef RTUINT32_HAVE_32BIT_BASICS
596 pValue1Result->u |= RT_BIT_32(iBit);
[52335]597#else
[60482]598 if (iBit >= 32)
[60484]599 pValue1Result->s.Hi |= UINT16_C(1) << (iBit - 32);
[52335]600 else
[60484]601 pValue1Result->s.Lo |= UINT16_C(1) << iBit;
[52335]602#endif
603 return pValue1Result;
604}
605
606
607
608/**
[60484]609 * Performs a bitwise XOR of two 32-bit unsigned integer values and assigned
[35488]610 * the result to the first one.
611 *
612 * @returns pValue1Result.
613 * @param pValue1Result The first value and result.
614 * @param pValue2 The second value.
615 */
[60484]616DECLINLINE(PRTUINT32U) RTUInt32AssignXor(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
[35488]617{
618 pValue1Result->s.Hi ^= pValue2->s.Hi;
619 pValue1Result->s.Lo ^= pValue2->s.Lo;
620 return pValue1Result;
621}
622
623
624/**
[60484]625 * Performs a bitwise left shift on a 32-bit unsigned integer value, assigning
[35488]626 * the result to it.
627 *
[57944]628 * @returns pValueResult.
629 * @param pValueResult The first value and result.
[35488]630 * @param cBits The number of bits to shift.
631 */
[60484]632DECLINLINE(PRTUINT32U) RTUInt32AssignShiftLeft(PRTUINT32U pValueResult, int cBits)
[35488]633{
[60484]634#ifndef RTUINT32_HAVE_32BIT_BASICS
635 RTUINT32U const InVal = *pValueResult;
636#endif
[35488]637 if (cBits > 0)
638 {
639 /* (left shift) */
[60484]640 cBits &= 31;
641#ifdef RTUINT32_HAVE_32BIT_BASICS
642 pValueResult->u <<= cBits;
643#else
644 if (cBits >= 16)
[35488]645 {
646 pValueResult->s.Lo = 0;
[60484]647 pValueResult->s.Hi = InVal.s.Lo << (cBits - 16);
[35488]648 }
649 else
650 {
651 pValueResult->s.Hi = InVal.s.Hi << cBits;
[60484]652 pValueResult->s.Hi |= InVal.s.Lo >> (16 - cBits);
[35488]653 pValueResult->s.Lo = InVal.s.Lo << cBits;
654 }
[60484]655#endif
[35488]656 }
657 else if (cBits < 0)
658 {
659 /* (right shift) */
660 cBits = -cBits;
[60484]661 cBits &= 31;
662#ifdef RTUINT32_HAVE_32BIT_BASICS
663 pValueResult->u >>= cBits;
664#else
665 if (cBits >= 16)
[35488]666 {
667 pValueResult->s.Hi = 0;
[60484]668 pValueResult->s.Lo = InVal.s.Hi >> (cBits - 16);
[35488]669 }
670 else
671 {
672 pValueResult->s.Lo = InVal.s.Lo >> cBits;
[60484]673 pValueResult->s.Lo |= InVal.s.Hi << (16 - cBits);
[35488]674 pValueResult->s.Hi = InVal.s.Hi >> cBits;
675 }
[60484]676#endif
[35488]677 }
678 return pValueResult;
679}
680
681
682/**
[60484]683 * Performs a bitwise left shift on a 32-bit unsigned integer value, assigning
[35488]684 * the result to it.
685 *
[57944]686 * @returns pValueResult.
687 * @param pValueResult The first value and result.
[35488]688 * @param cBits The number of bits to shift.
689 */
[60484]690DECLINLINE(PRTUINT32U) RTUInt32AssignShiftRight(PRTUINT32U pValueResult, int cBits)
[35488]691{
[60484]692 return RTUInt32AssignShiftLeft(pValueResult, -cBits);
[35488]693}
694
695
696/**
[60484]697 * Performs a bitwise NOT on a 32-bit unsigned integer value, assigning the
[35488]698 * result to it.
699 *
700 * @returns pValueResult
701 * @param pValueResult The value and result.
702 */
[60484]703DECLINLINE(PRTUINT32U) RTUInt32AssignBitwiseNot(PRTUINT32U pValueResult)
[35488]704{
705 pValueResult->s.Hi = ~pValueResult->s.Hi;
706 pValueResult->s.Lo = ~pValueResult->s.Lo;
707 return pValueResult;
708}
709
710
711/**
[60484]712 * Performs a boolean NOT on a 32-bit unsigned integer value, assigning the
[35488]713 * result to it.
714 *
715 * @returns pValueResult
716 * @param pValueResult The value and result.
717 */
[60484]718DECLINLINE(PRTUINT32U) RTUInt32AssignBooleanNot(PRTUINT32U pValueResult)
[35488]719{
[60484]720 return RTUInt32AssignBoolean(pValueResult, RTUInt32IsZero(pValueResult));
[35488]721}
722
723
724/**
[60484]725 * Compares two 32-bit unsigned integer values.
[35488]726 *
727 * @retval 0 if equal.
728 * @retval -1 if the first value is smaller than the second.
729 * @retval 1 if the first value is larger than the second.
730 *
731 * @param pValue1 The first value.
732 * @param pValue2 The second value.
733 */
[60484]734DECLINLINE(int) RTUInt32Compare(PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[35488]735{
736 if (pValue1->s.Hi != pValue2->s.Hi)
737 return pValue1->s.Hi > pValue2->s.Hi ? 1 : -1;
738 if (pValue1->s.Lo != pValue2->s.Lo)
739 return pValue1->s.Lo > pValue2->s.Lo ? 1 : -1;
740 return 0;
741}
742
743
744/**
[60482]745 * Tests if a 64-bit unsigned integer value is smaller than another.
[52335]746 *
747 * @returns true if the first value is smaller, false if not.
748 * @param pValue1 The first value.
749 * @param pValue2 The second value.
750 */
[60484]751DECLINLINE(bool) RTUInt32IsSmaller(PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[52335]752{
[60484]753#ifdef RTUINT32_HAVE_32BIT_BASICS
754 return pValue1->u < pValue2->u;
755#else
[52335]756 return pValue1->s.Hi < pValue2->s.Hi
757 || ( pValue1->s.Hi == pValue2->s.Hi
758 && pValue1->s.Lo < pValue2->s.Lo);
759#endif
760}
761
762
763/**
[60482]764 * Tests if a 32-bit unsigned integer value is larger than another.
[52335]765 *
766 * @returns true if the first value is larger, false if not.
767 * @param pValue1 The first value.
768 * @param pValue2 The second value.
769 */
[60484]770DECLINLINE(bool) RTUInt32IsLarger(PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[52335]771{
[60484]772#ifdef RTUINT32_HAVE_32BIT_BASICS
773 return pValue1->u > pValue2->u;
774#else
[52335]775 return pValue1->s.Hi > pValue2->s.Hi
776 || ( pValue1->s.Hi == pValue2->s.Hi
777 && pValue1->s.Lo > pValue2->s.Lo);
778#endif
779}
780
781
782/**
[60482]783 * Tests if a 64-bit unsigned integer value is larger or equal than another.
[52335]784 *
785 * @returns true if the first value is larger or equal, false if not.
786 * @param pValue1 The first value.
787 * @param pValue2 The second value.
788 */
[60484]789DECLINLINE(bool) RTUInt32IsLargerOrEqual(PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[52335]790{
[60484]791#ifdef RTUINT32_HAVE_32BIT_BASICS
792 return pValue1->u >= pValue2->u;
793#else
[52335]794 return pValue1->s.Hi > pValue2->s.Hi
795 || ( pValue1->s.Hi == pValue2->s.Hi
796 && pValue1->s.Lo >= pValue2->s.Lo);
797#endif
798}
799
800
801/**
[60482]802 * Tests if two 64-bit unsigned integer values not equal.
[35488]803 *
804 * @returns true if equal, false if not equal.
805 * @param pValue1 The first value.
806 * @param pValue2 The second value.
807 */
[60484]808DECLINLINE(bool) RTUInt32IsEqual(PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[35488]809{
[60484]810#ifdef RTUINT32_HAVE_32BIT_BASICS
811 return pValue1->u == pValue2->u;
812#else
[35488]813 return pValue1->s.Hi == pValue2->s.Hi
814 && pValue1->s.Lo == pValue2->s.Lo;
815#endif
816}
817
818
819/**
[60482]820 * Tests if two 64-bit unsigned integer values are not equal.
[35488]821 *
822 * @returns true if not equal, false if equal.
823 * @param pValue1 The first value.
824 * @param pValue2 The second value.
825 */
[60484]826DECLINLINE(bool) RTUInt32IsNotEqual(PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[35488]827{
[60484]828 return !RTUInt32IsEqual(pValue1, pValue2);
[35488]829}
830
831
832/**
[60484]833 * Sets a bit in a 32-bit unsigned integer type.
[35488]834 *
835 * @returns pValueResult.
836 * @param pValueResult The input and output value.
837 * @param iBit The bit to set.
838 */
[60484]839DECLINLINE(PRTUINT32U) RTUInt32BitSet(PRTUINT32U pValueResult, unsigned iBit)
[35488]840{
[60484]841#ifdef RTUINT32_HAVE_32BIT_BASICS
[60482]842 if (iBit < 32)
[60484]843 pValueResult->u |= RT_BIT_32(iBit);
[35488]844#else
[60484]845 if (iBit < 16)
846 pValueResult->s.Lo |= UINT16_C(1) << iBit;
847 else if (iBit < 32)
[60482]848 pValueResult->s.Hi |= UINT16_C(1) << (iBit - 32);
[35488]849#endif
850 return pValueResult;
851}
852
853
854/**
[60484]855 * Sets a bit in a 32-bit unsigned integer type.
[35488]856 *
857 * @returns pValueResult.
858 * @param pValueResult The input and output value.
859 * @param iBit The bit to set.
860 */
[60484]861DECLINLINE(PRTUINT32U) RTUInt32BitClear(PRTUINT32U pValueResult, unsigned iBit)
[35488]862{
[60484]863#ifdef RTUINT32_HAVE_32BIT_BASICS
[60482]864 if (iBit < 32)
[60484]865 pValueResult->u &= ~RT_BIT_32(iBit);
866
867#else
868 if (iBit < 16)
[60482]869 pValueResult->s.Lo &= ~RT_BIT_32(iBit);
[60484]870 else if (iBit < 32)
[60482]871 pValueResult->s.Hi &= ~RT_BIT_32(iBit - 32);
[35488]872#endif
873 return pValueResult;
874}
875
876
877/**
[60484]878 * Tests if a bit in a 32-bit unsigned integer value is set.
[35488]879 *
880 * @returns pValueResult.
881 * @param pValueResult The input and output value.
882 * @param iBit The bit to test.
883 */
[60484]884DECLINLINE(bool) RTUInt32BitTest(PRTUINT32U pValueResult, unsigned iBit)
[35488]885{
886 bool fRc;
[60484]887#ifdef RTUINT32_HAVE_32BIT_BASICS
[60482]888 if (iBit < 32)
[60484]889 fRc = RT_BOOL(pValueResult->u & RT_BIT_32(iBit));
[35488]890#else
[60484]891 if (iBit < 16)
892 fRc = RT_BOOL(pValueResult->s.Lo & (UINT16_C(1) << iBit));
893 else if (iBit < 32)
894 fRc = RT_BOOL(pValueResult->s.Hi & (UINT16_C(1) << (iBit - 64)));
[35488]895#endif
896 else
897 fRc = false;
898 return fRc;
899}
900
901
902/**
[60484]903 * Set a range of bits a 32-bit unsigned integer value.
[35488]904 *
905 * @returns pValueResult.
906 * @param pValueResult The input and output value.
907 * @param iFirstBit The first bit to test.
908 * @param cBits The number of bits to set.
909 */
[60484]910DECLINLINE(PRTUINT32U) RTUInt32BitSetRange(PRTUINT32U pValueResult, unsigned iFirstBit, unsigned cBits)
[35488]911{
912 /* bounds check & fix. */
[60484]913 if (iFirstBit < 32)
[35488]914 {
[60484]915#ifdef RTUINT32_HAVE_32BIT_BASICS
[35488]916 if (iFirstBit + cBits < 32)
[60484]917 pValueResult->u |= (RT_BIT_32(cBits) - 1) << iFirstBit;
[35488]918 else
[60484]919 pValueResult->u = UINT32_MAX << iFirstBit;
[60482]920#else
[60484]921 if (iFirstBit + cBits > 32)
922 cBits = 32 - iFirstBit;
[60482]923 if (iFirstBit + cBits < 16)
[60484]924 pValueResult->s.Lo |= ((UINT16_C(1) << cBits) - 1) << iFirstBit;
[60482]925 else if (iFirstBit + cBits < 32 && iFirstBit >= 16)
[60484]926 pValueResult->s.Hi |= ((UINT16_C(1) << cBits) - 1) << (iFirstBit - 16);
[60482]927 else
[60484]928 while (cBits-- > 0)
929 RTUInt32BitSet(pValueResult, iFirstBit++);
[35488]930#endif
931 }
932 return pValueResult;
933}
934
935
936/**
[60484]937 * Test if all the bits of a 32-bit unsigned integer value are set.
[35488]938 *
939 * @returns true if they are, false if they aren't.
940 * @param pValue The input and output value.
941 */
[60484]942DECLINLINE(bool) RTUInt32BitAreAllSet(PRTUINT32U pValue)
[35488]943{
[60485]944 return pValue->s.Hi == UINT16_MAX
945 && pValue->s.Lo == UINT16_MAX;
[35488]946}
947
948
949/**
[60484]950 * Test if all the bits of a 32-bit unsigned integer value are clear.
[35488]951 *
952 * @returns true if they are, false if they aren't.
953 * @param pValue The input and output value.
954 */
[60484]955DECLINLINE(bool) RTUInt32BitAreAllClear(PRTUINT32U pValue)
[35488]956{
[60484]957 return RTUInt32IsZero(pValue);
[35488]958}
959
[52335]960
[60484]961DECLINLINE(unsigned) RTUInt32BitCount(PCRTUINT32U pValue)
[52335]962{
[60482]963 unsigned cBits;
[52335]964 if (pValue->s.Hi != 0)
[60484]965 cBits = 16 + ASMBitLastSetU16(pValue->s.Hi);
[52335]966 else
[60484]967 cBits = ASMBitLastSetU16(pValue->s.Lo);
[52335]968 return cBits;
969}
970
971
972/**
[60484]973 * Divides a 32-bit unsigned integer value by another, returning both quotient
[52335]974 * and remainder.
975 *
976 * @returns pQuotient, NULL if pValue2 is 0.
977 * @param pQuotient Where to return the quotient.
978 * @param pRemainder Where to return the remainder.
979 * @param pValue1 The dividend value.
980 * @param pValue2 The divisor value.
981 */
[60484]982DECLINLINE(PRTUINT32U) RTUInt32DivRem(PRTUINT32U pQuotient, PRTUINT32U pRemainder, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
[52335]983{
984 int iDiff;
985
986 /*
987 * Sort out all the special cases first.
988 */
989 /* Divide by zero or 1? */
990 if (!pValue2->s.Hi)
991 {
992 if (!pValue2->s.Lo)
993 return NULL;
994
995 if (pValue2->s.Lo == 1)
996 {
[60484]997 RTUInt32SetZero(pRemainder);
[52335]998 *pQuotient = *pValue1;
999 return pQuotient;
1000 }
[60484]1001 /** @todo RTUInt32DivModByU32 */
[52335]1002 }
1003
1004 /* Dividend is smaller? */
[60484]1005 iDiff = RTUInt32Compare(pValue1, pValue2);
[52335]1006 if (iDiff < 0)
1007 {
1008 *pRemainder = *pValue1;
[60484]1009 RTUInt32SetZero(pQuotient);
[52335]1010 }
1011
1012 /* The values are equal? */
1013 else if (iDiff == 0)
1014 {
[60484]1015 RTUInt32SetZero(pRemainder);
1016 RTUInt32AssignU8(pQuotient, 1);
[52335]1017 }
1018 else
1019 {
1020 /*
1021 * Prepare.
1022 */
[60484]1023 unsigned iBitAdder = RTUInt32BitCount(pValue1) - RTUInt32BitCount(pValue2);
1024 RTUINT32U NormDivisor = *pValue2;
[52335]1025 if (iBitAdder)
1026 {
[60484]1027 RTUInt32ShiftLeft(&NormDivisor, pValue2, iBitAdder);
1028 if (RTUInt32IsLarger(&NormDivisor, pValue1))
[52335]1029 {
[60484]1030 RTUInt32AssignShiftRight(&NormDivisor, 1);
[52335]1031 iBitAdder--;
1032 }
1033 }
1034 else
1035 NormDivisor = *pValue2;
1036
[60484]1037 RTUInt32SetZero(pQuotient);
[52335]1038 *pRemainder = *pValue1;
1039
1040 /*
1041 * Do the division.
1042 */
[60484]1043 if (RTUInt32IsLargerOrEqual(pRemainder, pValue2))
[52335]1044 {
1045 for (;;)
1046 {
[60484]1047 if (RTUInt32IsLargerOrEqual(pRemainder, &NormDivisor))
[52335]1048 {
[60484]1049 RTUInt32AssignSub(pRemainder, &NormDivisor);
1050 RTUInt32AssignOrBit(pQuotient, iBitAdder);
[52335]1051 }
[60484]1052 if (RTUInt32IsSmaller(pRemainder, pValue2))
[52335]1053 break;
[60484]1054 RTUInt32AssignShiftRight(&NormDivisor, 1);
[52335]1055 iBitAdder--;
1056 }
1057 }
1058 }
1059 return pQuotient;
1060}
1061
1062
[35488]1063/** @} */
1064
1065RT_C_DECLS_END
1066
[76585]1067#endif /* !IPRT_INCLUDED_uint32_h */
[35488]1068
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