ReactOS  0.4.15-dev-4603-gb922b6d
__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_
21 typedef unsigned long long UINT3264;
22 typedef long long INT3264;
23 typedef struct
24 {
25  unsigned long long quotient; /* to be returned in R0,R1 */
26  unsigned long long modulus; /* to be returned in R2,R3 */
27 } RETURN_TYPE;
28 #define _CountLeadingZeros _CountLeadingZeros64
29 #else
30 typedef unsigned int UINT3264;
31 typedef int INT3264;
32 typedef unsigned long long RETURN_TYPE; /* to be returned in R0,R1 */
33 #endif
34 
35 __forceinline
36 void
37 __brkdiv0(void)
38 {
39  __emit(0xDEF9);
40 }
41 
42 typedef union _ARM_DIVRESULT
43 {
45  struct
46  {
49  } data;
51 
55  UINT3264 dividend)
56 {
59  UINT3264 mask;
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 }
RETURN_TYPE __rt_div_worker(UINT3264 divisor, UINT3264 dividend)
#define shift
Definition: input.c:1756
GLuint64EXT * result
Definition: glext.h:11304
unsigned long long RETURN_TYPE
struct _ARM_DIVRESULT::@4059 data
__INTRIN_INLINE unsigned _CountLeadingZeros(long Mask)
Definition: intrin_arm.h:47
RETURN_TYPE raw_data
__forceinline void __brkdiv0(void)
GLenum GLint GLuint mask
Definition: glext.h:6028
union _ARM_DIVRESULT ARM_DIVRESULT
int INT3264
GLuint divisor
Definition: glext.h:6313
unsigned int UINT3264