ReactOS 0.4.16-dev-197-g92996da
__rt_div_worker.h
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS CRT library
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Implementation of __rt_div_worker
5 * COPYRIGHT: Copyright 2015 Timo Kreuzer <timo.kreuzer@reactos.org>
6 * Copyright 2021 Roman Masanin <36927roma@gmail.com>
7 */
8
9/*
10 * See also:
11 * http://research.microsoft.com/pubs/70645/tr-2008-141.pdf
12 * https://web.archive.org/web/20100110044008/http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/arm/_div10.s.htm
13 * https://github.com/bawoodruff/BeagleBoard/blob/2731e3174af6daefe4a287a6be82e5ff9c46c99a/OS/BootLoader/Runtime/_udiv.c
14 * https://github.com/bawoodruff/BeagleBoard/blob/2731e3174af6daefe4a287a6be82e5ff9c46c99a/OS/BootLoader/Runtime/arm/_udivsi3.s
15 * https://github.com/bawoodruff/BeagleBoard/blob/2731e3174af6daefe4a287a6be82e5ff9c46c99a/OS/BootLoader/Runtime/arm/divide.s
16 * https://github.com/qemu/edk2/blob/e3c7db50cac9125607df49d5873991df6df11eae/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uldiv.asm
17 * https://github.com/jmonesti/qemu-4.1.1/blob/55fb6a81039a62174c2763759324c43a67d752a1/roms/ipxe/src/arch/arm32/libgcc/lldivmod.S
18 */
19
20#ifdef _USE_64_BITS_
21typedef unsigned long long UINT3264;
22typedef long long INT3264;
23typedef struct
24{
25 unsigned long long quotient; /* to be returned in R0,R1 */
26 unsigned long long modulus; /* to be returned in R2,R3 */
28#define _CountLeadingZeros _CountLeadingZeros64
29#else
30typedef unsigned int UINT3264;
31typedef int INT3264;
32typedef unsigned long long RETURN_TYPE; /* to be returned in R0,R1 */
33#endif
34
35__forceinline
36void
38{
39 __emit(0xDEF9);
40}
41
42typedef union _ARM_DIVRESULT
43{
45 struct
46 {
51
55 UINT3264 dividend)
56{
60 UINT3264 quotient;
61#ifdef _SIGNED_DIV_
62 int dividend_sign = 0;
63 int divisor_sign = 0;
64#endif // _SIGNED_DIV_
65
66 if (divisor == 0)
67 {
68 /* Raise divide by zero error */
69 __brkdiv0();
70 }
71
72#ifdef _SIGNED_DIV_
73 if ((INT3264)dividend < 0)
74 {
75 dividend_sign = 1;
76 dividend = -(INT3264)dividend;
77 }
78
79 if ((INT3264)divisor < 0)
80 {
81 divisor_sign = 1;
83 }
84#endif // _SIGNED_DIV_
85
86 if (divisor > dividend)
87 {
88 result.data.quotient = 0;
89#ifdef _SIGNED_DIV_
90 if (dividend_sign)
91 dividend = -(INT3264)dividend;
92#endif // _SIGNED_DIV_
93 result.data.modulus = dividend;
94 return result.raw_data;
95 }
96
97 /* Get the difference in count of leading zeros between dividend and divisor */
99 shift -= _CountLeadingZeros(dividend);
100
101 /* Shift the divisor to the left, so that it's highest bit is the same
102 as the highest bit of the dividend */
103 divisor <<= shift;
104
105 mask = (UINT3264)1 << shift;
106
107 quotient = 0;
108 do
109 {
110 if (dividend >= divisor)
111 {
112 quotient |= mask;
113 dividend -= divisor;
114 }
115 divisor >>= 1;
116 mask >>= 1;
117 }
118 while (mask);
119
120#ifdef _SIGNED_DIV_
121 if (dividend_sign ^ divisor_sign)
122 {
123 quotient = -(INT3264)quotient;
124 }
125
126 if (dividend_sign)
127 {
128 dividend = -(INT3264)dividend;
129 }
130#endif // _SIGNED_DIV_
131
132 result.data.quotient = quotient;
133 result.data.modulus = dividend;
134 return result.raw_data;
135}
__forceinline void __brkdiv0(void)
unsigned int UINT3264
union _ARM_DIVRESULT ARM_DIVRESULT
unsigned long long RETURN_TYPE
int INT3264
#define __rt_div_worker
Definition: __rt_sdiv.c:9
GLenum GLint GLuint mask
Definition: glext.h:6028
GLuint divisor
Definition: glext.h:6313
GLuint64EXT * result
Definition: glext.h:11304
__INTRIN_INLINE unsigned _CountLeadingZeros(long Mask)
Definition: intrin_arm.h:47
#define shift
Definition: input.c:1755
struct _ARM_DIVRESULT::@4305 data
RETURN_TYPE raw_data