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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3cf22f9 was 3bacee1, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Make ccheck-fix again and commit more good files.

  • Property mode set to 100644
File size: 5.4 KB
RevLine 
[c3a2f0b]1/*
[df4ed85]2 * Copyright (c) 2006 Josef Cejka
[c3a2f0b]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
[231a60a]29/** @addtogroup softint
[b2951e2]30 * @{
[1b20da0]31 */
[b2951e2]32/**
33 * @file
34 * SW implementation of 32 and 64 bit division and modulo.
35 */
36
[c3a2f0b]37#include <division.h>
38
[5a6a42f]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)
[c3a2f0b]44{
45 unsigned int result;
[1b20da0]46 int steps = sizeof(unsigned int) * 8;
[a35b458]47
[c3a2f0b]48 *remainder = 0;
49 result = 0;
[a35b458]50
[c3a2f0b]51 if (b == 0) {
52 /* FIXME: division by zero */
53 return 0;
54 }
[a35b458]55
[5a6a42f]56 if (a < b) {
[c3a2f0b]57 *remainder = a;
58 return 0;
59 }
[a35b458]60
[5a6a42f]61 for (; steps > 0; steps--) {
[c3a2f0b]62 /* shift one bit to remainder */
[3bacee1]63 *remainder = ((*remainder) << 1) | ((a >> 31) & 0x1);
[c3a2f0b]64 result <<= 1;
[a35b458]65
[c3a2f0b]66 if (*remainder >= b) {
[5a6a42f]67 *remainder -= b;
68 result |= 0x1;
[c3a2f0b]69 }
70 a <<= 1;
71 }
[a35b458]72
[c3a2f0b]73 return result;
74}
75
[5a6a42f]76static unsigned long long divandmod64(unsigned long long a,
77 unsigned long long b, unsigned long long *remainder)
[c3a2f0b]78{
79 unsigned long long result;
[5a6a42f]80 int steps = sizeof(unsigned long long) * 8;
[a35b458]81
[c3a2f0b]82 *remainder = 0;
83 result = 0;
[a35b458]84
[c3a2f0b]85 if (b == 0) {
86 /* FIXME: division by zero */
87 return 0;
88 }
[a35b458]89
[5a6a42f]90 if (a < b) {
[c3a2f0b]91 *remainder = a;
92 return 0;
93 }
[a35b458]94
[5a6a42f]95 for (; steps > 0; steps--) {
[c3a2f0b]96 /* shift one bit to remainder */
[5a6a42f]97 *remainder = ((*remainder) << 1) | ((a >> 63) & 0x1);
[c3a2f0b]98 result <<= 1;
[a35b458]99
[c3a2f0b]100 if (*remainder >= b) {
[5a6a42f]101 *remainder -= b;
102 result |= 0x1;
[c3a2f0b]103 }
104 a <<= 1;
105 }
[a35b458]106
[c3a2f0b]107 return result;
108}
109
110/* 32bit integer division */
[5a6a42f]111int __divsi3(int a, int b)
[c3a2f0b]112{
113 unsigned int rem;
[5a6a42f]114 int result = (int) divandmod32(ABSVAL(a), ABSVAL(b), &rem);
[a35b458]115
[5a6a42f]116 if (SGN(a) == SGN(b))
117 return result;
[a35b458]118
[c3a2f0b]119 return -result;
120}
121
122/* 64bit integer division */
[2467b41]123long long __divdi3(long long a, long long b)
[c3a2f0b]124{
125 unsigned long long rem;
[5a6a42f]126 long long result = (long long) divandmod64(ABSVAL(a), ABSVAL(b), &rem);
[a35b458]127
[5a6a42f]128 if (SGN(a) == SGN(b))
129 return result;
[a35b458]130
[c3a2f0b]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 */
[2467b41]142unsigned long long __udivdi3(unsigned long long a, unsigned long long b)
[c3a2f0b]143{
[5a6a42f]144 unsigned long long rem;
[c3a2f0b]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);
[a35b458]153
[c3a2f0b]154 /* if divident is negative, remainder must be too */
[5a6a42f]155 if (!(SGN(a)))
156 return -((int) rem);
[a35b458]157
[5a6a42f]158 return (int) rem;
[c3a2f0b]159}
160
161/* 64bit remainder of the signed division */
[2467b41]162long long __moddi3(long long a, long long b)
[c3a2f0b]163{
164 unsigned long long rem;
165 divandmod64(a, b, &rem);
[a35b458]166
[c3a2f0b]167 /* if divident is negative, remainder must be too */
[5a6a42f]168 if (!(SGN(a)))
169 return -((long long) rem);
[a35b458]170
[5a6a42f]171 return (long long) rem;
[c3a2f0b]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 */
[2467b41]183unsigned long long __umoddi3(unsigned long long a, unsigned long long b)
[c3a2f0b]184{
185 unsigned long long rem;
186 divandmod64(a, b, &rem);
187 return rem;
188}
189
[88d5c1e]190int __divmodsi3(int a, int b, int *c)
191{
192 unsigned int rem;
193 int result = (int) divandmod32(ABSVAL(a), ABSVAL(b), &rem);
[a35b458]194
[88d5c1e]195 if (SGN(a) == SGN(b)) {
196 *c = rem;
197 return result;
198 }
[a35b458]199
[88d5c1e]200 *c = -rem;
201 return -result;
202}
203
[5a6a42f]204unsigned int __udivmodsi3(unsigned int a, unsigned int b,
205 unsigned int *c)
206{
207 return divandmod32(a, b, c);
208}
209
[2467b41]210long long __divmoddi3(long long a, long long b, long long *c)
[88d5c1e]211{
212 unsigned long long rem;
213 long long result = (int) divandmod64(ABSVAL(a), ABSVAL(b), &rem);
[a35b458]214
[88d5c1e]215 if (SGN(a) == SGN(b)) {
216 *c = rem;
217 return result;
218 }
[a35b458]219
[88d5c1e]220 *c = -rem;
221 return -result;
222}
223
[2467b41]224long long __divmoddi4(long long a, long long b, long long *c)
[9abe2e5]225{
226 unsigned long long rem;
227 long long result = (int) divandmod64(ABSVAL(a), ABSVAL(b), &rem);
[a35b458]228
[9abe2e5]229 if (SGN(a) == SGN(b)) {
230 *c = rem;
231 return result;
232 }
[a35b458]233
[9abe2e5]234 *c = -rem;
235 return -result;
236}
237
[2467b41]238unsigned long long __udivmoddi3(unsigned long long a, unsigned long long b,
[5a6a42f]239 unsigned long long *c)
[c3a2f0b]240{
241 return divandmod64(a, b, c);
242}
243
[2467b41]244unsigned long long __udivmoddi4(unsigned long long a, unsigned long long b,
[9abe2e5]245 unsigned long long *c)
246{
247 return divandmod64(a, b, c);
248}
249
[b2951e2]250/** @}
251 */
Note: See TracBrowser for help on using the repository browser.