1/* Copyright (C) 2009-2022 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.cc 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.cc). 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.cc: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