xref: /netbsd-src/external/gpl3/gcc/dist/libgcc/config/cris/arit.c (revision f89f6560d453f5e37386cc7938c072d2f528b9fa)
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.
4 
5    Copyright (C) 1998-2013 Free Software Foundation, Inc.
6 
7 This file is part of GCC.
8 
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3, or (at your option) any
12 later version.
13 
14 This file is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 General Public License for more details.
18 
19 Under Section 7 of GPL version 3, you are granted additional
20 permissions described in the GCC Runtime Library Exception, version
21 3.1, as published by the Free Software Foundation.
22 
23 You should have received a copy of the GNU General Public License and
24 a copy of the GCC Runtime Library Exception along with this program;
25 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
26 <http://www.gnu.org/licenses/>.  */
27 
28 
29 /* Note that we provide prototypes for all "const" functions, to attach
30    the const attribute.  This is necessary in 2.7.2 - adding the
31    attribute to the function *definition* is a syntax error.
32     This did not work with e.g. 2.1; back then, the return type had to
33    be "const".  */
34 
35 #include "config.h"
36 
37 #if defined (__CRIS_arch_version) && __CRIS_arch_version >= 3
38 #define LZ(v) __builtin_clz (v)
39 #endif
40 
41 
42 #if defined (L_udivsi3) || defined (L_divsi3) || defined (L_umodsi3) \
43     || defined (L_modsi3)
44 /* Result type of divmod worker function.  */
45 struct quot_rem
46  {
47    long quot;
48    long rem;
49  };
50 
51 /* This is the worker function for div and mod.  It is inlined into the
52    respective library function.  Parameter A must have bit 31 == 0.  */
53 
54 static __inline__ struct quot_rem
55 do_31div (unsigned long a, unsigned long b)
56      __attribute__ ((__const__, __always_inline__));
57 
58 static __inline__ struct quot_rem
59 do_31div (unsigned long a, unsigned long b)
60 {
61   /* Adjust operands and result if a is 31 bits.  */
62   long extra = 0;
63   int quot_digits = 0;
64 
65   if (b == 0)
66     {
67       struct quot_rem ret;
68       ret.quot = 0xffffffff;
69       ret.rem = 0xffffffff;
70       return ret;
71     }
72 
73   if (a < b)
74     return (struct quot_rem) { 0, a };
75 
76 #ifdef LZ
77   if (b <= a)
78     {
79       quot_digits = LZ (b) - LZ (a);
80       quot_digits += (a >= (b << quot_digits));
81       b <<= quot_digits;
82     }
83 #else
84   while (b <= a)
85     {
86       b <<= 1;
87       quot_digits++;
88     }
89 #endif
90 
91   /* Is a 31 bits?  Note that bit 31 is handled by the caller.  */
92   if (a & 0x40000000)
93     {
94       /* Then make b:s highest bit max 0x40000000, because it must have
95 	 been 0x80000000 to be 1 bit higher than a.  */
96       b >>= 1;
97 
98       /* Adjust a to be maximum 0x3fffffff, i.e. two upper bits zero.  */
99       if (a >= b)
100 	{
101 	  a -= b;
102 	  extra = 1 << (quot_digits - 1);
103 	}
104       else
105 	{
106 	  a -= b >> 1;
107 
108 	  /* Remember that we adjusted a by subtracting b * 2 ** Something.  */
109 	  extra = 1 << quot_digits;
110 	}
111 
112       /* The number of quotient digits will be one less, because
113 	 we just adjusted b.  */
114       quot_digits--;
115     }
116 
117   /* Now do the division part.  */
118 
119   /* Subtract b and add ones to the right when a >= b
120      i.e. "a - (b - 1) == (a - b) + 1".  */
121   b--;
122 
123 #define DS __asm__ ("dstep %2,%0" : "=r" (a) : "0" (a), "r" (b))
124 
125   switch (quot_digits)
126     {
127     case 32: DS; case 31: DS; case 30: DS; case 29: DS;
128     case 28: DS; case 27: DS; case 26: DS; case 25: DS;
129     case 24: DS; case 23: DS; case 22: DS; case 21: DS;
130     case 20: DS; case 19: DS; case 18: DS; case 17: DS;
131     case 16: DS; case 15: DS; case 14: DS; case 13: DS;
132     case 12: DS; case 11: DS; case 10: DS; case 9: DS;
133     case 8: DS; case 7: DS; case 6: DS; case 5: DS;
134     case 4: DS; case 3: DS; case 2: DS; case 1: DS;
135     case 0:;
136     }
137 
138   {
139     struct quot_rem ret;
140     ret.quot = (a & ((1 << quot_digits) - 1)) + extra;
141     ret.rem = a >> quot_digits;
142     return ret;
143   }
144 }
145 
146 #ifdef L_udivsi3
147 unsigned long
148 __Udiv (unsigned long a, unsigned long b) __attribute__ ((__const__));
149 
150 unsigned long
151 __Udiv (unsigned long a, unsigned long b)
152 {
153   long extra = 0;
154 
155   /* Adjust operands and result, if a and/or b is 32 bits.  */
156   /* Effectively: b & 0x80000000.  */
157   if ((long) b < 0)
158     return a >= b;
159 
160   /* Effectively: a & 0x80000000.  */
161   if ((long) a < 0)
162     {
163       int tmp = 0;
164 
165       if (b == 0)
166 	return 0xffffffff;
167 #ifdef LZ
168       tmp = LZ (b);
169 #else
170       for (tmp = 31; (((long) b & (1 << tmp)) == 0); tmp--)
171 	;
172 
173       tmp = 31 - tmp;
174 #endif
175 
176       if ((b << tmp) > a)
177 	{
178 	  extra = 1 << (tmp-1);
179 	  a -= b << (tmp - 1);
180 	}
181       else
182 	{
183 	  extra = 1 << tmp;
184 	  a -= b << tmp;
185 	}
186     }
187 
188   return do_31div (a, b).quot+extra;
189 }
190 #endif /* L_udivsi3 */
191 
192 #ifdef L_divsi3
193 long
194 __Div (long a, long b) __attribute__ ((__const__));
195 
196 long
197 __Div (long a, long b)
198 {
199   long extra = 0;
200   long sign = (b < 0) ? -1 : 1;
201 
202   /* We need to handle a == -2147483648 as expected and must while
203      doing that avoid producing a sequence like "abs (a) < 0" as GCC
204      may optimize out the test.  That sequence may not be obvious as
205      we call inline functions.  Testing for a being negative and
206      handling (presumably much rarer than positive) enables us to get
207      a bit of optimization for an (accumulated) reduction of the
208      penalty of the 0x80000000 special-case.  */
209   if (a < 0)
210     {
211       sign = -sign;
212 
213       if ((a & 0x7fffffff) == 0)
214 	{
215 	  /* We're at 0x80000000.  Tread carefully.  */
216 	  a -= b * sign;
217 	  extra = sign;
218 	}
219       a = -a;
220     }
221 
222   /* We knowingly penalize pre-v10 models by multiplication with the
223      sign.  */
224   return sign * do_31div (a, __builtin_labs (b)).quot + extra;
225 }
226 #endif /* L_divsi3 */
227 
228 
229 #ifdef L_umodsi3
230 unsigned long
231 __Umod (unsigned long a, unsigned long b) __attribute__ ((__const__));
232 
233 unsigned long
234 __Umod (unsigned long a, unsigned long b)
235 {
236   /* Adjust operands and result if a and/or b is 32 bits.  */
237   if ((long) b < 0)
238     return a >= b ? a - b : a;
239 
240   if ((long) a < 0)
241     {
242       int tmp = 0;
243 
244       if (b == 0)
245 	return a;
246 #ifdef LZ
247       tmp = LZ (b);
248 #else
249       for (tmp = 31; (((long) b & (1 << tmp)) == 0); tmp--)
250 	;
251       tmp = 31 - tmp;
252 #endif
253 
254       if ((b << tmp) > a)
255 	{
256 	  a -= b << (tmp - 1);
257 	}
258       else
259 	{
260 	  a -= b << tmp;
261 	}
262     }
263 
264   return do_31div (a, b).rem;
265 }
266 #endif /* L_umodsi3 */
267 
268 #ifdef L_modsi3
269 long
270 __Mod (long a, long b) __attribute__ ((__const__));
271 
272 long
273 __Mod (long a, long b)
274 {
275   long sign = 1;
276 
277   /* We need to handle a == -2147483648 as expected and must while
278      doing that avoid producing a sequence like "abs (a) < 0" as GCC
279      may optimize out the test.  That sequence may not be obvious as
280      we call inline functions.  Testing for a being negative and
281      handling (presumably much rarer than positive) enables us to get
282      a bit of optimization for an (accumulated) reduction of the
283      penalty of the 0x80000000 special-case.  */
284   if (a < 0)
285     {
286       sign = -1;
287       if ((a & 0x7fffffff) == 0)
288 	/* We're at 0x80000000.  Tread carefully.  */
289 	a += __builtin_labs (b);
290       a = -a;
291     }
292 
293   return sign * do_31div (a, __builtin_labs (b)).rem;
294 }
295 #endif /* L_modsi3 */
296 #endif /* L_udivsi3 || L_divsi3 || L_umodsi3 || L_modsi3 */
297 
298 /*
299  * Local variables:
300  * eval: (c-set-style "gnu")
301  * indent-tabs-mode: t
302  * End:
303  */
304