source: mainline/kernel/genarch/src/softint/division.c@ 8ccd2ea

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8ccd2ea was 7fe9c5b, checked in by Jakub Jermar <jakub@…>, 18 years ago

Minor cleanup of softint.

  • Property mode set to 100644
File size: 4.5 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 genarch
30 * @{
31 */
32/** @file
33 */
34
35#include <genarch/softint/division.h>
36
37#define ABSVAL(x) ((x) > 0 ? (x) : -(x))
38#define SGN(x) ((x) >= 0 ? 1 : 0)
39
40static unsigned int divandmod32(unsigned int a, unsigned int b,
41 unsigned int *remainder)
42{
43 unsigned int result;
44 int steps = sizeof(unsigned int) * 8;
45
46 *remainder = 0;
47 result = 0;
48
49 if (b == 0) {
50 /* FIXME: division by zero */
51 return 0;
52 }
53
54 if (a < b) {
55 *remainder = a;
56 return 0;
57 }
58
59 for (; steps > 0; steps--) {
60 /* shift one bit to remainder */
61 *remainder = ((*remainder) << 1) | (( a >> 31) & 0x1);
62 result <<= 1;
63
64 if (*remainder >= b) {
65 *remainder -= b;
66 result |= 0x1;
67 }
68 a <<= 1;
69 }
70
71 return result;
72}
73
74
75static unsigned long long divandmod64(unsigned long long a,
76 unsigned long long b, unsigned long long *remainder)
77{
78 unsigned long long result;
79 int steps = sizeof(unsigned long long) * 8;
80
81 *remainder = 0;
82 result = 0;
83
84 if (b == 0) {
85 /* FIXME: division by zero */
86 return 0;
87 }
88
89 if (a < b) {
90 *remainder = a;
91 return 0;
92 }
93
94 for (; steps > 0; steps--) {
95 /* shift one bit to remainder */
96 *remainder = ((*remainder) << 1) | ((a >> 63) & 0x1);
97 result <<= 1;
98
99 if (*remainder >= b) {
100 *remainder -= b;
101 result |= 0x1;
102 }
103 a <<= 1;
104 }
105
106 return result;
107}
108
109/* 32bit integer division */
110int __divsi3(int a, int b)
111{
112 unsigned int rem;
113 int result;
114
115 result = (int) divandmod32(ABSVAL(a), ABSVAL(b), &rem);
116
117 if (SGN(a) == SGN(b))
118 return result;
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;
127
128 result = (long long) divandmod64(ABSVAL(a), ABSVAL(b), &rem);
129
130 if (SGN(a) == SGN(b))
131 return result;
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 __udivdi3(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
160 return (int) rem;
161}
162
163/* 64bit remainder of the signed division */
164long long __moddi3(long long a,long long b)
165{
166 unsigned long long rem;
167 divandmod64(a, b, &rem);
168
169 /* if divident is negative, remainder must be too */
170 if (!(SGN(a))) {
171 return -((long long) rem);
172 }
173
174 return (long long) rem;
175}
176
177/* 32bit remainder of the unsigned division */
178unsigned int __umodsi3(unsigned int a, unsigned int b)
179{
180 unsigned int rem;
181 divandmod32(a, b, &rem);
182 return rem;
183}
184
185/* 64bit remainder of the unsigned division */
186unsigned long long __umoddi3(unsigned long long a, unsigned long long b)
187{
188 unsigned long long rem;
189 divandmod64(a, b, &rem);
190 return rem;
191}
192
193unsigned long long __udivmoddi3(unsigned long long a, unsigned long long b,
194 unsigned long long *c)
195{
196 return divandmod64(a, b, c);
197}
198
199/** @}
200 */
Note: See TracBrowser for help on using the repository browser.