1 /* Copyright (C) 2009-2021 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 #define IN_TARGET_CODE 1
23 
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "target.h"
28 #include "c-family/c-common.h"
29 #include "stor-layout.h"
30 #include "langhooks.h"
31 #include "memmodel.h"
32 #include "tm_p.h"
33 
34 /* IDs for all the AVR builtins.  */
35 
36 enum avr_builtin_id
37   {
38 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME)  \
39     AVR_BUILTIN_ ## NAME,
40 #include "builtins.def"
41 #undef DEF_BUILTIN
42 
43     AVR_BUILTIN_COUNT
44   };
45 
46 
47 /* Implement `TARGET_RESOLVE_OVERLOADED_PLUGIN'.  */
48 
49 static tree
avr_resolve_overloaded_builtin(unsigned int iloc,tree fndecl,void * vargs)50 avr_resolve_overloaded_builtin (unsigned int iloc, tree fndecl, void *vargs)
51 {
52   tree type0, type1, fold = NULL_TREE;
53   enum avr_builtin_id id = AVR_BUILTIN_COUNT;
54   location_t loc = (location_t) iloc;
55   vec<tree, va_gc> &args = * (vec<tree, va_gc>*) vargs;
56 
57   switch (DECL_MD_FUNCTION_CODE (fndecl))
58     {
59     default:
60       break;
61 
62     case AVR_BUILTIN_ABSFX:
63       if (args.length() != 1)
64         {
65           error_at (loc, "%qs expects 1 argument but %d given",
66                     "absfx", (int) args.length());
67 
68           fold = error_mark_node;
69           break;
70         }
71 
72       type0 = TREE_TYPE (args[0]);
73 
74       if (!FIXED_POINT_TYPE_P (type0))
75         {
76           error_at (loc, "%qs expects a fixed-point value as argument",
77                     "absfx");
78 
79           fold = error_mark_node;
80         }
81 
82       switch (TYPE_MODE (type0))
83         {
84         case E_QQmode: id = AVR_BUILTIN_ABSHR; break;
85         case E_HQmode: id = AVR_BUILTIN_ABSR; break;
86         case E_SQmode: id = AVR_BUILTIN_ABSLR; break;
87         case E_DQmode: id = AVR_BUILTIN_ABSLLR; break;
88 
89         case E_HAmode: id = AVR_BUILTIN_ABSHK; break;
90         case E_SAmode: id = AVR_BUILTIN_ABSK; break;
91         case E_DAmode: id = AVR_BUILTIN_ABSLK; break;
92         case E_TAmode: id = AVR_BUILTIN_ABSLLK; break;
93 
94         case E_UQQmode:
95         case E_UHQmode:
96         case E_USQmode:
97         case E_UDQmode:
98         case E_UHAmode:
99         case E_USAmode:
100         case E_UDAmode:
101         case E_UTAmode:
102           warning_at (loc, 0, "using %qs with unsigned type has no effect",
103                       "absfx");
104           return args[0];
105 
106         default:
107           error_at (loc, "no matching fixed-point overload found for %qs",
108                     "absfx");
109 
110           fold = error_mark_node;
111           break;
112         }
113 
114       fold = targetm.builtin_decl (id, true);
115 
116       if (fold != error_mark_node)
117         fold = build_function_call_vec (loc, vNULL, fold, &args, NULL);
118 
119       break; // absfx
120 
121     case AVR_BUILTIN_ROUNDFX:
122       if (args.length() != 2)
123         {
124           error_at (loc, "%qs expects 2 arguments but %d given",
125                     "roundfx", (int) args.length());
126 
127           fold = error_mark_node;
128           break;
129         }
130 
131       type0 = TREE_TYPE (args[0]);
132       type1 = TREE_TYPE (args[1]);
133 
134       if (!FIXED_POINT_TYPE_P (type0))
135         {
136           error_at (loc, "%qs expects a fixed-point value as first argument",
137                     "roundfx");
138 
139           fold = error_mark_node;
140         }
141 
142       if (!INTEGRAL_TYPE_P (type1))
143         {
144           error_at (loc, "%qs expects an integer value as second argument",
145                     "roundfx");
146 
147           fold = error_mark_node;
148         }
149 
150       switch (TYPE_MODE (type0))
151         {
152         case E_QQmode: id = AVR_BUILTIN_ROUNDHR; break;
153         case E_HQmode: id = AVR_BUILTIN_ROUNDR; break;
154         case E_SQmode: id = AVR_BUILTIN_ROUNDLR; break;
155         case E_DQmode: id = AVR_BUILTIN_ROUNDLLR; break;
156 
157         case E_UQQmode: id = AVR_BUILTIN_ROUNDUHR; break;
158         case E_UHQmode: id = AVR_BUILTIN_ROUNDUR; break;
159         case E_USQmode: id = AVR_BUILTIN_ROUNDULR; break;
160         case E_UDQmode: id = AVR_BUILTIN_ROUNDULLR; break;
161 
162         case E_HAmode: id = AVR_BUILTIN_ROUNDHK; break;
163         case E_SAmode: id = AVR_BUILTIN_ROUNDK; break;
164         case E_DAmode: id = AVR_BUILTIN_ROUNDLK; break;
165         case E_TAmode: id = AVR_BUILTIN_ROUNDLLK; break;
166 
167         case E_UHAmode: id = AVR_BUILTIN_ROUNDUHK; break;
168         case E_USAmode: id = AVR_BUILTIN_ROUNDUK; break;
169         case E_UDAmode: id = AVR_BUILTIN_ROUNDULK; break;
170         case E_UTAmode: id = AVR_BUILTIN_ROUNDULLK; break;
171 
172         default:
173           error_at (loc, "no matching fixed-point overload found for %qs",
174                     "roundfx");
175 
176           fold = error_mark_node;
177           break;
178         }
179 
180       fold = targetm.builtin_decl (id, true);
181 
182       if (fold != error_mark_node)
183         fold = build_function_call_vec (loc, vNULL, fold, &args, NULL);
184 
185       break; // roundfx
186 
187     case AVR_BUILTIN_COUNTLSFX:
188       if (args.length() != 1)
189         {
190           error_at (loc, "%qs expects 1 argument but %d given",
191                     "countlsfx", (int) args.length());
192 
193           fold = error_mark_node;
194           break;
195         }
196 
197       type0 = TREE_TYPE (args[0]);
198 
199       if (!FIXED_POINT_TYPE_P (type0))
200         {
201           error_at (loc, "%qs expects a fixed-point value as first argument",
202                     "countlsfx");
203 
204           fold = error_mark_node;
205         }
206 
207       switch (TYPE_MODE (type0))
208         {
209         case E_QQmode: id = AVR_BUILTIN_COUNTLSHR; break;
210         case E_HQmode: id = AVR_BUILTIN_COUNTLSR; break;
211         case E_SQmode: id = AVR_BUILTIN_COUNTLSLR; break;
212         case E_DQmode: id = AVR_BUILTIN_COUNTLSLLR; break;
213 
214         case E_UQQmode: id = AVR_BUILTIN_COUNTLSUHR; break;
215         case E_UHQmode: id = AVR_BUILTIN_COUNTLSUR; break;
216         case E_USQmode: id = AVR_BUILTIN_COUNTLSULR; break;
217         case E_UDQmode: id = AVR_BUILTIN_COUNTLSULLR; break;
218 
219         case E_HAmode: id = AVR_BUILTIN_COUNTLSHK; break;
220         case E_SAmode: id = AVR_BUILTIN_COUNTLSK; break;
221         case E_DAmode: id = AVR_BUILTIN_COUNTLSLK; break;
222         case E_TAmode: id = AVR_BUILTIN_COUNTLSLLK; break;
223 
224         case E_UHAmode: id = AVR_BUILTIN_COUNTLSUHK; break;
225         case E_USAmode: id = AVR_BUILTIN_COUNTLSUK; break;
226         case E_UDAmode: id = AVR_BUILTIN_COUNTLSULK; break;
227         case E_UTAmode: id = AVR_BUILTIN_COUNTLSULLK; break;
228 
229         default:
230           error_at (loc, "no matching fixed-point overload found for %qs",
231                     "countlsfx");
232 
233           fold = error_mark_node;
234           break;
235         }
236 
237       fold = targetm.builtin_decl (id, true);
238 
239       if (fold != error_mark_node)
240         fold = build_function_call_vec (loc, vNULL, fold, &args, NULL);
241 
242       break; // countlsfx
243     }
244 
245   return fold;
246 }
247 
248 
249 /* Implement `REGISTER_TARGET_PRAGMAS'.  */
250 
251 void
avr_register_target_pragmas(void)252 avr_register_target_pragmas (void)
253 {
254   gcc_assert (ADDR_SPACE_GENERIC == ADDR_SPACE_RAM);
255 
256   /* Register address spaces.  The order must be the same as in the respective
257      enum from avr.h (or designated initializers must be used in avr.c).
258      We always register all address spaces even if some of them make no
259      sense for some targets.  Diagnose for non-supported spaces will be
260      emit by TARGET_ADDR_SPACE_DIAGNOSE_USAGE.  */
261 
262   for (int i = 0; i < ADDR_SPACE_COUNT; i++)
263     {
264       gcc_assert (i == avr_addrspace[i].id);
265 
266       if (!ADDR_SPACE_GENERIC_P (i))
267         c_register_addr_space (avr_addrspace[i].name, avr_addrspace[i].id);
268     }
269 
270   targetm.resolve_overloaded_builtin = avr_resolve_overloaded_builtin;
271 }
272 
273 
274 /* Transform LO into uppercase and write the result to UP.
275    You must provide enough space for UP.  Return UP.  */
276 
277 static char*
avr_toupper(char * up,const char * lo)278 avr_toupper (char *up, const char *lo)
279 {
280   char *up0 = up;
281 
282   for (; *lo; lo++, up++)
283     *up = TOUPPER (*lo);
284 
285   *up = '\0';
286 
287   return up0;
288 }
289 
290 /* Worker function for TARGET_CPU_CPP_BUILTINS.  */
291 
292 void
avr_cpu_cpp_builtins(struct cpp_reader * pfile)293 avr_cpu_cpp_builtins (struct cpp_reader *pfile)
294 {
295   builtin_define_std ("AVR");
296 
297   /* __AVR_DEVICE_NAME__ and  avr_mcu_types[].macro like __AVR_ATmega8__
298      are defined by -D command option, see device-specs file.  */
299 
300   if (avr_arch->macro)
301     cpp_define_formatted (pfile, "__AVR_ARCH__=%s", avr_arch->macro);
302   if (AVR_HAVE_RAMPD)    cpp_define (pfile, "__AVR_HAVE_RAMPD__");
303   if (AVR_HAVE_RAMPX)    cpp_define (pfile, "__AVR_HAVE_RAMPX__");
304   if (AVR_HAVE_RAMPY)    cpp_define (pfile, "__AVR_HAVE_RAMPY__");
305   if (AVR_HAVE_RAMPZ)    cpp_define (pfile, "__AVR_HAVE_RAMPZ__");
306   if (AVR_HAVE_ELPM)     cpp_define (pfile, "__AVR_HAVE_ELPM__");
307   if (AVR_HAVE_ELPMX)    cpp_define (pfile, "__AVR_HAVE_ELPMX__");
308   if (AVR_HAVE_MOVW)     cpp_define (pfile, "__AVR_HAVE_MOVW__");
309   if (AVR_HAVE_LPMX)     cpp_define (pfile, "__AVR_HAVE_LPMX__");
310 
311   if (avr_arch->asm_only)
312     cpp_define (pfile, "__AVR_ASM_ONLY__");
313   if (AVR_HAVE_MUL)
314     {
315       cpp_define (pfile, "__AVR_ENHANCED__");
316       cpp_define (pfile, "__AVR_HAVE_MUL__");
317     }
318 
319   if (AVR_HAVE_JMP_CALL)
320     cpp_define (pfile, "__AVR_HAVE_JMP_CALL__");
321 
322   if (avr_arch->have_jmp_call)
323     cpp_define (pfile, "__AVR_MEGA__");
324 
325   if (AVR_SHORT_CALLS)
326     cpp_define (pfile, "__AVR_SHORT_CALLS__");
327 
328   if (AVR_XMEGA)
329     cpp_define (pfile, "__AVR_XMEGA__");
330 
331   if (AVR_TINY)
332     {
333       cpp_define (pfile, "__AVR_TINY__");
334 
335       /* Define macro "__AVR_TINY_PM_BASE_ADDRESS__" with mapped program memory
336          start address.  This macro shall be used where mapped program
337          memory is accessed, eg. copying data section (__do_copy_data)
338          contents to data memory region.
339          NOTE:
340          Program memory of AVR_TINY devices cannot be accessed directly,
341          it has been mapped to the data memory.  For AVR_TINY devices
342          (ATtiny4/5/9/10/20 and 40) mapped program memory starts at 0x4000. */
343 
344       cpp_define_formatted (pfile, "__AVR_TINY_PM_BASE_ADDRESS__=0x%x",
345                             avr_arch->flash_pm_offset);
346     }
347 
348   if (avr_arch->flash_pm_offset)
349     cpp_define_formatted (pfile, "__AVR_PM_BASE_ADDRESS__=0x%x",
350                           avr_arch->flash_pm_offset);
351 
352   if (AVR_HAVE_EIJMP_EICALL)
353     {
354       cpp_define (pfile, "__AVR_HAVE_EIJMP_EICALL__");
355       cpp_define (pfile, "__AVR_3_BYTE_PC__");
356     }
357   else
358     {
359       cpp_define (pfile, "__AVR_2_BYTE_PC__");
360     }
361 
362   if (AVR_HAVE_8BIT_SP)
363     cpp_define (pfile, "__AVR_HAVE_8BIT_SP__");
364   else
365     cpp_define (pfile, "__AVR_HAVE_16BIT_SP__");
366 
367   if (AVR_HAVE_SPH)
368     cpp_define (pfile, "__AVR_HAVE_SPH__");
369   else
370     cpp_define (pfile, "__AVR_SP8__");
371 
372   if (TARGET_NO_INTERRUPTS)
373     cpp_define (pfile, "__NO_INTERRUPTS__");
374 
375   if (TARGET_SKIP_BUG)
376     {
377       cpp_define (pfile, "__AVR_ERRATA_SKIP__");
378 
379       if (AVR_HAVE_JMP_CALL)
380         cpp_define (pfile, "__AVR_ERRATA_SKIP_JMP_CALL__");
381     }
382 
383   if (TARGET_RMW)
384     cpp_define (pfile, "__AVR_ISA_RMW__");
385 
386   cpp_define_formatted (pfile, "__AVR_SFR_OFFSET__=0x%x",
387                         avr_arch->sfr_offset);
388 
389 #ifdef WITH_AVRLIBC
390   cpp_define (pfile, "__WITH_AVRLIBC__");
391 #endif /* WITH_AVRLIBC */
392 
393   // From configure --with-libf7={|libgcc|math|math-symbols|yes|no}
394 
395 #ifdef WITH_LIBF7_LIBGCC
396   cpp_define (pfile, "__WITH_LIBF7_LIBGCC__");
397 #endif /* WITH_LIBF7_LIBGCC */
398 
399 #ifdef WITH_LIBF7_MATH
400   cpp_define (pfile, "__WITH_LIBF7_MATH__");
401 #endif /* WITH_LIBF7_MATH */
402 
403 #ifdef WITH_LIBF7_MATH_SYMBOLS
404   cpp_define (pfile, "__WITH_LIBF7_MATH_SYMBOLS__");
405 #endif /* WITH_LIBF7_MATH_SYMBOLS */
406 
407   // From configure --with-double={|32|32,64|64,32|64}
408 
409 #ifdef HAVE_DOUBLE_MULTILIB
410   cpp_define (pfile, "__HAVE_DOUBLE_MULTILIB__");
411 #endif
412 
413 #ifdef HAVE_DOUBLE64
414   cpp_define (pfile, "__HAVE_DOUBLE64__");
415 #endif
416 
417 #ifdef HAVE_DOUBLE32
418   cpp_define (pfile, "__HAVE_DOUBLE32__");
419 #endif
420 
421 #if defined (WITH_DOUBLE64)
422   cpp_define (pfile, "__DEFAULT_DOUBLE__=64");
423 #elif defined (WITH_DOUBLE32)
424   cpp_define (pfile, "__DEFAULT_DOUBLE__=32");
425 #else
426 #error "align this with config.gcc"
427 #endif
428 
429   // From configure --with-long-double={|32|32,64|64,32|64|double}
430 
431 #ifdef HAVE_LONG_DOUBLE_MULTILIB
432   cpp_define (pfile, "__HAVE_LONG_DOUBLE_MULTILIB__");
433 #endif
434 
435 #ifdef HAVE_LONG_DOUBLE64
436   cpp_define (pfile, "__HAVE_LONG_DOUBLE64__");
437 #endif
438 
439 #ifdef HAVE_LONG_DOUBLE32
440   cpp_define (pfile, "__HAVE_LONG_DOUBLE32__");
441 #endif
442 
443 #ifdef HAVE_LONG_DOUBLE_IS_DOUBLE
444   cpp_define (pfile, "__HAVE_LONG_DOUBLE_IS_DOUBLE__");
445 #endif
446 
447 #if defined (WITH_LONG_DOUBLE64)
448   cpp_define (pfile, "__DEFAULT_LONG_DOUBLE__=64");
449 #elif defined (WITH_LONG_DOUBLE32)
450   cpp_define (pfile, "__DEFAULT_LONG_DOUBLE__=32");
451 #else
452 #error "align this with config.gcc"
453 #endif
454 
455   // From configure --with-double-comparison={2|3} --with-libf7.
456 
457 #if defined (WITH_DOUBLE_COMPARISON)
458 #if WITH_DOUBLE_COMPARISON == 2 || WITH_DOUBLE_COMPARISON == 3
459   /* The number of states a DFmode comparison libcall might take and
460      reflects what avr.c:FLOAT_LIB_COMPARE_RETURNS_BOOL returns for
461      DFmode.  GCC's default is 3-state, but some libraries like LibF7
462      implement true / false (2-state).  */
463   cpp_define_formatted (pfile, "__WITH_DOUBLE_COMPARISON__=%d",
464 			WITH_DOUBLE_COMPARISON);
465 #else
466 #error "align this with config.gcc"
467 #endif
468 #else
469 #error "align this with config.gcc"
470 #endif
471 
472   /* Define builtin macros so that the user can easily query whether
473      non-generic address spaces (and which) are supported or not.
474      This is only supported for C.  For C++, a language extension is needed
475      (as mentioned in ISO/IEC DTR 18037; Annex F.2) which is not
476      implemented in GCC up to now.  */
477 
478   if (lang_GNU_C ())
479     {
480       for (int i = 0; i < ADDR_SPACE_COUNT; i++)
481         if (!ADDR_SPACE_GENERIC_P (i)
482             /* Only supply __FLASH<n> macro if the address space is reasonable
483                for this target.  The address space qualifier itself is still
484                supported, but using it will throw an error.  */
485             && avr_addr_space_supported_p ((addr_space_t) i))
486           {
487             const char *name = avr_addrspace[i].name;
488             char *Name = (char*) alloca (1 + strlen (name));
489 
490             cpp_define (pfile, avr_toupper (Name, name));
491           }
492     }
493 
494   /* Define builtin macros so that the user can easily query whether or
495      not a specific builtin is available. */
496 
497 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME)  \
498   cpp_define (pfile, "__BUILTIN_AVR_" #NAME);
499 #include "builtins.def"
500 #undef DEF_BUILTIN
501 
502   /* Builtin macros for the __int24 and __uint24 type.  */
503 
504   cpp_define_formatted (pfile, "__INT24_MAX__=8388607%s",
505                         INT_TYPE_SIZE == 8 ? "LL" : "L");
506   cpp_define (pfile, "__INT24_MIN__=(-__INT24_MAX__-1)");
507   cpp_define_formatted (pfile, "__UINT24_MAX__=16777215%s",
508                         INT_TYPE_SIZE == 8 ? "ULL" : "UL");
509 }
510