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