1/* Copyright (C) 2009-2020 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
36enum 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
49static tree
50avr_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
251void
252avr_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
277static char*
278avr_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
292void
293avr_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