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, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
6
7This file is part of GCC.
8
9GCC is free software; you can redistribute it and/or modify it
10under the terms of the GNU General Public License as published by the
11Free Software Foundation; either version 2, or (at your option) any
12later version.
13
14In addition to the permissions in the GNU General Public License, the
15Free Software Foundation gives you unlimited permission to link the
16compiled version of this file with other programs, and to distribute
17those programs without any restriction coming from the use of this
18file.  (The General Public License restrictions do apply in other
19respects; for example, they cover modification of the file, and
20distribution when not linked into another program.)
21
22This file is distributed in the hope that it will be useful, but
23WITHOUT ANY WARRANTY; without even the implied warranty of
24MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25General Public License for more details.
26
27You should have received a copy of the GNU General Public License
28along with this program; see the file COPYING.  If not, write to
29the Free Software Foundation, 59 Temple Place - Suite 330,
30Boston, MA 02111-1307, USA.
31
32   As a special exception, if you link this library with files, some of
33   which are compiled with GCC, this library does not by itself cause
34   the resulting object or executable to be covered by the GNU General
35   Public License.
36   This exception does not however invalidate any other reasons why
37   the executable file or object might be covered by the GNU General
38   Public License.  */
39
40
41/* Note that we provide prototypes for all "const" functions, to attach
42   the const attribute.  This is necessary in 2.7.2 - adding the
43   attribute to the function *definition* is a syntax error.
44    This did not work with e.g. 2.1; back then, the return type had to
45   be "const".  */
46
47#include "config.h"
48
49#if defined (__CRIS_arch_version) && __CRIS_arch_version >= 3
50#define LZ(v) __extension__ \
51 ({ int tmp_; __asm__ ("lz %1,%0" : "=r" (tmp_) : "r" (v)); tmp_; })
52#endif
53
54
55#if defined (L_udivsi3) || defined (L_divsi3) || defined (L_umodsi3) \
56    || defined (L_modsi3)
57/* Result type of divmod worker function.  */
58struct quot_rem
59 {
60   long quot;
61   long rem;
62 };
63
64/* This is the worker function for div and mod.  It is inlined into the
65   respective library function.  */
66static __inline__ struct quot_rem
67do_31div (unsigned long a, unsigned long b)
68     __attribute__ ((__const__, __always_inline__));
69
70static __inline__ struct quot_rem
71do_31div (unsigned long a, unsigned long b)
72{
73  /* Adjust operands and result if a is 31 bits.  */
74  long extra = 0;
75  int quot_digits = 0;
76
77  if (b == 0)
78    {
79      struct quot_rem ret;
80      ret.quot = 0xffffffff;
81      ret.rem = 0xffffffff;
82      return ret;
83    }
84
85  if (a < b)
86    return (struct quot_rem) { 0, a };
87
88#ifdef LZ
89  if (b <= a)
90    {
91      quot_digits = LZ (b) - LZ (a);
92      quot_digits += (a >= (b << quot_digits));
93      b <<= quot_digits;
94    }
95#else
96  while (b <= a)
97    {
98      b <<= 1;
99      quot_digits++;
100    }
101#endif
102
103  /* Is a 31 bits?  Note that bit 31 is handled by the caller.  */
104  if (a & 0x40000000)
105    {
106      /* Then make b:s highest bit max 0x40000000, because it must have
107	 been 0x80000000 to be 1 bit higher than a.  */
108      b >>= 1;
109
110      /* Adjust a to be maximum 0x3fffffff, i.e. two upper bits zero.  */
111      if (a >= b)
112	{
113	  a -= b;
114	  extra = 1 << (quot_digits - 1);
115	}
116      else
117	{
118	  a -= b >> 1;
119
120	  /* Remember that we adjusted a by subtracting b * 2 ** Something.  */
121	  extra = 1 << quot_digits;
122	}
123
124      /* The number of quotient digits will be one less, because
125	 we just adjusted b.  */
126      quot_digits--;
127    }
128
129  /* Now do the division part.  */
130
131  /* Subtract b and add ones to the right when a >= b
132     i.e. "a - (b - 1) == (a - b) + 1".  */
133  b--;
134
135#define DS __asm__ ("dstep %2,%0" : "=r" (a) : "0" (a), "r" (b))
136
137  switch (quot_digits)
138    {
139    case 32: DS; case 31: DS; case 30: DS; case 29: DS;
140    case 28: DS; case 27: DS; case 26: DS; case 25: DS;
141    case 24: DS; case 23: DS; case 22: DS; case 21: DS;
142    case 20: DS; case 19: DS; case 18: DS; case 17: DS;
143    case 16: DS; case 15: DS; case 14: DS; case 13: DS;
144    case 12: DS; case 11: DS; case 10: DS; case 9: DS;
145    case 8: DS; case 7: DS; case 6: DS; case 5: DS;
146    case 4: DS; case 3: DS; case 2: DS; case 1: DS;
147    case 0:;
148    }
149
150  {
151    struct quot_rem ret;
152    ret.quot = (a & ((1 << quot_digits) - 1)) + extra;
153    ret.rem = a >> quot_digits;
154    return ret;
155  }
156}
157
158/* Note that unsigned and signed division both build when L_divsi3, but
159   the unsigned variant is then inlined, as with do_31div above.  */
160#if defined (L_udivsi3) || defined (L_divsi3)
161#ifndef L_udivsi3
162static __inline__
163#endif
164unsigned long
165__Udiv (unsigned long a, unsigned long b)
166     __attribute__ ((__const__, __always_inline__));
167
168#ifndef L_udivsi3
169static __inline__
170#endif
171unsigned long
172__Udiv (unsigned long a, unsigned long b)
173{
174  long extra = 0;
175
176  /* Adjust operands and result, if a and/or b is 32 bits.  */
177  /* Effectively: b & 0x80000000.  */
178  if ((long) b < 0)
179    return a >= b;
180
181  /* Effectively: a & 0x80000000.  */
182  if ((long) a < 0)
183    {
184      int tmp = 0;
185
186      if (b == 0)
187	return 0xffffffff;
188#ifdef LZ
189      tmp = LZ (b);
190#else
191      for (tmp = 31; (((long) b & (1 << tmp)) == 0); tmp--)
192	;
193
194      tmp = 31 - tmp;
195#endif
196
197      if ((b << tmp) > a)
198	{
199	  extra = 1 << (tmp-1);
200	  a -= b << (tmp - 1);
201	}
202      else
203	{
204	  extra = 1 << tmp;
205	  a -= b << tmp;
206	}
207    }
208
209  return do_31div (a, b).quot+extra;
210}
211
212
213#ifdef L_divsi3
214long
215__Div (long a, long b) __attribute__ ((__const__));
216
217long
218__Div (long a, long b)
219{
220  long sign;
221  long result;
222
223  /* Do *not* call do_31div since abs (-2147483648) == 2147483648
224     <=> abs (-0x80000000) == 0x80000000
225     which is still 32 bits.  */
226
227  sign = a ^ b;
228  result = __Udiv (__builtin_labs (a), __builtin_labs (b));
229
230  return  (sign < 0) ? -result : result;
231}
232#endif /* L_divsi3 */
233#endif /* L_udivsi3 || L_divsi3 */
234
235
236/* Note that unsigned and signed modulus both build when L_modsi3, but
237   then the unsigned variant is inlined, as with do_31div above.  */
238#if defined (L_umodsi3) || defined (L_modsi3)
239#ifndef L_umodsi3
240static __inline__
241#endif
242unsigned long
243__Umod (unsigned long a, unsigned long b)
244     __attribute__ ((__const__, __always_inline__));
245
246#ifndef L_umodsi3
247static __inline__
248#endif
249unsigned long
250__Umod (unsigned long a, unsigned long b)
251{
252  /* Adjust operands and result if a and/or b is 32 bits.  */
253  if ((long) b < 0)
254    return a >= b ? a - b : a;
255
256  if ((long) a < 0)
257    {
258      int tmp = 0;
259
260      if (b == 0)
261	return a;
262#ifdef LZ
263      tmp = LZ (b);
264#else
265      for (tmp = 31; (((long) b & (1 << tmp)) == 0); tmp--)
266	;
267      tmp = 31 - tmp;
268#endif
269
270      if ((b << tmp) > a)
271	{
272	  a -= b << (tmp - 1);
273	}
274      else
275	{
276	  a -= b << tmp;
277	}
278    }
279
280  return do_31div (a, b).rem;
281}
282
283#ifdef L_modsi3
284long
285__Mod (long a, long b) __attribute__ ((__const__));
286
287long
288__Mod (long a, long b)
289{
290  long	result;
291
292  result = __Umod (__builtin_labs (a), __builtin_labs (b));
293
294  return (a < 0) ? -result : result;
295}
296#endif /* L_modsi3 */
297#endif /* L_umodsi3 || L_modsi3 */
298#endif /* L_udivsi3 || L_divsi3 || L_umodsi3 || L_modsi3 */
299
300/*
301 * Local variables:
302 * eval: (c-set-style "gnu")
303 * indent-tabs-mode: t
304 * End:
305 */
306