1 /* Subroutines used for code generation on TI MSP430 processors. 2 Copyright (C) 2012-2015 Free Software Foundation, Inc. 3 Contributed by Red Hat. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 GCC is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 #include "config.h" 22 #include "system.h" 23 #include "coretypes.h" 24 #include "tm.h" 25 #include "hash-set.h" 26 #include "machmode.h" 27 #include "vec.h" 28 #include "double-int.h" 29 #include "input.h" 30 #include "alias.h" 31 #include "symtab.h" 32 #include "wide-int.h" 33 #include "inchash.h" 34 #include "tree.h" 35 #include "fold-const.h" 36 #include "stor-layout.h" 37 #include "calls.h" 38 #include "rtl.h" 39 #include "regs.h" 40 #include "hard-reg-set.h" 41 #include "insn-config.h" 42 #include "conditions.h" 43 #include "output.h" 44 #include "insn-attr.h" 45 #include "flags.h" 46 #include "function.h" 47 #include "hashtab.h" 48 #include "statistics.h" 49 #include "real.h" 50 #include "fixed-value.h" 51 #include "expmed.h" 52 #include "dojump.h" 53 #include "explow.h" 54 #include "emit-rtl.h" 55 #include "varasm.h" 56 #include "stmt.h" 57 #include "expr.h" 58 #include "insn-codes.h" 59 #include "optabs.h" 60 #include "libfuncs.h" 61 #include "recog.h" 62 #include "diagnostic-core.h" 63 #include "toplev.h" 64 #include "reload.h" 65 #include "dominance.h" 66 #include "cfg.h" 67 #include "cfgrtl.h" 68 #include "cfganal.h" 69 #include "lcm.h" 70 #include "cfgbuild.h" 71 #include "cfgcleanup.h" 72 #include "predict.h" 73 #include "basic-block.h" 74 #include "df.h" 75 #include "ggc.h" 76 #include "tm_p.h" 77 #include "debug.h" 78 #include "target.h" 79 #include "target-def.h" 80 #include "langhooks.h" 81 #include "msp430-protos.h" 82 #include "dumpfile.h" 83 #include "opts.h" 84 #include "builtins.h" 85 86 87 static void msp430_compute_frame_info (void); 88 89 90 91 /* Run-time Target Specification. */ 92 93 bool msp430x = true; 94 95 struct GTY(()) machine_function 96 { 97 /* If set, the rest of the fields have been computed. */ 98 int computed; 99 /* Which registers need to be saved in the pro/epilogue. */ 100 int need_to_save [FIRST_PSEUDO_REGISTER]; 101 102 /* These fields describe the frame layout... */ 103 /* arg pointer */ 104 /* 2/4 bytes for saved PC */ 105 int framesize_regs; 106 /* frame pointer */ 107 int framesize_locals; 108 int framesize_outgoing; 109 /* stack pointer */ 110 int framesize; 111 112 /* How much we adjust the stack when returning from an exception 113 handler. */ 114 rtx eh_stack_adjust; 115 }; 116 117 /* This is our init_machine_status, as set in 118 msp_option_override. */ 119 static struct machine_function * 120 msp430_init_machine_status (void) 121 { 122 struct machine_function *m; 123 124 m = ggc_cleared_alloc<machine_function> (); 125 126 return m; 127 } 128 129 #undef TARGET_OPTION_OVERRIDE 130 #define TARGET_OPTION_OVERRIDE msp430_option_override 131 132 static const char * msp430_mcu_names [] = 133 { 134 "msp430afe221", "msp430afe222", "msp430afe223", "msp430afe231", 135 "msp430afe232", "msp430afe233", "msp430afe251", "msp430afe252", 136 "msp430afe253", "msp430c091", "msp430c092", "msp430c111", 137 "msp430c1111", "msp430c112", "msp430c1121", "msp430c1331", 138 "msp430c1351", "msp430c311s", "msp430c312", "msp430c313", 139 "msp430c314", "msp430c315", "msp430c323", "msp430c325", 140 "msp430c336", "msp430c337", "msp430c412", "msp430c413", 141 "msp430e112", "msp430e313", "msp430e315", "msp430e325", 142 "msp430e337", "msp430f110", "msp430f1101", "msp430f1101a", 143 "msp430f1111", "msp430f1111a", "msp430f112", "msp430f1121", 144 "msp430f1121a", "msp430f1122", "msp430f1132", "msp430f122", 145 "msp430f1222", "msp430f123", "msp430f1232", "msp430f133", 146 "msp430f135", "msp430f147", "msp430f1471", "msp430f148", 147 "msp430f1481", "msp430f149", "msp430f1491", "msp430f155", 148 "msp430f156", "msp430f157", "msp430f1610", "msp430f1611", 149 "msp430f1612", "msp430f167", "msp430f168", "msp430f169", 150 "msp430f2001", "msp430f2002", "msp430f2003", "msp430f2011", 151 "msp430f2012", "msp430f2013", "msp430f2101", "msp430f2111", 152 "msp430f2112", "msp430f2121", "msp430f2122", "msp430f2131", 153 "msp430f2132", "msp430f2232", "msp430f2234", "msp430f2252", 154 "msp430f2254", "msp430f2272", "msp430f2274", "msp430f233", 155 "msp430f2330", "msp430f235", "msp430f2350", "msp430f2370", 156 "msp430f2410", "msp430f247", "msp430f2471", "msp430f248", 157 "msp430f2481", "msp430f249", "msp430f2491", "msp430f412", 158 "msp430f413", "msp430f4132", "msp430f415", "msp430f4152", 159 "msp430f417", "msp430f423", "msp430f423a", "msp430f425", 160 "msp430f4250", "msp430f425a", "msp430f4260", "msp430f427", 161 "msp430f4270", "msp430f427a", "msp430f435", "msp430f4351", 162 "msp430f436", "msp430f4361", "msp430f437", "msp430f4371", 163 "msp430f438", "msp430f439", "msp430f447", "msp430f448", 164 "msp430f4481", "msp430f449", "msp430f4491", "msp430f477", 165 "msp430f478", "msp430f4783", "msp430f4784", "msp430f479", 166 "msp430f4793", "msp430f4794", "msp430fe423", "msp430fe4232", 167 "msp430fe423a", "msp430fe4242", "msp430fe425", "msp430fe4252", 168 "msp430fe425a", "msp430fe427", "msp430fe4272", "msp430fe427a", 169 "msp430fg4250", "msp430fg4260", "msp430fg4270", "msp430fg437", 170 "msp430fg438", "msp430fg439", "msp430fg477", "msp430fg478", 171 "msp430fg479", "msp430fw423", "msp430fw425", "msp430fw427", 172 "msp430fw428", "msp430fw429", "msp430g2001", "msp430g2101", 173 "msp430g2102", "msp430g2111", "msp430g2112", "msp430g2113", 174 "msp430g2121", "msp430g2131", "msp430g2132", "msp430g2152", 175 "msp430g2153", "msp430g2201", "msp430g2202", "msp430g2203", 176 "msp430g2210", "msp430g2211", "msp430g2212", "msp430g2213", 177 "msp430g2221", "msp430g2230", "msp430g2231", "msp430g2232", 178 "msp430g2233", "msp430g2252", "msp430g2253", "msp430g2302", 179 "msp430g2303", "msp430g2312", "msp430g2313", "msp430g2332", 180 "msp430g2333", "msp430g2352", "msp430g2353", "msp430g2402", 181 "msp430g2403", "msp430g2412", "msp430g2413", "msp430g2432", 182 "msp430g2433", "msp430g2444", "msp430g2452", "msp430g2453", 183 "msp430g2513", "msp430g2533", "msp430g2544", "msp430g2553", 184 "msp430g2744", "msp430g2755", "msp430g2855", "msp430g2955", 185 "msp430i2020", "msp430i2021", "msp430i2030", "msp430i2031", 186 "msp430i2040", "msp430i2041", "msp430l092", "msp430p112", 187 "msp430p313", "msp430p315", "msp430p315s", "msp430p325", 188 "msp430p337", "msp430tch5e" 189 }; 190 191 /* Generate a C preprocessor symbol based upon the MCU selected by the user. 192 If a specific MCU has not been selected then return a generic symbol instead. */ 193 194 const char * 195 msp430_mcu_name (void) 196 { 197 if (target_mcu) 198 { 199 unsigned int i; 200 static char mcu_name [64]; 201 202 snprintf (mcu_name, sizeof (mcu_name) - 1, "__%s__", target_mcu); 203 for (i = strlen (mcu_name); i--;) 204 mcu_name[i] = TOUPPER (mcu_name[i]); 205 return mcu_name; 206 } 207 208 return msp430x ? "__MSP430XGENERIC__" : "__MSP430GENERIC__"; 209 } 210 211 static void 212 msp430_option_override (void) 213 { 214 init_machine_status = msp430_init_machine_status; 215 216 if (target_cpu) 217 { 218 if (strcasecmp (target_cpu, "msp430x") == 0) 219 msp430x = true; 220 else /* target_cpu == "msp430" - already handled by the front end. */ 221 msp430x = false; 222 } 223 /* Note - the front end has already ensured at most 224 one of target_cpu and target_mcu will be set. */ 225 else if (target_mcu) 226 { 227 int i; 228 229 /* If we are given an MCU name, we assume that it supports 430X. 230 Then we check to see if it is one of the known MCUs that only 231 supports 430. */ 232 msp430x = true; 233 234 for (i = ARRAY_SIZE (msp430_mcu_names); i--;) 235 if (strcasecmp (msp430_mcu_names[i], target_mcu) == 0) 236 { 237 msp430x = false; 238 break; 239 } 240 /* It is not an error if we do not match the MCU name. There are 241 hundreds of them. */ 242 } 243 244 if (TARGET_LARGE && !msp430x) 245 error ("-mlarge requires a 430X-compatible -mmcu="); 246 247 if (flag_exceptions || flag_non_call_exceptions 248 || flag_unwind_tables || flag_asynchronous_unwind_tables) 249 flag_omit_frame_pointer = false; 250 else 251 flag_omit_frame_pointer = true; 252 253 /* This is a hack to work around a problem with the newlib build 254 mechanism. Newlib always appends CFLAGS to the end of the GCC 255 command line and always sets -O2 in CFLAGS. Thus it is not 256 possible to build newlib with -Os enabled. Until now... */ 257 if (TARGET_OPT_SPACE && optimize < 3) 258 optimize_size = 1; 259 } 260 261 #undef TARGET_SCALAR_MODE_SUPPORTED_P 262 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p 263 264 static bool 265 msp430_scalar_mode_supported_p (machine_mode m) 266 { 267 if (m == PSImode && msp430x) 268 return true; 269 #if 0 270 if (m == TImode) 271 return true; 272 #endif 273 return default_scalar_mode_supported_p (m); 274 } 275 276 277 278 /* Storage Layout */ 279 280 #undef TARGET_MS_BITFIELD_LAYOUT_P 281 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p 282 283 bool 284 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED) 285 { 286 return false; 287 } 288 289 290 291 /* Register Usage */ 292 293 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single 294 PSImode value, but not an SImode value. */ 295 int 296 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED, 297 machine_mode mode) 298 { 299 if (mode == PSImode && msp430x) 300 return 1; 301 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) 302 / UNITS_PER_WORD); 303 } 304 305 /* Implements HARD_REGNO_NREGS_HAS_PADDING. */ 306 int 307 msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED, 308 machine_mode mode) 309 { 310 if (mode == PSImode && msp430x) 311 return 1; 312 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) 313 / UNITS_PER_WORD); 314 } 315 316 /* Implements HARD_REGNO_NREGS_WITH_PADDING. */ 317 int 318 msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED, 319 machine_mode mode) 320 { 321 if (mode == PSImode) 322 return 2; 323 return msp430_hard_regno_nregs (regno, mode); 324 } 325 326 /* Implements HARD_REGNO_MODE_OK. */ 327 int 328 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED, 329 machine_mode mode) 330 { 331 return regno <= (ARG_POINTER_REGNUM - msp430_hard_regno_nregs (regno, mode)); 332 } 333 334 /* Implements MODES_TIEABLE_P. */ 335 bool 336 msp430_modes_tieable_p (machine_mode mode1, machine_mode mode2) 337 { 338 if ((mode1 == PSImode || mode2 == SImode) 339 || (mode1 == SImode || mode2 == PSImode)) 340 return false; 341 342 return ((GET_MODE_CLASS (mode1) == MODE_FLOAT 343 || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT) 344 == (GET_MODE_CLASS (mode2) == MODE_FLOAT 345 || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT)); 346 } 347 348 #undef TARGET_FRAME_POINTER_REQUIRED 349 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required 350 351 static bool 352 msp430_frame_pointer_required (void) 353 { 354 return false; 355 } 356 357 #undef TARGET_CAN_ELIMINATE 358 #define TARGET_CAN_ELIMINATE msp430_can_eliminate 359 360 static bool 361 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED, 362 const int to_reg ATTRIBUTE_UNUSED) 363 { 364 return true; 365 } 366 367 /* Implements INITIAL_ELIMINATION_OFFSET. */ 368 int 369 msp430_initial_elimination_offset (int from, int to) 370 { 371 int rv = 0; /* As if arg to arg. */ 372 373 msp430_compute_frame_info (); 374 375 switch (to) 376 { 377 case STACK_POINTER_REGNUM: 378 rv += cfun->machine->framesize_outgoing; 379 rv += cfun->machine->framesize_locals; 380 /* Fall through. */ 381 case FRAME_POINTER_REGNUM: 382 rv += cfun->machine->framesize_regs; 383 /* Allow for the saved return address. */ 384 rv += (TARGET_LARGE ? 4 : 2); 385 /* NB/ No need to allow for crtl->args.pretend_args_size. 386 GCC does that for us. */ 387 break; 388 default: 389 gcc_unreachable (); 390 } 391 392 switch (from) 393 { 394 case FRAME_POINTER_REGNUM: 395 /* Allow for the fall through above. */ 396 rv -= (TARGET_LARGE ? 4 : 2); 397 rv -= cfun->machine->framesize_regs; 398 case ARG_POINTER_REGNUM: 399 break; 400 default: 401 gcc_unreachable (); 402 } 403 404 return rv; 405 } 406 407 /* Named Address Space support */ 408 409 410 /* Return the appropriate mode for a named address pointer. */ 411 #undef TARGET_ADDR_SPACE_POINTER_MODE 412 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode 413 #undef TARGET_ADDR_SPACE_ADDRESS_MODE 414 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode 415 416 static machine_mode 417 msp430_addr_space_pointer_mode (addr_space_t addrspace) 418 { 419 switch (addrspace) 420 { 421 default: 422 case ADDR_SPACE_GENERIC: 423 return Pmode; 424 case ADDR_SPACE_NEAR: 425 return HImode; 426 case ADDR_SPACE_FAR: 427 return PSImode; 428 } 429 } 430 431 /* Function pointers are stored in unwind_word sized 432 variables, so make sure that unwind_word is big enough. */ 433 #undef TARGET_UNWIND_WORD_MODE 434 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode 435 436 static machine_mode 437 msp430_unwind_word_mode (void) 438 { 439 return TARGET_LARGE ? PSImode : HImode; 440 } 441 442 /* Determine if one named address space is a subset of another. */ 443 #undef TARGET_ADDR_SPACE_SUBSET_P 444 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p 445 static bool 446 msp430_addr_space_subset_p (addr_space_t subset, addr_space_t superset) 447 { 448 if (subset == superset) 449 return true; 450 else 451 return (subset != ADDR_SPACE_FAR && superset == ADDR_SPACE_FAR); 452 } 453 454 #undef TARGET_ADDR_SPACE_CONVERT 455 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert 456 /* Convert from one address space to another. */ 457 static rtx 458 msp430_addr_space_convert (rtx op, tree from_type, tree to_type) 459 { 460 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type)); 461 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type)); 462 rtx result; 463 464 if (to_as != ADDR_SPACE_FAR && from_as == ADDR_SPACE_FAR) 465 { 466 /* This is unpredictable, as we're truncating off usable address 467 bits. */ 468 469 if (CONSTANT_P (op)) 470 return gen_rtx_CONST (HImode, op); 471 472 result = gen_reg_rtx (HImode); 473 emit_insn (gen_truncpsihi2 (result, op)); 474 return result; 475 } 476 else if (to_as == ADDR_SPACE_FAR && from_as != ADDR_SPACE_FAR) 477 { 478 /* This always works. */ 479 480 if (CONSTANT_P (op)) 481 return gen_rtx_CONST (PSImode, op); 482 483 result = gen_reg_rtx (PSImode); 484 emit_insn (gen_zero_extendhipsi2 (result, op)); 485 return result; 486 } 487 else 488 gcc_unreachable (); 489 } 490 491 /* Stack Layout and Calling Conventions. */ 492 493 /* For each function, we list the gcc version and the TI version on 494 each line, where we're converting the function names. */ 495 static char const * const special_convention_function_names [] = 496 { 497 "__muldi3", "__mspabi_mpyll", 498 "__udivdi3", "__mspabi_divull", 499 "__umoddi3", "__mspabi_remull", 500 "__divdi3", "__mspabi_divlli", 501 "__moddi3", "__mspabi_remlli", 502 "__mspabi_srall", 503 "__mspabi_srlll", 504 "__mspabi_sllll", 505 "__adddf3", "__mspabi_addd", 506 "__subdf3", "__mspabi_subd", 507 "__muldf3", "__mspabi_mpyd", 508 "__divdf3", "__mspabi_divd", 509 "__mspabi_cmpd", 510 NULL 511 }; 512 513 /* TRUE if the function passed is a "speical" function. Special 514 functions pass two DImode parameters in registers. */ 515 static bool 516 msp430_special_register_convention_p (const char *name) 517 { 518 int i; 519 520 for (i = 0; special_convention_function_names [i]; i++) 521 if (! strcmp (name, special_convention_function_names [i])) 522 return true; 523 524 return false; 525 } 526 527 #undef TARGET_FUNCTION_VALUE_REGNO_P 528 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p 529 530 bool 531 msp430_function_value_regno_p (unsigned int regno) 532 { 533 return regno == 12; 534 } 535 536 537 #undef TARGET_FUNCTION_VALUE 538 #define TARGET_FUNCTION_VALUE msp430_function_value 539 540 rtx 541 msp430_function_value (const_tree ret_type, 542 const_tree fn_decl_or_type ATTRIBUTE_UNUSED, 543 bool outgoing ATTRIBUTE_UNUSED) 544 { 545 return gen_rtx_REG (TYPE_MODE (ret_type), 12); 546 } 547 548 #undef TARGET_LIBCALL_VALUE 549 #define TARGET_LIBCALL_VALUE msp430_libcall_value 550 551 rtx 552 msp430_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED) 553 { 554 return gen_rtx_REG (mode, 12); 555 } 556 557 /* Implements INIT_CUMULATIVE_ARGS. */ 558 void 559 msp430_init_cumulative_args (CUMULATIVE_ARGS *ca, 560 tree fntype ATTRIBUTE_UNUSED, 561 rtx libname ATTRIBUTE_UNUSED, 562 tree fndecl ATTRIBUTE_UNUSED, 563 int n_named_args ATTRIBUTE_UNUSED) 564 { 565 const char *fname; 566 memset (ca, 0, sizeof(*ca)); 567 568 ca->can_split = 1; 569 570 if (fndecl) 571 fname = IDENTIFIER_POINTER (DECL_NAME (fndecl)); 572 else if (libname) 573 fname = XSTR (libname, 0); 574 else 575 fname = NULL; 576 577 if (fname && msp430_special_register_convention_p (fname)) 578 ca->special_p = 1; 579 } 580 581 /* Helper function for argument passing; this function is the common 582 code that determines where an argument will be passed. */ 583 static void 584 msp430_evaluate_arg (cumulative_args_t cap, 585 machine_mode mode, 586 const_tree type ATTRIBUTE_UNUSED, 587 bool named) 588 { 589 CUMULATIVE_ARGS *ca = get_cumulative_args (cap); 590 int nregs = GET_MODE_SIZE (mode); 591 int i; 592 593 ca->reg_count = 0; 594 ca->mem_count = 0; 595 596 if (!named) 597 return; 598 599 if (mode == PSImode) 600 nregs = 1; 601 else 602 nregs = (nregs + 1) / 2; 603 604 if (ca->special_p) 605 { 606 /* Function is passed two DImode operands, in R8:R11 and 607 R12:15. */ 608 ca->start_reg = 8; 609 ca->reg_count = 4; 610 return; 611 } 612 613 switch (nregs) 614 { 615 case 1: 616 for (i = 0; i < 4; i++) 617 if (! ca->reg_used [i]) 618 { 619 ca->reg_count = 1; 620 ca->start_reg = CA_FIRST_REG + i; 621 return; 622 } 623 break; 624 case 2: 625 for (i = 0; i < 3; i++) 626 if (! ca->reg_used [i] && ! ca->reg_used [i + 1]) 627 { 628 ca->reg_count = 2; 629 ca->start_reg = CA_FIRST_REG + i; 630 return; 631 } 632 if (! ca->reg_used [3] && ca->can_split) 633 { 634 ca->reg_count = 1; 635 ca->mem_count = 2; 636 ca->start_reg = CA_FIRST_REG + 3; 637 return; 638 } 639 break; 640 case 3: 641 case 4: 642 ca->can_split = 0; 643 if (! ca->reg_used [0] 644 && ! ca->reg_used [1] 645 && ! ca->reg_used [2] 646 && ! ca->reg_used [3]) 647 { 648 ca->reg_count = 4; 649 ca->start_reg = CA_FIRST_REG; 650 return; 651 } 652 break; 653 } 654 } 655 656 #undef TARGET_PROMOTE_PROTOTYPES 657 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes 658 659 bool 660 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED) 661 { 662 return false; 663 } 664 665 #undef TARGET_FUNCTION_ARG 666 #define TARGET_FUNCTION_ARG msp430_function_arg 667 668 rtx 669 msp430_function_arg (cumulative_args_t cap, 670 machine_mode mode, 671 const_tree type, 672 bool named) 673 { 674 CUMULATIVE_ARGS *ca = get_cumulative_args (cap); 675 676 msp430_evaluate_arg (cap, mode, type, named); 677 678 if (ca->reg_count) 679 return gen_rtx_REG (mode, ca->start_reg); 680 681 return 0; 682 } 683 684 #undef TARGET_ARG_PARTIAL_BYTES 685 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes 686 687 int 688 msp430_arg_partial_bytes (cumulative_args_t cap, 689 machine_mode mode, 690 tree type, 691 bool named) 692 { 693 CUMULATIVE_ARGS *ca = get_cumulative_args (cap); 694 695 msp430_evaluate_arg (cap, mode, type, named); 696 697 if (ca->reg_count && ca->mem_count) 698 return ca->reg_count * UNITS_PER_WORD; 699 700 return 0; 701 } 702 703 #undef TARGET_PASS_BY_REFERENCE 704 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference 705 706 static bool 707 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED, 708 machine_mode mode, 709 const_tree type, 710 bool named ATTRIBUTE_UNUSED) 711 { 712 return (mode == BLKmode 713 || (type && TREE_CODE (type) == RECORD_TYPE) 714 || (type && TREE_CODE (type) == UNION_TYPE)); 715 } 716 717 #undef TARGET_CALLEE_COPIES 718 #define TARGET_CALLEE_COPIES msp430_callee_copies 719 720 static bool 721 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED, 722 machine_mode mode ATTRIBUTE_UNUSED, 723 const_tree type ATTRIBUTE_UNUSED, 724 bool named ATTRIBUTE_UNUSED) 725 { 726 return true; 727 } 728 729 #undef TARGET_FUNCTION_ARG_ADVANCE 730 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance 731 732 void 733 msp430_function_arg_advance (cumulative_args_t cap, 734 machine_mode mode, 735 const_tree type, 736 bool named) 737 { 738 CUMULATIVE_ARGS *ca = get_cumulative_args (cap); 739 int i; 740 741 msp430_evaluate_arg (cap, mode, type, named); 742 743 if (ca->start_reg >= CA_FIRST_REG) 744 for (i = 0; i < ca->reg_count; i ++) 745 ca->reg_used [i + ca->start_reg - CA_FIRST_REG] = 1; 746 747 ca->special_p = 0; 748 } 749 750 #undef TARGET_FUNCTION_ARG_BOUNDARY 751 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary 752 753 static unsigned int 754 msp430_function_arg_boundary (machine_mode mode, const_tree type) 755 { 756 if (mode == BLKmode 757 && int_size_in_bytes (type) > 1) 758 return 16; 759 if (GET_MODE_BITSIZE (mode) > 8) 760 return 16; 761 return 8; 762 } 763 764 #undef TARGET_RETURN_IN_MEMORY 765 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory 766 767 static bool 768 msp430_return_in_memory (const_tree ret_type, const_tree fntype ATTRIBUTE_UNUSED) 769 { 770 machine_mode mode = TYPE_MODE (ret_type); 771 772 if (mode == BLKmode 773 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == RECORD_TYPE) 774 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == UNION_TYPE)) 775 return true; 776 777 if (GET_MODE_SIZE (mode) > 8) 778 return true; 779 780 return false; 781 } 782 783 #undef TARGET_GET_RAW_ARG_MODE 784 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode 785 786 static machine_mode 787 msp430_get_raw_arg_mode (int regno) 788 { 789 return (regno == ARG_POINTER_REGNUM) ? VOIDmode : Pmode; 790 } 791 792 #undef TARGET_GET_RAW_RESULT_MODE 793 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode 794 795 static machine_mode 796 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED) 797 { 798 return Pmode; 799 } 800 801 #undef TARGET_GIMPLIFY_VA_ARG_EXPR 802 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr 803 804 #include "gimplify.h" 805 #include "gimple-expr.h" 806 807 static tree 808 msp430_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, 809 gimple_seq *post_p) 810 { 811 tree addr, t, type_size, rounded_size, valist_tmp; 812 unsigned HOST_WIDE_INT align, boundary; 813 bool indirect; 814 815 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false); 816 if (indirect) 817 type = build_pointer_type (type); 818 819 align = PARM_BOUNDARY / BITS_PER_UNIT; 820 boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type); 821 822 /* When we align parameter on stack for caller, if the parameter 823 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be 824 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee 825 here with caller. */ 826 if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT) 827 boundary = MAX_SUPPORTED_STACK_ALIGNMENT; 828 829 boundary /= BITS_PER_UNIT; 830 831 /* Hoist the valist value into a temporary for the moment. */ 832 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL); 833 834 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually 835 requires greater alignment, we must perform dynamic alignment. */ 836 if (boundary > align 837 && !integer_zerop (TYPE_SIZE (type))) 838 { 839 /* FIXME: This is where this function diverts from targhooks.c: 840 std_gimplify_va_arg_expr(). It works, but I do not know why... */ 841 if (! POINTER_TYPE_P (type)) 842 { 843 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, 844 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1)); 845 gimplify_and_add (t, pre_p); 846 847 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, 848 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist), 849 valist_tmp, 850 build_int_cst (TREE_TYPE (valist), -boundary))); 851 gimplify_and_add (t, pre_p); 852 } 853 } 854 else 855 boundary = align; 856 857 /* If the actual alignment is less than the alignment of the type, 858 adjust the type accordingly so that we don't assume strict alignment 859 when dereferencing the pointer. */ 860 boundary *= BITS_PER_UNIT; 861 if (boundary < TYPE_ALIGN (type)) 862 { 863 type = build_variant_type_copy (type); 864 TYPE_ALIGN (type) = boundary; 865 } 866 867 /* Compute the rounded size of the type. */ 868 type_size = size_in_bytes (type); 869 rounded_size = round_up (type_size, align); 870 871 /* Reduce rounded_size so it's sharable with the postqueue. */ 872 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue); 873 874 /* Get AP. */ 875 addr = valist_tmp; 876 877 /* Compute new value for AP. */ 878 t = fold_build_pointer_plus (valist_tmp, rounded_size); 879 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t); 880 gimplify_and_add (t, pre_p); 881 882 addr = fold_convert (build_pointer_type (type), addr); 883 884 if (indirect) 885 addr = build_va_arg_indirect_ref (addr); 886 887 addr = build_va_arg_indirect_ref (addr); 888 889 return addr; 890 } 891 892 /* Addressing Modes */ 893 894 #undef TARGET_LEGITIMATE_ADDRESS_P 895 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p 896 897 static bool 898 reg_ok_for_addr (rtx r, bool strict) 899 { 900 int rn = REGNO (r); 901 902 if (strict && rn >= FIRST_PSEUDO_REGISTER) 903 rn = reg_renumber [rn]; 904 if (strict && 0 <= rn && rn < FIRST_PSEUDO_REGISTER) 905 return true; 906 if (!strict) 907 return true; 908 return false; 909 } 910 911 bool 912 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, 913 rtx x ATTRIBUTE_UNUSED, 914 bool strict ATTRIBUTE_UNUSED) 915 { 916 switch (GET_CODE (x)) 917 { 918 case MEM: 919 return false; 920 921 case PLUS: 922 if (REG_P (XEXP (x, 0))) 923 { 924 if (GET_MODE (x) != GET_MODE (XEXP (x, 0))) 925 return false; 926 if (!reg_ok_for_addr (XEXP (x, 0), strict)) 927 return false; 928 switch (GET_CODE (XEXP (x, 1))) 929 { 930 case CONST: 931 case SYMBOL_REF: 932 case CONST_INT: 933 return true; 934 default: 935 return false; 936 } 937 } 938 return false; 939 940 case REG: 941 if (!reg_ok_for_addr (x, strict)) 942 return false; 943 /* else... */ 944 case CONST: 945 case SYMBOL_REF: 946 case CONST_INT: 947 return true; 948 949 default: 950 return false; 951 } 952 } 953 954 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P 955 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p 956 957 bool 958 msp430_addr_space_legitimate_address_p (machine_mode mode, 959 rtx x, 960 bool strict, 961 addr_space_t as ATTRIBUTE_UNUSED) 962 { 963 return msp430_legitimate_address_p (mode, x, strict); 964 } 965 966 #undef TARGET_ASM_INTEGER 967 #define TARGET_ASM_INTEGER msp430_asm_integer 968 static bool 969 msp430_asm_integer (rtx x, unsigned int size, int aligned_p) 970 { 971 int c = GET_CODE (x); 972 973 if (size == 3 && GET_MODE (x) == PSImode) 974 size = 4; 975 976 switch (size) 977 { 978 case 4: 979 if (c == SYMBOL_REF || c == CONST || c == LABEL_REF || c == CONST_INT) 980 { 981 fprintf (asm_out_file, "\t.long\t"); 982 output_addr_const (asm_out_file, x); 983 fputc ('\n', asm_out_file); 984 return true; 985 } 986 break; 987 } 988 return default_assemble_integer (x, size, aligned_p); 989 } 990 991 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA 992 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra 993 static bool 994 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED, rtx x) 995 { 996 debug_rtx(x); 997 return false; 998 } 999 1000 #undef TARGET_LEGITIMATE_CONSTANT_P 1001 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant 1002 1003 static bool 1004 msp430_legitimate_constant (machine_mode mode, rtx x) 1005 { 1006 return ! CONST_INT_P (x) 1007 || mode != PSImode 1008 /* GCC does not know the width of the PSImode, so make 1009 sure that it does not try to use a constant value that 1010 is out of range. */ 1011 || (INTVAL (x) < (1 << 20) && INTVAL (x) >= (-1 << 20)); 1012 } 1013 1014 1015 #undef TARGET_RTX_COSTS 1016 #define TARGET_RTX_COSTS msp430_rtx_costs 1017 1018 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED, 1019 int code, 1020 int outer_code ATTRIBUTE_UNUSED, 1021 int opno ATTRIBUTE_UNUSED, 1022 int * total, 1023 bool speed ATTRIBUTE_UNUSED) 1024 { 1025 switch (code) 1026 { 1027 case SIGN_EXTEND: 1028 if (GET_MODE (x) == SImode && outer_code == SET) 1029 { 1030 *total = COSTS_N_INSNS (4); 1031 return true; 1032 } 1033 break; 1034 case ASHIFT: 1035 case ASHIFTRT: 1036 case LSHIFTRT: 1037 if (!msp430x) 1038 { 1039 *total = COSTS_N_INSNS (100); 1040 return true; 1041 } 1042 break; 1043 } 1044 return false; 1045 } 1046 1047 /* Function Entry and Exit */ 1048 1049 /* The MSP430 call frame looks like this: 1050 1051 <higher addresses> 1052 +--------------------+ 1053 | | 1054 | Stack Arguments | 1055 | | 1056 +--------------------+ <-- "arg pointer" 1057 | | 1058 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE) 1059 | | 1060 +--------------------+ 1061 | SR if this func has| 1062 | been called via an | 1063 | interrupt. | 1064 +--------------------+ <-- SP before prologue, also AP 1065 | | 1066 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE) 1067 | | 1068 +--------------------+ <-- "frame pointer" 1069 | | 1070 | Locals | 1071 | | 1072 +--------------------+ 1073 | | 1074 | Outgoing Args | 1075 | | 1076 +--------------------+ <-- SP during function 1077 <lower addresses> 1078 1079 */ 1080 1081 /* We use this to wrap all emitted insns in the prologue, so they get 1082 the "frame-related" (/f) flag set. */ 1083 static rtx 1084 F (rtx x) 1085 { 1086 RTX_FRAME_RELATED_P (x) = 1; 1087 return x; 1088 } 1089 1090 /* This is the one spot that decides if a register is to be saved and 1091 restored in the prologue/epilogue. */ 1092 static bool 1093 msp430_preserve_reg_p (int regno) 1094 { 1095 /* PC, SP, SR, and the constant generator. */ 1096 if (regno <= 3) 1097 return false; 1098 1099 /* FIXME: add interrupt, EH, etc. */ 1100 if (crtl->calls_eh_return) 1101 return true; 1102 1103 /* Shouldn't be more than the above, but just in case... */ 1104 if (fixed_regs [regno]) 1105 return false; 1106 1107 /* Interrupt handlers save all registers they use, even 1108 ones which are call saved. If they call other functions 1109 then *every* register is saved. */ 1110 if (msp430_is_interrupt_func ()) 1111 return ! crtl->is_leaf || df_regs_ever_live_p (regno); 1112 1113 if (!call_used_regs [regno] 1114 && df_regs_ever_live_p (regno)) 1115 return true; 1116 1117 return false; 1118 } 1119 1120 /* Compute all the frame-related fields in our machine_function 1121 structure. */ 1122 static void 1123 msp430_compute_frame_info (void) 1124 { 1125 int i; 1126 1127 cfun->machine->computed = 1; 1128 cfun->machine->framesize_regs = 0; 1129 cfun->machine->framesize_locals = get_frame_size (); 1130 cfun->machine->framesize_outgoing = crtl->outgoing_args_size; 1131 1132 for (i = 0; i < ARG_POINTER_REGNUM; i ++) 1133 if (msp430_preserve_reg_p (i)) 1134 { 1135 cfun->machine->need_to_save [i] = 1; 1136 cfun->machine->framesize_regs += (TARGET_LARGE ? 4 : 2); 1137 } 1138 else 1139 cfun->machine->need_to_save [i] = 0; 1140 1141 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1) 1142 cfun->machine->framesize_locals ++; 1143 1144 cfun->machine->framesize = (cfun->machine->framesize_regs 1145 + cfun->machine->framesize_locals 1146 + cfun->machine->framesize_outgoing); 1147 } 1148 1149 static inline bool 1150 is_attr_func (const char * attr) 1151 { 1152 return lookup_attribute (attr, DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE; 1153 } 1154 1155 /* Returns true if the current function has the "interrupt" attribute. */ 1156 1157 bool 1158 msp430_is_interrupt_func (void) 1159 { 1160 if (current_function_decl == NULL) 1161 return false; 1162 return is_attr_func ("interrupt"); 1163 } 1164 1165 static bool 1166 is_wakeup_func (void) 1167 { 1168 return msp430_is_interrupt_func () && is_attr_func ("wakeup"); 1169 } 1170 1171 static inline bool 1172 is_naked_func (void) 1173 { 1174 return is_attr_func ("naked"); 1175 } 1176 1177 static inline bool 1178 is_reentrant_func (void) 1179 { 1180 return is_attr_func ("reentrant"); 1181 } 1182 1183 static inline bool 1184 is_critical_func (void) 1185 { 1186 return is_attr_func ("critical"); 1187 } 1188 1189 #undef TARGET_ASM_FUNCTION_PROLOGUE 1190 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function 1191 1192 static void 1193 msp430_start_function (FILE *outfile, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED) 1194 { 1195 int r, n; 1196 1197 fprintf (outfile, "; start of function\n"); 1198 1199 if (DECL_ATTRIBUTES (current_function_decl) != NULL_TREE) 1200 { 1201 fprintf (outfile, "; attributes: "); 1202 if (is_naked_func ()) 1203 fprintf (outfile, "naked "); 1204 if (msp430_is_interrupt_func ()) 1205 fprintf (outfile, "interrupt "); 1206 if (is_reentrant_func ()) 1207 fprintf (outfile, "reentrant "); 1208 if (is_critical_func ()) 1209 fprintf (outfile, "critical "); 1210 if (is_wakeup_func ()) 1211 fprintf (outfile, "wakeup "); 1212 fprintf (outfile, "\n"); 1213 } 1214 1215 fprintf (outfile, "; framesize_regs: %d\n", cfun->machine->framesize_regs); 1216 fprintf (outfile, "; framesize_locals: %d\n", cfun->machine->framesize_locals); 1217 fprintf (outfile, "; framesize_outgoing: %d\n", cfun->machine->framesize_outgoing); 1218 fprintf (outfile, "; framesize: %d\n", cfun->machine->framesize); 1219 fprintf (outfile, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM)); 1220 fprintf (outfile, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM)); 1221 1222 n = 0; 1223 fprintf (outfile, "; saved regs:"); 1224 for (r = 0; r < ARG_POINTER_REGNUM; r++) 1225 if (cfun->machine->need_to_save [r]) 1226 { 1227 fprintf (outfile, " %s", reg_names [r]); 1228 n = 1; 1229 } 1230 if (n == 0) 1231 fprintf (outfile, "(none)"); 1232 fprintf (outfile, "\n"); 1233 } 1234 1235 /* Common code to change the stack pointer. */ 1236 static void 1237 increment_stack (HOST_WIDE_INT amount) 1238 { 1239 rtx inc; 1240 rtx sp = stack_pointer_rtx; 1241 1242 if (amount == 0) 1243 return; 1244 1245 if (amount < 0) 1246 { 1247 inc = GEN_INT (- amount); 1248 if (TARGET_LARGE) 1249 F (emit_insn (gen_subpsi3 (sp, sp, inc))); 1250 else 1251 F (emit_insn (gen_subhi3 (sp, sp, inc))); 1252 } 1253 else 1254 { 1255 inc = GEN_INT (amount); 1256 if (TARGET_LARGE) 1257 emit_insn (gen_addpsi3 (sp, sp, inc)); 1258 else 1259 emit_insn (gen_addhi3 (sp, sp, inc)); 1260 } 1261 } 1262 1263 /* Verify MSP430 specific attributes. */ 1264 1265 static tree 1266 msp430_attr (tree * node, 1267 tree name, 1268 tree args, 1269 int flags ATTRIBUTE_UNUSED, 1270 bool * no_add_attrs) 1271 { 1272 gcc_assert (DECL_P (* node)); 1273 1274 if (args != NULL) 1275 { 1276 tree value = TREE_VALUE (args); 1277 1278 switch (TREE_CODE (value)) 1279 { 1280 case STRING_CST: 1281 if ( strcmp (TREE_STRING_POINTER (value), "reset") 1282 && strcmp (TREE_STRING_POINTER (value), "nmi") 1283 && strcmp (TREE_STRING_POINTER (value), "watchdog")) 1284 /* Allow the attribute to be added - the linker script 1285 being used may still recognise this name. */ 1286 warning (OPT_Wattributes, 1287 "unrecognised interrupt vector argument of %qE attribute", 1288 name); 1289 break; 1290 1291 case INTEGER_CST: 1292 if (wi::gtu_p (value, 63)) 1293 /* Allow the attribute to be added - the linker script 1294 being used may still recognise this value. */ 1295 warning (OPT_Wattributes, 1296 "numeric argument of %qE attribute must be in range 0..63", 1297 name); 1298 break; 1299 1300 default: 1301 warning (OPT_Wattributes, 1302 "argument of %qE attribute is not a string constant or number", 1303 name); 1304 *no_add_attrs = true; 1305 break; 1306 } 1307 } 1308 1309 if (TREE_CODE (* node) != FUNCTION_DECL) 1310 { 1311 warning (OPT_Wattributes, 1312 "%qE attribute only applies to functions", 1313 name); 1314 * no_add_attrs = true; 1315 } 1316 1317 /* FIXME: We ought to check that the interrupt handler 1318 attribute has been applied to a void function. */ 1319 /* FIXME: We should check that reentrant and critical 1320 functions are not naked and that critical functions 1321 are not reentrant. */ 1322 1323 return NULL_TREE; 1324 } 1325 1326 #undef TARGET_ATTRIBUTE_TABLE 1327 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table 1328 1329 /* Table of MSP430-specific attributes. */ 1330 const struct attribute_spec msp430_attribute_table[] = 1331 { 1332 /* Name min_len decl_req, fn_type_req, affects_type_identity 1333 max_len, type_req, handler. */ 1334 { "interrupt", 0, 1, true, false, false, msp430_attr, false }, 1335 { "naked", 0, 0, true, false, false, msp430_attr, false }, 1336 { "reentrant", 0, 0, true, false, false, msp430_attr, false }, 1337 { "critical", 0, 0, true, false, false, msp430_attr, false }, 1338 { "wakeup", 0, 0, true, false, false, msp430_attr, false }, 1339 { NULL, 0, 0, false, false, false, NULL, false } 1340 }; 1341 1342 void 1343 msp430_start_function (FILE *file, const char *name, tree decl) 1344 { 1345 tree int_attr; 1346 1347 int_attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl)); 1348 if (int_attr != NULL_TREE) 1349 { 1350 tree intr_vector = TREE_VALUE (int_attr); 1351 1352 if (intr_vector != NULL_TREE) 1353 { 1354 char buf[101]; 1355 1356 intr_vector = TREE_VALUE (intr_vector); 1357 1358 /* The interrupt attribute has a vector value. Turn this into a 1359 section name, switch to that section and put the address of 1360 the current function into that vector slot. Note msp430_attr() 1361 has already verified the vector name for us. */ 1362 if (TREE_CODE (intr_vector) == STRING_CST) 1363 sprintf (buf, "__interrupt_vector_%.80s", 1364 TREE_STRING_POINTER (intr_vector)); 1365 else /* TREE_CODE (intr_vector) == INTEGER_CST */ 1366 sprintf (buf, "__interrupt_vector_%u", 1367 (unsigned int) TREE_INT_CST_LOW (intr_vector)); 1368 1369 switch_to_section (get_section (buf, SECTION_CODE, decl)); 1370 fputs ("\t.word\t", file); 1371 assemble_name (file, name); 1372 fputc ('\n', file); 1373 fputc ('\t', file); 1374 } 1375 } 1376 1377 switch_to_section (function_section (decl)); 1378 ASM_OUTPUT_FUNCTION_LABEL (file, name, decl); 1379 } 1380 1381 static section * 1382 msp430_function_section (tree decl, enum node_frequency freq, bool startup, bool exit) 1383 { 1384 /* In large mode we must make sure that interrupt handlers are put into 1385 low memory as the vector table only accepts 16-bit addresses. */ 1386 if (TARGET_LARGE 1387 && lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl))) 1388 return get_section (".lowtext", SECTION_CODE | SECTION_WRITE , decl); 1389 1390 /* Otherwise, use the default function section. */ 1391 return default_function_section (decl, freq, startup, exit); 1392 } 1393 1394 #undef TARGET_ASM_FUNCTION_SECTION 1395 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section 1396 1397 enum msp430_builtin 1398 { 1399 MSP430_BUILTIN_BIC_SR, 1400 MSP430_BUILTIN_BIS_SR, 1401 MSP430_BUILTIN_DELAY_CYCLES, 1402 MSP430_BUILTIN_max 1403 }; 1404 1405 static GTY(()) tree msp430_builtins [(int) MSP430_BUILTIN_max]; 1406 1407 static void 1408 msp430_init_builtins (void) 1409 { 1410 tree void_ftype_int = build_function_type_list (void_type_node, integer_type_node, NULL); 1411 tree void_ftype_longlong = build_function_type_list (void_type_node, long_long_integer_type_node, NULL); 1412 1413 msp430_builtins[MSP430_BUILTIN_BIC_SR] = 1414 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int, 1415 MSP430_BUILTIN_BIC_SR, BUILT_IN_MD, NULL, NULL_TREE); 1416 1417 msp430_builtins[MSP430_BUILTIN_BIS_SR] = 1418 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int, 1419 MSP430_BUILTIN_BIS_SR, BUILT_IN_MD, NULL, NULL_TREE); 1420 1421 msp430_builtins[MSP430_BUILTIN_DELAY_CYCLES] = 1422 add_builtin_function ( "__delay_cycles", void_ftype_longlong, 1423 MSP430_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL, NULL_TREE); 1424 } 1425 1426 static tree 1427 msp430_builtin_decl (unsigned code, bool initialize ATTRIBUTE_UNUSED) 1428 { 1429 switch (code) 1430 { 1431 case MSP430_BUILTIN_BIC_SR: 1432 case MSP430_BUILTIN_BIS_SR: 1433 case MSP430_BUILTIN_DELAY_CYCLES: 1434 return msp430_builtins[code]; 1435 default: 1436 return error_mark_node; 1437 } 1438 } 1439 1440 /* These constants are really register reads, which are faster than 1441 regular constants. */ 1442 static int 1443 cg_magic_constant (HOST_WIDE_INT c) 1444 { 1445 switch (c) 1446 { 1447 case 0xffff: 1448 case -1: 1449 case 0: 1450 case 1: 1451 case 2: 1452 case 4: 1453 case 8: 1454 return 1; 1455 default: 1456 return 0; 1457 } 1458 } 1459 1460 static rtx 1461 msp430_expand_delay_cycles (rtx arg) 1462 { 1463 HOST_WIDE_INT i, c, n; 1464 /* extra cycles for MSP430X instructions */ 1465 #define CYCX(M,X) (msp430x ? (X) : (M)) 1466 1467 if (GET_CODE (arg) != CONST_INT) 1468 { 1469 error ("__delay_cycles() only takes constant arguments"); 1470 return NULL_RTX; 1471 } 1472 1473 c = INTVAL (arg); 1474 1475 if (HOST_BITS_PER_WIDE_INT > 32) 1476 { 1477 if (c < 0) 1478 { 1479 error ("__delay_cycles only takes non-negative cycle counts."); 1480 return NULL_RTX; 1481 } 1482 } 1483 1484 emit_insn (gen_delay_cycles_start (arg)); 1485 1486 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */ 1487 if (c > 3 * 0xffff + CYCX (7, 10)) 1488 { 1489 n = c; 1490 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */ 1491 if (c >= 0x10000 * 7 + CYCX (14, 16)) 1492 { 1493 i = 0x10000; 1494 c -= CYCX (14, 16) + 7 * 0x10000; 1495 i += c / 4; 1496 c %= 4; 1497 if ((unsigned long long) i > 0xffffffffULL) 1498 { 1499 error ("__delay_cycles is limited to 32-bit loop counts."); 1500 return NULL_RTX; 1501 } 1502 } 1503 else 1504 { 1505 i = (c - CYCX (14, 16)) / 7; 1506 c -= CYCX (14, 16) + i * 7; 1507 } 1508 1509 if (cg_magic_constant (i & 0xffff)) 1510 c ++; 1511 if (cg_magic_constant ((i >> 16) & 0xffff)) 1512 c ++; 1513 1514 if (msp430x) 1515 emit_insn (gen_delay_cycles_32x (GEN_INT (i), GEN_INT (n - c))); 1516 else 1517 emit_insn (gen_delay_cycles_32 (GEN_INT (i), GEN_INT (n - c))); 1518 } 1519 1520 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */ 1521 if (c > 12) 1522 { 1523 n = c; 1524 i = (c - CYCX (7, 10)) / 3; 1525 c -= CYCX (7, 10) + i * 3; 1526 1527 if (cg_magic_constant (i)) 1528 c ++; 1529 1530 if (msp430x) 1531 emit_insn (gen_delay_cycles_16x (GEN_INT (i), GEN_INT (n - c))); 1532 else 1533 emit_insn (gen_delay_cycles_16 (GEN_INT (i), GEN_INT (n - c))); 1534 } 1535 1536 while (c > 1) 1537 { 1538 emit_insn (gen_delay_cycles_2 ()); 1539 c -= 2; 1540 } 1541 1542 if (c) 1543 { 1544 emit_insn (gen_delay_cycles_1 ()); 1545 c -= 1; 1546 } 1547 1548 emit_insn (gen_delay_cycles_end (arg)); 1549 1550 return NULL_RTX; 1551 } 1552 1553 static rtx 1554 msp430_expand_builtin (tree exp, 1555 rtx target ATTRIBUTE_UNUSED, 1556 rtx subtarget ATTRIBUTE_UNUSED, 1557 machine_mode mode ATTRIBUTE_UNUSED, 1558 int ignore ATTRIBUTE_UNUSED) 1559 { 1560 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); 1561 unsigned int fcode = DECL_FUNCTION_CODE (fndecl); 1562 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0)); 1563 1564 if (fcode == MSP430_BUILTIN_DELAY_CYCLES) 1565 return msp430_expand_delay_cycles (arg1); 1566 1567 if (! msp430_is_interrupt_func ()) 1568 { 1569 error ("MSP430 builtin functions only work inside interrupt handlers"); 1570 return NULL_RTX; 1571 } 1572 1573 if (! REG_P (arg1) && ! CONSTANT_P (arg1)) 1574 arg1 = force_reg (mode, arg1); 1575 1576 switch (fcode) 1577 { 1578 case MSP430_BUILTIN_BIC_SR: emit_insn (gen_bic_SR (arg1)); break; 1579 case MSP430_BUILTIN_BIS_SR: emit_insn (gen_bis_SR (arg1)); break; 1580 default: 1581 internal_error ("bad builtin code"); 1582 break; 1583 } 1584 return NULL_RTX; 1585 } 1586 1587 #undef TARGET_INIT_BUILTINS 1588 #define TARGET_INIT_BUILTINS msp430_init_builtins 1589 1590 #undef TARGET_EXPAND_BUILTIN 1591 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin 1592 1593 #undef TARGET_BUILTIN_DECL 1594 #define TARGET_BUILTIN_DECL msp430_builtin_decl 1595 1596 void 1597 msp430_expand_prologue (void) 1598 { 1599 int i, j; 1600 int fs; 1601 /* Always use stack_pointer_rtx instead of calling 1602 rtx_gen_REG ourselves. Code elsewhere in GCC assumes 1603 that there is a single rtx representing the stack pointer, 1604 namely stack_pointer_rtx, and uses == to recognize it. */ 1605 rtx sp = stack_pointer_rtx; 1606 rtx p; 1607 1608 if (is_naked_func ()) 1609 { 1610 /* We must generate some RTX as thread_prologue_and_epilogue_insns() 1611 examines the output of the gen_prologue() function. */ 1612 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0))); 1613 return; 1614 } 1615 1616 emit_insn (gen_prologue_start_marker ()); 1617 1618 if (is_critical_func ()) 1619 { 1620 emit_insn (gen_push_intr_state ()); 1621 emit_insn (gen_disable_interrupts ()); 1622 } 1623 else if (is_reentrant_func ()) 1624 emit_insn (gen_disable_interrupts ()); 1625 1626 if (!cfun->machine->computed) 1627 msp430_compute_frame_info (); 1628 1629 if (flag_stack_usage_info) 1630 current_function_static_stack_size = cfun->machine->framesize; 1631 1632 if (crtl->args.pretend_args_size) 1633 { 1634 rtx note; 1635 1636 gcc_assert (crtl->args.pretend_args_size == 2); 1637 1638 p = emit_insn (gen_grow_and_swap ()); 1639 1640 /* Document the stack decrement... */ 1641 note = F (gen_rtx_SET (Pmode, stack_pointer_rtx, 1642 gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (2)))); 1643 add_reg_note (p, REG_FRAME_RELATED_EXPR, note); 1644 1645 /* ...and the establishment of a new location for the return address. */ 1646 note = F (gen_rtx_SET (Pmode, gen_rtx_MEM (Pmode, 1647 gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-2))), 1648 pc_rtx)); 1649 add_reg_note (p, REG_CFA_OFFSET, note); 1650 F (p); 1651 } 1652 1653 for (i = 15; i >= 4; i--) 1654 if (cfun->machine->need_to_save [i]) 1655 { 1656 int seq, count; 1657 rtx note; 1658 1659 for (seq = i - 1; seq >= 4 && cfun->machine->need_to_save[seq]; seq --) 1660 ; 1661 count = i - seq; 1662 1663 if (msp430x) 1664 { 1665 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */ 1666 p = F (emit_insn (gen_pushm (gen_rtx_REG (Pmode, i), 1667 GEN_INT (count)))); 1668 1669 note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1)); 1670 1671 XVECEXP (note, 0, 0) 1672 = F (gen_rtx_SET (VOIDmode, 1673 stack_pointer_rtx, 1674 gen_rtx_PLUS (Pmode, 1675 stack_pointer_rtx, 1676 GEN_INT (count * (TARGET_LARGE ? -4 : -2))))); 1677 1678 /* *sp-- = R[i-j] */ 1679 /* sp+N R10 1680 ... 1681 sp R4 */ 1682 for (j = 0; j < count; j ++) 1683 { 1684 rtx addr; 1685 int ofs = (count - j - 1) * (TARGET_LARGE ? 4 : 2); 1686 1687 if (ofs) 1688 addr = gen_rtx_PLUS (Pmode, sp, GEN_INT (ofs)); 1689 else 1690 addr = stack_pointer_rtx; 1691 1692 XVECEXP (note, 0, j + 1) = 1693 F (gen_rtx_SET (VOIDmode, 1694 gen_rtx_MEM (Pmode, addr), 1695 gen_rtx_REG (Pmode, i - j)) ); 1696 } 1697 1698 add_reg_note (p, REG_FRAME_RELATED_EXPR, note); 1699 i -= count - 1; 1700 } 1701 else 1702 F (emit_insn (gen_push (gen_rtx_REG (Pmode, i)))); 1703 } 1704 1705 if (frame_pointer_needed) 1706 F (emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM), sp)); 1707 1708 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing; 1709 1710 increment_stack (- fs); 1711 1712 emit_insn (gen_prologue_end_marker ()); 1713 } 1714 1715 void 1716 msp430_expand_epilogue (int is_eh) 1717 { 1718 int i; 1719 int fs; 1720 int helper_n = 0; 1721 1722 if (is_naked_func ()) 1723 { 1724 /* We must generate some RTX as thread_prologue_and_epilogue_insns() 1725 examines the output of the gen_epilogue() function. */ 1726 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0))); 1727 return; 1728 } 1729 1730 if (cfun->machine->need_to_save [10]) 1731 { 1732 /* Check for a helper function. */ 1733 helper_n = 7; /* For when the loop below never sees a match. */ 1734 for (i = 9; i >= 4; i--) 1735 if (!cfun->machine->need_to_save [i]) 1736 { 1737 helper_n = 10 - i; 1738 for (; i >= 4; i--) 1739 if (cfun->machine->need_to_save [i]) 1740 { 1741 helper_n = 0; 1742 break; 1743 } 1744 break; 1745 } 1746 } 1747 1748 emit_insn (gen_epilogue_start_marker ()); 1749 1750 if (cfun->decl && strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun->decl)), "main") == 0) 1751 emit_insn (gen_msp430_refsym_need_exit ()); 1752 1753 if (is_wakeup_func ()) 1754 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the 1755 status register current residing on the stack. When this function 1756 executes its RETI instruction the SR will be updated with this saved 1757 value, thus ensuring that the processor is woken up from any low power 1758 state in which it may be residing. */ 1759 emit_insn (gen_bic_SR (GEN_INT (0xf0))); 1760 1761 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing; 1762 1763 increment_stack (fs); 1764 1765 if (is_eh) 1766 { 1767 /* We need to add the right "SP" register save just after the 1768 regular ones, so that when we pop it off we're in the EH 1769 return frame, not this one. This overwrites our own return 1770 address, but we're not going to be returning anyway. */ 1771 rtx r12 = gen_rtx_REG (Pmode, 12); 1772 rtx (*addPmode)(rtx, rtx, rtx) = TARGET_LARGE ? gen_addpsi3 : gen_addhi3; 1773 1774 /* R12 will hold the new SP. */ 1775 i = cfun->machine->framesize_regs; 1776 emit_move_insn (r12, stack_pointer_rtx); 1777 emit_insn (addPmode (r12, r12, EH_RETURN_STACKADJ_RTX)); 1778 emit_insn (addPmode (r12, r12, GEN_INT (i))); 1779 emit_move_insn (gen_rtx_MEM (Pmode, plus_constant (Pmode, stack_pointer_rtx, i)), r12); 1780 } 1781 1782 for (i = 4; i <= 15; i++) 1783 if (cfun->machine->need_to_save [i]) 1784 { 1785 int seq, count; 1786 1787 for (seq = i + 1; seq <= 15 && cfun->machine->need_to_save[seq]; seq ++) 1788 ; 1789 count = seq - i; 1790 1791 if (msp430x) 1792 { 1793 /* Note: With TARGET_LARGE we still use 1794 POPM as POPX.A is two bytes bigger. */ 1795 emit_insn (gen_popm (stack_pointer_rtx, GEN_INT (seq - 1), 1796 GEN_INT (count))); 1797 i += count - 1; 1798 } 1799 else if (i == 11 - helper_n 1800 && ! msp430_is_interrupt_func () 1801 && ! is_reentrant_func () 1802 && ! is_critical_func () 1803 && crtl->args.pretend_args_size == 0 1804 /* Calling the helper takes as many bytes as the POP;RET sequence. */ 1805 && helper_n > 1 1806 && !is_eh) 1807 { 1808 emit_insn (gen_epilogue_helper (GEN_INT (helper_n))); 1809 return; 1810 } 1811 else 1812 emit_insn (gen_pop (gen_rtx_REG (Pmode, i))); 1813 } 1814 1815 if (is_eh) 1816 { 1817 /* Also pop SP, which puts us into the EH return frame. Except 1818 that you can't "pop" sp, you have to just load it off the 1819 stack. */ 1820 emit_move_insn (stack_pointer_rtx, gen_rtx_MEM (Pmode, stack_pointer_rtx)); 1821 } 1822 1823 if (crtl->args.pretend_args_size) 1824 emit_insn (gen_swap_and_shrink ()); 1825 1826 if (is_critical_func ()) 1827 emit_insn (gen_pop_intr_state ()); 1828 else if (is_reentrant_func ()) 1829 emit_insn (gen_enable_interrupts ()); 1830 1831 emit_jump_insn (gen_msp_return ()); 1832 } 1833 1834 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in 1835 m32c_emit_eh_epilogue. */ 1836 rtx 1837 msp430_eh_return_stackadj_rtx (void) 1838 { 1839 if (!cfun->machine->eh_stack_adjust) 1840 { 1841 rtx sa; 1842 1843 sa = gen_rtx_REG (Pmode, 15); 1844 cfun->machine->eh_stack_adjust = sa; 1845 } 1846 return cfun->machine->eh_stack_adjust; 1847 } 1848 1849 /* This function is called before reload, to "fix" the stack in 1850 preparation for an EH return. */ 1851 void 1852 msp430_expand_eh_return (rtx eh_handler) 1853 { 1854 /* These are all Pmode */ 1855 rtx ap, sa, ra, tmp; 1856 1857 ap = arg_pointer_rtx; 1858 sa = msp430_eh_return_stackadj_rtx (); 1859 ra = eh_handler; 1860 1861 tmp = ap; 1862 tmp = gen_rtx_PLUS (Pmode, ap, sa); 1863 tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2); 1864 tmp = gen_rtx_MEM (Pmode, tmp); 1865 emit_move_insn (tmp, ra); 1866 } 1867 1868 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA 1869 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra 1870 void 1871 msp430_init_dwarf_reg_sizes_extra (tree address) 1872 { 1873 int i; 1874 rtx addr = expand_normal (address); 1875 rtx mem = gen_rtx_MEM (BLKmode, addr); 1876 1877 if (!msp430x) 1878 return; 1879 1880 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 1881 { 1882 unsigned int dnum = DWARF_FRAME_REGNUM (i); 1883 unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1); 1884 1885 if (rnum < DWARF_FRAME_REGISTERS) 1886 { 1887 HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (QImode); 1888 1889 emit_move_insn (adjust_address (mem, QImode, offset), 1890 gen_int_mode (4, QImode)); 1891 } 1892 } 1893 } 1894 1895 /* This is a list of MD patterns that implement fixed-count shifts. */ 1896 static struct 1897 { 1898 const char *name; 1899 int count; 1900 int need_430x; 1901 rtx (*genfunc)(rtx,rtx); 1902 } 1903 const_shift_helpers[] = 1904 { 1905 #define CSH(N,C,X,G) { "__mspabi_"N, C, X, gen_##G } 1906 1907 CSH ("slli", 1, 1, slli_1), 1908 CSH ("slll", 1, 1, slll_1), 1909 CSH ("slll", 2, 1, slll_2), 1910 1911 CSH ("srai", 1, 0, srai_1), 1912 CSH ("sral", 1, 0, sral_1), 1913 CSH ("sral", 2, 0, sral_2), 1914 1915 CSH ("srll", 1, 0, srll_1), 1916 CSH ("srll", 2, 1, srll_2x), 1917 { 0, 0, 0, 0 } 1918 #undef CSH 1919 }; 1920 1921 /* The MSP430 ABI defines a number of helper functions that should be 1922 used for, for example, 32-bit shifts. This function is called to 1923 emit such a function, using the table above to optimize some 1924 cases. */ 1925 void 1926 msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variants) 1927 { 1928 rtx c, f; 1929 char *helper_const = NULL; 1930 int arg2 = 13; 1931 int arg1sz = 1; 1932 machine_mode arg0mode = GET_MODE (operands[0]); 1933 machine_mode arg1mode = GET_MODE (operands[1]); 1934 machine_mode arg2mode = GET_MODE (operands[2]); 1935 int have_430x = msp430x ? 1 : 0; 1936 1937 if (CONST_INT_P (operands[2])) 1938 { 1939 int i; 1940 1941 for (i=0; const_shift_helpers[i].name; i++) 1942 { 1943 if (const_shift_helpers[i].need_430x <= have_430x 1944 && strcmp (helper_name, const_shift_helpers[i].name) == 0 1945 && INTVAL (operands[2]) == const_shift_helpers[i].count) 1946 { 1947 emit_insn (const_shift_helpers[i].genfunc (operands[0], operands[1])); 1948 return; 1949 } 1950 } 1951 } 1952 1953 if (arg1mode == VOIDmode) 1954 arg1mode = arg0mode; 1955 if (arg2mode == VOIDmode) 1956 arg2mode = arg0mode; 1957 1958 if (arg1mode == SImode) 1959 { 1960 arg2 = 14; 1961 arg1sz = 2; 1962 } 1963 1964 if (const_variants 1965 && CONST_INT_P (operands[2]) 1966 && INTVAL (operands[2]) >= 1 1967 && INTVAL (operands[2]) <= 15) 1968 { 1969 /* Note that the INTVAL is limited in value and length by the conditional above. */ 1970 int len = strlen (helper_name) + 4; 1971 helper_const = (char *) xmalloc (len); 1972 snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2])); 1973 } 1974 1975 emit_move_insn (gen_rtx_REG (arg1mode, 12), 1976 operands[1]); 1977 if (!helper_const) 1978 emit_move_insn (gen_rtx_REG (arg2mode, arg2), 1979 operands[2]); 1980 1981 c = gen_call_value_internal (gen_rtx_REG (arg0mode, 12), 1982 gen_rtx_SYMBOL_REF (VOIDmode, helper_const ? helper_const : helper_name), 1983 GEN_INT (0)); 1984 c = emit_call_insn (c); 1985 RTL_CONST_CALL_P (c) = 1; 1986 1987 f = 0; 1988 use_regs (&f, 12, arg1sz); 1989 if (!helper_const) 1990 use_regs (&f, arg2, 1); 1991 add_function_usage_to (c, f); 1992 1993 emit_move_insn (operands[0], 1994 gen_rtx_REG (arg0mode, 12)); 1995 } 1996 1997 /* Called by cbranch<mode>4 to coerce operands into usable forms. */ 1998 void 1999 msp430_fixup_compare_operands (machine_mode my_mode, rtx * operands) 2000 { 2001 /* constants we're looking for, not constants which are allowed. */ 2002 int const_op_idx = 1; 2003 2004 if (msp430_reversible_cmp_operator (operands[0], VOIDmode)) 2005 const_op_idx = 2; 2006 2007 if (GET_CODE (operands[const_op_idx]) != REG 2008 && GET_CODE (operands[const_op_idx]) != MEM) 2009 operands[const_op_idx] = copy_to_mode_reg (my_mode, operands[const_op_idx]); 2010 } 2011 2012 /* Simplify_gen_subreg() doesn't handle memory references the way we 2013 need it to below, so we use this function for when we must get a 2014 valid subreg in a "natural" state. */ 2015 rtx 2016 msp430_subreg (machine_mode mode, rtx r, machine_mode omode, int byte) 2017 { 2018 rtx rv; 2019 2020 if (GET_CODE (r) == SUBREG 2021 && SUBREG_BYTE (r) == 0) 2022 { 2023 rtx ireg = SUBREG_REG (r); 2024 machine_mode imode = GET_MODE (ireg); 2025 2026 /* special case for (HI (SI (PSI ...), 0)) */ 2027 if (imode == PSImode 2028 && mode == HImode 2029 && byte == 0) 2030 rv = gen_rtx_SUBREG (mode, ireg, byte); 2031 else 2032 rv = simplify_gen_subreg (mode, ireg, imode, byte); 2033 } 2034 else if (GET_CODE (r) == MEM) 2035 rv = adjust_address (r, mode, byte); 2036 else 2037 rv = simplify_gen_subreg (mode, r, omode, byte); 2038 2039 if (!rv) 2040 gcc_unreachable (); 2041 2042 return rv; 2043 } 2044 2045 /* Called by movsi_x to generate the HImode operands. */ 2046 void 2047 msp430_split_movsi (rtx *operands) 2048 { 2049 rtx op00, op02, op10, op12; 2050 2051 op00 = msp430_subreg (HImode, operands[0], SImode, 0); 2052 op02 = msp430_subreg (HImode, operands[0], SImode, 2); 2053 2054 if (GET_CODE (operands[1]) == CONST 2055 || GET_CODE (operands[1]) == SYMBOL_REF) 2056 { 2057 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0)); 2058 op10 = gen_rtx_CONST (HImode, op10); 2059 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16)); 2060 op12 = gen_rtx_CONST (HImode, op12); 2061 } 2062 else 2063 { 2064 op10 = msp430_subreg (HImode, operands[1], SImode, 0); 2065 op12 = msp430_subreg (HImode, operands[1], SImode, 2); 2066 } 2067 2068 if (rtx_equal_p (operands[0], operands[1])) 2069 { 2070 operands[2] = op02; 2071 operands[4] = op12; 2072 operands[3] = op00; 2073 operands[5] = op10; 2074 } 2075 else if (rtx_equal_p (op00, op12) 2076 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */ 2077 || (REG_P (op00) && reg_mentioned_p (op00, op10)) 2078 /* Or storing (rN) into mem (rN). */ 2079 || (REG_P (op10) && reg_mentioned_p (op10, op00)) 2080 ) 2081 { 2082 operands[2] = op02; 2083 operands[4] = op12; 2084 operands[3] = op00; 2085 operands[5] = op10; 2086 } 2087 else 2088 { 2089 operands[2] = op00; 2090 operands[4] = op10; 2091 operands[3] = op02; 2092 operands[5] = op12; 2093 } 2094 } 2095 2096 2097 /* The MSPABI specifies the names of various helper functions, many of 2098 which are compatible with GCC's helpers. This table maps the GCC 2099 name to the MSPABI name. */ 2100 static const struct 2101 { 2102 char const * const gcc_name; 2103 char const * const ti_name; 2104 } 2105 helper_function_name_mappings [] = 2106 { 2107 /* Floating point to/from integer conversions. */ 2108 { "__truncdfsf2", "__mspabi_cvtdf" }, 2109 { "__extendsfdf2", "__mspabi_cvtfd" }, 2110 { "__fixdfhi", "__mspabi_fixdi" }, 2111 { "__fixdfsi", "__mspabi_fixdli" }, 2112 { "__fixdfdi", "__mspabi_fixdlli" }, 2113 { "__fixunsdfhi", "__mspabi_fixdu" }, 2114 { "__fixunsdfsi", "__mspabi_fixdul" }, 2115 { "__fixunsdfdi", "__mspabi_fixdull" }, 2116 { "__fixsfhi", "__mspabi_fixfi" }, 2117 { "__fixsfsi", "__mspabi_fixfli" }, 2118 { "__fixsfdi", "__mspabi_fixflli" }, 2119 { "__fixunsfhi", "__mspabi_fixfu" }, 2120 { "__fixunsfsi", "__mspabi_fixful" }, 2121 { "__fixunsfdi", "__mspabi_fixfull" }, 2122 { "__floathisf", "__mspabi_fltif" }, 2123 { "__floatsisf", "__mspabi_fltlif" }, 2124 { "__floatdisf", "__mspabi_fltllif" }, 2125 { "__floathidf", "__mspabi_fltid" }, 2126 { "__floatsidf", "__mspabi_fltlid" }, 2127 { "__floatdidf", "__mspabi_fltllid" }, 2128 { "__floatunhisf", "__mspabi_fltuf" }, 2129 { "__floatunsisf", "__mspabi_fltulf" }, 2130 { "__floatundisf", "__mspabi_fltullf" }, 2131 { "__floatunhidf", "__mspabi_fltud" }, 2132 { "__floatunsidf", "__mspabi_fltuld" }, 2133 { "__floatundidf", "__mspabi_fltulld" }, 2134 2135 /* Floating point comparisons. */ 2136 /* GCC uses individual functions for each comparison, TI uses one 2137 compare <=> function. */ 2138 2139 /* Floating point arithmatic */ 2140 { "__adddf3", "__mspabi_addd" }, 2141 { "__addsf3", "__mspabi_addf" }, 2142 { "__divdf3", "__mspabi_divd" }, 2143 { "__divsf3", "__mspabi_divf" }, 2144 { "__muldf3", "__mspabi_mpyd" }, 2145 { "__mulsf3", "__mspabi_mpyf" }, 2146 { "__subdf3", "__mspabi_subd" }, 2147 { "__subsf3", "__mspabi_subf" }, 2148 /* GCC does not use helper functions for negation */ 2149 2150 /* Integer multiply, divide, remainder. */ 2151 { "__mulhi3", "__mspabi_mpyi" }, 2152 { "__mulsi3", "__mspabi_mpyl" }, 2153 { "__muldi3", "__mspabi_mpyll" }, 2154 #if 0 2155 /* Clarify signed vs unsigned first. */ 2156 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */ 2157 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */ 2158 #endif 2159 2160 { "__divhi3", "__mspabi_divi" }, 2161 { "__divsi3", "__mspabi_divli" }, 2162 { "__divdi3", "__mspabi_divlli" }, 2163 { "__udivhi3", "__mspabi_divu" }, 2164 { "__udivsi3", "__mspabi_divlu" }, 2165 { "__udivdi3", "__mspabi_divllu" }, 2166 { "__modhi3", "__mspabi_remi" }, 2167 { "__modsi3", "__mspabi_remli" }, 2168 { "__moddi3", "__mspabi_remlli" }, 2169 { "__umodhi3", "__mspabi_remu" }, 2170 { "__umodsi3", "__mspabi_remul" }, 2171 { "__umoddi3", "__mspabi_remull" }, 2172 2173 /* Bitwise operations. */ 2174 /* Rotation - no rotation support yet. */ 2175 /* Logical left shift - gcc already does these itself. */ 2176 /* Arithmetic left shift - gcc already does these itself. */ 2177 /* Arithmetic right shift - gcc already does these itself. */ 2178 2179 { NULL, NULL } 2180 }; 2181 2182 /* Returns true if the current MCU supports an F5xxx series 2183 hardware multiper. */ 2184 2185 bool 2186 msp430_use_f5_series_hwmult (void) 2187 { 2188 static const char * cached_match = NULL; 2189 static bool cached_result; 2190 2191 if (msp430_hwmult_type == F5SERIES) 2192 return true; 2193 2194 if (target_mcu == NULL || msp430_hwmult_type != AUTO) 2195 return false; 2196 2197 if (target_mcu == cached_match) 2198 return cached_result; 2199 2200 cached_match = target_mcu; 2201 2202 if (strncasecmp (target_mcu, "msp430f5", 8) == 0) 2203 return cached_result = true; 2204 if (strncasecmp (target_mcu, "msp430fr5", 9) == 0) 2205 return cached_result = true; 2206 if (strncasecmp (target_mcu, "msp430f6", 8) == 0) 2207 return cached_result = true; 2208 2209 static const char * known_f5_mult_mcus [] = 2210 { 2211 "cc430f5123", "cc430f5125", "cc430f5133", 2212 "cc430f5135", "cc430f5137", "cc430f5143", 2213 "cc430f5145", "cc430f5147", "cc430f6125", 2214 "cc430f6126", "cc430f6127", "cc430f6135", 2215 "cc430f6137", "cc430f6143", "cc430f6145", 2216 "cc430f6147", "msp430bt5190", "msp430sl5438a", 2217 "msp430xgeneric" 2218 }; 2219 int i; 2220 2221 for (i = ARRAY_SIZE (known_f5_mult_mcus); i--;) 2222 if (strcasecmp (target_mcu, known_f5_mult_mcus[i]) == 0) 2223 return cached_result = true; 2224 2225 return cached_result = false; 2226 } 2227 2228 /* Returns true if the current MCU has a second generation 2229 32-bit hardware multiplier. */ 2230 2231 static bool 2232 use_32bit_hwmult (void) 2233 { 2234 static const char * known_32bit_mult_mcus [] = 2235 { 2236 "msp430f4783", "msp430f4793", "msp430f4784", 2237 "msp430f4794", "msp430f47126", "msp430f47127", 2238 "msp430f47163", "msp430f47173", "msp430f47183", 2239 "msp430f47193", "msp430f47166", "msp430f47176", 2240 "msp430f47186", "msp430f47196", "msp430f47167", 2241 "msp430f47177", "msp430f47187", "msp430f47197" 2242 }; 2243 static const char * cached_match = NULL; 2244 static bool cached_result; 2245 int i; 2246 2247 if (msp430_hwmult_type == LARGE) 2248 return true; 2249 2250 if (target_mcu == NULL || msp430_hwmult_type != AUTO) 2251 return false; 2252 2253 if (target_mcu == cached_match) 2254 return cached_result; 2255 2256 cached_match = target_mcu; 2257 for (i = ARRAY_SIZE (known_32bit_mult_mcus); i--;) 2258 if (strcasecmp (target_mcu, known_32bit_mult_mcus[i]) == 0) 2259 return cached_result = true; 2260 2261 return cached_result = false; 2262 } 2263 2264 /* Returns true if the current MCU does not have a 2265 hardware multiplier of any kind. */ 2266 2267 static bool 2268 msp430_no_hwmult (void) 2269 { 2270 static const char * known_nomult_mcus [] = 2271 { 2272 "msp430c091", "msp430c092", "msp430c111", 2273 "msp430c1111", "msp430c112", "msp430c1121", 2274 "msp430c1331", "msp430c1351", "msp430c311s", 2275 "msp430c312", "msp430c313", "msp430c314", 2276 "msp430c315", "msp430c323", "msp430c325", 2277 "msp430c412", "msp430c413", "msp430e112", 2278 "msp430e313", "msp430e315", "msp430e325", 2279 "msp430f110", "msp430f1101", "msp430f1101a", 2280 "msp430f1111", "msp430f1111a", "msp430f112", 2281 "msp430f1121", "msp430f1121a", "msp430f1122", 2282 "msp430f1132", "msp430f122", "msp430f1222", 2283 "msp430f123", "msp430f1232", "msp430f133", 2284 "msp430f135", "msp430f155", "msp430f156", 2285 "msp430f157", "msp430f2001", "msp430f2002", 2286 "msp430f2003", "msp430f2011", "msp430f2012", 2287 "msp430f2013", "msp430f2101", "msp430f2111", 2288 "msp430f2112", "msp430f2121", "msp430f2122", 2289 "msp430f2131", "msp430f2132", "msp430f2232", 2290 "msp430f2234", "msp430f2252", "msp430f2254", 2291 "msp430f2272", "msp430f2274", "msp430f412", 2292 "msp430f413", "msp430f4132", "msp430f415", 2293 "msp430f4152", "msp430f417", "msp430f4250", 2294 "msp430f4260", "msp430f4270", "msp430f435", 2295 "msp430f4351", "msp430f436", "msp430f4361", 2296 "msp430f437", "msp430f4371", "msp430f438", 2297 "msp430f439", "msp430f477", "msp430f478", 2298 "msp430f479", "msp430fe423", "msp430fe4232", 2299 "msp430fe423a", "msp430fe4242", "msp430fe425", 2300 "msp430fe4252", "msp430fe425a", "msp430fe427", 2301 "msp430fe4272", "msp430fe427a", "msp430fg4250", 2302 "msp430fg4260", "msp430fg4270", "msp430fg437", 2303 "msp430fg438", "msp430fg439", "msp430fg477", 2304 "msp430fg478", "msp430fg479", "msp430fr2032", 2305 "msp430fr2033", "msp430fr4131", "msp430fr4132", 2306 "msp430fr4133", "msp430fw423", "msp430fw425", 2307 "msp430fw427", "msp430fw428", "msp430fw429", 2308 "msp430g2001", "msp430g2101", "msp430g2102", 2309 "msp430g2111", "msp430g2112", "msp430g2113", 2310 "msp430g2121", "msp430g2131", "msp430g2132", 2311 "msp430g2152", "msp430g2153", "msp430g2201", 2312 "msp430g2202", "msp430g2203", "msp430g2210", 2313 "msp430g2211", "msp430g2212", "msp430g2213", 2314 "msp430g2221", "msp430g2230", "msp430g2231", 2315 "msp430g2232", "msp430g2233", "msp430g2252", 2316 "msp430g2253", "msp430g2302", "msp430g2303", 2317 "msp430g2312", "msp430g2313", "msp430g2332", 2318 "msp430g2333", "msp430g2352", "msp430g2353", 2319 "msp430g2402", "msp430g2403", "msp430g2412", 2320 "msp430g2413", "msp430g2432", "msp430g2433", 2321 "msp430g2444", "msp430g2452", "msp430g2453", 2322 "msp430g2513", "msp430g2533", "msp430g2544", 2323 "msp430g2553", "msp430g2744", "msp430g2755", 2324 "msp430g2855", "msp430g2955", "msp430l092", 2325 "msp430p112", "msp430p313", "msp430p315", 2326 "msp430p315s", "msp430p325", "msp430tch5e" 2327 }; 2328 static const char * cached_match = NULL; 2329 static bool cached_result; 2330 int i; 2331 2332 if (msp430_hwmult_type == NONE) 2333 return true; 2334 2335 if (target_mcu == NULL || msp430_hwmult_type != AUTO) 2336 return false; 2337 2338 if (target_mcu == cached_match) 2339 return cached_result; 2340 2341 cached_match = target_mcu; 2342 for (i = ARRAY_SIZE (known_nomult_mcus); i--;) 2343 if (strcasecmp (target_mcu, known_nomult_mcus[i]) == 0) 2344 return cached_result = true; 2345 2346 return cached_result = false; 2347 } 2348 2349 /* This function does the same as the default, but it will replace GCC 2350 function names with the MSPABI-specified ones. */ 2351 2352 void 2353 msp430_output_labelref (FILE *file, const char *name) 2354 { 2355 int i; 2356 2357 for (i = 0; helper_function_name_mappings [i].gcc_name; i++) 2358 if (strcmp (helper_function_name_mappings [i].gcc_name, name) == 0) 2359 { 2360 name = helper_function_name_mappings [i].ti_name; 2361 break; 2362 } 2363 2364 /* If we have been given a specific MCU name then we may be 2365 able to make use of its hardware multiply capabilities. */ 2366 if (msp430_hwmult_type != NONE) 2367 { 2368 if (strcmp ("__mspabi_mpyi", name) == 0) 2369 { 2370 if (msp430_use_f5_series_hwmult ()) 2371 name = "__mulhi2_f5"; 2372 else if (! msp430_no_hwmult ()) 2373 name = "__mulhi2"; 2374 } 2375 else if (strcmp ("__mspabi_mpyl", name) == 0) 2376 { 2377 if (msp430_use_f5_series_hwmult ()) 2378 name = "__mulsi2_f5"; 2379 else if (use_32bit_hwmult ()) 2380 name = "__mulsi2_hw32"; 2381 else if (! msp430_no_hwmult ()) 2382 name = "__mulsi2"; 2383 } 2384 } 2385 2386 fputs (name, file); 2387 } 2388 2389 /* Common code for msp430_print_operand... */ 2390 2391 static void 2392 msp430_print_operand_raw (FILE * file, rtx op) 2393 { 2394 HOST_WIDE_INT i; 2395 2396 switch (GET_CODE (op)) 2397 { 2398 case REG: 2399 fprintf (file, "%s", reg_names [REGNO (op)]); 2400 break; 2401 2402 case CONST_INT: 2403 i = INTVAL (op); 2404 if (TARGET_ASM_HEX) 2405 fprintf (file, "%#" HOST_WIDE_INT_PRINT "x", i); 2406 else 2407 fprintf (file, "%" HOST_WIDE_INT_PRINT "d", i); 2408 break; 2409 2410 case CONST: 2411 case PLUS: 2412 case MINUS: 2413 case SYMBOL_REF: 2414 case LABEL_REF: 2415 output_addr_const (file, op); 2416 break; 2417 2418 default: 2419 print_rtl (file, op); 2420 break; 2421 } 2422 } 2423 2424 #undef TARGET_PRINT_OPERAND_ADDRESS 2425 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr 2426 2427 /* Output to stdio stream FILE the assembler syntax for an 2428 instruction operand that is a memory reference whose address 2429 is ADDR. */ 2430 2431 static void 2432 msp430_print_operand_addr (FILE * file, rtx addr) 2433 { 2434 switch (GET_CODE (addr)) 2435 { 2436 case PLUS: 2437 msp430_print_operand_raw (file, XEXP (addr, 1)); 2438 gcc_assert (REG_P (XEXP (addr, 0))); 2439 fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]); 2440 return; 2441 2442 case REG: 2443 fprintf (file, "@"); 2444 break; 2445 2446 case CONST: 2447 case CONST_INT: 2448 case SYMBOL_REF: 2449 case LABEL_REF: 2450 fprintf (file, "&"); 2451 break; 2452 2453 default: 2454 break; 2455 } 2456 2457 msp430_print_operand_raw (file, addr); 2458 } 2459 2460 #undef TARGET_PRINT_OPERAND 2461 #define TARGET_PRINT_OPERAND msp430_print_operand 2462 2463 /* A low 16-bits of int/lower of register pair 2464 B high 16-bits of int/higher of register pair 2465 C bits 32-47 of a 64-bit value/reg 3 of a DImode value 2466 D bits 48-63 of a 64-bit value/reg 4 of a DImode value 2467 H like %B (for backwards compatibility) 2468 I inverse of value 2469 J an integer without a # prefix 2470 L like %A (for backwards compatibility) 2471 O offset of the top of the stack 2472 Q like X but generates an A postfix 2473 R inverse of condition code, unsigned. 2474 X X instruction postfix in large mode 2475 Y value - 4 2476 Z value - 1 2477 b .B or .W or .A, depending upon the mode 2478 p bit position 2479 r inverse of condition code 2480 x like X but only for pointers. */ 2481 2482 static void 2483 msp430_print_operand (FILE * file, rtx op, int letter) 2484 { 2485 rtx addr; 2486 2487 /* We can't use c, n, a, or l. */ 2488 switch (letter) 2489 { 2490 case 'Z': 2491 gcc_assert (CONST_INT_P (op)); 2492 /* Print the constant value, less one. */ 2493 fprintf (file, "#%ld", INTVAL (op) - 1); 2494 return; 2495 case 'Y': 2496 gcc_assert (CONST_INT_P (op)); 2497 /* Print the constant value, less four. */ 2498 fprintf (file, "#%ld", INTVAL (op) - 4); 2499 return; 2500 case 'I': 2501 if (GET_CODE (op) == CONST_INT) 2502 { 2503 /* Inverse of constants */ 2504 int i = INTVAL (op); 2505 fprintf (file, "%d", ~i); 2506 return; 2507 } 2508 op = XEXP (op, 0); 2509 break; 2510 case 'r': /* Conditional jump where the condition is reversed. */ 2511 switch (GET_CODE (op)) 2512 { 2513 case EQ: fprintf (file, "NE"); break; 2514 case NE: fprintf (file, "EQ"); break; 2515 case GEU: fprintf (file, "LO"); break; 2516 case LTU: fprintf (file, "HS"); break; 2517 case GE: fprintf (file, "L"); break; 2518 case LT: fprintf (file, "GE"); break; 2519 /* Assume these have reversed operands. */ 2520 case GTU: fprintf (file, "HS"); break; 2521 case LEU: fprintf (file, "LO"); break; 2522 case GT: fprintf (file, "GE"); break; 2523 case LE: fprintf (file, "L"); break; 2524 default: 2525 msp430_print_operand_raw (file, op); 2526 break; 2527 } 2528 return; 2529 case 'R': /* Conditional jump where the operands are reversed. */ 2530 switch (GET_CODE (op)) 2531 { 2532 case GTU: fprintf (file, "LO"); break; 2533 case LEU: fprintf (file, "HS"); break; 2534 case GT: fprintf (file, "L"); break; 2535 case LE: fprintf (file, "GE"); break; 2536 default: 2537 msp430_print_operand_raw (file, op); 2538 break; 2539 } 2540 return; 2541 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */ 2542 gcc_assert (CONST_INT_P (op)); 2543 fprintf (file, "#%d", 1 << INTVAL (op)); 2544 return; 2545 case 'b': 2546 switch (GET_MODE (op)) 2547 { 2548 case QImode: fprintf (file, ".B"); return; 2549 case HImode: fprintf (file, ".W"); return; 2550 case PSImode: fprintf (file, ".A"); return; 2551 case SImode: fprintf (file, ".A"); return; 2552 default: 2553 return; 2554 } 2555 case 'A': 2556 case 'L': /* Low half. */ 2557 switch (GET_CODE (op)) 2558 { 2559 case MEM: 2560 op = adjust_address (op, Pmode, 0); 2561 break; 2562 case REG: 2563 break; 2564 case CONST_INT: 2565 op = GEN_INT (INTVAL (op) & 0xffff); 2566 letter = 0; 2567 break; 2568 default: 2569 /* If you get here, figure out a test case :-) */ 2570 gcc_unreachable (); 2571 } 2572 break; 2573 case 'B': 2574 case 'H': /* high half */ 2575 switch (GET_CODE (op)) 2576 { 2577 case MEM: 2578 op = adjust_address (op, Pmode, 2); 2579 break; 2580 case REG: 2581 op = gen_rtx_REG (Pmode, REGNO (op) + 1); 2582 break; 2583 case CONST_INT: 2584 op = GEN_INT (INTVAL (op) >> 16); 2585 letter = 0; 2586 break; 2587 default: 2588 /* If you get here, figure out a test case :-) */ 2589 gcc_unreachable (); 2590 } 2591 break; 2592 case 'C': 2593 switch (GET_CODE (op)) 2594 { 2595 case MEM: 2596 op = adjust_address (op, Pmode, 3); 2597 break; 2598 case REG: 2599 op = gen_rtx_REG (Pmode, REGNO (op) + 2); 2600 break; 2601 case CONST_INT: 2602 op = GEN_INT ((long long) INTVAL (op) >> 32); 2603 letter = 0; 2604 break; 2605 default: 2606 /* If you get here, figure out a test case :-) */ 2607 gcc_unreachable (); 2608 } 2609 break; 2610 case 'D': 2611 switch (GET_CODE (op)) 2612 { 2613 case MEM: 2614 op = adjust_address (op, Pmode, 4); 2615 break; 2616 case REG: 2617 op = gen_rtx_REG (Pmode, REGNO (op) + 3); 2618 break; 2619 case CONST_INT: 2620 op = GEN_INT ((long long) INTVAL (op) >> 48); 2621 letter = 0; 2622 break; 2623 default: 2624 /* If you get here, figure out a test case :-) */ 2625 gcc_unreachable (); 2626 } 2627 break; 2628 2629 case 'X': 2630 /* This is used to turn, for example, an ADD opcode into an ADDX 2631 opcode when we're using 20-bit addresses. */ 2632 if (TARGET_LARGE || GET_MODE (op) == PSImode) 2633 fprintf (file, "X"); 2634 /* We don't care which operand we use, but we want 'X' in the MD 2635 file, so we do it this way. */ 2636 return; 2637 2638 case 'x': 2639 /* Similarly, but only for PSImodes. BIC, for example, needs this. */ 2640 if (GET_MODE (op) == PSImode) 2641 fprintf (file, "X"); 2642 return; 2643 2644 case 'Q': 2645 /* Likewise, for BR -> BRA. */ 2646 if (TARGET_LARGE) 2647 fprintf (file, "A"); 2648 return; 2649 2650 case 'O': 2651 /* Computes the offset to the top of the stack for the current frame. 2652 This has to be done here rather than in, say, msp430_expand_builtin() 2653 because builtins are expanded before the frame layout is determined. */ 2654 fprintf (file, "%d", 2655 msp430_initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM) 2656 - (TARGET_LARGE ? 4 : 2)); 2657 return; 2658 2659 case 'J': 2660 gcc_assert (GET_CODE (op) == CONST_INT); 2661 case 0: 2662 break; 2663 default: 2664 output_operand_lossage ("invalid operand prefix"); 2665 return; 2666 } 2667 2668 switch (GET_CODE (op)) 2669 { 2670 case REG: 2671 msp430_print_operand_raw (file, op); 2672 break; 2673 2674 case MEM: 2675 addr = XEXP (op, 0); 2676 msp430_print_operand_addr (file, addr); 2677 break; 2678 2679 case CONST: 2680 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTRACT) 2681 { 2682 op = XEXP (op, 0); 2683 switch (INTVAL (XEXP (op, 2))) 2684 { 2685 case 0: 2686 fprintf (file, "#lo ("); 2687 msp430_print_operand_raw (file, XEXP (op, 0)); 2688 fprintf (file, ")"); 2689 break; 2690 2691 case 16: 2692 fprintf (file, "#hi ("); 2693 msp430_print_operand_raw (file, XEXP (op, 0)); 2694 fprintf (file, ")"); 2695 break; 2696 2697 default: 2698 output_operand_lossage ("invalid zero extract"); 2699 break; 2700 } 2701 break; 2702 } 2703 /* Fall through. */ 2704 case CONST_INT: 2705 case SYMBOL_REF: 2706 case LABEL_REF: 2707 if (letter == 0) 2708 fprintf (file, "#"); 2709 msp430_print_operand_raw (file, op); 2710 break; 2711 2712 case EQ: fprintf (file, "EQ"); break; 2713 case NE: fprintf (file, "NE"); break; 2714 case GEU: fprintf (file, "HS"); break; 2715 case LTU: fprintf (file, "LO"); break; 2716 case GE: fprintf (file, "GE"); break; 2717 case LT: fprintf (file, "L"); break; 2718 2719 default: 2720 print_rtl (file, op); 2721 break; 2722 } 2723 } 2724 2725 2726 /* Frame stuff. */ 2727 2728 rtx 2729 msp430_return_addr_rtx (int count) 2730 { 2731 int ra_size; 2732 if (count) 2733 return NULL_RTX; 2734 2735 ra_size = TARGET_LARGE ? 4 : 2; 2736 if (crtl->args.pretend_args_size) 2737 ra_size += 2; 2738 2739 return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, arg_pointer_rtx, GEN_INT (- ra_size))); 2740 } 2741 2742 rtx 2743 msp430_incoming_return_addr_rtx (void) 2744 { 2745 return gen_rtx_MEM (Pmode, stack_pointer_rtx); 2746 } 2747 2748 /* Instruction generation stuff. */ 2749 2750 /* Generate a sequence of instructions to sign-extend an HI 2751 value into an SI value. Handles the tricky case where 2752 we are overwriting the destination. */ 2753 2754 const char * 2755 msp430x_extendhisi (rtx * operands) 2756 { 2757 if (REGNO (operands[0]) == REGNO (operands[1])) 2758 /* Low word of dest == source word. */ 2759 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */ 2760 2761 if (! msp430x) 2762 /* Note: This sequence is approximately the same length as invoking a helper 2763 function to perform the sign-extension, as in: 2764 2765 MOV.W %1, %L0 2766 MOV.W %1, r12 2767 CALL __mspabi_srai_15 2768 MOV.W r12, %H0 2769 2770 but this version does not involve any function calls or using argument 2771 registers, so it reduces register pressure. */ 2772 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */ 2773 2774 if (REGNO (operands[0]) + 1 == REGNO (operands[1])) 2775 /* High word of dest == source word. */ 2776 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */ 2777 2778 /* No overlap between dest and source. */ 2779 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */ 2780 } 2781 2782 /* Likewise for logical right shifts. */ 2783 const char * 2784 msp430x_logical_shift_right (rtx amount) 2785 { 2786 /* The MSP430X's logical right shift instruction - RRUM - does 2787 not use an extension word, so we cannot encode a repeat count. 2788 Try various alternatives to work around this. If the count 2789 is in a register we are stuck, hence the assert. */ 2790 gcc_assert (CONST_INT_P (amount)); 2791 2792 if (INTVAL (amount) <= 0 2793 || INTVAL (amount) >= 16) 2794 return "# nop logical shift."; 2795 2796 if (INTVAL (amount) > 0 2797 && INTVAL (amount) < 5) 2798 return "rrum.w\t%2, %0"; /* Two bytes. */ 2799 2800 if (INTVAL (amount) > 4 2801 && INTVAL (amount) < 9) 2802 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */ 2803 2804 /* First we logically shift right by one. Now we know 2805 that the top bit is zero and we can use the arithmetic 2806 right shift instruction to perform the rest of the shift. */ 2807 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */ 2808 } 2809 2810 struct gcc_target targetm = TARGET_INITIALIZER; 2811 2812 #include "gt-msp430.h" 2813