1 /* Subroutines used for code generation on the Tilera TILEPro. 2 Copyright (C) 2011-2018 Free Software Foundation, Inc. 3 Contributed by Walter Lee (walt@tilera.com) 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published 9 by the Free Software Foundation; either version 3, or (at your 10 option) any later version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 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 #define IN_TARGET_CODE 1 22 23 #include "config.h" 24 #include "system.h" 25 #include "coretypes.h" 26 #include "backend.h" 27 #include "target.h" 28 #include "rtl.h" 29 #include "tree.h" 30 #include "gimple.h" 31 #include "df.h" 32 #include "memmodel.h" 33 #include "tm_p.h" 34 #include "stringpool.h" 35 #include "attribs.h" 36 #include "expmed.h" 37 #include "optabs.h" 38 #include "regs.h" 39 #include "emit-rtl.h" 40 #include "recog.h" 41 #include "diagnostic.h" 42 #include "output.h" 43 #include "insn-attr.h" 44 #include "alias.h" 45 #include "explow.h" 46 #include "calls.h" 47 #include "varasm.h" 48 #include "expr.h" 49 #include "langhooks.h" 50 #include "cfgrtl.h" 51 #include "tm-constrs.h" 52 #include "dwarf2.h" 53 #include "fold-const.h" 54 #include "stor-layout.h" 55 #include "gimplify.h" 56 #include "tilepro-builtins.h" 57 #include "tilepro-multiply.h" 58 #include "builtins.h" 59 60 /* This file should be included last. */ 61 #include "target-def.h" 62 63 /* SYMBOL_REF for GOT */ 64 static GTY(()) rtx g_got_symbol = NULL; 65 66 /* Report whether we're printing out the first address fragment of a 67 POST_INC or POST_DEC memory reference, from TARGET_PRINT_OPERAND to 68 TARGET_PRINT_OPERAND_ADDRESS. */ 69 static bool output_memory_autoinc_first; 70 71 72 73 /* Option handling */ 74 75 /* Implement TARGET_OPTION_OVERRIDE. */ 76 static void 77 tilepro_option_override (void) 78 { 79 /* When modulo scheduling is enabled, we still rely on regular 80 scheduler for bundling. */ 81 if (flag_modulo_sched) 82 flag_resched_modulo_sched = 1; 83 } 84 85 86 87 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */ 88 static bool 89 tilepro_scalar_mode_supported_p (scalar_mode mode) 90 { 91 switch (mode) 92 { 93 case E_QImode: 94 case E_HImode: 95 case E_SImode: 96 case E_DImode: 97 return true; 98 99 case E_SFmode: 100 case E_DFmode: 101 return true; 102 103 default: 104 return false; 105 } 106 } 107 108 109 /* Implement TARGET_VECTOR_MODE_SUPPORTED_P. */ 110 static bool 111 tile_vector_mode_supported_p (machine_mode mode) 112 { 113 return mode == V4QImode || mode == V2HImode; 114 } 115 116 117 /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */ 118 static bool 119 tilepro_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, 120 rtx x ATTRIBUTE_UNUSED) 121 { 122 return true; 123 } 124 125 126 /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL. */ 127 static bool 128 tilepro_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) 129 { 130 return decl != NULL; 131 } 132 133 134 /* Implement TARGET_PASS_BY_REFERENCE. Variable sized types are 135 passed by reference. */ 136 static bool 137 tilepro_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED, 138 machine_mode mode ATTRIBUTE_UNUSED, 139 const_tree type, bool named ATTRIBUTE_UNUSED) 140 { 141 return (type && TYPE_SIZE (type) 142 && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST); 143 } 144 145 146 /* Implement TARGET_RETURN_IN_MEMORY. */ 147 static bool 148 tilepro_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED) 149 { 150 return !IN_RANGE (int_size_in_bytes (type), 151 0, TILEPRO_NUM_RETURN_REGS * UNITS_PER_WORD); 152 } 153 154 155 /* Implement TARGET_FUNCTION_ARG_BOUNDARY. */ 156 static unsigned int 157 tilepro_function_arg_boundary (machine_mode mode, const_tree type) 158 { 159 unsigned int alignment; 160 161 alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode); 162 if (alignment < PARM_BOUNDARY) 163 alignment = PARM_BOUNDARY; 164 if (alignment > STACK_BOUNDARY) 165 alignment = STACK_BOUNDARY; 166 return alignment; 167 } 168 169 170 /* Implement TARGET_FUNCTION_ARG. */ 171 static rtx 172 tilepro_function_arg (cumulative_args_t cum_v, 173 machine_mode mode, 174 const_tree type, bool named ATTRIBUTE_UNUSED) 175 { 176 CUMULATIVE_ARGS cum = *get_cumulative_args (cum_v); 177 int byte_size = ((mode == BLKmode) 178 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode)); 179 bool doubleword_aligned_p; 180 181 if (cum >= TILEPRO_NUM_ARG_REGS) 182 return NULL_RTX; 183 184 /* See whether the argument has doubleword alignment. */ 185 doubleword_aligned_p = 186 tilepro_function_arg_boundary (mode, type) > BITS_PER_WORD; 187 188 if (doubleword_aligned_p) 189 cum += cum & 1; 190 191 /* The ABI does not allow parameters to be passed partially in reg 192 and partially in stack. */ 193 if ((cum + (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) 194 > TILEPRO_NUM_ARG_REGS) 195 return NULL_RTX; 196 197 return gen_rtx_REG (mode, cum); 198 } 199 200 201 /* Implement TARGET_FUNCTION_ARG_ADVANCE. */ 202 static void 203 tilepro_function_arg_advance (cumulative_args_t cum_v, 204 machine_mode mode, 205 const_tree type, bool named ATTRIBUTE_UNUSED) 206 { 207 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 208 209 int byte_size = ((mode == BLKmode) 210 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode)); 211 int word_size = (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 212 bool doubleword_aligned_p; 213 214 /* See whether the argument has doubleword alignment. */ 215 doubleword_aligned_p = 216 tilepro_function_arg_boundary (mode, type) > BITS_PER_WORD; 217 218 if (doubleword_aligned_p) 219 *cum += *cum & 1; 220 221 /* If the current argument does not fit in the pretend_args space, 222 skip over it. */ 223 if (*cum < TILEPRO_NUM_ARG_REGS 224 && *cum + word_size > TILEPRO_NUM_ARG_REGS) 225 *cum = TILEPRO_NUM_ARG_REGS; 226 227 *cum += word_size; 228 } 229 230 231 /* Implement TARGET_FUNCTION_VALUE. */ 232 static rtx 233 tilepro_function_value (const_tree valtype, const_tree fn_decl_or_type, 234 bool outgoing ATTRIBUTE_UNUSED) 235 { 236 machine_mode mode; 237 int unsigned_p; 238 239 mode = TYPE_MODE (valtype); 240 unsigned_p = TYPE_UNSIGNED (valtype); 241 242 mode = promote_function_mode (valtype, mode, &unsigned_p, 243 fn_decl_or_type, 1); 244 245 return gen_rtx_REG (mode, 0); 246 } 247 248 249 /* Implement TARGET_LIBCALL_VALUE. */ 250 static rtx 251 tilepro_libcall_value (machine_mode mode, 252 const_rtx fun ATTRIBUTE_UNUSED) 253 { 254 return gen_rtx_REG (mode, 0); 255 } 256 257 258 /* Implement FUNCTION_VALUE_REGNO_P. */ 259 static bool 260 tilepro_function_value_regno_p (const unsigned int regno) 261 { 262 return regno < TILEPRO_NUM_RETURN_REGS; 263 } 264 265 266 /* Implement TARGET_BUILD_BUILTIN_VA_LIST. */ 267 static tree 268 tilepro_build_builtin_va_list (void) 269 { 270 tree f_args, f_skip, record, type_decl; 271 bool owp; 272 273 record = lang_hooks.types.make_type (RECORD_TYPE); 274 275 type_decl = build_decl (BUILTINS_LOCATION, TYPE_DECL, 276 get_identifier ("__va_list_tag"), record); 277 278 f_args = build_decl (BUILTINS_LOCATION, FIELD_DECL, 279 get_identifier ("__args"), ptr_type_node); 280 f_skip = build_decl (BUILTINS_LOCATION, FIELD_DECL, 281 get_identifier ("__skip"), ptr_type_node); 282 283 DECL_FIELD_CONTEXT (f_args) = record; 284 285 DECL_FIELD_CONTEXT (f_skip) = record; 286 287 TREE_CHAIN (record) = type_decl; 288 TYPE_NAME (record) = type_decl; 289 TYPE_FIELDS (record) = f_args; 290 TREE_CHAIN (f_args) = f_skip; 291 292 /* We know this is being padded and we want it too. It is an 293 internal type so hide the warnings from the user. */ 294 owp = warn_padded; 295 warn_padded = false; 296 297 layout_type (record); 298 299 warn_padded = owp; 300 301 /* The correct type is an array type of one element. */ 302 return record; 303 } 304 305 306 /* Implement TARGET_EXPAND_BUILTIN_VA_START. */ 307 static void 308 tilepro_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) 309 { 310 tree f_args, f_skip; 311 tree args, skip, t; 312 313 f_args = TYPE_FIELDS (TREE_TYPE (valist)); 314 f_skip = TREE_CHAIN (f_args); 315 316 args = 317 build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE); 318 skip = 319 build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE); 320 321 /* Find the __args area. */ 322 t = make_tree (TREE_TYPE (args), virtual_incoming_args_rtx); 323 t = fold_build_pointer_plus_hwi (t, 324 UNITS_PER_WORD * 325 (crtl->args.info - TILEPRO_NUM_ARG_REGS)); 326 327 if (crtl->args.pretend_args_size > 0) 328 t = fold_build_pointer_plus_hwi (t, -STACK_POINTER_OFFSET); 329 330 t = build2 (MODIFY_EXPR, TREE_TYPE (args), args, t); 331 TREE_SIDE_EFFECTS (t) = 1; 332 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 333 334 /* Find the __skip area. */ 335 t = make_tree (TREE_TYPE (skip), virtual_incoming_args_rtx); 336 t = fold_build_pointer_plus_hwi (t, -STACK_POINTER_OFFSET); 337 t = build2 (MODIFY_EXPR, TREE_TYPE (skip), skip, t); 338 TREE_SIDE_EFFECTS (t) = 1; 339 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 340 } 341 342 343 /* Implement TARGET_SETUP_INCOMING_VARARGS. */ 344 static void 345 tilepro_setup_incoming_varargs (cumulative_args_t cum, 346 machine_mode mode, 347 tree type, int *pretend_args, int no_rtl) 348 { 349 CUMULATIVE_ARGS local_cum = *get_cumulative_args (cum); 350 int first_reg; 351 352 /* The caller has advanced CUM up to, but not beyond, the last named 353 argument. Advance a local copy of CUM past the last "real" named 354 argument, to find out how many registers are left over. */ 355 targetm.calls.function_arg_advance (pack_cumulative_args (&local_cum), 356 mode, type, true); 357 first_reg = local_cum; 358 359 if (local_cum < TILEPRO_NUM_ARG_REGS) 360 { 361 *pretend_args = UNITS_PER_WORD * (TILEPRO_NUM_ARG_REGS - first_reg); 362 363 if (!no_rtl) 364 { 365 alias_set_type set = get_varargs_alias_set (); 366 rtx tmp = 367 gen_rtx_MEM (BLKmode, plus_constant (Pmode, \ 368 virtual_incoming_args_rtx, 369 -STACK_POINTER_OFFSET - 370 UNITS_PER_WORD * 371 (TILEPRO_NUM_ARG_REGS - 372 first_reg))); 373 MEM_NOTRAP_P (tmp) = 1; 374 set_mem_alias_set (tmp, set); 375 move_block_from_reg (first_reg, tmp, 376 TILEPRO_NUM_ARG_REGS - first_reg); 377 } 378 } 379 else 380 *pretend_args = 0; 381 } 382 383 384 /* Implement TARGET_GIMPLIFY_VA_ARG_EXPR. Gimplify va_arg by updating 385 the va_list structure VALIST as required to retrieve an argument of 386 type TYPE, and returning that argument. 387 388 ret = va_arg(VALIST, TYPE); 389 390 generates code equivalent to: 391 392 paddedsize = (sizeof(TYPE) + 3) & -4; 393 if ((VALIST.__args + paddedsize > VALIST.__skip) 394 & (VALIST.__args <= VALIST.__skip)) 395 addr = VALIST.__skip + STACK_POINTER_OFFSET; 396 else 397 addr = VALIST.__args; 398 VALIST.__args = addr + paddedsize; 399 ret = *(TYPE *)addr; */ 400 static tree 401 tilepro_gimplify_va_arg_expr (tree valist, tree type, gimple_seq * pre_p, 402 gimple_seq * post_p ATTRIBUTE_UNUSED) 403 { 404 tree f_args, f_skip; 405 tree args, skip; 406 HOST_WIDE_INT size, rsize; 407 tree addr, tmp; 408 bool pass_by_reference_p; 409 410 f_args = TYPE_FIELDS (va_list_type_node); 411 f_skip = TREE_CHAIN (f_args); 412 413 args = 414 build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE); 415 skip = 416 build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE); 417 418 addr = create_tmp_var (ptr_type_node, "va_arg"); 419 420 /* if an object is dynamically sized, a pointer to it is passed 421 instead of the object itself. */ 422 pass_by_reference_p = pass_by_reference (NULL, TYPE_MODE (type), type, 423 false); 424 425 if (pass_by_reference_p) 426 type = build_pointer_type (type); 427 428 size = int_size_in_bytes (type); 429 rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD; 430 431 /* If the alignment of the type is greater than the default for a 432 parameter, align to STACK_BOUNDARY. */ 433 if (TYPE_ALIGN (type) > PARM_BOUNDARY) 434 { 435 /* Assert the only case we generate code for: when 436 stack boundary = 2 * parm boundary. */ 437 gcc_assert (STACK_BOUNDARY == PARM_BOUNDARY * 2); 438 439 tmp = build2 (BIT_AND_EXPR, sizetype, 440 fold_convert (sizetype, unshare_expr (args)), 441 size_int (PARM_BOUNDARY / 8)); 442 tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, 443 unshare_expr (args), tmp); 444 445 gimplify_assign (unshare_expr (args), tmp, pre_p); 446 } 447 448 /* Build conditional expression to calculate addr. The expression 449 will be gimplified later. */ 450 tmp = fold_build_pointer_plus_hwi (unshare_expr (args), rsize); 451 tmp = build2 (TRUTH_AND_EXPR, boolean_type_node, 452 build2 (GT_EXPR, boolean_type_node, tmp, unshare_expr (skip)), 453 build2 (LE_EXPR, boolean_type_node, unshare_expr (args), 454 unshare_expr (skip))); 455 456 tmp = build3 (COND_EXPR, ptr_type_node, tmp, 457 build2 (POINTER_PLUS_EXPR, ptr_type_node, unshare_expr (skip), 458 size_int (STACK_POINTER_OFFSET)), 459 unshare_expr (args)); 460 461 gimplify_assign (addr, tmp, pre_p); 462 463 /* Update VALIST.__args. */ 464 tmp = fold_build_pointer_plus_hwi (addr, rsize); 465 gimplify_assign (unshare_expr (args), tmp, pre_p); 466 467 addr = fold_convert (build_pointer_type (type), addr); 468 469 if (pass_by_reference_p) 470 addr = build_va_arg_indirect_ref (addr); 471 472 return build_va_arg_indirect_ref (addr); 473 } 474 475 476 477 /* Implement TARGET_RTX_COSTS. */ 478 static bool 479 tilepro_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, 480 int *total, bool speed) 481 { 482 int code = GET_CODE (x); 483 484 switch (code) 485 { 486 case CONST_INT: 487 /* If this is an 8-bit constant, return zero since it can be 488 used nearly anywhere with no cost. If it is a valid operand 489 for an ADD or AND, likewise return 0 if we know it will be 490 used in that context. Otherwise, return 2 since it might be 491 used there later. All other constants take at least two 492 insns. */ 493 if (satisfies_constraint_I (x)) 494 { 495 *total = 0; 496 return true; 497 } 498 else if (outer_code == PLUS && add_operand (x, VOIDmode)) 499 { 500 /* Slightly penalize large constants even though we can add 501 them in one instruction, because it forces the use of 502 2-wide bundling mode. */ 503 *total = 1; 504 return true; 505 } 506 else if (move_operand (x, SImode)) 507 { 508 /* We can materialize in one move. */ 509 *total = COSTS_N_INSNS (1); 510 return true; 511 } 512 else 513 { 514 /* We can materialize in two moves. */ 515 *total = COSTS_N_INSNS (2); 516 return true; 517 } 518 519 return false; 520 521 case CONST: 522 case LABEL_REF: 523 case SYMBOL_REF: 524 *total = COSTS_N_INSNS (2); 525 return true; 526 527 case CONST_DOUBLE: 528 *total = COSTS_N_INSNS (4); 529 return true; 530 531 case HIGH: 532 *total = 0; 533 return true; 534 535 case MEM: 536 /* If outer-code was a sign or zero extension, a cost of 537 COSTS_N_INSNS (1) was already added in, so account for 538 that. */ 539 if (outer_code == ZERO_EXTEND || outer_code == SIGN_EXTEND) 540 *total = COSTS_N_INSNS (1); 541 else 542 *total = COSTS_N_INSNS (2); 543 return true; 544 545 case PLUS: 546 /* Convey that s[123]a are efficient. */ 547 if (GET_CODE (XEXP (x, 0)) == MULT 548 && cint_248_operand (XEXP (XEXP (x, 0), 1), VOIDmode)) 549 { 550 *total = (rtx_cost (XEXP (XEXP (x, 0), 0), mode, 551 (enum rtx_code) outer_code, opno, speed) 552 + rtx_cost (XEXP (x, 1), mode, 553 (enum rtx_code) outer_code, opno, speed) 554 + COSTS_N_INSNS (1)); 555 return true; 556 } 557 return false; 558 559 case MULT: 560 *total = COSTS_N_INSNS (2); 561 return false; 562 563 case SIGN_EXTEND: 564 case ZERO_EXTEND: 565 if (outer_code == MULT) 566 *total = 0; 567 else 568 *total = COSTS_N_INSNS (1); 569 return false; 570 571 case DIV: 572 case UDIV: 573 case MOD: 574 case UMOD: 575 /* These are handled by software and are very expensive. */ 576 *total = COSTS_N_INSNS (100); 577 return false; 578 579 case UNSPEC: 580 case UNSPEC_VOLATILE: 581 { 582 int num = XINT (x, 1); 583 584 if (num <= TILEPRO_LAST_LATENCY_1_INSN) 585 *total = COSTS_N_INSNS (1); 586 else if (num <= TILEPRO_LAST_LATENCY_2_INSN) 587 *total = COSTS_N_INSNS (2); 588 else if (num > TILEPRO_LAST_LATENCY_INSN) 589 { 590 if (outer_code == PLUS) 591 *total = 0; 592 else 593 *total = COSTS_N_INSNS (1); 594 } 595 else 596 { 597 switch (num) 598 { 599 case UNSPEC_BLOCKAGE: 600 case UNSPEC_NETWORK_BARRIER: 601 *total = 0; 602 break; 603 604 case UNSPEC_LNK_AND_LABEL: 605 case UNSPEC_MF: 606 case UNSPEC_NETWORK_RECEIVE: 607 case UNSPEC_NETWORK_SEND: 608 case UNSPEC_TLS_GD_ADD: 609 *total = COSTS_N_INSNS (1); 610 break; 611 612 case UNSPEC_TLS_IE_LOAD: 613 *total = COSTS_N_INSNS (2); 614 break; 615 616 case UNSPEC_SP_SET: 617 *total = COSTS_N_INSNS (3); 618 break; 619 620 case UNSPEC_SP_TEST: 621 *total = COSTS_N_INSNS (4); 622 break; 623 624 case UNSPEC_LATENCY_L2: 625 *total = COSTS_N_INSNS (8); 626 break; 627 628 case UNSPEC_TLS_GD_CALL: 629 *total = COSTS_N_INSNS (30); 630 break; 631 632 case UNSPEC_LATENCY_MISS: 633 *total = COSTS_N_INSNS (80); 634 break; 635 636 default: 637 *total = COSTS_N_INSNS (1); 638 } 639 } 640 return true; 641 } 642 643 default: 644 return false; 645 } 646 } 647 648 649 650 /* Returns an SImode integer rtx with value VAL. */ 651 static rtx 652 gen_int_si (HOST_WIDE_INT val) 653 { 654 return gen_int_mode (val, SImode); 655 } 656 657 658 /* Create a temporary variable to hold a partial result, to enable 659 CSE. */ 660 static rtx 661 create_temp_reg_if_possible (machine_mode mode, rtx default_reg) 662 { 663 return can_create_pseudo_p ()? gen_reg_rtx (mode) : default_reg; 664 } 665 666 667 /* Functions to save and restore machine-specific function data. */ 668 static struct machine_function * 669 tilepro_init_machine_status (void) 670 { 671 return ggc_cleared_alloc<machine_function> (); 672 } 673 674 675 /* Do anything needed before RTL is emitted for each function. */ 676 void 677 tilepro_init_expanders (void) 678 { 679 /* Arrange to initialize and mark the machine per-function 680 status. */ 681 init_machine_status = tilepro_init_machine_status; 682 683 if (cfun && cfun->machine && flag_pic) 684 { 685 static int label_num = 0; 686 687 char text_label_name[32]; 688 689 struct machine_function *machine = cfun->machine; 690 691 ASM_GENERATE_INTERNAL_LABEL (text_label_name, "L_PICLNK", label_num++); 692 693 machine->text_label_symbol = 694 gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (text_label_name)); 695 696 machine->text_label_rtx = 697 gen_rtx_REG (Pmode, TILEPRO_PIC_TEXT_LABEL_REGNUM); 698 699 machine->got_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM); 700 701 machine->calls_tls_get_addr = false; 702 } 703 } 704 705 706 /* Return true if X contains a thread-local symbol. */ 707 static bool 708 tilepro_tls_referenced_p (rtx x) 709 { 710 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS) 711 x = XEXP (XEXP (x, 0), 0); 712 713 if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x)) 714 return true; 715 716 /* That's all we handle in tilepro_legitimize_tls_address for 717 now. */ 718 return false; 719 } 720 721 722 /* Return true if X requires a scratch register. It is given that 723 flag_pic is on and that X satisfies CONSTANT_P. */ 724 static int 725 tilepro_pic_address_needs_scratch (rtx x) 726 { 727 if (GET_CODE (x) == CONST 728 && GET_CODE (XEXP (x, 0)) == PLUS 729 && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF 730 || GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF) 731 && CONST_INT_P (XEXP (XEXP (x, 0), 1))) 732 return true; 733 734 return false; 735 } 736 737 738 /* Implement TARGET_LEGITIMATE_CONSTANT_P. This is all constants for 739 which we are willing to load the value into a register via a move 740 pattern. TLS cannot be treated as a constant because it can 741 include a function call. */ 742 static bool 743 tilepro_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x) 744 { 745 switch (GET_CODE (x)) 746 { 747 case CONST: 748 case SYMBOL_REF: 749 return !tilepro_tls_referenced_p (x); 750 751 default: 752 return true; 753 } 754 } 755 756 757 /* Return true if the constant value X is a legitimate general operand 758 when generating PIC code. It is given that flag_pic is on and that 759 X satisfies CONSTANT_P. */ 760 bool 761 tilepro_legitimate_pic_operand_p (rtx x) 762 { 763 if (tilepro_pic_address_needs_scratch (x)) 764 return false; 765 766 if (tilepro_tls_referenced_p (x)) 767 return false; 768 769 return true; 770 } 771 772 773 /* Return true if the rtx X can be used as an address operand. */ 774 static bool 775 tilepro_legitimate_address_p (machine_mode ARG_UNUSED (mode), rtx x, 776 bool strict) 777 { 778 if (GET_CODE (x) == SUBREG) 779 x = SUBREG_REG (x); 780 781 switch (GET_CODE (x)) 782 { 783 case POST_INC: 784 case POST_DEC: 785 if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD) 786 return false; 787 788 x = XEXP (x, 0); 789 break; 790 791 case POST_MODIFY: 792 if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD) 793 return false; 794 795 if (GET_CODE (XEXP (x, 1)) != PLUS) 796 return false; 797 798 if (!rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0))) 799 return false; 800 801 if (!satisfies_constraint_I (XEXP (XEXP (x, 1), 1))) 802 return false; 803 804 x = XEXP (x, 0); 805 break; 806 807 case REG: 808 break; 809 810 default: 811 return false; 812 } 813 814 /* Check if x is a valid reg. */ 815 if (!REG_P (x)) 816 return false; 817 818 if (strict) 819 return REGNO_OK_FOR_BASE_P (REGNO (x)); 820 else 821 return true; 822 } 823 824 825 /* Return the rtx containing SYMBOL_REF to the text label. */ 826 static rtx 827 tilepro_text_label_symbol (void) 828 { 829 return cfun->machine->text_label_symbol; 830 } 831 832 833 /* Return the register storing the value of the text label. */ 834 static rtx 835 tilepro_text_label_rtx (void) 836 { 837 return cfun->machine->text_label_rtx; 838 } 839 840 841 /* Return the register storing the value of the global offset 842 table. */ 843 static rtx 844 tilepro_got_rtx (void) 845 { 846 return cfun->machine->got_rtx; 847 } 848 849 850 /* Return the SYMBOL_REF for _GLOBAL_OFFSET_TABLE_. */ 851 static rtx 852 tilepro_got_symbol (void) 853 { 854 if (g_got_symbol == NULL) 855 g_got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); 856 857 return g_got_symbol; 858 } 859 860 861 /* Return a reference to the got to be used by tls references. */ 862 static rtx 863 tilepro_tls_got (void) 864 { 865 rtx temp; 866 if (flag_pic) 867 { 868 crtl->uses_pic_offset_table = 1; 869 return tilepro_got_rtx (); 870 } 871 872 temp = gen_reg_rtx (Pmode); 873 emit_move_insn (temp, tilepro_got_symbol ()); 874 875 return temp; 876 } 877 878 879 /* ADDR contains a thread-local SYMBOL_REF. Generate code to compute 880 this (thread-local) address. */ 881 static rtx 882 tilepro_legitimize_tls_address (rtx addr) 883 { 884 rtx ret; 885 886 gcc_assert (can_create_pseudo_p ()); 887 888 if (GET_CODE (addr) == SYMBOL_REF) 889 switch (SYMBOL_REF_TLS_MODEL (addr)) 890 { 891 case TLS_MODEL_GLOBAL_DYNAMIC: 892 case TLS_MODEL_LOCAL_DYNAMIC: 893 { 894 rtx r0, temp1, temp2, temp3, got; 895 rtx_insn *last; 896 897 ret = gen_reg_rtx (Pmode); 898 r0 = gen_rtx_REG (Pmode, 0); 899 temp1 = gen_reg_rtx (Pmode); 900 temp2 = gen_reg_rtx (Pmode); 901 temp3 = gen_reg_rtx (Pmode); 902 903 got = tilepro_tls_got (); 904 emit_insn (gen_tls_gd_addhi (temp1, got, addr)); 905 emit_insn (gen_tls_gd_addlo (temp2, temp1, addr)); 906 emit_move_insn (r0, temp2); 907 emit_insn (gen_tls_gd_call (addr)); 908 emit_move_insn (temp3, r0); 909 last = emit_insn (gen_tls_gd_add (ret, temp3, addr)); 910 set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr)); 911 break; 912 } 913 case TLS_MODEL_INITIAL_EXEC: 914 { 915 rtx temp1, temp2, temp3, got; 916 rtx_insn *last; 917 918 ret = gen_reg_rtx (Pmode); 919 temp1 = gen_reg_rtx (Pmode); 920 temp2 = gen_reg_rtx (Pmode); 921 temp3 = gen_reg_rtx (Pmode); 922 923 got = tilepro_tls_got (); 924 emit_insn (gen_tls_ie_addhi (temp1, got, addr)); 925 emit_insn (gen_tls_ie_addlo (temp2, temp1, addr)); 926 emit_insn (gen_tls_ie_load (temp3, temp2, addr)); 927 last = 928 emit_move_insn(ret, 929 gen_rtx_PLUS (Pmode, 930 gen_rtx_REG (Pmode, 931 THREAD_POINTER_REGNUM), 932 temp3)); 933 set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr)); 934 break; 935 } 936 case TLS_MODEL_LOCAL_EXEC: 937 { 938 rtx temp1; 939 rtx_insn *last; 940 941 ret = gen_reg_rtx (Pmode); 942 temp1 = gen_reg_rtx (Pmode); 943 944 emit_insn (gen_tls_le_addhi (temp1, 945 gen_rtx_REG (Pmode, 946 THREAD_POINTER_REGNUM), 947 addr)); 948 last = emit_insn (gen_tls_le_addlo (ret, temp1, addr)); 949 set_unique_reg_note (last, REG_EQUAL, copy_rtx (addr)); 950 break; 951 } 952 default: 953 gcc_unreachable (); 954 } 955 else if (GET_CODE (addr) == CONST) 956 { 957 rtx base, offset; 958 959 gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS); 960 961 base = tilepro_legitimize_tls_address (XEXP (XEXP (addr, 0), 0)); 962 offset = XEXP (XEXP (addr, 0), 1); 963 964 base = force_operand (base, NULL_RTX); 965 ret = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, offset)); 966 } 967 else 968 gcc_unreachable (); 969 970 return ret; 971 } 972 973 974 /* Legitimize PIC addresses. If the address is already 975 position-independent, we return ORIG. Newly generated 976 position-independent addresses go into a reg. This is REG if 977 nonzero, otherwise we allocate register(s) as necessary. */ 978 static rtx 979 tilepro_legitimize_pic_address (rtx orig, 980 machine_mode mode ATTRIBUTE_UNUSED, 981 rtx reg) 982 { 983 if (GET_CODE (orig) == SYMBOL_REF) 984 { 985 rtx address, pic_ref; 986 987 if (reg == 0) 988 { 989 gcc_assert (can_create_pseudo_p ()); 990 reg = gen_reg_rtx (Pmode); 991 } 992 993 if (SYMBOL_REF_LOCAL_P (orig)) 994 { 995 /* If not during reload, allocate another temp reg here for 996 loading in the address, so that these instructions can be 997 optimized properly. */ 998 rtx temp_reg = create_temp_reg_if_possible (Pmode, reg); 999 rtx text_label_symbol = tilepro_text_label_symbol (); 1000 rtx text_label_rtx = tilepro_text_label_rtx (); 1001 1002 emit_insn (gen_addli_pcrel (temp_reg, text_label_rtx, orig, 1003 text_label_symbol)); 1004 emit_insn (gen_auli_pcrel (temp_reg, temp_reg, orig, 1005 text_label_symbol)); 1006 1007 /* Note: this is conservative. We use the text_label but we 1008 don't use the pic_offset_table. However, in some cases 1009 we may need the pic_offset_table (see 1010 tilepro_fixup_pcrel_references). */ 1011 crtl->uses_pic_offset_table = 1; 1012 1013 address = temp_reg; 1014 1015 emit_move_insn (reg, address); 1016 return reg; 1017 } 1018 else 1019 { 1020 /* If not during reload, allocate another temp reg here for 1021 loading in the address, so that these instructions can be 1022 optimized properly. */ 1023 rtx temp_reg = create_temp_reg_if_possible (Pmode, reg); 1024 1025 gcc_assert (flag_pic); 1026 if (flag_pic == 1) 1027 { 1028 emit_insn (gen_add_got16 (temp_reg, 1029 tilepro_got_rtx (), orig)); 1030 } 1031 else 1032 { 1033 rtx temp_reg2 = create_temp_reg_if_possible (Pmode, reg); 1034 emit_insn (gen_addhi_got32 (temp_reg2, 1035 tilepro_got_rtx (), orig)); 1036 emit_insn (gen_addlo_got32 (temp_reg, temp_reg2, orig)); 1037 } 1038 1039 address = temp_reg; 1040 1041 pic_ref = gen_const_mem (Pmode, address); 1042 crtl->uses_pic_offset_table = 1; 1043 emit_move_insn (reg, pic_ref); 1044 /* The following put a REG_EQUAL note on this insn, so that 1045 it can be optimized by loop. But it causes the label to 1046 be optimized away. */ 1047 /* set_unique_reg_note (insn, REG_EQUAL, orig); */ 1048 return reg; 1049 } 1050 } 1051 else if (GET_CODE (orig) == CONST) 1052 { 1053 rtx base, offset; 1054 1055 if (GET_CODE (XEXP (orig, 0)) == PLUS 1056 && XEXP (XEXP (orig, 0), 0) == tilepro_got_rtx ()) 1057 return orig; 1058 1059 if (reg == 0) 1060 { 1061 gcc_assert (can_create_pseudo_p ()); 1062 reg = gen_reg_rtx (Pmode); 1063 } 1064 1065 gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS); 1066 base = tilepro_legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, 1067 reg); 1068 offset = 1069 tilepro_legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode, 1070 base == reg ? 0 : reg); 1071 1072 if (CONST_INT_P (offset)) 1073 { 1074 if (can_create_pseudo_p ()) 1075 offset = force_reg (Pmode, offset); 1076 else 1077 /* If we reach here, then something is seriously 1078 wrong. */ 1079 gcc_unreachable (); 1080 } 1081 1082 if (can_create_pseudo_p ()) 1083 return force_reg (Pmode, gen_rtx_PLUS (Pmode, base, offset)); 1084 else 1085 gcc_unreachable (); 1086 } 1087 else if (GET_CODE (orig) == LABEL_REF) 1088 { 1089 rtx address, temp_reg; 1090 rtx text_label_symbol; 1091 rtx text_label_rtx; 1092 1093 if (reg == 0) 1094 { 1095 gcc_assert (can_create_pseudo_p ()); 1096 reg = gen_reg_rtx (Pmode); 1097 } 1098 1099 /* If not during reload, allocate another temp reg here for 1100 loading in the address, so that these instructions can be 1101 optimized properly. */ 1102 temp_reg = create_temp_reg_if_possible (Pmode, reg); 1103 text_label_symbol = tilepro_text_label_symbol (); 1104 text_label_rtx = tilepro_text_label_rtx (); 1105 1106 emit_insn (gen_addli_pcrel (temp_reg, text_label_rtx, orig, 1107 text_label_symbol)); 1108 emit_insn (gen_auli_pcrel (temp_reg, temp_reg, orig, 1109 text_label_symbol)); 1110 1111 /* Note: this is conservative. We use the text_label but we 1112 don't use the pic_offset_table. */ 1113 crtl->uses_pic_offset_table = 1; 1114 1115 address = temp_reg; 1116 1117 emit_move_insn (reg, address); 1118 1119 return reg; 1120 } 1121 1122 return orig; 1123 } 1124 1125 1126 /* Implement TARGET_LEGITIMIZE_ADDRESS. */ 1127 static rtx 1128 tilepro_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, 1129 machine_mode mode) 1130 { 1131 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD 1132 && symbolic_operand (x, Pmode) && tilepro_tls_referenced_p (x)) 1133 { 1134 return tilepro_legitimize_tls_address (x); 1135 } 1136 else if (flag_pic) 1137 { 1138 return tilepro_legitimize_pic_address (x, mode, 0); 1139 } 1140 else 1141 return x; 1142 } 1143 1144 1145 /* Implement TARGET_DELEGITIMIZE_ADDRESS. */ 1146 static rtx 1147 tilepro_delegitimize_address (rtx x) 1148 { 1149 x = delegitimize_mem_from_attrs (x); 1150 1151 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == UNSPEC) 1152 { 1153 switch (XINT (XEXP (x, 0), 1)) 1154 { 1155 case UNSPEC_PCREL_SYM: 1156 case UNSPEC_GOT16_SYM: 1157 case UNSPEC_GOT32_SYM: 1158 case UNSPEC_TLS_GD: 1159 case UNSPEC_TLS_IE: 1160 x = XVECEXP (XEXP (x, 0), 0, 0); 1161 break; 1162 } 1163 } 1164 1165 return x; 1166 } 1167 1168 1169 /* Emit code to load the PIC register. */ 1170 static void 1171 load_pic_register (bool delay_pic_helper ATTRIBUTE_UNUSED) 1172 { 1173 int orig_flag_pic = flag_pic; 1174 1175 rtx got_symbol = tilepro_got_symbol (); 1176 rtx text_label_symbol = tilepro_text_label_symbol (); 1177 rtx text_label_rtx = tilepro_text_label_rtx (); 1178 flag_pic = 0; 1179 1180 emit_insn (gen_insn_lnk_and_label (text_label_rtx, text_label_symbol)); 1181 1182 emit_insn (gen_addli_pcrel (tilepro_got_rtx (), 1183 text_label_rtx, got_symbol, text_label_symbol)); 1184 1185 emit_insn (gen_auli_pcrel (tilepro_got_rtx (), 1186 tilepro_got_rtx (), 1187 got_symbol, text_label_symbol)); 1188 1189 flag_pic = orig_flag_pic; 1190 1191 /* Need to emit this whether or not we obey regdecls, since 1192 setjmp/longjmp can cause life info to screw up. ??? In the case 1193 where we don't obey regdecls, this is not sufficient since we may 1194 not fall out the bottom. */ 1195 emit_use (tilepro_got_rtx ()); 1196 } 1197 1198 1199 /* Return the simd variant of the constant NUM of mode MODE, by 1200 replicating it to fill an interger of mode SImode. NUM is first 1201 truncated to fit in MODE. */ 1202 rtx 1203 tilepro_simd_int (rtx num, machine_mode mode) 1204 { 1205 HOST_WIDE_INT n = 0; 1206 1207 gcc_assert (CONST_INT_P (num)); 1208 1209 n = INTVAL (num); 1210 1211 switch (mode) 1212 { 1213 case E_QImode: 1214 n = 0x01010101 * (n & 0x000000FF); 1215 break; 1216 case E_HImode: 1217 n = 0x00010001 * (n & 0x0000FFFF); 1218 break; 1219 case E_SImode: 1220 break; 1221 case E_DImode: 1222 break; 1223 default: 1224 gcc_unreachable (); 1225 } 1226 1227 return gen_int_si (n); 1228 } 1229 1230 1231 /* Split one or more DImode RTL references into pairs of SImode 1232 references. The RTL can be REG, offsettable MEM, integer constant, 1233 or CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL 1234 to split and "num" is its length. lo_half and hi_half are output 1235 arrays that parallel "operands". */ 1236 void 1237 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[]) 1238 { 1239 while (num--) 1240 { 1241 rtx op = operands[num]; 1242 1243 /* simplify_subreg refuse to split volatile memory addresses, 1244 but we still have to handle it. */ 1245 if (MEM_P (op)) 1246 { 1247 lo_half[num] = adjust_address (op, SImode, 0); 1248 hi_half[num] = adjust_address (op, SImode, 4); 1249 } 1250 else 1251 { 1252 lo_half[num] = simplify_gen_subreg (SImode, op, 1253 GET_MODE (op) == VOIDmode 1254 ? DImode : GET_MODE (op), 0); 1255 hi_half[num] = simplify_gen_subreg (SImode, op, 1256 GET_MODE (op) == VOIDmode 1257 ? DImode : GET_MODE (op), 4); 1258 } 1259 } 1260 } 1261 1262 1263 /* Returns true iff val can be moved into a register in one 1264 instruction. And if it can, it emits the code to move the 1265 constant. 1266 1267 If three_wide_only is true, this insists on an instruction that 1268 works in a bundle containing three instructions. */ 1269 static bool 1270 expand_set_cint32_one_inst (rtx dest_reg, 1271 HOST_WIDE_INT val, bool three_wide_only) 1272 { 1273 val = trunc_int_for_mode (val, SImode); 1274 1275 if (val == trunc_int_for_mode (val, QImode)) 1276 { 1277 /* Success! */ 1278 emit_move_insn (dest_reg, GEN_INT (val)); 1279 return true; 1280 } 1281 else if (!three_wide_only) 1282 { 1283 rtx imm_op = GEN_INT (val); 1284 1285 if (satisfies_constraint_J (imm_op) 1286 || satisfies_constraint_K (imm_op) 1287 || satisfies_constraint_N (imm_op) 1288 || satisfies_constraint_P (imm_op)) 1289 { 1290 emit_move_insn (dest_reg, imm_op); 1291 return true; 1292 } 1293 } 1294 1295 return false; 1296 } 1297 1298 1299 /* Implement SImode rotatert. */ 1300 static HOST_WIDE_INT 1301 rotate_right (HOST_WIDE_INT n, int count) 1302 { 1303 unsigned HOST_WIDE_INT x = n & 0xFFFFFFFF; 1304 if (count == 0) 1305 return x; 1306 return ((x >> count) | (x << (32 - count))) & 0xFFFFFFFF; 1307 } 1308 1309 1310 /* Return true iff n contains exactly one contiguous sequence of 1 1311 bits, possibly wrapping around from high bits to low bits. */ 1312 bool 1313 tilepro_bitfield_operand_p (HOST_WIDE_INT n, int *first_bit, int *last_bit) 1314 { 1315 int i; 1316 1317 if (n == 0) 1318 return false; 1319 1320 for (i = 0; i < 32; i++) 1321 { 1322 unsigned HOST_WIDE_INT x = rotate_right (n, i); 1323 if (!(x & 1)) 1324 continue; 1325 1326 /* See if x is a power of two minus one, i.e. only consecutive 1 1327 bits starting from bit 0. */ 1328 if ((x & (x + 1)) == 0) 1329 { 1330 if (first_bit != NULL) 1331 *first_bit = i; 1332 if (last_bit != NULL) 1333 *last_bit = (i + exact_log2 (x ^ (x >> 1))) & 31; 1334 1335 return true; 1336 } 1337 } 1338 1339 return false; 1340 } 1341 1342 1343 /* Create code to move the CONST_INT value in src_val to dest_reg. */ 1344 static void 1345 expand_set_cint32 (rtx dest_reg, rtx src_val) 1346 { 1347 HOST_WIDE_INT val; 1348 int leading_zeroes, trailing_zeroes; 1349 int lower, upper; 1350 int three_wide_only; 1351 rtx temp; 1352 1353 gcc_assert (CONST_INT_P (src_val)); 1354 val = trunc_int_for_mode (INTVAL (src_val), SImode); 1355 1356 /* See if we can generate the constant in one instruction. */ 1357 if (expand_set_cint32_one_inst (dest_reg, val, false)) 1358 return; 1359 1360 /* Create a temporary variable to hold a partial result, to enable 1361 CSE. */ 1362 temp = create_temp_reg_if_possible (SImode, dest_reg); 1363 1364 leading_zeroes = 31 - floor_log2 (val & 0xFFFFFFFF); 1365 trailing_zeroes = exact_log2 (val & -val); 1366 1367 lower = trunc_int_for_mode (val, HImode); 1368 upper = trunc_int_for_mode ((val - lower) >> 16, HImode); 1369 1370 /* First try all three-wide instructions that generate a constant 1371 (i.e. movei) followed by various shifts and rotates. If none of 1372 those work, try various two-wide ways of generating a constant 1373 followed by various shifts and rotates. */ 1374 for (three_wide_only = 1; three_wide_only >= 0; three_wide_only--) 1375 { 1376 int count; 1377 1378 if (expand_set_cint32_one_inst (temp, val >> trailing_zeroes, 1379 three_wide_only)) 1380 { 1381 /* 0xFFFFA500 becomes: 1382 movei temp, 0xFFFFFFA5 1383 shli dest, temp, 8 */ 1384 emit_move_insn (dest_reg, 1385 gen_rtx_ASHIFT (SImode, temp, 1386 GEN_INT (trailing_zeroes))); 1387 return; 1388 } 1389 1390 if (expand_set_cint32_one_inst (temp, val << leading_zeroes, 1391 three_wide_only)) 1392 { 1393 /* 0x7FFFFFFF becomes: 1394 movei temp, -2 1395 shri dest, temp, 1 */ 1396 emit_move_insn (dest_reg, 1397 gen_rtx_LSHIFTRT (SImode, temp, 1398 GEN_INT (leading_zeroes))); 1399 return; 1400 } 1401 1402 /* Try rotating a one-instruction immediate, since rotate is 1403 3-wide. */ 1404 for (count = 1; count < 32; count++) 1405 { 1406 HOST_WIDE_INT r = rotate_right (val, count); 1407 if (expand_set_cint32_one_inst (temp, r, three_wide_only)) 1408 { 1409 /* 0xFFA5FFFF becomes: 1410 movei temp, 0xFFFFFFA5 1411 rli dest, temp, 16 */ 1412 emit_move_insn (dest_reg, 1413 gen_rtx_ROTATE (SImode, temp, GEN_INT (count))); 1414 return; 1415 } 1416 } 1417 1418 if (lower == trunc_int_for_mode (lower, QImode)) 1419 { 1420 /* We failed to use two 3-wide instructions, but the low 16 1421 bits are a small number so just use a 2-wide + 3-wide 1422 auli + addi pair rather than anything more exotic. 1423 1424 0x12340056 becomes: 1425 auli temp, zero, 0x1234 1426 addi dest, temp, 0x56 */ 1427 break; 1428 } 1429 } 1430 1431 /* Fallback case: use a auli + addli/addi pair. */ 1432 emit_move_insn (temp, GEN_INT (upper << 16)); 1433 emit_move_insn (dest_reg, (gen_rtx_PLUS (SImode, temp, GEN_INT (lower)))); 1434 } 1435 1436 1437 /* Load OP1, a 32-bit constant, into OP0, a register. We know it 1438 can't be done in one insn when we get here, the move expander 1439 guarantees this. */ 1440 void 1441 tilepro_expand_set_const32 (rtx op0, rtx op1) 1442 { 1443 machine_mode mode = GET_MODE (op0); 1444 rtx temp; 1445 1446 if (CONST_INT_P (op1)) 1447 { 1448 /* TODO: I don't know if we want to split large constants now, 1449 or wait until later (with a define_split). 1450 1451 Does splitting early help CSE? Does it harm other 1452 optimizations that might fold loads? */ 1453 expand_set_cint32 (op0, op1); 1454 } 1455 else 1456 { 1457 temp = create_temp_reg_if_possible (mode, op0); 1458 1459 /* A symbol, emit in the traditional way. */ 1460 emit_move_insn (temp, gen_rtx_HIGH (mode, op1)); 1461 emit_move_insn (op0, gen_rtx_LO_SUM (mode, temp, op1)); 1462 } 1463 } 1464 1465 1466 /* Expand a move instruction. Return true if all work is done. */ 1467 bool 1468 tilepro_expand_mov (machine_mode mode, rtx *operands) 1469 { 1470 /* Handle sets of MEM first. */ 1471 if (MEM_P (operands[0])) 1472 { 1473 if (can_create_pseudo_p ()) 1474 operands[0] = validize_mem (operands[0]); 1475 1476 if (reg_or_0_operand (operands[1], mode)) 1477 return false; 1478 1479 if (!reload_in_progress) 1480 operands[1] = force_reg (mode, operands[1]); 1481 } 1482 1483 /* Fixup TLS cases. */ 1484 if (CONSTANT_P (operands[1]) && tilepro_tls_referenced_p (operands[1])) 1485 { 1486 operands[1] = tilepro_legitimize_tls_address (operands[1]); 1487 return false; 1488 } 1489 1490 /* Fixup PIC cases. */ 1491 if (flag_pic && CONSTANT_P (operands[1])) 1492 { 1493 if (tilepro_pic_address_needs_scratch (operands[1])) 1494 operands[1] = tilepro_legitimize_pic_address (operands[1], mode, 0); 1495 1496 if (symbolic_operand (operands[1], mode)) 1497 { 1498 operands[1] = tilepro_legitimize_pic_address (operands[1], 1499 mode, 1500 (reload_in_progress ? 1501 operands[0] : 1502 NULL_RTX)); 1503 return false; 1504 } 1505 } 1506 1507 /* Fixup for UNSPEC addresses. */ 1508 if (flag_pic 1509 && GET_CODE (operands[1]) == HIGH 1510 && GET_CODE (XEXP (operands[1], 0)) == CONST 1511 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == UNSPEC) 1512 { 1513 rtx unspec = XEXP (XEXP (operands[1], 0), 0); 1514 int unspec_num = XINT (unspec, 1); 1515 if (unspec_num == UNSPEC_PCREL_SYM) 1516 { 1517 emit_insn (gen_auli_pcrel (operands[0], const0_rtx, 1518 XVECEXP (unspec, 0, 0), 1519 XVECEXP (unspec, 0, 1))); 1520 return true; 1521 } 1522 else if (flag_pic == 2 && unspec_num == UNSPEC_GOT32_SYM) 1523 { 1524 emit_insn (gen_addhi_got32 (operands[0], const0_rtx, 1525 XVECEXP (unspec, 0, 0))); 1526 return true; 1527 } 1528 else if (HAVE_AS_TLS && unspec_num == UNSPEC_TLS_GD) 1529 { 1530 emit_insn (gen_tls_gd_addhi (operands[0], const0_rtx, 1531 XVECEXP (unspec, 0, 0))); 1532 return true; 1533 } 1534 else if (HAVE_AS_TLS && unspec_num == UNSPEC_TLS_IE) 1535 { 1536 emit_insn (gen_tls_ie_addhi (operands[0], const0_rtx, 1537 XVECEXP (unspec, 0, 0))); 1538 return true; 1539 } 1540 else if (HAVE_AS_TLS && unspec_num == UNSPEC_TLS_LE) 1541 { 1542 emit_insn (gen_tls_le_addhi (operands[0], const0_rtx, 1543 XVECEXP (unspec, 0, 0))); 1544 return true; 1545 } 1546 } 1547 1548 /* Accept non-constants and valid constants unmodified. */ 1549 if (!CONSTANT_P (operands[1]) 1550 || GET_CODE (operands[1]) == HIGH || move_operand (operands[1], mode)) 1551 return false; 1552 1553 /* Split large integers. */ 1554 if (GET_MODE_SIZE (mode) <= 4) 1555 { 1556 tilepro_expand_set_const32 (operands[0], operands[1]); 1557 return true; 1558 } 1559 1560 return false; 1561 } 1562 1563 1564 /* Expand the "insv" pattern. */ 1565 void 1566 tilepro_expand_insv (rtx operands[4]) 1567 { 1568 rtx first_rtx = operands[2]; 1569 HOST_WIDE_INT first = INTVAL (first_rtx); 1570 HOST_WIDE_INT width = INTVAL (operands[1]); 1571 rtx v = operands[3]; 1572 1573 /* Shift the inserted bits into position. */ 1574 if (first != 0) 1575 { 1576 if (CONST_INT_P (v)) 1577 { 1578 /* Shift the constant into mm position. */ 1579 v = gen_int_si (INTVAL (v) << first); 1580 } 1581 else 1582 { 1583 /* Shift over the value to be inserted. */ 1584 rtx tmp = gen_reg_rtx (SImode); 1585 emit_insn (gen_ashlsi3 (tmp, v, first_rtx)); 1586 v = tmp; 1587 } 1588 } 1589 1590 /* Insert the shifted bits using an 'mm' insn. */ 1591 emit_insn (gen_insn_mm (operands[0], v, operands[0], first_rtx, 1592 GEN_INT (first + width - 1))); 1593 } 1594 1595 1596 /* Expand unaligned loads. */ 1597 void 1598 tilepro_expand_unaligned_load (rtx dest_reg, rtx mem, HOST_WIDE_INT bitsize, 1599 HOST_WIDE_INT bit_offset, bool sign) 1600 { 1601 machine_mode mode; 1602 rtx addr_lo, addr_hi; 1603 rtx mem_lo, mem_hi, hi; 1604 rtx mema, wide_result; 1605 int last_byte_offset; 1606 HOST_WIDE_INT byte_offset = bit_offset / BITS_PER_UNIT; 1607 1608 mode = GET_MODE (dest_reg); 1609 1610 hi = gen_reg_rtx (mode); 1611 1612 if (bitsize == 2 * BITS_PER_UNIT && (bit_offset % BITS_PER_UNIT) == 0) 1613 { 1614 rtx lo; 1615 1616 /* When just loading a two byte value, we can load the two bytes 1617 individually and combine them efficiently. */ 1618 1619 mem_lo = adjust_address (mem, QImode, byte_offset); 1620 mem_hi = adjust_address (mem, QImode, byte_offset + 1); 1621 1622 lo = gen_reg_rtx (mode); 1623 emit_insn (gen_zero_extendqisi2 (lo, mem_lo)); 1624 1625 if (sign) 1626 { 1627 rtx tmp = gen_reg_rtx (mode); 1628 1629 /* Do a signed load of the second byte then shift and OR it 1630 in. */ 1631 emit_insn (gen_extendqisi2 (gen_lowpart (SImode, hi), mem_hi)); 1632 emit_insn (gen_ashlsi3 (gen_lowpart (SImode, tmp), 1633 gen_lowpart (SImode, hi), GEN_INT (8))); 1634 emit_insn (gen_iorsi3 (gen_lowpart (SImode, dest_reg), 1635 gen_lowpart (SImode, lo), 1636 gen_lowpart (SImode, tmp))); 1637 } 1638 else 1639 { 1640 /* Do two unsigned loads and use intlb to interleave 1641 them. */ 1642 emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, hi), mem_hi)); 1643 emit_insn (gen_insn_intlb (gen_lowpart (SImode, dest_reg), 1644 gen_lowpart (SImode, hi), 1645 gen_lowpart (SImode, lo))); 1646 } 1647 1648 return; 1649 } 1650 1651 mema = XEXP (mem, 0); 1652 1653 /* AND addresses cannot be in any alias set, since they may 1654 implicitly alias surrounding code. Ideally we'd have some alias 1655 set that covered all types except those with alignment 8 or 1656 higher. */ 1657 addr_lo = force_reg (Pmode, plus_constant (Pmode, mema, byte_offset)); 1658 mem_lo = change_address (mem, mode, 1659 gen_rtx_AND (Pmode, addr_lo, GEN_INT (-4))); 1660 set_mem_alias_set (mem_lo, 0); 1661 1662 /* Load the high word at an address that will not fault if the low 1663 address is aligned and at the very end of a page. */ 1664 last_byte_offset = (bit_offset + bitsize - 1) / BITS_PER_UNIT; 1665 addr_hi = force_reg (Pmode, plus_constant (Pmode, mema, last_byte_offset)); 1666 mem_hi = change_address (mem, mode, 1667 gen_rtx_AND (Pmode, addr_hi, GEN_INT (-4))); 1668 set_mem_alias_set (mem_hi, 0); 1669 1670 if (bitsize == 32) 1671 { 1672 addr_lo = make_safe_from (addr_lo, dest_reg); 1673 wide_result = dest_reg; 1674 } 1675 else 1676 { 1677 wide_result = gen_reg_rtx (mode); 1678 } 1679 1680 /* Load hi first in case dest_reg is used in mema. */ 1681 emit_move_insn (hi, mem_hi); 1682 emit_move_insn (wide_result, mem_lo); 1683 1684 emit_insn (gen_insn_dword_align (gen_lowpart (SImode, wide_result), 1685 gen_lowpart (SImode, wide_result), 1686 gen_lowpart (SImode, hi), addr_lo)); 1687 1688 if (bitsize != 32) 1689 { 1690 rtx extracted = 1691 extract_bit_field (gen_lowpart (SImode, wide_result), 1692 bitsize, bit_offset % BITS_PER_UNIT, 1693 !sign, gen_lowpart (SImode, dest_reg), 1694 SImode, SImode, false, NULL); 1695 1696 if (extracted != dest_reg) 1697 emit_move_insn (dest_reg, gen_lowpart (SImode, extracted)); 1698 } 1699 } 1700 1701 1702 /* Expand unaligned stores. */ 1703 static void 1704 tilepro_expand_unaligned_store (rtx mem, rtx src, HOST_WIDE_INT bitsize, 1705 HOST_WIDE_INT bit_offset) 1706 { 1707 HOST_WIDE_INT byte_offset = bit_offset / BITS_PER_UNIT; 1708 HOST_WIDE_INT bytesize = bitsize / BITS_PER_UNIT; 1709 HOST_WIDE_INT shift_amt; 1710 HOST_WIDE_INT i; 1711 rtx mem_addr; 1712 rtx store_val; 1713 1714 for (i = 0, shift_amt = 0; i < bytesize; i++, shift_amt += BITS_PER_UNIT) 1715 { 1716 mem_addr = adjust_address (mem, QImode, byte_offset + i); 1717 1718 if (shift_amt) 1719 { 1720 store_val = expand_simple_binop (SImode, LSHIFTRT, 1721 gen_lowpart (SImode, src), 1722 GEN_INT (shift_amt), NULL, 1, 1723 OPTAB_LIB_WIDEN); 1724 store_val = gen_lowpart (QImode, store_val); 1725 } 1726 else 1727 { 1728 store_val = gen_lowpart (QImode, src); 1729 } 1730 1731 emit_move_insn (mem_addr, store_val); 1732 } 1733 } 1734 1735 1736 /* Implement the movmisalign patterns. One of the operands is a 1737 memory that is not naturally aligned. Emit instructions to load 1738 it. */ 1739 void 1740 tilepro_expand_movmisalign (machine_mode mode, rtx *operands) 1741 { 1742 if (MEM_P (operands[1])) 1743 { 1744 rtx tmp; 1745 1746 if (register_operand (operands[0], mode)) 1747 tmp = operands[0]; 1748 else 1749 tmp = gen_reg_rtx (mode); 1750 1751 tilepro_expand_unaligned_load (tmp, operands[1], 1752 GET_MODE_BITSIZE (mode), 0, true); 1753 1754 if (tmp != operands[0]) 1755 emit_move_insn (operands[0], tmp); 1756 } 1757 else if (MEM_P (operands[0])) 1758 { 1759 if (!reg_or_0_operand (operands[1], mode)) 1760 operands[1] = force_reg (mode, operands[1]); 1761 1762 tilepro_expand_unaligned_store (operands[0], operands[1], 1763 GET_MODE_BITSIZE (mode), 0); 1764 } 1765 else 1766 gcc_unreachable (); 1767 } 1768 1769 1770 /* Implement the addsi3 pattern. */ 1771 bool 1772 tilepro_expand_addsi (rtx op0, rtx op1, rtx op2) 1773 { 1774 rtx temp; 1775 HOST_WIDE_INT n; 1776 HOST_WIDE_INT high; 1777 1778 /* Skip anything that only takes one instruction. */ 1779 if (add_operand (op2, SImode)) 1780 return false; 1781 1782 /* We can only optimize ints here (it should be impossible to get 1783 here with any other type, but it is harmless to check. */ 1784 if (!CONST_INT_P (op2)) 1785 return false; 1786 1787 temp = create_temp_reg_if_possible (SImode, op0); 1788 n = INTVAL (op2); 1789 high = (n + (n & 0x8000)) & ~0xffff; 1790 1791 emit_move_insn (temp, gen_rtx_PLUS (SImode, op1, gen_int_si (high))); 1792 emit_move_insn (op0, gen_rtx_PLUS (SImode, temp, gen_int_si (n - high))); 1793 1794 return true; 1795 } 1796 1797 1798 /* Implement the allocate_stack pattern (alloca). */ 1799 void 1800 tilepro_allocate_stack (rtx op0, rtx op1) 1801 { 1802 /* Technically the correct way to initialize chain_loc is with 1803 * gen_frame_mem() instead of gen_rtx_MEM(), but gen_frame_mem() 1804 * sets the alias_set to that of a frame reference. Some of our 1805 * tests rely on some unsafe assumption about when the chaining 1806 * update is done, we need to be conservative about reordering the 1807 * chaining instructions. 1808 */ 1809 rtx fp_addr = gen_reg_rtx (Pmode); 1810 rtx fp_value = gen_reg_rtx (Pmode); 1811 rtx fp_loc; 1812 1813 emit_move_insn (fp_addr, gen_rtx_PLUS (Pmode, stack_pointer_rtx, 1814 GEN_INT (UNITS_PER_WORD))); 1815 1816 fp_loc = gen_frame_mem (Pmode, fp_addr); 1817 1818 emit_move_insn (fp_value, fp_loc); 1819 1820 op1 = force_reg (Pmode, op1); 1821 1822 emit_move_insn (stack_pointer_rtx, 1823 gen_rtx_MINUS (Pmode, stack_pointer_rtx, op1)); 1824 1825 emit_move_insn (fp_addr, gen_rtx_PLUS (Pmode, stack_pointer_rtx, 1826 GEN_INT (UNITS_PER_WORD))); 1827 1828 fp_loc = gen_frame_mem (Pmode, fp_addr); 1829 1830 emit_move_insn (fp_loc, fp_value); 1831 1832 emit_move_insn (op0, virtual_stack_dynamic_rtx); 1833 } 1834 1835 1836 1837 /* Multiplies */ 1838 1839 /* Returns the insn_code in ENTRY. */ 1840 static enum insn_code 1841 tilepro_multiply_get_opcode (const struct tilepro_multiply_insn_seq_entry 1842 *entry) 1843 { 1844 return tilepro_multiply_insn_seq_decode_opcode[entry->compressed_opcode]; 1845 } 1846 1847 1848 /* Returns the length of the 'op' array. */ 1849 static int 1850 tilepro_multiply_get_num_ops (const struct tilepro_multiply_insn_seq *seq) 1851 { 1852 /* The array either uses all of its allocated slots or is terminated 1853 by a bogus opcode. Either way, the array size is the index of the 1854 last valid opcode plus one. */ 1855 int i; 1856 for (i = tilepro_multiply_insn_seq_MAX_OPERATIONS - 1; i >= 0; i--) 1857 if (tilepro_multiply_get_opcode (&seq->op[i]) != CODE_FOR_nothing) 1858 return i + 1; 1859 1860 /* An empty array is not allowed. */ 1861 gcc_unreachable (); 1862 } 1863 1864 1865 /* We precompute a number of expression trees for multiplying by 1866 constants. This generates code for such an expression tree by 1867 walking through the nodes in the tree (which are conveniently 1868 pre-linearized) and emitting an instruction for each one. */ 1869 static void 1870 tilepro_expand_constant_multiply_given_sequence (rtx result, rtx src, 1871 const struct 1872 tilepro_multiply_insn_seq 1873 *seq) 1874 { 1875 int i; 1876 int num_ops; 1877 1878 /* Keep track of the subexpressions computed so far, so later 1879 instructions can refer to them. We seed the array with zero and 1880 the value being multiplied. */ 1881 int num_subexprs = 2; 1882 rtx subexprs[tilepro_multiply_insn_seq_MAX_OPERATIONS + 2]; 1883 subexprs[0] = const0_rtx; 1884 subexprs[1] = src; 1885 1886 /* Determine how many instructions we are going to generate. */ 1887 num_ops = tilepro_multiply_get_num_ops (seq); 1888 gcc_assert (num_ops > 0 1889 && num_ops <= tilepro_multiply_insn_seq_MAX_OPERATIONS); 1890 1891 for (i = 0; i < num_ops; i++) 1892 { 1893 const struct tilepro_multiply_insn_seq_entry *entry = &seq->op[i]; 1894 1895 /* Figure out where to store the output of this instruction. */ 1896 const bool is_last_op = (i + 1 == num_ops); 1897 rtx out = is_last_op ? result : gen_reg_rtx (SImode); 1898 1899 enum insn_code opcode = tilepro_multiply_get_opcode (entry); 1900 if (opcode == CODE_FOR_ashlsi3) 1901 { 1902 /* Handle shift by immediate. This is a special case because 1903 the meaning of the second operand is a constant shift 1904 count rather than an operand index. */ 1905 1906 /* Make sure the shift count is in range. Zero should not 1907 happen. */ 1908 const int shift_count = entry->rhs; 1909 gcc_assert (shift_count > 0 && shift_count < 32); 1910 1911 /* Emit the actual instruction. */ 1912 emit_insn (GEN_FCN (opcode) 1913 (out, subexprs[entry->lhs], 1914 gen_rtx_CONST_INT (SImode, shift_count))); 1915 } 1916 else 1917 { 1918 /* Handle a normal two-operand instruction, such as add or 1919 s1a. */ 1920 1921 /* Make sure we are referring to a previously computed 1922 subexpression. */ 1923 gcc_assert (entry->rhs < num_subexprs); 1924 1925 /* Emit the actual instruction. */ 1926 emit_insn (GEN_FCN (opcode) 1927 (out, subexprs[entry->lhs], subexprs[entry->rhs])); 1928 } 1929 1930 /* Record this subexpression for use by later expressions. */ 1931 subexprs[num_subexprs++] = out; 1932 } 1933 } 1934 1935 1936 /* bsearch helper function. */ 1937 static int 1938 tilepro_compare_multipliers (const void *key, const void *t) 1939 { 1940 return *(const int *) key - 1941 ((const struct tilepro_multiply_insn_seq *) t)->multiplier; 1942 } 1943 1944 1945 /* Returns the tilepro_multiply_insn_seq for multiplier, or NULL if 1946 none exists. */ 1947 static const struct tilepro_multiply_insn_seq * 1948 tilepro_find_multiply_insn_seq_for_constant (int multiplier) 1949 { 1950 return ((const struct tilepro_multiply_insn_seq *) 1951 bsearch (&multiplier, tilepro_multiply_insn_seq_table, 1952 tilepro_multiply_insn_seq_table_size, 1953 sizeof tilepro_multiply_insn_seq_table[0], 1954 tilepro_compare_multipliers)); 1955 } 1956 1957 1958 /* Try to a expand constant multiply in SImode by looking it up in a 1959 precompiled table. OP0 is the result operand, OP1 is the source 1960 operand, and MULTIPLIER is the value of the constant. Return true 1961 if it succeeds. */ 1962 static bool 1963 tilepro_expand_const_mulsi (rtx op0, rtx op1, int multiplier) 1964 { 1965 /* See if we have precomputed an efficient way to multiply by this 1966 constant. */ 1967 const struct tilepro_multiply_insn_seq *seq = 1968 tilepro_find_multiply_insn_seq_for_constant (multiplier); 1969 if (seq != NULL) 1970 { 1971 tilepro_expand_constant_multiply_given_sequence (op0, op1, seq); 1972 return true; 1973 } 1974 else 1975 return false; 1976 } 1977 1978 1979 /* Expand the mulsi pattern. */ 1980 bool 1981 tilepro_expand_mulsi (rtx op0, rtx op1, rtx op2) 1982 { 1983 if (CONST_INT_P (op2)) 1984 { 1985 HOST_WIDE_INT n = trunc_int_for_mode (INTVAL (op2), SImode); 1986 return tilepro_expand_const_mulsi (op0, op1, n); 1987 } 1988 return false; 1989 } 1990 1991 1992 /* Expand a high multiply pattern in SImode. RESULT, OP1, OP2 are the 1993 operands, and SIGN is true if it's a signed multiply, and false if 1994 it's an unsigned multiply. */ 1995 static void 1996 tilepro_expand_high_multiply (rtx result, rtx op1, rtx op2, bool sign) 1997 { 1998 rtx tmp0 = gen_reg_rtx (SImode); 1999 rtx tmp1 = gen_reg_rtx (SImode); 2000 rtx tmp2 = gen_reg_rtx (SImode); 2001 rtx tmp3 = gen_reg_rtx (SImode); 2002 rtx tmp4 = gen_reg_rtx (SImode); 2003 rtx tmp5 = gen_reg_rtx (SImode); 2004 rtx tmp6 = gen_reg_rtx (SImode); 2005 rtx tmp7 = gen_reg_rtx (SImode); 2006 rtx tmp8 = gen_reg_rtx (SImode); 2007 rtx tmp9 = gen_reg_rtx (SImode); 2008 rtx tmp10 = gen_reg_rtx (SImode); 2009 rtx tmp11 = gen_reg_rtx (SImode); 2010 rtx tmp12 = gen_reg_rtx (SImode); 2011 rtx tmp13 = gen_reg_rtx (SImode); 2012 rtx result_lo = gen_reg_rtx (SImode); 2013 2014 if (sign) 2015 { 2016 emit_insn (gen_insn_mulhl_su (tmp0, op1, op2)); 2017 emit_insn (gen_insn_mulhl_su (tmp1, op2, op1)); 2018 emit_insn (gen_insn_mulll_uu (tmp2, op1, op2)); 2019 emit_insn (gen_insn_mulhh_ss (tmp3, op1, op2)); 2020 } 2021 else 2022 { 2023 emit_insn (gen_insn_mulhl_uu (tmp0, op1, op2)); 2024 emit_insn (gen_insn_mulhl_uu (tmp1, op2, op1)); 2025 emit_insn (gen_insn_mulll_uu (tmp2, op1, op2)); 2026 emit_insn (gen_insn_mulhh_uu (tmp3, op1, op2)); 2027 } 2028 2029 emit_move_insn (tmp4, (gen_rtx_ASHIFT (SImode, tmp0, GEN_INT (16)))); 2030 2031 emit_move_insn (tmp5, (gen_rtx_ASHIFT (SImode, tmp1, GEN_INT (16)))); 2032 2033 emit_move_insn (tmp6, (gen_rtx_PLUS (SImode, tmp4, tmp5))); 2034 emit_move_insn (result_lo, (gen_rtx_PLUS (SImode, tmp2, tmp6))); 2035 2036 emit_move_insn (tmp7, gen_rtx_LTU (SImode, tmp6, tmp4)); 2037 emit_move_insn (tmp8, gen_rtx_LTU (SImode, result_lo, tmp2)); 2038 2039 if (sign) 2040 { 2041 emit_move_insn (tmp9, (gen_rtx_ASHIFTRT (SImode, tmp0, GEN_INT (16)))); 2042 emit_move_insn (tmp10, (gen_rtx_ASHIFTRT (SImode, tmp1, GEN_INT (16)))); 2043 } 2044 else 2045 { 2046 emit_move_insn (tmp9, (gen_rtx_LSHIFTRT (SImode, tmp0, GEN_INT (16)))); 2047 emit_move_insn (tmp10, (gen_rtx_LSHIFTRT (SImode, tmp1, GEN_INT (16)))); 2048 } 2049 2050 emit_move_insn (tmp11, (gen_rtx_PLUS (SImode, tmp3, tmp7))); 2051 emit_move_insn (tmp12, (gen_rtx_PLUS (SImode, tmp8, tmp9))); 2052 emit_move_insn (tmp13, (gen_rtx_PLUS (SImode, tmp11, tmp12))); 2053 emit_move_insn (result, (gen_rtx_PLUS (SImode, tmp13, tmp10))); 2054 } 2055 2056 2057 /* Implement smulsi3_highpart. */ 2058 void 2059 tilepro_expand_smulsi3_highpart (rtx op0, rtx op1, rtx op2) 2060 { 2061 tilepro_expand_high_multiply (op0, op1, op2, true); 2062 } 2063 2064 2065 /* Implement umulsi3_highpart. */ 2066 void 2067 tilepro_expand_umulsi3_highpart (rtx op0, rtx op1, rtx op2) 2068 { 2069 tilepro_expand_high_multiply (op0, op1, op2, false); 2070 } 2071 2072 2073 2074 /* Compare and branches */ 2075 2076 /* Helper function to handle DImode for tilepro_emit_setcc_internal. */ 2077 static bool 2078 tilepro_emit_setcc_internal_di (rtx res, enum rtx_code code, rtx op0, rtx op1) 2079 { 2080 rtx operands[2], lo_half[2], hi_half[2]; 2081 rtx tmp, tmp0, tmp1, tmp2; 2082 bool swap = false; 2083 2084 /* Reduce the number of cases we need to handle by reversing the 2085 operands. */ 2086 switch (code) 2087 { 2088 case EQ: 2089 case NE: 2090 case LE: 2091 case LT: 2092 case LEU: 2093 case LTU: 2094 /* We handle these compares directly. */ 2095 break; 2096 2097 case GE: 2098 case GT: 2099 case GEU: 2100 case GTU: 2101 /* Reverse the operands. */ 2102 swap = true; 2103 break; 2104 2105 default: 2106 /* We should not have called this with any other code. */ 2107 gcc_unreachable (); 2108 } 2109 2110 if (swap) 2111 { 2112 code = swap_condition (code); 2113 tmp = op0, op0 = op1, op1 = tmp; 2114 } 2115 2116 operands[0] = op0; 2117 operands[1] = op1; 2118 2119 split_di (operands, 2, lo_half, hi_half); 2120 2121 if (!reg_or_0_operand (lo_half[0], SImode)) 2122 lo_half[0] = force_reg (SImode, lo_half[0]); 2123 2124 if (!reg_or_0_operand (hi_half[0], SImode)) 2125 hi_half[0] = force_reg (SImode, hi_half[0]); 2126 2127 if (!CONST_INT_P (lo_half[1]) && !register_operand (lo_half[1], SImode)) 2128 lo_half[1] = force_reg (SImode, lo_half[1]); 2129 2130 if (!CONST_INT_P (hi_half[1]) && !register_operand (hi_half[1], SImode)) 2131 hi_half[1] = force_reg (SImode, hi_half[1]); 2132 2133 tmp0 = gen_reg_rtx (SImode); 2134 tmp1 = gen_reg_rtx (SImode); 2135 tmp2 = gen_reg_rtx (SImode); 2136 2137 switch (code) 2138 { 2139 case EQ: 2140 emit_insn (gen_insn_seq (tmp0, lo_half[0], lo_half[1])); 2141 emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1])); 2142 emit_insn (gen_andsi3 (res, tmp0, tmp1)); 2143 return true; 2144 case NE: 2145 emit_insn (gen_insn_sne (tmp0, lo_half[0], lo_half[1])); 2146 emit_insn (gen_insn_sne (tmp1, hi_half[0], hi_half[1])); 2147 emit_insn (gen_iorsi3 (res, tmp0, tmp1)); 2148 return true; 2149 case LE: 2150 emit_insn (gen_insn_slte (tmp0, hi_half[0], hi_half[1])); 2151 emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1])); 2152 emit_insn (gen_insn_slte_u (tmp2, lo_half[0], lo_half[1])); 2153 emit_insn (gen_insn_mvnz (res, tmp0, tmp1, tmp2)); 2154 return true; 2155 case LT: 2156 if (operands[1] == const0_rtx) 2157 { 2158 emit_insn (gen_lshrsi3 (res, hi_half[0], GEN_INT (31))); 2159 return true; 2160 } 2161 else 2162 { 2163 emit_insn (gen_insn_slt (tmp0, hi_half[0], hi_half[1])); 2164 emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1])); 2165 emit_insn (gen_insn_slt_u (tmp2, lo_half[0], lo_half[1])); 2166 emit_insn (gen_insn_mvnz (res, tmp0, tmp1, tmp2)); 2167 } 2168 return true; 2169 case LEU: 2170 emit_insn (gen_insn_slte_u (tmp0, hi_half[0], hi_half[1])); 2171 emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1])); 2172 emit_insn (gen_insn_slte_u (tmp2, lo_half[0], lo_half[1])); 2173 emit_insn (gen_insn_mvnz (res, tmp0, tmp1, tmp2)); 2174 return true; 2175 case LTU: 2176 emit_insn (gen_insn_slt_u (tmp0, hi_half[0], hi_half[1])); 2177 emit_insn (gen_insn_seq (tmp1, hi_half[0], hi_half[1])); 2178 emit_insn (gen_insn_slt_u (tmp2, lo_half[0], lo_half[1])); 2179 emit_insn (gen_insn_mvnz (res, tmp0, tmp1, tmp2)); 2180 return true; 2181 default: 2182 gcc_unreachable (); 2183 } 2184 2185 return false; 2186 } 2187 2188 2189 /* Certain simplifications can be done to make invalid setcc 2190 operations valid. Return the final comparison, or NULL if we can't 2191 work. */ 2192 static bool 2193 tilepro_emit_setcc_internal (rtx res, enum rtx_code code, rtx op0, rtx op1, 2194 machine_mode cmp_mode) 2195 { 2196 rtx tmp; 2197 bool swap = false; 2198 2199 if (cmp_mode == DImode) 2200 { 2201 return tilepro_emit_setcc_internal_di (res, code, op0, op1); 2202 } 2203 2204 /* The general case: fold the comparison code to the types of 2205 compares that we have, choosing the branch as necessary. */ 2206 2207 switch (code) 2208 { 2209 case EQ: 2210 case NE: 2211 case LE: 2212 case LT: 2213 case LEU: 2214 case LTU: 2215 /* We have these compares. */ 2216 break; 2217 2218 case GE: 2219 case GT: 2220 case GEU: 2221 case GTU: 2222 /* We do not have these compares, so we reverse the 2223 operands. */ 2224 swap = true; 2225 break; 2226 2227 default: 2228 /* We should not have called this with any other code. */ 2229 gcc_unreachable (); 2230 } 2231 2232 if (swap) 2233 { 2234 code = swap_condition (code); 2235 tmp = op0, op0 = op1, op1 = tmp; 2236 } 2237 2238 if (!reg_or_0_operand (op0, SImode)) 2239 op0 = force_reg (SImode, op0); 2240 2241 if (!CONST_INT_P (op1) && !register_operand (op1, SImode)) 2242 op1 = force_reg (SImode, op1); 2243 2244 /* Return the setcc comparison. */ 2245 emit_insn (gen_rtx_SET (res, gen_rtx_fmt_ee (code, SImode, op0, op1))); 2246 2247 return true; 2248 } 2249 2250 2251 /* Implement cstore patterns. */ 2252 bool 2253 tilepro_emit_setcc (rtx operands[], machine_mode cmp_mode) 2254 { 2255 return 2256 tilepro_emit_setcc_internal (operands[0], GET_CODE (operands[1]), 2257 operands[2], operands[3], cmp_mode); 2258 } 2259 2260 2261 /* Return whether CODE is a signed comparison. */ 2262 static bool 2263 signed_compare_p (enum rtx_code code) 2264 { 2265 return (code == EQ || code == NE || code == LT || code == LE 2266 || code == GT || code == GE); 2267 } 2268 2269 2270 /* Generate the comparison for an SImode conditional branch. */ 2271 static rtx 2272 tilepro_emit_cc_test (enum rtx_code code, rtx op0, rtx op1, 2273 machine_mode cmp_mode, bool eq_ne_only) 2274 { 2275 enum rtx_code branch_code; 2276 rtx temp; 2277 2278 /* Check for a compare against zero using a comparison we can do 2279 directly. */ 2280 if (cmp_mode != DImode 2281 && op1 == const0_rtx 2282 && (code == EQ || code == NE 2283 || (!eq_ne_only && signed_compare_p (code)))) 2284 { 2285 op0 = force_reg (SImode, op0); 2286 return gen_rtx_fmt_ee (code, VOIDmode, op0, const0_rtx); 2287 } 2288 2289 /* The general case: fold the comparison code to the types of 2290 compares that we have, choosing the branch as necessary. */ 2291 switch (code) 2292 { 2293 case EQ: 2294 case LE: 2295 case LT: 2296 case LEU: 2297 case LTU: 2298 /* We have these compares. */ 2299 branch_code = NE; 2300 break; 2301 2302 case NE: 2303 case GE: 2304 case GT: 2305 case GEU: 2306 case GTU: 2307 /* These must be reversed (except NE, but let's 2308 canonicalize). */ 2309 code = reverse_condition (code); 2310 branch_code = EQ; 2311 break; 2312 2313 default: 2314 gcc_unreachable (); 2315 } 2316 2317 if (cmp_mode != DImode 2318 && CONST_INT_P (op1) && (!satisfies_constraint_I (op1) || code == LEU)) 2319 { 2320 HOST_WIDE_INT n = trunc_int_for_mode (INTVAL (op1), SImode); 2321 2322 switch (code) 2323 { 2324 case EQ: 2325 /* Subtract off the value we want to compare against and see 2326 if we get zero. This is cheaper than creating a constant 2327 in a register. Except that subtracting -128 is more 2328 expensive than seqi to -128, so we leave that alone. */ 2329 /* ??? Don't do this when comparing against symbols, 2330 otherwise we'll reduce (&x == 0x1234) to (&x-0x1234 == 2331 0), which will be declared false out of hand (at least 2332 for non-weak). */ 2333 if (!(symbolic_operand (op0, VOIDmode) 2334 || (REG_P (op0) && REG_POINTER (op0)))) 2335 { 2336 /* To compare against MIN_INT, we add MIN_INT and check 2337 for 0. */ 2338 HOST_WIDE_INT add; 2339 if (n != -2147483647 - 1) 2340 add = -n; 2341 else 2342 add = n; 2343 2344 op0 = force_reg (SImode, op0); 2345 temp = gen_reg_rtx (SImode); 2346 emit_insn (gen_addsi3 (temp, op0, gen_int_si (add))); 2347 return gen_rtx_fmt_ee (reverse_condition (branch_code), 2348 VOIDmode, temp, const0_rtx); 2349 } 2350 break; 2351 2352 case LEU: 2353 if (n == -1) 2354 break; 2355 /* FALLTHRU */ 2356 2357 case LTU: 2358 /* Change ((unsigned)x < 0x1000) into !((unsigned)x >> 12), 2359 etc. */ 2360 { 2361 int first = exact_log2 (code == LTU ? n : n + 1); 2362 if (first != -1) 2363 { 2364 op0 = force_reg (SImode, op0); 2365 temp = gen_reg_rtx (SImode); 2366 emit_move_insn (temp, 2367 gen_rtx_LSHIFTRT (SImode, op0, 2368 gen_int_si (first))); 2369 return gen_rtx_fmt_ee (reverse_condition (branch_code), 2370 VOIDmode, temp, const0_rtx); 2371 } 2372 } 2373 break; 2374 2375 default: 2376 break; 2377 } 2378 } 2379 2380 /* Compute a flag saying whether we should branch. */ 2381 temp = gen_reg_rtx (SImode); 2382 tilepro_emit_setcc_internal (temp, code, op0, op1, cmp_mode); 2383 2384 /* Return the branch comparison. */ 2385 return gen_rtx_fmt_ee (branch_code, VOIDmode, temp, const0_rtx); 2386 } 2387 2388 2389 /* Generate the comparison for a conditional branch. */ 2390 void 2391 tilepro_emit_conditional_branch (rtx operands[], machine_mode cmp_mode) 2392 { 2393 rtx cmp_rtx = 2394 tilepro_emit_cc_test (GET_CODE (operands[0]), operands[1], operands[2], 2395 cmp_mode, false); 2396 rtx branch_rtx = gen_rtx_SET (pc_rtx, 2397 gen_rtx_IF_THEN_ELSE (VOIDmode, cmp_rtx, 2398 gen_rtx_LABEL_REF 2399 (VOIDmode, 2400 operands[3]), 2401 pc_rtx)); 2402 emit_jump_insn (branch_rtx); 2403 } 2404 2405 2406 /* Implement the movsicc pattern. */ 2407 rtx 2408 tilepro_emit_conditional_move (rtx cmp) 2409 { 2410 return 2411 tilepro_emit_cc_test (GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1), 2412 GET_MODE (XEXP (cmp, 0)), true); 2413 } 2414 2415 2416 /* Return true if INSN is annotated with a REG_BR_PROB note that 2417 indicates it's a branch that's predicted taken. */ 2418 static bool 2419 cbranch_predicted_p (rtx_insn *insn) 2420 { 2421 rtx x = find_reg_note (insn, REG_BR_PROB, 0); 2422 2423 if (x) 2424 { 2425 return profile_probability::from_reg_br_prob_note (XINT (x, 0)) 2426 >= profile_probability::even (); 2427 } 2428 2429 return false; 2430 } 2431 2432 2433 /* Output assembly code for a specific branch instruction, appending 2434 the branch prediction flag to the opcode if appropriate. */ 2435 static const char * 2436 tilepro_output_simple_cbranch_with_opcode (rtx_insn *insn, const char *opcode, 2437 int regop, bool netreg_p, 2438 bool reverse_predicted) 2439 { 2440 static char buf[64]; 2441 sprintf (buf, "%s%s\t%%%c%d, %%l0", opcode, 2442 (cbranch_predicted_p (insn) ^ reverse_predicted) ? "t" : "", 2443 netreg_p ? 'N' : 'r', regop); 2444 return buf; 2445 } 2446 2447 2448 /* Output assembly code for a specific branch instruction, appending 2449 the branch prediction flag to the opcode if appropriate. */ 2450 const char * 2451 tilepro_output_cbranch_with_opcode (rtx_insn *insn, rtx *operands, 2452 const char *opcode, 2453 const char *rev_opcode, 2454 int regop, bool netreg_p) 2455 { 2456 const char *branch_if_false; 2457 rtx taken, not_taken; 2458 bool is_simple_branch; 2459 2460 gcc_assert (LABEL_P (operands[0])); 2461 2462 is_simple_branch = true; 2463 if (INSN_ADDRESSES_SET_P ()) 2464 { 2465 int from_addr = INSN_ADDRESSES (INSN_UID (insn)); 2466 int to_addr = INSN_ADDRESSES (INSN_UID (operands[0])); 2467 int delta = to_addr - from_addr; 2468 is_simple_branch = IN_RANGE (delta, -524288, 524280); 2469 } 2470 2471 if (is_simple_branch) 2472 { 2473 /* Just a simple conditional branch. */ 2474 return 2475 tilepro_output_simple_cbranch_with_opcode (insn, opcode, regop, 2476 netreg_p, false); 2477 } 2478 2479 /* Generate a reversed branch around a direct jump. This fallback 2480 does not use branch-likely instructions. */ 2481 not_taken = gen_label_rtx (); 2482 taken = operands[0]; 2483 2484 /* Generate the reversed branch to NOT_TAKEN. */ 2485 operands[0] = not_taken; 2486 branch_if_false = 2487 tilepro_output_simple_cbranch_with_opcode (insn, rev_opcode, regop, 2488 netreg_p, true); 2489 output_asm_insn (branch_if_false, operands); 2490 2491 output_asm_insn ("j\t%l0", &taken); 2492 2493 /* Output NOT_TAKEN. */ 2494 targetm.asm_out.internal_label (asm_out_file, "L", 2495 CODE_LABEL_NUMBER (not_taken)); 2496 return ""; 2497 } 2498 2499 2500 /* Output assembly code for a conditional branch instruction. */ 2501 const char * 2502 tilepro_output_cbranch (rtx_insn *insn, rtx *operands, bool reversed) 2503 { 2504 enum rtx_code code = GET_CODE (operands[1]); 2505 const char *opcode; 2506 const char *rev_opcode; 2507 2508 if (reversed) 2509 code = reverse_condition (code); 2510 2511 switch (code) 2512 { 2513 case NE: 2514 opcode = "bnz"; 2515 rev_opcode = "bz"; 2516 break; 2517 case EQ: 2518 opcode = "bz"; 2519 rev_opcode = "bnz"; 2520 break; 2521 case GE: 2522 opcode = "bgez"; 2523 rev_opcode = "blz"; 2524 break; 2525 case GT: 2526 opcode = "bgz"; 2527 rev_opcode = "blez"; 2528 break; 2529 case LE: 2530 opcode = "blez"; 2531 rev_opcode = "bgz"; 2532 break; 2533 case LT: 2534 opcode = "blz"; 2535 rev_opcode = "bgez"; 2536 break; 2537 default: 2538 gcc_unreachable (); 2539 } 2540 2541 return 2542 tilepro_output_cbranch_with_opcode (insn, operands, opcode, rev_opcode, 2543 2, false); 2544 } 2545 2546 2547 /* Implement the tablejump pattern. */ 2548 void 2549 tilepro_expand_tablejump (rtx op0, rtx op1) 2550 { 2551 if (flag_pic) 2552 { 2553 rtx table = gen_rtx_LABEL_REF (Pmode, op1); 2554 rtx temp = gen_reg_rtx (Pmode); 2555 rtx text_label_symbol = tilepro_text_label_symbol (); 2556 rtx text_label_rtx = tilepro_text_label_rtx (); 2557 2558 emit_insn (gen_addli_pcrel (temp, text_label_rtx, 2559 table, text_label_symbol)); 2560 emit_insn (gen_auli_pcrel (temp, temp, table, text_label_symbol)); 2561 emit_move_insn (temp, 2562 gen_rtx_PLUS (Pmode, 2563 convert_to_mode (Pmode, op0, false), 2564 temp)); 2565 op0 = temp; 2566 } 2567 2568 emit_jump_insn (gen_tablejump_aux (op0, op1)); 2569 } 2570 2571 2572 /* Expand a builtin vector binary op, by calling gen function GEN with 2573 operands in the proper modes. DEST is converted to DEST_MODE, and 2574 src0 and src1 (if DO_SRC1 is true) is converted to SRC_MODE. */ 2575 void 2576 tilepro_expand_builtin_vector_binop (rtx (*gen) (rtx, rtx, rtx), 2577 machine_mode dest_mode, 2578 rtx dest, 2579 machine_mode src_mode, 2580 rtx src0, rtx src1, bool do_src1) 2581 { 2582 dest = gen_lowpart (dest_mode, dest); 2583 2584 if (src0 == const0_rtx) 2585 src0 = CONST0_RTX (src_mode); 2586 else 2587 src0 = gen_lowpart (src_mode, src0); 2588 2589 if (do_src1) 2590 { 2591 if (src1 == const0_rtx) 2592 src1 = CONST0_RTX (src_mode); 2593 else 2594 src1 = gen_lowpart (src_mode, src1); 2595 } 2596 2597 emit_insn ((*gen) (dest, src0, src1)); 2598 } 2599 2600 2601 2602 /* Intrinsics */ 2603 2604 struct tile_builtin_info 2605 { 2606 enum insn_code icode; 2607 tree fndecl; 2608 }; 2609 2610 static struct tile_builtin_info tilepro_builtin_info[TILEPRO_BUILTIN_max] = { 2611 { CODE_FOR_addsi3, NULL }, /* add */ 2612 { CODE_FOR_insn_addb, NULL }, /* addb */ 2613 { CODE_FOR_insn_addbs_u, NULL }, /* addbs_u */ 2614 { CODE_FOR_insn_addh, NULL }, /* addh */ 2615 { CODE_FOR_insn_addhs, NULL }, /* addhs */ 2616 { CODE_FOR_insn_addib, NULL }, /* addib */ 2617 { CODE_FOR_insn_addih, NULL }, /* addih */ 2618 { CODE_FOR_insn_addlis, NULL }, /* addlis */ 2619 { CODE_FOR_ssaddsi3, NULL }, /* adds */ 2620 { CODE_FOR_insn_adiffb_u, NULL }, /* adiffb_u */ 2621 { CODE_FOR_insn_adiffh, NULL }, /* adiffh */ 2622 { CODE_FOR_andsi3, NULL }, /* and */ 2623 { CODE_FOR_insn_auli, NULL }, /* auli */ 2624 { CODE_FOR_insn_avgb_u, NULL }, /* avgb_u */ 2625 { CODE_FOR_insn_avgh, NULL }, /* avgh */ 2626 { CODE_FOR_insn_bitx, NULL }, /* bitx */ 2627 { CODE_FOR_bswapsi2, NULL }, /* bytex */ 2628 { CODE_FOR_clzsi2, NULL }, /* clz */ 2629 { CODE_FOR_insn_crc32_32, NULL }, /* crc32_32 */ 2630 { CODE_FOR_insn_crc32_8, NULL }, /* crc32_8 */ 2631 { CODE_FOR_ctzsi2, NULL }, /* ctz */ 2632 { CODE_FOR_insn_drain, NULL }, /* drain */ 2633 { CODE_FOR_insn_dtlbpr, NULL }, /* dtlbpr */ 2634 { CODE_FOR_insn_dword_align, NULL }, /* dword_align */ 2635 { CODE_FOR_insn_finv, NULL }, /* finv */ 2636 { CODE_FOR_insn_flush, NULL }, /* flush */ 2637 { CODE_FOR_insn_fnop, NULL }, /* fnop */ 2638 { CODE_FOR_insn_icoh, NULL }, /* icoh */ 2639 { CODE_FOR_insn_ill, NULL }, /* ill */ 2640 { CODE_FOR_insn_info, NULL }, /* info */ 2641 { CODE_FOR_insn_infol, NULL }, /* infol */ 2642 { CODE_FOR_insn_inthb, NULL }, /* inthb */ 2643 { CODE_FOR_insn_inthh, NULL }, /* inthh */ 2644 { CODE_FOR_insn_intlb, NULL }, /* intlb */ 2645 { CODE_FOR_insn_intlh, NULL }, /* intlh */ 2646 { CODE_FOR_insn_inv, NULL }, /* inv */ 2647 { CODE_FOR_insn_lb, NULL }, /* lb */ 2648 { CODE_FOR_insn_lb_u, NULL }, /* lb_u */ 2649 { CODE_FOR_insn_lh, NULL }, /* lh */ 2650 { CODE_FOR_insn_lh_u, NULL }, /* lh_u */ 2651 { CODE_FOR_insn_lnk, NULL }, /* lnk */ 2652 { CODE_FOR_insn_lw, NULL }, /* lw */ 2653 { CODE_FOR_insn_lw_na, NULL }, /* lw_na */ 2654 { CODE_FOR_insn_lb_L2, NULL }, /* lb_L2 */ 2655 { CODE_FOR_insn_lb_u_L2, NULL }, /* lb_u_L2 */ 2656 { CODE_FOR_insn_lh_L2, NULL }, /* lh_L2 */ 2657 { CODE_FOR_insn_lh_u_L2, NULL }, /* lh_u_L2 */ 2658 { CODE_FOR_insn_lw_L2, NULL }, /* lw_L2 */ 2659 { CODE_FOR_insn_lw_na_L2, NULL }, /* lw_na_L2 */ 2660 { CODE_FOR_insn_lb_miss, NULL }, /* lb_miss */ 2661 { CODE_FOR_insn_lb_u_miss, NULL }, /* lb_u_miss */ 2662 { CODE_FOR_insn_lh_miss, NULL }, /* lh_miss */ 2663 { CODE_FOR_insn_lh_u_miss, NULL }, /* lh_u_miss */ 2664 { CODE_FOR_insn_lw_miss, NULL }, /* lw_miss */ 2665 { CODE_FOR_insn_lw_na_miss, NULL }, /* lw_na_miss */ 2666 { CODE_FOR_insn_maxb_u, NULL }, /* maxb_u */ 2667 { CODE_FOR_insn_maxh, NULL }, /* maxh */ 2668 { CODE_FOR_insn_maxib_u, NULL }, /* maxib_u */ 2669 { CODE_FOR_insn_maxih, NULL }, /* maxih */ 2670 { CODE_FOR_memory_barrier, NULL }, /* mf */ 2671 { CODE_FOR_insn_mfspr, NULL }, /* mfspr */ 2672 { CODE_FOR_insn_minb_u, NULL }, /* minb_u */ 2673 { CODE_FOR_insn_minh, NULL }, /* minh */ 2674 { CODE_FOR_insn_minib_u, NULL }, /* minib_u */ 2675 { CODE_FOR_insn_minih, NULL }, /* minih */ 2676 { CODE_FOR_insn_mm, NULL }, /* mm */ 2677 { CODE_FOR_insn_mnz, NULL }, /* mnz */ 2678 { CODE_FOR_insn_mnzb, NULL }, /* mnzb */ 2679 { CODE_FOR_insn_mnzh, NULL }, /* mnzh */ 2680 { CODE_FOR_movsi, NULL }, /* move */ 2681 { CODE_FOR_insn_movelis, NULL }, /* movelis */ 2682 { CODE_FOR_insn_mtspr, NULL }, /* mtspr */ 2683 { CODE_FOR_insn_mulhh_ss, NULL }, /* mulhh_ss */ 2684 { CODE_FOR_insn_mulhh_su, NULL }, /* mulhh_su */ 2685 { CODE_FOR_insn_mulhh_uu, NULL }, /* mulhh_uu */ 2686 { CODE_FOR_insn_mulhha_ss, NULL }, /* mulhha_ss */ 2687 { CODE_FOR_insn_mulhha_su, NULL }, /* mulhha_su */ 2688 { CODE_FOR_insn_mulhha_uu, NULL }, /* mulhha_uu */ 2689 { CODE_FOR_insn_mulhhsa_uu, NULL }, /* mulhhsa_uu */ 2690 { CODE_FOR_insn_mulhl_ss, NULL }, /* mulhl_ss */ 2691 { CODE_FOR_insn_mulhl_su, NULL }, /* mulhl_su */ 2692 { CODE_FOR_insn_mulhl_us, NULL }, /* mulhl_us */ 2693 { CODE_FOR_insn_mulhl_uu, NULL }, /* mulhl_uu */ 2694 { CODE_FOR_insn_mulhla_ss, NULL }, /* mulhla_ss */ 2695 { CODE_FOR_insn_mulhla_su, NULL }, /* mulhla_su */ 2696 { CODE_FOR_insn_mulhla_us, NULL }, /* mulhla_us */ 2697 { CODE_FOR_insn_mulhla_uu, NULL }, /* mulhla_uu */ 2698 { CODE_FOR_insn_mulhlsa_uu, NULL }, /* mulhlsa_uu */ 2699 { CODE_FOR_insn_mulll_ss, NULL }, /* mulll_ss */ 2700 { CODE_FOR_insn_mulll_su, NULL }, /* mulll_su */ 2701 { CODE_FOR_insn_mulll_uu, NULL }, /* mulll_uu */ 2702 { CODE_FOR_insn_mullla_ss, NULL }, /* mullla_ss */ 2703 { CODE_FOR_insn_mullla_su, NULL }, /* mullla_su */ 2704 { CODE_FOR_insn_mullla_uu, NULL }, /* mullla_uu */ 2705 { CODE_FOR_insn_mulllsa_uu, NULL }, /* mulllsa_uu */ 2706 { CODE_FOR_insn_mvnz, NULL }, /* mvnz */ 2707 { CODE_FOR_insn_mvz, NULL }, /* mvz */ 2708 { CODE_FOR_insn_mz, NULL }, /* mz */ 2709 { CODE_FOR_insn_mzb, NULL }, /* mzb */ 2710 { CODE_FOR_insn_mzh, NULL }, /* mzh */ 2711 { CODE_FOR_insn_nap, NULL }, /* nap */ 2712 { CODE_FOR_nop, NULL }, /* nop */ 2713 { CODE_FOR_insn_nor, NULL }, /* nor */ 2714 { CODE_FOR_iorsi3, NULL }, /* or */ 2715 { CODE_FOR_insn_packbs_u, NULL }, /* packbs_u */ 2716 { CODE_FOR_insn_packhb, NULL }, /* packhb */ 2717 { CODE_FOR_insn_packhs, NULL }, /* packhs */ 2718 { CODE_FOR_insn_packlb, NULL }, /* packlb */ 2719 { CODE_FOR_popcountsi2, NULL }, /* pcnt */ 2720 { CODE_FOR_insn_prefetch, NULL }, /* prefetch */ 2721 { CODE_FOR_insn_prefetch_L1, NULL }, /* prefetch_L1 */ 2722 { CODE_FOR_rotlsi3, NULL }, /* rl */ 2723 { CODE_FOR_insn_s1a, NULL }, /* s1a */ 2724 { CODE_FOR_insn_s2a, NULL }, /* s2a */ 2725 { CODE_FOR_insn_s3a, NULL }, /* s3a */ 2726 { CODE_FOR_insn_sadab_u, NULL }, /* sadab_u */ 2727 { CODE_FOR_insn_sadah, NULL }, /* sadah */ 2728 { CODE_FOR_insn_sadah_u, NULL }, /* sadah_u */ 2729 { CODE_FOR_insn_sadb_u, NULL }, /* sadb_u */ 2730 { CODE_FOR_insn_sadh, NULL }, /* sadh */ 2731 { CODE_FOR_insn_sadh_u, NULL }, /* sadh_u */ 2732 { CODE_FOR_insn_sb, NULL }, /* sb */ 2733 { CODE_FOR_insn_seq, NULL }, /* seq */ 2734 { CODE_FOR_insn_seqb, NULL }, /* seqb */ 2735 { CODE_FOR_insn_seqh, NULL }, /* seqh */ 2736 { CODE_FOR_insn_seqib, NULL }, /* seqib */ 2737 { CODE_FOR_insn_seqih, NULL }, /* seqih */ 2738 { CODE_FOR_insn_sh, NULL }, /* sh */ 2739 { CODE_FOR_ashlsi3, NULL }, /* shl */ 2740 { CODE_FOR_insn_shlb, NULL }, /* shlb */ 2741 { CODE_FOR_insn_shlh, NULL }, /* shlh */ 2742 { CODE_FOR_insn_shlb, NULL }, /* shlib */ 2743 { CODE_FOR_insn_shlh, NULL }, /* shlih */ 2744 { CODE_FOR_lshrsi3, NULL }, /* shr */ 2745 { CODE_FOR_insn_shrb, NULL }, /* shrb */ 2746 { CODE_FOR_insn_shrh, NULL }, /* shrh */ 2747 { CODE_FOR_insn_shrb, NULL }, /* shrib */ 2748 { CODE_FOR_insn_shrh, NULL }, /* shrih */ 2749 { CODE_FOR_insn_slt, NULL }, /* slt */ 2750 { CODE_FOR_insn_slt_u, NULL }, /* slt_u */ 2751 { CODE_FOR_insn_sltb, NULL }, /* sltb */ 2752 { CODE_FOR_insn_sltb_u, NULL }, /* sltb_u */ 2753 { CODE_FOR_insn_slte, NULL }, /* slte */ 2754 { CODE_FOR_insn_slte_u, NULL }, /* slte_u */ 2755 { CODE_FOR_insn_slteb, NULL }, /* slteb */ 2756 { CODE_FOR_insn_slteb_u, NULL }, /* slteb_u */ 2757 { CODE_FOR_insn_slteh, NULL }, /* slteh */ 2758 { CODE_FOR_insn_slteh_u, NULL }, /* slteh_u */ 2759 { CODE_FOR_insn_slth, NULL }, /* slth */ 2760 { CODE_FOR_insn_slth_u, NULL }, /* slth_u */ 2761 { CODE_FOR_insn_sltib, NULL }, /* sltib */ 2762 { CODE_FOR_insn_sltib_u, NULL }, /* sltib_u */ 2763 { CODE_FOR_insn_sltih, NULL }, /* sltih */ 2764 { CODE_FOR_insn_sltih_u, NULL }, /* sltih_u */ 2765 { CODE_FOR_insn_sne, NULL }, /* sne */ 2766 { CODE_FOR_insn_sneb, NULL }, /* sneb */ 2767 { CODE_FOR_insn_sneh, NULL }, /* sneh */ 2768 { CODE_FOR_ashrsi3, NULL }, /* sra */ 2769 { CODE_FOR_insn_srab, NULL }, /* srab */ 2770 { CODE_FOR_insn_srah, NULL }, /* srah */ 2771 { CODE_FOR_insn_srab, NULL }, /* sraib */ 2772 { CODE_FOR_insn_srah, NULL }, /* sraih */ 2773 { CODE_FOR_subsi3, NULL }, /* sub */ 2774 { CODE_FOR_insn_subb, NULL }, /* subb */ 2775 { CODE_FOR_insn_subbs_u, NULL }, /* subbs_u */ 2776 { CODE_FOR_insn_subh, NULL }, /* subh */ 2777 { CODE_FOR_insn_subhs, NULL }, /* subhs */ 2778 { CODE_FOR_sssubsi3, NULL }, /* subs */ 2779 { CODE_FOR_insn_sw, NULL }, /* sw */ 2780 { CODE_FOR_insn_tblidxb0, NULL }, /* tblidxb0 */ 2781 { CODE_FOR_insn_tblidxb1, NULL }, /* tblidxb1 */ 2782 { CODE_FOR_insn_tblidxb2, NULL }, /* tblidxb2 */ 2783 { CODE_FOR_insn_tblidxb3, NULL }, /* tblidxb3 */ 2784 { CODE_FOR_insn_tns, NULL }, /* tns */ 2785 { CODE_FOR_insn_wh64, NULL }, /* wh64 */ 2786 { CODE_FOR_xorsi3, NULL }, /* xor */ 2787 { CODE_FOR_tilepro_network_barrier, NULL }, /* network_barrier */ 2788 { CODE_FOR_tilepro_idn0_receive, NULL }, /* idn0_receive */ 2789 { CODE_FOR_tilepro_idn1_receive, NULL }, /* idn1_receive */ 2790 { CODE_FOR_tilepro_idn_send, NULL }, /* idn_send */ 2791 { CODE_FOR_tilepro_sn_receive, NULL }, /* sn_receive */ 2792 { CODE_FOR_tilepro_sn_send, NULL }, /* sn_send */ 2793 { CODE_FOR_tilepro_udn0_receive, NULL }, /* udn0_receive */ 2794 { CODE_FOR_tilepro_udn1_receive, NULL }, /* udn1_receive */ 2795 { CODE_FOR_tilepro_udn2_receive, NULL }, /* udn2_receive */ 2796 { CODE_FOR_tilepro_udn3_receive, NULL }, /* udn3_receive */ 2797 { CODE_FOR_tilepro_udn_send, NULL }, /* udn_send */ 2798 }; 2799 2800 2801 struct tilepro_builtin_def 2802 { 2803 const char *name; 2804 enum tilepro_builtin code; 2805 bool is_const; 2806 /* The first character is the return type. Subsequent characters 2807 are the argument types. See char_to_type. */ 2808 const char *type; 2809 }; 2810 2811 2812 static const struct tilepro_builtin_def tilepro_builtins[] = { 2813 { "__insn_add", TILEPRO_INSN_ADD, true, "lll" }, 2814 { "__insn_addb", TILEPRO_INSN_ADDB, true, "lll" }, 2815 { "__insn_addbs_u", TILEPRO_INSN_ADDBS_U, false, "lll" }, 2816 { "__insn_addh", TILEPRO_INSN_ADDH, true, "lll" }, 2817 { "__insn_addhs", TILEPRO_INSN_ADDHS, false, "lll" }, 2818 { "__insn_addi", TILEPRO_INSN_ADD, true, "lll" }, 2819 { "__insn_addib", TILEPRO_INSN_ADDIB, true, "lll" }, 2820 { "__insn_addih", TILEPRO_INSN_ADDIH, true, "lll" }, 2821 { "__insn_addli", TILEPRO_INSN_ADD, true, "lll" }, 2822 { "__insn_addlis", TILEPRO_INSN_ADDLIS, false, "lll" }, 2823 { "__insn_adds", TILEPRO_INSN_ADDS, false, "lll" }, 2824 { "__insn_adiffb_u", TILEPRO_INSN_ADIFFB_U, true, "lll" }, 2825 { "__insn_adiffh", TILEPRO_INSN_ADIFFH, true, "lll" }, 2826 { "__insn_and", TILEPRO_INSN_AND, true, "lll" }, 2827 { "__insn_andi", TILEPRO_INSN_AND, true, "lll" }, 2828 { "__insn_auli", TILEPRO_INSN_AULI, true, "lll" }, 2829 { "__insn_avgb_u", TILEPRO_INSN_AVGB_U, true, "lll" }, 2830 { "__insn_avgh", TILEPRO_INSN_AVGH, true, "lll" }, 2831 { "__insn_bitx", TILEPRO_INSN_BITX, true, "ll" }, 2832 { "__insn_bytex", TILEPRO_INSN_BYTEX, true, "ll" }, 2833 { "__insn_clz", TILEPRO_INSN_CLZ, true, "ll" }, 2834 { "__insn_crc32_32", TILEPRO_INSN_CRC32_32, true, "lll" }, 2835 { "__insn_crc32_8", TILEPRO_INSN_CRC32_8, true, "lll" }, 2836 { "__insn_ctz", TILEPRO_INSN_CTZ, true, "ll" }, 2837 { "__insn_drain", TILEPRO_INSN_DRAIN, false, "v" }, 2838 { "__insn_dtlbpr", TILEPRO_INSN_DTLBPR, false, "vl" }, 2839 { "__insn_dword_align", TILEPRO_INSN_DWORD_ALIGN, true, "lllk" }, 2840 { "__insn_finv", TILEPRO_INSN_FINV, false, "vk" }, 2841 { "__insn_flush", TILEPRO_INSN_FLUSH, false, "vk" }, 2842 { "__insn_fnop", TILEPRO_INSN_FNOP, false, "v" }, 2843 { "__insn_icoh", TILEPRO_INSN_ICOH, false, "vk" }, 2844 { "__insn_ill", TILEPRO_INSN_ILL, false, "v" }, 2845 { "__insn_info", TILEPRO_INSN_INFO, false, "vl" }, 2846 { "__insn_infol", TILEPRO_INSN_INFOL, false, "vl" }, 2847 { "__insn_inthb", TILEPRO_INSN_INTHB, true, "lll" }, 2848 { "__insn_inthh", TILEPRO_INSN_INTHH, true, "lll" }, 2849 { "__insn_intlb", TILEPRO_INSN_INTLB, true, "lll" }, 2850 { "__insn_intlh", TILEPRO_INSN_INTLH, true, "lll" }, 2851 { "__insn_inv", TILEPRO_INSN_INV, false, "vp" }, 2852 { "__insn_lb", TILEPRO_INSN_LB, false, "lk" }, 2853 { "__insn_lb_u", TILEPRO_INSN_LB_U, false, "lk" }, 2854 { "__insn_lh", TILEPRO_INSN_LH, false, "lk" }, 2855 { "__insn_lh_u", TILEPRO_INSN_LH_U, false, "lk" }, 2856 { "__insn_lnk", TILEPRO_INSN_LNK, true, "l" }, 2857 { "__insn_lw", TILEPRO_INSN_LW, false, "lk" }, 2858 { "__insn_lw_na", TILEPRO_INSN_LW_NA, false, "lk" }, 2859 { "__insn_lb_L2", TILEPRO_INSN_LB_L2, false, "lk" }, 2860 { "__insn_lb_u_L2", TILEPRO_INSN_LB_U_L2, false, "lk" }, 2861 { "__insn_lh_L2", TILEPRO_INSN_LH_L2, false, "lk" }, 2862 { "__insn_lh_u_L2", TILEPRO_INSN_LH_U_L2, false, "lk" }, 2863 { "__insn_lw_L2", TILEPRO_INSN_LW_L2, false, "lk" }, 2864 { "__insn_lw_na_L2", TILEPRO_INSN_LW_NA_L2, false, "lk" }, 2865 { "__insn_lb_miss", TILEPRO_INSN_LB_MISS, false, "lk" }, 2866 { "__insn_lb_u_miss", TILEPRO_INSN_LB_U_MISS, false, "lk" }, 2867 { "__insn_lh_miss", TILEPRO_INSN_LH_MISS, false, "lk" }, 2868 { "__insn_lh_u_miss", TILEPRO_INSN_LH_U_MISS, false, "lk" }, 2869 { "__insn_lw_miss", TILEPRO_INSN_LW_MISS, false, "lk" }, 2870 { "__insn_lw_na_miss", TILEPRO_INSN_LW_NA_MISS, false, "lk" }, 2871 { "__insn_maxb_u", TILEPRO_INSN_MAXB_U, true, "lll" }, 2872 { "__insn_maxh", TILEPRO_INSN_MAXH, true, "lll" }, 2873 { "__insn_maxib_u", TILEPRO_INSN_MAXIB_U, true, "lll" }, 2874 { "__insn_maxih", TILEPRO_INSN_MAXIH, true, "lll" }, 2875 { "__insn_mf", TILEPRO_INSN_MF, false, "v" }, 2876 { "__insn_mfspr", TILEPRO_INSN_MFSPR, false, "ll" }, 2877 { "__insn_minb_u", TILEPRO_INSN_MINB_U, true, "lll" }, 2878 { "__insn_minh", TILEPRO_INSN_MINH, true, "lll" }, 2879 { "__insn_minib_u", TILEPRO_INSN_MINIB_U, true, "lll" }, 2880 { "__insn_minih", TILEPRO_INSN_MINIH, true, "lll" }, 2881 { "__insn_mm", TILEPRO_INSN_MM, true, "lllll" }, 2882 { "__insn_mnz", TILEPRO_INSN_MNZ, true, "lll" }, 2883 { "__insn_mnzb", TILEPRO_INSN_MNZB, true, "lll" }, 2884 { "__insn_mnzh", TILEPRO_INSN_MNZH, true, "lll" }, 2885 { "__insn_move", TILEPRO_INSN_MOVE, true, "ll" }, 2886 { "__insn_movei", TILEPRO_INSN_MOVE, true, "ll" }, 2887 { "__insn_moveli", TILEPRO_INSN_MOVE, true, "ll" }, 2888 { "__insn_movelis", TILEPRO_INSN_MOVELIS, false, "ll" }, 2889 { "__insn_mtspr", TILEPRO_INSN_MTSPR, false, "vll" }, 2890 { "__insn_mulhh_ss", TILEPRO_INSN_MULHH_SS, true, "lll" }, 2891 { "__insn_mulhh_su", TILEPRO_INSN_MULHH_SU, true, "lll" }, 2892 { "__insn_mulhh_uu", TILEPRO_INSN_MULHH_UU, true, "lll" }, 2893 { "__insn_mulhha_ss", TILEPRO_INSN_MULHHA_SS, true, "llll" }, 2894 { "__insn_mulhha_su", TILEPRO_INSN_MULHHA_SU, true, "llll" }, 2895 { "__insn_mulhha_uu", TILEPRO_INSN_MULHHA_UU, true, "llll" }, 2896 { "__insn_mulhhsa_uu", TILEPRO_INSN_MULHHSA_UU, true, "llll" }, 2897 { "__insn_mulhl_ss", TILEPRO_INSN_MULHL_SS, true, "lll" }, 2898 { "__insn_mulhl_su", TILEPRO_INSN_MULHL_SU, true, "lll" }, 2899 { "__insn_mulhl_us", TILEPRO_INSN_MULHL_US, true, "lll" }, 2900 { "__insn_mulhl_uu", TILEPRO_INSN_MULHL_UU, true, "lll" }, 2901 { "__insn_mulhla_ss", TILEPRO_INSN_MULHLA_SS, true, "llll" }, 2902 { "__insn_mulhla_su", TILEPRO_INSN_MULHLA_SU, true, "llll" }, 2903 { "__insn_mulhla_us", TILEPRO_INSN_MULHLA_US, true, "llll" }, 2904 { "__insn_mulhla_uu", TILEPRO_INSN_MULHLA_UU, true, "llll" }, 2905 { "__insn_mulhlsa_uu", TILEPRO_INSN_MULHLSA_UU, true, "llll" }, 2906 { "__insn_mulll_ss", TILEPRO_INSN_MULLL_SS, true, "lll" }, 2907 { "__insn_mulll_su", TILEPRO_INSN_MULLL_SU, true, "lll" }, 2908 { "__insn_mulll_uu", TILEPRO_INSN_MULLL_UU, true, "lll" }, 2909 { "__insn_mullla_ss", TILEPRO_INSN_MULLLA_SS, true, "llll" }, 2910 { "__insn_mullla_su", TILEPRO_INSN_MULLLA_SU, true, "llll" }, 2911 { "__insn_mullla_uu", TILEPRO_INSN_MULLLA_UU, true, "llll" }, 2912 { "__insn_mulllsa_uu", TILEPRO_INSN_MULLLSA_UU, true, "llll" }, 2913 { "__insn_mvnz", TILEPRO_INSN_MVNZ, true, "llll" }, 2914 { "__insn_mvz", TILEPRO_INSN_MVZ, true, "llll" }, 2915 { "__insn_mz", TILEPRO_INSN_MZ, true, "lll" }, 2916 { "__insn_mzb", TILEPRO_INSN_MZB, true, "lll" }, 2917 { "__insn_mzh", TILEPRO_INSN_MZH, true, "lll" }, 2918 { "__insn_nap", TILEPRO_INSN_NAP, false, "v" }, 2919 { "__insn_nop", TILEPRO_INSN_NOP, true, "v" }, 2920 { "__insn_nor", TILEPRO_INSN_NOR, true, "lll" }, 2921 { "__insn_or", TILEPRO_INSN_OR, true, "lll" }, 2922 { "__insn_ori", TILEPRO_INSN_OR, true, "lll" }, 2923 { "__insn_packbs_u", TILEPRO_INSN_PACKBS_U, false, "lll" }, 2924 { "__insn_packhb", TILEPRO_INSN_PACKHB, true, "lll" }, 2925 { "__insn_packhs", TILEPRO_INSN_PACKHS, false, "lll" }, 2926 { "__insn_packlb", TILEPRO_INSN_PACKLB, true, "lll" }, 2927 { "__insn_pcnt", TILEPRO_INSN_PCNT, true, "ll" }, 2928 { "__insn_prefetch", TILEPRO_INSN_PREFETCH, false, "vk" }, 2929 { "__insn_prefetch_L1", TILEPRO_INSN_PREFETCH_L1, false, "vk" }, 2930 { "__insn_rl", TILEPRO_INSN_RL, true, "lll" }, 2931 { "__insn_rli", TILEPRO_INSN_RL, true, "lll" }, 2932 { "__insn_s1a", TILEPRO_INSN_S1A, true, "lll" }, 2933 { "__insn_s2a", TILEPRO_INSN_S2A, true, "lll" }, 2934 { "__insn_s3a", TILEPRO_INSN_S3A, true, "lll" }, 2935 { "__insn_sadab_u", TILEPRO_INSN_SADAB_U, true, "llll" }, 2936 { "__insn_sadah", TILEPRO_INSN_SADAH, true, "llll" }, 2937 { "__insn_sadah_u", TILEPRO_INSN_SADAH_U, true, "llll" }, 2938 { "__insn_sadb_u", TILEPRO_INSN_SADB_U, true, "lll" }, 2939 { "__insn_sadh", TILEPRO_INSN_SADH, true, "lll" }, 2940 { "__insn_sadh_u", TILEPRO_INSN_SADH_U, true, "lll" }, 2941 { "__insn_sb", TILEPRO_INSN_SB, false, "vpl" }, 2942 { "__insn_seq", TILEPRO_INSN_SEQ, true, "lll" }, 2943 { "__insn_seqb", TILEPRO_INSN_SEQB, true, "lll" }, 2944 { "__insn_seqh", TILEPRO_INSN_SEQH, true, "lll" }, 2945 { "__insn_seqi", TILEPRO_INSN_SEQ, true, "lll" }, 2946 { "__insn_seqib", TILEPRO_INSN_SEQIB, true, "lll" }, 2947 { "__insn_seqih", TILEPRO_INSN_SEQIH, true, "lll" }, 2948 { "__insn_sh", TILEPRO_INSN_SH, false, "vpl" }, 2949 { "__insn_shl", TILEPRO_INSN_SHL, true, "lll" }, 2950 { "__insn_shlb", TILEPRO_INSN_SHLB, true, "lll" }, 2951 { "__insn_shlh", TILEPRO_INSN_SHLH, true, "lll" }, 2952 { "__insn_shli", TILEPRO_INSN_SHL, true, "lll" }, 2953 { "__insn_shlib", TILEPRO_INSN_SHLIB, true, "lll" }, 2954 { "__insn_shlih", TILEPRO_INSN_SHLIH, true, "lll" }, 2955 { "__insn_shr", TILEPRO_INSN_SHR, true, "lll" }, 2956 { "__insn_shrb", TILEPRO_INSN_SHRB, true, "lll" }, 2957 { "__insn_shrh", TILEPRO_INSN_SHRH, true, "lll" }, 2958 { "__insn_shri", TILEPRO_INSN_SHR, true, "lll" }, 2959 { "__insn_shrib", TILEPRO_INSN_SHRIB, true, "lll" }, 2960 { "__insn_shrih", TILEPRO_INSN_SHRIH, true, "lll" }, 2961 { "__insn_slt", TILEPRO_INSN_SLT, true, "lll" }, 2962 { "__insn_slt_u", TILEPRO_INSN_SLT_U, true, "lll" }, 2963 { "__insn_sltb", TILEPRO_INSN_SLTB, true, "lll" }, 2964 { "__insn_sltb_u", TILEPRO_INSN_SLTB_U, true, "lll" }, 2965 { "__insn_slte", TILEPRO_INSN_SLTE, true, "lll" }, 2966 { "__insn_slte_u", TILEPRO_INSN_SLTE_U, true, "lll" }, 2967 { "__insn_slteb", TILEPRO_INSN_SLTEB, true, "lll" }, 2968 { "__insn_slteb_u", TILEPRO_INSN_SLTEB_U, true, "lll" }, 2969 { "__insn_slteh", TILEPRO_INSN_SLTEH, true, "lll" }, 2970 { "__insn_slteh_u", TILEPRO_INSN_SLTEH_U, true, "lll" }, 2971 { "__insn_slth", TILEPRO_INSN_SLTH, true, "lll" }, 2972 { "__insn_slth_u", TILEPRO_INSN_SLTH_U, true, "lll" }, 2973 { "__insn_slti", TILEPRO_INSN_SLT, true, "lll" }, 2974 { "__insn_slti_u", TILEPRO_INSN_SLT_U, true, "lll" }, 2975 { "__insn_sltib", TILEPRO_INSN_SLTIB, true, "lll" }, 2976 { "__insn_sltib_u", TILEPRO_INSN_SLTIB_U, true, "lll" }, 2977 { "__insn_sltih", TILEPRO_INSN_SLTIH, true, "lll" }, 2978 { "__insn_sltih_u", TILEPRO_INSN_SLTIH_U, true, "lll" }, 2979 { "__insn_sne", TILEPRO_INSN_SNE, true, "lll" }, 2980 { "__insn_sneb", TILEPRO_INSN_SNEB, true, "lll" }, 2981 { "__insn_sneh", TILEPRO_INSN_SNEH, true, "lll" }, 2982 { "__insn_sra", TILEPRO_INSN_SRA, true, "lll" }, 2983 { "__insn_srab", TILEPRO_INSN_SRAB, true, "lll" }, 2984 { "__insn_srah", TILEPRO_INSN_SRAH, true, "lll" }, 2985 { "__insn_srai", TILEPRO_INSN_SRA, true, "lll" }, 2986 { "__insn_sraib", TILEPRO_INSN_SRAIB, true, "lll" }, 2987 { "__insn_sraih", TILEPRO_INSN_SRAIH, true, "lll" }, 2988 { "__insn_sub", TILEPRO_INSN_SUB, true, "lll" }, 2989 { "__insn_subb", TILEPRO_INSN_SUBB, true, "lll" }, 2990 { "__insn_subbs_u", TILEPRO_INSN_SUBBS_U, false, "lll" }, 2991 { "__insn_subh", TILEPRO_INSN_SUBH, true, "lll" }, 2992 { "__insn_subhs", TILEPRO_INSN_SUBHS, false, "lll" }, 2993 { "__insn_subs", TILEPRO_INSN_SUBS, false, "lll" }, 2994 { "__insn_sw", TILEPRO_INSN_SW, false, "vpl" }, 2995 { "__insn_tblidxb0", TILEPRO_INSN_TBLIDXB0, true, "lll" }, 2996 { "__insn_tblidxb1", TILEPRO_INSN_TBLIDXB1, true, "lll" }, 2997 { "__insn_tblidxb2", TILEPRO_INSN_TBLIDXB2, true, "lll" }, 2998 { "__insn_tblidxb3", TILEPRO_INSN_TBLIDXB3, true, "lll" }, 2999 { "__insn_tns", TILEPRO_INSN_TNS, false, "lp" }, 3000 { "__insn_wh64", TILEPRO_INSN_WH64, false, "vp" }, 3001 { "__insn_xor", TILEPRO_INSN_XOR, true, "lll" }, 3002 { "__insn_xori", TILEPRO_INSN_XOR, true, "lll" }, 3003 { "__tile_network_barrier", TILEPRO_NETWORK_BARRIER, false, "v" }, 3004 { "__tile_idn0_receive", TILEPRO_IDN0_RECEIVE, false, "l" }, 3005 { "__tile_idn1_receive", TILEPRO_IDN1_RECEIVE, false, "l" }, 3006 { "__tile_idn_send", TILEPRO_IDN_SEND, false, "vl" }, 3007 { "__tile_sn_receive", TILEPRO_SN_RECEIVE, false, "l" }, 3008 { "__tile_sn_send", TILEPRO_SN_SEND, false, "vl" }, 3009 { "__tile_udn0_receive", TILEPRO_UDN0_RECEIVE, false, "l" }, 3010 { "__tile_udn1_receive", TILEPRO_UDN1_RECEIVE, false, "l" }, 3011 { "__tile_udn2_receive", TILEPRO_UDN2_RECEIVE, false, "l" }, 3012 { "__tile_udn3_receive", TILEPRO_UDN3_RECEIVE, false, "l" }, 3013 { "__tile_udn_send", TILEPRO_UDN_SEND, false, "vl" }, 3014 }; 3015 3016 3017 /* Convert a character in a builtin type string to a tree type. */ 3018 static tree 3019 char_to_type (char c) 3020 { 3021 static tree volatile_ptr_type_node = NULL; 3022 static tree volatile_const_ptr_type_node = NULL; 3023 3024 if (volatile_ptr_type_node == NULL) 3025 { 3026 volatile_ptr_type_node = 3027 build_pointer_type (build_qualified_type (void_type_node, 3028 TYPE_QUAL_VOLATILE)); 3029 volatile_const_ptr_type_node = 3030 build_pointer_type (build_qualified_type (void_type_node, 3031 TYPE_QUAL_CONST 3032 | TYPE_QUAL_VOLATILE)); 3033 } 3034 3035 switch (c) 3036 { 3037 case 'v': 3038 return void_type_node; 3039 case 'l': 3040 return long_unsigned_type_node; 3041 case 'p': 3042 return volatile_ptr_type_node; 3043 case 'k': 3044 return volatile_const_ptr_type_node; 3045 default: 3046 gcc_unreachable (); 3047 } 3048 } 3049 3050 3051 /* Implement TARGET_INIT_BUILTINS. */ 3052 static void 3053 tilepro_init_builtins (void) 3054 { 3055 size_t i; 3056 3057 for (i = 0; i < ARRAY_SIZE (tilepro_builtins); i++) 3058 { 3059 const struct tilepro_builtin_def *p = &tilepro_builtins[i]; 3060 tree ftype, ret_type, arg_type_list = void_list_node; 3061 tree decl; 3062 int j; 3063 3064 for (j = strlen (p->type) - 1; j > 0; j--) 3065 { 3066 arg_type_list = 3067 tree_cons (NULL_TREE, char_to_type (p->type[j]), arg_type_list); 3068 } 3069 3070 ret_type = char_to_type (p->type[0]); 3071 3072 ftype = build_function_type (ret_type, arg_type_list); 3073 3074 decl = add_builtin_function (p->name, ftype, p->code, BUILT_IN_MD, 3075 NULL, NULL); 3076 3077 if (p->is_const) 3078 TREE_READONLY (decl) = 1; 3079 TREE_NOTHROW (decl) = 1; 3080 3081 if (tilepro_builtin_info[p->code].fndecl == NULL) 3082 tilepro_builtin_info[p->code].fndecl = decl; 3083 } 3084 } 3085 3086 3087 /* Implement TARGET_EXPAND_BUILTIN. */ 3088 static rtx 3089 tilepro_expand_builtin (tree exp, 3090 rtx target, 3091 rtx subtarget ATTRIBUTE_UNUSED, 3092 machine_mode mode ATTRIBUTE_UNUSED, 3093 int ignore ATTRIBUTE_UNUSED) 3094 { 3095 #define MAX_BUILTIN_ARGS 4 3096 3097 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); 3098 unsigned int fcode = DECL_FUNCTION_CODE (fndecl); 3099 tree arg; 3100 call_expr_arg_iterator iter; 3101 enum insn_code icode; 3102 rtx op[MAX_BUILTIN_ARGS + 1], pat; 3103 int opnum; 3104 bool nonvoid; 3105 insn_gen_fn fn; 3106 3107 if (fcode >= TILEPRO_BUILTIN_max) 3108 internal_error ("bad builtin fcode"); 3109 icode = tilepro_builtin_info[fcode].icode; 3110 if (icode == 0) 3111 internal_error ("bad builtin icode"); 3112 3113 nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node; 3114 3115 opnum = nonvoid; 3116 FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) 3117 { 3118 const struct insn_operand_data *insn_op; 3119 3120 if (arg == error_mark_node) 3121 return NULL_RTX; 3122 if (opnum > MAX_BUILTIN_ARGS) 3123 return NULL_RTX; 3124 3125 insn_op = &insn_data[icode].operand[opnum]; 3126 3127 op[opnum] = expand_expr (arg, NULL_RTX, insn_op->mode, EXPAND_NORMAL); 3128 3129 if (!(*insn_op->predicate) (op[opnum], insn_op->mode)) 3130 op[opnum] = copy_to_mode_reg (insn_op->mode, op[opnum]); 3131 3132 if (!(*insn_op->predicate) (op[opnum], insn_op->mode)) 3133 { 3134 /* We still failed to meet the predicate even after moving 3135 into a register. Assume we needed an immediate. */ 3136 error_at (EXPR_LOCATION (exp), 3137 "operand must be an immediate of the right size"); 3138 return const0_rtx; 3139 } 3140 3141 opnum++; 3142 } 3143 3144 if (nonvoid) 3145 { 3146 machine_mode tmode = insn_data[icode].operand[0].mode; 3147 if (!target 3148 || GET_MODE (target) != tmode 3149 || !(*insn_data[icode].operand[0].predicate) (target, tmode)) 3150 target = gen_reg_rtx (tmode); 3151 op[0] = target; 3152 } 3153 3154 fn = GEN_FCN (icode); 3155 switch (opnum) 3156 { 3157 case 0: 3158 pat = fn (NULL_RTX); 3159 break; 3160 case 1: 3161 pat = fn (op[0]); 3162 break; 3163 case 2: 3164 pat = fn (op[0], op[1]); 3165 break; 3166 case 3: 3167 pat = fn (op[0], op[1], op[2]); 3168 break; 3169 case 4: 3170 pat = fn (op[0], op[1], op[2], op[3]); 3171 break; 3172 case 5: 3173 pat = fn (op[0], op[1], op[2], op[3], op[4]); 3174 break; 3175 default: 3176 gcc_unreachable (); 3177 } 3178 if (!pat) 3179 return NULL_RTX; 3180 3181 /* If we are generating a prefetch, tell the scheduler not to move 3182 it around. */ 3183 if (GET_CODE (pat) == PREFETCH) 3184 PREFETCH_SCHEDULE_BARRIER_P (pat) = true; 3185 3186 emit_insn (pat); 3187 3188 if (nonvoid) 3189 return target; 3190 else 3191 return const0_rtx; 3192 } 3193 3194 3195 /* Implement TARGET_BUILTIN_DECL. */ 3196 static tree 3197 tilepro_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED) 3198 { 3199 if (code >= TILEPRO_BUILTIN_max) 3200 return error_mark_node; 3201 3202 return tilepro_builtin_info[code].fndecl; 3203 } 3204 3205 3206 3207 /* Stack frames */ 3208 3209 /* Return whether REGNO needs to be saved in the stack frame. */ 3210 static bool 3211 need_to_save_reg (unsigned int regno) 3212 { 3213 if (!fixed_regs[regno] && !call_used_regs[regno] 3214 && df_regs_ever_live_p (regno)) 3215 return true; 3216 3217 if (flag_pic 3218 && (regno == PIC_OFFSET_TABLE_REGNUM 3219 || regno == TILEPRO_PIC_TEXT_LABEL_REGNUM) 3220 && (crtl->uses_pic_offset_table || crtl->saves_all_registers)) 3221 return true; 3222 3223 if (crtl->calls_eh_return) 3224 { 3225 unsigned i; 3226 for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; i++) 3227 { 3228 if (regno == EH_RETURN_DATA_REGNO (i)) 3229 return true; 3230 } 3231 } 3232 3233 return false; 3234 } 3235 3236 3237 /* Return the size of the register savev area. This function is only 3238 correct starting with local register allocation */ 3239 static int 3240 tilepro_saved_regs_size (void) 3241 { 3242 int reg_save_size = 0; 3243 int regno; 3244 int offset_to_frame; 3245 int align_mask; 3246 3247 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 3248 if (need_to_save_reg (regno)) 3249 reg_save_size += UNITS_PER_WORD; 3250 3251 /* Pad out the register save area if necessary to make 3252 frame_pointer_rtx be as aligned as the stack pointer. */ 3253 offset_to_frame = crtl->args.pretend_args_size + reg_save_size; 3254 align_mask = (STACK_BOUNDARY / BITS_PER_UNIT) - 1; 3255 reg_save_size += (-offset_to_frame) & align_mask; 3256 3257 return reg_save_size; 3258 } 3259 3260 3261 /* Round up frame size SIZE. */ 3262 static int 3263 round_frame_size (int size) 3264 { 3265 return ((size + STACK_BOUNDARY / BITS_PER_UNIT - 1) 3266 & -STACK_BOUNDARY / BITS_PER_UNIT); 3267 } 3268 3269 3270 /* Emit a store in the stack frame to save REGNO at address ADDR, and 3271 emit the corresponding REG_CFA_OFFSET note described by CFA and 3272 CFA_OFFSET. Return the emitted insn. */ 3273 static rtx 3274 frame_emit_store (int regno, int regno_note, rtx addr, rtx cfa, 3275 int cfa_offset) 3276 { 3277 rtx reg = gen_rtx_REG (Pmode, regno); 3278 rtx mem = gen_frame_mem (Pmode, addr); 3279 rtx mov = gen_movsi (mem, reg); 3280 3281 /* Describe what just happened in a way that dwarf understands. We 3282 use temporary registers to hold the address to make scheduling 3283 easier, and use the REG_CFA_OFFSET to describe the address as an 3284 offset from the CFA. */ 3285 rtx reg_note = gen_rtx_REG (Pmode, regno_note); 3286 rtx cfa_relative_addr = gen_rtx_PLUS (Pmode, cfa, gen_int_si (cfa_offset)); 3287 rtx cfa_relative_mem = gen_frame_mem (Pmode, cfa_relative_addr); 3288 rtx real = gen_rtx_SET (cfa_relative_mem, reg_note); 3289 add_reg_note (mov, REG_CFA_OFFSET, real); 3290 3291 return emit_insn (mov); 3292 } 3293 3294 3295 /* Emit a load in the stack frame to load REGNO from address ADDR. 3296 Add a REG_CFA_RESTORE note to CFA_RESTORES if CFA_RESTORES is 3297 non-null. Return the emitted insn. */ 3298 static rtx_insn * 3299 frame_emit_load (int regno, rtx addr, rtx *cfa_restores) 3300 { 3301 rtx reg = gen_rtx_REG (Pmode, regno); 3302 rtx mem = gen_frame_mem (Pmode, addr); 3303 if (cfa_restores) 3304 *cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, *cfa_restores); 3305 return emit_insn (gen_movsi (reg, mem)); 3306 } 3307 3308 3309 /* Helper function to set RTX_FRAME_RELATED_P on instructions, 3310 including sequences. */ 3311 static rtx_insn * 3312 set_frame_related_p (void) 3313 { 3314 rtx_insn *seq = get_insns (); 3315 rtx_insn *insn; 3316 3317 end_sequence (); 3318 3319 if (!seq) 3320 return NULL; 3321 3322 if (INSN_P (seq)) 3323 { 3324 insn = seq; 3325 while (insn != NULL_RTX) 3326 { 3327 RTX_FRAME_RELATED_P (insn) = 1; 3328 insn = NEXT_INSN (insn); 3329 } 3330 seq = emit_insn (seq); 3331 } 3332 else 3333 { 3334 seq = emit_insn (seq); 3335 RTX_FRAME_RELATED_P (seq) = 1; 3336 } 3337 return seq; 3338 } 3339 3340 3341 #define FRP(exp) (start_sequence (), exp, set_frame_related_p ()) 3342 3343 /* This emits code for 'sp += offset'. 3344 3345 The ABI only allows us to modify 'sp' in a single 'addi' or 3346 'addli', so the backtracer understands it. Larger amounts cannot 3347 use those instructions, so are added by placing the offset into a 3348 large register and using 'add'. 3349 3350 This happens after reload, so we need to expand it ourselves. */ 3351 static rtx_insn * 3352 emit_sp_adjust (int offset, int *next_scratch_regno, bool frame_related, 3353 rtx reg_notes) 3354 { 3355 rtx to_add; 3356 rtx imm_rtx = gen_int_si (offset); 3357 3358 rtx_insn *insn; 3359 if (satisfies_constraint_J (imm_rtx)) 3360 { 3361 /* We can add this using a single addi or addli. */ 3362 to_add = imm_rtx; 3363 } 3364 else 3365 { 3366 rtx tmp = gen_rtx_REG (Pmode, (*next_scratch_regno)--); 3367 tilepro_expand_set_const32 (tmp, imm_rtx); 3368 to_add = tmp; 3369 } 3370 3371 /* Actually adjust the stack pointer. */ 3372 insn = emit_insn (gen_sp_adjust (stack_pointer_rtx, stack_pointer_rtx, 3373 to_add)); 3374 REG_NOTES (insn) = reg_notes; 3375 3376 /* Describe what just happened in a way that dwarf understands. */ 3377 if (frame_related) 3378 { 3379 rtx real = gen_rtx_SET (stack_pointer_rtx, 3380 gen_rtx_PLUS (Pmode, stack_pointer_rtx, 3381 imm_rtx)); 3382 RTX_FRAME_RELATED_P (insn) = 1; 3383 add_reg_note (insn, REG_CFA_ADJUST_CFA, real); 3384 } 3385 3386 return insn; 3387 } 3388 3389 3390 /* Return whether the current function is leaf. This takes into 3391 account whether the function calls tls_get_addr. */ 3392 static bool 3393 tilepro_current_function_is_leaf (void) 3394 { 3395 return crtl->is_leaf && !cfun->machine->calls_tls_get_addr; 3396 } 3397 3398 3399 /* Return the frame size. */ 3400 static int 3401 compute_total_frame_size (void) 3402 { 3403 int total_size = (get_frame_size () + tilepro_saved_regs_size () 3404 + crtl->outgoing_args_size 3405 + crtl->args.pretend_args_size); 3406 3407 if (!tilepro_current_function_is_leaf () || cfun->calls_alloca) 3408 { 3409 /* Make room for save area in callee. */ 3410 total_size += STACK_POINTER_OFFSET; 3411 } 3412 3413 return round_frame_size (total_size); 3414 } 3415 3416 3417 /* Return nonzero if this function is known to have a null epilogue. 3418 This allows the optimizer to omit jumps to jumps if no stack was 3419 created. */ 3420 bool 3421 tilepro_can_use_return_insn_p (void) 3422 { 3423 return (reload_completed 3424 && cfun->static_chain_decl == 0 3425 && compute_total_frame_size () == 0 3426 && tilepro_current_function_is_leaf () 3427 && !crtl->profile && !df_regs_ever_live_p (TILEPRO_LINK_REGNUM)); 3428 } 3429 3430 3431 /* Returns an rtx for a stack slot at 'FP + offset_from_fp'. If there 3432 is a frame pointer, it computes the value relative to 3433 that. Otherwise it uses the stack pointer. */ 3434 static rtx 3435 compute_frame_addr (int offset_from_fp, int *next_scratch_regno) 3436 { 3437 rtx base_reg_rtx, tmp_reg_rtx, offset_rtx; 3438 int offset_from_base; 3439 3440 if (frame_pointer_needed) 3441 { 3442 base_reg_rtx = hard_frame_pointer_rtx; 3443 offset_from_base = offset_from_fp; 3444 } 3445 else 3446 { 3447 int offset_from_sp = compute_total_frame_size () + offset_from_fp; 3448 base_reg_rtx = stack_pointer_rtx; 3449 offset_from_base = offset_from_sp; 3450 } 3451 3452 if (offset_from_base == 0) 3453 return base_reg_rtx; 3454 3455 /* Compute the new value of the stack pointer. */ 3456 tmp_reg_rtx = gen_rtx_REG (Pmode, (*next_scratch_regno)--); 3457 offset_rtx = gen_int_si (offset_from_base); 3458 3459 if (!tilepro_expand_addsi (tmp_reg_rtx, base_reg_rtx, offset_rtx)) 3460 { 3461 emit_insn (gen_rtx_SET (tmp_reg_rtx, 3462 gen_rtx_PLUS (Pmode, base_reg_rtx, 3463 offset_rtx))); 3464 } 3465 3466 return tmp_reg_rtx; 3467 } 3468 3469 3470 /* The stack frame looks like this: 3471 +-------------+ 3472 | ... | 3473 | incoming | 3474 | stack args | 3475 AP -> +-------------+ 3476 | caller's HFP| 3477 +-------------+ 3478 | lr save | 3479 HFP -> +-------------+ 3480 | var args | 3481 | reg save | crtl->args.pretend_args_size bytes 3482 +-------------+ 3483 | ... | 3484 | saved regs | tilepro_saved_regs_size() bytes 3485 FP -> +-------------+ 3486 | ... | 3487 | vars | get_frame_size() bytes 3488 +-------------+ 3489 | ... | 3490 | outgoing | 3491 | stack args | crtl->outgoing_args_size bytes 3492 +-------------+ 3493 | HFP | 4 bytes (only here if nonleaf / alloca) 3494 +-------------+ 3495 | callee lr | 4 bytes (only here if nonleaf / alloca) 3496 | save | 3497 SP -> +-------------+ 3498 3499 HFP == incoming SP. 3500 3501 For functions with a frame larger than 32767 bytes, or which use 3502 alloca (), r52 is used as a frame pointer. Otherwise there is no 3503 frame pointer. 3504 3505 FP is saved at SP+4 before calling a subroutine so the 3506 callee can chain. */ 3507 void 3508 tilepro_expand_prologue (void) 3509 { 3510 #define ROUND_ROBIN_SIZE 4 3511 /* We round-robin through four scratch registers to hold temporary 3512 addresses for saving registers, to make instruction scheduling 3513 easier. */ 3514 rtx reg_save_addr[ROUND_ROBIN_SIZE] = { 3515 NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX 3516 }; 3517 rtx insn, cfa; 3518 unsigned int which_scratch; 3519 int offset, start_offset, regno; 3520 3521 /* A register that holds a copy of the incoming fp. */ 3522 int fp_copy_regno = -1; 3523 3524 /* A register that holds a copy of the incoming sp. */ 3525 int sp_copy_regno = -1; 3526 3527 /* Next scratch register number to hand out (postdecrementing). */ 3528 int next_scratch_regno = 29; 3529 3530 int total_size = compute_total_frame_size (); 3531 3532 if (flag_stack_usage_info) 3533 current_function_static_stack_size = total_size; 3534 3535 /* Save lr first in its special location because code after this 3536 might use the link register as a scratch register. */ 3537 if (df_regs_ever_live_p (TILEPRO_LINK_REGNUM) || crtl->calls_eh_return) 3538 { 3539 FRP (frame_emit_store (TILEPRO_LINK_REGNUM, TILEPRO_LINK_REGNUM, 3540 stack_pointer_rtx, stack_pointer_rtx, 0)); 3541 emit_insn (gen_blockage ()); 3542 } 3543 3544 if (total_size == 0) 3545 { 3546 /* Load the PIC register if needed. */ 3547 if (flag_pic && crtl->uses_pic_offset_table) 3548 load_pic_register (false); 3549 3550 return; 3551 } 3552 3553 cfa = stack_pointer_rtx; 3554 3555 if (frame_pointer_needed) 3556 { 3557 fp_copy_regno = next_scratch_regno--; 3558 3559 /* Copy the old frame pointer aside so we can save it later. */ 3560 insn = FRP (emit_move_insn (gen_rtx_REG (word_mode, fp_copy_regno), 3561 hard_frame_pointer_rtx)); 3562 add_reg_note (insn, REG_CFA_REGISTER, NULL_RTX); 3563 3564 /* Set up the frame pointer. */ 3565 insn = FRP (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx)); 3566 add_reg_note (insn, REG_CFA_DEF_CFA, hard_frame_pointer_rtx); 3567 cfa = hard_frame_pointer_rtx; 3568 REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY; 3569 3570 /* fp holds a copy of the incoming sp, in case we need to store 3571 it. */ 3572 sp_copy_regno = HARD_FRAME_POINTER_REGNUM; 3573 } 3574 else if (!tilepro_current_function_is_leaf ()) 3575 { 3576 /* Copy the old stack pointer aside so we can save it later. */ 3577 sp_copy_regno = next_scratch_regno--; 3578 emit_move_insn (gen_rtx_REG (Pmode, sp_copy_regno), 3579 stack_pointer_rtx); 3580 } 3581 3582 if (tilepro_current_function_is_leaf ()) 3583 { 3584 /* No need to store chain pointer to caller's frame. */ 3585 emit_sp_adjust (-total_size, &next_scratch_regno, 3586 !frame_pointer_needed, NULL_RTX); 3587 } 3588 else 3589 { 3590 /* Save the frame pointer (incoming sp value) to support 3591 backtracing. First we need to create an rtx with the store 3592 address. */ 3593 rtx chain_addr = gen_rtx_REG (Pmode, next_scratch_regno--); 3594 rtx size_rtx = gen_int_si (-(total_size - UNITS_PER_WORD)); 3595 3596 if (add_operand (size_rtx, Pmode)) 3597 { 3598 /* Expose more parallelism by computing this value from the 3599 original stack pointer, not the one after we have pushed 3600 the frame. */ 3601 rtx p = gen_rtx_PLUS (Pmode, stack_pointer_rtx, size_rtx); 3602 emit_insn (gen_rtx_SET (chain_addr, p)); 3603 emit_sp_adjust (-total_size, &next_scratch_regno, 3604 !frame_pointer_needed, NULL_RTX); 3605 } 3606 else 3607 { 3608 /* The stack frame is large, so just store the incoming sp 3609 value at *(new_sp + UNITS_PER_WORD). */ 3610 rtx p; 3611 emit_sp_adjust (-total_size, &next_scratch_regno, 3612 !frame_pointer_needed, NULL_RTX); 3613 p = gen_rtx_PLUS (Pmode, stack_pointer_rtx, 3614 GEN_INT (UNITS_PER_WORD)); 3615 emit_insn (gen_rtx_SET (chain_addr, p)); 3616 } 3617 3618 /* Save our frame pointer for backtrace chaining. */ 3619 emit_insn (gen_movsi (gen_frame_mem (SImode, chain_addr), 3620 gen_rtx_REG (SImode, sp_copy_regno))); 3621 } 3622 3623 /* Compute where to start storing registers we need to save. */ 3624 start_offset = -crtl->args.pretend_args_size - UNITS_PER_WORD; 3625 offset = start_offset; 3626 3627 /* Store all registers that need saving. */ 3628 which_scratch = 0; 3629 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) 3630 if (need_to_save_reg (regno)) 3631 { 3632 rtx r = reg_save_addr[which_scratch]; 3633 int from_regno; 3634 int cfa_offset = frame_pointer_needed ? offset : total_size + offset; 3635 3636 if (r == NULL_RTX) 3637 { 3638 rtx p = compute_frame_addr (offset, &next_scratch_regno); 3639 r = gen_rtx_REG (word_mode, next_scratch_regno--); 3640 reg_save_addr[which_scratch] = r; 3641 3642 emit_insn (gen_rtx_SET (r, p)); 3643 } 3644 else 3645 { 3646 /* Advance to the next stack slot to store this register. */ 3647 int stride = ROUND_ROBIN_SIZE * -UNITS_PER_WORD; 3648 rtx p = gen_rtx_PLUS (Pmode, r, GEN_INT (stride)); 3649 emit_insn (gen_rtx_SET (r, p)); 3650 } 3651 3652 /* Save this register to the stack (but use the old fp value 3653 we copied aside if appropriate). */ 3654 from_regno = (fp_copy_regno >= 0 3655 && regno == 3656 HARD_FRAME_POINTER_REGNUM) ? fp_copy_regno : regno; 3657 FRP (frame_emit_store (from_regno, regno, r, cfa, cfa_offset)); 3658 3659 offset -= UNITS_PER_WORD; 3660 which_scratch = (which_scratch + 1) % ROUND_ROBIN_SIZE; 3661 } 3662 3663 /* If profiling, force that to happen after the frame is set up. */ 3664 if (crtl->profile) 3665 emit_insn (gen_blockage ()); 3666 3667 /* Load the PIC register if needed. */ 3668 if (flag_pic && crtl->uses_pic_offset_table) 3669 load_pic_register (false); 3670 } 3671 3672 3673 /* Implement the epilogue and sibcall_epilogue patterns. SIBCALL_P is 3674 true for a sibcall_epilogue pattern, and false for an epilogue 3675 pattern. */ 3676 void 3677 tilepro_expand_epilogue (bool sibcall_p) 3678 { 3679 /* We round-robin through four scratch registers to hold temporary 3680 addresses for saving registers, to make instruction scheduling 3681 easier. */ 3682 rtx reg_save_addr[ROUND_ROBIN_SIZE] = { 3683 NULL_RTX, NULL_RTX, NULL_RTX, NULL_RTX 3684 }; 3685 rtx_insn *last_insn, *insn; 3686 unsigned int which_scratch; 3687 int offset, start_offset, regno; 3688 rtx cfa_restores = NULL_RTX; 3689 3690 /* A register that holds a copy of the incoming fp. */ 3691 int fp_copy_regno = -1; 3692 3693 /* Next scratch register number to hand out (postdecrementing). */ 3694 int next_scratch_regno = 29; 3695 3696 int total_size = compute_total_frame_size (); 3697 3698 last_insn = get_last_insn (); 3699 3700 /* Load lr first since we are going to need it first. */ 3701 insn = NULL; 3702 if (df_regs_ever_live_p (TILEPRO_LINK_REGNUM)) 3703 { 3704 insn = frame_emit_load (TILEPRO_LINK_REGNUM, 3705 compute_frame_addr (0, &next_scratch_regno), 3706 &cfa_restores); 3707 } 3708 3709 if (total_size == 0) 3710 { 3711 if (insn) 3712 { 3713 RTX_FRAME_RELATED_P (insn) = 1; 3714 REG_NOTES (insn) = cfa_restores; 3715 } 3716 goto done; 3717 } 3718 3719 /* Compute where to start restoring registers. */ 3720 start_offset = -crtl->args.pretend_args_size - UNITS_PER_WORD; 3721 offset = start_offset; 3722 3723 if (frame_pointer_needed) 3724 fp_copy_regno = next_scratch_regno--; 3725 3726 /* Restore all callee-saved registers. */ 3727 which_scratch = 0; 3728 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--) 3729 if (need_to_save_reg (regno)) 3730 { 3731 rtx r = reg_save_addr[which_scratch]; 3732 if (r == NULL_RTX) 3733 { 3734 r = compute_frame_addr (offset, &next_scratch_regno); 3735 reg_save_addr[which_scratch] = r; 3736 } 3737 else 3738 { 3739 /* Advance to the next stack slot to store this 3740 register. */ 3741 int stride = ROUND_ROBIN_SIZE * -UNITS_PER_WORD; 3742 rtx p = gen_rtx_PLUS (Pmode, r, GEN_INT (stride)); 3743 emit_insn (gen_rtx_SET (r, p)); 3744 } 3745 3746 if (fp_copy_regno >= 0 && regno == HARD_FRAME_POINTER_REGNUM) 3747 frame_emit_load (fp_copy_regno, r, NULL); 3748 else 3749 frame_emit_load (regno, r, &cfa_restores); 3750 3751 offset -= UNITS_PER_WORD; 3752 which_scratch = (which_scratch + 1) % ROUND_ROBIN_SIZE; 3753 } 3754 3755 if (!tilepro_current_function_is_leaf ()) 3756 cfa_restores = 3757 alloc_reg_note (REG_CFA_RESTORE, stack_pointer_rtx, cfa_restores); 3758 3759 emit_insn (gen_blockage ()); 3760 3761 if (frame_pointer_needed) 3762 { 3763 /* Restore the old stack pointer by copying from the frame 3764 pointer. */ 3765 insn = emit_insn (gen_sp_restore (stack_pointer_rtx, 3766 hard_frame_pointer_rtx)); 3767 RTX_FRAME_RELATED_P (insn) = 1; 3768 REG_NOTES (insn) = cfa_restores; 3769 add_reg_note (insn, REG_CFA_DEF_CFA, stack_pointer_rtx); 3770 } 3771 else 3772 { 3773 insn = emit_sp_adjust (total_size, &next_scratch_regno, true, 3774 cfa_restores); 3775 } 3776 3777 if (crtl->calls_eh_return) 3778 emit_insn (gen_sp_adjust (stack_pointer_rtx, stack_pointer_rtx, 3779 EH_RETURN_STACKADJ_RTX)); 3780 3781 /* Restore the old frame pointer. */ 3782 if (frame_pointer_needed) 3783 { 3784 insn = emit_move_insn (hard_frame_pointer_rtx, 3785 gen_rtx_REG (Pmode, fp_copy_regno)); 3786 add_reg_note (insn, REG_CFA_RESTORE, hard_frame_pointer_rtx); 3787 } 3788 3789 /* Mark the pic registers as live outside of the function. */ 3790 if (flag_pic) 3791 { 3792 emit_use (cfun->machine->text_label_rtx); 3793 emit_use (cfun->machine->got_rtx); 3794 } 3795 3796 done: 3797 if (!sibcall_p) 3798 { 3799 /* Emit the actual 'return' instruction. */ 3800 emit_jump_insn (gen__return ()); 3801 } 3802 else 3803 { 3804 emit_use (gen_rtx_REG (Pmode, TILEPRO_LINK_REGNUM)); 3805 } 3806 3807 /* Mark all insns we just emitted as frame-related. */ 3808 for (; last_insn != NULL_RTX; last_insn = next_insn (last_insn)) 3809 RTX_FRAME_RELATED_P (last_insn) = 1; 3810 } 3811 3812 #undef ROUND_ROBIN_SIZE 3813 3814 3815 /* Implement INITIAL_ELIMINATION_OFFSET. */ 3816 int 3817 tilepro_initial_elimination_offset (int from, int to) 3818 { 3819 int total_size = compute_total_frame_size (); 3820 3821 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) 3822 { 3823 return (total_size - crtl->args.pretend_args_size 3824 - tilepro_saved_regs_size ()); 3825 } 3826 else if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) 3827 { 3828 return -(crtl->args.pretend_args_size + tilepro_saved_regs_size ()); 3829 } 3830 else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) 3831 { 3832 return STACK_POINTER_OFFSET + total_size; 3833 } 3834 else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) 3835 { 3836 return STACK_POINTER_OFFSET; 3837 } 3838 else 3839 gcc_unreachable (); 3840 } 3841 3842 3843 /* Return an RTX indicating where the return address to the 3844 calling function can be found. */ 3845 rtx 3846 tilepro_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) 3847 { 3848 if (count != 0) 3849 return const0_rtx; 3850 3851 return get_hard_reg_initial_val (Pmode, TILEPRO_LINK_REGNUM); 3852 } 3853 3854 3855 /* Implement EH_RETURN_HANDLER_RTX. */ 3856 rtx 3857 tilepro_eh_return_handler_rtx (void) 3858 { 3859 /* The MEM needs to be volatile to prevent it from being 3860 deleted. */ 3861 rtx tmp = gen_frame_mem (Pmode, hard_frame_pointer_rtx); 3862 MEM_VOLATILE_P (tmp) = true; 3863 return tmp; 3864 } 3865 3866 3867 3868 /* Registers */ 3869 3870 /* Implemnet TARGET_CONDITIONAL_REGISTER_USAGE. */ 3871 static void 3872 tilepro_conditional_register_usage (void) 3873 { 3874 global_regs[TILEPRO_NETORDER_REGNUM] = 1; 3875 /* TILEPRO_PIC_TEXT_LABEL_REGNUM is conditionally used. It is a 3876 member of fixed_regs, and therefore must be member of 3877 call_used_regs, but it is not a member of call_really_used_regs[] 3878 because it is not clobbered by a call. */ 3879 if (TILEPRO_PIC_TEXT_LABEL_REGNUM != INVALID_REGNUM) 3880 { 3881 fixed_regs[TILEPRO_PIC_TEXT_LABEL_REGNUM] = 1; 3882 call_used_regs[TILEPRO_PIC_TEXT_LABEL_REGNUM] = 1; 3883 } 3884 if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM) 3885 { 3886 fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; 3887 call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; 3888 } 3889 } 3890 3891 3892 /* Implement TARGET_FRAME_POINTER_REQUIRED. */ 3893 static bool 3894 tilepro_frame_pointer_required (void) 3895 { 3896 return crtl->calls_eh_return || cfun->calls_alloca; 3897 } 3898 3899 3900 3901 /* Scheduling and reorg */ 3902 3903 /* Return the length of INSN. LENGTH is the initial length computed 3904 by attributes in the machine-description file. This is where we 3905 account for bundles. */ 3906 int 3907 tilepro_adjust_insn_length (rtx_insn *insn, int length) 3908 { 3909 machine_mode mode = GET_MODE (insn); 3910 3911 /* A non-termininating instruction in a bundle has length 0. */ 3912 if (mode == SImode) 3913 return 0; 3914 3915 /* By default, there is not length adjustment. */ 3916 return length; 3917 } 3918 3919 3920 /* Implement TARGET_SCHED_ISSUE_RATE. */ 3921 static int 3922 tilepro_issue_rate (void) 3923 { 3924 return 3; 3925 } 3926 3927 3928 /* Return the rtx for the jump target. */ 3929 static rtx 3930 get_jump_target (rtx branch) 3931 { 3932 if (CALL_P (branch)) 3933 { 3934 rtx call; 3935 call = PATTERN (branch); 3936 3937 if (GET_CODE (call) == PARALLEL) 3938 call = XVECEXP (call, 0, 0); 3939 3940 if (GET_CODE (call) == SET) 3941 call = SET_SRC (call); 3942 3943 if (GET_CODE (call) == CALL) 3944 return XEXP (XEXP (call, 0), 0); 3945 } 3946 return 0; 3947 } 3948 3949 /* Implement TARGET_SCHED_ADJUST_COST. */ 3950 static int 3951 tilepro_sched_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, 3952 int cost, unsigned int) 3953 { 3954 /* If we have a true dependence, INSN is a call, and DEP_INSN 3955 defines a register that is needed by the call (argument or stack 3956 pointer), set its latency to 0 so that it can be bundled with 3957 the call. Explicitly check for and exclude the case when 3958 DEP_INSN defines the target of the jump. */ 3959 if (CALL_P (insn) && dep_type == REG_DEP_TRUE) 3960 { 3961 rtx target = get_jump_target (insn); 3962 if (!REG_P (target) || !set_of (target, dep_insn)) 3963 return 0; 3964 } 3965 3966 return cost; 3967 } 3968 3969 3970 /* Skip over irrelevant NOTEs and such and look for the next insn we 3971 would consider bundling. */ 3972 static rtx_insn * 3973 next_insn_to_bundle (rtx_insn *r, rtx_insn *end) 3974 { 3975 for (; r != end; r = NEXT_INSN (r)) 3976 { 3977 if (NONDEBUG_INSN_P (r) 3978 && GET_CODE (PATTERN (r)) != USE 3979 && GET_CODE (PATTERN (r)) != CLOBBER) 3980 return r; 3981 } 3982 3983 return NULL; 3984 } 3985 3986 3987 /* Go through all insns, and use the information generated during 3988 scheduling to generate SEQUENCEs to represent bundles of 3989 instructions issued simultaneously. */ 3990 static void 3991 tilepro_gen_bundles (void) 3992 { 3993 basic_block bb; 3994 FOR_EACH_BB_FN (bb, cfun) 3995 { 3996 rtx_insn *insn, *next; 3997 rtx_insn *end = NEXT_INSN (BB_END (bb)); 3998 3999 for (insn = next_insn_to_bundle (BB_HEAD (bb), end); insn; insn = next) 4000 { 4001 next = next_insn_to_bundle (NEXT_INSN (insn), end); 4002 4003 /* Never wrap {} around inline asm. */ 4004 if (GET_CODE (PATTERN (insn)) != ASM_INPUT) 4005 { 4006 if (next == NULL_RTX || GET_MODE (next) == TImode 4007 /* NOTE: The scheduler incorrectly believes a call 4008 insn can execute in the same cycle as the insn 4009 after the call. This is of course impossible. 4010 Really we need to fix the scheduler somehow, so 4011 the code after the call gets scheduled 4012 optimally. */ 4013 || CALL_P (insn)) 4014 { 4015 /* Mark current insn as the end of a bundle. */ 4016 PUT_MODE (insn, QImode); 4017 } 4018 else 4019 { 4020 /* Mark it as part of a bundle. */ 4021 PUT_MODE (insn, SImode); 4022 } 4023 } 4024 } 4025 } 4026 } 4027 4028 4029 /* Helper function for tilepro_fixup_pcrel_references. */ 4030 static void 4031 replace_pc_relative_symbol_ref (rtx_insn *insn, rtx opnds[4], bool first_insn_p) 4032 { 4033 rtx_insn *new_insns; 4034 4035 start_sequence (); 4036 4037 if (flag_pic == 1) 4038 { 4039 if (!first_insn_p) 4040 { 4041 emit_insn (gen_add_got16 (opnds[0], tilepro_got_rtx (), 4042 opnds[2])); 4043 emit_insn (gen_insn_lw (opnds[0], opnds[0])); 4044 } 4045 } 4046 else 4047 { 4048 if (first_insn_p) 4049 { 4050 emit_insn (gen_addhi_got32 (opnds[0], tilepro_got_rtx (), 4051 opnds[2])); 4052 } 4053 else 4054 { 4055 emit_insn (gen_addlo_got32 (opnds[0], opnds[1], opnds[2])); 4056 emit_insn (gen_insn_lw (opnds[0], opnds[0])); 4057 } 4058 } 4059 4060 new_insns = get_insns (); 4061 end_sequence (); 4062 4063 if (new_insns) 4064 emit_insn_before (new_insns, insn); 4065 4066 delete_insn (insn); 4067 } 4068 4069 4070 /* Returns whether INSN is a pc-relative addli insn. */ 4071 static bool 4072 match_addli_pcrel (rtx_insn *insn) 4073 { 4074 rtx pattern = PATTERN (insn); 4075 rtx unspec; 4076 4077 if (GET_CODE (pattern) != SET) 4078 return false; 4079 4080 if (GET_CODE (SET_SRC (pattern)) != LO_SUM) 4081 return false; 4082 4083 if (GET_CODE (XEXP (SET_SRC (pattern), 1)) != CONST) 4084 return false; 4085 4086 unspec = XEXP (XEXP (SET_SRC (pattern), 1), 0); 4087 4088 return (GET_CODE (unspec) == UNSPEC 4089 && XINT (unspec, 1) == UNSPEC_PCREL_SYM); 4090 } 4091 4092 4093 /* Helper function for tilepro_fixup_pcrel_references. */ 4094 static void 4095 replace_addli_pcrel (rtx_insn *insn) 4096 { 4097 rtx pattern = PATTERN (insn); 4098 rtx set_src; 4099 rtx unspec; 4100 rtx opnds[4]; 4101 bool first_insn_p; 4102 4103 gcc_assert (GET_CODE (pattern) == SET); 4104 opnds[0] = SET_DEST (pattern); 4105 4106 set_src = SET_SRC (pattern); 4107 gcc_assert (GET_CODE (set_src) == LO_SUM); 4108 gcc_assert (GET_CODE (XEXP (set_src, 1)) == CONST); 4109 opnds[1] = XEXP (set_src, 0); 4110 4111 unspec = XEXP (XEXP (set_src, 1), 0); 4112 gcc_assert (GET_CODE (unspec) == UNSPEC); 4113 gcc_assert (XINT (unspec, 1) == UNSPEC_PCREL_SYM); 4114 opnds[2] = XVECEXP (unspec, 0, 0); 4115 opnds[3] = XVECEXP (unspec, 0, 1); 4116 4117 /* We only need to replace SYMBOL_REFs, not LABEL_REFs. */ 4118 if (GET_CODE (opnds[2]) != SYMBOL_REF) 4119 return; 4120 4121 first_insn_p = (opnds[1] == tilepro_text_label_rtx ()); 4122 4123 replace_pc_relative_symbol_ref (insn, opnds, first_insn_p); 4124 } 4125 4126 4127 /* Returns whether INSN is a pc-relative auli insn. */ 4128 static bool 4129 match_auli_pcrel (rtx_insn *insn) 4130 { 4131 rtx pattern = PATTERN (insn); 4132 rtx high; 4133 rtx unspec; 4134 4135 if (GET_CODE (pattern) != SET) 4136 return false; 4137 4138 if (GET_CODE (SET_SRC (pattern)) != PLUS) 4139 return false; 4140 4141 high = XEXP (SET_SRC (pattern), 1); 4142 4143 if (GET_CODE (high) != HIGH 4144 || GET_CODE (XEXP (high, 0)) != CONST) 4145 return false; 4146 4147 unspec = XEXP (XEXP (high, 0), 0); 4148 4149 return (GET_CODE (unspec) == UNSPEC 4150 && XINT (unspec, 1) == UNSPEC_PCREL_SYM); 4151 } 4152 4153 4154 /* Helper function for tilepro_fixup_pcrel_references. */ 4155 static void 4156 replace_auli_pcrel (rtx_insn *insn) 4157 { 4158 rtx pattern = PATTERN (insn); 4159 rtx set_src; 4160 rtx high; 4161 rtx unspec; 4162 rtx opnds[4]; 4163 bool first_insn_p; 4164 4165 gcc_assert (GET_CODE (pattern) == SET); 4166 opnds[0] = SET_DEST (pattern); 4167 4168 set_src = SET_SRC (pattern); 4169 gcc_assert (GET_CODE (set_src) == PLUS); 4170 opnds[1] = XEXP (set_src, 0); 4171 4172 high = XEXP (set_src, 1); 4173 gcc_assert (GET_CODE (high) == HIGH); 4174 gcc_assert (GET_CODE (XEXP (high, 0)) == CONST); 4175 4176 unspec = XEXP (XEXP (high, 0), 0); 4177 gcc_assert (GET_CODE (unspec) == UNSPEC); 4178 gcc_assert (XINT (unspec, 1) == UNSPEC_PCREL_SYM); 4179 opnds[2] = XVECEXP (unspec, 0, 0); 4180 opnds[3] = XVECEXP (unspec, 0, 1); 4181 4182 /* We only need to replace SYMBOL_REFs, not LABEL_REFs. */ 4183 if (GET_CODE (opnds[2]) != SYMBOL_REF) 4184 return; 4185 4186 first_insn_p = (opnds[1] == tilepro_text_label_rtx ()); 4187 4188 replace_pc_relative_symbol_ref (insn, opnds, first_insn_p); 4189 } 4190 4191 4192 /* We generate PC relative SYMBOL_REFs as an optimization, to avoid 4193 going through the GOT when the symbol is local to the compilation 4194 unit. But such a symbol requires that the common text_label that 4195 we generate at the beginning of the function be in the same section 4196 as the reference to the SYMBOL_REF. This may not be true if we 4197 generate hot/cold sections. This function looks for such cases and 4198 replaces such references with the longer sequence going through the 4199 GOT. 4200 4201 We expect one of the following two instruction sequences: 4202 addli tmp1, txt_label_reg, lo16(sym - txt_label) 4203 auli tmp2, tmp1, ha16(sym - txt_label) 4204 4205 auli tmp1, txt_label_reg, ha16(sym - txt_label) 4206 addli tmp2, tmp1, lo16(sym - txt_label) 4207 4208 If we're compiling -fpic, we replace the first instruction with 4209 nothing, and the second instruction with: 4210 4211 addli tmp2, got_rtx, got(sym) 4212 lw tmp2, tmp2 4213 4214 If we're compiling -fPIC, we replace the first instruction with: 4215 4216 auli tmp1, got_rtx, got_ha16(sym) 4217 4218 and the second instruction with: 4219 4220 addli tmp2, tmp1, got_lo16(sym) 4221 lw tmp2, tmp2 4222 4223 Note that we're careful to disturb the instruction sequence as 4224 little as possible, since it's very late in the compilation 4225 process. 4226 */ 4227 static void 4228 tilepro_fixup_pcrel_references (void) 4229 { 4230 rtx_insn *insn, *next_insn; 4231 bool same_section_as_entry = true; 4232 4233 for (insn = get_insns (); insn; insn = next_insn) 4234 { 4235 next_insn = NEXT_INSN (insn); 4236 4237 if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS) 4238 { 4239 same_section_as_entry = !same_section_as_entry; 4240 continue; 4241 } 4242 4243 if (same_section_as_entry) 4244 continue; 4245 4246 if (!(INSN_P (insn) 4247 && GET_CODE (PATTERN (insn)) != USE 4248 && GET_CODE (PATTERN (insn)) != CLOBBER)) 4249 continue; 4250 4251 if (match_addli_pcrel (insn)) 4252 replace_addli_pcrel (insn); 4253 else if (match_auli_pcrel (insn)) 4254 replace_auli_pcrel (insn); 4255 } 4256 } 4257 4258 4259 /* Ensure that no var tracking notes are emitted in the middle of a 4260 three-instruction bundle. */ 4261 static void 4262 reorder_var_tracking_notes (void) 4263 { 4264 basic_block bb; 4265 FOR_EACH_BB_FN (bb, cfun) 4266 { 4267 rtx_insn *insn, *next; 4268 rtx_insn *queue = NULL; 4269 bool in_bundle = false; 4270 4271 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next) 4272 { 4273 next = NEXT_INSN (insn); 4274 4275 if (INSN_P (insn)) 4276 { 4277 /* Emit queued up notes at the last instruction of a bundle. */ 4278 if (GET_MODE (insn) == QImode) 4279 { 4280 while (queue) 4281 { 4282 rtx_insn *next_queue = PREV_INSN (queue); 4283 SET_PREV_INSN (NEXT_INSN (insn)) = queue; 4284 SET_NEXT_INSN (queue) = NEXT_INSN (insn); 4285 SET_NEXT_INSN (insn) = queue; 4286 SET_PREV_INSN (queue) = insn; 4287 queue = next_queue; 4288 } 4289 in_bundle = false; 4290 } 4291 else if (GET_MODE (insn) == SImode) 4292 in_bundle = true; 4293 } 4294 else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION) 4295 { 4296 if (in_bundle) 4297 { 4298 rtx_insn *prev = PREV_INSN (insn); 4299 SET_PREV_INSN (next) = prev; 4300 SET_NEXT_INSN (prev) = next; 4301 4302 SET_PREV_INSN (insn) = queue; 4303 queue = insn; 4304 } 4305 } 4306 } 4307 } 4308 } 4309 4310 4311 /* Perform machine dependent operations on the rtl chain INSNS. */ 4312 static void 4313 tilepro_reorg (void) 4314 { 4315 /* We are freeing block_for_insn in the toplev to keep compatibility 4316 with old MDEP_REORGS that are not CFG based. Recompute it 4317 now. */ 4318 compute_bb_for_insn (); 4319 4320 if (flag_reorder_blocks_and_partition) 4321 { 4322 tilepro_fixup_pcrel_references (); 4323 } 4324 4325 if (flag_schedule_insns_after_reload) 4326 { 4327 split_all_insns (); 4328 4329 timevar_push (TV_SCHED2); 4330 schedule_insns (); 4331 timevar_pop (TV_SCHED2); 4332 4333 /* Examine the schedule to group into bundles. */ 4334 tilepro_gen_bundles (); 4335 } 4336 4337 df_analyze (); 4338 4339 if (flag_var_tracking) 4340 { 4341 timevar_push (TV_VAR_TRACKING); 4342 variable_tracking_main (); 4343 reorder_var_tracking_notes (); 4344 timevar_pop (TV_VAR_TRACKING); 4345 } 4346 4347 df_finish_pass (false); 4348 } 4349 4350 4351 4352 /* Assembly */ 4353 4354 /* Select a format to encode pointers in exception handling data. 4355 CODE is 0 for data, 1 for code labels, 2 for function pointers. 4356 GLOBAL is true if the symbol may be affected by dynamic 4357 relocations. */ 4358 int 4359 tilepro_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED, int global) 4360 { 4361 return (global ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4; 4362 } 4363 4364 4365 /* Implement TARGET_ASM_OUTPUT_MI_THUNK. */ 4366 static void 4367 tilepro_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, 4368 HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset, 4369 tree function) 4370 { 4371 rtx this_rtx, funexp; 4372 rtx_insn *insn; 4373 4374 /* Pretend to be a post-reload pass while generating rtl. */ 4375 reload_completed = 1; 4376 4377 /* Mark the end of the (empty) prologue. */ 4378 emit_note (NOTE_INSN_PROLOGUE_END); 4379 4380 /* Find the "this" pointer. If the function returns a structure, 4381 the structure return pointer is in $1. */ 4382 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) 4383 this_rtx = gen_rtx_REG (Pmode, 1); 4384 else 4385 this_rtx = gen_rtx_REG (Pmode, 0); 4386 4387 /* Add DELTA to THIS_RTX. */ 4388 emit_insn (gen_addsi3 (this_rtx, this_rtx, GEN_INT (delta))); 4389 4390 /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */ 4391 if (vcall_offset) 4392 { 4393 rtx tmp; 4394 4395 tmp = gen_rtx_REG (Pmode, 29); 4396 emit_move_insn (tmp, gen_rtx_MEM (Pmode, this_rtx)); 4397 4398 emit_insn (gen_addsi3 (tmp, tmp, GEN_INT (vcall_offset))); 4399 4400 emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp)); 4401 4402 emit_insn (gen_addsi3 (this_rtx, this_rtx, tmp)); 4403 } 4404 4405 /* Generate a tail call to the target function. */ 4406 if (!TREE_USED (function)) 4407 { 4408 assemble_external (function); 4409 TREE_USED (function) = 1; 4410 } 4411 funexp = XEXP (DECL_RTL (function), 0); 4412 funexp = gen_rtx_MEM (FUNCTION_MODE, funexp); 4413 insn = emit_call_insn (gen_sibcall (funexp, const0_rtx)); 4414 SIBLING_CALL_P (insn) = 1; 4415 4416 /* Run just enough of rest_of_compilation to get the insns emitted. 4417 There's not really enough bulk here to make other passes such as 4418 instruction scheduling worth while. Note that use_thunk calls 4419 assemble_start_function and assemble_end_function. 4420 4421 We don't currently bundle, but the instruciton sequence is all 4422 serial except for the tail call, so we're only wasting one cycle. 4423 */ 4424 insn = get_insns (); 4425 shorten_branches (insn); 4426 final_start_function (insn, file, 1); 4427 final (insn, file, 1); 4428 final_end_function (); 4429 4430 /* Stop pretending to be a post-reload pass. */ 4431 reload_completed = 0; 4432 } 4433 4434 4435 /* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE. */ 4436 static void 4437 tilepro_asm_trampoline_template (FILE *file) 4438 { 4439 fprintf (file, "\tlnk r10\n"); 4440 fprintf (file, "\taddi r10, r10, 32\n"); 4441 fprintf (file, "\tlwadd r11, r10, %d\n", GET_MODE_SIZE (ptr_mode)); 4442 fprintf (file, "\tlw r10, r10\n"); 4443 fprintf (file, "\tjr r11\n"); 4444 fprintf (file, "\t.word 0 # <function address>\n"); 4445 fprintf (file, "\t.word 0 # <static chain value>\n"); 4446 } 4447 4448 4449 /* Implement TARGET_TRAMPOLINE_INIT. */ 4450 static void 4451 tilepro_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain) 4452 { 4453 rtx fnaddr, chaddr; 4454 rtx mem; 4455 rtx begin_addr, end_addr; 4456 int ptr_mode_size = GET_MODE_SIZE (ptr_mode); 4457 4458 fnaddr = copy_to_reg (XEXP (DECL_RTL (fndecl), 0)); 4459 chaddr = copy_to_reg (static_chain); 4460 4461 emit_block_move (m_tramp, assemble_trampoline_template (), 4462 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); 4463 4464 mem = adjust_address (m_tramp, ptr_mode, 4465 TRAMPOLINE_SIZE - 2 * ptr_mode_size); 4466 emit_move_insn (mem, fnaddr); 4467 mem = adjust_address (m_tramp, ptr_mode, 4468 TRAMPOLINE_SIZE - ptr_mode_size); 4469 emit_move_insn (mem, chaddr); 4470 4471 /* Get pointers to the beginning and end of the code block. */ 4472 begin_addr = force_reg (Pmode, XEXP (m_tramp, 0)); 4473 end_addr = force_reg (Pmode, plus_constant (Pmode, XEXP (m_tramp, 0), 4474 TRAMPOLINE_SIZE)); 4475 4476 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"), 4477 LCT_NORMAL, VOIDmode, begin_addr, Pmode, 4478 end_addr, Pmode); 4479 } 4480 4481 4482 /* Implement TARGET_PRINT_OPERAND. */ 4483 static void 4484 tilepro_print_operand (FILE *file, rtx x, int code) 4485 { 4486 switch (code) 4487 { 4488 case 'c': 4489 /* Print the compare operator opcode for conditional moves. */ 4490 switch (GET_CODE (x)) 4491 { 4492 case EQ: 4493 fputs ("z", file); 4494 break; 4495 case NE: 4496 fputs ("nz", file); 4497 break; 4498 default: 4499 output_operand_lossage ("invalid %%c operand"); 4500 } 4501 return; 4502 4503 case 'C': 4504 /* Print the compare operator opcode for conditional moves. */ 4505 switch (GET_CODE (x)) 4506 { 4507 case EQ: 4508 fputs ("nz", file); 4509 break; 4510 case NE: 4511 fputs ("z", file); 4512 break; 4513 default: 4514 output_operand_lossage ("invalid %%C operand"); 4515 } 4516 return; 4517 4518 case 'h': 4519 { 4520 /* Print the high 16 bits of a 32-bit constant. */ 4521 HOST_WIDE_INT i; 4522 if (CONST_INT_P (x)) 4523 i = INTVAL (x); 4524 else if (GET_CODE (x) == CONST_DOUBLE) 4525 i = CONST_DOUBLE_LOW (x); 4526 else 4527 { 4528 output_operand_lossage ("invalid %%h operand"); 4529 return; 4530 } 4531 i = trunc_int_for_mode (i >> 16, HImode); 4532 fprintf (file, HOST_WIDE_INT_PRINT_DEC, i); 4533 return; 4534 } 4535 4536 case 'H': 4537 { 4538 rtx addr = NULL; 4539 const char *opstr = NULL; 4540 bool pcrel = false; 4541 if (GET_CODE (x) == CONST 4542 && GET_CODE (XEXP (x, 0)) == UNSPEC) 4543 { 4544 addr = XVECEXP (XEXP (x, 0), 0, 0); 4545 switch (XINT (XEXP (x, 0), 1)) 4546 { 4547 case UNSPEC_GOT32_SYM: 4548 opstr = "got_ha16"; 4549 break; 4550 case UNSPEC_PCREL_SYM: 4551 opstr = "ha16"; 4552 pcrel = true; 4553 break; 4554 case UNSPEC_TLS_GD: 4555 opstr = "tls_gd_ha16"; 4556 break; 4557 case UNSPEC_TLS_IE: 4558 opstr = "tls_ie_ha16"; 4559 break; 4560 case UNSPEC_TLS_LE: 4561 opstr = "tls_le_ha16"; 4562 break; 4563 default: 4564 output_operand_lossage ("invalid %%H operand"); 4565 } 4566 } 4567 else 4568 { 4569 addr = x; 4570 opstr = "ha16"; 4571 } 4572 4573 fputs (opstr, file); 4574 fputc ('(', file); 4575 output_addr_const (file, addr); 4576 4577 if (pcrel) 4578 { 4579 rtx addr2 = XVECEXP (XEXP (x, 0), 0, 1); 4580 fputs (" - " , file); 4581 output_addr_const (file, addr2); 4582 } 4583 4584 fputc (')', file); 4585 return; 4586 } 4587 4588 case 'I': 4589 /* Print an auto-inc memory operand. */ 4590 if (!MEM_P (x)) 4591 { 4592 output_operand_lossage ("invalid %%I operand"); 4593 return; 4594 } 4595 4596 output_memory_autoinc_first = true; 4597 output_address (GET_MODE (x), XEXP (x, 0)); 4598 return; 4599 4600 case 'i': 4601 /* Print an auto-inc memory operand. */ 4602 if (!MEM_P (x)) 4603 { 4604 output_operand_lossage ("invalid %%i operand"); 4605 return; 4606 } 4607 4608 output_memory_autoinc_first = false; 4609 output_address (GET_MODE (x), XEXP (x, 0)); 4610 return; 4611 4612 case 'j': 4613 { 4614 /* Print the low 8 bits of a constant. */ 4615 HOST_WIDE_INT i; 4616 if (CONST_INT_P (x)) 4617 i = INTVAL (x); 4618 else if (GET_CODE (x) == CONST_DOUBLE) 4619 i = CONST_DOUBLE_LOW (x); 4620 else if (GET_CODE (x) == CONST_VECTOR 4621 && CONST_INT_P (CONST_VECTOR_ELT (x, 0))) 4622 i = INTVAL (CONST_VECTOR_ELT (x, 0)); 4623 else 4624 { 4625 output_operand_lossage ("invalid %%j operand"); 4626 return; 4627 } 4628 i = trunc_int_for_mode (i, QImode); 4629 fprintf (file, HOST_WIDE_INT_PRINT_DEC, i); 4630 return; 4631 } 4632 4633 case 'L': 4634 { 4635 rtx addr = NULL; 4636 const char *opstr = NULL; 4637 bool pcrel = false; 4638 if (GET_CODE (x) == CONST 4639 && GET_CODE (XEXP (x, 0)) == UNSPEC) 4640 { 4641 addr = XVECEXP (XEXP (x, 0), 0, 0); 4642 switch (XINT (XEXP (x, 0), 1)) 4643 { 4644 case UNSPEC_GOT16_SYM: 4645 opstr = "got"; 4646 break; 4647 case UNSPEC_GOT32_SYM: 4648 opstr = "got_lo16"; 4649 break; 4650 case UNSPEC_PCREL_SYM: 4651 opstr = "lo16"; 4652 pcrel = true; 4653 break; 4654 case UNSPEC_TLS_GD: 4655 opstr = "tls_gd_lo16"; 4656 break; 4657 case UNSPEC_TLS_IE: 4658 opstr = "tls_ie_lo16"; 4659 break; 4660 case UNSPEC_TLS_LE: 4661 opstr = "tls_le_lo16"; 4662 break; 4663 default: 4664 output_operand_lossage ("invalid %%L operand"); 4665 } 4666 } 4667 else 4668 { 4669 addr = x; 4670 opstr = "lo16"; 4671 } 4672 4673 fputs (opstr, file); 4674 fputc ('(', file); 4675 output_addr_const (file, addr); 4676 4677 if (pcrel) 4678 { 4679 rtx addr2 = XVECEXP (XEXP (x, 0), 0, 1); 4680 fputs (" - " , file); 4681 output_addr_const (file, addr2); 4682 } 4683 4684 fputc (')', file); 4685 return; 4686 } 4687 4688 case 'p': 4689 if (GET_CODE (x) == SYMBOL_REF) 4690 { 4691 if (flag_pic && !SYMBOL_REF_LOCAL_P (x)) 4692 fprintf (file, "plt("); 4693 output_addr_const (file, x); 4694 if (flag_pic && !SYMBOL_REF_LOCAL_P (x)) 4695 fprintf (file, ")"); 4696 } 4697 else 4698 output_addr_const (file, x); 4699 return; 4700 4701 case 'P': 4702 { 4703 /* Print a 32-bit constant plus one. */ 4704 HOST_WIDE_INT i; 4705 if (!CONST_INT_P (x)) 4706 { 4707 output_operand_lossage ("invalid %%P operand"); 4708 return; 4709 } 4710 i = trunc_int_for_mode (INTVAL (x) + 1, SImode); 4711 fprintf (file, HOST_WIDE_INT_PRINT_DEC, i); 4712 return; 4713 } 4714 4715 case 'M': 4716 { 4717 /* Print an mm-style bit range. */ 4718 int first_bit, last_bit; 4719 4720 if (!CONST_INT_P (x) 4721 || !tilepro_bitfield_operand_p (INTVAL (x), &first_bit, 4722 &last_bit)) 4723 { 4724 output_operand_lossage ("invalid %%M operand"); 4725 return; 4726 } 4727 4728 fprintf (file, "%d, %d", first_bit, last_bit); 4729 return; 4730 } 4731 4732 case 'N': 4733 { 4734 const char *reg = NULL; 4735 4736 /* Print a network register. */ 4737 if (!CONST_INT_P (x)) 4738 { 4739 output_operand_lossage ("invalid %%N operand"); 4740 return; 4741 } 4742 4743 switch (INTVAL (x)) 4744 { 4745 case TILEPRO_NETREG_IDN0: reg = "idn0"; break; 4746 case TILEPRO_NETREG_IDN1: reg = "idn1"; break; 4747 case TILEPRO_NETREG_SN: reg = "sn"; break; 4748 case TILEPRO_NETREG_UDN0: reg = "udn0"; break; 4749 case TILEPRO_NETREG_UDN1: reg = "udn1"; break; 4750 case TILEPRO_NETREG_UDN2: reg = "udn2"; break; 4751 case TILEPRO_NETREG_UDN3: reg = "udn3"; break; 4752 default: gcc_unreachable (); 4753 } 4754 4755 fprintf (file, reg); 4756 return; 4757 } 4758 4759 case 't': 4760 { 4761 /* Log base 2 of a power of two. */ 4762 HOST_WIDE_INT i; 4763 HOST_WIDE_INT n; 4764 4765 if (!CONST_INT_P (x)) 4766 { 4767 output_operand_lossage ("invalid %%t operand"); 4768 return; 4769 } 4770 n = trunc_int_for_mode (INTVAL (x), SImode); 4771 i = exact_log2 (n); 4772 if (i < 0) 4773 { 4774 output_operand_lossage ("invalid %%t operand '" 4775 HOST_WIDE_INT_PRINT_DEC "'", n); 4776 return; 4777 } 4778 4779 fprintf (file, HOST_WIDE_INT_PRINT_DEC, i); 4780 return; 4781 } 4782 break; 4783 4784 case 'r': 4785 /* In this case we need a register. Use 'zero' if the 4786 operand is const0_rtx. */ 4787 if (x == const0_rtx 4788 || (GET_MODE (x) != VOIDmode && x == CONST0_RTX (GET_MODE (x)))) 4789 { 4790 fputs ("zero", file); 4791 return; 4792 } 4793 else if (!REG_P (x)) 4794 { 4795 output_operand_lossage ("invalid %%r operand"); 4796 return; 4797 } 4798 /* FALLTHRU */ 4799 4800 case 0: 4801 if (REG_P (x)) 4802 { 4803 fprintf (file, "%s", reg_names[REGNO (x)]); 4804 return; 4805 } 4806 else if (MEM_P (x)) 4807 { 4808 output_address (VOIDmode, XEXP (x, 0)); 4809 return; 4810 } 4811 else 4812 { 4813 output_addr_const (file, x); 4814 return; 4815 } 4816 break; 4817 } 4818 4819 debug_rtx (x); 4820 output_operand_lossage ("unable to print out operand yet; code == %d (%c)", 4821 code, code); 4822 } 4823 4824 4825 /* Implement TARGET_PRINT_OPERAND_ADDRESS. */ 4826 static void 4827 tilepro_print_operand_address (FILE *file, machine_mode mode, rtx addr) 4828 { 4829 if (GET_CODE (addr) == POST_DEC 4830 || GET_CODE (addr) == POST_INC) 4831 { 4832 int offset = GET_MODE_SIZE (mode); 4833 4834 gcc_assert (mode != VOIDmode); 4835 4836 if (output_memory_autoinc_first) 4837 fprintf (file, "%s", reg_names[REGNO (XEXP (addr, 0))]); 4838 else 4839 fprintf (file, "%d", 4840 GET_CODE (addr) == POST_DEC ? -offset : offset); 4841 } 4842 else if (GET_CODE (addr) == POST_MODIFY) 4843 { 4844 gcc_assert (mode != VOIDmode); 4845 4846 gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS); 4847 4848 if (output_memory_autoinc_first) 4849 fprintf (file, "%s", reg_names[REGNO (XEXP (addr, 0))]); 4850 else 4851 fprintf (file, HOST_WIDE_INT_PRINT_DEC, 4852 INTVAL (XEXP (XEXP (addr, 1), 1))); 4853 } 4854 else 4855 tilepro_print_operand (file, addr, 'r'); 4856 } 4857 4858 4859 /* Machine mode of current insn, for determining curly brace 4860 placement. */ 4861 static machine_mode insn_mode; 4862 4863 4864 /* Implement FINAL_PRESCAN_INSN. This is used to emit bundles. */ 4865 void 4866 tilepro_final_prescan_insn (rtx_insn *insn) 4867 { 4868 /* Record this for tilepro_asm_output_opcode to examine. */ 4869 insn_mode = GET_MODE (insn); 4870 } 4871 4872 4873 /* While emitting asm, are we currently inside '{' for a bundle? */ 4874 static bool tilepro_in_bundle = false; 4875 4876 /* Implement ASM_OUTPUT_OPCODE. Prepend/append curly braces as 4877 appropriate given the bundling information recorded by 4878 tilepro_gen_bundles. */ 4879 const char * 4880 tilepro_asm_output_opcode (FILE *stream, const char *code) 4881 { 4882 bool pseudo = !strcmp (code, "pseudo"); 4883 4884 if (!tilepro_in_bundle && insn_mode == SImode) 4885 { 4886 /* Start a new bundle. */ 4887 fprintf (stream, "{\n\t"); 4888 tilepro_in_bundle = true; 4889 } 4890 4891 if (tilepro_in_bundle && insn_mode == QImode) 4892 { 4893 /* Close an existing bundle. */ 4894 static char buf[100]; 4895 4896 gcc_assert (strlen (code) + 3 + 1 < sizeof (buf)); 4897 4898 strcpy (buf, pseudo ? "" : code); 4899 strcat (buf, "\n\t}"); 4900 tilepro_in_bundle = false; 4901 4902 return buf; 4903 } 4904 else 4905 { 4906 return pseudo ? "" : code; 4907 } 4908 } 4909 4910 4911 /* Output assembler code to FILE to increment profiler label # LABELNO 4912 for profiling a function entry. */ 4913 void 4914 tilepro_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) 4915 { 4916 if (tilepro_in_bundle) 4917 { 4918 fprintf (file, "\t}\n"); 4919 } 4920 4921 if (flag_pic) 4922 { 4923 fprintf (file, 4924 "\t{\n" 4925 "\tmove\tr10, lr\n" 4926 "\tjal\tplt(%s)\n" 4927 "\t}\n", MCOUNT_NAME); 4928 } 4929 else 4930 { 4931 fprintf (file, 4932 "\t{\n" 4933 "\tmove\tr10, lr\n" 4934 "\tjal\t%s\n" 4935 "\t}\n", MCOUNT_NAME); 4936 } 4937 4938 tilepro_in_bundle = false; 4939 } 4940 4941 4942 /* Implement TARGET_ASM_FILE_END. */ 4943 static void 4944 tilepro_file_end (void) 4945 { 4946 if (NEED_INDICATE_EXEC_STACK) 4947 file_end_indicate_exec_stack (); 4948 } 4949 4950 4951 #undef TARGET_HAVE_TLS 4952 #define TARGET_HAVE_TLS HAVE_AS_TLS 4953 4954 #undef TARGET_OPTION_OVERRIDE 4955 #define TARGET_OPTION_OVERRIDE tilepro_option_override 4956 4957 #ifdef TARGET_THREAD_SSP_OFFSET 4958 #undef TARGET_STACK_PROTECT_GUARD 4959 #define TARGET_STACK_PROTECT_GUARD hook_tree_void_null 4960 #endif 4961 4962 #undef TARGET_SCALAR_MODE_SUPPORTED_P 4963 #define TARGET_SCALAR_MODE_SUPPORTED_P tilepro_scalar_mode_supported_p 4964 4965 #undef TARGET_VECTOR_MODE_SUPPORTED_P 4966 #define TARGET_VECTOR_MODE_SUPPORTED_P tile_vector_mode_supported_p 4967 4968 #undef TARGET_CANNOT_FORCE_CONST_MEM 4969 #define TARGET_CANNOT_FORCE_CONST_MEM tilepro_cannot_force_const_mem 4970 4971 #undef TARGET_FUNCTION_OK_FOR_SIBCALL 4972 #define TARGET_FUNCTION_OK_FOR_SIBCALL tilepro_function_ok_for_sibcall 4973 4974 #undef TARGET_PASS_BY_REFERENCE 4975 #define TARGET_PASS_BY_REFERENCE tilepro_pass_by_reference 4976 4977 #undef TARGET_RETURN_IN_MEMORY 4978 #define TARGET_RETURN_IN_MEMORY tilepro_return_in_memory 4979 4980 #undef TARGET_FUNCTION_ARG_BOUNDARY 4981 #define TARGET_FUNCTION_ARG_BOUNDARY tilepro_function_arg_boundary 4982 4983 #undef TARGET_FUNCTION_ARG 4984 #define TARGET_FUNCTION_ARG tilepro_function_arg 4985 4986 #undef TARGET_FUNCTION_ARG_ADVANCE 4987 #define TARGET_FUNCTION_ARG_ADVANCE tilepro_function_arg_advance 4988 4989 #undef TARGET_FUNCTION_VALUE 4990 #define TARGET_FUNCTION_VALUE tilepro_function_value 4991 4992 #undef TARGET_LIBCALL_VALUE 4993 #define TARGET_LIBCALL_VALUE tilepro_libcall_value 4994 4995 #undef TARGET_FUNCTION_VALUE_REGNO_P 4996 #define TARGET_FUNCTION_VALUE_REGNO_P tilepro_function_value_regno_p 4997 4998 #undef TARGET_PROMOTE_FUNCTION_MODE 4999 #define TARGET_PROMOTE_FUNCTION_MODE \ 5000 default_promote_function_mode_always_promote 5001 5002 #undef TARGET_PROMOTE_PROTOTYPES 5003 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false 5004 5005 #undef TARGET_BUILD_BUILTIN_VA_LIST 5006 #define TARGET_BUILD_BUILTIN_VA_LIST tilepro_build_builtin_va_list 5007 5008 #undef TARGET_EXPAND_BUILTIN_VA_START 5009 #define TARGET_EXPAND_BUILTIN_VA_START tilepro_va_start 5010 5011 #undef TARGET_SETUP_INCOMING_VARARGS 5012 #define TARGET_SETUP_INCOMING_VARARGS tilepro_setup_incoming_varargs 5013 5014 #undef TARGET_GIMPLIFY_VA_ARG_EXPR 5015 #define TARGET_GIMPLIFY_VA_ARG_EXPR tilepro_gimplify_va_arg_expr 5016 5017 #undef TARGET_RTX_COSTS 5018 #define TARGET_RTX_COSTS tilepro_rtx_costs 5019 5020 /* Limit to what we can reach in one addli. */ 5021 #undef TARGET_MIN_ANCHOR_OFFSET 5022 #define TARGET_MIN_ANCHOR_OFFSET -32768 5023 #undef TARGET_MAX_ANCHOR_OFFSET 5024 #define TARGET_MAX_ANCHOR_OFFSET 32767 5025 5026 #undef TARGET_LEGITIMATE_CONSTANT_P 5027 #define TARGET_LEGITIMATE_CONSTANT_P tilepro_legitimate_constant_p 5028 5029 #undef TARGET_LRA_P 5030 #define TARGET_LRA_P hook_bool_void_false 5031 5032 #undef TARGET_LEGITIMATE_ADDRESS_P 5033 #define TARGET_LEGITIMATE_ADDRESS_P tilepro_legitimate_address_p 5034 5035 #undef TARGET_LEGITIMIZE_ADDRESS 5036 #define TARGET_LEGITIMIZE_ADDRESS tilepro_legitimize_address 5037 5038 #undef TARGET_DELEGITIMIZE_ADDRESS 5039 #define TARGET_DELEGITIMIZE_ADDRESS tilepro_delegitimize_address 5040 5041 #undef TARGET_INIT_BUILTINS 5042 #define TARGET_INIT_BUILTINS tilepro_init_builtins 5043 5044 #undef TARGET_BUILTIN_DECL 5045 #define TARGET_BUILTIN_DECL tilepro_builtin_decl 5046 5047 #undef TARGET_EXPAND_BUILTIN 5048 #define TARGET_EXPAND_BUILTIN tilepro_expand_builtin 5049 5050 #undef TARGET_CONDITIONAL_REGISTER_USAGE 5051 #define TARGET_CONDITIONAL_REGISTER_USAGE tilepro_conditional_register_usage 5052 5053 #undef TARGET_FRAME_POINTER_REQUIRED 5054 #define TARGET_FRAME_POINTER_REQUIRED tilepro_frame_pointer_required 5055 5056 #undef TARGET_DELAY_SCHED2 5057 #define TARGET_DELAY_SCHED2 true 5058 5059 #undef TARGET_DELAY_VARTRACK 5060 #define TARGET_DELAY_VARTRACK true 5061 5062 #undef TARGET_SCHED_ISSUE_RATE 5063 #define TARGET_SCHED_ISSUE_RATE tilepro_issue_rate 5064 5065 #undef TARGET_SCHED_ADJUST_COST 5066 #define TARGET_SCHED_ADJUST_COST tilepro_sched_adjust_cost 5067 5068 #undef TARGET_MACHINE_DEPENDENT_REORG 5069 #define TARGET_MACHINE_DEPENDENT_REORG tilepro_reorg 5070 5071 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK 5072 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \ 5073 hook_bool_const_tree_hwi_hwi_const_tree_true 5074 5075 #undef TARGET_ASM_OUTPUT_MI_THUNK 5076 #define TARGET_ASM_OUTPUT_MI_THUNK tilepro_asm_output_mi_thunk 5077 5078 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE 5079 #define TARGET_ASM_TRAMPOLINE_TEMPLATE tilepro_asm_trampoline_template 5080 5081 #undef TARGET_TRAMPOLINE_INIT 5082 #define TARGET_TRAMPOLINE_INIT tilepro_trampoline_init 5083 5084 #undef TARGET_PRINT_OPERAND 5085 #define TARGET_PRINT_OPERAND tilepro_print_operand 5086 5087 #undef TARGET_PRINT_OPERAND_ADDRESS 5088 #define TARGET_PRINT_OPERAND_ADDRESS tilepro_print_operand_address 5089 5090 #undef TARGET_ASM_FILE_END 5091 #define TARGET_ASM_FILE_END tilepro_file_end 5092 5093 #undef TARGET_CAN_USE_DOLOOP_P 5094 #define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost 5095 5096 #undef TARGET_CONSTANT_ALIGNMENT 5097 #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings 5098 5099 struct gcc_target targetm = TARGET_INITIALIZER; 5100 5101 #include "gt-tilepro.h" 5102