source: mainline/uspace/lib/softint/generic/division.c@ 8348846

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8348846 was 8348846, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

Fix symbols in libsoftint.

  • Property mode set to 100644
File size: 5.9 KB
Line 
1/*
2 * Copyright (c) 2006 Josef Cejka
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup softint
30 * @{
31 */
32/**
33 * @file
34 * SW implementation of 32 and 64 bit division and modulo.
35 */
36
37#include <alias.h>
38#include <division.h>
39
40#define ABSVAL(x) ((x) > 0 ? (x) : -(x))
41#define SGN(x) ((x) >= 0 ? 1 : 0)
42
43static unsigned int divandmod32(unsigned int a, unsigned int b,
44 unsigned int *remainder)
45{
46 unsigned int result;
47 int steps = sizeof(unsigned int) * 8;
48
49 *remainder = 0;
50 result = 0;
51
52 if (b == 0) {
53 /* FIXME: division by zero */
54 return 0;
55 }
56
57 if (a < b) {
58 *remainder = a;
59 return 0;
60 }
61
62 for (; steps > 0; steps--) {
63 /* shift one bit to remainder */
64 *remainder = ((*remainder) << 1) | (( a >> 31) & 0x1);
65 result <<= 1;
66
67 if (*remainder >= b) {
68 *remainder -= b;
69 result |= 0x1;
70 }
71 a <<= 1;
72 }
73
74 return result;
75}
76
77static unsigned long long divandmod64(unsigned long long a,
78 unsigned long long b, unsigned long long *remainder)
79{
80 unsigned long long result;
81 int steps = sizeof(unsigned long long) * 8;
82
83 *remainder = 0;
84 result = 0;
85
86 if (b == 0) {
87 /* FIXME: division by zero */
88 return 0;
89 }
90
91 if (a < b) {
92 *remainder = a;
93 return 0;
94 }
95
96 for (; steps > 0; steps--) {
97 /* shift one bit to remainder */
98 *remainder = ((*remainder) << 1) | ((a >> 63) & 0x1);
99 result <<= 1;
100
101 if (*remainder >= b) {
102 *remainder -= b;
103 result |= 0x1;
104 }
105 a <<= 1;
106 }
107
108 return result;
109}
110
111/* 32bit integer division */
112int __divsi3(int a, int b)
113{
114 unsigned int rem;
115 int result = (int) divandmod32(ABSVAL(a), ABSVAL(b), &rem);
116
117 if (SGN(a) == SGN(b))
118 return result;
119
120 return -result;
121}
122
123/* 64bit integer division */
124long long __divti3(long long a, long long b)
125{
126 unsigned long long rem;
127 long long result = (long long) divandmod64(ABSVAL(a), ABSVAL(b), &rem);
128
129 if (SGN(a) == SGN(b))
130 return result;
131
132 return -result;
133}
134
135/* 32bit unsigned integer division */
136unsigned int __udivsi3(unsigned int a, unsigned int b)
137{
138 unsigned int rem;
139 return divandmod32(a, b, &rem);
140}
141
142/* 64bit unsigned integer division */
143unsigned long long __udivti3(unsigned long long a, unsigned long long b)
144{
145 unsigned long long rem;
146 return divandmod64(a, b, &rem);
147}
148
149/* 32bit remainder of the signed division */
150int __modsi3(int a, int b)
151{
152 unsigned int rem;
153 divandmod32(a, b, &rem);
154
155 /* if divident is negative, remainder must be too */
156 if (!(SGN(a)))
157 return -((int) rem);
158
159 return (int) rem;
160}
161
162/* 64bit remainder of the signed division */
163long long __modti3(long long a, long long b)
164{
165 unsigned long long rem;
166 divandmod64(a, b, &rem);
167
168 /* if divident is negative, remainder must be too */
169 if (!(SGN(a)))
170 return -((long long) rem);
171
172 return (long long) rem;
173}
174
175/* 32bit remainder of the unsigned division */
176unsigned int __umodsi3(unsigned int a, unsigned int b)
177{
178 unsigned int rem;
179 divandmod32(a, b, &rem);
180 return rem;
181}
182
183/* 64bit remainder of the unsigned division */
184unsigned long long __umodti3(unsigned long long a, unsigned long long b)
185{
186 unsigned long long rem;
187 divandmod64(a, b, &rem);
188 return rem;
189}
190
191int __divmodsi3(int a, int b, int *c)
192{
193 unsigned int rem;
194 int result = (int) divandmod32(ABSVAL(a), ABSVAL(b), &rem);
195
196 if (SGN(a) == SGN(b)) {
197 *c = rem;
198 return result;
199 }
200
201 *c = -rem;
202 return -result;
203}
204
205int __divmodsi4(int a, int b, int *c)
206{
207 return __divmodsi3(a, b, c);
208}
209
210unsigned int __udivmodsi3(unsigned int a, unsigned int b,
211 unsigned int *c)
212{
213 return divandmod32(a, b, c);
214}
215
216unsigned int __udivmodsi4(unsigned int a, unsigned int b,
217 unsigned int *c)
218{
219 return divandmod32(a, b, c);
220}
221
222long long __divmodti3(long long a, long long b, long long *c)
223{
224 unsigned long long rem;
225 long long result = (int) divandmod64(ABSVAL(a), ABSVAL(b), &rem);
226
227 if (SGN(a) == SGN(b)) {
228 *c = rem;
229 return result;
230 }
231
232 *c = -rem;
233 return -result;
234}
235
236
237long long __divmodti4(long long a, long long b, long long *c)
238{
239 unsigned long long rem;
240 long long result = (int) divandmod64(ABSVAL(a), ABSVAL(b), &rem);
241
242 if (SGN(a) == SGN(b)) {
243 *c = rem;
244 return result;
245 }
246
247 *c = -rem;
248 return -result;
249}
250
251unsigned long long __udivmodti3(unsigned long long a, unsigned long long b,
252 unsigned long long *c)
253{
254 return divandmod64(a, b, c);
255}
256
257unsigned long long __udivmodti4(unsigned long long a, unsigned long long b,
258 unsigned long long *c)
259{
260 return divandmod64(a, b, c);
261}
262
263long ALIAS(__div, i3);
264long ALIAS(__mod, i3);
265long ALIAS(__divmod, i3);
266long ALIAS(__divmod, i4);
267unsigned long ALIAS(__udiv, i3);
268unsigned long ALIAS(__umod, i3);
269unsigned long ALIAS(__udivmod, i3);
270unsigned long ALIAS(__udivmod, i4);
271
272/** @}
273 */
Note: See TracBrowser for help on using the repository browser.