1 /* Copyright (C) 2009-2016 Free Software Foundation, Inc.
2    Contributed by Anatoly Sokolov (aesok@post.ru)
3 
4    This file is part of GCC.
5 
6    GCC is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    GCC is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with GCC; see the file COPYING3.  If not see
18    <http://www.gnu.org/licenses/>.  */
19 
20 /* Not included in avr.c since this requires C front end.  */
21 
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "target.h"
26 #include "c-family/c-common.h"
27 #include "stor-layout.h"
28 #include "langhooks.h"
29 
30 
31 /* IDs for all the AVR builtins.  */
32 
33 enum avr_builtin_id
34   {
35 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME)  \
36     AVR_BUILTIN_ ## NAME,
37 #include "builtins.def"
38 #undef DEF_BUILTIN
39 
40     AVR_BUILTIN_COUNT
41   };
42 
43 
44 /* Implement `TARGET_RESOLVE_OVERLOADED_PLUGIN'.  */
45 
46 static tree
avr_resolve_overloaded_builtin(unsigned int iloc,tree fndecl,void * vargs)47 avr_resolve_overloaded_builtin (unsigned int iloc, tree fndecl, void *vargs)
48 {
49   tree type0, type1, fold = NULL_TREE;
50   enum avr_builtin_id id = AVR_BUILTIN_COUNT;
51   location_t loc = (location_t) iloc;
52   vec<tree, va_gc> &args = * (vec<tree, va_gc>*) vargs;
53 
54   switch (DECL_FUNCTION_CODE (fndecl))
55     {
56     default:
57       break;
58 
59     case AVR_BUILTIN_ABSFX:
60       if (args.length() != 1)
61         {
62           error_at (loc, "%qs expects 1 argument but %d given",
63                     "absfx", (int) args.length());
64 
65           fold = error_mark_node;
66           break;
67         }
68 
69       type0 = TREE_TYPE (args[0]);
70 
71       if (!FIXED_POINT_TYPE_P (type0))
72         {
73           error_at (loc, "%qs expects a fixed-point value as argument",
74                     "absfx");
75 
76           fold = error_mark_node;
77         }
78 
79       switch (TYPE_MODE (type0))
80         {
81         case QQmode: id = AVR_BUILTIN_ABSHR; break;
82         case HQmode: id = AVR_BUILTIN_ABSR; break;
83         case SQmode: id = AVR_BUILTIN_ABSLR; break;
84         case DQmode: id = AVR_BUILTIN_ABSLLR; break;
85 
86         case HAmode: id = AVR_BUILTIN_ABSHK; break;
87         case SAmode: id = AVR_BUILTIN_ABSK; break;
88         case DAmode: id = AVR_BUILTIN_ABSLK; break;
89         case TAmode: id = AVR_BUILTIN_ABSLLK; break;
90 
91         case UQQmode:
92         case UHQmode:
93         case USQmode:
94         case UDQmode:
95         case UHAmode:
96         case USAmode:
97         case UDAmode:
98         case UTAmode:
99           warning_at (loc, 0, "using %qs with unsigned type has no effect",
100                       "absfx");
101           return args[0];
102 
103         default:
104           error_at (loc, "no matching fixed-point overload found for %qs",
105                     "absfx");
106 
107           fold = error_mark_node;
108           break;
109         }
110 
111       fold = targetm.builtin_decl (id, true);
112 
113       if (fold != error_mark_node)
114         fold = build_function_call_vec (loc, vNULL, fold, &args, NULL);
115 
116       break; // absfx
117 
118     case AVR_BUILTIN_ROUNDFX:
119       if (args.length() != 2)
120         {
121           error_at (loc, "%qs expects 2 arguments but %d given",
122                     "roundfx", (int) args.length());
123 
124           fold = error_mark_node;
125           break;
126         }
127 
128       type0 = TREE_TYPE (args[0]);
129       type1 = TREE_TYPE (args[1]);
130 
131       if (!FIXED_POINT_TYPE_P (type0))
132         {
133           error_at (loc, "%qs expects a fixed-point value as first argument",
134                     "roundfx");
135 
136           fold = error_mark_node;
137         }
138 
139       if (!INTEGRAL_TYPE_P (type1))
140         {
141           error_at (loc, "%qs expects an integer value as second argument",
142                     "roundfx");
143 
144           fold = error_mark_node;
145         }
146 
147       switch (TYPE_MODE (type0))
148         {
149         case QQmode: id = AVR_BUILTIN_ROUNDHR; break;
150         case HQmode: id = AVR_BUILTIN_ROUNDR; break;
151         case SQmode: id = AVR_BUILTIN_ROUNDLR; break;
152         case DQmode: id = AVR_BUILTIN_ROUNDLLR; break;
153 
154         case UQQmode: id = AVR_BUILTIN_ROUNDUHR; break;
155         case UHQmode: id = AVR_BUILTIN_ROUNDUR; break;
156         case USQmode: id = AVR_BUILTIN_ROUNDULR; break;
157         case UDQmode: id = AVR_BUILTIN_ROUNDULLR; break;
158 
159         case HAmode: id = AVR_BUILTIN_ROUNDHK; break;
160         case SAmode: id = AVR_BUILTIN_ROUNDK; break;
161         case DAmode: id = AVR_BUILTIN_ROUNDLK; break;
162         case TAmode: id = AVR_BUILTIN_ROUNDLLK; break;
163 
164         case UHAmode: id = AVR_BUILTIN_ROUNDUHK; break;
165         case USAmode: id = AVR_BUILTIN_ROUNDUK; break;
166         case UDAmode: id = AVR_BUILTIN_ROUNDULK; break;
167         case UTAmode: id = AVR_BUILTIN_ROUNDULLK; break;
168 
169         default:
170           error_at (loc, "no matching fixed-point overload found for %qs",
171                     "roundfx");
172 
173           fold = error_mark_node;
174           break;
175         }
176 
177       fold = targetm.builtin_decl (id, true);
178 
179       if (fold != error_mark_node)
180         fold = build_function_call_vec (loc, vNULL, fold, &args, NULL);
181 
182       break; // roundfx
183 
184     case AVR_BUILTIN_COUNTLSFX:
185       if (args.length() != 1)
186         {
187           error_at (loc, "%qs expects 1 argument but %d given",
188                     "countlsfx", (int) args.length());
189 
190           fold = error_mark_node;
191           break;
192         }
193 
194       type0 = TREE_TYPE (args[0]);
195 
196       if (!FIXED_POINT_TYPE_P (type0))
197         {
198           error_at (loc, "%qs expects a fixed-point value as first argument",
199                     "countlsfx");
200 
201           fold = error_mark_node;
202         }
203 
204       switch (TYPE_MODE (type0))
205         {
206         case QQmode: id = AVR_BUILTIN_COUNTLSHR; break;
207         case HQmode: id = AVR_BUILTIN_COUNTLSR; break;
208         case SQmode: id = AVR_BUILTIN_COUNTLSLR; break;
209         case DQmode: id = AVR_BUILTIN_COUNTLSLLR; break;
210 
211         case UQQmode: id = AVR_BUILTIN_COUNTLSUHR; break;
212         case UHQmode: id = AVR_BUILTIN_COUNTLSUR; break;
213         case USQmode: id = AVR_BUILTIN_COUNTLSULR; break;
214         case UDQmode: id = AVR_BUILTIN_COUNTLSULLR; break;
215 
216         case HAmode: id = AVR_BUILTIN_COUNTLSHK; break;
217         case SAmode: id = AVR_BUILTIN_COUNTLSK; break;
218         case DAmode: id = AVR_BUILTIN_COUNTLSLK; break;
219         case TAmode: id = AVR_BUILTIN_COUNTLSLLK; break;
220 
221         case UHAmode: id = AVR_BUILTIN_COUNTLSUHK; break;
222         case USAmode: id = AVR_BUILTIN_COUNTLSUK; break;
223         case UDAmode: id = AVR_BUILTIN_COUNTLSULK; break;
224         case UTAmode: id = AVR_BUILTIN_COUNTLSULLK; break;
225 
226         default:
227           error_at (loc, "no matching fixed-point overload found for %qs",
228                     "countlsfx");
229 
230           fold = error_mark_node;
231           break;
232         }
233 
234       fold = targetm.builtin_decl (id, true);
235 
236       if (fold != error_mark_node)
237         fold = build_function_call_vec (loc, vNULL, fold, &args, NULL);
238 
239       break; // countlsfx
240     }
241 
242   return fold;
243 }
244 
245 
246 /* Implement `REGISTER_TARGET_PRAGMAS'.  */
247 
248 void
avr_register_target_pragmas(void)249 avr_register_target_pragmas (void)
250 {
251   int i;
252 
253   gcc_assert (ADDR_SPACE_GENERIC == ADDR_SPACE_RAM);
254 
255   /* Register address spaces.  The order must be the same as in the respective
256      enum from avr.h (or designated initializers must be used in avr.c).  */
257 
258   for (i = 0; i < ADDR_SPACE_COUNT; i++)
259     {
260       gcc_assert (i == avr_addrspace[i].id);
261 
262       if (!ADDR_SPACE_GENERIC_P (i))
263         c_register_addr_space (avr_addrspace[i].name, avr_addrspace[i].id);
264     }
265 
266   targetm.resolve_overloaded_builtin = avr_resolve_overloaded_builtin;
267 }
268 
269 
270 /* Transform LO into uppercase and write the result to UP.
271    You must provide enough space for UP.  Return UP.  */
272 
273 static char*
avr_toupper(char * up,const char * lo)274 avr_toupper (char *up, const char *lo)
275 {
276   char *up0 = up;
277 
278   for (; *lo; lo++, up++)
279     *up = TOUPPER (*lo);
280 
281   *up = '\0';
282 
283   return up0;
284 }
285 
286 /* Worker function for TARGET_CPU_CPP_BUILTINS.  */
287 
288 void
avr_cpu_cpp_builtins(struct cpp_reader * pfile)289 avr_cpu_cpp_builtins (struct cpp_reader *pfile)
290 {
291   int i;
292 
293   builtin_define_std ("AVR");
294 
295   /* __AVR_DEVICE_NAME__ and  avr_mcu_types[].macro like __AVR_ATmega8__
296 	 are defined by -D command option, see device-specs file.  */
297 
298   if (avr_arch->macro)
299     cpp_define_formatted (pfile, "__AVR_ARCH__=%s", avr_arch->macro);
300   if (AVR_HAVE_RAMPD)    cpp_define (pfile, "__AVR_HAVE_RAMPD__");
301   if (AVR_HAVE_RAMPX)    cpp_define (pfile, "__AVR_HAVE_RAMPX__");
302   if (AVR_HAVE_RAMPY)    cpp_define (pfile, "__AVR_HAVE_RAMPY__");
303   if (AVR_HAVE_RAMPZ)    cpp_define (pfile, "__AVR_HAVE_RAMPZ__");
304   if (AVR_HAVE_ELPM)     cpp_define (pfile, "__AVR_HAVE_ELPM__");
305   if (AVR_HAVE_ELPMX)    cpp_define (pfile, "__AVR_HAVE_ELPMX__");
306   if (AVR_HAVE_MOVW)     cpp_define (pfile, "__AVR_HAVE_MOVW__");
307   if (AVR_HAVE_LPMX)     cpp_define (pfile, "__AVR_HAVE_LPMX__");
308 
309   if (avr_arch->asm_only)
310     cpp_define (pfile, "__AVR_ASM_ONLY__");
311   if (AVR_HAVE_MUL)
312     {
313       cpp_define (pfile, "__AVR_ENHANCED__");
314       cpp_define (pfile, "__AVR_HAVE_MUL__");
315     }
316   if (avr_arch->have_jmp_call)
317     {
318       cpp_define (pfile, "__AVR_MEGA__");
319       cpp_define (pfile, "__AVR_HAVE_JMP_CALL__");
320     }
321   if (AVR_XMEGA)
322     cpp_define (pfile, "__AVR_XMEGA__");
323 
324   if (AVR_TINY)
325     {
326       cpp_define (pfile, "__AVR_TINY__");
327 
328       /* Define macro "__AVR_TINY_PM_BASE_ADDRESS__" with mapped program memory
329          start address.  This macro shall be used where mapped program
330          memory is accessed, eg. copying data section (__do_copy_data)
331          contents to data memory region.
332          NOTE:
333          Program memory of AVR_TINY devices cannot be accessed directly,
334          it has been mapped to the data memory.  For AVR_TINY devices
335          (ATtiny4/5/9/10/20 and 40) mapped program memory starts at 0x4000. */
336 
337       cpp_define (pfile, "__AVR_TINY_PM_BASE_ADDRESS__=0x4000");
338     }
339 
340   if (AVR_HAVE_EIJMP_EICALL)
341     {
342       cpp_define (pfile, "__AVR_HAVE_EIJMP_EICALL__");
343       cpp_define (pfile, "__AVR_3_BYTE_PC__");
344     }
345   else
346     {
347       cpp_define (pfile, "__AVR_2_BYTE_PC__");
348     }
349 
350   if (AVR_HAVE_8BIT_SP)
351     cpp_define (pfile, "__AVR_HAVE_8BIT_SP__");
352   else
353     cpp_define (pfile, "__AVR_HAVE_16BIT_SP__");
354 
355   if (AVR_HAVE_SPH)
356     cpp_define (pfile, "__AVR_HAVE_SPH__");
357   else
358     cpp_define (pfile, "__AVR_SP8__");
359 
360   if (TARGET_NO_INTERRUPTS)
361     cpp_define (pfile, "__NO_INTERRUPTS__");
362 
363   if (TARGET_SKIP_BUG)
364     {
365       cpp_define (pfile, "__AVR_ERRATA_SKIP__");
366 
367       if (AVR_HAVE_JMP_CALL)
368         cpp_define (pfile, "__AVR_ERRATA_SKIP_JMP_CALL__");
369     }
370 
371   if (TARGET_RMW)
372     cpp_define (pfile, "__AVR_ISA_RMW__");
373 
374   cpp_define_formatted (pfile, "__AVR_SFR_OFFSET__=0x%x",
375                         avr_arch->sfr_offset);
376 
377 #ifdef WITH_AVRLIBC
378   cpp_define (pfile, "__WITH_AVRLIBC__");
379 #endif /* WITH_AVRLIBC */
380 
381   /* Define builtin macros so that the user can easily query whether
382      non-generic address spaces (and which) are supported or not.
383      This is only supported for C.  For C++, a language extension is needed
384      (as mentioned in ISO/IEC DTR 18037; Annex F.2) which is not
385      implemented in GCC up to now.  */
386 
387   if (lang_GNU_C ())
388     {
389       for (i = 0; i < ADDR_SPACE_COUNT; i++)
390         if (!ADDR_SPACE_GENERIC_P (i)
391             /* Only supply __FLASH<n> macro if the address space is reasonable
392                for this target.  The address space qualifier itself is still
393                supported, but using it will throw an error.  */
394             && avr_addrspace[i].segment < avr_n_flash
395 	    /* Only support __MEMX macro if we have LPM.  */
396 	    && (AVR_HAVE_LPM || avr_addrspace[i].pointer_size <= 2))
397 
398           {
399             const char *name = avr_addrspace[i].name;
400             char *Name = (char*) alloca (1 + strlen (name));
401 
402             cpp_define (pfile, avr_toupper (Name, name));
403           }
404     }
405 
406   /* Define builtin macros so that the user can easily query whether or
407      not a specific builtin is available. */
408 
409 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME)  \
410   cpp_define (pfile, "__BUILTIN_AVR_" #NAME);
411 #include "builtins.def"
412 #undef DEF_BUILTIN
413 
414   /* Builtin macros for the __int24 and __uint24 type.  */
415 
416   cpp_define_formatted (pfile, "__INT24_MAX__=8388607%s",
417                         INT_TYPE_SIZE == 8 ? "LL" : "L");
418   cpp_define (pfile, "__INT24_MIN__=(-__INT24_MAX__-1)");
419   cpp_define_formatted (pfile, "__UINT24_MAX__=16777215%s",
420                         INT_TYPE_SIZE == 8 ? "ULL" : "UL");
421 }
422