VirtualBox

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

Last change on this file since 62485 was 60485, checked in by vboxsync, 9 years ago

bs3kit: 8086 friendly 32-bit and 64-bit unsigned integer division.

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