]>
Commit | Line | Data |
---|---|---|
dcfae47c NC |
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 | ||
85ec4feb | 7 | /* Copyright (C) 2005-2018 Free Software Foundation, Inc. |
dcfae47c NC |
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 | |
748086b7 | 13 | Software Foundation; either version 3, or (at your option) any later |
dcfae47c NC |
14 | version. |
15 | ||
dcfae47c NC |
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 | ||
748086b7 JJ |
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/>. */ | |
dcfae47c NC |
29 | |
30 | #include "tconfig.h" | |
31 | #include "tsystem.h" | |
32 | #include "coretypes.h" | |
33 | #include "tm.h" | |
852b75ed | 34 | #include "libgcc_tm.h" |
dcfae47c NC |
35 | |
36 | #ifdef HAVE_GAS_HIDDEN | |
37 | #define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) | |
38 | #else | |
39 | #define ATTRIBUTE_HIDDEN | |
40 | #endif | |
41 | ||
f84fe9b6 NC |
42 | #ifndef MIN_UNITS_PER_WORD |
43 | #define MIN_UNITS_PER_WORD UNITS_PER_WORD | |
44 | #endif | |
45 | ||
46 | #ifndef LIBGCC2_UNITS_PER_WORD | |
47 | # if MIN_UNITS_PER_WORD > 4 | |
48 | # define LIBGCC2_UNITS_PER_WORD 8 | |
49 | # elif (MIN_UNITS_PER_WORD > 2 \ | |
50 | || (MIN_UNITS_PER_WORD > 1 && LONG_LONG_TYPE_SIZE > 32)) | |
51 | # define LIBGCC2_UNITS_PER_WORD 4 | |
52 | # else | |
53 | # define LIBGCC2_UNITS_PER_WORD MIN_UNITS_PER_WORD | |
54 | # endif | |
55 | #endif | |
56 | ||
57 | #define word_type Wtype | |
58 | ||
dcfae47c NC |
59 | #include "libgcc2.h" |
60 | #undef int | |
61 | ||
62 | /* These prototypes would normally live in libgcc2.h, but this can | |
63 | only happen once the code below is integrated into libgcc2.c. */ | |
64 | ||
65 | extern USItype udivmodsi4 (USItype, USItype, word_type); | |
66 | extern SItype __divsi3 (SItype, SItype); | |
67 | extern SItype __modsi3 (SItype, SItype); | |
68 | extern SItype __udivsi3 (SItype, SItype); | |
69 | extern SItype __umodsi3 (SItype, SItype); | |
70 | extern SItype __ashlsi3 (SItype, SItype); | |
71 | extern SItype __ashrsi3 (SItype, SItype); | |
72 | extern USItype __lshrsi3 (USItype, USItype); | |
73 | extern int __popcounthi2 (UHWtype); | |
74 | extern int __parityhi2 (UHWtype); | |
75 | extern int __clzhi2 (UHWtype); | |
76 | extern int __ctzhi2 (UHWtype); | |
77 | ||
4b58290f | 78 | |
ba964383 | 79 | #ifdef XSTORMY16_UDIVMODSI4 |
4b58290f | 80 | USItype |
dcfae47c | 81 | udivmodsi4 (USItype num, USItype den, word_type modwanted) |
4b58290f GK |
82 | { |
83 | USItype bit = 1; | |
84 | USItype res = 0; | |
85 | ||
dcfae47c | 86 | while (den < num && bit && !(den & (1L << 31))) |
4b58290f | 87 | { |
dcfae47c NC |
88 | den <<= 1; |
89 | bit <<= 1; | |
4b58290f GK |
90 | } |
91 | while (bit) | |
92 | { | |
93 | if (num >= den) | |
94 | { | |
95 | num -= den; | |
96 | res |= bit; | |
97 | } | |
dcfae47c NC |
98 | bit >>= 1; |
99 | den >>= 1; | |
4b58290f | 100 | } |
dcfae47c NC |
101 | |
102 | if (modwanted) | |
103 | return num; | |
4b58290f GK |
104 | return res; |
105 | } | |
ba964383 | 106 | #endif |
4b58290f | 107 | |
ba964383 | 108 | #ifdef XSTORMY16_DIVSI3 |
4b58290f GK |
109 | SItype |
110 | __divsi3 (SItype a, SItype b) | |
111 | { | |
112 | word_type neg = 0; | |
113 | SItype res; | |
114 | ||
115 | if (a < 0) | |
116 | { | |
117 | a = -a; | |
118 | neg = !neg; | |
119 | } | |
120 | ||
121 | if (b < 0) | |
122 | { | |
123 | b = -b; | |
124 | neg = !neg; | |
125 | } | |
126 | ||
127 | res = udivmodsi4 (a, b, 0); | |
128 | ||
129 | if (neg) | |
130 | res = -res; | |
131 | ||
132 | return res; | |
133 | } | |
ba964383 | 134 | #endif |
4b58290f | 135 | |
ba964383 | 136 | #ifdef XSTORMY16_MODSI3 |
4b58290f GK |
137 | SItype |
138 | __modsi3 (SItype a, SItype b) | |
139 | { | |
140 | word_type neg = 0; | |
141 | SItype res; | |
142 | ||
143 | if (a < 0) | |
144 | { | |
145 | a = -a; | |
146 | neg = 1; | |
147 | } | |
148 | ||
149 | if (b < 0) | |
150 | b = -b; | |
151 | ||
152 | res = udivmodsi4 (a, b, 1); | |
153 | ||
154 | if (neg) | |
155 | res = -res; | |
156 | ||
157 | return res; | |
158 | } | |
ba964383 | 159 | #endif |
4b58290f | 160 | |
ba964383 | 161 | #ifdef XSTORMY16_UDIVSI3 |
4b58290f GK |
162 | SItype |
163 | __udivsi3 (SItype a, SItype b) | |
164 | { | |
165 | return udivmodsi4 (a, b, 0); | |
166 | } | |
ba964383 | 167 | #endif |
4b58290f | 168 | |
ba964383 | 169 | #ifdef XSTORMY16_UMODSI3 |
4b58290f GK |
170 | SItype |
171 | __umodsi3 (SItype a, SItype b) | |
172 | { | |
173 | return udivmodsi4 (a, b, 1); | |
174 | } | |
ba964383 | 175 | #endif |
4b58290f | 176 | |
ba964383 | 177 | #ifdef XSTORMY16_ASHLSI3 |
4b58290f GK |
178 | SItype |
179 | __ashlsi3 (SItype a, SItype b) | |
180 | { | |
181 | word_type i; | |
182 | ||
183 | if (b & 16) | |
184 | a <<= 16; | |
185 | if (b & 8) | |
186 | a <<= 8; | |
187 | for (i = (b & 0x7); i > 0; --i) | |
188 | a <<= 1; | |
189 | return a; | |
190 | } | |
ba964383 | 191 | #endif |
4b58290f | 192 | |
ba964383 | 193 | #ifdef XSTORMY16_ASHRSI3 |
4b58290f GK |
194 | SItype |
195 | __ashrsi3 (SItype a, SItype b) | |
196 | { | |
197 | word_type i; | |
198 | ||
199 | if (b & 16) | |
200 | a >>= 16; | |
201 | if (b & 8) | |
202 | a >>= 8; | |
203 | for (i = (b & 0x7); i > 0; --i) | |
204 | a >>= 1; | |
205 | return a; | |
206 | } | |
ba964383 | 207 | #endif |
4b58290f | 208 | |
ba964383 | 209 | #ifdef XSTORMY16_LSHRSI3 |
4b58290f GK |
210 | USItype |
211 | __lshrsi3 (USItype a, USItype b) | |
212 | { | |
213 | word_type i; | |
214 | ||
215 | if (b & 16) | |
216 | a >>= 16; | |
217 | if (b & 8) | |
218 | a >>= 8; | |
219 | for (i = (b & 0x7); i > 0; --i) | |
220 | a >>= 1; | |
221 | return a; | |
222 | } | |
ba964383 | 223 | #endif |
ebf178cd | 224 | |
ba964383 | 225 | #ifdef XSTORMY16_POPCOUNTHI2 |
dcfae47c | 226 | /* Returns the number of set bits in X. |
ba964383 | 227 | FIXME: The return type really should be "unsigned int" |
dcfae47c | 228 | but this is not how the builtin is prototyped. */ |
ebf178cd | 229 | int |
dcfae47c | 230 | __popcounthi2 (UHWtype x) |
ebf178cd | 231 | { |
dcfae47c | 232 | int ret; |
ebf178cd NC |
233 | |
234 | ret = __popcount_tab [x & 0xff]; | |
235 | ret += __popcount_tab [(x >> 8) & 0xff]; | |
236 | ||
237 | return ret; | |
238 | } | |
ba964383 | 239 | #endif |
ebf178cd | 240 | |
ba964383 | 241 | #ifdef XSTORMY16_PARITYHI2 |
dcfae47c | 242 | /* Returns the number of set bits in X, modulo 2. |
ba964383 | 243 | FIXME: The return type really should be "unsigned int" |
dcfae47c NC |
244 | but this is not how the builtin is prototyped. */ |
245 | ||
ebf178cd | 246 | int |
dcfae47c | 247 | __parityhi2 (UHWtype x) |
ebf178cd NC |
248 | { |
249 | x ^= x >> 8; | |
250 | x ^= x >> 4; | |
251 | x &= 0xf; | |
252 | return (0x6996 >> x) & 1; | |
253 | } | |
ba964383 | 254 | #endif |
ebf178cd | 255 | |
ba964383 | 256 | #ifdef XSTORMY16_CLZHI2 |
0761b460 NC |
257 | /* Returns the number of zero-bits from the most significant bit to the |
258 | first nonzero bit in X. Returns 16 for X == 0. Implemented as a | |
259 | simple for loop in order to save space by removing the need for | |
260 | the __clz_tab array. | |
261 | FIXME: The return type really should be "unsigned int" but this is | |
262 | not how the builtin is prototyped. */ | |
263 | #undef unsigned | |
ebf178cd | 264 | int |
dcfae47c | 265 | __clzhi2 (UHWtype x) |
ebf178cd | 266 | { |
0761b460 NC |
267 | unsigned int i; |
268 | unsigned int c; | |
269 | unsigned int value = x; | |
270 | ||
271 | for (c = 0, i = 1 << 15; i; i >>= 1, c++) | |
272 | if (i & value) | |
273 | break; | |
274 | return c; | |
ebf178cd | 275 | } |
ba964383 | 276 | #endif |
ebf178cd | 277 | |
ba964383 | 278 | #ifdef XSTORMY16_CTZHI2 |
dcfae47c | 279 | /* Returns the number of trailing zero bits in X. |
ba964383 NC |
280 | FIXME: The return type really should be "signed int" since |
281 | ctz(0) returns -1, but this is not how the builtin is prototyped. */ | |
dcfae47c | 282 | |
ebf178cd | 283 | int |
dcfae47c | 284 | __ctzhi2 (UHWtype x) |
ebf178cd | 285 | { |
dcfae47c | 286 | /* This is cunning. It converts X into a number with only the one bit |
ba964383 NC |
287 | set, the bit that was the least significant bit in X. From this we |
288 | can use the count_leading_zeros to compute the number of trailing | |
289 | bits. */ | |
dcfae47c NC |
290 | x &= - x; |
291 | ||
0761b460 | 292 | return 15 - __builtin_clz (x); |
ba964383 NC |
293 | } |
294 | #endif | |
295 | ||
296 | #ifdef XSTORMY16_FFSHI2 | |
297 | /* Returns one plus the index of the least significant 1-bit of X, | |
298 | or if X is zero, returns zero. FIXME: The return type really | |
299 | should be "unsigned int" but this is not how the builtin is | |
300 | prototyped. */ | |
301 | ||
302 | int | |
303 | __ffshi2 (UHWtype u) | |
304 | { | |
305 | UHWtype count; | |
306 | ||
307 | if (u == 0) | |
308 | return 0; | |
309 | ||
0761b460 | 310 | return 16 - __builtin_clz (u & - u); |
ba964383 NC |
311 | } |
312 | #endif | |
038eab67 | 313 | |
0d13c974 NC |
314 | #ifdef XSTORMY16_CLRSBHI2 |
315 | /* Returns the number of leading redundant sign bits in X. | |
316 | I.e. the number of bits following the most significant bit which are | |
317 | identical to it. There are no special cases for 0 or other values. */ | |
318 | ||
319 | int | |
320 | __clrsbhi2 (HWtype x) | |
321 | { | |
322 | if (x < 0) | |
323 | x = ~x; | |
324 | if (x == 0) | |
325 | return 15; | |
326 | return __builtin_clz (x) - 1; | |
327 | } | |
328 | #endif | |
329 | ||
038eab67 NC |
330 | #ifdef XSTORMY16_UCMPSI2 |
331 | /* Performs an unsigned comparison of two 32-bit values: A and B. | |
332 | If A is less than B, then 0 is returned. If A is greater than B, | |
333 | then 2 is returned. Otherwise A and B are equal and 1 is returned. */ | |
334 | ||
335 | word_type | |
336 | __ucmpsi2 (USItype a, USItype b) | |
337 | { | |
d5f4a527 NC |
338 | word_type hi_a = (a >> 16); |
339 | word_type hi_b = (b >> 16); | |
038eab67 NC |
340 | |
341 | if (hi_a == hi_b) | |
342 | { | |
d5f4a527 NC |
343 | word_type low_a = (a & 0xffff); |
344 | word_type low_b = (b & 0xffff); | |
038eab67 NC |
345 | |
346 | return low_a < low_b ? 0 : (low_a > low_b ? 2 : 1); | |
347 | } | |
348 | ||
349 | return hi_a < hi_b ? 0 : 2; | |
350 | } | |
351 | #endif | |
bfd71bc1 NC |
352 | |
353 | #ifdef XSTORMY16_CMPSI2 | |
354 | /* Performs an signed comparison of two 32-bit values: A and B. | |
355 | If A is less than B, then 0 is returned. If A is greater than B, | |
356 | then 2 is returned. Otherwise A and B are equal and 1 is returned. */ | |
357 | ||
358 | word_type | |
359 | __cmpsi2 (SItype a, SItype b) | |
360 | { | |
361 | word_type hi_a = (a >> 16); | |
362 | word_type hi_b = (b >> 16); | |
363 | ||
364 | if (hi_a == hi_b) | |
365 | { | |
366 | word_type low_a = (a & 0xffff); | |
367 | word_type low_b = (b & 0xffff); | |
368 | ||
369 | return low_a < low_b ? 0 : (low_a > low_b ? 2 : 1); | |
370 | } | |
371 | ||
372 | return hi_a < hi_b ? 0 : 2; | |
373 | } | |
374 | #endif |