1/* Output routines for Visium. 2 Copyright (C) 2002-2015 Free Software Foundation, Inc. 3 Contributed by C.Nettleton, J.P.Parkes and P.Garbett. 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#include "config.h" 22#include "system.h" 23#include "coretypes.h" 24#include "tm.h" 25#include "hashtab.h" 26#include "hash-set.h" 27#include "machmode.h" 28#include "input.h" 29#include "statistics.h" 30#include "vec.h" 31#include "double-int.h" 32#include "real.h" 33#include "fixed-value.h" 34#include "alias.h" 35#include "flags.h" 36#include "symtab.h" 37#include "tree-core.h" 38#include "wide-int.h" 39#include "inchash.h" 40#include "fold-const.h" 41#include "tree-check.h" 42#include "tree.h" 43#include "stringpool.h" 44#include "stor-layout.h" 45#include "calls.h" 46#include "varasm.h" 47#include "rtl.h" 48#include "regs.h" 49#include "hard-reg-set.h" 50#include "insn-config.h" 51#include "conditions.h" 52#include "output.h" 53#include "insn-attr.h" 54#include "function.h" 55#include "expmed.h" 56#include "dojump.h" 57#include "explow.h" 58#include "emit-rtl.h" 59#include "stmt.h" 60#include "expr.h" 61#include "recog.h" 62#include "diagnostic-core.h" 63#include "tm_p.h" 64#include "ggc.h" 65#include "optabs.h" 66#include "target.h" 67#include "target-def.h" 68#include "common/common-target.h" 69#include "predict.h" 70#include "basic-block.h" 71#include "gimple-expr.h" 72#include "gimplify.h" 73#include "langhooks.h" 74#include "reload.h" 75#include "tm-constrs.h" 76#include "df.h" 77#include "params.h" 78#include "errors.h" 79#include "tree-pass.h" 80#include "context.h" 81#include "builtins.h" 82 83/* Machine specific function data. */ 84struct GTY (()) machine_function 85{ 86 /* Size of the frame of the function. */ 87 int frame_size; 88 89 /* Size of the reg parm save area, non-zero only for functions with variable 90 argument list. We cannot use the crtl->args.pretend_args_size machinery 91 for this purpose because this size is added to virtual_incoming_args_rtx 92 to give the location of the first parameter passed by the caller on the 93 stack and virtual_incoming_args_rtx is also the location of the first 94 parameter on the stack. So crtl->args.pretend_args_size can be non-zero 95 only if the first non-register named parameter is not passed entirely on 96 the stack and this runs afoul of the need to have a reg parm save area 97 even with a variable argument list starting on the stack because of the 98 separate handling of general and floating-point registers. */ 99 int reg_parm_save_area_size; 100 101 /* True if we have created an rtx which relies on the frame pointer. */ 102 bool frame_needed; 103 104 /* True if we have exposed the flags register. From this moment on, we 105 cannot generate simple operations for integer registers. We could 106 use reload_completed for this purpose, but this would cripple the 107 postreload CSE and GCSE passes which run before postreload split. */ 108 bool flags_exposed; 109}; 110 111#define visium_frame_size cfun->machine->frame_size 112#define visium_reg_parm_save_area_size cfun->machine->reg_parm_save_area_size 113#define visium_frame_needed cfun->machine->frame_needed 114#define visium_flags_exposed cfun->machine->flags_exposed 115 116/* 1 if the next opcode is to be specially indented. */ 117int visium_indent_opcode = 0; 118 119/* Register number used for long branches when LR isn't available. It 120 must be a call-used register since it isn't saved on function entry. 121 We do not care whether the branch is predicted or not on the GR6, 122 given how unlikely it is to have a long branch in a leaf function. */ 123static unsigned int long_branch_regnum = 31; 124 125static void visium_output_address (FILE *, enum machine_mode, rtx); 126static tree visium_handle_interrupt_attr (tree *, tree, tree, int, bool *); 127static inline bool current_function_saves_fp (void); 128static inline bool current_function_saves_lr (void); 129static inline bool current_function_has_lr_slot (void); 130 131/* Supported attributes: 132 interrupt -- specifies this function is an interrupt handler. */ 133static const struct attribute_spec visium_attribute_table[] = 134{ 135 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, 136 affects_type_identity } */ 137 {"interrupt", 0, 0, true, false, false, visium_handle_interrupt_attr, false}, 138 {NULL, 0, 0, false, false, false, NULL, false} 139}; 140 141static struct machine_function *visium_init_machine_status (void); 142 143/* Target hooks and TARGET_INITIALIZER */ 144 145static bool visium_pass_by_reference (cumulative_args_t, enum machine_mode, 146 const_tree, bool); 147 148static rtx visium_function_arg (cumulative_args_t, enum machine_mode, 149 const_tree, bool); 150 151static void visium_function_arg_advance (cumulative_args_t, enum machine_mode, 152 const_tree, bool); 153 154static bool visium_return_in_memory (const_tree, const_tree fntype); 155 156static rtx visium_function_value (const_tree, const_tree fn_decl_or_type, 157 bool); 158 159static rtx visium_libcall_value (enum machine_mode, const_rtx); 160 161static void visium_setup_incoming_varargs (cumulative_args_t, 162 enum machine_mode, 163 tree, int *, int); 164 165static void visium_va_start (tree valist, rtx nextarg); 166 167static tree visium_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *); 168 169static bool visium_function_ok_for_sibcall (tree, tree); 170 171static bool visium_frame_pointer_required (void); 172 173static tree visium_build_builtin_va_list (void); 174 175static tree visium_md_asm_clobbers (tree, tree, tree); 176 177static bool visium_legitimate_constant_p (enum machine_mode, rtx); 178 179static bool visium_legitimate_address_p (enum machine_mode, rtx, bool); 180 181static void visium_conditional_register_usage (void); 182 183static rtx visium_legitimize_address (rtx, rtx, enum machine_mode); 184 185static reg_class_t visium_secondary_reload (bool, rtx, reg_class_t, 186 enum machine_mode, 187 secondary_reload_info *); 188 189static bool visium_class_likely_spilled_p (reg_class_t); 190 191static void visium_trampoline_init (rtx, tree, rtx); 192 193static int visium_issue_rate (void); 194 195static int visium_adjust_priority (rtx_insn *, int); 196 197static int visium_adjust_cost (rtx_insn *, rtx, rtx_insn *, int); 198 199static int visium_register_move_cost (enum machine_mode, reg_class_t, 200 reg_class_t); 201 202static int visium_memory_move_cost (enum machine_mode, reg_class_t, bool); 203 204static bool visium_rtx_costs (rtx, int, int, int, int *, bool); 205 206static void visium_option_override (void); 207 208static unsigned int visium_reorg (void); 209 210/* Setup the global target hooks structure. */ 211 212#undef TARGET_MAX_ANCHOR_OFFSET 213#define TARGET_MAX_ANCHOR_OFFSET 31 214 215#undef TARGET_PASS_BY_REFERENCE 216#define TARGET_PASS_BY_REFERENCE visium_pass_by_reference 217 218#undef TARGET_FUNCTION_ARG 219#define TARGET_FUNCTION_ARG visium_function_arg 220 221#undef TARGET_FUNCTION_ARG_ADVANCE 222#define TARGET_FUNCTION_ARG_ADVANCE visium_function_arg_advance 223 224#undef TARGET_RETURN_IN_MEMORY 225#define TARGET_RETURN_IN_MEMORY visium_return_in_memory 226 227#undef TARGET_FUNCTION_VALUE 228#define TARGET_FUNCTION_VALUE visium_function_value 229 230#undef TARGET_LIBCALL_VALUE 231#define TARGET_LIBCALL_VALUE visium_libcall_value 232 233#undef TARGET_SETUP_INCOMING_VARARGS 234#define TARGET_SETUP_INCOMING_VARARGS visium_setup_incoming_varargs 235 236#undef TARGET_EXPAND_BUILTIN_VA_START 237#define TARGET_EXPAND_BUILTIN_VA_START visium_va_start 238 239#undef TARGET_BUILD_BUILTIN_VA_LIST 240#define TARGET_BUILD_BUILTIN_VA_LIST visium_build_builtin_va_list 241 242#undef TARGET_GIMPLIFY_VA_ARG_EXPR 243#define TARGET_GIMPLIFY_VA_ARG_EXPR visium_gimplify_va_arg 244 245#undef TARGET_LEGITIMATE_CONSTANT_P 246#define TARGET_LEGITIMATE_CONSTANT_P visium_legitimate_constant_p 247 248#undef TARGET_LEGITIMATE_ADDRESS_P 249#define TARGET_LEGITIMATE_ADDRESS_P visium_legitimate_address_p 250 251#undef TARGET_ATTRIBUTE_TABLE 252#define TARGET_ATTRIBUTE_TABLE visium_attribute_table 253 254#undef TARGET_ADDRESS_COST 255#define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0 256 257#undef TARGET_STRICT_ARGUMENT_NAMING 258#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true 259 260#undef TARGET_SCHED_ISSUE_RATE 261#define TARGET_SCHED_ISSUE_RATE visium_issue_rate 262 263#undef TARGET_SCHED_ADJUST_PRIORITY 264#define TARGET_SCHED_ADJUST_PRIORITY visium_adjust_priority 265 266#undef TARGET_SCHED_ADJUST_COST 267#define TARGET_SCHED_ADJUST_COST visium_adjust_cost 268 269#undef TARGET_MEMORY_MOVE_COST 270#define TARGET_MEMORY_MOVE_COST visium_memory_move_cost 271 272#undef TARGET_REGISTER_MOVE_COST 273#define TARGET_REGISTER_MOVE_COST visium_register_move_cost 274 275#undef TARGET_RTX_COSTS 276#define TARGET_RTX_COSTS visium_rtx_costs 277 278#undef TARGET_FUNCTION_OK_FOR_SIBCALL 279#define TARGET_FUNCTION_OK_FOR_SIBCALL visium_function_ok_for_sibcall 280 281#undef TARGET_FRAME_POINTER_REQUIRED 282#define TARGET_FRAME_POINTER_REQUIRED visium_frame_pointer_required 283 284#undef TARGET_SECONDARY_RELOAD 285#define TARGET_SECONDARY_RELOAD visium_secondary_reload 286 287#undef TARGET_CLASS_LIKELY_SPILLED_P 288#define TARGET_CLASS_LIKELY_SPILLED_P visium_class_likely_spilled_p 289 290#undef TARGET_LEGITIMIZE_ADDRESS 291#define TARGET_LEGITIMIZE_ADDRESS visium_legitimize_address 292 293#undef TARGET_OPTION_OVERRIDE 294#define TARGET_OPTION_OVERRIDE visium_option_override 295 296#undef TARGET_CONDITIONAL_REGISTER_USAGE 297#define TARGET_CONDITIONAL_REGISTER_USAGE visium_conditional_register_usage 298 299#undef TARGET_TRAMPOLINE_INIT 300#define TARGET_TRAMPOLINE_INIT visium_trampoline_init 301 302#undef TARGET_MD_ASM_CLOBBERS 303#define TARGET_MD_ASM_CLOBBERS visium_md_asm_clobbers 304 305#undef TARGET_FLAGS_REGNUM 306#define TARGET_FLAGS_REGNUM FLAGS_REGNUM 307 308struct gcc_target targetm = TARGET_INITIALIZER; 309 310namespace { 311 312const pass_data pass_data_visium_reorg = 313{ 314 RTL_PASS, /* type */ 315 "mach2", /* name */ 316 OPTGROUP_NONE, /* optinfo_flags */ 317 TV_MACH_DEP, /* tv_id */ 318 0, /* properties_required */ 319 0, /* properties_provided */ 320 0, /* properties_destroyed */ 321 0, /* todo_flags_start */ 322 0, /* todo_flags_finish */ 323}; 324 325class pass_visium_reorg : public rtl_opt_pass 326{ 327public: 328 pass_visium_reorg(gcc::context *ctxt) 329 : rtl_opt_pass(pass_data_visium_reorg, ctxt) 330 {} 331 332 /* opt_pass methods: */ 333 virtual unsigned int execute (function *) 334 { 335 return visium_reorg (); 336 } 337 338}; // class pass_work_around_errata 339 340} // anon namespace 341 342rtl_opt_pass * 343make_pass_visium_reorg (gcc::context *ctxt) 344{ 345 return new pass_visium_reorg (ctxt); 346} 347 348/* Options override for Visium. */ 349 350static void 351visium_option_override (void) 352{ 353 if (flag_pic == 1) 354 warning (OPT_fpic, "-fpic is not supported"); 355 if (flag_pic == 2) 356 warning (OPT_fPIC, "-fPIC is not supported"); 357 358 /* MCM is the default in the GR5/GR6 era. */ 359 target_flags |= MASK_MCM; 360 361 /* FPU is the default with MCM, but don't override an explicit option. */ 362 if ((target_flags_explicit & MASK_FPU) == 0) 363 target_flags |= MASK_FPU; 364 365 /* The supervisor mode is the default. */ 366 if ((target_flags_explicit & MASK_SV_MODE) == 0) 367 target_flags |= MASK_SV_MODE; 368 369 /* The GR6 has the Block Move Instructions and an IEEE-compliant FPU. */ 370 if (visium_cpu_and_features == PROCESSOR_GR6) 371 { 372 target_flags |= MASK_BMI; 373 if (target_flags & MASK_FPU) 374 target_flags |= MASK_FPU_IEEE; 375 } 376 377 /* Set -mtune from -mcpu if not specified. */ 378 if (!global_options_set.x_visium_cpu) 379 visium_cpu = visium_cpu_and_features; 380 381 /* Align functions on 256-byte (32-quadword) for GR5 and 64-byte (8-quadword) 382 boundaries for GR6 so they start a new burst mode window. */ 383 if (align_functions == 0) 384 { 385 if (visium_cpu == PROCESSOR_GR6) 386 align_functions = 64; 387 else 388 align_functions = 256; 389 390 /* Allow the size of compilation units to double because of inlining. 391 In practice the global size of the object code is hardly affected 392 because the additional instructions will take up the padding. */ 393 maybe_set_param_value (PARAM_INLINE_UNIT_GROWTH, 100, 394 global_options.x_param_values, 395 global_options_set.x_param_values); 396 } 397 398 /* Likewise for loops. */ 399 if (align_loops == 0) 400 { 401 if (visium_cpu == PROCESSOR_GR6) 402 align_loops = 64; 403 else 404 { 405 align_loops = 256; 406 /* But not if they are too far away from a 256-byte boundary. */ 407 align_loops_max_skip = 31; 408 } 409 } 410 411 /* Align all jumps on quadword boundaries for the burst mode, and even 412 on 8-quadword boundaries for GR6 so they start a new window. */ 413 if (align_jumps == 0) 414 { 415 if (visium_cpu == PROCESSOR_GR6) 416 align_jumps = 64; 417 else 418 align_jumps = 8; 419 } 420 421 /* We register a machine-specific pass. This pass must be scheduled as 422 late as possible so that we have the (essentially) final form of the 423 insn stream to work on. Registering the pass must be done at start up. 424 It's convenient to do it here. */ 425 opt_pass *visium_reorg_pass = make_pass_visium_reorg (g); 426 struct register_pass_info insert_pass_visium_reorg = 427 { 428 visium_reorg_pass, /* pass */ 429 "dbr", /* reference_pass_name */ 430 1, /* ref_pass_instance_number */ 431 PASS_POS_INSERT_AFTER /* po_op */ 432 }; 433 register_pass (&insert_pass_visium_reorg); 434} 435 436/* Return the number of instructions that can issue on the same cycle. */ 437 438static int 439visium_issue_rate (void) 440{ 441 switch (visium_cpu) 442 { 443 case PROCESSOR_GR5: 444 return 1; 445 446 case PROCESSOR_GR6: 447 return 2; 448 449 default: 450 gcc_unreachable (); 451 } 452} 453 454/* Return the adjusted PRIORITY of INSN. */ 455 456static int 457visium_adjust_priority (rtx_insn *insn, int priority) 458{ 459 /* On the GR5, we slightly increase the priority of writes in order to avoid 460 scheduling a read on the next cycle. This is necessary in addition to the 461 associated insn reservation because there are no data dependencies. 462 We also slightly increase the priority of reads from ROM in order to group 463 them as much as possible. These reads are a bit problematic because they 464 conflict with the instruction fetches, i.e. the data and instruction buses 465 tread on each other's toes when they are executed. */ 466 if (visium_cpu == PROCESSOR_GR5 467 && reload_completed 468 && INSN_P (insn) 469 && recog_memoized (insn) >= 0) 470 { 471 enum attr_type attr_type = get_attr_type (insn); 472 if (attr_type == TYPE_REG_MEM 473 || (attr_type == TYPE_MEM_REG 474 && MEM_READONLY_P (SET_SRC (PATTERN (insn))))) 475 return priority + 1; 476 } 477 478 return priority; 479} 480 481/* Adjust the cost of a scheduling dependency. Return the new cost of 482 a dependency LINK of INSN on DEP_INSN. COST is the current cost. */ 483 484static int 485visium_adjust_cost (rtx_insn *insn, rtx link, rtx_insn *dep_insn, int cost) 486{ 487 enum attr_type attr_type; 488 489 /* Don't adjust costs for true dependencies as they are described with 490 bypasses. But we make an exception for the first scheduling pass to 491 help the subsequent postreload compare elimination pass. */ 492 if (REG_NOTE_KIND (link) == REG_DEP_TRUE) 493 { 494 if (!reload_completed 495 && recog_memoized (insn) >= 0 496 && get_attr_type (insn) == TYPE_CMP) 497 { 498 rtx pat = PATTERN (insn); 499 gcc_assert (GET_CODE (pat) == SET); 500 rtx src = SET_SRC (pat); 501 502 /* Only the branches can be modified by the postreload compare 503 elimination pass, not the cstores because they accept only 504 unsigned comparison operators and they are eliminated if 505 one of the operands is zero. */ 506 if (GET_CODE (src) == IF_THEN_ELSE 507 && XEXP (XEXP (src, 0), 1) == const0_rtx 508 && recog_memoized (dep_insn) >= 0) 509 { 510 enum attr_type dep_attr_type = get_attr_type (dep_insn); 511 512 /* The logical instructions use CCmode and thus work with any 513 comparison operator, whereas the arithmetic instructions use 514 CC_NOOVmode and thus work with only a small subset. */ 515 if (dep_attr_type == TYPE_LOGIC 516 || (dep_attr_type == TYPE_ARITH 517 && visium_noov_operator (XEXP (src, 0), 518 GET_MODE (XEXP (src, 0))))) 519 return 0; 520 } 521 } 522 523 return cost; 524 } 525 526 if (recog_memoized (insn) < 0) 527 return 0; 528 529 attr_type = get_attr_type (insn); 530 531 /* Anti dependency: DEP_INSN reads a register that INSN writes some 532 cycles later. */ 533 if (REG_NOTE_KIND (link) == REG_DEP_ANTI) 534 { 535 /* On the GR5, the latency of FP instructions needs to be taken into 536 account for every dependency involving a write. */ 537 if (attr_type == TYPE_REG_FP && visium_cpu == PROCESSOR_GR5) 538 { 539 /* INSN is FLOAD. */ 540 rtx pat = PATTERN (insn); 541 rtx dep_pat = PATTERN (dep_insn); 542 543 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) 544 /* If this happens, we have to extend this to schedule 545 optimally. Return 0 for now. */ 546 return 0; 547 548 if (reg_mentioned_p (SET_DEST (pat), SET_SRC (dep_pat))) 549 { 550 if (recog_memoized (dep_insn) < 0) 551 return 0; 552 553 switch (get_attr_type (dep_insn)) 554 { 555 case TYPE_FDIV: 556 case TYPE_FSQRT: 557 case TYPE_FTOI: 558 case TYPE_ITOF: 559 case TYPE_FP: 560 case TYPE_FMOVE: 561 /* A fload can't be issued until a preceding arithmetic 562 operation has finished if the target of the fload is 563 any of the sources (or destination) of the arithmetic 564 operation. Note that the latency may be (much) 565 greater than this if the preceding instruction 566 concerned is in a queue. */ 567 return insn_default_latency (dep_insn); 568 569 default: 570 return 0; 571 } 572 } 573 } 574 575 /* On the GR6, we try to make sure that the link register is restored 576 sufficiently ahead of the return as to yield a correct prediction 577 from the branch predictor. By default there is no true dependency 578 but an anti dependency between them, so we simply reuse it. */ 579 else if (attr_type == TYPE_RET && visium_cpu == PROCESSOR_GR6) 580 { 581 rtx dep_pat = PATTERN (dep_insn); 582 if (GET_CODE (dep_pat) == SET 583 && REG_P (SET_DEST (dep_pat)) 584 && REGNO (SET_DEST (dep_pat)) == LINK_REGNUM) 585 return 8; 586 } 587 588 /* For other anti dependencies, the cost is 0. */ 589 return 0; 590 } 591 592 /* Output dependency: DEP_INSN writes a register that INSN writes some 593 cycles later. */ 594 else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT) 595 { 596 /* On the GR5, the latency of FP instructions needs to be taken into 597 account for every dependency involving a write. */ 598 if (attr_type == TYPE_REG_FP && visium_cpu == PROCESSOR_GR5) 599 { 600 /* INSN is FLOAD. */ 601 rtx pat = PATTERN (insn); 602 rtx dep_pat = PATTERN (dep_insn); 603 604 if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET) 605 /* If this happens, we have to extend this to schedule 606 optimally. Return 0 for now. */ 607 return 0; 608 609 if (reg_mentioned_p (SET_DEST (pat), SET_DEST (dep_pat))) 610 { 611 if (recog_memoized (dep_insn) < 0) 612 return 0; 613 614 switch (get_attr_type (dep_insn)) 615 { 616 case TYPE_FDIV: 617 case TYPE_FSQRT: 618 case TYPE_FTOI: 619 case TYPE_ITOF: 620 case TYPE_FP: 621 case TYPE_FMOVE: 622 /* A fload can't be issued until a preceding arithmetic 623 operation has finished if the target of the fload is 624 the destination of the arithmetic operation. Note that 625 the latency may be (much) greater than this if the 626 preceding instruction concerned is in a queue. */ 627 return insn_default_latency (dep_insn); 628 629 default: 630 return 0; 631 } 632 } 633 } 634 635 /* For other output dependencies, the cost is 0. */ 636 return 0; 637 } 638 639 return 0; 640} 641 642/* Handle an "interrupt_handler" attribute; arguments as in 643 struct attribute_spec.handler. */ 644 645static tree 646visium_handle_interrupt_attr (tree *node, tree name, 647 tree args ATTRIBUTE_UNUSED, 648 int flags ATTRIBUTE_UNUSED, 649 bool *no_add_attrs) 650{ 651 if (TREE_CODE (*node) != FUNCTION_DECL) 652 { 653 warning (OPT_Wattributes, "%qE attribute only applies to functions", 654 name); 655 *no_add_attrs = true; 656 } 657 else if (!TARGET_SV_MODE) 658 { 659 error ("an interrupt handler cannot be compiled with -muser-mode"); 660 *no_add_attrs = true; 661 } 662 663 return NULL_TREE; 664} 665 666/* Return non-zero if the current function is an interrupt function. */ 667 668int 669visium_interrupt_function_p (void) 670{ 671 return 672 lookup_attribute ("interrupt", 673 DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE; 674} 675 676/* Conditionally modify the settings of the register file. */ 677 678static void 679visium_conditional_register_usage (void) 680{ 681 /* If the supervisor mode is disabled, mask some general registers. */ 682 if (!TARGET_SV_MODE) 683 { 684 if (visium_cpu_and_features == PROCESSOR_GR5) 685 { 686 fixed_regs[24] = call_used_regs[24] = 1; 687 fixed_regs[25] = call_used_regs[25] = 1; 688 fixed_regs[26] = call_used_regs[26] = 1; 689 fixed_regs[27] = call_used_regs[27] = 1; 690 fixed_regs[28] = call_used_regs[28] = 1; 691 call_really_used_regs[24] = 0; 692 call_really_used_regs[25] = 0; 693 call_really_used_regs[26] = 0; 694 call_really_used_regs[27] = 0; 695 call_really_used_regs[28] = 0; 696 } 697 698 fixed_regs[31] = call_used_regs[31] = 1; 699 call_really_used_regs[31] = 0; 700 701 /* We also need to change the long-branch register. */ 702 if (visium_cpu_and_features == PROCESSOR_GR5) 703 long_branch_regnum = 20; 704 else 705 long_branch_regnum = 28; 706 } 707 708 /* If the FPU is disabled, mask the FP registers. */ 709 if (!TARGET_FPU) 710 { 711 for (int i = FP_FIRST_REGNUM; i <= FP_LAST_REGNUM; i++) 712 { 713 fixed_regs[i] = call_used_regs[i] = 1; 714 call_really_used_regs[i] = 0; 715 } 716 } 717} 718 719/* Prepend to CLOBBERS hard registers that are automatically clobbered for 720 an asm We do this for the FLAGS to maintain source compatibility with 721 the original cc0-based compiler. */ 722 723static tree 724visium_md_asm_clobbers (tree outputs ATTRIBUTE_UNUSED, 725 tree inputs ATTRIBUTE_UNUSED, 726 tree clobbers) 727{ 728 const char *flags = reg_names[FLAGS_REGNUM]; 729 return tree_cons (NULL_TREE, build_string (strlen (flags), flags), clobbers); 730} 731 732/* Return true if X is a legitimate constant for a MODE immediate operand. 733 X is guaranteed to satisfy the CONSTANT_P predicate. */ 734 735static bool 736visium_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, 737 rtx x ATTRIBUTE_UNUSED) 738{ 739 return true; 740} 741 742/* Compute the alignment for a variable. The alignment of an aggregate is 743 set to be at least that of a scalar less than or equal to it in size. */ 744 745unsigned int 746visium_data_alignment (tree type, unsigned int align) 747{ 748 if (AGGREGATE_TYPE_P (type) 749 && TYPE_SIZE (type) 750 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST && align < 32) 751 { 752 if (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 32) 753 return 32; 754 755 if (TREE_INT_CST_LOW (TYPE_SIZE (type)) >= 16 && align < 16) 756 return 16; 757 } 758 759 return align; 760} 761 762/* Helper function for HARD_REGNO_RENAME_OK (FROM, TO). Return non-zero if 763 it is OK to rename a hard register FROM to another hard register TO. */ 764 765int 766visium_hard_regno_rename_ok (unsigned int from ATTRIBUTE_UNUSED, 767 unsigned int to) 768{ 769 /* If the function doesn't save LR, then the long-branch register will be 770 used for long branches so we need to know whether it is live before the 771 frame layout is computed. */ 772 if (!current_function_saves_lr () && to == long_branch_regnum) 773 return 0; 774 775 /* Interrupt functions can only use registers that have already been 776 saved by the prologue, even if they would normally be call-clobbered. */ 777 if (crtl->is_leaf 778 && !df_regs_ever_live_p (to) 779 && visium_interrupt_function_p ()) 780 return 0; 781 782 return 1; 783} 784 785/* Return true if it is ok to do sibling call optimization for the specified 786 call expression EXP. DECL will be the called function, or NULL if this 787 is an indirect call. */ 788 789static bool 790visium_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, 791 tree exp ATTRIBUTE_UNUSED) 792{ 793 return !visium_interrupt_function_p (); 794} 795 796/* Prepare operands for a move define_expand in MODE. */ 797 798void 799prepare_move_operands (rtx *operands, enum machine_mode mode) 800{ 801 /* If the output is not a register, the input must be. */ 802 if (GET_CODE (operands[0]) == MEM && !reg_or_0_operand (operands[1], mode)) 803 operands[1] = force_reg (mode, operands[1]); 804} 805 806/* Return true if the operands are valid for a simple move insn. */ 807 808bool 809ok_for_simple_move_operands (rtx *operands, enum machine_mode mode) 810{ 811 /* One of the operands must be a register. */ 812 if (!register_operand (operands[0], mode) 813 && !reg_or_0_operand (operands[1], mode)) 814 return false; 815 816 /* Once the flags are exposed, no simple moves between integer registers. */ 817 if (visium_flags_exposed 818 && gpc_reg_operand (operands[0], mode) 819 && gpc_reg_operand (operands[1], mode)) 820 return false; 821 822 return true; 823} 824 825/* Return true if the operands are valid for a simple move strict insn. */ 826 827bool 828ok_for_simple_move_strict_operands (rtx *operands, enum machine_mode mode) 829{ 830 /* Once the flags are exposed, no simple moves between integer registers. 831 Note that, in QImode only, a zero source counts as an integer register 832 since it will be emitted as r0. */ 833 if (visium_flags_exposed 834 && gpc_reg_operand (operands[0], mode) 835 && (gpc_reg_operand (operands[1], mode) 836 || (mode == QImode && operands[1] == const0_rtx))) 837 return false; 838 839 return true; 840} 841 842/* Return true if the operands are valid for a simple arithmetic or logical 843 insn. */ 844 845bool 846ok_for_simple_arith_logic_operands (rtx *, enum machine_mode) 847{ 848 /* Once the flags are exposed, no simple arithmetic or logical operations 849 between integer registers. */ 850 return !visium_flags_exposed; 851} 852 853/* Return non-zero if a branch or call instruction will be emitting a nop 854 into its delay slot. */ 855 856int 857empty_delay_slot (rtx_insn *insn) 858{ 859 rtx seq; 860 861 /* If no previous instruction (should not happen), return true. */ 862 if (PREV_INSN (insn) == NULL) 863 return 1; 864 865 seq = NEXT_INSN (PREV_INSN (insn)); 866 if (GET_CODE (PATTERN (seq)) == SEQUENCE) 867 return 0; 868 869 return 1; 870} 871 872/* Wrapper around single_set which returns the first SET of a pair if the 873 second SET is to the flags register. */ 874 875static rtx 876single_set_and_flags (rtx_insn *insn) 877{ 878 if (multiple_sets (insn)) 879 { 880 rtx pat = PATTERN (insn); 881 if (XVECLEN (pat, 0) == 2 882 && GET_CODE (XVECEXP (pat, 0, 1)) == SET 883 && REG_P (SET_DEST (XVECEXP (pat, 0, 1))) 884 && REGNO (SET_DEST (XVECEXP (pat, 0, 1))) == FLAGS_REGNUM) 885 return XVECEXP (pat, 0, 0); 886 } 887 888 return single_set (insn); 889} 890 891/* This is called with OUT_INSN an instruction setting a (base) register 892 and IN_INSN a read or a write. Return 1 if these instructions together 893 constitute a pipeline hazard. 894 895 On the original architecture, a pipeline data hazard occurs when the Dest 896 of one instruction becomes the SrcA for an immediately following READ or 897 WRITE instruction with a non-zero index (indexing occurs at the decode 898 stage and so a NOP must be inserted in-between for this to work). 899 900 An example is: 901 902 move.l r2,r1 903 read.l r4,10(r2) 904 905 On the MCM, the non-zero index condition is lifted but the hazard is 906 patched up by the hardware through the injection of wait states: 907 908 move.l r2,r1 909 read.l r4,(r2) 910 911 We nevertheless try to schedule instructions around this. */ 912 913int 914gr5_hazard_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn) 915{ 916 rtx out_set, in_set, dest, memexpr; 917 unsigned int out_reg, in_reg; 918 919 /* A CALL is storage register class, but the link register is of no 920 interest here. */ 921 if (GET_CODE (out_insn) == CALL_INSN) 922 return 0; 923 924 out_set = single_set_and_flags (out_insn); 925 dest = SET_DEST (out_set); 926 927 /* Should be no stall/hazard if OUT_INSN is MEM := ???. This only 928 occurs prior to reload. */ 929 if (GET_CODE (dest) == MEM) 930 return 0; 931 932 if (GET_CODE (dest) == STRICT_LOW_PART) 933 dest = XEXP (dest, 0); 934 if (GET_CODE (dest) == SUBREG) 935 dest = SUBREG_REG (dest); 936 out_reg = REGNO (dest); 937 938 in_set = single_set_and_flags (in_insn); 939 940 /* If IN_INSN is MEM := MEM, it's the source that counts. */ 941 if (GET_CODE (SET_SRC (in_set)) == MEM) 942 memexpr = XEXP (SET_SRC (in_set), 0); 943 else 944 memexpr = XEXP (SET_DEST (in_set), 0); 945 946 if (GET_CODE (memexpr) == PLUS) 947 { 948 memexpr = XEXP (memexpr, 0); 949 if (GET_CODE (memexpr) == SUBREG) 950 in_reg = REGNO (SUBREG_REG (memexpr)); 951 else 952 in_reg = REGNO (memexpr); 953 954 if (in_reg == out_reg) 955 return 1; 956 } 957 else if (TARGET_MCM) 958 { 959 if (GET_CODE (memexpr) == STRICT_LOW_PART) 960 memexpr = XEXP (memexpr, 0); 961 if (GET_CODE (memexpr) == SUBREG) 962 memexpr = SUBREG_REG (memexpr); 963 in_reg = REGNO (memexpr); 964 965 if (in_reg == out_reg) 966 return 1; 967 } 968 969 return 0; 970} 971 972/* Return true if INSN is an empty asm instruction. */ 973 974static bool 975empty_asm_p (rtx insn) 976{ 977 rtx body = PATTERN (insn); 978 const char *templ; 979 980 if (GET_CODE (body) == ASM_INPUT) 981 templ = XSTR (body, 0); 982 else if (asm_noperands (body) >= 0) 983 templ = decode_asm_operands (body, NULL, NULL, NULL, NULL, NULL); 984 else 985 templ = NULL; 986 987 return (templ && templ[0] == '\0'); 988} 989 990/* Insert a NOP immediately before INSN wherever there is a pipeline hazard. 991 LAST_REG records the register set in the last insn and LAST_INSN_CALL 992 records whether the last insn was a call insn. */ 993 994static void 995gr5_avoid_hazard (rtx_insn *insn, unsigned int *last_reg, bool *last_insn_call) 996{ 997 unsigned int dest_reg = 0; 998 rtx set; 999 1000 switch (GET_CODE (insn)) 1001 { 1002 case CALL_INSN: 1003 *last_reg = 0; 1004 *last_insn_call = true; 1005 return; 1006 1007 case JUMP_INSN: 1008 /* If this is an empty asm, just skip it. */ 1009 if (!empty_asm_p (insn)) 1010 { 1011 *last_reg = 0; 1012 *last_insn_call = false; 1013 } 1014 return; 1015 1016 case INSN: 1017 /* If this is an empty asm, just skip it. */ 1018 if (empty_asm_p (insn)) 1019 return; 1020 break; 1021 1022 default: 1023 return; 1024 } 1025 1026 set = single_set_and_flags (insn); 1027 if (set != NULL_RTX) 1028 { 1029 rtx dest = SET_DEST (set); 1030 const bool double_p = GET_MODE_SIZE (GET_MODE (dest)) > UNITS_PER_WORD; 1031 rtx memrtx = NULL; 1032 1033 if (GET_CODE (SET_SRC (set)) == MEM) 1034 { 1035 memrtx = XEXP (SET_SRC (set), 0); 1036 if (GET_CODE (dest) == STRICT_LOW_PART) 1037 dest = XEXP (dest, 0); 1038 if (REG_P (dest)) 1039 dest_reg = REGNO (dest); 1040 1041 /* If this is a DI or DF mode memory to register 1042 copy, then if rd = rs we get 1043 1044 rs + 1 := 1[rs] 1045 rs := [rs] 1046 1047 otherwise the order is 1048 1049 rd := [rs] 1050 rd + 1 := 1[rs] */ 1051 1052 if (double_p) 1053 { 1054 unsigned int base_reg; 1055 1056 if (GET_CODE (memrtx) == PLUS) 1057 base_reg = REGNO (XEXP (memrtx, 0)); 1058 else 1059 base_reg = REGNO (memrtx); 1060 1061 if (dest_reg != base_reg) 1062 dest_reg++; 1063 } 1064 } 1065 1066 else if (GET_CODE (dest) == MEM) 1067 memrtx = XEXP (dest, 0); 1068 1069 else if (GET_MODE_CLASS (GET_MODE (dest)) != MODE_CC) 1070 { 1071 if (GET_CODE (dest) == STRICT_LOW_PART 1072 ||GET_CODE (dest) == ZERO_EXTRACT) 1073 dest = XEXP (dest, 0); 1074 dest_reg = REGNO (dest); 1075 1076 if (GET_CODE (SET_SRC (set)) == REG) 1077 { 1078 unsigned int srcreg = REGNO (SET_SRC (set)); 1079 1080 /* Check for rs := rs, which will be deleted. */ 1081 if (srcreg == dest_reg) 1082 return; 1083 1084 /* In the case of a DI or DF mode move from register to 1085 register there is overlap if rd = rs + 1 in which case 1086 the order of the copies is reversed : 1087 1088 rd + 1 := rs + 1; 1089 rd := rs */ 1090 1091 if (double_p && dest_reg != srcreg + 1) 1092 dest_reg++; 1093 } 1094 } 1095 1096 /* If this is the delay slot of a call insn, any register it sets 1097 is not relevant. */ 1098 if (*last_insn_call) 1099 dest_reg = 0; 1100 1101 /* If the previous insn sets the value of a register, and this insn 1102 uses a base register, check for the pipeline hazard where it is 1103 the same register in each case. */ 1104 if (*last_reg != 0 && memrtx != NULL_RTX) 1105 { 1106 unsigned int reg = 0; 1107 1108 /* Check for an index (original architecture). */ 1109 if (GET_CODE (memrtx) == PLUS) 1110 reg = REGNO (XEXP (memrtx, 0)); 1111 1112 /* Check for an MCM target or rs := [rs], in DI or DF mode. */ 1113 else if (TARGET_MCM || (double_p && REGNO (memrtx) == dest_reg)) 1114 reg = REGNO (memrtx); 1115 1116 /* Remove any pipeline hazard by inserting a NOP. */ 1117 if (reg == *last_reg) 1118 { 1119 if (dump_file) 1120 fprintf (dump_file, 1121 "inserting nop before insn %d\n", INSN_UID (insn)); 1122 emit_insn_after (gen_hazard_nop (), prev_active_insn (insn)); 1123 emit_insn_after (gen_blockage (), insn); 1124 } 1125 } 1126 1127 *last_reg = dest_reg; 1128 } 1129 1130 *last_insn_call = false; 1131} 1132 1133/* Go through the instruction stream and insert nops where necessary to avoid 1134 pipeline hazards. There are two cases: 1135 1136 1. On the original architecture, it is invalid to set the value of a 1137 (base) register and then use it in an address with a non-zero index 1138 in the next instruction. 1139 1140 2. On the MCM, setting the value of a (base) register and then using 1141 it in address (including with zero index) in the next instruction 1142 will result in a pipeline stall of 3 cycles. */ 1143 1144static void 1145gr5_hazard_avoidance (void) 1146{ 1147 unsigned int last_reg = 0; 1148 bool last_insn_call = false; 1149 rtx_insn *insn; 1150 1151 for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 1152 if (INSN_P (insn)) 1153 { 1154 rtx pat = PATTERN (insn); 1155 1156 if (GET_CODE (pat) == SEQUENCE) 1157 { 1158 for (int i = 0; i < XVECLEN (pat, 0); i++) 1159 gr5_avoid_hazard (as_a <rtx_insn *> (XVECEXP (pat, 0, i)), 1160 &last_reg, &last_insn_call); 1161 } 1162 1163 else if (GET_CODE (insn) == CALL_INSN) 1164 { 1165 /* This call is going to get a nop in its delay slot. */ 1166 last_reg = 0; 1167 last_insn_call = false; 1168 } 1169 1170 else 1171 gr5_avoid_hazard (insn, &last_reg, &last_insn_call); 1172 } 1173 1174 else if (GET_CODE (insn) == BARRIER) 1175 last_reg = 0; 1176} 1177 1178/* Perform a target-specific pass over the instruction stream. The compiler 1179 will run it at all optimization levels, just after the point at which it 1180 normally does delayed-branch scheduling. */ 1181 1182static unsigned int 1183visium_reorg (void) 1184{ 1185 if (visium_cpu == PROCESSOR_GR5) 1186 gr5_hazard_avoidance (); 1187 1188 return 0; 1189} 1190/* Return true if an argument must be passed by indirect reference. */ 1191 1192static bool 1193visium_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED, 1194 enum machine_mode mode ATTRIBUTE_UNUSED, 1195 const_tree type, 1196 bool named ATTRIBUTE_UNUSED) 1197{ 1198 return type && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == VECTOR_TYPE); 1199} 1200 1201/* Define how arguments are passed. 1202 1203 A range of general registers and floating registers is available 1204 for passing arguments. When the class of registers which an 1205 argument would normally use is exhausted, that argument, is passed 1206 in the overflow region of the stack. No argument is split between 1207 registers and stack. 1208 1209 Arguments of type float or _Complex float go in FP registers if FP 1210 hardware is available. If there is no FP hardware, arguments of 1211 type float go in general registers. All other arguments are passed 1212 in general registers. */ 1213 1214static rtx 1215visium_function_arg (cumulative_args_t pcum_v, enum machine_mode mode, 1216 const_tree type ATTRIBUTE_UNUSED, 1217 bool named ATTRIBUTE_UNUSED) 1218{ 1219 int size; 1220 CUMULATIVE_ARGS *ca = get_cumulative_args (pcum_v); 1221 1222 size = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 1223 if (mode == VOIDmode) 1224 return GEN_INT (0); 1225 1226 /* Scalar or complex single precision floating point arguments are returned 1227 in floating registers. */ 1228 if (TARGET_FPU 1229 && ((GET_MODE_CLASS (mode) == MODE_FLOAT 1230 && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE) 1231 || (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT 1232 && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE * 2))) 1233 { 1234 if (ca->frcount + size <= MAX_ARGS_IN_FP_REGISTERS) 1235 return gen_rtx_REG (mode, FP_ARG_FIRST + ca->frcount); 1236 else 1237 return NULL_RTX; 1238 } 1239 1240 if (ca->grcount + size <= MAX_ARGS_IN_GP_REGISTERS) 1241 return gen_rtx_REG (mode, ca->grcount + GP_ARG_FIRST); 1242 1243 return NULL_RTX; 1244} 1245 1246/* Update the summarizer variable pointed to by PCUM_V to advance past an 1247 argument in the argument list. The values MODE, TYPE and NAMED describe 1248 that argument. Once this is done, the variable CUM is suitable for 1249 analyzing the _following_ argument with visium_function_arg. */ 1250 1251static void 1252visium_function_arg_advance (cumulative_args_t pcum_v, 1253 enum machine_mode mode, 1254 const_tree type ATTRIBUTE_UNUSED, 1255 bool named) 1256{ 1257 int size = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 1258 int stack_size = 0; 1259 CUMULATIVE_ARGS *ca = get_cumulative_args (pcum_v); 1260 1261 /* Scalar or complex single precision floating point arguments are returned 1262 in floating registers. */ 1263 if (TARGET_FPU 1264 && ((GET_MODE_CLASS (mode) == MODE_FLOAT 1265 && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE) 1266 || (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT 1267 && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE * 2))) 1268 { 1269 if (ca->frcount + size <= MAX_ARGS_IN_FP_REGISTERS) 1270 ca->frcount += size; 1271 else 1272 { 1273 stack_size = size; 1274 ca->frcount = MAX_ARGS_IN_FP_REGISTERS; 1275 } 1276 } 1277 else 1278 { 1279 /* Everything else goes in a general register, if enough are 1280 available. */ 1281 if (ca->grcount + size <= MAX_ARGS_IN_GP_REGISTERS) 1282 ca->grcount += size; 1283 else 1284 { 1285 stack_size = size; 1286 ca->grcount = MAX_ARGS_IN_GP_REGISTERS; 1287 } 1288 } 1289 1290 if (named) 1291 ca->stack_words += stack_size; 1292} 1293 1294/* Specify whether to return the return value in memory. */ 1295 1296static bool 1297visium_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) 1298{ 1299 return (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == VECTOR_TYPE); 1300} 1301 1302/* Define how scalar values are returned. */ 1303 1304static rtx 1305visium_function_value_1 (enum machine_mode mode) 1306{ 1307 /* Scalar or complex single precision floating point values 1308 are returned in floating register f1. */ 1309 if (TARGET_FPU 1310 && ((GET_MODE_CLASS (mode) == MODE_FLOAT 1311 && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE) 1312 || (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT 1313 && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE * 2))) 1314 return gen_rtx_REG (mode, FP_RETURN_REGNUM); 1315 1316 /* All others are returned in r1. */ 1317 return gen_rtx_REG (mode, RETURN_REGNUM); 1318} 1319 1320/* Return an RTX representing the place where a function returns or receives 1321 a value of data type RET_TYPE. */ 1322 1323static rtx 1324visium_function_value (const_tree ret_type, 1325 const_tree fn_decl_or_type ATTRIBUTE_UNUSED, 1326 bool outgoing ATTRIBUTE_UNUSED) 1327{ 1328 return visium_function_value_1 (TYPE_MODE (ret_type)); 1329} 1330 1331/* Return an RTX representing the place where the library function result will 1332 be returned. */ 1333 1334static rtx 1335visium_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED) 1336{ 1337 return visium_function_value_1 (mode); 1338} 1339 1340/* Store the anonymous register arguments into the stack so that all the 1341 arguments appear to have been passed consecutively on the stack. */ 1342 1343static void 1344visium_setup_incoming_varargs (cumulative_args_t pcum_v, 1345 enum machine_mode mode, 1346 tree type, 1347 int *pretend_size ATTRIBUTE_UNUSED, 1348 int no_rtl) 1349{ 1350 cumulative_args_t local_args_so_far; 1351 CUMULATIVE_ARGS local_copy; 1352 CUMULATIVE_ARGS *locargs; 1353 int gp_saved, fp_saved, size; 1354 1355 /* Create an internal cumulative_args_t pointer to internally define 1356 storage to ensure calling TARGET_FUNCTION_ARG_ADVANCE does not 1357 make global changes. */ 1358 local_args_so_far.p = &local_copy; 1359 locargs = get_cumulative_args (pcum_v); 1360 1361#ifdef ENABLE_CHECKING 1362 local_args_so_far.magic = CUMULATIVE_ARGS_MAGIC; 1363#endif 1364 1365 local_copy.grcount = locargs->grcount; 1366 local_copy.frcount = locargs->frcount; 1367 local_copy.stack_words = locargs->stack_words; 1368 1369 /* The caller has advanced ARGS_SO_FAR up to, but not beyond, the last named 1370 argument. Advance a local copy of ARGS_SO_FAR past the last "real" named 1371 argument, to find out how many registers are left over. */ 1372 TARGET_FUNCTION_ARG_ADVANCE (local_args_so_far, mode, type, 1); 1373 1374 /* Find how many registers we need to save. */ 1375 locargs = get_cumulative_args (local_args_so_far); 1376 gp_saved = MAX_ARGS_IN_GP_REGISTERS - locargs->grcount; 1377 fp_saved = (TARGET_FPU ? MAX_ARGS_IN_FP_REGISTERS - locargs->frcount : 0); 1378 size = (gp_saved * UNITS_PER_WORD) + (fp_saved * UNITS_PER_HWFPVALUE); 1379 1380 if (!no_rtl && size > 0) 1381 { 1382 /* To avoid negative offsets, which are not valid addressing modes on 1383 the Visium, we create a base register for the pretend args. */ 1384 rtx ptr 1385 = force_reg (Pmode, 1386 plus_constant (Pmode, virtual_incoming_args_rtx, -size)); 1387 1388 if (gp_saved > 0) 1389 { 1390 rtx mem 1391 = gen_rtx_MEM (BLKmode, 1392 plus_constant (Pmode, 1393 ptr, 1394 fp_saved * UNITS_PER_HWFPVALUE)); 1395 MEM_NOTRAP_P (mem) = 1; 1396 set_mem_alias_set (mem, get_varargs_alias_set ()); 1397 move_block_from_reg (locargs->grcount + GP_ARG_FIRST, mem, gp_saved); 1398 } 1399 1400 if (fp_saved > 0) 1401 { 1402 rtx mem = gen_rtx_MEM (BLKmode, ptr); 1403 MEM_NOTRAP_P (mem) = 1; 1404 set_mem_alias_set (mem, get_varargs_alias_set ()); 1405 gcc_assert (UNITS_PER_WORD == UNITS_PER_HWFPVALUE); 1406 move_block_from_reg (locargs->frcount + FP_ARG_FIRST, mem, fp_saved); 1407 } 1408 } 1409 1410 visium_reg_parm_save_area_size = size; 1411} 1412 1413/* Define the `__builtin_va_list' type for the ABI. */ 1414 1415static tree 1416visium_build_builtin_va_list (void) 1417{ 1418 tree f_ovfl, f_gbase, f_fbase, f_gbytes, f_fbytes, record; 1419 1420 record = (*lang_hooks.types.make_type) (RECORD_TYPE); 1421 f_ovfl = build_decl (BUILTINS_LOCATION, FIELD_DECL, 1422 get_identifier ("__overflow_argptr"), ptr_type_node); 1423 f_gbase = build_decl (BUILTINS_LOCATION, FIELD_DECL, 1424 get_identifier ("__gpr_base"), ptr_type_node); 1425 f_fbase = build_decl (BUILTINS_LOCATION, FIELD_DECL, 1426 get_identifier ("__fpr_base"), ptr_type_node); 1427 f_gbytes = build_decl (BUILTINS_LOCATION, FIELD_DECL, 1428 get_identifier ("__gpr_bytes"), 1429 short_unsigned_type_node); 1430 f_fbytes = build_decl (BUILTINS_LOCATION, FIELD_DECL, 1431 get_identifier ("__fpr_bytes"), 1432 short_unsigned_type_node); 1433 1434 DECL_FIELD_CONTEXT (f_ovfl) = record; 1435 DECL_FIELD_CONTEXT (f_gbase) = record; 1436 DECL_FIELD_CONTEXT (f_fbase) = record; 1437 DECL_FIELD_CONTEXT (f_gbytes) = record; 1438 DECL_FIELD_CONTEXT (f_fbytes) = record; 1439 TYPE_FIELDS (record) = f_ovfl; 1440 TREE_CHAIN (f_ovfl) = f_gbase; 1441 TREE_CHAIN (f_gbase) = f_fbase; 1442 TREE_CHAIN (f_fbase) = f_gbytes; 1443 TREE_CHAIN (f_gbytes) = f_fbytes; 1444 layout_type (record); 1445 1446 return record; 1447} 1448 1449/* Implement `va_start' for varargs and stdarg. */ 1450 1451static void 1452visium_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) 1453{ 1454 const CUMULATIVE_ARGS *ca = &crtl->args.info; 1455 int gp_saved = MAX_ARGS_IN_GP_REGISTERS - ca->grcount; 1456 int fp_saved = (TARGET_FPU ? MAX_ARGS_IN_FP_REGISTERS - ca->frcount : 0); 1457 int named_stack_size = ca->stack_words * UNITS_PER_WORD, offset; 1458 tree f_ovfl, f_gbase, f_fbase, f_gbytes, f_fbytes; 1459 tree ovfl, gbase, gbytes, fbase, fbytes, t; 1460 1461 f_ovfl = TYPE_FIELDS (va_list_type_node); 1462 f_gbase = TREE_CHAIN (f_ovfl); 1463 f_fbase = TREE_CHAIN (f_gbase); 1464 f_gbytes = TREE_CHAIN (f_fbase); 1465 f_fbytes = TREE_CHAIN (f_gbytes); 1466 ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl, NULL_TREE); 1467 gbase = build3 (COMPONENT_REF, TREE_TYPE (f_gbase), valist, f_gbase, 1468 NULL_TREE); 1469 fbase = build3 (COMPONENT_REF, TREE_TYPE (f_fbase), valist, f_fbase, 1470 NULL_TREE); 1471 gbytes = build3 (COMPONENT_REF, TREE_TYPE (f_gbytes), valist, f_gbytes, 1472 NULL_TREE); 1473 fbytes = build3 (COMPONENT_REF, TREE_TYPE (f_fbytes), valist, f_fbytes, 1474 NULL_TREE); 1475 1476 /* Store the stacked vararg pointer in the OVFL member. */ 1477 t = make_tree (TREE_TYPE (ovfl), virtual_incoming_args_rtx); 1478 t = fold_build_pointer_plus_hwi (t, named_stack_size); 1479 t = build2 (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t); 1480 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 1481 1482 /* Store the base address of the GPR save area into GBASE. */ 1483 t = make_tree (TREE_TYPE (gbase), virtual_incoming_args_rtx); 1484 offset = MAX_ARGS_IN_GP_REGISTERS * UNITS_PER_WORD; 1485 t = fold_build_pointer_plus_hwi (t, -offset); 1486 t = build2 (MODIFY_EXPR, TREE_TYPE (gbase), gbase, t); 1487 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 1488 1489 /* Store the base address of the FPR save area into FBASE. */ 1490 if (fp_saved) 1491 { 1492 t = make_tree (TREE_TYPE (fbase), virtual_incoming_args_rtx); 1493 offset = gp_saved * UNITS_PER_WORD 1494 + MAX_ARGS_IN_FP_REGISTERS * UNITS_PER_HWFPVALUE; 1495 t = fold_build_pointer_plus_hwi (t, -offset); 1496 t = build2 (MODIFY_EXPR, TREE_TYPE (fbase), fbase, t); 1497 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 1498 } 1499 1500 /* Fill in the GBYTES member. */ 1501 t = build2 (MODIFY_EXPR, TREE_TYPE (gbytes), gbytes, 1502 size_int (gp_saved * UNITS_PER_WORD)); 1503 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 1504 1505 /* Fill in the FBYTES member. */ 1506 t = build2 (MODIFY_EXPR, TREE_TYPE (fbytes), 1507 fbytes, size_int (fp_saved * UNITS_PER_HWFPVALUE)); 1508 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 1509} 1510 1511/* Implement `va_arg'. */ 1512 1513static tree 1514visium_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, 1515 gimple_seq *post_p) 1516{ 1517 tree f_ovfl, f_gbase, f_fbase, f_gbytes, f_fbytes; 1518 tree ovfl, base, bytes; 1519 HOST_WIDE_INT size, rsize; 1520 const bool by_reference_p 1521 = pass_by_reference (NULL, TYPE_MODE (type), type, false); 1522 const bool float_reg_arg_p 1523 = (TARGET_FPU && !by_reference_p 1524 && ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT 1525 && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_HWFPVALUE) 1526 || (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT 1527 && (GET_MODE_SIZE (TYPE_MODE (type)) 1528 <= UNITS_PER_HWFPVALUE * 2)))); 1529 const int max_save_area_size 1530 = (float_reg_arg_p ? MAX_ARGS_IN_FP_REGISTERS * UNITS_PER_HWFPVALUE 1531 : MAX_ARGS_IN_GP_REGISTERS * UNITS_PER_WORD); 1532 tree t, u, offs; 1533 tree lab_false, lab_over, addr; 1534 tree ptrtype = build_pointer_type (type); 1535 1536 if (by_reference_p) 1537 { 1538 t = visium_gimplify_va_arg (valist, ptrtype, pre_p, post_p); 1539 return build_va_arg_indirect_ref (t); 1540 } 1541 1542 size = int_size_in_bytes (type); 1543 rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD; 1544 f_ovfl = TYPE_FIELDS (va_list_type_node); 1545 f_gbase = TREE_CHAIN (f_ovfl); 1546 f_fbase = TREE_CHAIN (f_gbase); 1547 f_gbytes = TREE_CHAIN (f_fbase); 1548 f_fbytes = TREE_CHAIN (f_gbytes); 1549 1550 /* We maintain separate pointers and offsets for floating-point and 1551 general registers, but we need similar code in both cases. 1552 1553 Let: 1554 1555 BYTES be the number of unused bytes in the register save area. 1556 BASE be the base address of the register save area. 1557 OFFS be the current offset into the register save area. Either 1558 MAX_ARGS_IN_GP_REGISTERS * UNITS_PER_WORD - bytes or 1559 MAX_ARGS_IN_FP_REGISTERS * UNITS_PER_HWFPVALUE - bytes 1560 depending upon whether the argument is in general or floating 1561 registers. 1562 ADDR_RTX be the address of the argument. 1563 RSIZE be the size in bytes of the argument. 1564 OVFL be the pointer to the stack overflow area. 1565 1566 The code we want is: 1567 1568 1: if (bytes >= rsize) 1569 2: { 1570 3: addr_rtx = base + offs; 1571 4: bytes -= rsize; 1572 5: } 1573 6: else 1574 7: { 1575 8: bytes = 0; 1576 9: addr_rtx = ovfl; 1577 10: ovfl += rsize; 1578 11: } 1579 1580 */ 1581 1582 addr = create_tmp_var (ptr_type_node, "addr"); 1583 lab_false = create_artificial_label (UNKNOWN_LOCATION); 1584 lab_over = create_artificial_label (UNKNOWN_LOCATION); 1585 if (float_reg_arg_p) 1586 bytes = build3 (COMPONENT_REF, TREE_TYPE (f_fbytes), unshare_expr (valist), 1587 f_fbytes, NULL_TREE); 1588 else 1589 bytes = build3 (COMPONENT_REF, TREE_TYPE (f_gbytes), unshare_expr (valist), 1590 f_gbytes, NULL_TREE); 1591 1592 /* [1] Emit code to branch if bytes < rsize. */ 1593 t = fold_convert (TREE_TYPE (bytes), size_int (rsize)); 1594 t = build2 (LT_EXPR, boolean_type_node, bytes, t); 1595 u = build1 (GOTO_EXPR, void_type_node, lab_false); 1596 t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE); 1597 gimplify_and_add (t, pre_p); 1598 1599 /* [3] Emit code for: addr_rtx = base + offs, where 1600 offs = max_save_area_size - bytes. */ 1601 t = fold_convert (sizetype, bytes); 1602 offs = build2 (MINUS_EXPR, sizetype, size_int (max_save_area_size), t); 1603 if (float_reg_arg_p) 1604 base = build3 (COMPONENT_REF, TREE_TYPE (f_fbase), valist, f_fbase, 1605 NULL_TREE); 1606 else 1607 base = build3 (COMPONENT_REF, TREE_TYPE (f_gbase), valist, f_gbase, 1608 NULL_TREE); 1609 1610 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (base), base, offs); 1611 t = build2 (MODIFY_EXPR, void_type_node, addr, t); 1612 gimplify_and_add (t, pre_p); 1613 1614 /* [4] Emit code for: bytes -= rsize. */ 1615 t = fold_convert (TREE_TYPE (bytes), size_int (rsize)); 1616 t = build2 (MINUS_EXPR, TREE_TYPE (bytes), bytes, t); 1617 t = build2 (MODIFY_EXPR, TREE_TYPE (bytes), bytes, t); 1618 gimplify_and_add (t, pre_p); 1619 1620 /* [6] Emit code to branch over the else clause, then the label. */ 1621 t = build1 (GOTO_EXPR, void_type_node, lab_over); 1622 gimplify_and_add (t, pre_p); 1623 t = build1 (LABEL_EXPR, void_type_node, lab_false); 1624 gimplify_and_add (t, pre_p); 1625 1626 /* [8] Emit code for: bytes = 0. */ 1627 t = fold_convert (TREE_TYPE (bytes), size_int (0)); 1628 t = build2 (MODIFY_EXPR, TREE_TYPE (bytes), unshare_expr (bytes), t); 1629 gimplify_and_add (t, pre_p); 1630 1631 /* [9] Emit code for: addr_rtx = ovfl. */ 1632 ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl, NULL_TREE); 1633 t = build2 (MODIFY_EXPR, void_type_node, addr, ovfl); 1634 gimplify_and_add (t, pre_p); 1635 1636 /* [10] Emit code for: ovfl += rsize. */ 1637 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (ovfl), ovfl, size_int (rsize)); 1638 t = build2 (MODIFY_EXPR, TREE_TYPE (ovfl), unshare_expr (ovfl), t); 1639 gimplify_and_add (t, pre_p); 1640 t = build1 (LABEL_EXPR, void_type_node, lab_over); 1641 gimplify_and_add (t, pre_p); 1642 addr = fold_convert (ptrtype, addr); 1643 1644 return build_va_arg_indirect_ref (addr); 1645} 1646 1647/* Return true if OP is an offset suitable for use as a displacement in the 1648 address of a memory access in mode MODE. */ 1649 1650static bool 1651rtx_ok_for_offset_p (enum machine_mode mode, rtx op) 1652{ 1653 if (!CONST_INT_P (op) || INTVAL (op) < 0) 1654 return false; 1655 1656 switch (mode) 1657 { 1658 case QImode: 1659 return INTVAL (op) <= 31; 1660 1661 case HImode: 1662 return (INTVAL (op) % 2) == 0 && INTVAL (op) < 63; 1663 1664 case SImode: 1665 case SFmode: 1666 return (INTVAL (op) % 4) == 0 && INTVAL (op) < 127; 1667 1668 case DImode: 1669 case DFmode: 1670 return (INTVAL (op) % 4) == 0 && INTVAL (op) < 123; 1671 1672 default: 1673 return false; 1674 } 1675} 1676 1677/* Return whether X is a legitimate memory address for a memory operand 1678 of mode MODE. 1679 1680 Legitimate addresses are defined in two variants: a strict variant 1681 and a non-strict one. The STRICT parameter chooses which variant 1682 is desired by the caller. 1683 1684 The strict variant is used in the reload pass. It must be defined 1685 so that any pseudo-register that has not been allocated a hard 1686 register is considered a memory reference. This is because in 1687 contexts where some kind of register is required, a 1688 pseudo-register with no hard register must be rejected. For 1689 non-hard registers, the strict variant should look up the 1690 `reg_renumber' array; it should then proceed using the hard 1691 register number in the array, or treat the pseudo as a memory 1692 reference if the array holds `-1'. 1693 1694 The non-strict variant is used in other passes. It must be 1695 defined to accept all pseudo-registers in every context where some 1696 kind of register is required. */ 1697 1698static bool 1699visium_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) 1700{ 1701 rtx base; 1702 unsigned int regno; 1703 1704 /* If X is base+disp, check that we have an appropriate offset. */ 1705 if (GET_CODE (x) == PLUS) 1706 { 1707 if (!rtx_ok_for_offset_p (mode, XEXP (x, 1))) 1708 return false; 1709 base = XEXP (x, 0); 1710 } 1711 else 1712 base = x; 1713 1714 /* Now check the base: it must be either a register or a subreg thereof. */ 1715 if (GET_CODE (base) == SUBREG) 1716 base = SUBREG_REG (base); 1717 if (!REG_P (base)) 1718 return false; 1719 1720 regno = REGNO (base); 1721 1722 /* For the strict variant, the register must be REGNO_OK_FOR_BASE_P. */ 1723 if (strict) 1724 return REGNO_OK_FOR_BASE_P (regno); 1725 1726 /* For the non-strict variant, the register may also be a pseudo. */ 1727 return BASE_REGISTER_P (regno) || regno >= FIRST_PSEUDO_REGISTER; 1728} 1729 1730/* Try machine-dependent ways of modifying an illegitimate address 1731 to be legitimate. If we find one, return the new, valid address. 1732 This macro is used in only one place: `memory_address' in explow.c. 1733 1734 OLDX is the address as it was before break_out_memory_refs was called. 1735 In some cases it is useful to look at this to decide what needs to be done. 1736 1737 MODE and WIN are passed so that this macro can use 1738 GO_IF_LEGITIMATE_ADDRESS. 1739 1740 It is always safe for this macro to do nothing. It exists to recognize 1741 opportunities to optimize the output. 1742 1743 For Visium 1744 1745 memory (reg + <out of range int>) 1746 1747 is transformed to 1748 1749 base_int = <out of range int> & ~mask 1750 ptr_reg = reg + base_int 1751 memory (ptr_reg + <out of range int> - base_int) 1752 1753 Thus ptr_reg is a base register for a range of addresses, 1754 which should help CSE. 1755 1756 For a 1 byte reference mask is 0x1f 1757 for a 2 byte reference mask is 0x3f 1758 For a 4 byte reference mask is 0x7f 1759 1760 This reflects the indexing range of the processor. 1761 1762 For a > 4 byte reference the mask is 0x7f provided all of the words 1763 can be accessed with the base address obtained. Otherwise a mask 1764 of 0x3f is used. 1765 1766 On rare occasions an unaligned base register value with an 1767 unaligned offset is generated. Unaligned offsets are left alone for 1768 this reason. */ 1769 1770static rtx 1771visium_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, 1772 enum machine_mode mode) 1773{ 1774 if (GET_CODE (x) == PLUS 1775 && GET_CODE (XEXP (x, 1)) == CONST_INT 1776 && GET_CODE (XEXP (x, 0)) == REG && mode != BLKmode) 1777 { 1778 int offset = INTVAL (XEXP (x, 1)); 1779 int size = GET_MODE_SIZE (mode); 1780 int mask = (size == 1 ? 0x1f : (size == 2 ? 0x3f : 0x7f)); 1781 int mask1 = (size == 1 ? 0 : (size == 2 ? 1 : 3)); 1782 int offset_base = offset & ~mask; 1783 1784 /* Check that all of the words can be accessed. */ 1785 if (4 < size && 0x80 < size + offset - offset_base) 1786 offset_base = offset & ~0x3f; 1787 if (offset_base != 0 && offset_base != offset && (offset & mask1) == 0) 1788 { 1789 rtx ptr_reg = force_reg (Pmode, 1790 gen_rtx_PLUS (Pmode, 1791 XEXP (x, 0), 1792 GEN_INT (offset_base))); 1793 1794 return plus_constant (Pmode, ptr_reg, offset - offset_base); 1795 } 1796 } 1797 1798 return x; 1799} 1800 1801/* Perform a similar function to visium_legitimize_address, but this time 1802 for reload. Generating new registers is not an option here. Parts 1803 that need reloading are indicated by calling push_reload. */ 1804 1805rtx 1806visium_legitimize_reload_address (rtx x, enum machine_mode mode, int opnum, 1807 int type, int ind ATTRIBUTE_UNUSED) 1808{ 1809 rtx newrtx, tem = NULL_RTX; 1810 1811 if (mode == BLKmode) 1812 return NULL_RTX; 1813 1814 if (optimize && GET_CODE (x) == PLUS) 1815 tem = simplify_binary_operation (PLUS, GET_MODE (x), XEXP (x, 0), 1816 XEXP (x, 1)); 1817 1818 newrtx = tem ? tem : x; 1819 if (GET_CODE (newrtx) == PLUS 1820 && GET_CODE (XEXP (newrtx, 1)) == CONST_INT 1821 && GET_CODE (XEXP (newrtx, 0)) == REG 1822 && BASE_REGISTER_P (REGNO (XEXP (newrtx, 0)))) 1823 { 1824 int offset = INTVAL (XEXP (newrtx, 1)); 1825 int size = GET_MODE_SIZE (mode); 1826 int mask = (size == 1 ? 0x1f : (size == 2 ? 0x3f : 0x7f)); 1827 int mask1 = (size == 1 ? 0 : (size == 2 ? 1 : 3)); 1828 int offset_base = offset & ~mask; 1829 1830 /* Check that all of the words can be accessed. */ 1831 if (4 < size && 0x80 < size + offset - offset_base) 1832 offset_base = offset & ~0x3f; 1833 1834 if (offset_base && (offset & mask1) == 0) 1835 { 1836 rtx temp = gen_rtx_PLUS (Pmode, 1837 XEXP (newrtx, 0), GEN_INT (offset_base)); 1838 1839 x = gen_rtx_PLUS (Pmode, temp, GEN_INT (offset - offset_base)); 1840 push_reload (XEXP (x, 0), 0, &XEXP (x, 0), 0, 1841 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum, 1842 (enum reload_type) type); 1843 return x; 1844 } 1845 } 1846 1847 return NULL_RTX; 1848} 1849 1850/* Return the cost of moving data of mode MODE from a register in class FROM to 1851 one in class TO. A value of 2 is the default; other values are interpreted 1852 relative to that. */ 1853 1854static int 1855visium_register_move_cost (enum machine_mode mode, reg_class_t from, 1856 reg_class_t to) 1857{ 1858 const int numwords = (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) ? 1 : 2; 1859 1860 if (from == MDB || to == MDB) 1861 return 4; 1862 else if (from == MDC || to == MDC || (from == FP_REGS) != (to == FP_REGS)) 1863 return 4 * numwords; 1864 else 1865 return 2 * numwords; 1866} 1867 1868/* Return the cost of moving data of mode MODE between a register of class 1869 CLASS and memory. IN is zero if the value is to be written to memory, 1870 non-zero if it is to be read in. This cost is relative to those in 1871 visium_register_move_cost. */ 1872 1873static int 1874visium_memory_move_cost (enum machine_mode mode, 1875 reg_class_t to ATTRIBUTE_UNUSED, 1876 bool in) 1877{ 1878 /* Moving data in can be from PROM and this is expensive. */ 1879 if (in) 1880 { 1881 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) 1882 return 7; 1883 else 1884 return 13; 1885 } 1886 1887 /* Moving data out is mostly to RAM and should be cheaper. */ 1888 else 1889 { 1890 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) 1891 return 6; 1892 else 1893 return 12; 1894 } 1895} 1896 1897/* Return the relative costs of expression X. */ 1898 1899static bool 1900visium_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, 1901 int opno ATTRIBUTE_UNUSED, int *total, 1902 bool speed ATTRIBUTE_UNUSED) 1903{ 1904 enum machine_mode mode = GET_MODE (x); 1905 1906 switch (code) 1907 { 1908 case CONST_INT: 1909 /* Small integers are as cheap as registers. 4-byte values can 1910 be fetched as immediate constants - let's give that the cost 1911 of an extra insn. */ 1912 *total = COSTS_N_INSNS (!satisfies_constraint_J (x)); 1913 return true; 1914 1915 case CONST: 1916 case LABEL_REF: 1917 case SYMBOL_REF: 1918 *total = COSTS_N_INSNS (2); 1919 return true; 1920 1921 case CONST_DOUBLE: 1922 { 1923 rtx high, low; 1924 split_double (x, &high, &low); 1925 *total = 1926 COSTS_N_INSNS 1927 (!satisfies_constraint_J (high) + !satisfies_constraint_J (low)); 1928 return true; 1929 } 1930 1931 case MULT: 1932 *total = COSTS_N_INSNS (3); 1933 return false; 1934 1935 case DIV: 1936 case UDIV: 1937 case MOD: 1938 case UMOD: 1939 if (mode == DImode) 1940 *total = COSTS_N_INSNS (64); 1941 else 1942 *total = COSTS_N_INSNS (32); 1943 return false; 1944 1945 case PLUS: 1946 case MINUS: 1947 case NEG: 1948 /* DImode operations are performed directly on the ALU. */ 1949 if (mode == DImode) 1950 *total = COSTS_N_INSNS (2); 1951 else 1952 *total = COSTS_N_INSNS (1); 1953 return false; 1954 1955 case ASHIFT: 1956 case ASHIFTRT: 1957 case LSHIFTRT: 1958 /* DImode operations are performed on the EAM instead. */ 1959 if (mode == DImode) 1960 *total = COSTS_N_INSNS (3); 1961 else 1962 *total = COSTS_N_INSNS (1); 1963 return false; 1964 1965 case COMPARE: 1966 /* This matches the btst pattern. */ 1967 if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT 1968 && XEXP (x, 1) == const0_rtx 1969 && XEXP (XEXP (x, 0), 1) == const1_rtx 1970 && satisfies_constraint_K (XEXP (XEXP (x, 0), 2))) 1971 *total = COSTS_N_INSNS (1); 1972 return false; 1973 1974 default: 1975 return false; 1976 } 1977} 1978 1979/* Split a double move of OPERANDS in MODE. */ 1980 1981void 1982split_double_move (rtx *operands, enum machine_mode mode) 1983{ 1984 bool swap = false; 1985 1986 /* Check register to register with overlap. */ 1987 if (GET_CODE (operands[0]) == REG 1988 && GET_CODE (operands[1]) == REG 1989 && REGNO (operands[0]) == REGNO (operands[1]) + 1) 1990 swap = true; 1991 1992 /* Check memory to register where the base reg overlaps the destination. */ 1993 if (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == MEM) 1994 { 1995 rtx op = XEXP (operands[1], 0); 1996 1997 if (GET_CODE (op) == SUBREG) 1998 op = SUBREG_REG (op); 1999 2000 if (GET_CODE (op) == REG && REGNO (op) == REGNO (operands[0])) 2001 swap = true; 2002 2003 if (GET_CODE (op) == PLUS) 2004 { 2005 rtx x = XEXP (op, 0); 2006 rtx y = XEXP (op, 1); 2007 2008 if (GET_CODE (x) == REG && REGNO (x) == REGNO (operands[0])) 2009 swap = true; 2010 2011 if (GET_CODE (y) == REG && REGNO (y) == REGNO (operands[0])) 2012 swap = true; 2013 } 2014 } 2015 2016 if (swap) 2017 { 2018 operands[2] = operand_subword (operands[0], 1, 1, mode); 2019 operands[3] = operand_subword (operands[1], 1, 1, mode); 2020 operands[4] = operand_subword (operands[0], 0, 1, mode); 2021 operands[5] = operand_subword (operands[1], 0, 1, mode); 2022 } 2023 else 2024 { 2025 operands[2] = operand_subword (operands[0], 0, 1, mode); 2026 operands[3] = operand_subword (operands[1], 0, 1, mode); 2027 operands[4] = operand_subword (operands[0], 1, 1, mode); 2028 operands[5] = operand_subword (operands[1], 1, 1, mode); 2029 } 2030} 2031 2032/* Expand a copysign of OPERANDS in MODE. */ 2033 2034void 2035visium_expand_copysign (rtx *operands, enum machine_mode mode) 2036{ 2037 rtx dest = operands[0]; 2038 rtx op0 = operands[1]; 2039 rtx op1 = operands[2]; 2040 rtx mask = force_reg (SImode, GEN_INT (0x7fffffff)); 2041 rtx x; 2042 2043 /* We manually handle SFmode because the abs and neg instructions of 2044 the FPU on the MCM have a non-standard behavior wrt NaNs. */ 2045 gcc_assert (mode == SFmode); 2046 2047 /* First get all the non-sign bits of OP0. */ 2048 if (GET_CODE (op0) == CONST_DOUBLE) 2049 { 2050 if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0))) 2051 op0 = simplify_unary_operation (ABS, mode, op0, mode); 2052 if (op0 != CONST0_RTX (mode)) 2053 { 2054 long l; 2055 REAL_VALUE_TYPE rv; 2056 REAL_VALUE_FROM_CONST_DOUBLE (rv, op0); 2057 REAL_VALUE_TO_TARGET_SINGLE (rv, l); 2058 op0 = force_reg (SImode, GEN_INT (trunc_int_for_mode (l, SImode))); 2059 } 2060 } 2061 else 2062 { 2063 op0 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op0)); 2064 op0 = force_reg (SImode, gen_rtx_AND (SImode, op0, mask)); 2065 } 2066 2067 /* Then get the sign bit of OP1. */ 2068 mask = force_reg (SImode, gen_rtx_NOT (SImode, mask)); 2069 op1 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op1)); 2070 op1 = force_reg (SImode, gen_rtx_AND (SImode, op1, mask)); 2071 2072 /* Finally OR the two values. */ 2073 if (op0 == CONST0_RTX (SFmode)) 2074 x = op1; 2075 else 2076 x = force_reg (SImode, gen_rtx_IOR (SImode, op0, op1)); 2077 2078 /* And move the result to the destination. */ 2079 emit_insn (gen_rtx_SET (VOIDmode, dest, gen_lowpart (SFmode, x))); 2080} 2081 2082/* Expand a cstore of OPERANDS in MODE for EQ/NE/LTU/GTU/GEU/LEU. We generate 2083 the result in the C flag and use the ADC/SUBC instructions to write it into 2084 the destination register. 2085 2086 It would also be possible to implement support for LT/GT/LE/GE by means of 2087 the RFLAG instruction followed by some shifts, but this can pessimize the 2088 generated code. */ 2089 2090void 2091visium_expand_int_cstore (rtx *operands, enum machine_mode mode) 2092{ 2093 enum rtx_code code = GET_CODE (operands[1]); 2094 rtx op0 = operands[0], op1 = operands[2], op2 = operands[3], sltu; 2095 bool reverse = false; 2096 2097 switch (code) 2098 { 2099 case EQ: 2100 case NE: 2101 /* We use a special comparison to get the result in the C flag. */ 2102 if (op2 != const0_rtx) 2103 op1 = force_reg (mode, gen_rtx_XOR (mode, op1, op2)); 2104 op1 = gen_rtx_NOT (mode, op1); 2105 op2 = constm1_rtx; 2106 if (code == EQ) 2107 reverse = true; 2108 break; 2109 2110 case LEU: 2111 case GEU: 2112 /* The result is naturally in the C flag modulo a couple of tricks. */ 2113 code = reverse_condition (code); 2114 reverse = true; 2115 2116 /* ... fall through ... */ 2117 2118 case LTU: 2119 case GTU: 2120 if (code == GTU) 2121 { 2122 rtx tmp = op1; 2123 op1 = op2; 2124 op2 = tmp; 2125 } 2126 break; 2127 2128 default: 2129 gcc_unreachable (); 2130 } 2131 2132 /* We need either a single ADC or a SUBC and a PLUS. */ 2133 sltu = gen_rtx_LTU (SImode, op1, op2); 2134 2135 if (reverse) 2136 { 2137 rtx tmp = copy_to_mode_reg (SImode, gen_rtx_NEG (SImode, sltu)); 2138 emit_insn (gen_add3_insn (op0, tmp, const1_rtx)); 2139 } 2140 else 2141 emit_insn (gen_rtx_SET (VOIDmode, op0, sltu)); 2142} 2143 2144/* Expand a cstore of OPERANDS in MODE for LT/GT/UNGE/UNLE. We generate the 2145 result in the C flag and use the ADC/SUBC instructions to write it into 2146 the destination register. */ 2147 2148void 2149visium_expand_fp_cstore (rtx *operands, 2150 enum machine_mode mode ATTRIBUTE_UNUSED) 2151{ 2152 enum rtx_code code = GET_CODE (operands[1]); 2153 rtx op0 = operands[0], op1 = operands[2], op2 = operands[3], slt; 2154 bool reverse = false; 2155 2156 switch (code) 2157 { 2158 case UNLE: 2159 case UNGE: 2160 /* The result is naturally in the C flag modulo a couple of tricks. */ 2161 code = reverse_condition_maybe_unordered (code); 2162 reverse = true; 2163 2164 /* ... fall through ... */ 2165 2166 case LT: 2167 case GT: 2168 if (code == GT) 2169 { 2170 rtx tmp = op1; 2171 op1 = op2; 2172 op2 = tmp; 2173 } 2174 break; 2175 2176 default: 2177 gcc_unreachable (); 2178 } 2179 2180 /* We need either a single ADC or a SUBC and a PLUS. */ 2181 slt = gen_rtx_LT (SImode, op1, op2); 2182 2183 if (reverse) 2184 { 2185 rtx tmp = copy_to_mode_reg (SImode, gen_rtx_NEG (SImode, slt)); 2186 emit_insn (gen_add3_insn (op0, tmp, const1_rtx)); 2187 } 2188 else 2189 emit_insn (gen_rtx_SET (VOIDmode, op0, slt)); 2190} 2191 2192/* Split a compare-and-store with CODE, operands OP2 and OP3, combined with 2193 operation with OP_CODE, operands OP0 and OP1. */ 2194 2195void 2196visium_split_cstore (enum rtx_code op_code, rtx op0, rtx op1, 2197 enum rtx_code code, rtx op2, rtx op3) 2198{ 2199 enum machine_mode cc_mode = visium_select_cc_mode (code, op2, op3); 2200 2201 /* If a FP cstore was reversed, then it was originally UNGE/UNLE. */ 2202 if (cc_mode == CCFPEmode && (op_code == NEG || op_code == MINUS)) 2203 cc_mode = CCFPmode; 2204 2205 rtx flags = gen_rtx_REG (cc_mode, FLAGS_REGNUM); 2206 rtx x = gen_rtx_COMPARE (cc_mode, op2, op3); 2207 x = gen_rtx_SET (VOIDmode, flags, x); 2208 emit_insn (x); 2209 2210 x = gen_rtx_fmt_ee (code, SImode, flags, const0_rtx); 2211 switch (op_code) 2212 { 2213 case SET: 2214 break; 2215 case NEG: 2216 x = gen_rtx_NEG (SImode, x); 2217 break; 2218 case PLUS: 2219 case MINUS: 2220 x = gen_rtx_fmt_ee (op_code, SImode, op1, x); 2221 break; 2222 default: 2223 gcc_unreachable (); 2224 } 2225 2226 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2)); 2227 XVECEXP (pat, 0, 0) = gen_rtx_SET (VOIDmode, op0, x); 2228 flags = gen_rtx_REG (CCmode, FLAGS_REGNUM); 2229 XVECEXP (pat, 0, 1) = gen_rtx_CLOBBER (VOIDmode, flags); 2230 emit_insn (pat); 2231 2232 visium_flags_exposed = true; 2233} 2234 2235/* Generate a call to a library function to move BYTES_RTX bytes from SRC with 2236 address SRC_REG to DST with address DST_REG in 4-byte chunks. */ 2237 2238static void 2239expand_block_move_4 (rtx dst, rtx dst_reg, rtx src, rtx src_reg, rtx bytes_rtx) 2240{ 2241 const rtx sym = gen_rtx_SYMBOL_REF (Pmode, "__long_int_memcpy"); 2242 unsigned HOST_WIDE_INT bytes = UINTVAL (bytes_rtx); 2243 unsigned int rem = bytes % 4; 2244 2245 if (TARGET_BMI) 2246 { 2247 unsigned int i; 2248 rtx insn; 2249 2250 emit_move_insn (regno_reg_rtx[1], dst_reg); 2251 emit_move_insn (regno_reg_rtx[2], src_reg); 2252 emit_move_insn (regno_reg_rtx[3], bytes_rtx); 2253 2254 insn = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (8)); 2255 XVECEXP (insn, 0, 0) 2256 = gen_rtx_SET (VOIDmode, 2257 replace_equiv_address_nv (dst, regno_reg_rtx[1]), 2258 replace_equiv_address_nv (src, regno_reg_rtx[2])); 2259 XVECEXP (insn, 0, 1) = gen_rtx_USE (VOIDmode, regno_reg_rtx[3]); 2260 for (i = 1; i <= 6; i++) 2261 XVECEXP (insn, 0, 1 + i) 2262 = gen_rtx_CLOBBER (VOIDmode, regno_reg_rtx[i]); 2263 emit_insn (insn); 2264 } 2265 else 2266 emit_library_call (sym, LCT_NORMAL, VOIDmode, 3, dst_reg, Pmode, src_reg, 2267 Pmode, 2268 convert_to_mode (TYPE_MODE (sizetype), 2269 GEN_INT (bytes >> 2), 2270 TYPE_UNSIGNED (sizetype)), 2271 TYPE_MODE (sizetype)); 2272 if (rem == 0) 2273 return; 2274 2275 dst = replace_equiv_address_nv (dst, dst_reg); 2276 src = replace_equiv_address_nv (src, src_reg); 2277 bytes -= rem; 2278 2279 if (rem > 1) 2280 { 2281 emit_move_insn (adjust_address_nv (dst, HImode, bytes), 2282 adjust_address_nv (src, HImode, bytes)); 2283 bytes += 2; 2284 rem -= 2; 2285 } 2286 2287 if (rem > 0) 2288 emit_move_insn (adjust_address_nv (dst, QImode, bytes), 2289 adjust_address_nv (src, QImode, bytes)); 2290} 2291 2292/* Generate a call to a library function to move BYTES_RTX bytes from SRC with 2293 address SRC_REG to DST with address DST_REG in 2-bytes chunks. */ 2294 2295static void 2296expand_block_move_2 (rtx dst, rtx dst_reg, rtx src, rtx src_reg, rtx bytes_rtx) 2297{ 2298 const rtx sym = gen_rtx_SYMBOL_REF (Pmode, "__wrd_memcpy"); 2299 unsigned HOST_WIDE_INT bytes = UINTVAL (bytes_rtx); 2300 unsigned int rem = bytes % 2; 2301 2302 emit_library_call (sym, LCT_NORMAL, VOIDmode, 3, dst_reg, Pmode, src_reg, 2303 Pmode, 2304 convert_to_mode (TYPE_MODE (sizetype), 2305 GEN_INT (bytes >> 1), 2306 TYPE_UNSIGNED (sizetype)), 2307 TYPE_MODE (sizetype)); 2308 if (rem == 0) 2309 return; 2310 2311 dst = replace_equiv_address_nv (dst, dst_reg); 2312 src = replace_equiv_address_nv (src, src_reg); 2313 bytes -= rem; 2314 2315 emit_move_insn (adjust_address_nv (dst, QImode, bytes), 2316 adjust_address_nv (src, QImode, bytes)); 2317} 2318 2319/* Generate a call to a library function to move BYTES_RTX bytes from address 2320 SRC_REG to address DST_REG in 1-byte chunks. */ 2321 2322static void 2323expand_block_move_1 (rtx dst_reg, rtx src_reg, rtx bytes_rtx) 2324{ 2325 const rtx sym = gen_rtx_SYMBOL_REF (Pmode, "__byt_memcpy"); 2326 2327 emit_library_call (sym, LCT_NORMAL, VOIDmode, 3, dst_reg, Pmode, 2328 src_reg, Pmode, 2329 convert_to_mode (TYPE_MODE (sizetype), 2330 bytes_rtx, 2331 TYPE_UNSIGNED (sizetype)), 2332 TYPE_MODE (sizetype)); 2333} 2334 2335/* Generate a call to a library function to set BYTES_RTX bytes of DST with 2336 address DST_REG to VALUE_RTX in 4-byte chunks. */ 2337 2338static void 2339expand_block_set_4 (rtx dst, rtx dst_reg, rtx value_rtx, rtx bytes_rtx) 2340{ 2341 const rtx sym = gen_rtx_SYMBOL_REF (Pmode, "__long_int_memset"); 2342 unsigned HOST_WIDE_INT bytes = UINTVAL (bytes_rtx); 2343 unsigned int rem = bytes % 4; 2344 2345 value_rtx = convert_to_mode (Pmode, value_rtx, 1); 2346 emit_library_call (sym, LCT_NORMAL, VOIDmode, 3, dst_reg, Pmode, 2347 value_rtx, Pmode, 2348 convert_to_mode (TYPE_MODE (sizetype), 2349 GEN_INT (bytes >> 2), 2350 TYPE_UNSIGNED (sizetype)), 2351 TYPE_MODE (sizetype)); 2352 if (rem == 0) 2353 return; 2354 2355 dst = replace_equiv_address_nv (dst, dst_reg); 2356 bytes -= rem; 2357 2358 if (rem > 1) 2359 { 2360 if (CONST_INT_P (value_rtx)) 2361 { 2362 const unsigned HOST_WIDE_INT value = UINTVAL (value_rtx) & 0xff; 2363 emit_move_insn (adjust_address_nv (dst, HImode, bytes), 2364 gen_int_mode ((value << 8) | value, HImode)); 2365 } 2366 else 2367 { 2368 rtx temp = convert_to_mode (QImode, value_rtx, 1); 2369 emit_move_insn (adjust_address_nv (dst, QImode, bytes), temp); 2370 emit_move_insn (adjust_address_nv (dst, QImode, bytes + 1), temp); 2371 } 2372 bytes += 2; 2373 rem -= 2; 2374 } 2375 2376 if (rem > 0) 2377 emit_move_insn (adjust_address_nv (dst, QImode, bytes), 2378 convert_to_mode (QImode, value_rtx, 1)); 2379} 2380 2381/* Generate a call to a library function to set BYTES_RTX bytes of DST with 2382 address DST_REG to VALUE_RTX in 2-byte chunks. */ 2383 2384static void 2385expand_block_set_2 (rtx dst, rtx dst_reg, rtx value_rtx, rtx bytes_rtx) 2386{ 2387 const rtx sym = gen_rtx_SYMBOL_REF (Pmode, "__wrd_memset"); 2388 unsigned HOST_WIDE_INT bytes = UINTVAL (bytes_rtx); 2389 unsigned int rem = bytes % 2; 2390 2391 value_rtx = convert_to_mode (Pmode, value_rtx, 1); 2392 emit_library_call (sym, LCT_NORMAL, VOIDmode, 3, dst_reg, Pmode, 2393 value_rtx, Pmode, 2394 convert_to_mode (TYPE_MODE (sizetype), 2395 GEN_INT (bytes >> 1), 2396 TYPE_UNSIGNED (sizetype)), 2397 TYPE_MODE (sizetype)); 2398 if (rem == 0) 2399 return; 2400 2401 dst = replace_equiv_address_nv (dst, dst_reg); 2402 bytes -= rem; 2403 2404 emit_move_insn (adjust_address_nv (dst, QImode, bytes), 2405 convert_to_mode (QImode, value_rtx, 1)); 2406} 2407 2408/* Generate a call to a library function to set BYTES_RTX bytes at address 2409 DST_REG to VALUE_RTX in 1-byte chunks. */ 2410 2411static void 2412expand_block_set_1 (rtx dst_reg, rtx value_rtx, rtx bytes_rtx) 2413{ 2414 const rtx sym = gen_rtx_SYMBOL_REF (Pmode, "__byt_memset"); 2415 2416 value_rtx = convert_to_mode (Pmode, value_rtx, 1); 2417 emit_library_call (sym, LCT_NORMAL, VOIDmode, 3, dst_reg, Pmode, 2418 value_rtx, Pmode, 2419 convert_to_mode (TYPE_MODE (sizetype), 2420 bytes_rtx, 2421 TYPE_UNSIGNED (sizetype)), 2422 TYPE_MODE (sizetype)); 2423} 2424 2425/* Expand string/block move operations. 2426 2427 operands[0] is the pointer to the destination. 2428 operands[1] is the pointer to the source. 2429 operands[2] is the number of bytes to move. 2430 operands[3] is the alignment. 2431 2432 Return 1 upon success, 0 otherwise. */ 2433 2434int 2435visium_expand_block_move (rtx *operands) 2436{ 2437 rtx dst = operands[0]; 2438 rtx src = operands[1]; 2439 rtx bytes_rtx = operands[2]; 2440 rtx align_rtx = operands[3]; 2441 const int align = INTVAL (align_rtx); 2442 rtx dst_reg, src_reg; 2443 tree dst_expr, src_expr; 2444 2445 /* We only handle a fixed number of bytes for now. */ 2446 if (!CONST_INT_P (bytes_rtx) || INTVAL (bytes_rtx) <= 0) 2447 return 0; 2448 2449 /* Copy the addresses into scratch registers. */ 2450 dst_reg = copy_addr_to_reg (XEXP (dst, 0)); 2451 src_reg = copy_addr_to_reg (XEXP (src, 0)); 2452 2453 /* Move the data with the appropriate granularity. */ 2454 if (align >= 4) 2455 expand_block_move_4 (dst, dst_reg, src, src_reg, bytes_rtx); 2456 else if (align >= 2) 2457 expand_block_move_2 (dst, dst_reg, src, src_reg, bytes_rtx); 2458 else 2459 expand_block_move_1 (dst_reg, src_reg, bytes_rtx); 2460 2461 /* Since DST and SRC are passed to a libcall, mark the corresponding 2462 tree EXPR as addressable. */ 2463 dst_expr = MEM_EXPR (dst); 2464 src_expr = MEM_EXPR (src); 2465 if (dst_expr) 2466 mark_addressable (dst_expr); 2467 if (src_expr) 2468 mark_addressable (src_expr); 2469 2470 return 1; 2471} 2472 2473/* Expand string/block set operations. 2474 2475 operands[0] is the pointer to the destination. 2476 operands[1] is the number of bytes to set. 2477 operands[2] is the source value. 2478 operands[3] is the alignment. 2479 2480 Return 1 upon success, 0 otherwise. */ 2481 2482int 2483visium_expand_block_set (rtx *operands) 2484{ 2485 rtx dst = operands[0]; 2486 rtx bytes_rtx = operands[1]; 2487 rtx value_rtx = operands[2]; 2488 rtx align_rtx = operands[3]; 2489 const int align = INTVAL (align_rtx); 2490 rtx dst_reg; 2491 tree dst_expr; 2492 2493 /* We only handle a fixed number of bytes for now. */ 2494 if (!CONST_INT_P (bytes_rtx) || INTVAL (bytes_rtx) <= 0) 2495 return 0; 2496 2497 /* Copy the address into a scratch register. */ 2498 dst_reg = copy_addr_to_reg (XEXP (dst, 0)); 2499 2500 /* Set the data with the appropriate granularity. */ 2501 if (align >= 4) 2502 expand_block_set_4 (dst, dst_reg, value_rtx, bytes_rtx); 2503 else if (align >= 2) 2504 expand_block_set_2 (dst, dst_reg, value_rtx, bytes_rtx); 2505 else 2506 expand_block_set_1 (dst_reg, value_rtx, bytes_rtx); 2507 2508 /* Since DST is passed to a libcall, mark the corresponding 2509 tree EXPR as addressable. */ 2510 dst_expr = MEM_EXPR (dst); 2511 if (dst_expr) 2512 mark_addressable (dst_expr); 2513 2514 return 1; 2515} 2516 2517/* Initialize a trampoline. M_TRAMP is an RTX for the memory block for the 2518 trampoline, FNDECL is the FUNCTION_DECL for the nested function and 2519 STATIC_CHAIN is an RTX for the static chain value that should be passed 2520 to the function when it is called. */ 2521 2522static void 2523visium_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain) 2524{ 2525 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0); 2526 rtx addr = XEXP (m_tramp, 0); 2527 2528 /* The trampoline initialization sequence is: 2529 2530 moviu r9,%u FUNCTION 2531 movil r9,%l FUNCTION 2532 moviu r20,%u STATIC 2533 bra tr,r9,r9 2534 movil r20,%l STATIC 2535 2536 We don't use r0 as the destination register of the branch because we want 2537 the Branch Pre-decode Logic of the GR6 to use the Address Load Array to 2538 predict the branch target. */ 2539 2540 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, addr, 0)), 2541 plus_constant (SImode, 2542 expand_shift (RSHIFT_EXPR, SImode, fnaddr, 2543 16, NULL_RTX, 1), 2544 0x04a90000)); 2545 2546 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, addr, 4)), 2547 plus_constant (SImode, 2548 expand_and (SImode, fnaddr, GEN_INT (0xffff), 2549 NULL_RTX), 2550 0x04890000)); 2551 2552 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, addr, 8)), 2553 plus_constant (SImode, 2554 expand_shift (RSHIFT_EXPR, SImode, 2555 static_chain, 2556 16, NULL_RTX, 1), 2557 0x04b40000)); 2558 2559 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, addr, 12)), 2560 gen_int_mode (0xff892404, SImode)); 2561 2562 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, addr, 16)), 2563 plus_constant (SImode, 2564 expand_and (SImode, static_chain, 2565 GEN_INT (0xffff), NULL_RTX), 2566 0x04940000)); 2567 2568 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__set_trampoline_parity"), 2569 LCT_NORMAL, VOIDmode, 1, addr, SImode); 2570} 2571 2572/* Return true if the current function must have and use a frame pointer. */ 2573 2574static bool 2575visium_frame_pointer_required (void) 2576{ 2577 /* The frame pointer is required if the function isn't leaf to be able to 2578 do manual stack unwinding. */ 2579 if (!crtl->is_leaf) 2580 return true; 2581 2582 /* If the stack pointer is dynamically modified in the function, it cannot 2583 serve as the frame pointer. */ 2584 if (!crtl->sp_is_unchanging) 2585 return true; 2586 2587 /* If the function receives nonlocal gotos, it needs to save the frame 2588 pointer in the nonlocal_goto_save_area object. */ 2589 if (cfun->has_nonlocal_label) 2590 return true; 2591 2592 /* The frame also needs to be established in some special cases. */ 2593 if (visium_frame_needed) 2594 return true; 2595 2596 return false; 2597} 2598 2599/* Profiling support. Just a call to MCOUNT is needed. No labelled counter 2600 location is involved. Proper support for __builtin_return_address is also 2601 required, which is fairly straightforward provided a frame gets created. */ 2602 2603void 2604visium_profile_hook (void) 2605{ 2606 visium_frame_needed = true; 2607 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "mcount"), LCT_NORMAL, 2608 VOIDmode, 0); 2609} 2610 2611/* A C expression whose value is RTL representing the address in a stack frame 2612 where the pointer to the caller's frame is stored. Assume that FRAMEADDR is 2613 an RTL expression for the address of the stack frame itself. 2614 2615 If you don't define this macro, the default is to return the value of 2616 FRAMEADDR--that is, the stack frame address is also the address of the stack 2617 word that points to the previous frame. */ 2618 2619rtx 2620visium_dynamic_chain_address (rtx frame) 2621{ 2622 /* This is the default, but we need to make sure the frame gets created. */ 2623 visium_frame_needed = true; 2624 return frame; 2625} 2626 2627/* A C expression whose value is RTL representing the value of the return 2628 address for the frame COUNT steps up from the current frame, after the 2629 prologue. FRAMEADDR is the frame pointer of the COUNT frame, or the frame 2630 pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is 2631 defined. 2632 2633 The value of the expression must always be the correct address when COUNT is 2634 zero, but may be `NULL_RTX' if there is not way to determine the return 2635 address of other frames. */ 2636 2637rtx 2638visium_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED) 2639{ 2640 /* Dont try to compute anything other than frame zero. */ 2641 if (count != 0) 2642 return NULL_RTX; 2643 2644 visium_frame_needed = true; 2645 return 2646 gen_frame_mem (Pmode, plus_constant (Pmode, hard_frame_pointer_rtx, 4)); 2647} 2648 2649/* Helper function for EH_RETURN_HANDLER_RTX. Return the RTX representing a 2650 location in which to store the address of an exception handler to which we 2651 should return. */ 2652 2653rtx 2654visium_eh_return_handler_rtx (void) 2655{ 2656 rtx mem 2657 = gen_frame_mem (SImode, plus_constant (Pmode, hard_frame_pointer_rtx, 4)); 2658 MEM_VOLATILE_P (mem) = 1; 2659 return mem; 2660} 2661 2662static struct machine_function * 2663visium_init_machine_status (void) 2664{ 2665 return ggc_cleared_alloc<machine_function> (); 2666} 2667 2668/* The per-function data machinery is needed to indicate when a frame 2669 is required. */ 2670 2671void 2672visium_init_expanders (void) 2673{ 2674 init_machine_status = visium_init_machine_status; 2675} 2676 2677/* Given a comparison code (EQ, NE, etc.) and the operands of a COMPARE, 2678 return the mode to be used for the comparison. */ 2679 2680enum machine_mode 2681visium_select_cc_mode (enum rtx_code code, rtx op0, rtx op1) 2682{ 2683 if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT) 2684 { 2685 switch (code) 2686 { 2687 case EQ: 2688 case NE: 2689 case ORDERED: 2690 case UNORDERED: 2691 case UNLT: 2692 case UNLE: 2693 case UNGT: 2694 case UNGE: 2695 return CCFPmode; 2696 2697 case LT: 2698 case LE: 2699 case GT: 2700 case GE: 2701 return CCFPEmode; 2702 2703 /* These 2 comparison codes are not supported. */ 2704 case UNEQ: 2705 case LTGT: 2706 default: 2707 gcc_unreachable (); 2708 } 2709 } 2710 2711 if (op1 != const0_rtx) 2712 return CCmode; 2713 2714 switch (GET_CODE (op0)) 2715 { 2716 case PLUS: 2717 case MINUS: 2718 case NEG: 2719 case ASHIFT: 2720 case LTU: 2721 case LT: 2722 /* The V flag may be set differently from a COMPARE with zero. 2723 The consequence is that a comparison operator testing V must 2724 be turned into another operator not testing V and yielding 2725 the same result for a comparison with zero. That's possible 2726 for GE/LT which become NC/NS respectively, but not for GT/LE 2727 for which the altered operator doesn't exist on the Visium. */ 2728 return CC_NOOVmode; 2729 2730 case ZERO_EXTRACT: 2731 /* This is a btst, the result is in C instead of Z. */ 2732 return CC_BTSTmode; 2733 2734 case CONST_INT: 2735 /* This is a degenerate case, typically an uninitialized variable. */ 2736 gcc_assert (op0 == constm1_rtx); 2737 case REG: 2738 case AND: 2739 case IOR: 2740 case XOR: 2741 case NOT: 2742 case ASHIFTRT: 2743 case LSHIFTRT: 2744 case TRUNCATE: 2745 case SIGN_EXTEND: 2746 /* Pretend that the flags are set as for a COMPARE with zero. 2747 That's mostly true, except for the 2 right shift insns that 2748 will set the C flag. But the C flag is relevant only for 2749 the unsigned comparison operators and they are eliminated 2750 when applied to a comparison with zero. */ 2751 return CCmode; 2752 2753 default: 2754 gcc_unreachable (); 2755 } 2756} 2757 2758/* Split a compare-and-branch with CODE, operands OP0 and OP1, and LABEL. */ 2759 2760void 2761visium_split_cbranch (enum rtx_code code, rtx op0, rtx op1, rtx label) 2762{ 2763 enum machine_mode cc_mode = visium_select_cc_mode (code, op0, op1); 2764 rtx flags = gen_rtx_REG (cc_mode, FLAGS_REGNUM); 2765 2766 rtx x = gen_rtx_COMPARE (cc_mode, op0, op1); 2767 x = gen_rtx_SET (VOIDmode, flags, x); 2768 emit_insn (x); 2769 2770 x = gen_rtx_fmt_ee (code, VOIDmode, flags, const0_rtx); 2771 x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, gen_rtx_LABEL_REF (Pmode, label), 2772 pc_rtx); 2773 x = gen_rtx_SET (VOIDmode, pc_rtx, x); 2774 emit_jump_insn (x); 2775 2776 visium_flags_exposed = true; 2777} 2778 2779/* Branch instructions on the Visium. 2780 2781 Setting aside the interrupt-handling specific instructions, the ISA has 2782 two branch instructions: BRR and BRA. The former is used to implement 2783 short branches (+/- 2^17) within functions and its target is encoded in 2784 the instruction. The latter is used to implement all the other types 2785 of control flow changes and its target might not be statically known 2786 or even easily predictable at run time. Here's a complete summary of 2787 the patterns that generate a BRA instruction: 2788 2789 1. Indirect jump 2790 2. Table jump 2791 3. Call 2792 4. Sibling call 2793 5. Return 2794 6. Long branch 2795 7. Trampoline 2796 2797 Among these patterns, only the return (5) and the long branch (6) can be 2798 conditional; all the other patterns are always unconditional. 2799 2800 The following algorithm can be used to identify the pattern for which 2801 the BRA instruction was generated and work out its target: 2802 2803 A. If the source is r21 and the destination is r0, this is a return (5) 2804 and the target is the caller (i.e. the value of r21 on function's 2805 entry). 2806 2807 B. If the source is rN, N != 21 and the destination is r0, this is either 2808 an indirect jump or a table jump (1, 2) and the target is not easily 2809 predictable. 2810 2811 C. If the source is rN, N != 21 and the destination is r21, this is a call 2812 (3) and the target is given by the preceding MOVIL/MOVIU pair for rN, 2813 unless this is an indirect call in which case the target is not easily 2814 predictable. 2815 2816 D. If the source is rN, N != 21 and the destination is also rN, this is 2817 either a sibling call or a trampoline (4, 7) and the target is given 2818 by the preceding MOVIL/MOVIU pair for rN. 2819 2820 E. If the source is r21 and the destination is also r21, this is a long 2821 branch (6) and the target is given by the preceding MOVIL/MOVIU pair 2822 for r21. 2823 2824 The other combinations are not used. This implementation has been devised 2825 to accommodate the branch predictor of the GR6 but is used unconditionally 2826 by the compiler, i.e. including for earlier processors. */ 2827 2828/* Output a conditional/unconditional branch to LABEL. COND is the string 2829 condition. INSN is the instruction. */ 2830 2831static const char * 2832output_branch (rtx label, const char *cond, rtx_insn *insn) 2833{ 2834 char str[64]; 2835 rtx operands[2]; 2836 2837 gcc_assert (cond); 2838 operands[0] = label; 2839 2840 /* If the length of the instruction is greater than 8, then this is a 2841 long branch and we need to work harder to emit it properly. */ 2842 if (get_attr_length (insn) > 8) 2843 { 2844 bool spilled; 2845 2846 /* If the link register has been saved, then we use it. */ 2847 if (current_function_saves_lr ()) 2848 { 2849 operands[1] = regno_reg_rtx [LINK_REGNUM]; 2850 spilled = false; 2851 } 2852 2853 /* Or else, if the long-branch register isn't live, we use it. */ 2854 else if (!df_regs_ever_live_p (long_branch_regnum)) 2855 { 2856 operands[1] = regno_reg_rtx [long_branch_regnum]; 2857 spilled = false; 2858 } 2859 2860 /* Otherwise, we will use the long-branch register but we need to 2861 spill it to the stack and reload it at the end. We should have 2862 reserved the LR slot for this purpose. */ 2863 else 2864 { 2865 operands[1] = regno_reg_rtx [long_branch_regnum]; 2866 spilled = true; 2867 gcc_assert (current_function_has_lr_slot ()); 2868 } 2869 2870 /* First emit the spill to the stack: 2871 2872 insn_in_delay_slot 2873 write.l [1](sp),reg */ 2874 if (spilled) 2875 { 2876 if (final_sequence) 2877 { 2878 rtx_insn *delay = NEXT_INSN (insn); 2879 int seen; 2880 gcc_assert (delay); 2881 2882 final_scan_insn (delay, asm_out_file, optimize, 0, &seen); 2883 PATTERN (delay) = gen_blockage (); 2884 INSN_CODE (delay) = -1; 2885 } 2886 2887 if (current_function_saves_fp ()) 2888 output_asm_insn ("write.l 1(sp),%1", operands); 2889 else 2890 output_asm_insn ("write.l (sp),%1", operands); 2891 } 2892 2893 /* Then emit the core sequence: 2894 2895 moviu reg,%u label 2896 movil reg,%l label 2897 bra tr,reg,reg 2898 2899 We don't use r0 as the destination register of the branch because we 2900 want the Branch Pre-decode Logic of the GR6 to use the Address Load 2901 Array to predict the branch target. */ 2902 output_asm_insn ("moviu %1,%%u %0", operands); 2903 output_asm_insn ("movil %1,%%l %0", operands); 2904 strcpy (str, "bra "); 2905 strcat (str, cond); 2906 strcat (str, ",%1,%1"); 2907 if (!spilled) 2908 strcat (str, "%#"); 2909 strcat (str, "\t\t;long branch"); 2910 output_asm_insn (str, operands); 2911 2912 /* Finally emit the reload: 2913 2914 read.l reg,[1](sp) */ 2915 if (spilled) 2916 { 2917 if (current_function_saves_fp ()) 2918 output_asm_insn (" read.l %1,1(sp)", operands); 2919 else 2920 output_asm_insn (" read.l %1,(sp)", operands); 2921 } 2922 } 2923 2924 /* Or else, if the label is PC, then this is a return. */ 2925 else if (label == pc_rtx) 2926 { 2927 strcpy (str, "bra "); 2928 strcat (str, cond); 2929 strcat (str, ",r21,r0%#\t\t;return"); 2930 output_asm_insn (str, operands); 2931 } 2932 2933 /* Otherwise, this is a short branch. */ 2934 else 2935 { 2936 strcpy (str, "brr "); 2937 strcat (str, cond); 2938 strcat (str, ",%0%#"); 2939 output_asm_insn (str, operands); 2940 } 2941 2942 return ""; 2943} 2944 2945/* Output an unconditional branch to LABEL. INSN is the instruction. */ 2946 2947const char * 2948output_ubranch (rtx label, rtx_insn *insn) 2949{ 2950 return output_branch (label, "tr", insn); 2951} 2952 2953/* Output a conditional branch to LABEL. CODE is the comparison code. 2954 CC_MODE is the mode of the CC register. REVERSED is non-zero if we 2955 should reverse the sense of the comparison. INSN is the instruction. */ 2956 2957const char * 2958output_cbranch (rtx label, enum rtx_code code, enum machine_mode cc_mode, 2959 int reversed, rtx_insn *insn) 2960{ 2961 const char *cond; 2962 2963 if (reversed) 2964 { 2965 if (cc_mode == CCFPmode || cc_mode == CCFPEmode) 2966 code = reverse_condition_maybe_unordered (code); 2967 else 2968 code = reverse_condition (code); 2969 } 2970 2971 switch (code) 2972 { 2973 case NE: 2974 if (cc_mode == CC_BTSTmode) 2975 cond = "cs"; 2976 else 2977 cond = "ne"; 2978 break; 2979 2980 case EQ: 2981 if (cc_mode == CC_BTSTmode) 2982 cond = "cc"; 2983 else 2984 cond = "eq"; 2985 break; 2986 2987 case GE: 2988 if (cc_mode == CC_NOOVmode) 2989 cond = "nc"; 2990 else 2991 cond = "ge"; 2992 break; 2993 2994 case GT: 2995 cond = "gt"; 2996 break; 2997 2998 case LE: 2999 if (cc_mode == CCFPmode || cc_mode == CCFPEmode) 3000 cond = "ls"; 3001 else 3002 cond = "le"; 3003 break; 3004 3005 case LT: 3006 if (cc_mode == CCFPmode || cc_mode == CCFPEmode) 3007 cond = "ns"; 3008 else if (cc_mode == CC_NOOVmode) 3009 cond = "ns"; 3010 else 3011 cond = "lt"; 3012 break; 3013 3014 case GEU: 3015 cond = "cc"; 3016 break; 3017 3018 case GTU: 3019 cond = "hi"; 3020 break; 3021 3022 case LEU: 3023 cond = "ls"; 3024 break; 3025 3026 case LTU: 3027 cond = "cs"; 3028 break; 3029 3030 case UNORDERED: 3031 cond = "os"; 3032 break; 3033 3034 case ORDERED: 3035 cond = "oc"; 3036 break; 3037 3038 case UNGE: 3039 cond = "nc"; 3040 break; 3041 3042 case UNGT: 3043 cond = "hi"; 3044 break; 3045 3046 case UNLE: 3047 cond = "le"; 3048 break; 3049 3050 case UNLT: 3051 cond = "lt"; 3052 break; 3053 3054 /* These 2 comparison codes are not supported. */ 3055 case UNEQ: 3056 case LTGT: 3057 default: 3058 gcc_unreachable (); 3059 } 3060 3061 return output_branch (label, cond, insn); 3062} 3063 3064/* Helper function for PRINT_OPERAND (STREAM, X, CODE). Output to stdio 3065 stream FILE the assembler syntax for an instruction operand OP subject 3066 to the modifier LETTER. */ 3067 3068void 3069print_operand (FILE *file, rtx op, int letter) 3070{ 3071 switch (letter) 3072 { 3073 case '#': 3074 /* Output an insn in a delay slot. */ 3075 if (final_sequence) 3076 visium_indent_opcode = 1; 3077 else 3078 fputs ("\n\t nop", file); 3079 return; 3080 3081 case 'b': 3082 /* Print LS 8 bits of operand. */ 3083 fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, UINTVAL (op) & 0xff); 3084 return; 3085 3086 case 'w': 3087 /* Print LS 16 bits of operand. */ 3088 fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, UINTVAL (op) & 0xffff); 3089 return; 3090 3091 case 'u': 3092 /* Print MS 16 bits of operand. */ 3093 fprintf (file, 3094 HOST_WIDE_INT_PRINT_UNSIGNED, (UINTVAL (op) >> 16) & 0xffff); 3095 return; 3096 3097 case 'r': 3098 /* It's either a register or zero. */ 3099 if (GET_CODE (op) == REG) 3100 fputs (reg_names[REGNO (op)], file); 3101 else 3102 fputs (reg_names[0], file); 3103 return; 3104 3105 case 'f': 3106 /* It's either a FP register or zero. */ 3107 if (GET_CODE (op) == REG) 3108 fputs (reg_names[REGNO (op)], file); 3109 else 3110 fputs (reg_names[FP_FIRST_REGNUM], file); 3111 return; 3112 } 3113 3114 switch (GET_CODE (op)) 3115 { 3116 case REG: 3117 if (letter == 'd') 3118 fputs (reg_names[REGNO (op) + 1], file); 3119 else 3120 fputs (reg_names[REGNO (op)], file); 3121 break; 3122 3123 case SYMBOL_REF: 3124 case LABEL_REF: 3125 case CONST: 3126 output_addr_const (file, op); 3127 break; 3128 3129 case MEM: 3130 visium_output_address (file, GET_MODE (op), XEXP (op, 0)); 3131 break; 3132 3133 case CONST_INT: 3134 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op)); 3135 break; 3136 3137 case CODE_LABEL: 3138 asm_fprintf (file, "%LL%d", CODE_LABEL_NUMBER (op)); 3139 break; 3140 3141 case HIGH: 3142 print_operand (file, XEXP (op, 1), letter); 3143 break; 3144 3145 default: 3146 fatal_insn ("illegal operand ", op); 3147 } 3148} 3149 3150/* Output to stdio stream FILE the assembler syntax for an instruction operand 3151 that is a memory reference in MODE and whose address is ADDR. */ 3152 3153static void 3154visium_output_address (FILE *file, enum machine_mode mode, rtx addr) 3155{ 3156 switch (GET_CODE (addr)) 3157 { 3158 case REG: 3159 case SUBREG: 3160 fprintf (file, "(%s)", reg_names[true_regnum (addr)]); 3161 break; 3162 3163 case PLUS: 3164 { 3165 rtx x = XEXP (addr, 0), y = XEXP (addr, 1); 3166 3167 switch (GET_CODE (x)) 3168 { 3169 case REG: 3170 case SUBREG: 3171 if (CONST_INT_P (y)) 3172 { 3173 unsigned int regno = true_regnum (x); 3174 HOST_WIDE_INT val = INTVAL (y); 3175 switch (mode) 3176 { 3177 case SImode: 3178 case DImode: 3179 case SFmode: 3180 case DFmode: 3181 val >>= 2; 3182 break; 3183 3184 case HImode: 3185 val >>= 1; 3186 break; 3187 3188 case QImode: 3189 default: 3190 break; 3191 } 3192 fprintf (file, HOST_WIDE_INT_PRINT_DEC"(%s)", val, 3193 reg_names[regno]); 3194 } 3195 else 3196 fatal_insn ("illegal operand address (1)", addr); 3197 break; 3198 3199 default: 3200 if (CONSTANT_P (x) && CONSTANT_P (y)) 3201 output_addr_const (file, addr); 3202 else 3203 fatal_insn ("illegal operand address (2)", addr); 3204 break; 3205 } 3206 } 3207 break; 3208 3209 case LABEL_REF: 3210 case SYMBOL_REF: 3211 case CONST_INT: 3212 case CONST: 3213 output_addr_const (file, addr); 3214 break; 3215 3216 case NOTE: 3217 if (NOTE_KIND (addr) != NOTE_INSN_DELETED_LABEL) 3218 fatal_insn ("illegal operand address (3)", addr); 3219 break; 3220 3221 case CODE_LABEL: 3222 asm_fprintf (file, "%LL%d", CODE_LABEL_NUMBER (addr)); 3223 break; 3224 3225 default: 3226 fatal_insn ("illegal operand address (4)", addr); 3227 break; 3228 } 3229} 3230 3231/* Helper function for PRINT_OPERAND_ADDRESS (STREAM, X). Output to stdio 3232 stream FILE the assembler syntax for an instruction operand that is a 3233 memory reference whose address is ADDR. */ 3234 3235void 3236print_operand_address (FILE *file, rtx addr) 3237{ 3238 visium_output_address (file, QImode, addr); 3239} 3240 3241/* The Visium stack frames look like: 3242 3243 Before call After call 3244 +-----------------------+ +-----------------------+ 3245 | | | | 3246 high | previous | | previous | 3247 mem | frame | | frame | 3248 | | | | 3249 +-----------------------+ +-----------------------+ 3250 | | | | 3251 | arguments on stack | | arguments on stack | 3252 | | | | 3253 SP+0->+-----------------------+ +-----------------------+ 3254 | reg parm save area, | 3255 | only created for | 3256 | variable argument | 3257 | functions | 3258 +-----------------------+ 3259 | | 3260 | register save area | 3261 | | 3262 +-----------------------+ 3263 | | 3264 | local variables | 3265 | | 3266 FP+8->+-----------------------+ 3267 | return address | 3268 FP+4->+-----------------------+ 3269 | previous FP | 3270 FP+0->+-----------------------+ 3271 | | 3272 | alloca allocations | 3273 | | 3274 +-----------------------+ 3275 | | 3276 low | arguments on stack | 3277 mem | | 3278 SP+0->+-----------------------+ 3279 3280 Notes: 3281 1) The "reg parm save area" does not exist for non variable argument fns. 3282 2) The FP register is not saved if `frame_pointer_needed' is zero and it 3283 is not altered in the current function. 3284 3) The return address is not saved if there is no frame pointer and the 3285 current function is leaf. 3286 4) If the return address is not saved and the static chain register is 3287 live in the function, we allocate the return address slot to be able 3288 to spill the register for a long branch. */ 3289 3290/* Define the register classes for local purposes. */ 3291enum reg_type { general, mdb, mdc, floating, last_type}; 3292 3293#define GET_REG_TYPE(regno) \ 3294 (GP_REGISTER_P (regno) ? general : \ 3295 (regno) == MDB_REGNUM ? mdb : \ 3296 (regno) == MDC_REGNUM ? mdc : \ 3297 floating) 3298 3299/* First regno of each register type. */ 3300const int first_regno[last_type] = {0, MDB_REGNUM, MDC_REGNUM, FP_FIRST_REGNUM}; 3301 3302/* Size in bytes of each register type. */ 3303const int reg_type_size[last_type] = {4, 8, 4, 4}; 3304 3305/* Structure to be filled in by visium_compute_frame_size. */ 3306struct visium_frame_info 3307{ 3308 unsigned int save_area_size; /* # bytes in the reg parm save area. */ 3309 unsigned int reg_size1; /* # bytes to store first block of regs. */ 3310 unsigned int reg_size2; /* # bytes to store second block of regs. */ 3311 unsigned int max_reg1; /* max. regno in first block */ 3312 unsigned int var_size; /* # bytes that variables take up. */ 3313 unsigned int save_fp; /* Nonzero if fp must be saved. */ 3314 unsigned int save_lr; /* Nonzero if lr must be saved. */ 3315 unsigned int lr_slot; /* Nonzero if the lr slot is needed. */ 3316 unsigned int combine; /* Nonzero if we can combine the allocation of 3317 variables and regs. */ 3318 unsigned int interrupt; /* Nonzero if the function is an interrupt 3319 handler. */ 3320 unsigned int mask[last_type]; /* Masks of saved regs: gp, mdb, mdc, fp */ 3321}; 3322 3323/* Current frame information calculated by visium_compute_frame_size. */ 3324static struct visium_frame_info current_frame_info; 3325 3326/* Accessor for current_frame_info.save_fp. */ 3327 3328static inline bool 3329current_function_saves_fp (void) 3330{ 3331 return current_frame_info.save_fp != 0; 3332} 3333 3334/* Accessor for current_frame_info.save_lr. */ 3335 3336static inline bool 3337current_function_saves_lr (void) 3338{ 3339 return current_frame_info.save_lr != 0; 3340} 3341 3342/* Accessor for current_frame_info.lr_slot. */ 3343 3344static inline bool 3345current_function_has_lr_slot (void) 3346{ 3347 return current_frame_info.lr_slot != 0; 3348} 3349 3350/* Return non-zero if register REGNO needs to be saved in the frame. */ 3351 3352static int 3353visium_save_reg_p (int interrupt, int regno) 3354{ 3355 switch (regno) 3356 { 3357 case HARD_FRAME_POINTER_REGNUM: 3358 /* This register is call-saved but handled specially. */ 3359 return 0; 3360 3361 case MDC_REGNUM: 3362 /* This register is fixed but can be modified. */ 3363 break; 3364 3365 case 29: 3366 case 30: 3367 /* These registers are fixed and hold the interrupt context. */ 3368 return (interrupt != 0); 3369 3370 default: 3371 /* The other fixed registers are either immutable or special. */ 3372 if (fixed_regs[regno]) 3373 return 0; 3374 break; 3375 } 3376 3377 if (interrupt) 3378 { 3379 if (crtl->is_leaf) 3380 { 3381 if (df_regs_ever_live_p (regno)) 3382 return 1; 3383 } 3384 else if (call_used_regs[regno]) 3385 return 1; 3386 3387 /* To save mdb requires two temporary registers. To save mdc or 3388 any of the floating registers requires one temporary 3389 register. If this is an interrupt routine, the temporary 3390 registers need to be saved as well. These temporary registers 3391 are call used, so we only need deal with the case of leaf 3392 functions here. */ 3393 if (regno == PROLOGUE_TMP_REGNUM) 3394 { 3395 if (df_regs_ever_live_p (MDB_REGNUM) 3396 || df_regs_ever_live_p (MDC_REGNUM)) 3397 return 1; 3398 3399 for (int i = FP_FIRST_REGNUM; i <= FP_LAST_REGNUM; i++) 3400 if (df_regs_ever_live_p (i)) 3401 return 1; 3402 } 3403 3404 else if (regno == PROLOGUE_TMP_REGNUM + 1) 3405 { 3406 if (df_regs_ever_live_p (MDB_REGNUM)) 3407 return 1; 3408 } 3409 } 3410 3411 return df_regs_ever_live_p (regno) && !call_used_regs[regno]; 3412} 3413 3414/* Compute the frame size required by the function. This function is called 3415 during the reload pass and also by visium_expand_prologue. */ 3416 3417static int 3418visium_compute_frame_size (int size) 3419{ 3420 const int save_area_size = visium_reg_parm_save_area_size; 3421 const int var_size = VISIUM_STACK_ALIGN (size); 3422 const int save_fp 3423 = frame_pointer_needed || df_regs_ever_live_p (HARD_FRAME_POINTER_REGNUM); 3424 const int save_lr = frame_pointer_needed || !crtl->is_leaf; 3425 const int lr_slot = !save_lr && df_regs_ever_live_p (long_branch_regnum); 3426 const int local_frame_offset 3427 = (save_fp + save_lr + lr_slot) * UNITS_PER_WORD; 3428 const int interrupt = visium_interrupt_function_p (); 3429 unsigned int mask[last_type]; 3430 int reg_size1 = 0; 3431 int max_reg1 = 0; 3432 int reg_size2 = 0; 3433 int reg_size; 3434 int combine; 3435 int frame_size; 3436 int regno; 3437 3438 memset (mask, 0, last_type * sizeof (unsigned int)); 3439 3440 /* The registers may need stacking in 2 blocks since only 32 32-bit words 3441 can be indexed from a given base address. */ 3442 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 3443 { 3444 if (visium_save_reg_p (interrupt, regno)) 3445 { 3446 enum reg_type reg_type = GET_REG_TYPE (regno); 3447 int mask_bit = 1 << (regno - first_regno[reg_type]); 3448 int nbytes = reg_type_size[reg_type]; 3449 3450 if (reg_size1 + nbytes > 32 * UNITS_PER_WORD) 3451 break; 3452 3453 reg_size1 += nbytes; 3454 max_reg1 = regno; 3455 mask[reg_type] |= mask_bit; 3456 } 3457 } 3458 3459 for (regno = max_reg1 + 1; regno < FIRST_PSEUDO_REGISTER; regno++) 3460 { 3461 if (visium_save_reg_p (interrupt, regno)) 3462 { 3463 enum reg_type reg_type = GET_REG_TYPE (regno); 3464 int mask_bit = 1 << (regno - first_regno[reg_type]); 3465 int nbytes = reg_type_size[reg_type]; 3466 3467 reg_size2 += nbytes; 3468 mask[reg_type] |= mask_bit; 3469 } 3470 } 3471 3472 reg_size = reg_size2 ? reg_size2 : reg_size1; 3473 combine = (local_frame_offset + var_size + reg_size) <= 32 * UNITS_PER_WORD; 3474 frame_size 3475 = local_frame_offset + var_size + reg_size2 + reg_size1 + save_area_size; 3476 3477 current_frame_info.save_area_size = save_area_size; 3478 current_frame_info.reg_size1 = reg_size1; 3479 current_frame_info.max_reg1 = max_reg1; 3480 current_frame_info.reg_size2 = reg_size2; 3481 current_frame_info.var_size = var_size; 3482 current_frame_info.save_fp = save_fp; 3483 current_frame_info.save_lr = save_lr; 3484 current_frame_info.lr_slot = lr_slot; 3485 current_frame_info.combine = combine; 3486 current_frame_info.interrupt = interrupt; 3487 3488 memcpy (current_frame_info.mask, mask, last_type * sizeof (unsigned int)); 3489 3490 return frame_size; 3491} 3492 3493/* Helper function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET). Define 3494 the offset between two registers, one to be eliminated, and the other its 3495 replacement, at the start of a routine. */ 3496 3497int 3498visium_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED) 3499{ 3500 const int frame_size = visium_compute_frame_size (get_frame_size ()); 3501 const int save_fp = current_frame_info.save_fp; 3502 const int save_lr = current_frame_info.save_lr; 3503 const int lr_slot = current_frame_info.lr_slot; 3504 const int local_frame_offset 3505 = (save_fp + save_lr + lr_slot) * UNITS_PER_WORD; 3506 int offset; 3507 3508 if (from == FRAME_POINTER_REGNUM) 3509 offset = local_frame_offset; 3510 else if (from == ARG_POINTER_REGNUM) 3511 offset = frame_size; 3512 else 3513 gcc_unreachable (); 3514 3515 return offset; 3516} 3517 3518/* For an interrupt handler, we may be saving call-clobbered registers. 3519 Say the epilogue uses these in addition to the link register. */ 3520 3521int 3522visium_epilogue_uses (int regno) 3523{ 3524 if (regno == LINK_REGNUM) 3525 return 1; 3526 3527 if (reload_completed) 3528 { 3529 enum reg_type reg_type = GET_REG_TYPE (regno); 3530 int mask_bit = 1 << (regno - first_regno[reg_type]); 3531 3532 return (current_frame_info.mask[reg_type] & mask_bit) != 0; 3533 } 3534 3535 return 0; 3536} 3537 3538/* Wrapper around emit_insn that sets RTX_FRAME_RELATED_P on the insn. */ 3539 3540static rtx 3541emit_frame_insn (rtx x) 3542{ 3543 x = emit_insn (x); 3544 RTX_FRAME_RELATED_P (x) = 1; 3545 return x; 3546} 3547 3548/* Allocate ALLOC bytes on the stack and save the registers LOW_REGNO to 3549 HIGH_REGNO at OFFSET from the stack pointer. */ 3550 3551static void 3552visium_save_regs (int alloc, int offset, int low_regno, int high_regno) 3553{ 3554 /* If this is an interrupt handler function, then mark the register 3555 stores as volatile. This will prevent the instruction scheduler 3556 from scrambling the order of register saves. */ 3557 const int volatile_p = current_frame_info.interrupt; 3558 int regno; 3559 3560 /* Allocate the stack space. */ 3561 emit_frame_insn (gen_addsi3_flags (stack_pointer_rtx, stack_pointer_rtx, 3562 GEN_INT (-alloc))); 3563 3564 for (regno = low_regno; regno <= high_regno; regno++) 3565 { 3566 enum reg_type reg_type = GET_REG_TYPE (regno); 3567 int mask_bit = 1 << (regno - first_regno[reg_type]); 3568 rtx insn; 3569 3570 if (current_frame_info.mask[reg_type] & mask_bit) 3571 { 3572 offset -= reg_type_size[reg_type]; 3573 switch (reg_type) 3574 { 3575 case general: 3576 { 3577 rtx mem 3578 = gen_frame_mem (SImode, 3579 plus_constant (Pmode, 3580 stack_pointer_rtx, offset)); 3581 MEM_VOLATILE_P (mem) = volatile_p; 3582 emit_frame_insn (gen_movsi (mem, gen_rtx_REG (SImode, regno))); 3583 } 3584 break; 3585 3586 case mdb: 3587 { 3588 rtx tmp = gen_rtx_REG (DImode, PROLOGUE_TMP_REGNUM); 3589 rtx mem 3590 = gen_frame_mem (DImode, 3591 plus_constant (Pmode, 3592 stack_pointer_rtx, offset)); 3593 rtx reg = gen_rtx_REG (DImode, regno); 3594 MEM_VOLATILE_P (mem) = volatile_p; 3595 emit_insn (gen_movdi (tmp, reg)); 3596 /* Do not generate CFI if in interrupt handler. */ 3597 if (volatile_p) 3598 emit_insn (gen_movdi (mem, tmp)); 3599 else 3600 { 3601 insn = emit_frame_insn (gen_movdi (mem, tmp)); 3602 add_reg_note (insn, REG_FRAME_RELATED_EXPR, 3603 gen_rtx_SET (VOIDmode, mem, reg)); 3604 } 3605 } 3606 break; 3607 3608 case mdc: 3609 { 3610 rtx tmp = gen_rtx_REG (SImode, PROLOGUE_TMP_REGNUM); 3611 rtx mem 3612 = gen_frame_mem (SImode, 3613 plus_constant (Pmode, 3614 stack_pointer_rtx, offset)); 3615 rtx reg = gen_rtx_REG (SImode, regno); 3616 MEM_VOLATILE_P (mem) = volatile_p; 3617 emit_insn (gen_movsi (tmp, reg)); 3618 insn = emit_frame_insn (gen_movsi (mem, tmp)); 3619 add_reg_note (insn, REG_FRAME_RELATED_EXPR, 3620 gen_rtx_SET (VOIDmode, mem, reg)); 3621 } 3622 break; 3623 3624 case floating: 3625 { 3626 rtx tmp = gen_rtx_REG (SFmode, PROLOGUE_TMP_REGNUM); 3627 rtx mem 3628 = gen_frame_mem (SFmode, 3629 plus_constant (Pmode, 3630 stack_pointer_rtx, offset)); 3631 rtx reg = gen_rtx_REG (SFmode, regno); 3632 MEM_VOLATILE_P (mem) = volatile_p; 3633 emit_insn (gen_movsf (tmp, reg)); 3634 insn = emit_frame_insn (gen_movsf (mem, tmp)); 3635 add_reg_note (insn, REG_FRAME_RELATED_EXPR, 3636 gen_rtx_SET (VOIDmode, mem, reg)); 3637 } 3638 break; 3639 3640 default: 3641 break; 3642 } 3643 } 3644 } 3645} 3646 3647/* This function generates the code for function entry. */ 3648 3649void 3650visium_expand_prologue (void) 3651{ 3652 const int frame_size = visium_compute_frame_size (get_frame_size ()); 3653 const int save_area_size = current_frame_info.save_area_size; 3654 const int reg_size1 = current_frame_info.reg_size1; 3655 const int max_reg1 = current_frame_info.max_reg1; 3656 const int reg_size2 = current_frame_info.reg_size2; 3657 const int var_size = current_frame_info.var_size; 3658 const int save_fp = current_frame_info.save_fp; 3659 const int save_lr = current_frame_info.save_lr; 3660 const int lr_slot = current_frame_info.lr_slot; 3661 const int local_frame_offset 3662 = (save_fp + save_lr + lr_slot) * UNITS_PER_WORD; 3663 const int combine = current_frame_info.combine; 3664 int reg_size; 3665 int first_reg; 3666 int fsize; 3667 3668 /* Save the frame size for future references. */ 3669 visium_frame_size = frame_size; 3670 3671 if (flag_stack_usage_info) 3672 current_function_static_stack_size = frame_size; 3673 3674 /* If the registers have to be stacked in 2 blocks, stack the first one. */ 3675 if (reg_size2) 3676 { 3677 visium_save_regs (reg_size1 + save_area_size, reg_size1, 0, max_reg1); 3678 reg_size = reg_size2; 3679 first_reg = max_reg1 + 1; 3680 fsize = local_frame_offset + var_size + reg_size2; 3681 } 3682 else 3683 { 3684 reg_size = reg_size1; 3685 first_reg = 0; 3686 fsize = local_frame_offset + var_size + reg_size1 + save_area_size; 3687 } 3688 3689 /* If we can't combine register stacking with variable allocation, partially 3690 allocate and stack the (remaining) registers now. */ 3691 if (reg_size && !combine) 3692 visium_save_regs (fsize - local_frame_offset - var_size, reg_size, 3693 first_reg, FIRST_PSEUDO_REGISTER - 1); 3694 3695 /* If we can combine register stacking with variable allocation, fully 3696 allocate and stack the (remaining) registers now. */ 3697 if (reg_size && combine) 3698 visium_save_regs (fsize, local_frame_offset + var_size + reg_size, 3699 first_reg, FIRST_PSEUDO_REGISTER - 1); 3700 3701 /* Otherwise space may still need to be allocated for the variables. */ 3702 else if (fsize) 3703 { 3704 const int alloc_size = reg_size ? local_frame_offset + var_size : fsize; 3705 3706 if (alloc_size > 65535) 3707 { 3708 rtx tmp = gen_rtx_REG (SImode, PROLOGUE_TMP_REGNUM), insn; 3709 emit_insn (gen_movsi (tmp, GEN_INT (alloc_size))); 3710 insn = emit_frame_insn (gen_subsi3_flags (stack_pointer_rtx, 3711 stack_pointer_rtx, 3712 tmp)); 3713 add_reg_note (insn, REG_FRAME_RELATED_EXPR, 3714 gen_rtx_SET (VOIDmode, stack_pointer_rtx, 3715 gen_rtx_PLUS (Pmode, stack_pointer_rtx, 3716 GEN_INT (-alloc_size)))); 3717 } 3718 else 3719 emit_frame_insn (gen_addsi3_flags (stack_pointer_rtx, 3720 stack_pointer_rtx, 3721 GEN_INT (-alloc_size))); 3722 } 3723 3724 if (save_fp) 3725 emit_frame_insn (gen_movsi (gen_frame_mem (SImode, stack_pointer_rtx), 3726 hard_frame_pointer_rtx)); 3727 3728 if (frame_pointer_needed) 3729 emit_frame_insn (gen_stack_save ()); 3730 3731 if (save_lr) 3732 { 3733 rtx base_rtx, mem; 3734 3735 /* Normally the frame pointer and link register get saved via 3736 write.l (sp),fp 3737 move.l fp,sp 3738 write.l 1(sp),r21 3739 3740 Indexing off sp rather than fp to store the link register 3741 avoids presenting the instruction scheduler with an initial 3742 pipeline hazard. If however the frame is needed for eg. 3743 __builtin_return_address which needs to retrieve the saved 3744 value of the link register from the stack at fp + 4 then 3745 indexing from sp can confuse the dataflow, causing the link 3746 register to be retrieved before it has been saved. */ 3747 if (cfun->machine->frame_needed) 3748 base_rtx = hard_frame_pointer_rtx; 3749 else 3750 base_rtx = stack_pointer_rtx; 3751 3752 mem = gen_frame_mem (SImode, 3753 plus_constant (Pmode, 3754 base_rtx, save_fp * UNITS_PER_WORD)); 3755 emit_frame_insn (gen_movsi (mem, gen_rtx_REG (SImode, LINK_REGNUM))); 3756 } 3757} 3758 3759static GTY(()) rtx cfa_restores; 3760 3761/* Queue a REG_CFA_RESTORE note until next stack manipulation insn. */ 3762 3763static void 3764visium_add_cfa_restore_note (rtx reg) 3765{ 3766 cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores); 3767} 3768 3769/* Add queued REG_CFA_RESTORE notes to INSN, if any. */ 3770 3771static void 3772visium_add_queued_cfa_restore_notes (rtx insn) 3773{ 3774 rtx last; 3775 if (!cfa_restores) 3776 return; 3777 for (last = cfa_restores; XEXP (last, 1); last = XEXP (last, 1)) 3778 ; 3779 XEXP (last, 1) = REG_NOTES (insn); 3780 REG_NOTES (insn) = cfa_restores; 3781 cfa_restores = NULL_RTX; 3782} 3783 3784/* Restore the registers LOW_REGNO to HIGH_REGNO from the save area at OFFSET 3785 from the stack pointer and pop DEALLOC bytes off the stack. */ 3786 3787static void 3788visium_restore_regs (int dealloc, int offset, int high_regno, int low_regno) 3789{ 3790 /* If this is an interrupt handler function, then mark the register 3791 restores as volatile. This will prevent the instruction scheduler 3792 from scrambling the order of register restores. */ 3793 const int volatile_p = current_frame_info.interrupt; 3794 int r30_offset = -1; 3795 int regno; 3796 3797 for (regno = high_regno; regno >= low_regno; --regno) 3798 { 3799 enum reg_type reg_type = GET_REG_TYPE (regno); 3800 int mask_bit = 1 << (regno - first_regno[reg_type]); 3801 3802 if (current_frame_info.mask[reg_type] & mask_bit) 3803 { 3804 switch (reg_type) 3805 { 3806 case general: 3807 /* Postpone restoring the interrupted context registers 3808 until last, since they need to be preceded by a dsi. */ 3809 if (regno == 29) 3810 ; 3811 else if (regno == 30) 3812 r30_offset = offset; 3813 else 3814 { 3815 rtx mem 3816 = gen_frame_mem (SImode, 3817 plus_constant (Pmode, 3818 stack_pointer_rtx, 3819 offset)); 3820 rtx reg = gen_rtx_REG (SImode, regno); 3821 MEM_VOLATILE_P (mem) = volatile_p; 3822 emit_insn (gen_movsi (reg, mem)); 3823 visium_add_cfa_restore_note (reg); 3824 } 3825 break; 3826 3827 case mdb: 3828 { 3829 rtx tmp = gen_rtx_REG (DImode, PROLOGUE_TMP_REGNUM); 3830 rtx mem 3831 = gen_frame_mem (DImode, 3832 plus_constant (Pmode, 3833 stack_pointer_rtx, offset)); 3834 rtx reg = gen_rtx_REG (DImode, regno); 3835 MEM_VOLATILE_P (mem) = volatile_p; 3836 emit_insn (gen_movdi (tmp, mem)); 3837 emit_insn (gen_movdi (reg, tmp)); 3838 /* Do not generate CFI if in interrupt handler. */ 3839 if (!volatile_p) 3840 visium_add_cfa_restore_note (reg); 3841 } 3842 break; 3843 3844 case mdc: 3845 { 3846 rtx tmp = gen_rtx_REG (SImode, PROLOGUE_TMP_REGNUM); 3847 rtx mem 3848 = gen_frame_mem (SImode, 3849 plus_constant (Pmode, 3850 stack_pointer_rtx, offset)); 3851 rtx reg = gen_rtx_REG (SImode, regno); 3852 MEM_VOLATILE_P (mem) = volatile_p; 3853 emit_insn (gen_movsi (tmp, mem)); 3854 emit_insn (gen_movsi (reg, tmp)); 3855 visium_add_cfa_restore_note (reg); 3856 } 3857 break; 3858 3859 case floating: 3860 { 3861 rtx tmp = gen_rtx_REG (SFmode, PROLOGUE_TMP_REGNUM); 3862 rtx mem 3863 = gen_frame_mem (SFmode, 3864 plus_constant (Pmode, 3865 stack_pointer_rtx, offset)); 3866 rtx reg = gen_rtx_REG (SFmode, regno); 3867 MEM_VOLATILE_P (mem) = volatile_p; 3868 emit_insn (gen_movsf (tmp, mem)); 3869 emit_insn (gen_movsf (reg, tmp)); 3870 visium_add_cfa_restore_note (reg); 3871 } 3872 break; 3873 3874 default: 3875 break; 3876 } 3877 3878 offset += reg_type_size[reg_type]; 3879 } 3880 } 3881 3882 /* If the interrupted context needs to be restored, precede the 3883 restores of r29 and r30 by a dsi. */ 3884 if (r30_offset >= 0) 3885 { 3886 emit_insn (gen_dsi ()); 3887 emit_move_insn (gen_rtx_REG (SImode, 30), 3888 gen_frame_mem (SImode, 3889 plus_constant (Pmode, 3890 stack_pointer_rtx, 3891 r30_offset))); 3892 emit_move_insn (gen_rtx_REG (SImode, 29), 3893 gen_frame_mem (SImode, 3894 plus_constant (Pmode, 3895 stack_pointer_rtx, 3896 r30_offset + 4))); 3897 } 3898 3899 /* Deallocate the stack space. */ 3900 rtx insn = emit_frame_insn (gen_stack_pop (GEN_INT (dealloc))); 3901 add_reg_note (insn, REG_FRAME_RELATED_EXPR, 3902 gen_rtx_SET (VOIDmode, stack_pointer_rtx, 3903 gen_rtx_PLUS (Pmode, stack_pointer_rtx, 3904 GEN_INT (dealloc)))); 3905 visium_add_queued_cfa_restore_notes (insn); 3906} 3907 3908/* This function generates the code for function exit. */ 3909 3910void 3911visium_expand_epilogue (void) 3912{ 3913 const int save_area_size = current_frame_info.save_area_size; 3914 const int reg_size1 = current_frame_info.reg_size1; 3915 const int max_reg1 = current_frame_info.max_reg1; 3916 const int reg_size2 = current_frame_info.reg_size2; 3917 const int var_size = current_frame_info.var_size; 3918 const int restore_fp = current_frame_info.save_fp; 3919 const int restore_lr = current_frame_info.save_lr; 3920 const int lr_slot = current_frame_info.lr_slot; 3921 const int local_frame_offset 3922 = (restore_fp + restore_lr + lr_slot) * UNITS_PER_WORD; 3923 const int combine = current_frame_info.combine; 3924 int reg_size; 3925 int last_reg; 3926 int fsize; 3927 3928 /* Do not bother restoring the stack pointer if it hasn't been changed in 3929 the function since it was saved _after_ the allocation of the frame. */ 3930 if (!crtl->sp_is_unchanging) 3931 emit_insn (gen_stack_restore ()); 3932 3933 /* Restore the frame pointer if necessary. The usual code would be: 3934 3935 move.l sp,fp 3936 read.l fp,(sp) 3937 3938 but for the MCM this constitutes a stall/hazard so it is changed to: 3939 3940 move.l sp,fp 3941 read.l fp,(fp) 3942 3943 if the stack pointer has actually been restored. */ 3944 if (restore_fp) 3945 { 3946 rtx src; 3947 3948 if (TARGET_MCM && !crtl->sp_is_unchanging) 3949 src = gen_frame_mem (SImode, hard_frame_pointer_rtx); 3950 else 3951 src = gen_frame_mem (SImode, stack_pointer_rtx); 3952 3953 rtx insn = emit_frame_insn (gen_movsi (hard_frame_pointer_rtx, src)); 3954 add_reg_note (insn, REG_CFA_ADJUST_CFA, 3955 gen_rtx_SET (VOIDmode, stack_pointer_rtx, 3956 hard_frame_pointer_rtx)); 3957 visium_add_cfa_restore_note (hard_frame_pointer_rtx); 3958 } 3959 3960 /* Restore the link register if necessary. */ 3961 if (restore_lr) 3962 { 3963 rtx mem = gen_frame_mem (SImode, 3964 plus_constant (Pmode, 3965 stack_pointer_rtx, 3966 restore_fp * UNITS_PER_WORD)); 3967 rtx reg = gen_rtx_REG (SImode, LINK_REGNUM); 3968 emit_insn (gen_movsi (reg, mem)); 3969 visium_add_cfa_restore_note (reg); 3970 } 3971 3972 /* If we have two blocks of registers, deal with the second one first. */ 3973 if (reg_size2) 3974 { 3975 reg_size = reg_size2; 3976 last_reg = max_reg1 + 1; 3977 fsize = local_frame_offset + var_size + reg_size2; 3978 } 3979 else 3980 { 3981 reg_size = reg_size1; 3982 last_reg = 0; 3983 fsize = local_frame_offset + var_size + reg_size1 + save_area_size; 3984 } 3985 3986 /* If the variable allocation could be combined with register stacking, 3987 restore the (remaining) registers and fully deallocate now. */ 3988 if (reg_size && combine) 3989 visium_restore_regs (fsize, local_frame_offset + var_size, 3990 FIRST_PSEUDO_REGISTER - 1, last_reg); 3991 3992 /* Otherwise deallocate the variables first. */ 3993 else if (fsize) 3994 { 3995 const int pop_size = reg_size ? local_frame_offset + var_size : fsize; 3996 rtx insn; 3997 3998 if (pop_size > 65535) 3999 { 4000 rtx tmp = gen_rtx_REG (SImode, PROLOGUE_TMP_REGNUM); 4001 emit_move_insn (tmp, GEN_INT (pop_size)); 4002 insn = emit_frame_insn (gen_stack_pop (tmp)); 4003 } 4004 else 4005 insn = emit_frame_insn (gen_stack_pop (GEN_INT (pop_size))); 4006 add_reg_note (insn, REG_FRAME_RELATED_EXPR, 4007 gen_rtx_SET (VOIDmode, stack_pointer_rtx, 4008 gen_rtx_PLUS (Pmode, stack_pointer_rtx, 4009 GEN_INT (pop_size)))); 4010 visium_add_queued_cfa_restore_notes (insn); 4011 } 4012 4013 /* If the variable allocation couldn't be combined with register stacking, 4014 restore the (remaining) registers now and partially deallocate. */ 4015 if (reg_size && !combine) 4016 visium_restore_regs (fsize - local_frame_offset - var_size, 0, 4017 FIRST_PSEUDO_REGISTER - 1, last_reg); 4018 4019 /* If the first block of registers has yet to be restored, do it now. */ 4020 if (reg_size2) 4021 visium_restore_regs (reg_size1 + save_area_size, 0, max_reg1, 0); 4022 4023 /* If this is an exception return, make the necessary stack adjustment. */ 4024 if (crtl->calls_eh_return) 4025 emit_insn (gen_stack_pop (EH_RETURN_STACKADJ_RTX)); 4026} 4027 4028/* Return true if it is appropriate to emit `return' instructions in the 4029 body of a function. */ 4030 4031bool 4032visium_can_use_return_insn_p (void) 4033{ 4034 return reload_completed 4035 && visium_frame_size == 0 4036 && !visium_interrupt_function_p (); 4037} 4038 4039/* Return the register class required for an intermediate register used to 4040 copy a register of RCLASS from/to X. If no such intermediate register is 4041 required, return NO_REGS. If more than one such intermediate register is 4042 required, describe the one that is closest in the copy chain to the reload 4043 register. */ 4044 4045static reg_class_t 4046visium_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x, 4047 reg_class_t rclass, 4048 enum machine_mode mode ATTRIBUTE_UNUSED, 4049 secondary_reload_info *sri ATTRIBUTE_UNUSED) 4050{ 4051 int regno = true_regnum (x); 4052 4053 /* For MDB, MDC and FP_REGS, a general register is needed for a move to 4054 or from memory. */ 4055 if (regno == -1 && (rclass == MDB || rclass == MDC || rclass == FP_REGS)) 4056 return GENERAL_REGS; 4057 4058 /* Moves between MDB, MDC and FP_REGS also require a general register. */ 4059 else if (((regno == R_MDB || regno == R_MDC) && rclass == FP_REGS) 4060 || (FP_REGISTER_P (regno) && (rclass == MDB || rclass == MDC))) 4061 return GENERAL_REGS; 4062 4063 /* Finally an (unlikely ?) move between MDB and MDC needs a general reg. */ 4064 else if ((regno == R_MDB && rclass == MDC) 4065 || (rclass == MDB && regno == R_MDC)) 4066 return GENERAL_REGS; 4067 4068 return NO_REGS; 4069} 4070 4071/* Return true if pseudos that have been assigned to registers of RCLASS 4072 would likely be spilled because registers of RCLASS are needed for 4073 spill registers. */ 4074 4075static bool 4076visium_class_likely_spilled_p (reg_class_t rclass ATTRIBUTE_UNUSED) 4077{ 4078 /* Return false for classes R1, R2 and R3, which are intended to be used 4079 only in the source code in conjunction with block move instructions. */ 4080 return false; 4081} 4082 4083/* Return the register number if OP is a REG or a SUBREG of a REG, and 4084 INVALID_REGNUM in all the other cases. */ 4085 4086unsigned int 4087reg_or_subreg_regno (rtx op) 4088{ 4089 unsigned int regno; 4090 4091 if (GET_CODE (op) == REG) 4092 regno = REGNO (op); 4093 else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) 4094 { 4095 if (REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER) 4096 regno = subreg_regno (op); 4097 else 4098 regno = REGNO (SUBREG_REG (op)); 4099 } 4100 else 4101 regno = INVALID_REGNUM; 4102 4103 return regno; 4104} 4105 4106#include "gt-visium.h" 4107