xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/avr/avr-c.c (revision d90047b5d07facf36e6c01dcc0bded8997ce9cc2)
1 /* Copyright (C) 2009-2017 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 #include "memmodel.h"
30 #include "tm_p.h"
31 
32 /* IDs for all the AVR builtins.  */
33 
34 enum avr_builtin_id
35   {
36 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME)  \
37     AVR_BUILTIN_ ## NAME,
38 #include "builtins.def"
39 #undef DEF_BUILTIN
40 
41     AVR_BUILTIN_COUNT
42   };
43 
44 
45 /* Implement `TARGET_RESOLVE_OVERLOADED_PLUGIN'.  */
46 
47 static tree
48 avr_resolve_overloaded_builtin (unsigned int iloc, tree fndecl, void *vargs)
49 {
50   tree type0, type1, fold = NULL_TREE;
51   enum avr_builtin_id id = AVR_BUILTIN_COUNT;
52   location_t loc = (location_t) iloc;
53   vec<tree, va_gc> &args = * (vec<tree, va_gc>*) vargs;
54 
55   switch (DECL_FUNCTION_CODE (fndecl))
56     {
57     default:
58       break;
59 
60     case AVR_BUILTIN_ABSFX:
61       if (args.length() != 1)
62         {
63           error_at (loc, "%qs expects 1 argument but %d given",
64                     "absfx", (int) args.length());
65 
66           fold = error_mark_node;
67           break;
68         }
69 
70       type0 = TREE_TYPE (args[0]);
71 
72       if (!FIXED_POINT_TYPE_P (type0))
73         {
74           error_at (loc, "%qs expects a fixed-point value as argument",
75                     "absfx");
76 
77           fold = error_mark_node;
78         }
79 
80       switch (TYPE_MODE (type0))
81         {
82         case QQmode: id = AVR_BUILTIN_ABSHR; break;
83         case HQmode: id = AVR_BUILTIN_ABSR; break;
84         case SQmode: id = AVR_BUILTIN_ABSLR; break;
85         case DQmode: id = AVR_BUILTIN_ABSLLR; break;
86 
87         case HAmode: id = AVR_BUILTIN_ABSHK; break;
88         case SAmode: id = AVR_BUILTIN_ABSK; break;
89         case DAmode: id = AVR_BUILTIN_ABSLK; break;
90         case TAmode: id = AVR_BUILTIN_ABSLLK; break;
91 
92         case UQQmode:
93         case UHQmode:
94         case USQmode:
95         case UDQmode:
96         case UHAmode:
97         case USAmode:
98         case UDAmode:
99         case UTAmode:
100           warning_at (loc, 0, "using %qs with unsigned type has no effect",
101                       "absfx");
102           return args[0];
103 
104         default:
105           error_at (loc, "no matching fixed-point overload found for %qs",
106                     "absfx");
107 
108           fold = error_mark_node;
109           break;
110         }
111 
112       fold = targetm.builtin_decl (id, true);
113 
114       if (fold != error_mark_node)
115         fold = build_function_call_vec (loc, vNULL, fold, &args, NULL);
116 
117       break; // absfx
118 
119     case AVR_BUILTIN_ROUNDFX:
120       if (args.length() != 2)
121         {
122           error_at (loc, "%qs expects 2 arguments but %d given",
123                     "roundfx", (int) args.length());
124 
125           fold = error_mark_node;
126           break;
127         }
128 
129       type0 = TREE_TYPE (args[0]);
130       type1 = TREE_TYPE (args[1]);
131 
132       if (!FIXED_POINT_TYPE_P (type0))
133         {
134           error_at (loc, "%qs expects a fixed-point value as first argument",
135                     "roundfx");
136 
137           fold = error_mark_node;
138         }
139 
140       if (!INTEGRAL_TYPE_P (type1))
141         {
142           error_at (loc, "%qs expects an integer value as second argument",
143                     "roundfx");
144 
145           fold = error_mark_node;
146         }
147 
148       switch (TYPE_MODE (type0))
149         {
150         case QQmode: id = AVR_BUILTIN_ROUNDHR; break;
151         case HQmode: id = AVR_BUILTIN_ROUNDR; break;
152         case SQmode: id = AVR_BUILTIN_ROUNDLR; break;
153         case DQmode: id = AVR_BUILTIN_ROUNDLLR; break;
154 
155         case UQQmode: id = AVR_BUILTIN_ROUNDUHR; break;
156         case UHQmode: id = AVR_BUILTIN_ROUNDUR; break;
157         case USQmode: id = AVR_BUILTIN_ROUNDULR; break;
158         case UDQmode: id = AVR_BUILTIN_ROUNDULLR; break;
159 
160         case HAmode: id = AVR_BUILTIN_ROUNDHK; break;
161         case SAmode: id = AVR_BUILTIN_ROUNDK; break;
162         case DAmode: id = AVR_BUILTIN_ROUNDLK; break;
163         case TAmode: id = AVR_BUILTIN_ROUNDLLK; break;
164 
165         case UHAmode: id = AVR_BUILTIN_ROUNDUHK; break;
166         case USAmode: id = AVR_BUILTIN_ROUNDUK; break;
167         case UDAmode: id = AVR_BUILTIN_ROUNDULK; break;
168         case UTAmode: id = AVR_BUILTIN_ROUNDULLK; break;
169 
170         default:
171           error_at (loc, "no matching fixed-point overload found for %qs",
172                     "roundfx");
173 
174           fold = error_mark_node;
175           break;
176         }
177 
178       fold = targetm.builtin_decl (id, true);
179 
180       if (fold != error_mark_node)
181         fold = build_function_call_vec (loc, vNULL, fold, &args, NULL);
182 
183       break; // roundfx
184 
185     case AVR_BUILTIN_COUNTLSFX:
186       if (args.length() != 1)
187         {
188           error_at (loc, "%qs expects 1 argument but %d given",
189                     "countlsfx", (int) args.length());
190 
191           fold = error_mark_node;
192           break;
193         }
194 
195       type0 = TREE_TYPE (args[0]);
196 
197       if (!FIXED_POINT_TYPE_P (type0))
198         {
199           error_at (loc, "%qs expects a fixed-point value as first argument",
200                     "countlsfx");
201 
202           fold = error_mark_node;
203         }
204 
205       switch (TYPE_MODE (type0))
206         {
207         case QQmode: id = AVR_BUILTIN_COUNTLSHR; break;
208         case HQmode: id = AVR_BUILTIN_COUNTLSR; break;
209         case SQmode: id = AVR_BUILTIN_COUNTLSLR; break;
210         case DQmode: id = AVR_BUILTIN_COUNTLSLLR; break;
211 
212         case UQQmode: id = AVR_BUILTIN_COUNTLSUHR; break;
213         case UHQmode: id = AVR_BUILTIN_COUNTLSUR; break;
214         case USQmode: id = AVR_BUILTIN_COUNTLSULR; break;
215         case UDQmode: id = AVR_BUILTIN_COUNTLSULLR; break;
216 
217         case HAmode: id = AVR_BUILTIN_COUNTLSHK; break;
218         case SAmode: id = AVR_BUILTIN_COUNTLSK; break;
219         case DAmode: id = AVR_BUILTIN_COUNTLSLK; break;
220         case TAmode: id = AVR_BUILTIN_COUNTLSLLK; break;
221 
222         case UHAmode: id = AVR_BUILTIN_COUNTLSUHK; break;
223         case USAmode: id = AVR_BUILTIN_COUNTLSUK; break;
224         case UDAmode: id = AVR_BUILTIN_COUNTLSULK; break;
225         case UTAmode: id = AVR_BUILTIN_COUNTLSULLK; break;
226 
227         default:
228           error_at (loc, "no matching fixed-point overload found for %qs",
229                     "countlsfx");
230 
231           fold = error_mark_node;
232           break;
233         }
234 
235       fold = targetm.builtin_decl (id, true);
236 
237       if (fold != error_mark_node)
238         fold = build_function_call_vec (loc, vNULL, fold, &args, NULL);
239 
240       break; // countlsfx
241     }
242 
243   return fold;
244 }
245 
246 
247 /* Implement `REGISTER_TARGET_PRAGMAS'.  */
248 
249 void
250 avr_register_target_pragmas (void)
251 {
252   gcc_assert (ADDR_SPACE_GENERIC == ADDR_SPACE_RAM);
253 
254   /* Register address spaces.  The order must be the same as in the respective
255      enum from avr.h (or designated initializers must be used in avr.c).
256      We always register all address spaces even if some of them make no
257      sense for some targets.  Diagnose for non-supported spaces will be
258      emit by TARGET_ADDR_SPACE_DIAGNOSE_USAGE.  */
259 
260   for (int i = 0; i < ADDR_SPACE_COUNT; i++)
261     {
262       gcc_assert (i == avr_addrspace[i].id);
263 
264       if (!ADDR_SPACE_GENERIC_P (i))
265         c_register_addr_space (avr_addrspace[i].name, avr_addrspace[i].id);
266     }
267 
268   targetm.resolve_overloaded_builtin = avr_resolve_overloaded_builtin;
269 }
270 
271 
272 /* Transform LO into uppercase and write the result to UP.
273    You must provide enough space for UP.  Return UP.  */
274 
275 static char*
276 avr_toupper (char *up, const char *lo)
277 {
278   char *up0 = up;
279 
280   for (; *lo; lo++, up++)
281     *up = TOUPPER (*lo);
282 
283   *up = '\0';
284 
285   return up0;
286 }
287 
288 /* Worker function for TARGET_CPU_CPP_BUILTINS.  */
289 
290 void
291 avr_cpu_cpp_builtins (struct cpp_reader *pfile)
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_formatted (pfile, "__AVR_TINY_PM_BASE_ADDRESS__=0x%x",
338                             AVR_TINY_PM_OFFSET);
339     }
340 
341   if (AVR_HAVE_EIJMP_EICALL)
342     {
343       cpp_define (pfile, "__AVR_HAVE_EIJMP_EICALL__");
344       cpp_define (pfile, "__AVR_3_BYTE_PC__");
345     }
346   else
347     {
348       cpp_define (pfile, "__AVR_2_BYTE_PC__");
349     }
350 
351   if (AVR_HAVE_8BIT_SP)
352     cpp_define (pfile, "__AVR_HAVE_8BIT_SP__");
353   else
354     cpp_define (pfile, "__AVR_HAVE_16BIT_SP__");
355 
356   if (AVR_HAVE_SPH)
357     cpp_define (pfile, "__AVR_HAVE_SPH__");
358   else
359     cpp_define (pfile, "__AVR_SP8__");
360 
361   if (TARGET_NO_INTERRUPTS)
362     cpp_define (pfile, "__NO_INTERRUPTS__");
363 
364   if (TARGET_SKIP_BUG)
365     {
366       cpp_define (pfile, "__AVR_ERRATA_SKIP__");
367 
368       if (AVR_HAVE_JMP_CALL)
369         cpp_define (pfile, "__AVR_ERRATA_SKIP_JMP_CALL__");
370     }
371 
372   if (TARGET_RMW)
373     cpp_define (pfile, "__AVR_ISA_RMW__");
374 
375   cpp_define_formatted (pfile, "__AVR_SFR_OFFSET__=0x%x",
376                         avr_arch->sfr_offset);
377 
378 #ifdef WITH_AVRLIBC
379   cpp_define (pfile, "__WITH_AVRLIBC__");
380 #endif /* WITH_AVRLIBC */
381 
382   /* Define builtin macros so that the user can easily query whether
383      non-generic address spaces (and which) are supported or not.
384      This is only supported for C.  For C++, a language extension is needed
385      (as mentioned in ISO/IEC DTR 18037; Annex F.2) which is not
386      implemented in GCC up to now.  */
387 
388   if (lang_GNU_C ())
389     {
390       for (int i = 0; i < ADDR_SPACE_COUNT; i++)
391         if (!ADDR_SPACE_GENERIC_P (i)
392             /* Only supply __FLASH<n> macro if the address space is reasonable
393                for this target.  The address space qualifier itself is still
394                supported, but using it will throw an error.  */
395             && avr_addr_space_supported_p ((addr_space_t) i))
396           {
397             const char *name = avr_addrspace[i].name;
398             char *Name = (char*) alloca (1 + strlen (name));
399 
400             cpp_define (pfile, avr_toupper (Name, name));
401           }
402     }
403 
404   /* Define builtin macros so that the user can easily query whether or
405      not a specific builtin is available. */
406 
407 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME)  \
408   cpp_define (pfile, "__BUILTIN_AVR_" #NAME);
409 #include "builtins.def"
410 #undef DEF_BUILTIN
411 
412   /* Builtin macros for the __int24 and __uint24 type.  */
413 
414   cpp_define_formatted (pfile, "__INT24_MAX__=8388607%s",
415                         INT_TYPE_SIZE == 8 ? "LL" : "L");
416   cpp_define (pfile, "__INT24_MIN__=(-__INT24_MAX__-1)");
417   cpp_define_formatted (pfile, "__UINT24_MAX__=16777215%s",
418                         INT_TYPE_SIZE == 8 ? "ULL" : "UL");
419 }
420