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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 88d5c1e was 88d5c1e, checked in by Martin Decky <martin@…>, 13 years ago

softfloat redesign

  • avoid hardwired type sizes, actual sizes are determined at compile-time
  • add basic support for x87 extended-precision data types (stored as 96bit long double)
  • a lot of coding style changes (removal of CamelCase, etc.)
  • Property mode set to 100644
File size: 5.0 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 <division.h>
38
39#define ABSVAL(x) ((x) > 0 ? (x) : -(x))
40#define SGN(x) ((x) >= 0 ? 1 : 0)
41
42static unsigned int divandmod32(unsigned int a, unsigned int b,
43 unsigned int *remainder)
44{
45 unsigned int result;
46 int steps = sizeof(unsigned int) * 8;
47
48 *remainder = 0;
49 result = 0;
50
51 if (b == 0) {
52 /* FIXME: division by zero */
53 return 0;
54 }
55
56 if (a < b) {
57 *remainder = a;
58 return 0;
59 }
60
61 for (; steps > 0; steps--) {
62 /* shift one bit to remainder */
63 *remainder = ((*remainder) << 1) | (( a >> 31) & 0x1);
64 result <<= 1;
65
66 if (*remainder >= b) {
67 *remainder -= b;
68 result |= 0x1;
69 }
70 a <<= 1;
71 }
72
73 return result;
74}
75
76static unsigned long long divandmod64(unsigned long long a,
77 unsigned long long b, unsigned long long *remainder)
78{
79 unsigned long long result;
80 int steps = sizeof(unsigned long long) * 8;
81
82 *remainder = 0;
83 result = 0;
84
85 if (b == 0) {
86 /* FIXME: division by zero */
87 return 0;
88 }
89
90 if (a < b) {
91 *remainder = a;
92 return 0;
93 }
94
95 for (; steps > 0; steps--) {
96 /* shift one bit to remainder */
97 *remainder = ((*remainder) << 1) | ((a >> 63) & 0x1);
98 result <<= 1;
99
100 if (*remainder >= b) {
101 *remainder -= b;
102 result |= 0x1;
103 }
104 a <<= 1;
105 }
106
107 return result;
108}
109
110/* 32bit integer division */
111int __divsi3(int a, int b)
112{
113 unsigned int rem;
114 int result = (int) divandmod32(ABSVAL(a), ABSVAL(b), &rem);
115
116 if (SGN(a) == SGN(b))
117 return result;
118
119 return -result;
120}
121
122/* 64bit integer division */
123long long __divdi3(long long a, long long b)
124{
125 unsigned long long rem;
126 long long result = (long long) divandmod64(ABSVAL(a), ABSVAL(b), &rem);
127
128 if (SGN(a) == SGN(b))
129 return result;
130
131 return -result;
132}
133
134/* 32bit unsigned integer division */
135unsigned int __udivsi3(unsigned int a, unsigned int b)
136{
137 unsigned int rem;
138 return divandmod32(a, b, &rem);
139}
140
141/* 64bit unsigned integer division */
142unsigned long long __udivdi3(unsigned long long a, unsigned long long b)
143{
144 unsigned long long rem;
145 return divandmod64(a, b, &rem);
146}
147
148/* 32bit remainder of the signed division */
149int __modsi3(int a, int b)
150{
151 unsigned int rem;
152 divandmod32(a, b, &rem);
153
154 /* if divident is negative, remainder must be too */
155 if (!(SGN(a)))
156 return -((int) rem);
157
158 return (int) rem;
159}
160
161/* 64bit remainder of the signed division */
162long long __moddi3(long long a, long long b)
163{
164 unsigned long long rem;
165 divandmod64(a, b, &rem);
166
167 /* if divident is negative, remainder must be too */
168 if (!(SGN(a)))
169 return -((long long) rem);
170
171 return (long long) rem;
172}
173
174/* 32bit remainder of the unsigned division */
175unsigned int __umodsi3(unsigned int a, unsigned int b)
176{
177 unsigned int rem;
178 divandmod32(a, b, &rem);
179 return rem;
180}
181
182/* 64bit remainder of the unsigned division */
183unsigned long long __umoddi3(unsigned long long a, unsigned long long b)
184{
185 unsigned long long rem;
186 divandmod64(a, b, &rem);
187 return rem;
188}
189
190int __divmodsi3(int a, int b, int *c)
191{
192 unsigned int rem;
193 int result = (int) divandmod32(ABSVAL(a), ABSVAL(b), &rem);
194
195 if (SGN(a) == SGN(b)) {
196 *c = rem;
197 return result;
198 }
199
200 *c = -rem;
201 return -result;
202}
203
204unsigned int __udivmodsi3(unsigned int a, unsigned int b,
205 unsigned int *c)
206{
207 return divandmod32(a, b, c);
208}
209
210long long __divmoddi3(long long a, long long b, long long *c)
211{
212 unsigned long long rem;
213 long long result = (int) divandmod64(ABSVAL(a), ABSVAL(b), &rem);
214
215 if (SGN(a) == SGN(b)) {
216 *c = rem;
217 return result;
218 }
219
220 *c = -rem;
221 return -result;
222}
223
224unsigned long long __udivmoddi3(unsigned long long a, unsigned long long b,
225 unsigned long long *c)
226{
227 return divandmod64(a, b, c);
228}
229
230/** @}
231 */
Note: See TracBrowser for help on using the repository browser.