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