2007-01-03 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / gcc / config / cris / arit.c
blobe094ea76ec0f81ba09d450c2c5a324ec8542bafa
1 /* Signed and unsigned multiplication and division and modulus for CRIS.
2 Contributed by Axis Communications.
3 Written by Hans-Peter Nilsson <hp@axis.se>, c:a 1992.
5 Copyright (C) 1998, 1999, 2000, 2001, 2002,
6 2005 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
13 later version.
15 In addition to the permissions in the GNU General Public License, the
16 Free Software Foundation gives you unlimited permission to link the
17 compiled version of this file with other programs, and to distribute
18 those programs without any restriction coming from the use of this
19 file. (The General Public License restrictions do apply in other
20 respects; for example, they cover modification of the file, and
21 distribution when not linked into another program.)
23 This file is distributed in the hope that it will be useful, but
24 WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 General Public License for more details.
28 You should have received a copy of the GNU General Public License
29 along with this program; see the file COPYING. If not, write to
30 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
31 Boston, MA 02110-1301, USA.
33 As a special exception, if you link this library with files, some of
34 which are compiled with GCC, this library does not by itself cause
35 the resulting object or executable to be covered by the GNU General
36 Public License.
37 This exception does not however invalidate any other reasons why
38 the executable file or object might be covered by the GNU General
39 Public License. */
42 /* Note that we provide prototypes for all "const" functions, to attach
43 the const attribute. This is necessary in 2.7.2 - adding the
44 attribute to the function *definition* is a syntax error.
45 This did not work with e.g. 2.1; back then, the return type had to
46 be "const". */
48 #include "config.h"
50 #if defined (__CRIS_arch_version) && __CRIS_arch_version >= 3
51 #define LZ(v) __extension__ \
52 ({ int tmp_; __asm__ ("lz %1,%0" : "=r" (tmp_) : "r" (v)); tmp_; })
53 #endif
56 #if defined (L_udivsi3) || defined (L_divsi3) || defined (L_umodsi3) \
57 || defined (L_modsi3)
58 /* Result type of divmod worker function. */
59 struct quot_rem
61 long quot;
62 long rem;
65 /* This is the worker function for div and mod. It is inlined into the
66 respective library function. Parameter A must have bit 31 == 0. */
68 static __inline__ struct quot_rem
69 do_31div (unsigned long a, unsigned long b)
70 __attribute__ ((__const__, __always_inline__));
72 static __inline__ struct quot_rem
73 do_31div (unsigned long a, unsigned long b)
75 /* Adjust operands and result if a is 31 bits. */
76 long extra = 0;
77 int quot_digits = 0;
79 if (b == 0)
81 struct quot_rem ret;
82 ret.quot = 0xffffffff;
83 ret.rem = 0xffffffff;
84 return ret;
87 if (a < b)
88 return (struct quot_rem) { 0, a };
90 #ifdef LZ
91 if (b <= a)
93 quot_digits = LZ (b) - LZ (a);
94 quot_digits += (a >= (b << quot_digits));
95 b <<= quot_digits;
97 #else
98 while (b <= a)
100 b <<= 1;
101 quot_digits++;
103 #endif
105 /* Is a 31 bits? Note that bit 31 is handled by the caller. */
106 if (a & 0x40000000)
108 /* Then make b:s highest bit max 0x40000000, because it must have
109 been 0x80000000 to be 1 bit higher than a. */
110 b >>= 1;
112 /* Adjust a to be maximum 0x3fffffff, i.e. two upper bits zero. */
113 if (a >= b)
115 a -= b;
116 extra = 1 << (quot_digits - 1);
118 else
120 a -= b >> 1;
122 /* Remember that we adjusted a by subtracting b * 2 ** Something. */
123 extra = 1 << quot_digits;
126 /* The number of quotient digits will be one less, because
127 we just adjusted b. */
128 quot_digits--;
131 /* Now do the division part. */
133 /* Subtract b and add ones to the right when a >= b
134 i.e. "a - (b - 1) == (a - b) + 1". */
135 b--;
137 #define DS __asm__ ("dstep %2,%0" : "=r" (a) : "0" (a), "r" (b))
139 switch (quot_digits)
141 case 32: DS; case 31: DS; case 30: DS; case 29: DS;
142 case 28: DS; case 27: DS; case 26: DS; case 25: DS;
143 case 24: DS; case 23: DS; case 22: DS; case 21: DS;
144 case 20: DS; case 19: DS; case 18: DS; case 17: DS;
145 case 16: DS; case 15: DS; case 14: DS; case 13: DS;
146 case 12: DS; case 11: DS; case 10: DS; case 9: DS;
147 case 8: DS; case 7: DS; case 6: DS; case 5: DS;
148 case 4: DS; case 3: DS; case 2: DS; case 1: DS;
149 case 0:;
153 struct quot_rem ret;
154 ret.quot = (a & ((1 << quot_digits) - 1)) + extra;
155 ret.rem = a >> quot_digits;
156 return ret;
160 #ifdef L_udivsi3
161 unsigned long
162 __Udiv (unsigned long a, unsigned long b) __attribute__ ((__const__));
164 unsigned long
165 __Udiv (unsigned long a, unsigned long b)
167 long extra = 0;
169 /* Adjust operands and result, if a and/or b is 32 bits. */
170 /* Effectively: b & 0x80000000. */
171 if ((long) b < 0)
172 return a >= b;
174 /* Effectively: a & 0x80000000. */
175 if ((long) a < 0)
177 int tmp = 0;
179 if (b == 0)
180 return 0xffffffff;
181 #ifdef LZ
182 tmp = LZ (b);
183 #else
184 for (tmp = 31; (((long) b & (1 << tmp)) == 0); tmp--)
187 tmp = 31 - tmp;
188 #endif
190 if ((b << tmp) > a)
192 extra = 1 << (tmp-1);
193 a -= b << (tmp - 1);
195 else
197 extra = 1 << tmp;
198 a -= b << tmp;
202 return do_31div (a, b).quot+extra;
204 #endif /* L_udivsi3 */
206 #ifdef L_divsi3
207 long
208 __Div (long a, long b) __attribute__ ((__const__));
210 long
211 __Div (long a, long b)
213 long extra = 0;
214 long sign = (b < 0) ? -1 : 1;
216 /* We need to handle a == -2147483648 as expected and must while
217 doing that avoid producing a sequence like "abs (a) < 0" as GCC
218 may optimize out the test. That sequence may not be obvious as
219 we call inline functions. Testing for a being negative and
220 handling (presumably much rarer than positive) enables us to get
221 a bit of optimization for an (accumulated) reduction of the
222 penalty of the 0x80000000 special-case. */
223 if (a < 0)
225 sign = -sign;
227 if ((a & 0x7fffffff) == 0)
229 /* We're at 0x80000000. Tread carefully. */
230 a -= b * sign;
231 extra = sign;
233 a = -a;
236 /* We knowingly penalize pre-v10 models by multiplication with the
237 sign. */
238 return sign * do_31div (a, __builtin_labs (b)).quot + extra;
240 #endif /* L_divsi3 */
243 #ifdef L_umodsi3
244 unsigned long
245 __Umod (unsigned long a, unsigned long b) __attribute__ ((__const__));
247 unsigned long
248 __Umod (unsigned long a, unsigned long b)
250 /* Adjust operands and result if a and/or b is 32 bits. */
251 if ((long) b < 0)
252 return a >= b ? a - b : a;
254 if ((long) a < 0)
256 int tmp = 0;
258 if (b == 0)
259 return a;
260 #ifdef LZ
261 tmp = LZ (b);
262 #else
263 for (tmp = 31; (((long) b & (1 << tmp)) == 0); tmp--)
265 tmp = 31 - tmp;
266 #endif
268 if ((b << tmp) > a)
270 a -= b << (tmp - 1);
272 else
274 a -= b << tmp;
278 return do_31div (a, b).rem;
280 #endif /* L_umodsi3 */
282 #ifdef L_modsi3
283 long
284 __Mod (long a, long b) __attribute__ ((__const__));
286 long
287 __Mod (long a, long b)
289 long sign = 1;
291 /* We need to handle a == -2147483648 as expected and must while
292 doing that avoid producing a sequence like "abs (a) < 0" as GCC
293 may optimize out the test. That sequence may not be obvious as
294 we call inline functions. Testing for a being negative and
295 handling (presumably much rarer than positive) enables us to get
296 a bit of optimization for an (accumulated) reduction of the
297 penalty of the 0x80000000 special-case. */
298 if (a < 0)
300 sign = -1;
301 if ((a & 0x7fffffff) == 0)
302 /* We're at 0x80000000. Tread carefully. */
303 a += __builtin_labs (b);
304 a = -a;
307 return sign * do_31div (a, __builtin_labs (b)).rem;
309 #endif /* L_modsi3 */
310 #endif /* L_udivsi3 || L_divsi3 || L_umodsi3 || L_modsi3 */
313 * Local variables:
314 * eval: (c-set-style "gnu")
315 * indent-tabs-mode: t
316 * End: