OSDN Git Service

b8f957e915cf63b5366378173b0be8c5ecdabad5
[pf3gnuchains/gcc-fork.git] / gcc / config / stormy16 / stormy16-lib2.c
1 /* This file contains 16-bit versions of some of the functions found in
2    libgcc2.c.  Really libgcc ought to be moved out of the gcc directory
3    and into its own top level directory, and then split up into multiple
4    files.  On this glorious day maybe this code can be integrated into
5    it too.  */
6
7 /* Copyright (C) 2005, 2008, 2009, 2010  Free Software Foundation, Inc.
8
9    This file is part of GCC.
10
11    GCC is free software; you can redistribute it and/or modify it under
12    the terms of the GNU General Public License as published by the Free
13    Software Foundation; either version 3, or (at your option) any later
14    version.
15
16    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17    WARRANTY; without even the implied warranty of MERCHANTABILITY or
18    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19    for more details.
20
21    Under Section 7 of GPL version 3, you are granted additional
22    permissions described in the GCC Runtime Library Exception, version
23    3.1, as published by the Free Software Foundation.
24
25    You should have received a copy of the GNU General Public License and
26    a copy of the GCC Runtime Library Exception along with this program;
27    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
28    <http://www.gnu.org/licenses/>.  */
29
30 #include "tconfig.h"
31 #include "tsystem.h"
32 #include "coretypes.h"
33 #include "tm.h"
34
35 #ifdef HAVE_GAS_HIDDEN
36 #define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
37 #else
38 #define ATTRIBUTE_HIDDEN
39 #endif
40
41 #ifndef MIN_UNITS_PER_WORD
42 #define MIN_UNITS_PER_WORD UNITS_PER_WORD
43 #endif
44
45 #ifndef LIBGCC2_UNITS_PER_WORD
46 # if MIN_UNITS_PER_WORD > 4
47 #  define LIBGCC2_UNITS_PER_WORD 8
48 # elif (MIN_UNITS_PER_WORD > 2 \
49         || (MIN_UNITS_PER_WORD > 1 && LONG_LONG_TYPE_SIZE > 32))
50 #  define LIBGCC2_UNITS_PER_WORD 4
51 # else
52 #  define LIBGCC2_UNITS_PER_WORD MIN_UNITS_PER_WORD
53 # endif
54 #endif
55
56 #define word_type Wtype
57
58 #include "libgcc2.h"
59 #undef int
60
61 /* These prototypes would normally live in libgcc2.h, but this can
62    only happen once the code below is integrated into libgcc2.c.  */
63
64 extern USItype udivmodsi4 (USItype, USItype, word_type);
65 extern SItype __divsi3 (SItype, SItype);
66 extern SItype __modsi3 (SItype, SItype);
67 extern SItype __udivsi3 (SItype, SItype);
68 extern SItype __umodsi3 (SItype, SItype);
69 extern SItype __ashlsi3 (SItype, SItype);
70 extern SItype __ashrsi3 (SItype, SItype);
71 extern USItype __lshrsi3 (USItype, USItype);
72 extern int __popcounthi2 (UHWtype);
73 extern int __parityhi2 (UHWtype);
74 extern int __clzhi2 (UHWtype);
75 extern int __ctzhi2 (UHWtype);
76
77
78 #ifdef XSTORMY16_UDIVMODSI4
79 USItype
80 udivmodsi4 (USItype num, USItype den, word_type modwanted)
81 {
82   USItype bit = 1;
83   USItype res = 0;
84
85   while (den < num && bit && !(den & (1L << 31)))
86     {
87       den <<= 1;
88       bit <<= 1;
89     }
90   while (bit)
91     {
92       if (num >= den)
93         {
94           num -= den;
95           res |= bit;
96         }
97       bit >>= 1;
98       den >>= 1;
99     }
100
101   if (modwanted)
102     return num;
103   return res;
104 }
105 #endif
106
107 #ifdef XSTORMY16_DIVSI3
108 SItype
109 __divsi3 (SItype a, SItype b)
110 {
111   word_type neg = 0;
112   SItype res;
113
114   if (a < 0)
115     {
116       a = -a;
117       neg = !neg;
118     }
119
120   if (b < 0)
121     {
122       b = -b;
123       neg = !neg;
124     }
125
126   res = udivmodsi4 (a, b, 0);
127
128   if (neg)
129     res = -res;
130
131   return res;
132 }
133 #endif
134
135 #ifdef XSTORMY16_MODSI3
136 SItype
137 __modsi3 (SItype a, SItype b)
138 {
139   word_type neg = 0;
140   SItype res;
141
142   if (a < 0)
143     {
144       a = -a;
145       neg = 1;
146     }
147
148   if (b < 0)
149     b = -b;
150
151   res = udivmodsi4 (a, b, 1);
152
153   if (neg)
154     res = -res;
155
156   return res;
157 }
158 #endif
159
160 #ifdef XSTORMY16_UDIVSI3
161 SItype
162 __udivsi3 (SItype a, SItype b)
163 {
164   return udivmodsi4 (a, b, 0);
165 }
166 #endif
167
168 #ifdef XSTORMY16_UMODSI3
169 SItype
170 __umodsi3 (SItype a, SItype b)
171 {
172   return udivmodsi4 (a, b, 1);
173 }
174 #endif
175
176 #ifdef XSTORMY16_ASHLSI3
177 SItype
178 __ashlsi3 (SItype a, SItype b)
179 {
180   word_type i;
181   
182   if (b & 16)
183     a <<= 16;
184   if (b & 8)
185     a <<= 8;
186   for (i = (b & 0x7); i > 0; --i)
187     a <<= 1;
188   return a;
189 }
190 #endif
191
192 #ifdef XSTORMY16_ASHRSI3
193 SItype
194 __ashrsi3 (SItype a, SItype b)
195 {
196   word_type i;
197   
198   if (b & 16)
199     a >>= 16;
200   if (b & 8)
201     a >>= 8;
202   for (i = (b & 0x7); i > 0; --i)
203     a >>= 1;
204   return a;
205 }
206 #endif
207
208 #ifdef XSTORMY16_LSHRSI3
209 USItype
210 __lshrsi3 (USItype a, USItype b)
211 {
212   word_type i;
213   
214   if (b & 16)
215     a >>= 16;
216   if (b & 8)
217     a >>= 8;
218   for (i = (b & 0x7); i > 0; --i)
219     a >>= 1;
220   return a;
221 }
222 #endif
223
224 #ifdef XSTORMY16_POPCOUNTHI2
225 /* Returns the number of set bits in X.
226    FIXME:  The return type really should be "unsigned int"
227    but this is not how the builtin is prototyped.  */
228 int
229 __popcounthi2 (UHWtype x)
230 {
231   int ret;
232
233   ret = __popcount_tab [x & 0xff];
234   ret += __popcount_tab [(x >> 8) & 0xff];
235
236   return ret;
237 }
238 #endif
239
240 #ifdef XSTORMY16_PARITYHI2
241 /* Returns the number of set bits in X, modulo 2.
242    FIXME:  The return type really should be "unsigned int"
243    but this is not how the builtin is prototyped.  */
244
245 int
246 __parityhi2 (UHWtype x)
247 {
248   x ^= x >> 8;
249   x ^= x >> 4;
250   x &= 0xf;
251   return (0x6996 >> x) & 1;
252 }
253 #endif
254
255 #ifdef XSTORMY16_CLZHI2
256 /* Returns the number of zero-bits from the most significant bit to the
257    first nonzero bit in X.  Returns 16 for X == 0.  Implemented as a
258    simple for loop in order to save space by removing the need for
259    the __clz_tab array.
260    FIXME:  The return type really should be "unsigned int" but this is
261    not how the builtin is prototyped.  */
262 #undef unsigned
263 int
264 __clzhi2 (UHWtype x)
265 {
266   unsigned int i;
267   unsigned int c;
268   unsigned int value = x;
269
270   for (c = 0, i = 1 << 15; i; i >>= 1, c++)
271     if (i & value)
272       break;
273   return c;
274 }
275 #endif
276
277 #ifdef XSTORMY16_CTZHI2
278 /* Returns the number of trailing zero bits in X.
279    FIXME:  The return type really should be "signed int" since
280    ctz(0) returns -1, but this is not how the builtin is prototyped.  */
281
282 int
283 __ctzhi2 (UHWtype x)
284 {
285   /* This is cunning.  It converts X into a number with only the one bit
286      set, the bit that was the least significant bit in X.  From this we
287      can use the count_leading_zeros to compute the number of trailing
288      bits.  */
289   x &= - x;
290
291   return 15 - __builtin_clz (x);
292 }
293 #endif
294
295 #ifdef XSTORMY16_FFSHI2
296 /* Returns one plus the index of the least significant 1-bit of X,
297    or if X is zero, returns zero.  FIXME:  The return type really
298    should be "unsigned int" but this is not how the builtin is
299    prototyped.  */
300
301 int
302 __ffshi2 (UHWtype u)
303 {
304   UHWtype count;
305
306   if (u == 0)
307     return 0;
308
309   return 16 - __builtin_clz (u & - u);
310 }
311 #endif
312
313 #ifdef XSTORMY16_UCMPSI2
314 /* Performs an unsigned comparison of two 32-bit values: A and B.
315    If A is less than B, then 0 is returned.  If A is greater than B,
316    then 2 is returned.  Otherwise A and B are equal and 1 is returned.  */
317
318 word_type
319 __ucmpsi2 (USItype a, USItype b)
320 {
321   word_type hi_a = (a << 16);
322   word_type hi_b = (b << 16);
323
324   if (hi_a == hi_b)
325     {
326       word_type low_a = (a & 0xff);
327       word_type low_b = (b & 0xff);
328
329       return low_a < low_b ? 0 : (low_a > low_b ? 2 : 1);
330     }
331
332   return hi_a < hi_b ? 0 : 2;
333 }
334 #endif