1 /* Copyright (C) 2013 Free Software Foundation, Inc.
2 
3    This file is part of GCC.
4 
5    GCC is free software; you can redistribute it and/or modify it under
6    the terms of the GNU General Public License as published by the Free
7    Software Foundation; either version 3, or (at your option) any later
8    version.
9 
10    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11    WARRANTY; without even the implied warranty of MERCHANTABILITY or
12    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13    for more details.
14 
15    Under Section 7 of GPL version 3, you are granted additional
16    permissions described in the GCC Runtime Library Exception, version
17    3.1, as published by the Free Software Foundation.
18 
19    You should have received a copy of the GNU General Public License and
20    a copy of the GCC Runtime Library Exception along with this program;
21    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
22    <http://www.gnu.org/licenses/>.  */
23 
24 
25 /* This file supplies implementations for some AVR-specific builtin
26    functions so that code like the following works as expected:
27 
28    int (*f (void))(_Fract)
29    {
30        return __builtin_avr_countlsr;
31    }
32 
33    In this specific case, the generated code is:
34 
35    f:
36        ldi r24,lo8(gs(__countlsHI))
37        ldi r25,hi8(gs(__countlsHI))
38        ret
39 */
40 
41 /* Map fixed-point suffix to the corresponding fixed-point type.  */
42 
43 typedef short _Fract fx_hr_t;
44 typedef _Fract fx_r_t;
45 typedef long _Fract fx_lr_t;
46 typedef long long _Fract fx_llr_t;
47 
48 typedef unsigned short _Fract fx_uhr_t;
49 typedef unsigned _Fract fx_ur_t;
50 typedef unsigned long _Fract fx_ulr_t;
51 typedef unsigned long long _Fract fx_ullr_t;
52 
53 typedef short _Accum fx_hk_t;
54 typedef _Accum fx_k_t;
55 typedef long _Accum fx_lk_t;
56 typedef long long _Accum fx_llk_t;
57 
58 typedef unsigned short _Accum fx_uhk_t;
59 typedef unsigned _Accum fx_uk_t;
60 typedef unsigned long _Accum fx_ulk_t;
61 typedef unsigned long long _Accum fx_ullk_t;
62 
63 /* Map fixed-point suffix to the corresponding natural integer type.  */
64 
65 typedef char int_hr_t;
66 typedef int int_r_t;
67 typedef long int_lr_t;
68 typedef long long int_llr_t;
69 
70 typedef unsigned char int_uhr_t;
71 typedef unsigned int int_ur_t;
72 typedef unsigned long int_ulr_t;
73 typedef unsigned long long int_ullr_t;
74 
75 typedef int int_hk_t;
76 typedef long int_k_t;
77 typedef long long int_lk_t;
78 typedef long long int_llk_t;
79 
80 typedef unsigned int int_uhk_t;
81 typedef unsigned long int_uk_t;
82 typedef unsigned long long int_ulk_t;
83 typedef unsigned long long int_ullk_t;
84 
85 /* Map mode to the corresponding integer type.  */
86 
87 typedef char int_qi_t;
88 typedef int int_hi_t;
89 typedef long int_si_t;
90 typedef long long int_di_t;
91 
92 typedef unsigned char uint_qi_t;
93 typedef unsigned int uint_hi_t;
94 typedef unsigned long uint_si_t;
95 typedef unsigned long long uint_di_t;
96 
97 
98 
99 /************************************************************************/
100 
101 /* Supply implementations / symbols for __builtin_roundFX ASM_NAME.  */
102 
103 #ifdef L_round
104 
105 #define ROUND1(FX)                              \
106   ROUND2 (FX)
107 
108 #define ROUND2(FX)                                                      \
109   extern fx_## FX ##_t __round## FX (fx_## FX ##_t x, int rpoint);      \
110                                                                         \
111   fx_## FX ##_t                                                         \
112   __round## FX (fx_## FX ##_t x, int rpoint)                            \
113   {                                                                     \
114     return __builtin_avr_round ##FX (x, rpoint);                        \
115   }
116 
117 ROUND1(L_LABEL)
118 
119 #endif /* L_round */
120 
121 
122 
123 /*********************************************************************/
124 
125 /* Implement some count-leading-redundant-sign-bits to be used with
126    coundlsFX implementation.  */
127 
128 #ifdef L__clrsbqi
129 extern int __clrsbqi2 (char x);
130 
131 int
__clrsbqi2(char x)132 __clrsbqi2 (char x)
133 {
134   int ret;
135 
136   if (x < 0)
137     x = ~x;
138 
139   if (x == 0)
140     return 8 * sizeof (x) -1;
141 
142   ret = __builtin_clz (x << 8);
143   return ret - 1;
144 }
145 #endif /* L__clrsbqi */
146 
147 
148 #ifdef L__clrsbdi
149 extern int __clrsbdi2 (long long x);
150 
151 int
__clrsbdi2(long long x)152 __clrsbdi2 (long long x)
153 {
154   int ret;
155 
156   if (x < 0LL)
157     x = ~x;
158 
159   if (x == 0LL)
160     return 8 * sizeof (x) -1;
161 
162   ret = __builtin_clzll ((unsigned long long) x);
163   return ret - 1;
164 }
165 #endif /* L__clrsbdi */
166 
167 
168 
169 /*********************************************************************/
170 
171 /* Supply implementations / symbols for __builtin_avr_countlsFX.  */
172 
173 /* Signed */
174 
175 #ifdef L_countls
176 
177 #define COUNTLS1(MM)                            \
178   COUNTLS2 (MM)
179 
180 #define COUNTLS2(MM)                                                    \
181   extern int __countls## MM ##2 (int_## MM ##_t);                       \
182   extern int __clrsb## MM ##2 (int_## MM ##_t);                         \
183                                                                         \
184   int                                                                   \
185   __countls## MM ##2 (int_## MM ##_t x)                                 \
186   {                                                                     \
187     if (x == 0)                                                         \
188       return __INT8_MAX__;                                              \
189                                                                         \
190     return __clrsb## MM ##2 (x);                                        \
191   }
192 
193 COUNTLS1(L_LABEL)
194 
195 #endif /* L_countls */
196 
197 /* Unsigned */
198 
199 #ifdef L_countlsu
200 
201 #define clz_qi2 __builtin_clz /* unused, avoid warning */
202 #define clz_hi2 __builtin_clz
203 #define clz_si2 __builtin_clzl
204 #define clz_di2 __builtin_clzll
205 
206 #define COUNTLS1(MM)                            \
207   COUNTLS2 (MM)
208 
209 #define COUNTLS2(MM)                                                    \
210   extern int __countlsu## MM ##2 (uint_## MM ##_t);                     \
211                                                                         \
212   int                                                                   \
213   __countlsu## MM ##2 (uint_## MM ##_t x)                               \
214   {                                                                     \
215     if (x == 0)                                                         \
216       return __INT8_MAX__;                                              \
217                                                                         \
218     if (sizeof (x) == 1)                                                \
219       return clz_hi2 (x << 8);                                          \
220     else                                                                \
221       return clz_## MM ##2 (x);                                         \
222   }
223 
224 COUNTLS1(L_LABEL)
225 
226 #endif /* L_countlsu */
227