source: mainline/boot/genarch/src/division.c@ 8df0306

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8df0306 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: 4.9 KB
RevLine 
[4872160]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/** @file
30 */
31
32#include <genarch/division.h>
33
34#define ABSVAL(x) ((x) > 0 ? (x) : -(x))
35#define SGN(x) ((x) >= 0 ? 1 : 0)
36
37static unsigned int divandmod32(unsigned int a, unsigned int b,
38 unsigned int *remainder)
39{
40 unsigned int result;
[1b20da0]41 int steps = sizeof(unsigned int) * 8;
[a35b458]42
[4872160]43 *remainder = 0;
44 result = 0;
[a35b458]45
[4872160]46 if (b == 0) {
47 /* FIXME: division by zero */
48 return 0;
49 }
[a35b458]50
[4872160]51 if (a < b) {
52 *remainder = a;
53 return 0;
54 }
[a35b458]55
[4872160]56 for (; steps > 0; steps--) {
57 /* shift one bit to remainder */
[3bacee1]58 *remainder = ((*remainder) << 1) | ((a >> 31) & 0x1);
[4872160]59 result <<= 1;
[a35b458]60
[4872160]61 if (*remainder >= b) {
62 *remainder -= b;
63 result |= 0x1;
64 }
65 a <<= 1;
66 }
[a35b458]67
[4872160]68 return result;
69}
70
71static unsigned long long divandmod64(unsigned long long a,
72 unsigned long long b, unsigned long long *remainder)
73{
74 unsigned long long result;
[5a6a42f]75 int steps = sizeof(unsigned long long) * 8;
[a35b458]76
[4872160]77 *remainder = 0;
78 result = 0;
[a35b458]79
[4872160]80 if (b == 0) {
81 /* FIXME: division by zero */
82 return 0;
83 }
[a35b458]84
[4872160]85 if (a < b) {
86 *remainder = a;
87 return 0;
88 }
[a35b458]89
[4872160]90 for (; steps > 0; steps--) {
91 /* shift one bit to remainder */
92 *remainder = ((*remainder) << 1) | ((a >> 63) & 0x1);
93 result <<= 1;
[a35b458]94
[4872160]95 if (*remainder >= b) {
96 *remainder -= b;
97 result |= 0x1;
98 }
99 a <<= 1;
100 }
[a35b458]101
[4872160]102 return result;
103}
104
105/* 32bit integer division */
[5a6a42f]106int __divsi3(int a, int b)
[4872160]107{
108 unsigned int rem;
109 int result = (int) divandmod32(ABSVAL(a), ABSVAL(b), &rem);
[a35b458]110
[4872160]111 if (SGN(a) == SGN(b))
112 return result;
[a35b458]113
[4872160]114 return -result;
115}
116
117/* 64bit integer division */
[5a6a42f]118long long __divdi3(long long a, long long b)
[4872160]119{
120 unsigned long long rem;
121 long long result = (long long) divandmod64(ABSVAL(a), ABSVAL(b), &rem);
[a35b458]122
[4872160]123 if (SGN(a) == SGN(b))
124 return result;
[a35b458]125
[4872160]126 return -result;
127}
128
129/* 32bit unsigned integer division */
130unsigned int __udivsi3(unsigned int a, unsigned int b)
131{
132 unsigned int rem;
133 return divandmod32(a, b, &rem);
134}
135
136/* 64bit unsigned integer division */
137unsigned long long __udivdi3(unsigned long long a, unsigned long long b)
138{
139 unsigned long long rem;
140 return divandmod64(a, b, &rem);
141}
142
143/* 32bit remainder of the signed division */
144int __modsi3(int a, int b)
145{
146 unsigned int rem;
147 divandmod32(a, b, &rem);
[a35b458]148
[4872160]149 /* if divident is negative, remainder must be too */
150 if (!(SGN(a)))
151 return -((int) rem);
[a35b458]152
[4872160]153 return (int) rem;
154}
155
156/* 64bit remainder of the signed division */
[5a6a42f]157long long __moddi3(long long a, long long b)
[4872160]158{
159 unsigned long long rem;
160 divandmod64(a, b, &rem);
[a35b458]161
[4872160]162 /* if divident is negative, remainder must be too */
163 if (!(SGN(a)))
164 return -((long long) rem);
[a35b458]165
[4872160]166 return (long long) rem;
167}
168
169/* 32bit remainder of the unsigned division */
170unsigned int __umodsi3(unsigned int a, unsigned int b)
171{
172 unsigned int rem;
173 divandmod32(a, b, &rem);
174 return rem;
175}
176
177/* 64bit remainder of the unsigned division */
178unsigned long long __umoddi3(unsigned long long a, unsigned long long b)
179{
180 unsigned long long rem;
181 divandmod64(a, b, &rem);
182 return rem;
183}
184
[c7afcba7]185int __divmodsi3(int a, int b, int *c)
186{
187 unsigned int rem;
188 int result = (int) divandmod32(ABSVAL(a), ABSVAL(b), &rem);
[a35b458]189
[c7afcba7]190 if (SGN(a) == SGN(b)) {
191 *c = rem;
192 return result;
193 }
[a35b458]194
[c7afcba7]195 *c = -rem;
196 return -result;
197}
198
[5a6a42f]199unsigned int __udivmodsi3(unsigned int a, unsigned int b,
200 unsigned int *c)
201{
202 return divandmod32(a, b, c);
203}
204
[c7afcba7]205long long __divmoddi3(long long a, long long b, long long *c)
206{
207 unsigned long long rem;
208 long long result = (int) divandmod64(ABSVAL(a), ABSVAL(b), &rem);
[a35b458]209
[c7afcba7]210 if (SGN(a) == SGN(b)) {
211 *c = rem;
212 return result;
213 }
[a35b458]214
[c7afcba7]215 *c = -rem;
216 return -result;
217}
218
[4872160]219unsigned long long __udivmoddi3(unsigned long long a, unsigned long long b,
220 unsigned long long *c)
221{
222 return divandmod64(a, b, c);
223}
224
225/** @}
226 */
Note: See TracBrowser for help on using the repository browser.