1/* Definitions for Toshiba Media Processor 2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 3 Free Software Foundation, Inc. 4 Contributed by Red Hat, Inc. 5 6This file is part of GCC. 7 8GCC is free software; you can redistribute it and/or modify it under 9the terms of the GNU General Public License as published by the Free 10Software Foundation; either version 3, or (at your option) any later 11version. 12 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14WARRANTY; without even the implied warranty of MERCHANTABILITY or 15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16for more details. 17 18You should have received a copy of the GNU General Public License 19along with GCC; see the file COPYING3. If not see 20<http://www.gnu.org/licenses/>. */ 21 22#include "config.h" 23#include "system.h" 24#include "coretypes.h" 25#include "tm.h" 26#include "rtl.h" 27#include "tree.h" 28#include "regs.h" 29#include "hard-reg-set.h" 30#include "real.h" 31#include "insn-config.h" 32#include "conditions.h" 33#include "insn-flags.h" 34#include "output.h" 35#include "insn-attr.h" 36#include "flags.h" 37#include "recog.h" 38#include "obstack.h" 39#include "tree.h" 40#include "expr.h" 41#include "except.h" 42#include "function.h" 43#include "optabs.h" 44#include "reload.h" 45#include "tm_p.h" 46#include "ggc.h" 47#include "toplev.h" 48#include "integrate.h" 49#include "target.h" 50#include "target-def.h" 51#include "langhooks.h" 52#include "df.h" 53#include "gimple.h" 54 55/* Structure of this file: 56 57 + Command Line Option Support 58 + Pattern support - constraints, predicates, expanders 59 + Reload Support 60 + Costs 61 + Functions to save and restore machine-specific function data. 62 + Frame/Epilog/Prolog Related 63 + Operand Printing 64 + Function args in registers 65 + Handle pipeline hazards 66 + Handle attributes 67 + Trampolines 68 + Machine-dependent Reorg 69 + Builtins. */ 70 71/* Symbol encodings: 72 73 Symbols are encoded as @ <char> . <name> where <char> is one of these: 74 75 b - based 76 t - tiny 77 n - near 78 f - far 79 i - io, near 80 I - io, far 81 c - cb (control bus) */ 82 83struct GTY(()) machine_function 84{ 85 int mep_frame_pointer_needed; 86 87 /* For varargs. */ 88 int arg_regs_to_save; 89 int regsave_filler; 90 int frame_filler; 91 int frame_locked; 92 93 /* Records __builtin_return address. */ 94 rtx eh_stack_adjust; 95 96 int reg_save_size; 97 int reg_save_slot[FIRST_PSEUDO_REGISTER]; 98 unsigned char reg_saved[FIRST_PSEUDO_REGISTER]; 99 100 /* 2 if the current function has an interrupt attribute, 1 if not, 0 101 if unknown. This is here because resource.c uses EPILOGUE_USES 102 which needs it. */ 103 int interrupt_handler; 104 105 /* Likewise, for disinterrupt attribute. */ 106 int disable_interrupts; 107 108 /* Number of doloop tags used so far. */ 109 int doloop_tags; 110 111 /* True if the last tag was allocated to a doloop_end. */ 112 bool doloop_tag_from_end; 113 114 /* True if reload changes $TP. */ 115 bool reload_changes_tp; 116 117 /* 2 if there are asm()s without operands, 1 if not, 0 if unknown. 118 We only set this if the function is an interrupt handler. */ 119 int asms_without_operands; 120}; 121 122#define MEP_CONTROL_REG(x) \ 123 (GET_CODE (x) == REG && ANY_CONTROL_REGNO_P (REGNO (x))) 124 125static const struct attribute_spec mep_attribute_table[11]; 126 127static GTY(()) section * based_section; 128static GTY(()) section * tinybss_section; 129static GTY(()) section * far_section; 130static GTY(()) section * farbss_section; 131static GTY(()) section * frodata_section; 132static GTY(()) section * srodata_section; 133 134static GTY(()) section * vtext_section; 135static GTY(()) section * vftext_section; 136static GTY(()) section * ftext_section; 137 138static void mep_set_leaf_registers (int); 139static bool symbol_p (rtx); 140static bool symbolref_p (rtx); 141static void encode_pattern_1 (rtx); 142static void encode_pattern (rtx); 143static bool const_in_range (rtx, int, int); 144static void mep_rewrite_mult (rtx, rtx); 145static void mep_rewrite_mulsi3 (rtx, rtx, rtx, rtx); 146static void mep_rewrite_maddsi3 (rtx, rtx, rtx, rtx, rtx); 147static bool mep_reuse_lo_p_1 (rtx, rtx, rtx, bool); 148static bool move_needs_splitting (rtx, rtx, enum machine_mode); 149static bool mep_expand_setcc_1 (enum rtx_code, rtx, rtx, rtx); 150static bool mep_nongeneral_reg (rtx); 151static bool mep_general_copro_reg (rtx); 152static bool mep_nonregister (rtx); 153static struct machine_function* mep_init_machine_status (void); 154static rtx mep_tp_rtx (void); 155static rtx mep_gp_rtx (void); 156static bool mep_interrupt_p (void); 157static bool mep_disinterrupt_p (void); 158static bool mep_reg_set_p (rtx, rtx); 159static bool mep_reg_set_in_function (int); 160static bool mep_interrupt_saved_reg (int); 161static bool mep_call_saves_register (int); 162static rtx F (rtx); 163static void add_constant (int, int, int, int); 164static rtx maybe_dead_move (rtx, rtx, bool); 165static void mep_reload_pointer (int, const char *); 166static void mep_start_function (FILE *, HOST_WIDE_INT); 167static bool mep_function_ok_for_sibcall (tree, tree); 168static int unique_bit_in (HOST_WIDE_INT); 169static int bit_size_for_clip (HOST_WIDE_INT); 170static int bytesize (const_tree, enum machine_mode); 171static tree mep_validate_based_tiny (tree *, tree, tree, int, bool *); 172static tree mep_validate_near_far (tree *, tree, tree, int, bool *); 173static tree mep_validate_disinterrupt (tree *, tree, tree, int, bool *); 174static tree mep_validate_interrupt (tree *, tree, tree, int, bool *); 175static tree mep_validate_io_cb (tree *, tree, tree, int, bool *); 176static tree mep_validate_vliw (tree *, tree, tree, int, bool *); 177static bool mep_function_attribute_inlinable_p (const_tree); 178static bool mep_can_inline_p (tree, tree); 179static bool mep_lookup_pragma_disinterrupt (const char *); 180static int mep_multiple_address_regions (tree, bool); 181static int mep_attrlist_to_encoding (tree, tree); 182static void mep_insert_attributes (tree, tree *); 183static void mep_encode_section_info (tree, rtx, int); 184static section * mep_select_section (tree, int, unsigned HOST_WIDE_INT); 185static void mep_unique_section (tree, int); 186static unsigned int mep_section_type_flags (tree, const char *, int); 187static void mep_asm_named_section (const char *, unsigned int, tree); 188static bool mep_mentioned_p (rtx, rtx, int); 189static void mep_reorg_regmove (rtx); 190static rtx mep_insert_repeat_label_last (rtx, rtx, bool, bool); 191static void mep_reorg_repeat (rtx); 192static bool mep_invertable_branch_p (rtx); 193static void mep_invert_branch (rtx, rtx); 194static void mep_reorg_erepeat (rtx); 195static void mep_jmp_return_reorg (rtx); 196static void mep_reorg_addcombine (rtx); 197static void mep_reorg (void); 198static void mep_init_intrinsics (void); 199static void mep_init_builtins (void); 200static void mep_intrinsic_unavailable (int); 201static bool mep_get_intrinsic_insn (int, const struct cgen_insn **); 202static bool mep_get_move_insn (int, const struct cgen_insn **); 203static rtx mep_convert_arg (enum machine_mode, rtx); 204static rtx mep_convert_regnum (const struct cgen_regnum_operand *, rtx); 205static rtx mep_legitimize_arg (const struct insn_operand_data *, rtx, int); 206static void mep_incompatible_arg (const struct insn_operand_data *, rtx, int, tree); 207static rtx mep_expand_builtin (tree, rtx, rtx, enum machine_mode, int); 208static int mep_adjust_cost (rtx, rtx, rtx, int); 209static int mep_issue_rate (void); 210static rtx mep_find_ready_insn (rtx *, int, enum attr_slot, int); 211static void mep_move_ready_insn (rtx *, int, rtx); 212static int mep_sched_reorder (FILE *, int, rtx *, int *, int); 213static rtx mep_make_bundle (rtx, rtx); 214static void mep_bundle_insns (rtx); 215static bool mep_rtx_cost (rtx, int, int, int *, bool); 216static int mep_address_cost (rtx, bool); 217static void mep_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, 218 tree, int *, int); 219static bool mep_pass_by_reference (CUMULATIVE_ARGS * cum, enum machine_mode, 220 const_tree, bool); 221static bool mep_vector_mode_supported_p (enum machine_mode); 222static bool mep_handle_option (size_t, const char *, int); 223static rtx mep_allocate_initial_value (rtx); 224static void mep_asm_init_sections (void); 225static int mep_comp_type_attributes (const_tree, const_tree); 226static bool mep_narrow_volatile_bitfield (void); 227static rtx mep_expand_builtin_saveregs (void); 228static tree mep_build_builtin_va_list (void); 229static void mep_expand_va_start (tree, rtx); 230static tree mep_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *); 231static bool mep_can_eliminate (const int, const int); 232static void mep_trampoline_init (rtx, tree, rtx); 233 234/* Initialize the GCC target structure. */ 235 236#undef TARGET_ASM_FUNCTION_PROLOGUE 237#define TARGET_ASM_FUNCTION_PROLOGUE mep_start_function 238#undef TARGET_ATTRIBUTE_TABLE 239#define TARGET_ATTRIBUTE_TABLE mep_attribute_table 240#undef TARGET_COMP_TYPE_ATTRIBUTES 241#define TARGET_COMP_TYPE_ATTRIBUTES mep_comp_type_attributes 242#undef TARGET_INSERT_ATTRIBUTES 243#define TARGET_INSERT_ATTRIBUTES mep_insert_attributes 244#undef TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P 245#define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P mep_function_attribute_inlinable_p 246#undef TARGET_CAN_INLINE_P 247#define TARGET_CAN_INLINE_P mep_can_inline_p 248#undef TARGET_SECTION_TYPE_FLAGS 249#define TARGET_SECTION_TYPE_FLAGS mep_section_type_flags 250#undef TARGET_ASM_NAMED_SECTION 251#define TARGET_ASM_NAMED_SECTION mep_asm_named_section 252#undef TARGET_INIT_BUILTINS 253#define TARGET_INIT_BUILTINS mep_init_builtins 254#undef TARGET_EXPAND_BUILTIN 255#define TARGET_EXPAND_BUILTIN mep_expand_builtin 256#undef TARGET_SCHED_ADJUST_COST 257#define TARGET_SCHED_ADJUST_COST mep_adjust_cost 258#undef TARGET_SCHED_ISSUE_RATE 259#define TARGET_SCHED_ISSUE_RATE mep_issue_rate 260#undef TARGET_SCHED_REORDER 261#define TARGET_SCHED_REORDER mep_sched_reorder 262#undef TARGET_STRIP_NAME_ENCODING 263#define TARGET_STRIP_NAME_ENCODING mep_strip_name_encoding 264#undef TARGET_ASM_SELECT_SECTION 265#define TARGET_ASM_SELECT_SECTION mep_select_section 266#undef TARGET_ASM_UNIQUE_SECTION 267#define TARGET_ASM_UNIQUE_SECTION mep_unique_section 268#undef TARGET_ENCODE_SECTION_INFO 269#define TARGET_ENCODE_SECTION_INFO mep_encode_section_info 270#undef TARGET_FUNCTION_OK_FOR_SIBCALL 271#define TARGET_FUNCTION_OK_FOR_SIBCALL mep_function_ok_for_sibcall 272#undef TARGET_RTX_COSTS 273#define TARGET_RTX_COSTS mep_rtx_cost 274#undef TARGET_ADDRESS_COST 275#define TARGET_ADDRESS_COST mep_address_cost 276#undef TARGET_MACHINE_DEPENDENT_REORG 277#define TARGET_MACHINE_DEPENDENT_REORG mep_reorg 278#undef TARGET_SETUP_INCOMING_VARARGS 279#define TARGET_SETUP_INCOMING_VARARGS mep_setup_incoming_varargs 280#undef TARGET_PASS_BY_REFERENCE 281#define TARGET_PASS_BY_REFERENCE mep_pass_by_reference 282#undef TARGET_VECTOR_MODE_SUPPORTED_P 283#define TARGET_VECTOR_MODE_SUPPORTED_P mep_vector_mode_supported_p 284#undef TARGET_HANDLE_OPTION 285#define TARGET_HANDLE_OPTION mep_handle_option 286#undef TARGET_DEFAULT_TARGET_FLAGS 287#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT 288#undef TARGET_ALLOCATE_INITIAL_VALUE 289#define TARGET_ALLOCATE_INITIAL_VALUE mep_allocate_initial_value 290#undef TARGET_ASM_INIT_SECTIONS 291#define TARGET_ASM_INIT_SECTIONS mep_asm_init_sections 292#undef TARGET_RETURN_IN_MEMORY 293#define TARGET_RETURN_IN_MEMORY mep_return_in_memory 294#undef TARGET_NARROW_VOLATILE_BITFIELD 295#define TARGET_NARROW_VOLATILE_BITFIELD mep_narrow_volatile_bitfield 296#undef TARGET_EXPAND_BUILTIN_SAVEREGS 297#define TARGET_EXPAND_BUILTIN_SAVEREGS mep_expand_builtin_saveregs 298#undef TARGET_BUILD_BUILTIN_VA_LIST 299#define TARGET_BUILD_BUILTIN_VA_LIST mep_build_builtin_va_list 300#undef TARGET_EXPAND_BUILTIN_VA_START 301#define TARGET_EXPAND_BUILTIN_VA_START mep_expand_va_start 302#undef TARGET_GIMPLIFY_VA_ARG_EXPR 303#define TARGET_GIMPLIFY_VA_ARG_EXPR mep_gimplify_va_arg_expr 304#undef TARGET_CAN_ELIMINATE 305#define TARGET_CAN_ELIMINATE mep_can_eliminate 306#undef TARGET_TRAMPOLINE_INIT 307#define TARGET_TRAMPOLINE_INIT mep_trampoline_init 308 309struct gcc_target targetm = TARGET_INITIALIZER; 310 311#define WANT_GCC_DEFINITIONS 312#include "mep-intrin.h" 313#undef WANT_GCC_DEFINITIONS 314 315 316/* Command Line Option Support. */ 317 318char mep_leaf_registers [FIRST_PSEUDO_REGISTER]; 319 320/* True if we can use cmov instructions to move values back and forth 321 between core and coprocessor registers. */ 322bool mep_have_core_copro_moves_p; 323 324/* True if we can use cmov instructions (or a work-alike) to move 325 values between coprocessor registers. */ 326bool mep_have_copro_copro_moves_p; 327 328/* A table of all coprocessor instructions that can act like 329 a coprocessor-to-coprocessor cmov. */ 330static const int mep_cmov_insns[] = { 331 mep_cmov, 332 mep_cpmov, 333 mep_fmovs, 334 mep_caddi3, 335 mep_csubi3, 336 mep_candi3, 337 mep_cori3, 338 mep_cxori3, 339 mep_cand3, 340 mep_cor3 341}; 342 343static int option_mtiny_specified = 0; 344 345 346static void 347mep_set_leaf_registers (int enable) 348{ 349 int i; 350 351 if (mep_leaf_registers[0] != enable) 352 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 353 mep_leaf_registers[i] = enable; 354} 355 356void 357mep_conditional_register_usage (char *fixed_regs, char *call_used_regs) 358{ 359 int i; 360 361 if (!TARGET_OPT_MULT && !TARGET_OPT_DIV) 362 { 363 fixed_regs[HI_REGNO] = 1; 364 fixed_regs[LO_REGNO] = 1; 365 call_used_regs[HI_REGNO] = 1; 366 call_used_regs[LO_REGNO] = 1; 367 } 368 369 for (i = FIRST_SHADOW_REGISTER; i <= LAST_SHADOW_REGISTER; i++) 370 global_regs[i] = 1; 371} 372 373void 374mep_optimization_options (void) 375{ 376 /* The first scheduling pass often increases register pressure and tends 377 to result in more spill code. Only run it when specifically asked. */ 378 flag_schedule_insns = 0; 379 380 /* Using $fp doesn't gain us much, even when debugging is important. */ 381 flag_omit_frame_pointer = 1; 382} 383 384void 385mep_override_options (void) 386{ 387 if (flag_pic == 1) 388 warning (OPT_fpic, "-fpic is not supported"); 389 if (flag_pic == 2) 390 warning (OPT_fPIC, "-fPIC is not supported"); 391 if (TARGET_S && TARGET_M) 392 error ("only one of -ms and -mm may be given"); 393 if (TARGET_S && TARGET_L) 394 error ("only one of -ms and -ml may be given"); 395 if (TARGET_M && TARGET_L) 396 error ("only one of -mm and -ml may be given"); 397 if (TARGET_S && option_mtiny_specified) 398 error ("only one of -ms and -mtiny= may be given"); 399 if (TARGET_M && option_mtiny_specified) 400 error ("only one of -mm and -mtiny= may be given"); 401 if (TARGET_OPT_CLIP && ! TARGET_OPT_MINMAX) 402 warning (0, "-mclip currently has no effect without -mminmax"); 403 404 if (mep_const_section) 405 { 406 if (strcmp (mep_const_section, "tiny") != 0 407 && strcmp (mep_const_section, "near") != 0 408 && strcmp (mep_const_section, "far") != 0) 409 error ("-mc= must be -mc=tiny, -mc=near, or -mc=far"); 410 } 411 412 if (TARGET_S) 413 mep_tiny_cutoff = 65536; 414 if (TARGET_M) 415 mep_tiny_cutoff = 0; 416 if (TARGET_L && ! option_mtiny_specified) 417 mep_tiny_cutoff = 0; 418 419 if (TARGET_64BIT_CR_REGS) 420 flag_split_wide_types = 0; 421 422 init_machine_status = mep_init_machine_status; 423 mep_init_intrinsics (); 424} 425 426/* Pattern Support - constraints, predicates, expanders. */ 427 428/* MEP has very few instructions that can refer to the span of 429 addresses used by symbols, so it's common to check for them. */ 430 431static bool 432symbol_p (rtx x) 433{ 434 int c = GET_CODE (x); 435 436 return (c == CONST_INT 437 || c == CONST 438 || c == SYMBOL_REF); 439} 440 441static bool 442symbolref_p (rtx x) 443{ 444 int c; 445 446 if (GET_CODE (x) != MEM) 447 return false; 448 449 c = GET_CODE (XEXP (x, 0)); 450 return (c == CONST_INT 451 || c == CONST 452 || c == SYMBOL_REF); 453} 454 455/* static const char *reg_class_names[] = REG_CLASS_NAMES; */ 456 457#define GEN_REG(R, STRICT) \ 458 (GR_REGNO_P (R) \ 459 || (!STRICT \ 460 && ((R) == ARG_POINTER_REGNUM \ 461 || (R) >= FIRST_PSEUDO_REGISTER))) 462 463static char pattern[12], *patternp; 464static GTY(()) rtx patternr[12]; 465#define RTX_IS(x) (strcmp (pattern, x) == 0) 466 467static void 468encode_pattern_1 (rtx x) 469{ 470 int i; 471 472 if (patternp == pattern + sizeof (pattern) - 2) 473 { 474 patternp[-1] = '?'; 475 return; 476 } 477 478 patternr[patternp-pattern] = x; 479 480 switch (GET_CODE (x)) 481 { 482 case REG: 483 *patternp++ = 'r'; 484 break; 485 case MEM: 486 *patternp++ = 'm'; 487 case CONST: 488 encode_pattern_1 (XEXP(x, 0)); 489 break; 490 case PLUS: 491 *patternp++ = '+'; 492 encode_pattern_1 (XEXP(x, 0)); 493 encode_pattern_1 (XEXP(x, 1)); 494 break; 495 case LO_SUM: 496 *patternp++ = 'L'; 497 encode_pattern_1 (XEXP(x, 0)); 498 encode_pattern_1 (XEXP(x, 1)); 499 break; 500 case HIGH: 501 *patternp++ = 'H'; 502 encode_pattern_1 (XEXP(x, 0)); 503 break; 504 case SYMBOL_REF: 505 *patternp++ = 's'; 506 break; 507 case LABEL_REF: 508 *patternp++ = 'l'; 509 break; 510 case CONST_INT: 511 case CONST_DOUBLE: 512 *patternp++ = 'i'; 513 break; 514 case UNSPEC: 515 *patternp++ = 'u'; 516 *patternp++ = '0' + XCINT(x, 1, UNSPEC); 517 for (i=0; i<XVECLEN (x, 0); i++) 518 encode_pattern_1 (XVECEXP (x, 0, i)); 519 break; 520 case USE: 521 *patternp++ = 'U'; 522 break; 523 default: 524 *patternp++ = '?'; 525#if 0 526 fprintf (stderr, "can't encode pattern %s\n", GET_RTX_NAME(GET_CODE(x))); 527 debug_rtx (x); 528 gcc_unreachable (); 529#endif 530 break; 531 } 532} 533 534static void 535encode_pattern (rtx x) 536{ 537 patternp = pattern; 538 encode_pattern_1 (x); 539 *patternp = 0; 540} 541 542int 543mep_section_tag (rtx x) 544{ 545 const char *name; 546 547 while (1) 548 { 549 switch (GET_CODE (x)) 550 { 551 case MEM: 552 case CONST: 553 x = XEXP (x, 0); 554 break; 555 case UNSPEC: 556 x = XVECEXP (x, 0, 0); 557 break; 558 case PLUS: 559 if (GET_CODE (XEXP (x, 1)) != CONST_INT) 560 return 0; 561 x = XEXP (x, 0); 562 break; 563 default: 564 goto done; 565 } 566 } 567 done: 568 if (GET_CODE (x) != SYMBOL_REF) 569 return 0; 570 name = XSTR (x, 0); 571 if (name[0] == '@' && name[2] == '.') 572 { 573 if (name[1] == 'i' || name[1] == 'I') 574 { 575 if (name[1] == 'I') 576 return 'f'; /* near */ 577 return 'n'; /* far */ 578 } 579 return name[1]; 580 } 581 return 0; 582} 583 584int 585mep_regno_reg_class (int regno) 586{ 587 switch (regno) 588 { 589 case SP_REGNO: return SP_REGS; 590 case TP_REGNO: return TP_REGS; 591 case GP_REGNO: return GP_REGS; 592 case 0: return R0_REGS; 593 case HI_REGNO: return HI_REGS; 594 case LO_REGNO: return LO_REGS; 595 case ARG_POINTER_REGNUM: return GENERAL_REGS; 596 } 597 598 if (GR_REGNO_P (regno)) 599 return regno < FIRST_GR_REGNO + 8 ? TPREL_REGS : GENERAL_REGS; 600 if (CONTROL_REGNO_P (regno)) 601 return CONTROL_REGS; 602 603 if (CR_REGNO_P (regno)) 604 { 605 int i, j; 606 607 /* Search for the register amongst user-defined subclasses of 608 the coprocessor registers. */ 609 for (i = USER0_REGS; i <= USER3_REGS; ++i) 610 { 611 if (! TEST_HARD_REG_BIT (reg_class_contents[i], regno)) 612 continue; 613 for (j = 0; j < N_REG_CLASSES; ++j) 614 { 615 enum reg_class sub = reg_class_subclasses[i][j]; 616 617 if (sub == LIM_REG_CLASSES) 618 return i; 619 if (TEST_HARD_REG_BIT (reg_class_contents[sub], regno)) 620 break; 621 } 622 } 623 624 return LOADABLE_CR_REGNO_P (regno) ? LOADABLE_CR_REGS : CR_REGS; 625 } 626 627 if (CCR_REGNO_P (regno)) 628 return CCR_REGS; 629 630 gcc_assert (regno >= FIRST_SHADOW_REGISTER && regno <= LAST_SHADOW_REGISTER); 631 return NO_REGS; 632} 633 634#if 0 635int 636mep_reg_class_from_constraint (int c, const char *str) 637{ 638 switch (c) 639 { 640 case 'a': 641 return SP_REGS; 642 case 'b': 643 return TP_REGS; 644 case 'c': 645 return CONTROL_REGS; 646 case 'd': 647 return HILO_REGS; 648 case 'e': 649 { 650 switch (str[1]) 651 { 652 case 'm': 653 return LOADABLE_CR_REGS; 654 case 'x': 655 return mep_have_copro_copro_moves_p ? CR_REGS : NO_REGS; 656 case 'r': 657 return mep_have_core_copro_moves_p ? CR_REGS : NO_REGS; 658 default: 659 return NO_REGS; 660 } 661 } 662 case 'h': 663 return HI_REGS; 664 case 'j': 665 return RPC_REGS; 666 case 'l': 667 return LO_REGS; 668 case 't': 669 return TPREL_REGS; 670 case 'v': 671 return GP_REGS; 672 case 'x': 673 return CR_REGS; 674 case 'y': 675 return CCR_REGS; 676 case 'z': 677 return R0_REGS; 678 679 case 'A': 680 case 'B': 681 case 'C': 682 case 'D': 683 { 684 enum reg_class which = c - 'A' + USER0_REGS; 685 return (reg_class_size[which] > 0 ? which : NO_REGS); 686 } 687 688 default: 689 return NO_REGS; 690 } 691} 692 693bool 694mep_const_ok_for_letter_p (HOST_WIDE_INT value, int c) 695{ 696 switch (c) 697 { 698 case 'I': return value >= -32768 && value < 32768; 699 case 'J': return value >= 0 && value < 65536; 700 case 'K': return value >= 0 && value < 0x01000000; 701 case 'L': return value >= -32 && value < 32; 702 case 'M': return value >= 0 && value < 32; 703 case 'N': return value >= 0 && value < 16; 704 case 'O': 705 if (value & 0xffff) 706 return false; 707 return value >= -2147483647-1 && value <= 2147483647; 708 default: 709 gcc_unreachable (); 710 } 711} 712 713bool 714mep_extra_constraint (rtx value, int c) 715{ 716 encode_pattern (value); 717 718 switch (c) 719 { 720 case 'R': 721 /* For near symbols, like what call uses. */ 722 if (GET_CODE (value) == REG) 723 return 0; 724 return mep_call_address_operand (value, GET_MODE (value)); 725 726 case 'S': 727 /* For signed 8-bit immediates. */ 728 return (GET_CODE (value) == CONST_INT 729 && INTVAL (value) >= -128 730 && INTVAL (value) <= 127); 731 732 case 'T': 733 /* For tp/gp relative symbol values. */ 734 return (RTX_IS ("u3s") || RTX_IS ("u2s") 735 || RTX_IS ("+u3si") || RTX_IS ("+u2si")); 736 737 case 'U': 738 /* Non-absolute memories. */ 739 return GET_CODE (value) == MEM && ! CONSTANT_P (XEXP (value, 0)); 740 741 case 'W': 742 /* %hi(sym) */ 743 return RTX_IS ("Hs"); 744 745 case 'Y': 746 /* Register indirect. */ 747 return RTX_IS ("mr"); 748 749 case 'Z': 750 return mep_section_tag (value) == 'c' && RTX_IS ("ms"); 751 } 752 753 return false; 754} 755#endif 756 757#undef PASS 758#undef FAIL 759 760static bool 761const_in_range (rtx x, int minv, int maxv) 762{ 763 return (GET_CODE (x) == CONST_INT 764 && INTVAL (x) >= minv 765 && INTVAL (x) <= maxv); 766} 767 768/* Given three integer registers DEST, SRC1 and SRC2, return an rtx X 769 such that "mulr DEST,X" will calculate DEST = SRC1 * SRC2. If a move 770 is needed, emit it before INSN if INSN is nonnull, otherwise emit it 771 at the end of the insn stream. */ 772 773rtx 774mep_mulr_source (rtx insn, rtx dest, rtx src1, rtx src2) 775{ 776 if (rtx_equal_p (dest, src1)) 777 return src2; 778 else if (rtx_equal_p (dest, src2)) 779 return src1; 780 else 781 { 782 if (insn == 0) 783 emit_insn (gen_movsi (copy_rtx (dest), src1)); 784 else 785 emit_insn_before (gen_movsi (copy_rtx (dest), src1), insn); 786 return src2; 787 } 788} 789 790/* Replace INSN's pattern with PATTERN, a multiplication PARALLEL. 791 Change the last element of PATTERN from (clobber (scratch:SI)) 792 to (clobber (reg:SI HI_REGNO)). */ 793 794static void 795mep_rewrite_mult (rtx insn, rtx pattern) 796{ 797 rtx hi_clobber; 798 799 hi_clobber = XVECEXP (pattern, 0, XVECLEN (pattern, 0) - 1); 800 XEXP (hi_clobber, 0) = gen_rtx_REG (SImode, HI_REGNO); 801 PATTERN (insn) = pattern; 802 INSN_CODE (insn) = -1; 803} 804 805/* Subroutine of mep_reuse_lo_p. Rewrite instruction INSN so that it 806 calculates SRC1 * SRC2 and stores the result in $lo. Also make it 807 store the result in DEST if nonnull. */ 808 809static void 810mep_rewrite_mulsi3 (rtx insn, rtx dest, rtx src1, rtx src2) 811{ 812 rtx lo, pattern; 813 814 lo = gen_rtx_REG (SImode, LO_REGNO); 815 if (dest) 816 pattern = gen_mulsi3r (lo, dest, copy_rtx (dest), 817 mep_mulr_source (insn, dest, src1, src2)); 818 else 819 pattern = gen_mulsi3_lo (lo, src1, src2); 820 mep_rewrite_mult (insn, pattern); 821} 822 823/* Like mep_rewrite_mulsi3, but calculate SRC1 * SRC2 + SRC3. First copy 824 SRC3 into $lo, then use either madd or maddr. The move into $lo will 825 be deleted by a peephole2 if SRC3 is already in $lo. */ 826 827static void 828mep_rewrite_maddsi3 (rtx insn, rtx dest, rtx src1, rtx src2, rtx src3) 829{ 830 rtx lo, pattern; 831 832 lo = gen_rtx_REG (SImode, LO_REGNO); 833 emit_insn_before (gen_movsi (copy_rtx (lo), src3), insn); 834 if (dest) 835 pattern = gen_maddsi3r (lo, dest, copy_rtx (dest), 836 mep_mulr_source (insn, dest, src1, src2), 837 copy_rtx (lo)); 838 else 839 pattern = gen_maddsi3_lo (lo, src1, src2, copy_rtx (lo)); 840 mep_rewrite_mult (insn, pattern); 841} 842 843/* Return true if $lo has the same value as integer register GPR when 844 instruction INSN is reached. If necessary, rewrite the instruction 845 that sets $lo so that it uses a proper SET, not a CLOBBER. LO is an 846 rtx for (reg:SI LO_REGNO). 847 848 This function is intended to be used by the peephole2 pass. Since 849 that pass goes from the end of a basic block to the beginning, and 850 propagates liveness information on the way, there is no need to 851 update register notes here. 852 853 If GPR_DEAD_P is true on entry, and this function returns true, 854 then the caller will replace _every_ use of GPR in and after INSN 855 with LO. This means that if the instruction that sets $lo is a 856 mulr- or maddr-type instruction, we can rewrite it to use mul or 857 madd instead. In combination with the copy progagation pass, 858 this allows us to replace sequences like: 859 860 mov GPR,R1 861 mulr GPR,R2 862 863 with: 864 865 mul R1,R2 866 867 if GPR is no longer used. */ 868 869static bool 870mep_reuse_lo_p_1 (rtx lo, rtx gpr, rtx insn, bool gpr_dead_p) 871{ 872 do 873 { 874 insn = PREV_INSN (insn); 875 if (INSN_P (insn)) 876 switch (recog_memoized (insn)) 877 { 878 case CODE_FOR_mulsi3_1: 879 extract_insn (insn); 880 if (rtx_equal_p (recog_data.operand[0], gpr)) 881 { 882 mep_rewrite_mulsi3 (insn, 883 gpr_dead_p ? NULL : recog_data.operand[0], 884 recog_data.operand[1], 885 recog_data.operand[2]); 886 return true; 887 } 888 return false; 889 890 case CODE_FOR_maddsi3: 891 extract_insn (insn); 892 if (rtx_equal_p (recog_data.operand[0], gpr)) 893 { 894 mep_rewrite_maddsi3 (insn, 895 gpr_dead_p ? NULL : recog_data.operand[0], 896 recog_data.operand[1], 897 recog_data.operand[2], 898 recog_data.operand[3]); 899 return true; 900 } 901 return false; 902 903 case CODE_FOR_mulsi3r: 904 case CODE_FOR_maddsi3r: 905 extract_insn (insn); 906 return rtx_equal_p (recog_data.operand[1], gpr); 907 908 default: 909 if (reg_set_p (lo, insn) 910 || reg_set_p (gpr, insn) 911 || volatile_insn_p (PATTERN (insn))) 912 return false; 913 914 if (gpr_dead_p && reg_referenced_p (gpr, PATTERN (insn))) 915 gpr_dead_p = false; 916 break; 917 } 918 } 919 while (!NOTE_INSN_BASIC_BLOCK_P (insn)); 920 return false; 921} 922 923/* A wrapper around mep_reuse_lo_p_1 that preserves recog_data. */ 924 925bool 926mep_reuse_lo_p (rtx lo, rtx gpr, rtx insn, bool gpr_dead_p) 927{ 928 bool result = mep_reuse_lo_p_1 (lo, gpr, insn, gpr_dead_p); 929 extract_insn (insn); 930 return result; 931} 932 933/* Return true if SET can be turned into a post-modify load or store 934 that adds OFFSET to GPR. In other words, return true if SET can be 935 changed into: 936 937 (parallel [SET (set GPR (plus:SI GPR OFFSET))]). 938 939 It's OK to change SET to an equivalent operation in order to 940 make it match. */ 941 942static bool 943mep_use_post_modify_for_set_p (rtx set, rtx gpr, rtx offset) 944{ 945 rtx *reg, *mem; 946 unsigned int reg_bytes, mem_bytes; 947 enum machine_mode reg_mode, mem_mode; 948 949 /* Only simple SETs can be converted. */ 950 if (GET_CODE (set) != SET) 951 return false; 952 953 /* Point REG to what we hope will be the register side of the set and 954 MEM to what we hope will be the memory side. */ 955 if (GET_CODE (SET_DEST (set)) == MEM) 956 { 957 mem = &SET_DEST (set); 958 reg = &SET_SRC (set); 959 } 960 else 961 { 962 reg = &SET_DEST (set); 963 mem = &SET_SRC (set); 964 if (GET_CODE (*mem) == SIGN_EXTEND) 965 mem = &XEXP (*mem, 0); 966 } 967 968 /* Check that *REG is a suitable coprocessor register. */ 969 if (GET_CODE (*reg) != REG || !LOADABLE_CR_REGNO_P (REGNO (*reg))) 970 return false; 971 972 /* Check that *MEM is a suitable memory reference. */ 973 if (GET_CODE (*mem) != MEM || !rtx_equal_p (XEXP (*mem, 0), gpr)) 974 return false; 975 976 /* Get the number of bytes in each operand. */ 977 mem_bytes = GET_MODE_SIZE (GET_MODE (*mem)); 978 reg_bytes = GET_MODE_SIZE (GET_MODE (*reg)); 979 980 /* Check that OFFSET is suitably aligned. */ 981 if (INTVAL (offset) & (mem_bytes - 1)) 982 return false; 983 984 /* Convert *MEM to a normal integer mode. */ 985 mem_mode = mode_for_size (mem_bytes * BITS_PER_UNIT, MODE_INT, 0); 986 *mem = change_address (*mem, mem_mode, NULL); 987 988 /* Adjust *REG as well. */ 989 *reg = shallow_copy_rtx (*reg); 990 if (reg == &SET_DEST (set) && reg_bytes < UNITS_PER_WORD) 991 { 992 /* SET is a subword load. Convert it to an explicit extension. */ 993 PUT_MODE (*reg, SImode); 994 *mem = gen_rtx_SIGN_EXTEND (SImode, *mem); 995 } 996 else 997 { 998 reg_mode = mode_for_size (reg_bytes * BITS_PER_UNIT, MODE_INT, 0); 999 PUT_MODE (*reg, reg_mode); 1000 } 1001 return true; 1002} 1003 1004/* Return the effect of frame-related instruction INSN. */ 1005 1006static rtx 1007mep_frame_expr (rtx insn) 1008{ 1009 rtx note, expr; 1010 1011 note = find_reg_note (insn, REG_FRAME_RELATED_EXPR, 0); 1012 expr = (note != 0 ? XEXP (note, 0) : copy_rtx (PATTERN (insn))); 1013 RTX_FRAME_RELATED_P (expr) = 1; 1014 return expr; 1015} 1016 1017/* Merge instructions INSN1 and INSN2 using a PARALLEL. Store the 1018 new pattern in INSN1; INSN2 will be deleted by the caller. */ 1019 1020static void 1021mep_make_parallel (rtx insn1, rtx insn2) 1022{ 1023 rtx expr; 1024 1025 if (RTX_FRAME_RELATED_P (insn2)) 1026 { 1027 expr = mep_frame_expr (insn2); 1028 if (RTX_FRAME_RELATED_P (insn1)) 1029 expr = gen_rtx_SEQUENCE (VOIDmode, 1030 gen_rtvec (2, mep_frame_expr (insn1), expr)); 1031 set_unique_reg_note (insn1, REG_FRAME_RELATED_EXPR, expr); 1032 RTX_FRAME_RELATED_P (insn1) = 1; 1033 } 1034 1035 PATTERN (insn1) = gen_rtx_PARALLEL (VOIDmode, 1036 gen_rtvec (2, PATTERN (insn1), 1037 PATTERN (insn2))); 1038 INSN_CODE (insn1) = -1; 1039} 1040 1041/* SET_INSN is an instruction that adds OFFSET to REG. Go back through 1042 the basic block to see if any previous load or store instruction can 1043 be persuaded to do SET_INSN as a side-effect. Return true if so. */ 1044 1045static bool 1046mep_use_post_modify_p_1 (rtx set_insn, rtx reg, rtx offset) 1047{ 1048 rtx insn; 1049 1050 insn = set_insn; 1051 do 1052 { 1053 insn = PREV_INSN (insn); 1054 if (INSN_P (insn)) 1055 { 1056 if (mep_use_post_modify_for_set_p (PATTERN (insn), reg, offset)) 1057 { 1058 mep_make_parallel (insn, set_insn); 1059 return true; 1060 } 1061 1062 if (reg_set_p (reg, insn) 1063 || reg_referenced_p (reg, PATTERN (insn)) 1064 || volatile_insn_p (PATTERN (insn))) 1065 return false; 1066 } 1067 } 1068 while (!NOTE_INSN_BASIC_BLOCK_P (insn)); 1069 return false; 1070} 1071 1072/* A wrapper around mep_use_post_modify_p_1 that preserves recog_data. */ 1073 1074bool 1075mep_use_post_modify_p (rtx insn, rtx reg, rtx offset) 1076{ 1077 bool result = mep_use_post_modify_p_1 (insn, reg, offset); 1078 extract_insn (insn); 1079 return result; 1080} 1081 1082bool 1083mep_allow_clip (rtx ux, rtx lx, int s) 1084{ 1085 HOST_WIDE_INT u = INTVAL (ux); 1086 HOST_WIDE_INT l = INTVAL (lx); 1087 int i; 1088 1089 if (!TARGET_OPT_CLIP) 1090 return false; 1091 1092 if (s) 1093 { 1094 for (i = 0; i < 30; i ++) 1095 if ((u == ((HOST_WIDE_INT) 1 << i) - 1) 1096 && (l == - ((HOST_WIDE_INT) 1 << i))) 1097 return true; 1098 } 1099 else 1100 { 1101 if (l != 0) 1102 return false; 1103 1104 for (i = 0; i < 30; i ++) 1105 if ((u == ((HOST_WIDE_INT) 1 << i) - 1)) 1106 return true; 1107 } 1108 return false; 1109} 1110 1111bool 1112mep_bit_position_p (rtx x, bool looking_for) 1113{ 1114 if (GET_CODE (x) != CONST_INT) 1115 return false; 1116 switch ((int) INTVAL(x) & 0xff) 1117 { 1118 case 0x01: case 0x02: case 0x04: case 0x08: 1119 case 0x10: case 0x20: case 0x40: case 0x80: 1120 return looking_for; 1121 case 0xfe: case 0xfd: case 0xfb: case 0xf7: 1122 case 0xef: case 0xdf: case 0xbf: case 0x7f: 1123 return !looking_for; 1124 } 1125 return false; 1126} 1127 1128static bool 1129move_needs_splitting (rtx dest, rtx src, 1130 enum machine_mode mode ATTRIBUTE_UNUSED) 1131{ 1132 int s = mep_section_tag (src); 1133 1134 while (1) 1135 { 1136 if (GET_CODE (src) == CONST 1137 || GET_CODE (src) == MEM) 1138 src = XEXP (src, 0); 1139 else if (GET_CODE (src) == SYMBOL_REF 1140 || GET_CODE (src) == LABEL_REF 1141 || GET_CODE (src) == PLUS) 1142 break; 1143 else 1144 return false; 1145 } 1146 if (s == 'f' 1147 || (GET_CODE (src) == PLUS 1148 && GET_CODE (XEXP (src, 1)) == CONST_INT 1149 && (INTVAL (XEXP (src, 1)) < -65536 1150 || INTVAL (XEXP (src, 1)) > 0xffffff)) 1151 || (GET_CODE (dest) == REG 1152 && REGNO (dest) > 7 && REGNO (dest) < FIRST_PSEUDO_REGISTER)) 1153 return true; 1154 return false; 1155} 1156 1157bool 1158mep_split_mov (rtx *operands, int symbolic) 1159{ 1160 if (symbolic) 1161 { 1162 if (move_needs_splitting (operands[0], operands[1], SImode)) 1163 return true; 1164 return false; 1165 } 1166 1167 if (GET_CODE (operands[1]) != CONST_INT) 1168 return false; 1169 1170 if (constraint_satisfied_p (operands[1], CONSTRAINT_I) 1171 || constraint_satisfied_p (operands[1], CONSTRAINT_J) 1172 || constraint_satisfied_p (operands[1], CONSTRAINT_O)) 1173 return false; 1174 1175 if (((!reload_completed && !reload_in_progress) 1176 || (REG_P (operands[0]) && REGNO (operands[0]) < 8)) 1177 && constraint_satisfied_p (operands[1], CONSTRAINT_K)) 1178 return false; 1179 1180 return true; 1181} 1182 1183/* Irritatingly, the "jsrv" insn *toggles* PSW.OM rather than set 1184 it to one specific value. So the insn chosen depends on whether 1185 the source and destination modes match. */ 1186 1187bool 1188mep_vliw_mode_match (rtx tgt) 1189{ 1190 bool src_vliw = mep_vliw_function_p (cfun->decl); 1191 bool tgt_vliw = INTVAL (tgt); 1192 1193 return src_vliw == tgt_vliw; 1194} 1195 1196/* Like the above, but also test for near/far mismatches. */ 1197 1198bool 1199mep_vliw_jmp_match (rtx tgt) 1200{ 1201 bool src_vliw = mep_vliw_function_p (cfun->decl); 1202 bool tgt_vliw = INTVAL (tgt); 1203 1204 if (mep_section_tag (DECL_RTL (cfun->decl)) == 'f') 1205 return false; 1206 1207 return src_vliw == tgt_vliw; 1208} 1209 1210bool 1211mep_multi_slot (rtx x) 1212{ 1213 return get_attr_slot (x) == SLOT_MULTI; 1214} 1215 1216 1217bool 1218mep_legitimate_constant_p (rtx x) 1219{ 1220 /* We can't convert symbol values to gp- or tp-rel values after 1221 reload, as reload might have used $gp or $tp for other 1222 purposes. */ 1223 if (GET_CODE (x) == SYMBOL_REF && (reload_in_progress || reload_completed)) 1224 { 1225 char e = mep_section_tag (x); 1226 return (e != 't' && e != 'b'); 1227 } 1228 return 1; 1229} 1230 1231/* Be careful not to use macros that need to be compiled one way for 1232 strict, and another way for not-strict, like REG_OK_FOR_BASE_P. */ 1233 1234bool 1235mep_legitimate_address (enum machine_mode mode, rtx x, int strict) 1236{ 1237 int the_tag; 1238 1239#define DEBUG_LEGIT 0 1240#if DEBUG_LEGIT 1241 fprintf (stderr, "legit: mode %s strict %d ", mode_name[mode], strict); 1242 debug_rtx (x); 1243#endif 1244 1245 if (GET_CODE (x) == LO_SUM 1246 && GET_CODE (XEXP (x, 0)) == REG 1247 && GEN_REG (REGNO (XEXP (x, 0)), strict) 1248 && CONSTANT_P (XEXP (x, 1))) 1249 { 1250 if (GET_MODE_SIZE (mode) > 4) 1251 { 1252 /* We will end up splitting this, and lo_sums are not 1253 offsettable for us. */ 1254#if DEBUG_LEGIT 1255 fprintf(stderr, " - nope, %%lo(sym)[reg] not splittable\n"); 1256#endif 1257 return false; 1258 } 1259#if DEBUG_LEGIT 1260 fprintf (stderr, " - yup, %%lo(sym)[reg]\n"); 1261#endif 1262 return true; 1263 } 1264 1265 if (GET_CODE (x) == REG 1266 && GEN_REG (REGNO (x), strict)) 1267 { 1268#if DEBUG_LEGIT 1269 fprintf (stderr, " - yup, [reg]\n"); 1270#endif 1271 return true; 1272 } 1273 1274 if (GET_CODE (x) == PLUS 1275 && GET_CODE (XEXP (x, 0)) == REG 1276 && GEN_REG (REGNO (XEXP (x, 0)), strict) 1277 && const_in_range (XEXP (x, 1), -32768, 32767)) 1278 { 1279#if DEBUG_LEGIT 1280 fprintf (stderr, " - yup, [reg+const]\n"); 1281#endif 1282 return true; 1283 } 1284 1285 if (GET_CODE (x) == PLUS 1286 && GET_CODE (XEXP (x, 0)) == REG 1287 && GEN_REG (REGNO (XEXP (x, 0)), strict) 1288 && GET_CODE (XEXP (x, 1)) == CONST 1289 && (GET_CODE (XEXP (XEXP (x, 1), 0)) == UNSPEC 1290 || (GET_CODE (XEXP (XEXP (x, 1), 0)) == PLUS 1291 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 0)) == UNSPEC 1292 && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == CONST_INT))) 1293 { 1294#if DEBUG_LEGIT 1295 fprintf (stderr, " - yup, [reg+unspec]\n"); 1296#endif 1297 return true; 1298 } 1299 1300 the_tag = mep_section_tag (x); 1301 1302 if (the_tag == 'f') 1303 { 1304#if DEBUG_LEGIT 1305 fprintf (stderr, " - nope, [far]\n"); 1306#endif 1307 return false; 1308 } 1309 1310 if (mode == VOIDmode 1311 && GET_CODE (x) == SYMBOL_REF) 1312 { 1313#if DEBUG_LEGIT 1314 fprintf (stderr, " - yup, call [symbol]\n"); 1315#endif 1316 return true; 1317 } 1318 1319 if ((mode == SImode || mode == SFmode) 1320 && CONSTANT_P (x) 1321 && LEGITIMATE_CONSTANT_P (x) 1322 && the_tag != 't' && the_tag != 'b') 1323 { 1324 if (GET_CODE (x) != CONST_INT 1325 || (INTVAL (x) <= 0xfffff 1326 && INTVAL (x) >= 0 1327 && (INTVAL (x) % 4) == 0)) 1328 { 1329#if DEBUG_LEGIT 1330 fprintf (stderr, " - yup, [const]\n"); 1331#endif 1332 return true; 1333 } 1334 } 1335 1336#if DEBUG_LEGIT 1337 fprintf (stderr, " - nope.\n"); 1338#endif 1339 return false; 1340} 1341 1342int 1343mep_legitimize_reload_address (rtx *x, enum machine_mode mode, int opnum, 1344 enum reload_type type, 1345 int ind_levels ATTRIBUTE_UNUSED) 1346{ 1347 if (GET_CODE (*x) == PLUS 1348 && GET_CODE (XEXP (*x, 0)) == MEM 1349 && GET_CODE (XEXP (*x, 1)) == REG) 1350 { 1351 /* GCC will by default copy the MEM into a REG, which results in 1352 an invalid address. For us, the best thing to do is move the 1353 whole expression to a REG. */ 1354 push_reload (*x, NULL_RTX, x, NULL, 1355 GENERAL_REGS, mode, VOIDmode, 1356 0, 0, opnum, type); 1357 return 1; 1358 } 1359 1360 if (GET_CODE (*x) == PLUS 1361 && GET_CODE (XEXP (*x, 0)) == SYMBOL_REF 1362 && GET_CODE (XEXP (*x, 1)) == CONST_INT) 1363 { 1364 char e = mep_section_tag (XEXP (*x, 0)); 1365 1366 if (e != 't' && e != 'b') 1367 { 1368 /* GCC thinks that (sym+const) is a valid address. Well, 1369 sometimes it is, this time it isn't. The best thing to 1370 do is reload the symbol to a register, since reg+int 1371 tends to work, and we can't just add the symbol and 1372 constant anyway. */ 1373 push_reload (XEXP (*x, 0), NULL_RTX, &(XEXP(*x, 0)), NULL, 1374 GENERAL_REGS, mode, VOIDmode, 1375 0, 0, opnum, type); 1376 return 1; 1377 } 1378 } 1379 return 0; 1380} 1381 1382int 1383mep_core_address_length (rtx insn, int opn) 1384{ 1385 rtx set = single_set (insn); 1386 rtx mem = XEXP (set, opn); 1387 rtx other = XEXP (set, 1-opn); 1388 rtx addr = XEXP (mem, 0); 1389 1390 if (register_operand (addr, Pmode)) 1391 return 2; 1392 if (GET_CODE (addr) == PLUS) 1393 { 1394 rtx addend = XEXP (addr, 1); 1395 1396 gcc_assert (REG_P (XEXP (addr, 0))); 1397 1398 switch (REGNO (XEXP (addr, 0))) 1399 { 1400 case STACK_POINTER_REGNUM: 1401 if (GET_MODE_SIZE (GET_MODE (mem)) == 4 1402 && mep_imm7a4_operand (addend, VOIDmode)) 1403 return 2; 1404 break; 1405 1406 case 13: /* TP */ 1407 gcc_assert (REG_P (other)); 1408 1409 if (REGNO (other) >= 8) 1410 break; 1411 1412 if (GET_CODE (addend) == CONST 1413 && GET_CODE (XEXP (addend, 0)) == UNSPEC 1414 && XINT (XEXP (addend, 0), 1) == UNS_TPREL) 1415 return 2; 1416 1417 if (GET_CODE (addend) == CONST_INT 1418 && INTVAL (addend) >= 0 1419 && INTVAL (addend) <= 127 1420 && INTVAL (addend) % GET_MODE_SIZE (GET_MODE (mem)) == 0) 1421 return 2; 1422 break; 1423 } 1424 } 1425 1426 return 4; 1427} 1428 1429int 1430mep_cop_address_length (rtx insn, int opn) 1431{ 1432 rtx set = single_set (insn); 1433 rtx mem = XEXP (set, opn); 1434 rtx addr = XEXP (mem, 0); 1435 1436 if (GET_CODE (mem) != MEM) 1437 return 2; 1438 if (register_operand (addr, Pmode)) 1439 return 2; 1440 if (GET_CODE (addr) == POST_INC) 1441 return 2; 1442 1443 return 4; 1444} 1445 1446#define DEBUG_EXPAND_MOV 0 1447bool 1448mep_expand_mov (rtx *operands, enum machine_mode mode) 1449{ 1450 int i, t; 1451 int tag[2]; 1452 rtx tpsym, tpoffs; 1453 int post_reload = 0; 1454 1455 tag[0] = mep_section_tag (operands[0]); 1456 tag[1] = mep_section_tag (operands[1]); 1457 1458 if (!reload_in_progress 1459 && !reload_completed 1460 && GET_CODE (operands[0]) != REG 1461 && GET_CODE (operands[0]) != SUBREG 1462 && GET_CODE (operands[1]) != REG 1463 && GET_CODE (operands[1]) != SUBREG) 1464 operands[1] = copy_to_mode_reg (mode, operands[1]); 1465 1466#if DEBUG_EXPAND_MOV 1467 fprintf(stderr, "expand move %s %d\n", mode_name[mode], 1468 reload_in_progress || reload_completed); 1469 debug_rtx (operands[0]); 1470 debug_rtx (operands[1]); 1471#endif 1472 1473 if (mode == DImode || mode == DFmode) 1474 return false; 1475 1476 if (reload_in_progress || reload_completed) 1477 { 1478 rtx r; 1479 1480 if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == TP_REGNO) 1481 cfun->machine->reload_changes_tp = true; 1482 1483 if (tag[0] == 't' || tag[1] == 't') 1484 { 1485 r = has_hard_reg_initial_val (Pmode, GP_REGNO); 1486 if (!r || GET_CODE (r) != REG || REGNO (r) != GP_REGNO) 1487 post_reload = 1; 1488 } 1489 if (tag[0] == 'b' || tag[1] == 'b') 1490 { 1491 r = has_hard_reg_initial_val (Pmode, TP_REGNO); 1492 if (!r || GET_CODE (r) != REG || REGNO (r) != TP_REGNO) 1493 post_reload = 1; 1494 } 1495 if (cfun->machine->reload_changes_tp == true) 1496 post_reload = 1; 1497 } 1498 1499 if (!post_reload) 1500 { 1501 rtx n; 1502 if (symbol_p (operands[1])) 1503 { 1504 t = mep_section_tag (operands[1]); 1505 if (t == 'b' || t == 't') 1506 { 1507 1508 if (GET_CODE (operands[1]) == SYMBOL_REF) 1509 { 1510 tpsym = operands[1]; 1511 n = gen_rtx_UNSPEC (mode, 1512 gen_rtvec (1, operands[1]), 1513 t == 'b' ? UNS_TPREL : UNS_GPREL); 1514 n = gen_rtx_CONST (mode, n); 1515 } 1516 else if (GET_CODE (operands[1]) == CONST 1517 && GET_CODE (XEXP (operands[1], 0)) == PLUS 1518 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF 1519 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT) 1520 { 1521 tpsym = XEXP (XEXP (operands[1], 0), 0); 1522 tpoffs = XEXP (XEXP (operands[1], 0), 1); 1523 n = gen_rtx_UNSPEC (mode, 1524 gen_rtvec (1, tpsym), 1525 t == 'b' ? UNS_TPREL : UNS_GPREL); 1526 n = gen_rtx_PLUS (mode, n, tpoffs); 1527 n = gen_rtx_CONST (mode, n); 1528 } 1529 else if (GET_CODE (operands[1]) == CONST 1530 && GET_CODE (XEXP (operands[1], 0)) == UNSPEC) 1531 return false; 1532 else 1533 { 1534 error ("unusual TP-relative address"); 1535 return false; 1536 } 1537 1538 n = gen_rtx_PLUS (mode, (t == 'b' ? mep_tp_rtx () 1539 : mep_gp_rtx ()), n); 1540 n = emit_insn (gen_rtx_SET (mode, operands[0], n)); 1541#if DEBUG_EXPAND_MOV 1542 fprintf(stderr, "mep_expand_mov emitting "); 1543 debug_rtx(n); 1544#endif 1545 return true; 1546 } 1547 } 1548 1549 for (i=0; i < 2; i++) 1550 { 1551 t = mep_section_tag (operands[i]); 1552 if (GET_CODE (operands[i]) == MEM && (t == 'b' || t == 't')) 1553 { 1554 rtx sym, n, r; 1555 int u; 1556 1557 sym = XEXP (operands[i], 0); 1558 if (GET_CODE (sym) == CONST 1559 && GET_CODE (XEXP (sym, 0)) == UNSPEC) 1560 sym = XVECEXP (XEXP (sym, 0), 0, 0); 1561 1562 if (t == 'b') 1563 { 1564 r = mep_tp_rtx (); 1565 u = UNS_TPREL; 1566 } 1567 else 1568 { 1569 r = mep_gp_rtx (); 1570 u = UNS_GPREL; 1571 } 1572 1573 n = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), u); 1574 n = gen_rtx_CONST (Pmode, n); 1575 n = gen_rtx_PLUS (Pmode, r, n); 1576 operands[i] = replace_equiv_address (operands[i], n); 1577 } 1578 } 1579 } 1580 1581 if ((GET_CODE (operands[1]) != REG 1582 && MEP_CONTROL_REG (operands[0])) 1583 || (GET_CODE (operands[0]) != REG 1584 && MEP_CONTROL_REG (operands[1]))) 1585 { 1586 rtx temp; 1587#if DEBUG_EXPAND_MOV 1588 fprintf (stderr, "cr-mem, forcing op1 to reg\n"); 1589#endif 1590 temp = gen_reg_rtx (mode); 1591 emit_move_insn (temp, operands[1]); 1592 operands[1] = temp; 1593 } 1594 1595 if (symbolref_p (operands[0]) 1596 && (mep_section_tag (XEXP (operands[0], 0)) == 'f' 1597 || (GET_MODE_SIZE (mode) != 4))) 1598 { 1599 rtx temp; 1600 1601 gcc_assert (!reload_in_progress && !reload_completed); 1602 1603 temp = force_reg (Pmode, XEXP (operands[0], 0)); 1604 operands[0] = replace_equiv_address (operands[0], temp); 1605 emit_move_insn (operands[0], operands[1]); 1606 return true; 1607 } 1608 1609 if (!post_reload && (tag[1] == 't' || tag[1] == 'b')) 1610 tag[1] = 0; 1611 1612 if (symbol_p (operands[1]) 1613 && (tag[1] == 'f' || tag[1] == 't' || tag[1] == 'b')) 1614 { 1615 emit_insn (gen_movsi_topsym_s (operands[0], operands[1])); 1616 emit_insn (gen_movsi_botsym_s (operands[0], operands[0], operands[1])); 1617 return true; 1618 } 1619 1620 if (symbolref_p (operands[1]) 1621 && (tag[1] == 'f' || tag[1] == 't' || tag[1] == 'b')) 1622 { 1623 rtx temp; 1624 1625 if (reload_in_progress || reload_completed) 1626 temp = operands[0]; 1627 else 1628 temp = gen_reg_rtx (Pmode); 1629 1630 emit_insn (gen_movsi_topsym_s (temp, operands[1])); 1631 emit_insn (gen_movsi_botsym_s (temp, temp, operands[1])); 1632 emit_move_insn (operands[0], replace_equiv_address (operands[1], temp)); 1633 return true; 1634 } 1635 1636 return false; 1637} 1638 1639/* Cases where the pattern can't be made to use at all. */ 1640 1641bool 1642mep_mov_ok (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED) 1643{ 1644 int i; 1645 1646#define DEBUG_MOV_OK 0 1647#if DEBUG_MOV_OK 1648 fprintf (stderr, "mep_mov_ok %s %c=%c\n", mode_name[mode], mep_section_tag (operands[0]), 1649 mep_section_tag (operands[1])); 1650 debug_rtx (operands[0]); 1651 debug_rtx (operands[1]); 1652#endif 1653 1654 /* We want the movh patterns to get these. */ 1655 if (GET_CODE (operands[1]) == HIGH) 1656 return false; 1657 1658 /* We can't store a register to a far variable without using a 1659 scratch register to hold the address. Using far variables should 1660 be split by mep_emit_mov anyway. */ 1661 if (mep_section_tag (operands[0]) == 'f' 1662 || mep_section_tag (operands[1]) == 'f') 1663 { 1664#if DEBUG_MOV_OK 1665 fprintf (stderr, " - no, f\n"); 1666#endif 1667 return false; 1668 } 1669 i = mep_section_tag (operands[1]); 1670 if ((i == 'b' || i == 't') && !reload_completed && !reload_in_progress) 1671 /* These are supposed to be generated with adds of the appropriate 1672 register. During and after reload, however, we allow them to 1673 be accessed as normal symbols because adding a dependency on 1674 the base register now might cause problems. */ 1675 { 1676#if DEBUG_MOV_OK 1677 fprintf (stderr, " - no, bt\n"); 1678#endif 1679 return false; 1680 } 1681 1682 /* The only moves we can allow involve at least one general 1683 register, so require it. */ 1684 for (i = 0; i < 2; i ++) 1685 { 1686 /* Allow subregs too, before reload. */ 1687 rtx x = operands[i]; 1688 1689 if (GET_CODE (x) == SUBREG) 1690 x = XEXP (x, 0); 1691 if (GET_CODE (x) == REG 1692 && ! MEP_CONTROL_REG (x)) 1693 { 1694#if DEBUG_MOV_OK 1695 fprintf (stderr, " - ok\n"); 1696#endif 1697 return true; 1698 } 1699 } 1700#if DEBUG_MOV_OK 1701 fprintf (stderr, " - no, no gen reg\n"); 1702#endif 1703 return false; 1704} 1705 1706#define DEBUG_SPLIT_WIDE_MOVE 0 1707void 1708mep_split_wide_move (rtx *operands, enum machine_mode mode) 1709{ 1710 int i; 1711 1712#if DEBUG_SPLIT_WIDE_MOVE 1713 fprintf (stderr, "\n\033[34mmep_split_wide_move\033[0m mode %s\n", mode_name[mode]); 1714 debug_rtx (operands[0]); 1715 debug_rtx (operands[1]); 1716#endif 1717 1718 for (i = 0; i <= 1; i++) 1719 { 1720 rtx op = operands[i], hi, lo; 1721 1722 switch (GET_CODE (op)) 1723 { 1724 case REG: 1725 { 1726 unsigned int regno = REGNO (op); 1727 1728 if (TARGET_64BIT_CR_REGS && CR_REGNO_P (regno)) 1729 { 1730 rtx i32; 1731 1732 lo = gen_rtx_REG (SImode, regno); 1733 i32 = GEN_INT (32); 1734 hi = gen_rtx_ZERO_EXTRACT (SImode, 1735 gen_rtx_REG (DImode, regno), 1736 i32, i32); 1737 } 1738 else 1739 { 1740 hi = gen_rtx_REG (SImode, regno + TARGET_LITTLE_ENDIAN); 1741 lo = gen_rtx_REG (SImode, regno + TARGET_BIG_ENDIAN); 1742 } 1743 } 1744 break; 1745 1746 case CONST_INT: 1747 case CONST_DOUBLE: 1748 case MEM: 1749 hi = operand_subword (op, TARGET_LITTLE_ENDIAN, 0, mode); 1750 lo = operand_subword (op, TARGET_BIG_ENDIAN, 0, mode); 1751 break; 1752 1753 default: 1754 gcc_unreachable (); 1755 } 1756 1757 /* The high part of CR <- GPR moves must be done after the low part. */ 1758 operands [i + 4] = lo; 1759 operands [i + 2] = hi; 1760 } 1761 1762 if (reg_mentioned_p (operands[2], operands[5]) 1763 || GET_CODE (operands[2]) == ZERO_EXTRACT 1764 || GET_CODE (operands[4]) == ZERO_EXTRACT) 1765 { 1766 rtx tmp; 1767 1768 /* Overlapping register pairs -- make sure we don't 1769 early-clobber ourselves. */ 1770 tmp = operands[2]; 1771 operands[2] = operands[4]; 1772 operands[4] = tmp; 1773 tmp = operands[3]; 1774 operands[3] = operands[5]; 1775 operands[5] = tmp; 1776 } 1777 1778#if DEBUG_SPLIT_WIDE_MOVE 1779 fprintf(stderr, "\033[34m"); 1780 debug_rtx (operands[2]); 1781 debug_rtx (operands[3]); 1782 debug_rtx (operands[4]); 1783 debug_rtx (operands[5]); 1784 fprintf(stderr, "\033[0m"); 1785#endif 1786} 1787 1788/* Emit a setcc instruction in its entirity. */ 1789 1790static bool 1791mep_expand_setcc_1 (enum rtx_code code, rtx dest, rtx op1, rtx op2) 1792{ 1793 rtx tmp; 1794 1795 switch (code) 1796 { 1797 case GT: 1798 case GTU: 1799 tmp = op1, op1 = op2, op2 = tmp; 1800 code = swap_condition (code); 1801 /* FALLTHRU */ 1802 1803 case LT: 1804 case LTU: 1805 op1 = force_reg (SImode, op1); 1806 emit_insn (gen_rtx_SET (VOIDmode, dest, 1807 gen_rtx_fmt_ee (code, SImode, op1, op2))); 1808 return true; 1809 1810 case EQ: 1811 if (op2 != const0_rtx) 1812 op1 = expand_binop (SImode, sub_optab, op1, op2, NULL, 1, OPTAB_WIDEN); 1813 mep_expand_setcc_1 (LTU, dest, op1, const1_rtx); 1814 return true; 1815 1816 case NE: 1817 /* Branchful sequence: 1818 mov dest, 0 16-bit 1819 beq op1, op2, Lover 16-bit (op2 < 16), 32-bit otherwise 1820 mov dest, 1 16-bit 1821 1822 Branchless sequence: 1823 add3 tmp, op1, -op2 32-bit (or mov + sub) 1824 sltu3 tmp, tmp, 1 16-bit 1825 xor3 dest, tmp, 1 32-bit 1826 */ 1827 if (optimize_size && op2 != const0_rtx) 1828 return false; 1829 1830 if (op2 != const0_rtx) 1831 op1 = expand_binop (SImode, sub_optab, op1, op2, NULL, 1, OPTAB_WIDEN); 1832 1833 op2 = gen_reg_rtx (SImode); 1834 mep_expand_setcc_1 (LTU, op2, op1, const1_rtx); 1835 1836 emit_insn (gen_rtx_SET (VOIDmode, dest, 1837 gen_rtx_XOR (SImode, op2, const1_rtx))); 1838 return true; 1839 1840 case LE: 1841 if (GET_CODE (op2) != CONST_INT 1842 || INTVAL (op2) == 0x7ffffff) 1843 return false; 1844 op2 = GEN_INT (INTVAL (op2) + 1); 1845 return mep_expand_setcc_1 (LT, dest, op1, op2); 1846 1847 case LEU: 1848 if (GET_CODE (op2) != CONST_INT 1849 || INTVAL (op2) == -1) 1850 return false; 1851 op2 = GEN_INT (trunc_int_for_mode (INTVAL (op2) + 1, SImode)); 1852 return mep_expand_setcc_1 (LTU, dest, op1, op2); 1853 1854 case GE: 1855 if (GET_CODE (op2) != CONST_INT 1856 || INTVAL (op2) == trunc_int_for_mode (0x80000000, SImode)) 1857 return false; 1858 op2 = GEN_INT (INTVAL (op2) - 1); 1859 return mep_expand_setcc_1 (GT, dest, op1, op2); 1860 1861 case GEU: 1862 if (GET_CODE (op2) != CONST_INT 1863 || op2 == const0_rtx) 1864 return false; 1865 op2 = GEN_INT (trunc_int_for_mode (INTVAL (op2) - 1, SImode)); 1866 return mep_expand_setcc_1 (GTU, dest, op1, op2); 1867 1868 default: 1869 gcc_unreachable (); 1870 } 1871} 1872 1873bool 1874mep_expand_setcc (rtx *operands) 1875{ 1876 rtx dest = operands[0]; 1877 enum rtx_code code = GET_CODE (operands[1]); 1878 rtx op0 = operands[2]; 1879 rtx op1 = operands[3]; 1880 1881 return mep_expand_setcc_1 (code, dest, op0, op1); 1882} 1883 1884rtx 1885mep_expand_cbranch (rtx *operands) 1886{ 1887 enum rtx_code code = GET_CODE (operands[0]); 1888 rtx op0 = operands[1]; 1889 rtx op1 = operands[2]; 1890 rtx tmp; 1891 1892 restart: 1893 switch (code) 1894 { 1895 case LT: 1896 if (mep_imm4_operand (op1, SImode)) 1897 break; 1898 1899 tmp = gen_reg_rtx (SImode); 1900 gcc_assert (mep_expand_setcc_1 (LT, tmp, op0, op1)); 1901 code = NE; 1902 op0 = tmp; 1903 op1 = const0_rtx; 1904 break; 1905 1906 case GE: 1907 if (mep_imm4_operand (op1, SImode)) 1908 break; 1909 1910 tmp = gen_reg_rtx (SImode); 1911 gcc_assert (mep_expand_setcc_1 (LT, tmp, op0, op1)); 1912 1913 code = EQ; 1914 op0 = tmp; 1915 op1 = const0_rtx; 1916 break; 1917 1918 case EQ: 1919 case NE: 1920 if (! mep_reg_or_imm4_operand (op1, SImode)) 1921 op1 = force_reg (SImode, op1); 1922 break; 1923 1924 case LE: 1925 case GT: 1926 if (GET_CODE (op1) == CONST_INT 1927 && INTVAL (op1) != 0x7fffffff) 1928 { 1929 op1 = GEN_INT (INTVAL (op1) + 1); 1930 code = (code == LE ? LT : GE); 1931 goto restart; 1932 } 1933 1934 tmp = gen_reg_rtx (SImode); 1935 gcc_assert (mep_expand_setcc_1 (LT, tmp, op1, op0)); 1936 1937 code = (code == LE ? EQ : NE); 1938 op0 = tmp; 1939 op1 = const0_rtx; 1940 break; 1941 1942 case LTU: 1943 if (op1 == const1_rtx) 1944 { 1945 code = EQ; 1946 op1 = const0_rtx; 1947 break; 1948 } 1949 1950 tmp = gen_reg_rtx (SImode); 1951 gcc_assert (mep_expand_setcc_1 (LTU, tmp, op0, op1)); 1952 code = NE; 1953 op0 = tmp; 1954 op1 = const0_rtx; 1955 break; 1956 1957 case LEU: 1958 tmp = gen_reg_rtx (SImode); 1959 if (mep_expand_setcc_1 (LEU, tmp, op0, op1)) 1960 code = NE; 1961 else if (mep_expand_setcc_1 (LTU, tmp, op1, op0)) 1962 code = EQ; 1963 else 1964 gcc_unreachable (); 1965 op0 = tmp; 1966 op1 = const0_rtx; 1967 break; 1968 1969 case GTU: 1970 tmp = gen_reg_rtx (SImode); 1971 gcc_assert (mep_expand_setcc_1 (GTU, tmp, op0, op1) 1972 || mep_expand_setcc_1 (LTU, tmp, op1, op0)); 1973 code = NE; 1974 op0 = tmp; 1975 op1 = const0_rtx; 1976 break; 1977 1978 case GEU: 1979 tmp = gen_reg_rtx (SImode); 1980 if (mep_expand_setcc_1 (GEU, tmp, op0, op1)) 1981 code = NE; 1982 else if (mep_expand_setcc_1 (LTU, tmp, op0, op1)) 1983 code = EQ; 1984 else 1985 gcc_unreachable (); 1986 op0 = tmp; 1987 op1 = const0_rtx; 1988 break; 1989 1990 default: 1991 gcc_unreachable (); 1992 } 1993 1994 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); 1995} 1996 1997const char * 1998mep_emit_cbranch (rtx *operands, int ne) 1999{ 2000 if (GET_CODE (operands[1]) == REG) 2001 return ne ? "bne\t%0, %1, %l2" : "beq\t%0, %1, %l2"; 2002 else if (INTVAL (operands[1]) == 0 && !mep_vliw_function_p(cfun->decl)) 2003 return ne ? "bnez\t%0, %l2" : "beqz\t%0, %l2"; 2004 else 2005 return ne ? "bnei\t%0, %1, %l2" : "beqi\t%0, %1, %l2"; 2006} 2007 2008void 2009mep_expand_call (rtx *operands, int returns_value) 2010{ 2011 rtx addr = operands[returns_value]; 2012 rtx tp = mep_tp_rtx (); 2013 rtx gp = mep_gp_rtx (); 2014 2015 gcc_assert (GET_CODE (addr) == MEM); 2016 2017 addr = XEXP (addr, 0); 2018 2019 if (! mep_call_address_operand (addr, VOIDmode)) 2020 addr = force_reg (SImode, addr); 2021 2022 if (! operands[returns_value+2]) 2023 operands[returns_value+2] = const0_rtx; 2024 2025 if (returns_value) 2026 emit_call_insn (gen_call_value_internal (operands[0], addr, operands[2], 2027 operands[3], tp, gp)); 2028 else 2029 emit_call_insn (gen_call_internal (addr, operands[1], 2030 operands[2], tp, gp)); 2031} 2032 2033/* Aliasing Support. */ 2034 2035/* If X is a machine specific address (i.e. a symbol or label being 2036 referenced as a displacement from the GOT implemented using an 2037 UNSPEC), then return the base term. Otherwise return X. */ 2038 2039rtx 2040mep_find_base_term (rtx x) 2041{ 2042 rtx base, term; 2043 int unspec; 2044 2045 if (GET_CODE (x) != PLUS) 2046 return x; 2047 base = XEXP (x, 0); 2048 term = XEXP (x, 1); 2049 2050 if (has_hard_reg_initial_val(Pmode, TP_REGNO) 2051 && base == mep_tp_rtx ()) 2052 unspec = UNS_TPREL; 2053 else if (has_hard_reg_initial_val(Pmode, GP_REGNO) 2054 && base == mep_gp_rtx ()) 2055 unspec = UNS_GPREL; 2056 else 2057 return x; 2058 2059 if (GET_CODE (term) != CONST) 2060 return x; 2061 term = XEXP (term, 0); 2062 2063 if (GET_CODE (term) != UNSPEC 2064 || XINT (term, 1) != unspec) 2065 return x; 2066 2067 return XVECEXP (term, 0, 0); 2068} 2069 2070/* Reload Support. */ 2071 2072/* Return true if the registers in CLASS cannot represent the change from 2073 modes FROM to TO. */ 2074 2075bool 2076mep_cannot_change_mode_class (enum machine_mode from, enum machine_mode to, 2077 enum reg_class regclass) 2078{ 2079 if (from == to) 2080 return false; 2081 2082 /* 64-bit COP regs must remain 64-bit COP regs. */ 2083 if (TARGET_64BIT_CR_REGS 2084 && (regclass == CR_REGS 2085 || regclass == LOADABLE_CR_REGS) 2086 && (GET_MODE_SIZE (to) < 8 2087 || GET_MODE_SIZE (from) < 8)) 2088 return true; 2089 2090 return false; 2091} 2092 2093#define MEP_NONGENERAL_CLASS(C) (!reg_class_subset_p (C, GENERAL_REGS)) 2094 2095static bool 2096mep_general_reg (rtx x) 2097{ 2098 while (GET_CODE (x) == SUBREG) 2099 x = XEXP (x, 0); 2100 return GET_CODE (x) == REG && GR_REGNO_P (REGNO (x)); 2101} 2102 2103static bool 2104mep_nongeneral_reg (rtx x) 2105{ 2106 while (GET_CODE (x) == SUBREG) 2107 x = XEXP (x, 0); 2108 return (GET_CODE (x) == REG 2109 && !GR_REGNO_P (REGNO (x)) && REGNO (x) < FIRST_PSEUDO_REGISTER); 2110} 2111 2112static bool 2113mep_general_copro_reg (rtx x) 2114{ 2115 while (GET_CODE (x) == SUBREG) 2116 x = XEXP (x, 0); 2117 return (GET_CODE (x) == REG && CR_REGNO_P (REGNO (x))); 2118} 2119 2120static bool 2121mep_nonregister (rtx x) 2122{ 2123 while (GET_CODE (x) == SUBREG) 2124 x = XEXP (x, 0); 2125 return (GET_CODE (x) != REG || REGNO (x) >= FIRST_PSEUDO_REGISTER); 2126} 2127 2128#define DEBUG_RELOAD 0 2129 2130/* Return the secondary reload class needed for moving value X to or 2131 from a register in coprocessor register class CLASS. */ 2132 2133static enum reg_class 2134mep_secondary_copro_reload_class (enum reg_class rclass, rtx x) 2135{ 2136 if (mep_general_reg (x)) 2137 /* We can do the move directly if mep_have_core_copro_moves_p, 2138 otherwise we need to go through memory. Either way, no secondary 2139 register is needed. */ 2140 return NO_REGS; 2141 2142 if (mep_general_copro_reg (x)) 2143 { 2144 /* We can do the move directly if mep_have_copro_copro_moves_p. */ 2145 if (mep_have_copro_copro_moves_p) 2146 return NO_REGS; 2147 2148 /* Otherwise we can use a temporary if mep_have_core_copro_moves_p. */ 2149 if (mep_have_core_copro_moves_p) 2150 return GENERAL_REGS; 2151 2152 /* Otherwise we need to do it through memory. No secondary 2153 register is needed. */ 2154 return NO_REGS; 2155 } 2156 2157 if (reg_class_subset_p (rclass, LOADABLE_CR_REGS) 2158 && constraint_satisfied_p (x, CONSTRAINT_U)) 2159 /* X is a memory value that we can access directly. */ 2160 return NO_REGS; 2161 2162 /* We have to move X into a GPR first and then copy it to 2163 the coprocessor register. The move from the GPR to the 2164 coprocessor might be done directly or through memory, 2165 depending on mep_have_core_copro_moves_p. */ 2166 return GENERAL_REGS; 2167} 2168 2169/* Copying X to register in RCLASS. */ 2170 2171int 2172mep_secondary_input_reload_class (enum reg_class rclass, 2173 enum machine_mode mode ATTRIBUTE_UNUSED, 2174 rtx x) 2175{ 2176 int rv = NO_REGS; 2177 2178#if DEBUG_RELOAD 2179 fprintf (stderr, "secondary input reload copy to %s %s from ", reg_class_names[rclass], mode_name[mode]); 2180 debug_rtx (x); 2181#endif 2182 2183 if (reg_class_subset_p (rclass, CR_REGS)) 2184 rv = mep_secondary_copro_reload_class (rclass, x); 2185 else if (MEP_NONGENERAL_CLASS (rclass) 2186 && (mep_nonregister (x) || mep_nongeneral_reg (x))) 2187 rv = GENERAL_REGS; 2188 2189#if DEBUG_RELOAD 2190 fprintf (stderr, " - requires %s\n", reg_class_names[rv]); 2191#endif 2192 return rv; 2193} 2194 2195/* Copying register in RCLASS to X. */ 2196 2197int 2198mep_secondary_output_reload_class (enum reg_class rclass, 2199 enum machine_mode mode ATTRIBUTE_UNUSED, 2200 rtx x) 2201{ 2202 int rv = NO_REGS; 2203 2204#if DEBUG_RELOAD 2205 fprintf (stderr, "secondary output reload copy from %s %s to ", reg_class_names[rclass], mode_name[mode]); 2206 debug_rtx (x); 2207#endif 2208 2209 if (reg_class_subset_p (rclass, CR_REGS)) 2210 rv = mep_secondary_copro_reload_class (rclass, x); 2211 else if (MEP_NONGENERAL_CLASS (rclass) 2212 && (mep_nonregister (x) || mep_nongeneral_reg (x))) 2213 rv = GENERAL_REGS; 2214 2215#if DEBUG_RELOAD 2216 fprintf (stderr, " - requires %s\n", reg_class_names[rv]); 2217#endif 2218 2219 return rv; 2220} 2221 2222/* Implement SECONDARY_MEMORY_NEEDED. */ 2223 2224bool 2225mep_secondary_memory_needed (enum reg_class rclass1, enum reg_class rclass2, 2226 enum machine_mode mode ATTRIBUTE_UNUSED) 2227{ 2228 if (!mep_have_core_copro_moves_p) 2229 { 2230 if (reg_classes_intersect_p (rclass1, CR_REGS) 2231 && reg_classes_intersect_p (rclass2, GENERAL_REGS)) 2232 return true; 2233 if (reg_classes_intersect_p (rclass2, CR_REGS) 2234 && reg_classes_intersect_p (rclass1, GENERAL_REGS)) 2235 return true; 2236 if (!mep_have_copro_copro_moves_p 2237 && reg_classes_intersect_p (rclass1, CR_REGS) 2238 && reg_classes_intersect_p (rclass2, CR_REGS)) 2239 return true; 2240 } 2241 return false; 2242} 2243 2244void 2245mep_expand_reload (rtx *operands, enum machine_mode mode) 2246{ 2247 /* There are three cases for each direction: 2248 register, farsym 2249 control, farsym 2250 control, nearsym */ 2251 2252 int s0 = mep_section_tag (operands[0]) == 'f'; 2253 int s1 = mep_section_tag (operands[1]) == 'f'; 2254 int c0 = mep_nongeneral_reg (operands[0]); 2255 int c1 = mep_nongeneral_reg (operands[1]); 2256 int which = (s0 ? 20:0) + (c0 ? 10:0) + (s1 ? 2:0) + (c1 ? 1:0); 2257 2258#if DEBUG_RELOAD 2259 fprintf (stderr, "expand_reload %s\n", mode_name[mode]); 2260 debug_rtx (operands[0]); 2261 debug_rtx (operands[1]); 2262#endif 2263 2264 switch (which) 2265 { 2266 case 00: /* Don't know why this gets here. */ 2267 case 02: /* general = far */ 2268 emit_move_insn (operands[0], operands[1]); 2269 return; 2270 2271 case 10: /* cr = mem */ 2272 case 11: /* cr = cr */ 2273 case 01: /* mem = cr */ 2274 case 12: /* cr = far */ 2275 emit_move_insn (operands[2], operands[1]); 2276 emit_move_insn (operands[0], operands[2]); 2277 return; 2278 2279 case 20: /* far = general */ 2280 emit_move_insn (operands[2], XEXP (operands[1], 0)); 2281 emit_move_insn (operands[0], gen_rtx_MEM (mode, operands[2])); 2282 return; 2283 2284 case 21: /* far = cr */ 2285 case 22: /* far = far */ 2286 default: 2287 fprintf (stderr, "unsupported expand reload case %02d for mode %s\n", 2288 which, mode_name[mode]); 2289 debug_rtx (operands[0]); 2290 debug_rtx (operands[1]); 2291 gcc_unreachable (); 2292 } 2293} 2294 2295/* Implement PREFERRED_RELOAD_CLASS. See whether X is a constant that 2296 can be moved directly into registers 0 to 7, but not into the rest. 2297 If so, and if the required class includes registers 0 to 7, restrict 2298 it to those registers. */ 2299 2300enum reg_class 2301mep_preferred_reload_class (rtx x, enum reg_class rclass) 2302{ 2303 switch (GET_CODE (x)) 2304 { 2305 case CONST_INT: 2306 if (INTVAL (x) >= 0x10000 2307 && INTVAL (x) < 0x01000000 2308 && (INTVAL (x) & 0xffff) != 0 2309 && reg_class_subset_p (TPREL_REGS, rclass)) 2310 rclass = TPREL_REGS; 2311 break; 2312 2313 case CONST: 2314 case SYMBOL_REF: 2315 case LABEL_REF: 2316 if (mep_section_tag (x) != 'f' 2317 && reg_class_subset_p (TPREL_REGS, rclass)) 2318 rclass = TPREL_REGS; 2319 break; 2320 2321 default: 2322 break; 2323 } 2324 return rclass; 2325} 2326 2327/* Implement REGISTER_MOVE_COST. Return 2 for direct single-register 2328 moves, 4 for direct double-register moves, and 1000 for anything 2329 that requires a temporary register or temporary stack slot. */ 2330 2331int 2332mep_register_move_cost (enum machine_mode mode, enum reg_class from, enum reg_class to) 2333{ 2334 if (mep_have_copro_copro_moves_p 2335 && reg_class_subset_p (from, CR_REGS) 2336 && reg_class_subset_p (to, CR_REGS)) 2337 { 2338 if (TARGET_32BIT_CR_REGS && GET_MODE_SIZE (mode) > UNITS_PER_WORD) 2339 return 4; 2340 return 2; 2341 } 2342 if (reg_class_subset_p (from, CR_REGS) 2343 && reg_class_subset_p (to, CR_REGS)) 2344 { 2345 if (TARGET_32BIT_CR_REGS && GET_MODE_SIZE (mode) > UNITS_PER_WORD) 2346 return 8; 2347 return 4; 2348 } 2349 if (reg_class_subset_p (from, CR_REGS) 2350 || reg_class_subset_p (to, CR_REGS)) 2351 { 2352 if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) 2353 return 4; 2354 return 2; 2355 } 2356 if (mep_secondary_memory_needed (from, to, mode)) 2357 return 1000; 2358 if (MEP_NONGENERAL_CLASS (from) && MEP_NONGENERAL_CLASS (to)) 2359 return 1000; 2360 2361 if (GET_MODE_SIZE (mode) > 4) 2362 return 4; 2363 2364 return 2; 2365} 2366 2367 2368/* Functions to save and restore machine-specific function data. */ 2369 2370static struct machine_function * 2371mep_init_machine_status (void) 2372{ 2373 struct machine_function *f; 2374 2375 f = (struct machine_function *) ggc_alloc_cleared (sizeof (struct machine_function)); 2376 2377 return f; 2378} 2379 2380static rtx 2381mep_allocate_initial_value (rtx reg) 2382{ 2383 int rss; 2384 2385 if (GET_CODE (reg) != REG) 2386 return NULL_RTX; 2387 2388 if (REGNO (reg) >= FIRST_PSEUDO_REGISTER) 2389 return NULL_RTX; 2390 2391 /* In interrupt functions, the "initial" values of $gp and $tp are 2392 provided by the prologue. They are not necessarily the same as 2393 the values that the caller was using. */ 2394 if (REGNO (reg) == TP_REGNO || REGNO (reg) == GP_REGNO) 2395 if (mep_interrupt_p ()) 2396 return NULL_RTX; 2397 2398 if (! cfun->machine->reg_save_slot[REGNO(reg)]) 2399 { 2400 cfun->machine->reg_save_size += 4; 2401 cfun->machine->reg_save_slot[REGNO(reg)] = cfun->machine->reg_save_size; 2402 } 2403 2404 rss = cfun->machine->reg_save_slot[REGNO(reg)]; 2405 return gen_rtx_MEM (SImode, plus_constant (arg_pointer_rtx, -rss)); 2406} 2407 2408rtx 2409mep_return_addr_rtx (int count) 2410{ 2411 if (count != 0) 2412 return const0_rtx; 2413 2414 return get_hard_reg_initial_val (Pmode, LP_REGNO); 2415} 2416 2417static rtx 2418mep_tp_rtx (void) 2419{ 2420 return get_hard_reg_initial_val (Pmode, TP_REGNO); 2421} 2422 2423static rtx 2424mep_gp_rtx (void) 2425{ 2426 return get_hard_reg_initial_val (Pmode, GP_REGNO); 2427} 2428 2429static bool 2430mep_interrupt_p (void) 2431{ 2432 if (cfun->machine->interrupt_handler == 0) 2433 { 2434 int interrupt_handler 2435 = (lookup_attribute ("interrupt", 2436 DECL_ATTRIBUTES (current_function_decl)) 2437 != NULL_TREE); 2438 cfun->machine->interrupt_handler = interrupt_handler ? 2 : 1; 2439 } 2440 return cfun->machine->interrupt_handler == 2; 2441} 2442 2443static bool 2444mep_disinterrupt_p (void) 2445{ 2446 if (cfun->machine->disable_interrupts == 0) 2447 { 2448 int disable_interrupts 2449 = (lookup_attribute ("disinterrupt", 2450 DECL_ATTRIBUTES (current_function_decl)) 2451 != NULL_TREE); 2452 cfun->machine->disable_interrupts = disable_interrupts ? 2 : 1; 2453 } 2454 return cfun->machine->disable_interrupts == 2; 2455} 2456 2457 2458/* Frame/Epilog/Prolog Related. */ 2459 2460static bool 2461mep_reg_set_p (rtx reg, rtx insn) 2462{ 2463 /* Similar to reg_set_p in rtlanal.c, but we ignore calls */ 2464 if (INSN_P (insn)) 2465 { 2466 if (FIND_REG_INC_NOTE (insn, reg)) 2467 return true; 2468 insn = PATTERN (insn); 2469 } 2470 2471 if (GET_CODE (insn) == SET 2472 && GET_CODE (XEXP (insn, 0)) == REG 2473 && GET_CODE (XEXP (insn, 1)) == REG 2474 && REGNO (XEXP (insn, 0)) == REGNO (XEXP (insn, 1))) 2475 return false; 2476 2477 return set_of (reg, insn) != NULL_RTX; 2478} 2479 2480 2481#define MEP_SAVES_UNKNOWN 0 2482#define MEP_SAVES_YES 1 2483#define MEP_SAVES_MAYBE 2 2484#define MEP_SAVES_NO 3 2485 2486static bool 2487mep_reg_set_in_function (int regno) 2488{ 2489 rtx reg, insn; 2490 2491 if (mep_interrupt_p () && df_regs_ever_live_p(regno)) 2492 return true; 2493 2494 if (regno == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0)) 2495 return true; 2496 2497 push_topmost_sequence (); 2498 insn = get_insns (); 2499 pop_topmost_sequence (); 2500 2501 if (!insn) 2502 return false; 2503 2504 reg = gen_rtx_REG (SImode, regno); 2505 2506 for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn)) 2507 if (INSN_P (insn) && mep_reg_set_p (reg, insn)) 2508 return true; 2509 return false; 2510} 2511 2512static bool 2513mep_asm_without_operands_p (void) 2514{ 2515 if (cfun->machine->asms_without_operands == 0) 2516 { 2517 rtx insn; 2518 2519 push_topmost_sequence (); 2520 insn = get_insns (); 2521 pop_topmost_sequence (); 2522 2523 cfun->machine->asms_without_operands = 1; 2524 while (insn) 2525 { 2526 if (INSN_P (insn) 2527 && GET_CODE (PATTERN (insn)) == ASM_INPUT) 2528 { 2529 cfun->machine->asms_without_operands = 2; 2530 break; 2531 } 2532 insn = NEXT_INSN (insn); 2533 } 2534 2535 } 2536 return cfun->machine->asms_without_operands == 2; 2537} 2538 2539/* Interrupt functions save/restore every call-preserved register, and 2540 any call-used register it uses (or all if it calls any function, 2541 since they may get clobbered there too). Here we check to see 2542 which call-used registers need saving. */ 2543 2544#define IVC2_ISAVED_REG(r) (TARGET_IVC2 \ 2545 && (r == FIRST_CCR_REGNO + 1 \ 2546 || (r >= FIRST_CCR_REGNO + 8 && r <= FIRST_CCR_REGNO + 11) \ 2547 || (r >= FIRST_CCR_REGNO + 16 && r <= FIRST_CCR_REGNO + 31))) 2548 2549static bool 2550mep_interrupt_saved_reg (int r) 2551{ 2552 if (!mep_interrupt_p ()) 2553 return false; 2554 if (r == REGSAVE_CONTROL_TEMP 2555 || (TARGET_64BIT_CR_REGS && TARGET_COP && r == REGSAVE_CONTROL_TEMP+1)) 2556 return true; 2557 if (mep_asm_without_operands_p () 2558 && (!fixed_regs[r] 2559 || (r == RPB_REGNO || r == RPE_REGNO || r == RPC_REGNO || r == LP_REGNO) 2560 || IVC2_ISAVED_REG (r))) 2561 return true; 2562 if (!current_function_is_leaf) 2563 /* Function calls mean we need to save $lp. */ 2564 if (r == LP_REGNO || IVC2_ISAVED_REG (r)) 2565 return true; 2566 if (!current_function_is_leaf || cfun->machine->doloop_tags > 0) 2567 /* The interrupt handler might use these registers for repeat blocks, 2568 or it might call a function that does so. */ 2569 if (r == RPB_REGNO || r == RPE_REGNO || r == RPC_REGNO) 2570 return true; 2571 if (current_function_is_leaf && call_used_regs[r] && !df_regs_ever_live_p(r)) 2572 return false; 2573 /* Functions we call might clobber these. */ 2574 if (call_used_regs[r] && !fixed_regs[r]) 2575 return true; 2576 /* Additional registers that need to be saved for IVC2. */ 2577 if (IVC2_ISAVED_REG (r)) 2578 return true; 2579 2580 return false; 2581} 2582 2583static bool 2584mep_call_saves_register (int r) 2585{ 2586 if (! cfun->machine->frame_locked) 2587 { 2588 int rv = MEP_SAVES_NO; 2589 2590 if (cfun->machine->reg_save_slot[r]) 2591 rv = MEP_SAVES_YES; 2592 else if (r == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0)) 2593 rv = MEP_SAVES_YES; 2594 else if (r == FRAME_POINTER_REGNUM && frame_pointer_needed) 2595 rv = MEP_SAVES_YES; 2596 else if ((!call_used_regs[r] || r == LP_REGNO) && df_regs_ever_live_p(r)) 2597 rv = MEP_SAVES_YES; 2598 else if (crtl->calls_eh_return && (r == 10 || r == 11)) 2599 /* We need these to have stack slots so that they can be set during 2600 unwinding. */ 2601 rv = MEP_SAVES_YES; 2602 else if (mep_interrupt_saved_reg (r)) 2603 rv = MEP_SAVES_YES; 2604 cfun->machine->reg_saved[r] = rv; 2605 } 2606 return cfun->machine->reg_saved[r] == MEP_SAVES_YES; 2607} 2608 2609/* Return true if epilogue uses register REGNO. */ 2610 2611bool 2612mep_epilogue_uses (int regno) 2613{ 2614 /* Since $lp is a call-saved register, the generic code will normally 2615 mark it used in the epilogue if it needs to be saved and restored. 2616 However, when profiling is enabled, the profiling code will implicitly 2617 clobber $11. This case has to be handled specially both here and in 2618 mep_call_saves_register. */ 2619 if (regno == LP_REGNO && (profile_arc_flag > 0 || profile_flag > 0)) 2620 return true; 2621 /* Interrupt functions save/restore pretty much everything. */ 2622 return (reload_completed && mep_interrupt_saved_reg (regno)); 2623} 2624 2625static int 2626mep_reg_size (int regno) 2627{ 2628 if (CR_REGNO_P (regno) && TARGET_64BIT_CR_REGS) 2629 return 8; 2630 return 4; 2631} 2632 2633/* Worker function for TARGET_CAN_ELIMINATE. */ 2634 2635bool 2636mep_can_eliminate (const int from, const int to) 2637{ 2638 return (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM 2639 ? ! frame_pointer_needed 2640 : true); 2641} 2642 2643int 2644mep_elimination_offset (int from, int to) 2645{ 2646 int reg_save_size; 2647 int i; 2648 int frame_size = get_frame_size () + crtl->outgoing_args_size; 2649 int total_size; 2650 2651 if (!cfun->machine->frame_locked) 2652 memset (cfun->machine->reg_saved, 0, sizeof (cfun->machine->reg_saved)); 2653 2654 /* We don't count arg_regs_to_save in the arg pointer offset, because 2655 gcc thinks the arg pointer has moved along with the saved regs. 2656 However, we do count it when we adjust $sp in the prologue. */ 2657 reg_save_size = 0; 2658 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 2659 if (mep_call_saves_register (i)) 2660 reg_save_size += mep_reg_size (i); 2661 2662 if (reg_save_size % 8) 2663 cfun->machine->regsave_filler = 8 - (reg_save_size % 8); 2664 else 2665 cfun->machine->regsave_filler = 0; 2666 2667 /* This is what our total stack adjustment looks like. */ 2668 total_size = (reg_save_size + frame_size + cfun->machine->regsave_filler); 2669 2670 if (total_size % 8) 2671 cfun->machine->frame_filler = 8 - (total_size % 8); 2672 else 2673 cfun->machine->frame_filler = 0; 2674 2675 2676 if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM) 2677 return reg_save_size + cfun->machine->regsave_filler; 2678 2679 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) 2680 return cfun->machine->frame_filler + frame_size; 2681 2682 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) 2683 return reg_save_size + cfun->machine->regsave_filler + cfun->machine->frame_filler + frame_size; 2684 2685 gcc_unreachable (); 2686} 2687 2688static rtx 2689F (rtx x) 2690{ 2691 RTX_FRAME_RELATED_P (x) = 1; 2692 return x; 2693} 2694 2695/* Since the prologue/epilogue code is generated after optimization, 2696 we can't rely on gcc to split constants for us. So, this code 2697 captures all the ways to add a constant to a register in one logic 2698 chunk, including optimizing away insns we just don't need. This 2699 makes the prolog/epilog code easier to follow. */ 2700static void 2701add_constant (int dest, int src, int value, int mark_frame) 2702{ 2703 rtx insn; 2704 int hi, lo; 2705 2706 if (src == dest && value == 0) 2707 return; 2708 2709 if (value == 0) 2710 { 2711 insn = emit_move_insn (gen_rtx_REG (SImode, dest), 2712 gen_rtx_REG (SImode, src)); 2713 if (mark_frame) 2714 RTX_FRAME_RELATED_P(insn) = 1; 2715 return; 2716 } 2717 2718 if (value >= -32768 && value <= 32767) 2719 { 2720 insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, dest), 2721 gen_rtx_REG (SImode, src), 2722 GEN_INT (value))); 2723 if (mark_frame) 2724 RTX_FRAME_RELATED_P(insn) = 1; 2725 return; 2726 } 2727 2728 /* Big constant, need to use a temp register. We use 2729 REGSAVE_CONTROL_TEMP because it's call clobberable (the reg save 2730 area is always small enough to directly add to). */ 2731 2732 hi = trunc_int_for_mode (value & 0xffff0000, SImode); 2733 lo = value & 0xffff; 2734 2735 insn = emit_move_insn (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP), 2736 GEN_INT (hi)); 2737 2738 if (lo) 2739 { 2740 insn = emit_insn (gen_iorsi3 (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP), 2741 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP), 2742 GEN_INT (lo))); 2743 } 2744 2745 insn = emit_insn (gen_addsi3 (gen_rtx_REG (SImode, dest), 2746 gen_rtx_REG (SImode, src), 2747 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP))); 2748 if (mark_frame) 2749 { 2750 RTX_FRAME_RELATED_P(insn) = 1; 2751 add_reg_note (insn, REG_FRAME_RELATED_EXPR, 2752 gen_rtx_SET (SImode, 2753 gen_rtx_REG (SImode, dest), 2754 gen_rtx_PLUS (SImode, 2755 gen_rtx_REG (SImode, dest), 2756 GEN_INT (value)))); 2757 } 2758} 2759 2760/* Move SRC to DEST. Mark the move as being potentially dead if 2761 MAYBE_DEAD_P. */ 2762 2763static rtx 2764maybe_dead_move (rtx dest, rtx src, bool ATTRIBUTE_UNUSED maybe_dead_p) 2765{ 2766 rtx insn = emit_move_insn (dest, src); 2767#if 0 2768 if (maybe_dead_p) 2769 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL); 2770#endif 2771 return insn; 2772} 2773 2774/* Used for interrupt functions, which can't assume that $tp and $gp 2775 contain the correct pointers. */ 2776 2777static void 2778mep_reload_pointer (int regno, const char *symbol) 2779{ 2780 rtx reg, sym; 2781 2782 if (!df_regs_ever_live_p(regno) && current_function_is_leaf) 2783 return; 2784 2785 reg = gen_rtx_REG (SImode, regno); 2786 sym = gen_rtx_SYMBOL_REF (SImode, symbol); 2787 emit_insn (gen_movsi_topsym_s (reg, sym)); 2788 emit_insn (gen_movsi_botsym_s (reg, reg, sym)); 2789} 2790 2791/* Assign save slots for any register not already saved. DImode 2792 registers go at the end of the reg save area; the rest go at the 2793 beginning. This is for alignment purposes. Returns true if a frame 2794 is really needed. */ 2795static bool 2796mep_assign_save_slots (int reg_save_size) 2797{ 2798 bool really_need_stack_frame = false; 2799 int di_ofs = 0; 2800 int i; 2801 2802 for (i=0; i<FIRST_PSEUDO_REGISTER; i++) 2803 if (mep_call_saves_register(i)) 2804 { 2805 int regsize = mep_reg_size (i); 2806 2807 if ((i != TP_REGNO && i != GP_REGNO && i != LP_REGNO) 2808 || mep_reg_set_in_function (i)) 2809 really_need_stack_frame = true; 2810 2811 if (cfun->machine->reg_save_slot[i]) 2812 continue; 2813 2814 if (regsize < 8) 2815 { 2816 cfun->machine->reg_save_size += regsize; 2817 cfun->machine->reg_save_slot[i] = cfun->machine->reg_save_size; 2818 } 2819 else 2820 { 2821 cfun->machine->reg_save_slot[i] = reg_save_size - di_ofs; 2822 di_ofs += 8; 2823 } 2824 } 2825 cfun->machine->frame_locked = 1; 2826 return really_need_stack_frame; 2827} 2828 2829void 2830mep_expand_prologue (void) 2831{ 2832 int i, rss, sp_offset = 0; 2833 int reg_save_size; 2834 int frame_size; 2835 int really_need_stack_frame; 2836 2837 /* We must not allow register renaming in interrupt functions, 2838 because that invalidates the correctness of the set of call-used 2839 registers we're going to save/restore. */ 2840 mep_set_leaf_registers (mep_interrupt_p () ? 0 : 1); 2841 2842 if (mep_disinterrupt_p ()) 2843 emit_insn (gen_mep_disable_int ()); 2844 2845 cfun->machine->mep_frame_pointer_needed = frame_pointer_needed; 2846 2847 reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM); 2848 frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM); 2849 really_need_stack_frame = frame_size; 2850 2851 really_need_stack_frame |= mep_assign_save_slots (reg_save_size); 2852 2853 sp_offset = reg_save_size; 2854 if (sp_offset + frame_size < 128) 2855 sp_offset += frame_size ; 2856 2857 add_constant (SP_REGNO, SP_REGNO, -sp_offset, 1); 2858 2859 for (i=0; i<FIRST_PSEUDO_REGISTER; i++) 2860 if (mep_call_saves_register(i)) 2861 { 2862 rtx mem; 2863 bool maybe_dead_p; 2864 enum machine_mode rmode; 2865 2866 rss = cfun->machine->reg_save_slot[i]; 2867 2868 if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO) 2869 && (!mep_reg_set_in_function (i) 2870 && !mep_interrupt_p ())) 2871 continue; 2872 2873 if (mep_reg_size (i) == 8) 2874 rmode = DImode; 2875 else 2876 rmode = SImode; 2877 2878 /* If there is a pseudo associated with this register's initial value, 2879 reload might have already spilt it to the stack slot suggested by 2880 ALLOCATE_INITIAL_VALUE. The moves emitted here can then be safely 2881 deleted as dead. */ 2882 mem = gen_rtx_MEM (rmode, 2883 plus_constant (stack_pointer_rtx, sp_offset - rss)); 2884 maybe_dead_p = rtx_equal_p (mem, has_hard_reg_initial_val (rmode, i)); 2885 2886 if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i)) 2887 F(maybe_dead_move (mem, gen_rtx_REG (rmode, i), maybe_dead_p)); 2888 else if (rmode == DImode) 2889 { 2890 rtx insn; 2891 int be = TARGET_BIG_ENDIAN ? 4 : 0; 2892 2893 mem = gen_rtx_MEM (SImode, 2894 plus_constant (stack_pointer_rtx, sp_offset - rss + be)); 2895 2896 maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP), 2897 gen_rtx_REG (SImode, i), 2898 maybe_dead_p); 2899 maybe_dead_move (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1), 2900 gen_rtx_ZERO_EXTRACT (SImode, 2901 gen_rtx_REG (DImode, i), 2902 GEN_INT (32), 2903 GEN_INT (32)), 2904 maybe_dead_p); 2905 insn = maybe_dead_move (mem, 2906 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP), 2907 maybe_dead_p); 2908 RTX_FRAME_RELATED_P (insn) = 1; 2909 2910 add_reg_note (insn, REG_FRAME_RELATED_EXPR, 2911 gen_rtx_SET (VOIDmode, 2912 copy_rtx (mem), 2913 gen_rtx_REG (rmode, i))); 2914 mem = gen_rtx_MEM (SImode, 2915 plus_constant (stack_pointer_rtx, sp_offset - rss + (4-be))); 2916 insn = maybe_dead_move (mem, 2917 gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP+1), 2918 maybe_dead_p); 2919 } 2920 else 2921 { 2922 rtx insn; 2923 maybe_dead_move (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP), 2924 gen_rtx_REG (rmode, i), 2925 maybe_dead_p); 2926 insn = maybe_dead_move (mem, 2927 gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP), 2928 maybe_dead_p); 2929 RTX_FRAME_RELATED_P (insn) = 1; 2930 2931 add_reg_note (insn, REG_FRAME_RELATED_EXPR, 2932 gen_rtx_SET (VOIDmode, 2933 copy_rtx (mem), 2934 gen_rtx_REG (rmode, i))); 2935 } 2936 } 2937 2938 if (frame_pointer_needed) 2939 { 2940 /* We've already adjusted down by sp_offset. Total $sp change 2941 is reg_save_size + frame_size. We want a net change here of 2942 just reg_save_size. */ 2943 add_constant (FP_REGNO, SP_REGNO, sp_offset - reg_save_size, 1); 2944 } 2945 2946 add_constant (SP_REGNO, SP_REGNO, sp_offset-(reg_save_size+frame_size), 1); 2947 2948 if (mep_interrupt_p ()) 2949 { 2950 mep_reload_pointer(GP_REGNO, "__sdabase"); 2951 mep_reload_pointer(TP_REGNO, "__tpbase"); 2952 } 2953} 2954 2955static void 2956mep_start_function (FILE *file, HOST_WIDE_INT hwi_local) 2957{ 2958 int local = hwi_local; 2959 int frame_size = local + crtl->outgoing_args_size; 2960 int reg_save_size; 2961 int ffill; 2962 int i, sp, skip; 2963 int sp_offset; 2964 int slot_map[FIRST_PSEUDO_REGISTER], si, sj; 2965 2966 reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM); 2967 frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM); 2968 sp_offset = reg_save_size + frame_size; 2969 2970 ffill = cfun->machine->frame_filler; 2971 2972 if (cfun->machine->mep_frame_pointer_needed) 2973 reg_names[FP_REGNO] = "$fp"; 2974 else 2975 reg_names[FP_REGNO] = "$8"; 2976 2977 if (sp_offset == 0) 2978 return; 2979 2980 if (debug_info_level == DINFO_LEVEL_NONE) 2981 { 2982 fprintf (file, "\t# frame: %d", sp_offset); 2983 if (reg_save_size) 2984 fprintf (file, " %d regs", reg_save_size); 2985 if (local) 2986 fprintf (file, " %d locals", local); 2987 if (crtl->outgoing_args_size) 2988 fprintf (file, " %d args", crtl->outgoing_args_size); 2989 fprintf (file, "\n"); 2990 return; 2991 } 2992 2993 fprintf (file, "\t#\n"); 2994 fprintf (file, "\t# Initial Frame Information:\n"); 2995 if (sp_offset || !frame_pointer_needed) 2996 fprintf (file, "\t# Entry ---------- 0\n"); 2997 2998 /* Sort registers by save slots, so they're printed in the order 2999 they appear in memory, not the order they're saved in. */ 3000 for (si=0; si<FIRST_PSEUDO_REGISTER; si++) 3001 slot_map[si] = si; 3002 for (si=0; si<FIRST_PSEUDO_REGISTER-1; si++) 3003 for (sj=si+1; sj<FIRST_PSEUDO_REGISTER; sj++) 3004 if (cfun->machine->reg_save_slot[slot_map[si]] 3005 > cfun->machine->reg_save_slot[slot_map[sj]]) 3006 { 3007 int t = slot_map[si]; 3008 slot_map[si] = slot_map[sj]; 3009 slot_map[sj] = t; 3010 } 3011 3012 sp = 0; 3013 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 3014 { 3015 int rsize; 3016 int r = slot_map[i]; 3017 int rss = cfun->machine->reg_save_slot[r]; 3018 3019 if (!mep_call_saves_register (r)) 3020 continue; 3021 3022 if ((r == TP_REGNO || r == GP_REGNO || r == LP_REGNO) 3023 && (!mep_reg_set_in_function (r) 3024 && !mep_interrupt_p ())) 3025 continue; 3026 3027 rsize = mep_reg_size(r); 3028 skip = rss - (sp+rsize); 3029 if (skip) 3030 fprintf (file, "\t# %3d bytes for alignment\n", skip); 3031 fprintf (file, "\t# %3d bytes for saved %-3s %3d($sp)\n", 3032 rsize, reg_names[r], sp_offset - rss); 3033 sp = rss; 3034 } 3035 3036 skip = reg_save_size - sp; 3037 if (skip) 3038 fprintf (file, "\t# %3d bytes for alignment\n", skip); 3039 3040 if (frame_pointer_needed) 3041 fprintf (file, "\t# FP ---> ---------- %d (sp-%d)\n", reg_save_size, sp_offset-reg_save_size); 3042 if (local) 3043 fprintf (file, "\t# %3d bytes for local vars\n", local); 3044 if (ffill) 3045 fprintf (file, "\t# %3d bytes for alignment\n", ffill); 3046 if (crtl->outgoing_args_size) 3047 fprintf (file, "\t# %3d bytes for outgoing args\n", 3048 crtl->outgoing_args_size); 3049 fprintf (file, "\t# SP ---> ---------- %d\n", sp_offset); 3050 fprintf (file, "\t#\n"); 3051} 3052 3053 3054static int mep_prevent_lp_restore = 0; 3055static int mep_sibcall_epilogue = 0; 3056 3057void 3058mep_expand_epilogue (void) 3059{ 3060 int i, sp_offset = 0; 3061 int reg_save_size = 0; 3062 int frame_size; 3063 int lp_temp = LP_REGNO, lp_slot = -1; 3064 int really_need_stack_frame = get_frame_size() + crtl->outgoing_args_size; 3065 int interrupt_handler = mep_interrupt_p (); 3066 3067 if (profile_arc_flag == 2) 3068 emit_insn (gen_mep_bb_trace_ret ()); 3069 3070 reg_save_size = mep_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM); 3071 frame_size = mep_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM); 3072 3073 really_need_stack_frame |= mep_assign_save_slots (reg_save_size); 3074 3075 if (frame_pointer_needed) 3076 { 3077 /* If we have a frame pointer, we won't have a reliable stack 3078 pointer (alloca, you know), so rebase SP from FP */ 3079 emit_move_insn (gen_rtx_REG (SImode, SP_REGNO), 3080 gen_rtx_REG (SImode, FP_REGNO)); 3081 sp_offset = reg_save_size; 3082 } 3083 else 3084 { 3085 /* SP is right under our local variable space. Adjust it if 3086 needed. */ 3087 sp_offset = reg_save_size + frame_size; 3088 if (sp_offset >= 128) 3089 { 3090 add_constant (SP_REGNO, SP_REGNO, frame_size, 0); 3091 sp_offset -= frame_size; 3092 } 3093 } 3094 3095 /* This is backwards so that we restore the control and coprocessor 3096 registers before the temporary registers we use to restore 3097 them. */ 3098 for (i=FIRST_PSEUDO_REGISTER-1; i>=1; i--) 3099 if (mep_call_saves_register (i)) 3100 { 3101 enum machine_mode rmode; 3102 int rss = cfun->machine->reg_save_slot[i]; 3103 3104 if (mep_reg_size (i) == 8) 3105 rmode = DImode; 3106 else 3107 rmode = SImode; 3108 3109 if ((i == TP_REGNO || i == GP_REGNO || i == LP_REGNO) 3110 && !(mep_reg_set_in_function (i) || interrupt_handler)) 3111 continue; 3112 if (mep_prevent_lp_restore && i == LP_REGNO) 3113 continue; 3114 if (!mep_prevent_lp_restore 3115 && !interrupt_handler 3116 && (i == 10 || i == 11)) 3117 continue; 3118 3119 if (GR_REGNO_P (i) || LOADABLE_CR_REGNO_P (i)) 3120 emit_move_insn (gen_rtx_REG (rmode, i), 3121 gen_rtx_MEM (rmode, 3122 plus_constant (stack_pointer_rtx, 3123 sp_offset-rss))); 3124 else 3125 { 3126 if (i == LP_REGNO && !mep_sibcall_epilogue && !interrupt_handler) 3127 /* Defer this one so we can jump indirect rather than 3128 copying the RA to $lp and "ret". EH epilogues 3129 automatically skip this anyway. */ 3130 lp_slot = sp_offset-rss; 3131 else 3132 { 3133 emit_move_insn (gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP), 3134 gen_rtx_MEM (rmode, 3135 plus_constant (stack_pointer_rtx, 3136 sp_offset-rss))); 3137 emit_move_insn (gen_rtx_REG (rmode, i), 3138 gen_rtx_REG (rmode, REGSAVE_CONTROL_TEMP)); 3139 } 3140 } 3141 } 3142 if (lp_slot != -1) 3143 { 3144 /* Restore this one last so we know it will be in the temp 3145 register when we return by jumping indirectly via the temp. */ 3146 emit_move_insn (gen_rtx_REG (SImode, REGSAVE_CONTROL_TEMP), 3147 gen_rtx_MEM (SImode, 3148 plus_constant (stack_pointer_rtx, 3149 lp_slot))); 3150 lp_temp = REGSAVE_CONTROL_TEMP; 3151 } 3152 3153 3154 add_constant (SP_REGNO, SP_REGNO, sp_offset, 0); 3155 3156 if (crtl->calls_eh_return && mep_prevent_lp_restore) 3157 emit_insn (gen_addsi3 (gen_rtx_REG (SImode, SP_REGNO), 3158 gen_rtx_REG (SImode, SP_REGNO), 3159 cfun->machine->eh_stack_adjust)); 3160 3161 if (mep_sibcall_epilogue) 3162 return; 3163 3164 if (mep_disinterrupt_p ()) 3165 emit_insn (gen_mep_enable_int ()); 3166 3167 if (mep_prevent_lp_restore) 3168 { 3169 emit_jump_insn (gen_eh_return_internal ()); 3170 emit_barrier (); 3171 } 3172 else if (interrupt_handler) 3173 emit_jump_insn (gen_mep_reti ()); 3174 else 3175 emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, lp_temp))); 3176} 3177 3178void 3179mep_expand_eh_return (rtx *operands) 3180{ 3181 if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) != LP_REGNO) 3182 { 3183 rtx ra = gen_rtx_REG (Pmode, LP_REGNO); 3184 emit_move_insn (ra, operands[0]); 3185 operands[0] = ra; 3186 } 3187 3188 emit_insn (gen_eh_epilogue (operands[0])); 3189} 3190 3191void 3192mep_emit_eh_epilogue (rtx *operands ATTRIBUTE_UNUSED) 3193{ 3194 cfun->machine->eh_stack_adjust = gen_rtx_REG (Pmode, 0); 3195 mep_prevent_lp_restore = 1; 3196 mep_expand_epilogue (); 3197 mep_prevent_lp_restore = 0; 3198} 3199 3200void 3201mep_expand_sibcall_epilogue (void) 3202{ 3203 mep_sibcall_epilogue = 1; 3204 mep_expand_epilogue (); 3205 mep_sibcall_epilogue = 0; 3206} 3207 3208static bool 3209mep_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) 3210{ 3211 if (decl == NULL) 3212 return false; 3213 3214 if (mep_section_tag (DECL_RTL (decl)) == 'f') 3215 return false; 3216 3217 /* Can't call to a sibcall from an interrupt or disinterrupt function. */ 3218 if (mep_interrupt_p () || mep_disinterrupt_p ()) 3219 return false; 3220 3221 return true; 3222} 3223 3224rtx 3225mep_return_stackadj_rtx (void) 3226{ 3227 return gen_rtx_REG (SImode, 10); 3228} 3229 3230rtx 3231mep_return_handler_rtx (void) 3232{ 3233 return gen_rtx_REG (SImode, LP_REGNO); 3234} 3235 3236void 3237mep_function_profiler (FILE *file) 3238{ 3239 /* Always right at the beginning of the function. */ 3240 fprintf (file, "\t# mep function profiler\n"); 3241 fprintf (file, "\tadd\t$sp, -8\n"); 3242 fprintf (file, "\tsw\t$0, ($sp)\n"); 3243 fprintf (file, "\tldc\t$0, $lp\n"); 3244 fprintf (file, "\tsw\t$0, 4($sp)\n"); 3245 fprintf (file, "\tbsr\t__mep_mcount\n"); 3246 fprintf (file, "\tlw\t$0, 4($sp)\n"); 3247 fprintf (file, "\tstc\t$0, $lp\n"); 3248 fprintf (file, "\tlw\t$0, ($sp)\n"); 3249 fprintf (file, "\tadd\t$sp, 8\n\n"); 3250} 3251 3252const char * 3253mep_emit_bb_trace_ret (void) 3254{ 3255 fprintf (asm_out_file, "\t# end of block profiling\n"); 3256 fprintf (asm_out_file, "\tadd\t$sp, -8\n"); 3257 fprintf (asm_out_file, "\tsw\t$0, ($sp)\n"); 3258 fprintf (asm_out_file, "\tldc\t$0, $lp\n"); 3259 fprintf (asm_out_file, "\tsw\t$0, 4($sp)\n"); 3260 fprintf (asm_out_file, "\tbsr\t__bb_trace_ret\n"); 3261 fprintf (asm_out_file, "\tlw\t$0, 4($sp)\n"); 3262 fprintf (asm_out_file, "\tstc\t$0, $lp\n"); 3263 fprintf (asm_out_file, "\tlw\t$0, ($sp)\n"); 3264 fprintf (asm_out_file, "\tadd\t$sp, 8\n\n"); 3265 return ""; 3266} 3267 3268#undef SAVE 3269#undef RESTORE 3270 3271/* Operand Printing. */ 3272 3273void 3274mep_print_operand_address (FILE *stream, rtx address) 3275{ 3276 if (GET_CODE (address) == MEM) 3277 address = XEXP (address, 0); 3278 else 3279 /* cf: gcc.dg/asm-4.c. */ 3280 gcc_assert (GET_CODE (address) == REG); 3281 3282 mep_print_operand (stream, address, 0); 3283} 3284 3285static struct 3286{ 3287 char code; 3288 const char *pattern; 3289 const char *format; 3290} 3291const conversions[] = 3292{ 3293 { 0, "r", "0" }, 3294 { 0, "m+ri", "3(2)" }, 3295 { 0, "mr", "(1)" }, 3296 { 0, "ms", "(1)" }, 3297 { 0, "ml", "(1)" }, 3298 { 0, "mLrs", "%lo(3)(2)" }, 3299 { 0, "mLr+si", "%lo(4+5)(2)" }, 3300 { 0, "m+ru2s", "%tpoff(5)(2)" }, 3301 { 0, "m+ru3s", "%sdaoff(5)(2)" }, 3302 { 0, "m+r+u2si", "%tpoff(6+7)(2)" }, 3303 { 0, "m+ru2+si", "%tpoff(6+7)(2)" }, 3304 { 0, "m+r+u3si", "%sdaoff(6+7)(2)" }, 3305 { 0, "m+ru3+si", "%sdaoff(6+7)(2)" }, 3306 { 0, "mi", "(1)" }, 3307 { 0, "m+si", "(2+3)" }, 3308 { 0, "m+li", "(2+3)" }, 3309 { 0, "i", "0" }, 3310 { 0, "s", "0" }, 3311 { 0, "+si", "1+2" }, 3312 { 0, "+u2si", "%tpoff(3+4)" }, 3313 { 0, "+u3si", "%sdaoff(3+4)" }, 3314 { 0, "l", "0" }, 3315 { 'b', "i", "0" }, 3316 { 'B', "i", "0" }, 3317 { 'U', "i", "0" }, 3318 { 'h', "i", "0" }, 3319 { 'h', "Hs", "%hi(1)" }, 3320 { 'I', "i", "0" }, 3321 { 'I', "u2s", "%tpoff(2)" }, 3322 { 'I', "u3s", "%sdaoff(2)" }, 3323 { 'I', "+u2si", "%tpoff(3+4)" }, 3324 { 'I', "+u3si", "%sdaoff(3+4)" }, 3325 { 'J', "i", "0" }, 3326 { 'P', "mr", "(1\\+),\\0" }, 3327 { 'x', "i", "0" }, 3328 { 0, 0, 0 } 3329}; 3330 3331static int 3332unique_bit_in (HOST_WIDE_INT i) 3333{ 3334 switch (i & 0xff) 3335 { 3336 case 0x01: case 0xfe: return 0; 3337 case 0x02: case 0xfd: return 1; 3338 case 0x04: case 0xfb: return 2; 3339 case 0x08: case 0xf7: return 3; 3340 case 0x10: case 0x7f: return 4; 3341 case 0x20: case 0xbf: return 5; 3342 case 0x40: case 0xdf: return 6; 3343 case 0x80: case 0xef: return 7; 3344 default: 3345 gcc_unreachable (); 3346 } 3347} 3348 3349static int 3350bit_size_for_clip (HOST_WIDE_INT i) 3351{ 3352 int rv; 3353 3354 for (rv = 0; rv < 31; rv ++) 3355 if (((HOST_WIDE_INT) 1 << rv) > i) 3356 return rv + 1; 3357 gcc_unreachable (); 3358} 3359 3360/* Print an operand to a assembler instruction. */ 3361 3362void 3363mep_print_operand (FILE *file, rtx x, int code) 3364{ 3365 int i, j; 3366 const char *real_name; 3367 3368 if (code == '<') 3369 { 3370 /* Print a mnemonic to do CR <- CR moves. Find out which intrinsic 3371 we're using, then skip over the "mep_" part of its name. */ 3372 const struct cgen_insn *insn; 3373 3374 if (mep_get_move_insn (mep_cmov, &insn)) 3375 fputs (cgen_intrinsics[insn->intrinsic] + 4, file); 3376 else 3377 mep_intrinsic_unavailable (mep_cmov); 3378 return; 3379 } 3380 if (code == 'L') 3381 { 3382 switch (GET_CODE (x)) 3383 { 3384 case AND: 3385 fputs ("clr", file); 3386 return; 3387 case IOR: 3388 fputs ("set", file); 3389 return; 3390 case XOR: 3391 fputs ("not", file); 3392 return; 3393 default: 3394 output_operand_lossage ("invalid %%L code"); 3395 } 3396 } 3397 if (code == 'M') 3398 { 3399 /* Print the second operand of a CR <- CR move. If we're using 3400 a two-operand instruction (i.e., a real cmov), then just print 3401 the operand normally. If we're using a "reg, reg, immediate" 3402 instruction such as caddi3, print the operand followed by a 3403 zero field. If we're using a three-register instruction, 3404 print the operand twice. */ 3405 const struct cgen_insn *insn; 3406 3407 mep_print_operand (file, x, 0); 3408 if (mep_get_move_insn (mep_cmov, &insn) 3409 && insn_data[insn->icode].n_operands == 3) 3410 { 3411 fputs (", ", file); 3412 if (insn_data[insn->icode].operand[2].predicate (x, VOIDmode)) 3413 mep_print_operand (file, x, 0); 3414 else 3415 mep_print_operand (file, const0_rtx, 0); 3416 } 3417 return; 3418 } 3419 3420 encode_pattern (x); 3421 for (i = 0; conversions[i].pattern; i++) 3422 if (conversions[i].code == code 3423 && strcmp(conversions[i].pattern, pattern) == 0) 3424 { 3425 for (j = 0; conversions[i].format[j]; j++) 3426 if (conversions[i].format[j] == '\\') 3427 { 3428 fputc (conversions[i].format[j+1], file); 3429 j++; 3430 } 3431 else if (ISDIGIT(conversions[i].format[j])) 3432 { 3433 rtx r = patternr[conversions[i].format[j] - '0']; 3434 switch (GET_CODE (r)) 3435 { 3436 case REG: 3437 fprintf (file, "%s", reg_names [REGNO (r)]); 3438 break; 3439 case CONST_INT: 3440 switch (code) 3441 { 3442 case 'b': 3443 fprintf (file, "%d", unique_bit_in (INTVAL (r))); 3444 break; 3445 case 'B': 3446 fprintf (file, "%d", bit_size_for_clip (INTVAL (r))); 3447 break; 3448 case 'h': 3449 fprintf (file, "0x%x", ((int) INTVAL (r) >> 16) & 0xffff); 3450 break; 3451 case 'U': 3452 fprintf (file, "%d", bit_size_for_clip (INTVAL (r)) - 1); 3453 break; 3454 case 'J': 3455 fprintf (file, "0x%x", (int) INTVAL (r) & 0xffff); 3456 break; 3457 case 'x': 3458 if (INTVAL (r) & ~(HOST_WIDE_INT)0xff 3459 && !(INTVAL (r) & 0xff)) 3460 fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL(r)); 3461 else 3462 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r)); 3463 break; 3464 case 'I': 3465 if (INTVAL (r) & ~(HOST_WIDE_INT)0xff 3466 && conversions[i].format[j+1] == 0) 3467 { 3468 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (r)); 3469 fprintf (file, " # 0x%x", (int) INTVAL(r) & 0xffff); 3470 } 3471 else 3472 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r)); 3473 break; 3474 default: 3475 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL(r)); 3476 break; 3477 } 3478 break; 3479 case CONST_DOUBLE: 3480 fprintf(file, "[const_double 0x%lx]", 3481 (unsigned long) CONST_DOUBLE_HIGH(r)); 3482 break; 3483 case SYMBOL_REF: 3484 real_name = TARGET_STRIP_NAME_ENCODING (XSTR (r, 0)); 3485 assemble_name (file, real_name); 3486 break; 3487 case LABEL_REF: 3488 output_asm_label (r); 3489 break; 3490 default: 3491 fprintf (stderr, "don't know how to print this operand:"); 3492 debug_rtx (r); 3493 gcc_unreachable (); 3494 } 3495 } 3496 else 3497 { 3498 if (conversions[i].format[j] == '+' 3499 && (!code || code == 'I') 3500 && ISDIGIT (conversions[i].format[j+1]) 3501 && GET_CODE (patternr[conversions[i].format[j+1] - '0']) == CONST_INT 3502 && INTVAL (patternr[conversions[i].format[j+1] - '0']) < 0) 3503 continue; 3504 fputc(conversions[i].format[j], file); 3505 } 3506 break; 3507 } 3508 if (!conversions[i].pattern) 3509 { 3510 error ("unconvertible operand %c %qs", code?code:'-', pattern); 3511 debug_rtx(x); 3512 } 3513 3514 return; 3515} 3516 3517void 3518mep_final_prescan_insn (rtx insn, rtx *operands ATTRIBUTE_UNUSED, 3519 int noperands ATTRIBUTE_UNUSED) 3520{ 3521 /* Despite the fact that MeP is perfectly capable of branching and 3522 doing something else in the same bundle, gcc does jump 3523 optimization *after* scheduling, so we cannot trust the bundling 3524 flags on jump instructions. */ 3525 if (GET_MODE (insn) == BImode 3526 && get_attr_slots (insn) != SLOTS_CORE) 3527 fputc ('+', asm_out_file); 3528} 3529 3530/* Function args in registers. */ 3531 3532static void 3533mep_setup_incoming_varargs (CUMULATIVE_ARGS *cum, 3534 enum machine_mode mode ATTRIBUTE_UNUSED, 3535 tree type ATTRIBUTE_UNUSED, int *pretend_size, 3536 int second_time ATTRIBUTE_UNUSED) 3537{ 3538 int nsave = 4 - (cum->nregs + 1); 3539 3540 if (nsave > 0) 3541 cfun->machine->arg_regs_to_save = nsave; 3542 *pretend_size = nsave * 4; 3543} 3544 3545static int 3546bytesize (const_tree type, enum machine_mode mode) 3547{ 3548 if (mode == BLKmode) 3549 return int_size_in_bytes (type); 3550 return GET_MODE_SIZE (mode); 3551} 3552 3553static rtx 3554mep_expand_builtin_saveregs (void) 3555{ 3556 int bufsize, i, ns; 3557 rtx regbuf; 3558 3559 ns = cfun->machine->arg_regs_to_save; 3560 if (TARGET_IVC2) 3561 { 3562 bufsize = 8 * ((ns + 1) / 2) + 8 * ns; 3563 regbuf = assign_stack_local (SImode, bufsize, 64); 3564 } 3565 else 3566 { 3567 bufsize = ns * 4; 3568 regbuf = assign_stack_local (SImode, bufsize, 32); 3569 } 3570 3571 move_block_from_reg (5-ns, regbuf, ns); 3572 3573 if (TARGET_IVC2) 3574 { 3575 rtx tmp = gen_rtx_MEM (DImode, XEXP (regbuf, 0)); 3576 int ofs = 8 * ((ns+1)/2); 3577 3578 for (i=0; i<ns; i++) 3579 { 3580 int rn = (4-ns) + i + 49; 3581 rtx ptr; 3582 3583 ptr = offset_address (tmp, GEN_INT (ofs), 2); 3584 emit_move_insn (ptr, gen_rtx_REG (DImode, rn)); 3585 ofs += 8; 3586 } 3587 } 3588 return XEXP (regbuf, 0); 3589} 3590 3591#define VECTOR_TYPE_P(t) (TREE_CODE(t) == VECTOR_TYPE) 3592 3593static tree 3594mep_build_builtin_va_list (void) 3595{ 3596 tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack; 3597 tree record; 3598 3599 3600 record = (*lang_hooks.types.make_type) (RECORD_TYPE); 3601 3602 f_next_gp = build_decl (BUILTINS_LOCATION, FIELD_DECL, 3603 get_identifier ("__va_next_gp"), ptr_type_node); 3604 f_next_gp_limit = build_decl (BUILTINS_LOCATION, FIELD_DECL, 3605 get_identifier ("__va_next_gp_limit"), 3606 ptr_type_node); 3607 f_next_cop = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("__va_next_cop"), 3608 ptr_type_node); 3609 f_next_stack = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("__va_next_stack"), 3610 ptr_type_node); 3611 3612 DECL_FIELD_CONTEXT (f_next_gp) = record; 3613 DECL_FIELD_CONTEXT (f_next_gp_limit) = record; 3614 DECL_FIELD_CONTEXT (f_next_cop) = record; 3615 DECL_FIELD_CONTEXT (f_next_stack) = record; 3616 3617 TYPE_FIELDS (record) = f_next_gp; 3618 TREE_CHAIN (f_next_gp) = f_next_gp_limit; 3619 TREE_CHAIN (f_next_gp_limit) = f_next_cop; 3620 TREE_CHAIN (f_next_cop) = f_next_stack; 3621 3622 layout_type (record); 3623 3624 return record; 3625} 3626 3627static void 3628mep_expand_va_start (tree valist, rtx nextarg) 3629{ 3630 tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack; 3631 tree next_gp, next_gp_limit, next_cop, next_stack; 3632 tree t, u; 3633 int ns; 3634 3635 ns = cfun->machine->arg_regs_to_save; 3636 3637 f_next_gp = TYPE_FIELDS (va_list_type_node); 3638 f_next_gp_limit = TREE_CHAIN (f_next_gp); 3639 f_next_cop = TREE_CHAIN (f_next_gp_limit); 3640 f_next_stack = TREE_CHAIN (f_next_cop); 3641 3642 next_gp = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp), valist, f_next_gp, 3643 NULL_TREE); 3644 next_gp_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp_limit), 3645 valist, f_next_gp_limit, NULL_TREE); 3646 next_cop = build3 (COMPONENT_REF, TREE_TYPE (f_next_cop), valist, f_next_cop, 3647 NULL_TREE); 3648 next_stack = build3 (COMPONENT_REF, TREE_TYPE (f_next_stack), 3649 valist, f_next_stack, NULL_TREE); 3650 3651 /* va_list.next_gp = expand_builtin_saveregs (); */ 3652 u = make_tree (sizetype, expand_builtin_saveregs ()); 3653 u = fold_convert (ptr_type_node, u); 3654 t = build2 (MODIFY_EXPR, ptr_type_node, next_gp, u); 3655 TREE_SIDE_EFFECTS (t) = 1; 3656 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 3657 3658 /* va_list.next_gp_limit = va_list.next_gp + 4 * ns; */ 3659 u = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, u, 3660 size_int (4 * ns)); 3661 t = build2 (MODIFY_EXPR, ptr_type_node, next_gp_limit, u); 3662 TREE_SIDE_EFFECTS (t) = 1; 3663 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 3664 3665 u = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, u, 3666 size_int (8 * ((ns+1)/2))); 3667 /* va_list.next_cop = ROUND_UP(va_list.next_gp_limit,8); */ 3668 t = build2 (MODIFY_EXPR, ptr_type_node, next_cop, u); 3669 TREE_SIDE_EFFECTS (t) = 1; 3670 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 3671 3672 /* va_list.next_stack = nextarg; */ 3673 u = make_tree (ptr_type_node, nextarg); 3674 t = build2 (MODIFY_EXPR, ptr_type_node, next_stack, u); 3675 TREE_SIDE_EFFECTS (t) = 1; 3676 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 3677} 3678 3679static tree 3680mep_gimplify_va_arg_expr (tree valist, tree type, 3681 gimple_seq *pre_p, 3682 gimple_seq *post_p ATTRIBUTE_UNUSED) 3683{ 3684 HOST_WIDE_INT size, rsize; 3685 bool by_reference, ivc2_vec; 3686 tree f_next_gp, f_next_gp_limit, f_next_cop, f_next_stack; 3687 tree next_gp, next_gp_limit, next_cop, next_stack; 3688 tree label_sover, label_selse; 3689 tree tmp, res_addr; 3690 3691 ivc2_vec = TARGET_IVC2 && VECTOR_TYPE_P (type); 3692 3693 size = int_size_in_bytes (type); 3694 by_reference = (size > (ivc2_vec ? 8 : 4)) || (size <= 0); 3695 3696 if (by_reference) 3697 { 3698 type = build_pointer_type (type); 3699 size = 4; 3700 } 3701 rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD; 3702 3703 f_next_gp = TYPE_FIELDS (va_list_type_node); 3704 f_next_gp_limit = TREE_CHAIN (f_next_gp); 3705 f_next_cop = TREE_CHAIN (f_next_gp_limit); 3706 f_next_stack = TREE_CHAIN (f_next_cop); 3707 3708 next_gp = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp), valist, f_next_gp, 3709 NULL_TREE); 3710 next_gp_limit = build3 (COMPONENT_REF, TREE_TYPE (f_next_gp_limit), 3711 valist, f_next_gp_limit, NULL_TREE); 3712 next_cop = build3 (COMPONENT_REF, TREE_TYPE (f_next_cop), valist, f_next_cop, 3713 NULL_TREE); 3714 next_stack = build3 (COMPONENT_REF, TREE_TYPE (f_next_stack), 3715 valist, f_next_stack, NULL_TREE); 3716 3717 /* if f_next_gp < f_next_gp_limit 3718 IF (VECTOR_P && IVC2) 3719 val = *f_next_cop; 3720 ELSE 3721 val = *f_next_gp; 3722 f_next_gp += 4; 3723 f_next_cop += 8; 3724 else 3725 label_selse: 3726 val = *f_next_stack; 3727 f_next_stack += rsize; 3728 label_sover: 3729 */ 3730 3731 label_sover = create_artificial_label (UNKNOWN_LOCATION); 3732 label_selse = create_artificial_label (UNKNOWN_LOCATION); 3733 res_addr = create_tmp_var (ptr_type_node, NULL); 3734 3735 tmp = build2 (GE_EXPR, boolean_type_node, next_gp, 3736 unshare_expr (next_gp_limit)); 3737 tmp = build3 (COND_EXPR, void_type_node, tmp, 3738 build1 (GOTO_EXPR, void_type_node, 3739 unshare_expr (label_selse)), 3740 NULL_TREE); 3741 gimplify_and_add (tmp, pre_p); 3742 3743 if (ivc2_vec) 3744 { 3745 tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, next_cop); 3746 gimplify_and_add (tmp, pre_p); 3747 } 3748 else 3749 { 3750 tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, next_gp); 3751 gimplify_and_add (tmp, pre_p); 3752 } 3753 3754 tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, 3755 unshare_expr (next_gp), size_int (4)); 3756 gimplify_assign (unshare_expr (next_gp), tmp, pre_p); 3757 3758 tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, 3759 unshare_expr (next_cop), size_int (8)); 3760 gimplify_assign (unshare_expr (next_cop), tmp, pre_p); 3761 3762 tmp = build1 (GOTO_EXPR, void_type_node, unshare_expr (label_sover)); 3763 gimplify_and_add (tmp, pre_p); 3764 3765 /* - - */ 3766 3767 tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (label_selse)); 3768 gimplify_and_add (tmp, pre_p); 3769 3770 tmp = build2 (MODIFY_EXPR, void_type_node, res_addr, unshare_expr (next_stack)); 3771 gimplify_and_add (tmp, pre_p); 3772 3773 tmp = build2 (POINTER_PLUS_EXPR, ptr_type_node, 3774 unshare_expr (next_stack), size_int (rsize)); 3775 gimplify_assign (unshare_expr (next_stack), tmp, pre_p); 3776 3777 /* - - */ 3778 3779 tmp = build1 (LABEL_EXPR, void_type_node, unshare_expr (label_sover)); 3780 gimplify_and_add (tmp, pre_p); 3781 3782 res_addr = fold_convert (build_pointer_type (type), res_addr); 3783 3784 if (by_reference) 3785 res_addr = build_va_arg_indirect_ref (res_addr); 3786 3787 return build_va_arg_indirect_ref (res_addr); 3788} 3789 3790void 3791mep_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype, 3792 rtx libname ATTRIBUTE_UNUSED, 3793 tree fndecl ATTRIBUTE_UNUSED) 3794{ 3795 pcum->nregs = 0; 3796 3797 if (fntype && lookup_attribute ("vliw", TYPE_ATTRIBUTES (fntype))) 3798 pcum->vliw = 1; 3799 else 3800 pcum->vliw = 0; 3801} 3802 3803rtx 3804mep_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, 3805 tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED) 3806{ 3807 /* VOIDmode is a signal for the backend to pass data to the call 3808 expander via the second operand to the call pattern. We use 3809 this to determine whether to use "jsr" or "jsrv". */ 3810 if (mode == VOIDmode) 3811 return GEN_INT (cum.vliw); 3812 3813 /* If we havn't run out of argument registers, return the next. */ 3814 if (cum.nregs < 4) 3815 { 3816 if (type && TARGET_IVC2 && VECTOR_TYPE_P (type)) 3817 return gen_rtx_REG (mode, cum.nregs + 49); 3818 else 3819 return gen_rtx_REG (mode, cum.nregs + 1); 3820 } 3821 3822 /* Otherwise the argument goes on the stack. */ 3823 return NULL_RTX; 3824} 3825 3826static bool 3827mep_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED, 3828 enum machine_mode mode, 3829 const_tree type, 3830 bool named ATTRIBUTE_UNUSED) 3831{ 3832 int size = bytesize (type, mode); 3833 3834 /* This is non-obvious, but yes, large values passed after we've run 3835 out of registers are *still* passed by reference - we put the 3836 address of the parameter on the stack, as well as putting the 3837 parameter itself elsewhere on the stack. */ 3838 3839 if (size <= 0 || size > 8) 3840 return true; 3841 if (size <= 4) 3842 return false; 3843 if (TARGET_IVC2 && cum->nregs < 4 && type != NULL_TREE && VECTOR_TYPE_P (type)) 3844 return false; 3845 return true; 3846} 3847 3848void 3849mep_arg_advance (CUMULATIVE_ARGS *pcum, 3850 enum machine_mode mode ATTRIBUTE_UNUSED, 3851 tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED) 3852{ 3853 pcum->nregs += 1; 3854} 3855 3856bool 3857mep_return_in_memory (const_tree type, const_tree decl ATTRIBUTE_UNUSED) 3858{ 3859 int size = bytesize (type, BLKmode); 3860 if (TARGET_IVC2 && VECTOR_TYPE_P (type)) 3861 return size > 0 && size <= 8 ? 0 : 1; 3862 return size > 0 && size <= 4 ? 0 : 1; 3863} 3864 3865static bool 3866mep_narrow_volatile_bitfield (void) 3867{ 3868 return true; 3869 return false; 3870} 3871 3872/* Implement FUNCTION_VALUE. All values are returned in $0. */ 3873 3874rtx 3875mep_function_value (tree type, tree func ATTRIBUTE_UNUSED) 3876{ 3877 if (TARGET_IVC2 && VECTOR_TYPE_P (type)) 3878 return gen_rtx_REG (TYPE_MODE (type), 48); 3879 return gen_rtx_REG (TYPE_MODE (type), RETURN_VALUE_REGNUM); 3880} 3881 3882/* Implement LIBCALL_VALUE, using the same rules as mep_function_value. */ 3883 3884rtx 3885mep_libcall_value (enum machine_mode mode) 3886{ 3887 return gen_rtx_REG (mode, RETURN_VALUE_REGNUM); 3888} 3889 3890/* Handle pipeline hazards. */ 3891 3892typedef enum { op_none, op_stc, op_fsft, op_ret } op_num; 3893static const char *opnames[] = { "", "stc", "fsft", "ret" }; 3894 3895static int prev_opcode = 0; 3896 3897/* This isn't as optimal as it could be, because we don't know what 3898 control register the STC opcode is storing in. We only need to add 3899 the nop if it's the relevent register, but we add it for irrelevent 3900 registers also. */ 3901 3902void 3903mep_asm_output_opcode (FILE *file, const char *ptr) 3904{ 3905 int this_opcode = op_none; 3906 const char *hazard = 0; 3907 3908 switch (*ptr) 3909 { 3910 case 'f': 3911 if (strncmp (ptr, "fsft", 4) == 0 && !ISGRAPH (ptr[4])) 3912 this_opcode = op_fsft; 3913 break; 3914 case 'r': 3915 if (strncmp (ptr, "ret", 3) == 0 && !ISGRAPH (ptr[3])) 3916 this_opcode = op_ret; 3917 break; 3918 case 's': 3919 if (strncmp (ptr, "stc", 3) == 0 && !ISGRAPH (ptr[3])) 3920 this_opcode = op_stc; 3921 break; 3922 } 3923 3924 if (prev_opcode == op_stc && this_opcode == op_fsft) 3925 hazard = "nop"; 3926 if (prev_opcode == op_stc && this_opcode == op_ret) 3927 hazard = "nop"; 3928 3929 if (hazard) 3930 fprintf(file, "%s\t# %s-%s hazard\n\t", 3931 hazard, opnames[prev_opcode], opnames[this_opcode]); 3932 3933 prev_opcode = this_opcode; 3934} 3935 3936/* Handle attributes. */ 3937 3938static tree 3939mep_validate_based_tiny (tree *node, tree name, tree args, 3940 int flags ATTRIBUTE_UNUSED, bool *no_add) 3941{ 3942 if (TREE_CODE (*node) != VAR_DECL 3943 && TREE_CODE (*node) != POINTER_TYPE 3944 && TREE_CODE (*node) != TYPE_DECL) 3945 { 3946 warning (0, "%qE attribute only applies to variables", name); 3947 *no_add = true; 3948 } 3949 else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL) 3950 { 3951 if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node))) 3952 { 3953 warning (0, "address region attributes not allowed with auto storage class"); 3954 *no_add = true; 3955 } 3956 /* Ignore storage attribute of pointed to variable: char __far * x; */ 3957 if (TREE_TYPE (*node) && TREE_CODE (TREE_TYPE (*node)) == POINTER_TYPE) 3958 { 3959 warning (0, "address region attributes on pointed-to types ignored"); 3960 *no_add = true; 3961 } 3962 } 3963 3964 return NULL_TREE; 3965} 3966 3967static int 3968mep_multiple_address_regions (tree list, bool check_section_attr) 3969{ 3970 tree a; 3971 int count_sections = 0; 3972 int section_attr_count = 0; 3973 3974 for (a = list; a; a = TREE_CHAIN (a)) 3975 { 3976 if (is_attribute_p ("based", TREE_PURPOSE (a)) 3977 || is_attribute_p ("tiny", TREE_PURPOSE (a)) 3978 || is_attribute_p ("near", TREE_PURPOSE (a)) 3979 || is_attribute_p ("far", TREE_PURPOSE (a)) 3980 || is_attribute_p ("io", TREE_PURPOSE (a))) 3981 count_sections ++; 3982 if (check_section_attr) 3983 section_attr_count += is_attribute_p ("section", TREE_PURPOSE (a)); 3984 } 3985 3986 if (check_section_attr) 3987 return section_attr_count; 3988 else 3989 return count_sections; 3990} 3991 3992#define MEP_ATTRIBUTES(decl) \ 3993 (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \ 3994 : DECL_ATTRIBUTES (decl) \ 3995 ? (DECL_ATTRIBUTES (decl)) \ 3996 : TYPE_ATTRIBUTES (TREE_TYPE (decl)) 3997 3998static tree 3999mep_validate_near_far (tree *node, tree name, tree args, 4000 int flags ATTRIBUTE_UNUSED, bool *no_add) 4001{ 4002 if (TREE_CODE (*node) != VAR_DECL 4003 && TREE_CODE (*node) != FUNCTION_DECL 4004 && TREE_CODE (*node) != METHOD_TYPE 4005 && TREE_CODE (*node) != POINTER_TYPE 4006 && TREE_CODE (*node) != TYPE_DECL) 4007 { 4008 warning (0, "%qE attribute only applies to variables and functions", 4009 name); 4010 *no_add = true; 4011 } 4012 else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL) 4013 { 4014 if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node))) 4015 { 4016 warning (0, "address region attributes not allowed with auto storage class"); 4017 *no_add = true; 4018 } 4019 /* Ignore storage attribute of pointed to variable: char __far * x; */ 4020 if (TREE_TYPE (*node) && TREE_CODE (TREE_TYPE (*node)) == POINTER_TYPE) 4021 { 4022 warning (0, "address region attributes on pointed-to types ignored"); 4023 *no_add = true; 4024 } 4025 } 4026 else if (mep_multiple_address_regions (MEP_ATTRIBUTES (*node), false) > 0) 4027 { 4028 warning (0, "duplicate address region attribute %qE in declaration of %qE on line %d", 4029 name, DECL_NAME (*node), DECL_SOURCE_LINE (*node)); 4030 DECL_ATTRIBUTES (*node) = NULL_TREE; 4031 } 4032 return NULL_TREE; 4033} 4034 4035static tree 4036mep_validate_disinterrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED, 4037 int flags ATTRIBUTE_UNUSED, bool *no_add) 4038{ 4039 if (TREE_CODE (*node) != FUNCTION_DECL 4040 && TREE_CODE (*node) != METHOD_TYPE) 4041 { 4042 warning (0, "%qE attribute only applies to functions", name); 4043 *no_add = true; 4044 } 4045 return NULL_TREE; 4046} 4047 4048static tree 4049mep_validate_interrupt (tree *node, tree name, tree args ATTRIBUTE_UNUSED, 4050 int flags ATTRIBUTE_UNUSED, bool *no_add) 4051{ 4052 tree function_type; 4053 4054 if (TREE_CODE (*node) != FUNCTION_DECL) 4055 { 4056 warning (0, "%qE attribute only applies to functions", name); 4057 *no_add = true; 4058 return NULL_TREE; 4059 } 4060 4061 if (DECL_DECLARED_INLINE_P (*node)) 4062 error ("cannot inline interrupt function %qE", DECL_NAME (*node)); 4063 DECL_UNINLINABLE (*node) = 1; 4064 4065 function_type = TREE_TYPE (*node); 4066 4067 if (TREE_TYPE (function_type) != void_type_node) 4068 error ("interrupt function must have return type of void"); 4069 4070 if (TYPE_ARG_TYPES (function_type) 4071 && (TREE_VALUE (TYPE_ARG_TYPES (function_type)) != void_type_node 4072 || TREE_CHAIN (TYPE_ARG_TYPES (function_type)) != NULL_TREE)) 4073 error ("interrupt function must have no arguments"); 4074 4075 return NULL_TREE; 4076} 4077 4078static tree 4079mep_validate_io_cb (tree *node, tree name, tree args, 4080 int flags ATTRIBUTE_UNUSED, bool *no_add) 4081{ 4082 if (TREE_CODE (*node) != VAR_DECL) 4083 { 4084 warning (0, "%qE attribute only applies to variables", name); 4085 *no_add = true; 4086 } 4087 4088 if (args != NULL_TREE) 4089 { 4090 if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR) 4091 TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0); 4092 if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST) 4093 { 4094 warning (0, "%qE attribute allows only an integer constant argument", 4095 name); 4096 *no_add = true; 4097 } 4098 } 4099 4100 if (*no_add == false && !TARGET_IO_NO_VOLATILE) 4101 TREE_THIS_VOLATILE (*node) = 1; 4102 4103 return NULL_TREE; 4104} 4105 4106static tree 4107mep_validate_vliw (tree *node, tree name, tree args ATTRIBUTE_UNUSED, 4108 int flags ATTRIBUTE_UNUSED, bool *no_add) 4109{ 4110 if (TREE_CODE (*node) != FUNCTION_TYPE 4111 && TREE_CODE (*node) != FUNCTION_DECL 4112 && TREE_CODE (*node) != METHOD_TYPE 4113 && TREE_CODE (*node) != FIELD_DECL 4114 && TREE_CODE (*node) != TYPE_DECL) 4115 { 4116 static int gave_pointer_note = 0; 4117 static int gave_array_note = 0; 4118 static const char * given_type = NULL; 4119 4120 given_type = tree_code_name[TREE_CODE (*node)]; 4121 if (TREE_CODE (*node) == POINTER_TYPE) 4122 given_type = "pointers"; 4123 if (TREE_CODE (*node) == ARRAY_TYPE) 4124 given_type = "arrays"; 4125 4126 if (given_type) 4127 warning (0, "%qE attribute only applies to functions, not %s", 4128 name, given_type); 4129 else 4130 warning (0, "%qE attribute only applies to functions", 4131 name); 4132 *no_add = true; 4133 4134 if (TREE_CODE (*node) == POINTER_TYPE 4135 && !gave_pointer_note) 4136 { 4137 inform (input_location, "To describe a pointer to a VLIW function, use syntax like this:"); 4138 inform (input_location, " typedef int (__vliw *vfuncptr) ();"); 4139 gave_pointer_note = 1; 4140 } 4141 4142 if (TREE_CODE (*node) == ARRAY_TYPE 4143 && !gave_array_note) 4144 { 4145 inform (input_location, "To describe an array of VLIW function pointers, use syntax like this:"); 4146 inform (input_location, " typedef int (__vliw *vfuncptr[]) ();"); 4147 gave_array_note = 1; 4148 } 4149 } 4150 if (!TARGET_VLIW) 4151 error ("VLIW functions are not allowed without a VLIW configuration"); 4152 return NULL_TREE; 4153} 4154 4155static const struct attribute_spec mep_attribute_table[11] = 4156{ 4157 /* name min max decl type func handler */ 4158 { "based", 0, 0, false, false, false, mep_validate_based_tiny }, 4159 { "tiny", 0, 0, false, false, false, mep_validate_based_tiny }, 4160 { "near", 0, 0, false, false, false, mep_validate_near_far }, 4161 { "far", 0, 0, false, false, false, mep_validate_near_far }, 4162 { "disinterrupt", 0, 0, false, false, false, mep_validate_disinterrupt }, 4163 { "interrupt", 0, 0, false, false, false, mep_validate_interrupt }, 4164 { "io", 0, 1, false, false, false, mep_validate_io_cb }, 4165 { "cb", 0, 1, false, false, false, mep_validate_io_cb }, 4166 { "vliw", 0, 0, false, true, false, mep_validate_vliw }, 4167 { NULL, 0, 0, false, false, false, NULL } 4168}; 4169 4170static bool 4171mep_function_attribute_inlinable_p (const_tree callee) 4172{ 4173 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (callee)); 4174 if (!attrs) attrs = DECL_ATTRIBUTES (callee); 4175 return (lookup_attribute ("disinterrupt", attrs) == 0 4176 && lookup_attribute ("interrupt", attrs) == 0); 4177} 4178 4179static bool 4180mep_can_inline_p (tree caller, tree callee) 4181{ 4182 if (TREE_CODE (callee) == ADDR_EXPR) 4183 callee = TREE_OPERAND (callee, 0); 4184 4185 if (!mep_vliw_function_p (caller) 4186 && mep_vliw_function_p (callee)) 4187 { 4188 return false; 4189 } 4190 return true; 4191} 4192 4193#define FUNC_CALL 1 4194#define FUNC_DISINTERRUPT 2 4195 4196 4197struct GTY(()) pragma_entry { 4198 int used; 4199 int flag; 4200 const char *funcname; 4201}; 4202typedef struct pragma_entry pragma_entry; 4203 4204/* Hash table of farcall-tagged sections. */ 4205static GTY((param_is (pragma_entry))) htab_t pragma_htab; 4206 4207static int 4208pragma_entry_eq (const void *p1, const void *p2) 4209{ 4210 const pragma_entry *old = (const pragma_entry *) p1; 4211 const char *new_name = (const char *) p2; 4212 4213 return strcmp (old->funcname, new_name) == 0; 4214} 4215 4216static hashval_t 4217pragma_entry_hash (const void *p) 4218{ 4219 const pragma_entry *old = (const pragma_entry *) p; 4220 return htab_hash_string (old->funcname); 4221} 4222 4223static void 4224mep_note_pragma_flag (const char *funcname, int flag) 4225{ 4226 pragma_entry **slot; 4227 4228 if (!pragma_htab) 4229 pragma_htab = htab_create_ggc (31, pragma_entry_hash, 4230 pragma_entry_eq, NULL); 4231 4232 slot = (pragma_entry **) 4233 htab_find_slot_with_hash (pragma_htab, funcname, 4234 htab_hash_string (funcname), INSERT); 4235 4236 if (!*slot) 4237 { 4238 *slot = GGC_NEW (pragma_entry); 4239 (*slot)->flag = 0; 4240 (*slot)->used = 0; 4241 (*slot)->funcname = ggc_strdup (funcname); 4242 } 4243 (*slot)->flag |= flag; 4244} 4245 4246static bool 4247mep_lookup_pragma_flag (const char *funcname, int flag) 4248{ 4249 pragma_entry **slot; 4250 4251 if (!pragma_htab) 4252 return false; 4253 4254 if (funcname[0] == '@' && funcname[2] == '.') 4255 funcname += 3; 4256 4257 slot = (pragma_entry **) 4258 htab_find_slot_with_hash (pragma_htab, funcname, 4259 htab_hash_string (funcname), NO_INSERT); 4260 if (slot && *slot && ((*slot)->flag & flag)) 4261 { 4262 (*slot)->used |= flag; 4263 return true; 4264 } 4265 return false; 4266} 4267 4268bool 4269mep_lookup_pragma_call (const char *funcname) 4270{ 4271 return mep_lookup_pragma_flag (funcname, FUNC_CALL); 4272} 4273 4274void 4275mep_note_pragma_call (const char *funcname) 4276{ 4277 mep_note_pragma_flag (funcname, FUNC_CALL); 4278} 4279 4280bool 4281mep_lookup_pragma_disinterrupt (const char *funcname) 4282{ 4283 return mep_lookup_pragma_flag (funcname, FUNC_DISINTERRUPT); 4284} 4285 4286void 4287mep_note_pragma_disinterrupt (const char *funcname) 4288{ 4289 mep_note_pragma_flag (funcname, FUNC_DISINTERRUPT); 4290} 4291 4292static int 4293note_unused_pragma_disinterrupt (void **slot, void *data ATTRIBUTE_UNUSED) 4294{ 4295 const pragma_entry *d = (const pragma_entry *)(*slot); 4296 4297 if ((d->flag & FUNC_DISINTERRUPT) 4298 && !(d->used & FUNC_DISINTERRUPT)) 4299 warning (0, "\"#pragma disinterrupt %s\" not used", d->funcname); 4300 return 1; 4301} 4302 4303void 4304mep_file_cleanups (void) 4305{ 4306 if (pragma_htab) 4307 htab_traverse (pragma_htab, note_unused_pragma_disinterrupt, NULL); 4308} 4309 4310 4311static int 4312mep_attrlist_to_encoding (tree list, tree decl) 4313{ 4314 if (mep_multiple_address_regions (list, false) > 1) 4315 { 4316 warning (0, "duplicate address region attribute %qE in declaration of %qE on line %d", 4317 TREE_PURPOSE (TREE_CHAIN (list)), 4318 DECL_NAME (decl), 4319 DECL_SOURCE_LINE (decl)); 4320 TREE_CHAIN (list) = NULL_TREE; 4321 } 4322 4323 while (list) 4324 { 4325 if (is_attribute_p ("based", TREE_PURPOSE (list))) 4326 return 'b'; 4327 if (is_attribute_p ("tiny", TREE_PURPOSE (list))) 4328 return 't'; 4329 if (is_attribute_p ("near", TREE_PURPOSE (list))) 4330 return 'n'; 4331 if (is_attribute_p ("far", TREE_PURPOSE (list))) 4332 return 'f'; 4333 if (is_attribute_p ("io", TREE_PURPOSE (list))) 4334 { 4335 if (TREE_VALUE (list) 4336 && TREE_VALUE (TREE_VALUE (list)) 4337 && TREE_CODE (TREE_VALUE (TREE_VALUE (list))) == INTEGER_CST) 4338 { 4339 int location = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE(list))); 4340 if (location >= 0 4341 && location <= 0x1000000) 4342 return 'i'; 4343 } 4344 return 'I'; 4345 } 4346 if (is_attribute_p ("cb", TREE_PURPOSE (list))) 4347 return 'c'; 4348 list = TREE_CHAIN (list); 4349 } 4350 if (TARGET_TF 4351 && TREE_CODE (decl) == FUNCTION_DECL 4352 && DECL_SECTION_NAME (decl) == 0) 4353 return 'f'; 4354 return 0; 4355} 4356 4357static int 4358mep_comp_type_attributes (const_tree t1, const_tree t2) 4359{ 4360 int vliw1, vliw2; 4361 4362 vliw1 = (lookup_attribute ("vliw", TYPE_ATTRIBUTES (t1)) != 0); 4363 vliw2 = (lookup_attribute ("vliw", TYPE_ATTRIBUTES (t2)) != 0); 4364 4365 if (vliw1 != vliw2) 4366 return 0; 4367 4368 return 1; 4369} 4370 4371static void 4372mep_insert_attributes (tree decl, tree *attributes) 4373{ 4374 int size; 4375 const char *secname = 0; 4376 tree attrib, attrlist; 4377 char encoding; 4378 4379 if (TREE_CODE (decl) == FUNCTION_DECL) 4380 { 4381 const char *funcname = IDENTIFIER_POINTER (DECL_NAME (decl)); 4382 4383 if (mep_lookup_pragma_disinterrupt (funcname)) 4384 { 4385 attrib = build_tree_list (get_identifier ("disinterrupt"), NULL_TREE); 4386 *attributes = chainon (*attributes, attrib); 4387 } 4388 } 4389 4390 if (TREE_CODE (decl) != VAR_DECL 4391 || ! (TREE_PUBLIC (decl) || TREE_STATIC (decl) || DECL_EXTERNAL (decl))) 4392 return; 4393 4394 if (TREE_READONLY (decl) && TARGET_DC) 4395 /* -mdc means that const variables default to the near section, 4396 regardless of the size cutoff. */ 4397 return; 4398 4399 /* User specified an attribute, so override the default. 4400 Ignore storage attribute of pointed to variable. char __far * x; */ 4401 if (! (TREE_TYPE (decl) && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)) 4402 { 4403 if (TYPE_P (decl) && TYPE_ATTRIBUTES (decl) && *attributes) 4404 TYPE_ATTRIBUTES (decl) = NULL_TREE; 4405 else if (DECL_ATTRIBUTES (decl) && *attributes) 4406 DECL_ATTRIBUTES (decl) = NULL_TREE; 4407 } 4408 4409 attrlist = *attributes ? *attributes : DECL_ATTRIBUTES (decl); 4410 encoding = mep_attrlist_to_encoding (attrlist, decl); 4411 if (!encoding && TYPE_P (TREE_TYPE (decl))) 4412 { 4413 attrlist = TYPE_ATTRIBUTES (TREE_TYPE (decl)); 4414 encoding = mep_attrlist_to_encoding (attrlist, decl); 4415 } 4416 if (encoding) 4417 { 4418 /* This means that the declaration has a specific section 4419 attribute, so we should not apply the default rules. */ 4420 4421 if (encoding == 'i' || encoding == 'I') 4422 { 4423 tree attr = lookup_attribute ("io", attrlist); 4424 if (attr 4425 && TREE_VALUE (attr) 4426 && TREE_VALUE (TREE_VALUE(attr))) 4427 { 4428 int location = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE(attr))); 4429 static tree previous_value = 0; 4430 static int previous_location = 0; 4431 static tree previous_name = 0; 4432 4433 /* We take advantage of the fact that gcc will reuse the 4434 same tree pointer when applying an attribute to a 4435 list of decls, but produce a new tree for attributes 4436 on separate source lines, even when they're textually 4437 identical. This is the behavior we want. */ 4438 if (TREE_VALUE (attr) == previous_value 4439 && location == previous_location) 4440 { 4441 warning(0, "__io address 0x%x is the same for %qE and %qE", 4442 location, previous_name, DECL_NAME (decl)); 4443 } 4444 previous_name = DECL_NAME (decl); 4445 previous_location = location; 4446 previous_value = TREE_VALUE (attr); 4447 } 4448 } 4449 return; 4450 } 4451 4452 4453 /* Declarations of arrays can change size. Don't trust them. */ 4454 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) 4455 size = 0; 4456 else 4457 size = int_size_in_bytes (TREE_TYPE (decl)); 4458 4459 if (TARGET_RAND_TPGP && size <= 4 && size > 0) 4460 { 4461 if (TREE_PUBLIC (decl) 4462 || DECL_EXTERNAL (decl) 4463 || TREE_STATIC (decl)) 4464 { 4465 const char *name = IDENTIFIER_POINTER (DECL_NAME (decl)); 4466 int key = 0; 4467 4468 while (*name) 4469 key += *name++; 4470 4471 switch (key & 3) 4472 { 4473 case 0: 4474 secname = "based"; 4475 break; 4476 case 1: 4477 secname = "tiny"; 4478 break; 4479 case 2: 4480 secname = "far"; 4481 break; 4482 default: 4483 ; 4484 } 4485 } 4486 } 4487 else 4488 { 4489 if (size <= mep_based_cutoff && size > 0) 4490 secname = "based"; 4491 else if (size <= mep_tiny_cutoff && size > 0) 4492 secname = "tiny"; 4493 else if (TARGET_L) 4494 secname = "far"; 4495 } 4496 4497 if (mep_const_section && TREE_READONLY (decl)) 4498 { 4499 if (strcmp (mep_const_section, "tiny") == 0) 4500 secname = "tiny"; 4501 else if (strcmp (mep_const_section, "near") == 0) 4502 return; 4503 else if (strcmp (mep_const_section, "far") == 0) 4504 secname = "far"; 4505 } 4506 4507 if (!secname) 4508 return; 4509 4510 if (!mep_multiple_address_regions (*attributes, true) 4511 && !mep_multiple_address_regions (DECL_ATTRIBUTES (decl), false)) 4512 { 4513 attrib = build_tree_list (get_identifier (secname), NULL_TREE); 4514 4515 /* Chain the attribute directly onto the variable's DECL_ATTRIBUTES 4516 in order to avoid the POINTER_TYPE bypasses in mep_validate_near_far 4517 and mep_validate_based_tiny. */ 4518 DECL_ATTRIBUTES (decl) = chainon (DECL_ATTRIBUTES (decl), attrib); 4519 } 4520} 4521 4522static void 4523mep_encode_section_info (tree decl, rtx rtl, int first) 4524{ 4525 rtx rtlname; 4526 const char *oldname; 4527 const char *secname; 4528 char encoding; 4529 char *newname; 4530 tree idp; 4531 int maxsize; 4532 tree type; 4533 tree mep_attributes; 4534 4535 if (! first) 4536 return; 4537 4538 if (TREE_CODE (decl) != VAR_DECL 4539 && TREE_CODE (decl) != FUNCTION_DECL) 4540 return; 4541 4542 rtlname = XEXP (rtl, 0); 4543 if (GET_CODE (rtlname) == SYMBOL_REF) 4544 oldname = XSTR (rtlname, 0); 4545 else if (GET_CODE (rtlname) == MEM 4546 && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) 4547 oldname = XSTR (XEXP (rtlname, 0), 0); 4548 else 4549 gcc_unreachable (); 4550 4551 type = TREE_TYPE (decl); 4552 if (type == error_mark_node) 4553 return; 4554 mep_attributes = MEP_ATTRIBUTES (decl); 4555 4556 encoding = mep_attrlist_to_encoding (mep_attributes, decl); 4557 4558 if (encoding) 4559 { 4560 newname = (char *) alloca (strlen (oldname) + 4); 4561 sprintf (newname, "@%c.%s", encoding, oldname); 4562 idp = get_identifier (newname); 4563 XEXP (rtl, 0) = 4564 gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); 4565 SYMBOL_REF_WEAK (XEXP (rtl, 0)) = DECL_WEAK (decl); 4566 SET_SYMBOL_REF_DECL (XEXP (rtl, 0), decl); 4567 4568 switch (encoding) 4569 { 4570 case 'b': 4571 maxsize = 128; 4572 secname = "based"; 4573 break; 4574 case 't': 4575 maxsize = 65536; 4576 secname = "tiny"; 4577 break; 4578 case 'n': 4579 maxsize = 0x1000000; 4580 secname = "near"; 4581 break; 4582 default: 4583 maxsize = 0; 4584 secname = 0; 4585 break; 4586 } 4587 if (maxsize && int_size_in_bytes (TREE_TYPE (decl)) > maxsize) 4588 { 4589 warning (0, "variable %s (%ld bytes) is too large for the %s section (%d bytes)", 4590 oldname, 4591 (long) int_size_in_bytes (TREE_TYPE (decl)), 4592 secname, 4593 maxsize); 4594 } 4595 } 4596} 4597 4598const char * 4599mep_strip_name_encoding (const char *sym) 4600{ 4601 while (1) 4602 { 4603 if (*sym == '*') 4604 sym++; 4605 else if (*sym == '@' && sym[2] == '.') 4606 sym += 3; 4607 else 4608 return sym; 4609 } 4610} 4611 4612static section * 4613mep_select_section (tree decl, int reloc ATTRIBUTE_UNUSED, 4614 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) 4615{ 4616 int readonly = 1; 4617 int encoding; 4618 4619 switch (TREE_CODE (decl)) 4620 { 4621 case VAR_DECL: 4622 if (!TREE_READONLY (decl) 4623 || TREE_SIDE_EFFECTS (decl) 4624 || !DECL_INITIAL (decl) 4625 || (DECL_INITIAL (decl) != error_mark_node 4626 && !TREE_CONSTANT (DECL_INITIAL (decl)))) 4627 readonly = 0; 4628 break; 4629 case CONSTRUCTOR: 4630 if (! TREE_CONSTANT (decl)) 4631 readonly = 0; 4632 break; 4633 4634 default: 4635 break; 4636 } 4637 4638 if (TREE_CODE (decl) == FUNCTION_DECL) 4639 { 4640 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); 4641 4642 if (name[0] == '@' && name[2] == '.') 4643 encoding = name[1]; 4644 else 4645 encoding = 0; 4646 4647 if (flag_function_sections || DECL_ONE_ONLY (decl)) 4648 mep_unique_section (decl, 0); 4649 else if (lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl)))) 4650 { 4651 if (encoding == 'f') 4652 return vftext_section; 4653 else 4654 return vtext_section; 4655 } 4656 else if (encoding == 'f') 4657 return ftext_section; 4658 else 4659 return text_section; 4660 } 4661 4662 if (TREE_CODE (decl) == VAR_DECL) 4663 { 4664 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); 4665 4666 if (name[0] == '@' && name[2] == '.') 4667 switch (name[1]) 4668 { 4669 case 'b': 4670 return based_section; 4671 4672 case 't': 4673 if (readonly) 4674 return srodata_section; 4675 if (DECL_INITIAL (decl)) 4676 return sdata_section; 4677 return tinybss_section; 4678 4679 case 'f': 4680 if (readonly) 4681 return frodata_section; 4682 return far_section; 4683 4684 case 'i': 4685 case 'I': 4686 error_at (DECL_SOURCE_LOCATION (decl), 4687 "variable %D of type %<io%> must be uninitialized", decl); 4688 return data_section; 4689 4690 case 'c': 4691 error_at (DECL_SOURCE_LOCATION (decl), 4692 "variable %D of type %<cb%> must be uninitialized", decl); 4693 return data_section; 4694 } 4695 } 4696 4697 if (readonly) 4698 return readonly_data_section; 4699 4700 return data_section; 4701} 4702 4703static void 4704mep_unique_section (tree decl, int reloc) 4705{ 4706 static const char *prefixes[][2] = 4707 { 4708 { ".text.", ".gnu.linkonce.t." }, 4709 { ".rodata.", ".gnu.linkonce.r." }, 4710 { ".data.", ".gnu.linkonce.d." }, 4711 { ".based.", ".gnu.linkonce.based." }, 4712 { ".sdata.", ".gnu.linkonce.s." }, 4713 { ".far.", ".gnu.linkonce.far." }, 4714 { ".ftext.", ".gnu.linkonce.ft." }, 4715 { ".frodata.", ".gnu.linkonce.frd." }, 4716 { ".srodata.", ".gnu.linkonce.srd." }, 4717 { ".vtext.", ".gnu.linkonce.v." }, 4718 { ".vftext.", ".gnu.linkonce.vf." } 4719 }; 4720 int sec = 2; /* .data */ 4721 int len; 4722 const char *name, *prefix; 4723 char *string; 4724 4725 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 4726 if (DECL_RTL (decl)) 4727 name = XSTR (XEXP (DECL_RTL (decl), 0), 0); 4728 4729 if (TREE_CODE (decl) == FUNCTION_DECL) 4730 { 4731 if (lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl)))) 4732 sec = 9; /* .vtext */ 4733 else 4734 sec = 0; /* .text */ 4735 } 4736 else if (decl_readonly_section (decl, reloc)) 4737 sec = 1; /* .rodata */ 4738 4739 if (name[0] == '@' && name[2] == '.') 4740 { 4741 switch (name[1]) 4742 { 4743 case 'b': 4744 sec = 3; /* .based */ 4745 break; 4746 case 't': 4747 if (sec == 1) 4748 sec = 8; /* .srodata */ 4749 else 4750 sec = 4; /* .sdata */ 4751 break; 4752 case 'f': 4753 if (sec == 0) 4754 sec = 6; /* .ftext */ 4755 else if (sec == 9) 4756 sec = 10; /* .vftext */ 4757 else if (sec == 1) 4758 sec = 7; /* .frodata */ 4759 else 4760 sec = 5; /* .far. */ 4761 break; 4762 } 4763 name += 3; 4764 } 4765 4766 prefix = prefixes[sec][DECL_ONE_ONLY(decl)]; 4767 len = strlen (name) + strlen (prefix); 4768 string = (char *) alloca (len + 1); 4769 4770 sprintf (string, "%s%s", prefix, name); 4771 4772 DECL_SECTION_NAME (decl) = build_string (len, string); 4773} 4774 4775/* Given a decl, a section name, and whether the decl initializer 4776 has relocs, choose attributes for the section. */ 4777 4778#define SECTION_MEP_VLIW SECTION_MACH_DEP 4779 4780static unsigned int 4781mep_section_type_flags (tree decl, const char *name, int reloc) 4782{ 4783 unsigned int flags = default_section_type_flags (decl, name, reloc); 4784 4785 if (decl && TREE_CODE (decl) == FUNCTION_DECL 4786 && lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl)))) 4787 flags |= SECTION_MEP_VLIW; 4788 4789 return flags; 4790} 4791 4792/* Switch to an arbitrary section NAME with attributes as specified 4793 by FLAGS. ALIGN specifies any known alignment requirements for 4794 the section; 0 if the default should be used. 4795 4796 Differs from the standard ELF version only in support of VLIW mode. */ 4797 4798static void 4799mep_asm_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED) 4800{ 4801 char flagchars[8], *f = flagchars; 4802 const char *type; 4803 4804 if (!(flags & SECTION_DEBUG)) 4805 *f++ = 'a'; 4806 if (flags & SECTION_WRITE) 4807 *f++ = 'w'; 4808 if (flags & SECTION_CODE) 4809 *f++ = 'x'; 4810 if (flags & SECTION_SMALL) 4811 *f++ = 's'; 4812 if (flags & SECTION_MEP_VLIW) 4813 *f++ = 'v'; 4814 *f = '\0'; 4815 4816 if (flags & SECTION_BSS) 4817 type = "nobits"; 4818 else 4819 type = "progbits"; 4820 4821 fprintf (asm_out_file, "\t.section\t%s,\"%s\",@%s\n", 4822 name, flagchars, type); 4823 4824 if (flags & SECTION_CODE) 4825 fputs ((flags & SECTION_MEP_VLIW ? "\t.vliw\n" : "\t.core\n"), 4826 asm_out_file); 4827} 4828 4829void 4830mep_output_aligned_common (FILE *stream, tree decl, const char *name, 4831 int size, int align, int global) 4832{ 4833 /* We intentionally don't use mep_section_tag() here. */ 4834 if (name[0] == '@' 4835 && (name[1] == 'i' || name[1] == 'I' || name[1] == 'c') 4836 && name[2] == '.') 4837 { 4838 int location = -1; 4839 tree attr = lookup_attribute ((name[1] == 'c' ? "cb" : "io"), 4840 DECL_ATTRIBUTES (decl)); 4841 if (attr 4842 && TREE_VALUE (attr) 4843 && TREE_VALUE (TREE_VALUE(attr))) 4844 location = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE(attr))); 4845 if (location == -1) 4846 return; 4847 if (global) 4848 { 4849 fprintf (stream, "\t.globl\t"); 4850 assemble_name (stream, name); 4851 fprintf (stream, "\n"); 4852 } 4853 assemble_name (stream, name); 4854 fprintf (stream, " = %d\n", location); 4855 return; 4856 } 4857 if (name[0] == '@' && name[2] == '.') 4858 { 4859 const char *sec = 0; 4860 switch (name[1]) 4861 { 4862 case 'b': 4863 switch_to_section (based_section); 4864 sec = ".based"; 4865 break; 4866 case 't': 4867 switch_to_section (tinybss_section); 4868 sec = ".sbss"; 4869 break; 4870 case 'f': 4871 switch_to_section (farbss_section); 4872 sec = ".farbss"; 4873 break; 4874 } 4875 if (sec) 4876 { 4877 const char *name2; 4878 int p2align = 0; 4879 4880 while (align > BITS_PER_UNIT) 4881 { 4882 align /= 2; 4883 p2align ++; 4884 } 4885 name2 = TARGET_STRIP_NAME_ENCODING (name); 4886 if (global) 4887 fprintf (stream, "\t.globl\t%s\n", name2); 4888 fprintf (stream, "\t.p2align %d\n", p2align); 4889 fprintf (stream, "\t.type\t%s,@object\n", name2); 4890 fprintf (stream, "\t.size\t%s,%d\n", name2, size); 4891 fprintf (stream, "%s:\n\t.zero\t%d\n", name2, size); 4892 return; 4893 } 4894 } 4895 4896 if (!global) 4897 { 4898 fprintf (stream, "\t.local\t"); 4899 assemble_name (stream, name); 4900 fprintf (stream, "\n"); 4901 } 4902 fprintf (stream, "\t.comm\t"); 4903 assemble_name (stream, name); 4904 fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT); 4905} 4906 4907/* Trampolines. */ 4908 4909static void 4910mep_trampoline_init (rtx m_tramp, tree fndecl, rtx static_chain) 4911{ 4912 rtx addr = XEXP (m_tramp, 0); 4913 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0); 4914 4915 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__mep_trampoline_helper"), 4916 LCT_NORMAL, VOIDmode, 3, 4917 addr, Pmode, 4918 fnaddr, Pmode, 4919 static_chain, Pmode); 4920} 4921 4922/* Experimental Reorg. */ 4923 4924static bool 4925mep_mentioned_p (rtx in, 4926 rtx reg, /* NULL for mem */ 4927 int modes_too) /* if nonzero, modes must match also. */ 4928{ 4929 const char *fmt; 4930 int i; 4931 enum rtx_code code; 4932 4933 if (in == 0) 4934 return false; 4935 if (reg && GET_CODE (reg) != REG) 4936 return false; 4937 4938 if (GET_CODE (in) == LABEL_REF) 4939 return (reg == 0); 4940 4941 code = GET_CODE (in); 4942 4943 switch (code) 4944 { 4945 case MEM: 4946 if (reg) 4947 return mep_mentioned_p (XEXP (in, 0), reg, modes_too); 4948 return true; 4949 4950 case REG: 4951 if (!reg) 4952 return false; 4953 if (modes_too && (GET_MODE (in) != GET_MODE (reg))) 4954 return false; 4955 return (REGNO (in) == REGNO (reg)); 4956 4957 case SCRATCH: 4958 case CC0: 4959 case PC: 4960 case CONST_INT: 4961 case CONST_DOUBLE: 4962 return false; 4963 4964 default: 4965 break; 4966 } 4967 4968 /* Set's source should be read-only. */ 4969 if (code == SET && !reg) 4970 return mep_mentioned_p (SET_DEST (in), reg, modes_too); 4971 4972 fmt = GET_RTX_FORMAT (code); 4973 4974 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 4975 { 4976 if (fmt[i] == 'E') 4977 { 4978 register int j; 4979 for (j = XVECLEN (in, i) - 1; j >= 0; j--) 4980 if (mep_mentioned_p (XVECEXP (in, i, j), reg, modes_too)) 4981 return true; 4982 } 4983 else if (fmt[i] == 'e' 4984 && mep_mentioned_p (XEXP (in, i), reg, modes_too)) 4985 return true; 4986 } 4987 return false; 4988} 4989 4990#define EXPERIMENTAL_REGMOVE_REORG 1 4991 4992#if EXPERIMENTAL_REGMOVE_REORG 4993 4994static int 4995mep_compatible_reg_class (int r1, int r2) 4996{ 4997 if (GR_REGNO_P (r1) && GR_REGNO_P (r2)) 4998 return 1; 4999 if (CR_REGNO_P (r1) && CR_REGNO_P (r2)) 5000 return 1; 5001 return 0; 5002} 5003 5004static void 5005mep_reorg_regmove (rtx insns) 5006{ 5007 rtx insn, next, pat, follow, *where; 5008 int count = 0, done = 0, replace, before = 0; 5009 5010 if (dump_file) 5011 for (insn = insns; insn; insn = NEXT_INSN (insn)) 5012 if (GET_CODE (insn) == INSN) 5013 before++; 5014 5015 /* We're looking for (set r2 r1) moves where r1 dies, followed by a 5016 set that uses the r2 and r2 dies there. We replace r2 with r1 5017 and see if it's still a valid insn. If so, delete the first set. 5018 Copied from reorg.c. */ 5019 5020 while (!done) 5021 { 5022 done = 1; 5023 for (insn = insns; insn; insn = next) 5024 { 5025 next = NEXT_INSN (insn); 5026 if (GET_CODE (insn) != INSN) 5027 continue; 5028 pat = PATTERN (insn); 5029 5030 replace = 0; 5031 5032 if (GET_CODE (pat) == SET 5033 && GET_CODE (SET_SRC (pat)) == REG 5034 && GET_CODE (SET_DEST (pat)) == REG 5035 && find_regno_note (insn, REG_DEAD, REGNO (SET_SRC (pat))) 5036 && mep_compatible_reg_class (REGNO (SET_SRC (pat)), REGNO (SET_DEST (pat)))) 5037 { 5038 follow = next_nonnote_insn (insn); 5039 if (dump_file) 5040 fprintf (dump_file, "superfluous moves: considering %d\n", INSN_UID (insn)); 5041 5042 while (follow && GET_CODE (follow) == INSN 5043 && GET_CODE (PATTERN (follow)) == SET 5044 && !dead_or_set_p (follow, SET_SRC (pat)) 5045 && !mep_mentioned_p (PATTERN (follow), SET_SRC (pat), 0) 5046 && !mep_mentioned_p (PATTERN (follow), SET_DEST (pat), 0)) 5047 { 5048 if (dump_file) 5049 fprintf (dump_file, "\tskipping %d\n", INSN_UID (follow)); 5050 follow = next_nonnote_insn (follow); 5051 } 5052 5053 if (dump_file) 5054 fprintf (dump_file, "\tfollow is %d\n", INSN_UID (follow)); 5055 if (follow && GET_CODE (follow) == INSN 5056 && GET_CODE (PATTERN (follow)) == SET 5057 && find_regno_note (follow, REG_DEAD, REGNO (SET_DEST (pat)))) 5058 { 5059 if (GET_CODE (SET_DEST (PATTERN (follow))) == REG) 5060 { 5061 if (mep_mentioned_p (SET_SRC (PATTERN (follow)), SET_DEST (pat), 1)) 5062 { 5063 replace = 1; 5064 where = & SET_SRC (PATTERN (follow)); 5065 } 5066 } 5067 else if (GET_CODE (SET_DEST (PATTERN (follow))) == MEM) 5068 { 5069 if (mep_mentioned_p (PATTERN (follow), SET_DEST (pat), 1)) 5070 { 5071 replace = 1; 5072 where = & PATTERN (follow); 5073 } 5074 } 5075 } 5076 } 5077 5078 /* If so, follow is the corresponding insn */ 5079 if (replace) 5080 { 5081 if (dump_file) 5082 { 5083 rtx x; 5084 5085 fprintf (dump_file, "----- Candidate for superfluous move deletion:\n\n"); 5086 for (x = insn; x ;x = NEXT_INSN (x)) 5087 { 5088 print_rtl_single (dump_file, x); 5089 if (x == follow) 5090 break; 5091 fprintf (dump_file, "\n"); 5092 } 5093 } 5094 5095 if (validate_replace_rtx_subexp (SET_DEST (pat), SET_SRC (pat), 5096 follow, where)) 5097 { 5098 count ++; 5099 next = delete_insn (insn); 5100 if (dump_file) 5101 { 5102 fprintf (dump_file, "\n----- Success! new insn:\n\n"); 5103 print_rtl_single (dump_file, follow); 5104 } 5105 done = 0; 5106 } 5107 } 5108 } 5109 } 5110 5111 if (dump_file) 5112 { 5113 fprintf (dump_file, "\n%d insn%s deleted out of %d.\n\n", count, count == 1 ? "" : "s", before); 5114 fprintf (dump_file, "=====\n"); 5115 } 5116} 5117#endif 5118 5119 5120/* Figure out where to put LABEL, which is the label for a repeat loop. 5121 If INCLUDING, LAST_INSN is the last instruction in the loop, otherwise 5122 the loop ends just before LAST_INSN. If SHARED, insns other than the 5123 "repeat" might use LABEL to jump to the loop's continuation point. 5124 5125 Return the last instruction in the adjusted loop. */ 5126 5127static rtx 5128mep_insert_repeat_label_last (rtx last_insn, rtx label, bool including, 5129 bool shared) 5130{ 5131 rtx next, prev; 5132 int count = 0, code, icode; 5133 5134 if (dump_file) 5135 fprintf (dump_file, "considering end of repeat loop at insn %d\n", 5136 INSN_UID (last_insn)); 5137 5138 /* Set PREV to the last insn in the loop. */ 5139 prev = last_insn; 5140 if (!including) 5141 prev = PREV_INSN (prev); 5142 5143 /* Set NEXT to the next insn after the repeat label. */ 5144 next = last_insn; 5145 if (!shared) 5146 while (prev != 0) 5147 { 5148 code = GET_CODE (prev); 5149 if (code == CALL_INSN || code == CODE_LABEL || code == BARRIER) 5150 break; 5151 5152 if (INSN_P (prev)) 5153 { 5154 if (GET_CODE (PATTERN (prev)) == SEQUENCE) 5155 prev = XVECEXP (PATTERN (prev), 0, 1); 5156 5157 /* Other insns that should not be in the last two opcodes. */ 5158 icode = recog_memoized (prev); 5159 if (icode < 0 5160 || icode == CODE_FOR_repeat 5161 || icode == CODE_FOR_erepeat 5162 || get_attr_may_trap (prev) == MAY_TRAP_YES) 5163 break; 5164 5165 /* That leaves JUMP_INSN and INSN. It will have BImode if it 5166 is the second instruction in a VLIW bundle. In that case, 5167 loop again: if the first instruction also satisfies the 5168 conditions above then we will reach here again and put 5169 both of them into the repeat epilogue. Otherwise both 5170 should remain outside. */ 5171 if (GET_MODE (prev) != BImode) 5172 { 5173 count++; 5174 next = prev; 5175 if (dump_file) 5176 print_rtl_single (dump_file, next); 5177 if (count == 2) 5178 break; 5179 } 5180 } 5181 prev = PREV_INSN (prev); 5182 } 5183 5184 /* See if we're adding the label immediately after the repeat insn. 5185 If so, we need to separate them with a nop. */ 5186 prev = prev_real_insn (next); 5187 if (prev) 5188 switch (recog_memoized (prev)) 5189 { 5190 case CODE_FOR_repeat: 5191 case CODE_FOR_erepeat: 5192 if (dump_file) 5193 fprintf (dump_file, "Adding nop inside loop\n"); 5194 emit_insn_before (gen_nop (), next); 5195 break; 5196 5197 default: 5198 break; 5199 } 5200 5201 /* Insert the label. */ 5202 emit_label_before (label, next); 5203 5204 /* Insert the nops. */ 5205 if (dump_file && count < 2) 5206 fprintf (dump_file, "Adding %d nop%s\n\n", 5207 2 - count, count == 1 ? "" : "s"); 5208 5209 for (; count < 2; count++) 5210 if (including) 5211 last_insn = emit_insn_after (gen_nop (), last_insn); 5212 else 5213 emit_insn_before (gen_nop (), last_insn); 5214 5215 return last_insn; 5216} 5217 5218 5219void 5220mep_emit_doloop (rtx *operands, int is_end) 5221{ 5222 rtx tag; 5223 5224 if (cfun->machine->doloop_tags == 0 5225 || cfun->machine->doloop_tag_from_end == is_end) 5226 { 5227 cfun->machine->doloop_tags++; 5228 cfun->machine->doloop_tag_from_end = is_end; 5229 } 5230 5231 tag = GEN_INT (cfun->machine->doloop_tags - 1); 5232 if (is_end) 5233 emit_jump_insn (gen_doloop_end_internal (operands[0], operands[4], tag)); 5234 else 5235 emit_insn (gen_doloop_begin_internal (operands[0], operands[0], tag)); 5236} 5237 5238 5239/* Code for converting doloop_begins and doloop_ends into valid 5240 MeP instructions. A doloop_begin is just a placeholder: 5241 5242 $count = unspec ($count) 5243 5244 where $count is initially the number of iterations - 1. 5245 doloop_end has the form: 5246 5247 if ($count-- == 0) goto label 5248 5249 The counter variable is private to the doloop insns, nothing else 5250 relies on its value. 5251 5252 There are three cases, in decreasing order of preference: 5253 5254 1. A loop has exactly one doloop_begin and one doloop_end. 5255 The doloop_end branches to the first instruction after 5256 the doloop_begin. 5257 5258 In this case we can replace the doloop_begin with a repeat 5259 instruction and remove the doloop_end. I.e.: 5260 5261 $count1 = unspec ($count1) 5262 label: 5263 ... 5264 insn1 5265 insn2 5266 if ($count2-- == 0) goto label 5267 5268 becomes: 5269 5270 repeat $count1,repeat_label 5271 label: 5272 ... 5273 repeat_label: 5274 insn1 5275 insn2 5276 # end repeat 5277 5278 2. As for (1), except there are several doloop_ends. One of them 5279 (call it X) falls through to a label L. All the others fall 5280 through to branches to L. 5281 5282 In this case, we remove X and replace the other doloop_ends 5283 with branches to the repeat label. For example: 5284 5285 $count1 = unspec ($count1) 5286 start: 5287 ... 5288 if ($count2-- == 0) goto label 5289 end: 5290 ... 5291 if ($count3-- == 0) goto label 5292 goto end 5293 5294 becomes: 5295 5296 repeat $count1,repeat_label 5297 start: 5298 ... 5299 repeat_label: 5300 nop 5301 nop 5302 # end repeat 5303 end: 5304 ... 5305 goto repeat_label 5306 5307 3. The fallback case. Replace doloop_begins with: 5308 5309 $count = $count + 1 5310 5311 Replace doloop_ends with the equivalent of: 5312 5313 $count = $count - 1 5314 if ($count == 0) goto label 5315 5316 Note that this might need a scratch register if $count 5317 is stored in memory. */ 5318 5319/* A structure describing one doloop_begin. */ 5320struct mep_doloop_begin { 5321 /* The next doloop_begin with the same tag. */ 5322 struct mep_doloop_begin *next; 5323 5324 /* The instruction itself. */ 5325 rtx insn; 5326 5327 /* The initial counter value. This is known to be a general register. */ 5328 rtx counter; 5329}; 5330 5331/* A structure describing a doloop_end. */ 5332struct mep_doloop_end { 5333 /* The next doloop_end with the same loop tag. */ 5334 struct mep_doloop_end *next; 5335 5336 /* The instruction itself. */ 5337 rtx insn; 5338 5339 /* The first instruction after INSN when the branch isn't taken. */ 5340 rtx fallthrough; 5341 5342 /* The location of the counter value. Since doloop_end_internal is a 5343 jump instruction, it has to allow the counter to be stored anywhere 5344 (any non-fixed register or memory location). */ 5345 rtx counter; 5346 5347 /* The target label (the place where the insn branches when the counter 5348 isn't zero). */ 5349 rtx label; 5350 5351 /* A scratch register. Only available when COUNTER isn't stored 5352 in a general register. */ 5353 rtx scratch; 5354}; 5355 5356 5357/* One do-while loop. */ 5358struct mep_doloop { 5359 /* All the doloop_begins for this loop (in no particular order). */ 5360 struct mep_doloop_begin *begin; 5361 5362 /* All the doloop_ends. When there is more than one, arrange things 5363 so that the first one is the most likely to be X in case (2) above. */ 5364 struct mep_doloop_end *end; 5365}; 5366 5367 5368/* Return true if LOOP can be converted into repeat/repeat_end form 5369 (that is, if it matches cases (1) or (2) above). */ 5370 5371static bool 5372mep_repeat_loop_p (struct mep_doloop *loop) 5373{ 5374 struct mep_doloop_end *end; 5375 rtx fallthrough; 5376 5377 /* There must be exactly one doloop_begin and at least one doloop_end. */ 5378 if (loop->begin == 0 || loop->end == 0 || loop->begin->next != 0) 5379 return false; 5380 5381 /* The first doloop_end (X) must branch back to the insn after 5382 the doloop_begin. */ 5383 if (prev_real_insn (loop->end->label) != loop->begin->insn) 5384 return false; 5385 5386 /* All the other doloop_ends must branch to the same place as X. 5387 When the branch isn't taken, they must jump to the instruction 5388 after X. */ 5389 fallthrough = loop->end->fallthrough; 5390 for (end = loop->end->next; end != 0; end = end->next) 5391 if (end->label != loop->end->label 5392 || !simplejump_p (end->fallthrough) 5393 || next_real_insn (JUMP_LABEL (end->fallthrough)) != fallthrough) 5394 return false; 5395 5396 return true; 5397} 5398 5399 5400/* The main repeat reorg function. See comment above for details. */ 5401 5402static void 5403mep_reorg_repeat (rtx insns) 5404{ 5405 rtx insn; 5406 struct mep_doloop *loops, *loop; 5407 struct mep_doloop_begin *begin; 5408 struct mep_doloop_end *end; 5409 5410 /* Quick exit if we haven't created any loops. */ 5411 if (cfun->machine->doloop_tags == 0) 5412 return; 5413 5414 /* Create an array of mep_doloop structures. */ 5415 loops = (struct mep_doloop *) alloca (sizeof (loops[0]) * cfun->machine->doloop_tags); 5416 memset (loops, 0, sizeof (loops[0]) * cfun->machine->doloop_tags); 5417 5418 /* Search the function for do-while insns and group them by loop tag. */ 5419 for (insn = insns; insn; insn = NEXT_INSN (insn)) 5420 if (INSN_P (insn)) 5421 switch (recog_memoized (insn)) 5422 { 5423 case CODE_FOR_doloop_begin_internal: 5424 insn_extract (insn); 5425 loop = &loops[INTVAL (recog_data.operand[2])]; 5426 5427 begin = (struct mep_doloop_begin *) alloca (sizeof (struct mep_doloop_begin)); 5428 begin->next = loop->begin; 5429 begin->insn = insn; 5430 begin->counter = recog_data.operand[0]; 5431 5432 loop->begin = begin; 5433 break; 5434 5435 case CODE_FOR_doloop_end_internal: 5436 insn_extract (insn); 5437 loop = &loops[INTVAL (recog_data.operand[2])]; 5438 5439 end = (struct mep_doloop_end *) alloca (sizeof (struct mep_doloop_end)); 5440 end->insn = insn; 5441 end->fallthrough = next_real_insn (insn); 5442 end->counter = recog_data.operand[0]; 5443 end->label = recog_data.operand[1]; 5444 end->scratch = recog_data.operand[3]; 5445 5446 /* If this insn falls through to an unconditional jump, 5447 give it a lower priority than the others. */ 5448 if (loop->end != 0 && simplejump_p (end->fallthrough)) 5449 { 5450 end->next = loop->end->next; 5451 loop->end->next = end; 5452 } 5453 else 5454 { 5455 end->next = loop->end; 5456 loop->end = end; 5457 } 5458 break; 5459 } 5460 5461 /* Convert the insns for each loop in turn. */ 5462 for (loop = loops; loop < loops + cfun->machine->doloop_tags; loop++) 5463 if (mep_repeat_loop_p (loop)) 5464 { 5465 /* Case (1) or (2). */ 5466 rtx repeat_label, label_ref; 5467 5468 /* Create a new label for the repeat insn. */ 5469 repeat_label = gen_label_rtx (); 5470 5471 /* Replace the doloop_begin with a repeat. */ 5472 label_ref = gen_rtx_LABEL_REF (VOIDmode, repeat_label); 5473 emit_insn_before (gen_repeat (loop->begin->counter, label_ref), 5474 loop->begin->insn); 5475 delete_insn (loop->begin->insn); 5476 5477 /* Insert the repeat label before the first doloop_end. 5478 Fill the gap with nops if there are other doloop_ends. */ 5479 mep_insert_repeat_label_last (loop->end->insn, repeat_label, 5480 false, loop->end->next != 0); 5481 5482 /* Emit a repeat_end (to improve the readability of the output). */ 5483 emit_insn_before (gen_repeat_end (), loop->end->insn); 5484 5485 /* Delete the first doloop_end. */ 5486 delete_insn (loop->end->insn); 5487 5488 /* Replace the others with branches to REPEAT_LABEL. */ 5489 for (end = loop->end->next; end != 0; end = end->next) 5490 { 5491 emit_jump_insn_before (gen_jump (repeat_label), end->insn); 5492 delete_insn (end->insn); 5493 delete_insn (end->fallthrough); 5494 } 5495 } 5496 else 5497 { 5498 /* Case (3). First replace all the doloop_begins with increment 5499 instructions. */ 5500 for (begin = loop->begin; begin != 0; begin = begin->next) 5501 { 5502 emit_insn_before (gen_add3_insn (copy_rtx (begin->counter), 5503 begin->counter, const1_rtx), 5504 begin->insn); 5505 delete_insn (begin->insn); 5506 } 5507 5508 /* Replace all the doloop_ends with decrement-and-branch sequences. */ 5509 for (end = loop->end; end != 0; end = end->next) 5510 { 5511 rtx reg; 5512 5513 start_sequence (); 5514 5515 /* Load the counter value into a general register. */ 5516 reg = end->counter; 5517 if (!REG_P (reg) || REGNO (reg) > 15) 5518 { 5519 reg = end->scratch; 5520 emit_move_insn (copy_rtx (reg), copy_rtx (end->counter)); 5521 } 5522 5523 /* Decrement the counter. */ 5524 emit_insn (gen_add3_insn (copy_rtx (reg), copy_rtx (reg), 5525 constm1_rtx)); 5526 5527 /* Copy it back to its original location. */ 5528 if (reg != end->counter) 5529 emit_move_insn (copy_rtx (end->counter), copy_rtx (reg)); 5530 5531 /* Jump back to the start label. */ 5532 insn = emit_jump_insn (gen_mep_bne_true (reg, const0_rtx, 5533 end->label)); 5534 JUMP_LABEL (insn) = end->label; 5535 LABEL_NUSES (end->label)++; 5536 5537 /* Emit the whole sequence before the doloop_end. */ 5538 insn = get_insns (); 5539 end_sequence (); 5540 emit_insn_before (insn, end->insn); 5541 5542 /* Delete the doloop_end. */ 5543 delete_insn (end->insn); 5544 } 5545 } 5546} 5547 5548 5549static bool 5550mep_invertable_branch_p (rtx insn) 5551{ 5552 rtx cond, set; 5553 enum rtx_code old_code; 5554 int i; 5555 5556 set = PATTERN (insn); 5557 if (GET_CODE (set) != SET) 5558 return false; 5559 if (GET_CODE (XEXP (set, 1)) != IF_THEN_ELSE) 5560 return false; 5561 cond = XEXP (XEXP (set, 1), 0); 5562 old_code = GET_CODE (cond); 5563 switch (old_code) 5564 { 5565 case EQ: 5566 PUT_CODE (cond, NE); 5567 break; 5568 case NE: 5569 PUT_CODE (cond, EQ); 5570 break; 5571 case LT: 5572 PUT_CODE (cond, GE); 5573 break; 5574 case GE: 5575 PUT_CODE (cond, LT); 5576 break; 5577 default: 5578 return false; 5579 } 5580 INSN_CODE (insn) = -1; 5581 i = recog_memoized (insn); 5582 PUT_CODE (cond, old_code); 5583 INSN_CODE (insn) = -1; 5584 return i >= 0; 5585} 5586 5587static void 5588mep_invert_branch (rtx insn, rtx after) 5589{ 5590 rtx cond, set, label; 5591 int i; 5592 5593 set = PATTERN (insn); 5594 5595 gcc_assert (GET_CODE (set) == SET); 5596 gcc_assert (GET_CODE (XEXP (set, 1)) == IF_THEN_ELSE); 5597 5598 cond = XEXP (XEXP (set, 1), 0); 5599 switch (GET_CODE (cond)) 5600 { 5601 case EQ: 5602 PUT_CODE (cond, NE); 5603 break; 5604 case NE: 5605 PUT_CODE (cond, EQ); 5606 break; 5607 case LT: 5608 PUT_CODE (cond, GE); 5609 break; 5610 case GE: 5611 PUT_CODE (cond, LT); 5612 break; 5613 default: 5614 gcc_unreachable (); 5615 } 5616 label = gen_label_rtx (); 5617 emit_label_after (label, after); 5618 for (i=1; i<=2; i++) 5619 if (GET_CODE (XEXP (XEXP (set, 1), i)) == LABEL_REF) 5620 { 5621 rtx ref = XEXP (XEXP (set, 1), i); 5622 if (LABEL_NUSES (XEXP (ref, 0)) == 1) 5623 delete_insn (XEXP (ref, 0)); 5624 XEXP (ref, 0) = label; 5625 LABEL_NUSES (label) ++; 5626 JUMP_LABEL (insn) = label; 5627 } 5628 INSN_CODE (insn) = -1; 5629 i = recog_memoized (insn); 5630 gcc_assert (i >= 0); 5631} 5632 5633static void 5634mep_reorg_erepeat (rtx insns) 5635{ 5636 rtx insn, prev, label_before, l, x; 5637 int count; 5638 5639 for (insn = insns; insn; insn = NEXT_INSN (insn)) 5640 if (JUMP_P (insn) 5641 && ! JUMP_TABLE_DATA_P (insn) 5642 && mep_invertable_branch_p (insn)) 5643 { 5644 if (dump_file) 5645 { 5646 fprintf (dump_file, "\n------------------------------\n"); 5647 fprintf (dump_file, "erepeat: considering this jump:\n"); 5648 print_rtl_single (dump_file, insn); 5649 } 5650 count = simplejump_p (insn) ? 0 : 1; 5651 label_before = 0; 5652 for (prev = PREV_INSN (insn); prev; prev = PREV_INSN (prev)) 5653 { 5654 if (GET_CODE (prev) == CALL_INSN 5655 || BARRIER_P (prev)) 5656 break; 5657 5658 if (prev == JUMP_LABEL (insn)) 5659 { 5660 rtx newlast; 5661 if (dump_file) 5662 fprintf (dump_file, "found loop top, %d insns\n", count); 5663 5664 if (LABEL_NUSES (prev) == 1) 5665 /* We're the only user, always safe */ ; 5666 else if (LABEL_NUSES (prev) == 2) 5667 { 5668 /* See if there's a barrier before this label. If 5669 so, we know nobody inside the loop uses it. 5670 But we must be careful to put the erepeat 5671 *after* the label. */ 5672 rtx barrier; 5673 for (barrier = PREV_INSN (prev); 5674 barrier && GET_CODE (barrier) == NOTE; 5675 barrier = PREV_INSN (barrier)) 5676 ; 5677 if (barrier && GET_CODE (barrier) != BARRIER) 5678 break; 5679 } 5680 else 5681 { 5682 /* We don't know who else, within or without our loop, uses this */ 5683 if (dump_file) 5684 fprintf (dump_file, "... but there are multiple users, too risky.\n"); 5685 break; 5686 } 5687 5688 /* Generate a label to be used by the erepat insn. */ 5689 l = gen_label_rtx (); 5690 5691 /* Insert the erepeat after INSN's target label. */ 5692 x = gen_erepeat (gen_rtx_LABEL_REF (VOIDmode, l)); 5693 LABEL_NUSES (l)++; 5694 emit_insn_after (x, prev); 5695 5696 /* Insert the erepeat label. */ 5697 newlast = (mep_insert_repeat_label_last 5698 (insn, l, !simplejump_p (insn), false)); 5699 if (simplejump_p (insn)) 5700 { 5701 emit_insn_before (gen_erepeat_end (), insn); 5702 delete_insn (insn); 5703 } 5704 else 5705 { 5706 mep_invert_branch (insn, newlast); 5707 emit_insn_after (gen_erepeat_end (), newlast); 5708 } 5709 break; 5710 } 5711 5712 if (LABEL_P (prev)) 5713 { 5714 /* A label is OK if there is exactly one user, and we 5715 can find that user before the next label. */ 5716 rtx user = 0; 5717 int safe = 0; 5718 if (LABEL_NUSES (prev) == 1) 5719 { 5720 for (user = PREV_INSN (prev); 5721 user && (INSN_P (user) || GET_CODE (user) == NOTE); 5722 user = PREV_INSN (user)) 5723 if (GET_CODE (user) == JUMP_INSN 5724 && JUMP_LABEL (user) == prev) 5725 { 5726 safe = INSN_UID (user); 5727 break; 5728 } 5729 } 5730 if (!safe) 5731 break; 5732 if (dump_file) 5733 fprintf (dump_file, "... ignoring jump from insn %d to %d\n", 5734 safe, INSN_UID (prev)); 5735 } 5736 5737 if (INSN_P (prev)) 5738 { 5739 count ++; 5740 if (count == 2) 5741 label_before = prev; 5742 } 5743 } 5744 } 5745 if (dump_file) 5746 fprintf (dump_file, "\n==============================\n"); 5747} 5748 5749/* Replace a jump to a return, with a copy of the return. GCC doesn't 5750 always do this on its own. */ 5751 5752static void 5753mep_jmp_return_reorg (rtx insns) 5754{ 5755 rtx insn, label, ret; 5756 int ret_code; 5757 5758 for (insn = insns; insn; insn = NEXT_INSN (insn)) 5759 if (simplejump_p (insn)) 5760 { 5761 /* Find the fist real insn the jump jumps to. */ 5762 label = ret = JUMP_LABEL (insn); 5763 while (ret 5764 && (GET_CODE (ret) == NOTE 5765 || GET_CODE (ret) == CODE_LABEL 5766 || GET_CODE (PATTERN (ret)) == USE)) 5767 ret = NEXT_INSN (ret); 5768 5769 if (ret) 5770 { 5771 /* Is it a return? */ 5772 ret_code = recog_memoized (ret); 5773 if (ret_code == CODE_FOR_return_internal 5774 || ret_code == CODE_FOR_eh_return_internal) 5775 { 5776 /* It is. Replace the jump with a return. */ 5777 LABEL_NUSES (label) --; 5778 if (LABEL_NUSES (label) == 0) 5779 delete_insn (label); 5780 PATTERN (insn) = copy_rtx (PATTERN (ret)); 5781 INSN_CODE (insn) = -1; 5782 } 5783 } 5784 } 5785} 5786 5787 5788static void 5789mep_reorg_addcombine (rtx insns) 5790{ 5791 rtx i, n; 5792 5793 for (i = insns; i; i = NEXT_INSN (i)) 5794 if (INSN_P (i) 5795 && INSN_CODE (i) == CODE_FOR_addsi3 5796 && GET_CODE (SET_DEST (PATTERN (i))) == REG 5797 && GET_CODE (XEXP (SET_SRC (PATTERN (i)), 0)) == REG 5798 && REGNO (SET_DEST (PATTERN (i))) == REGNO (XEXP (SET_SRC (PATTERN (i)), 0)) 5799 && GET_CODE (XEXP (SET_SRC (PATTERN (i)), 1)) == CONST_INT) 5800 { 5801 n = NEXT_INSN (i); 5802 if (INSN_P (n) 5803 && INSN_CODE (n) == CODE_FOR_addsi3 5804 && GET_CODE (SET_DEST (PATTERN (n))) == REG 5805 && GET_CODE (XEXP (SET_SRC (PATTERN (n)), 0)) == REG 5806 && REGNO (SET_DEST (PATTERN (n))) == REGNO (XEXP (SET_SRC (PATTERN (n)), 0)) 5807 && GET_CODE (XEXP (SET_SRC (PATTERN (n)), 1)) == CONST_INT) 5808 { 5809 int ic = INTVAL (XEXP (SET_SRC (PATTERN (i)), 1)); 5810 int nc = INTVAL (XEXP (SET_SRC (PATTERN (n)), 1)); 5811 if (REGNO (SET_DEST (PATTERN (i))) == REGNO (SET_DEST (PATTERN (n))) 5812 && ic + nc < 32767 5813 && ic + nc > -32768) 5814 { 5815 XEXP (SET_SRC (PATTERN (i)), 1) = GEN_INT (ic + nc); 5816 NEXT_INSN (i) = NEXT_INSN (n); 5817 if (NEXT_INSN (i)) 5818 PREV_INSN (NEXT_INSN (i)) = i; 5819 } 5820 } 5821 } 5822} 5823 5824/* If this insn adjusts the stack, return the adjustment, else return 5825 zero. */ 5826static int 5827add_sp_insn_p (rtx insn) 5828{ 5829 rtx pat; 5830 5831 if (! single_set (insn)) 5832 return 0; 5833 pat = PATTERN (insn); 5834 if (GET_CODE (SET_DEST (pat)) != REG) 5835 return 0; 5836 if (REGNO (SET_DEST (pat)) != SP_REGNO) 5837 return 0; 5838 if (GET_CODE (SET_SRC (pat)) != PLUS) 5839 return 0; 5840 if (GET_CODE (XEXP (SET_SRC (pat), 0)) != REG) 5841 return 0; 5842 if (REGNO (XEXP (SET_SRC (pat), 0)) != SP_REGNO) 5843 return 0; 5844 if (GET_CODE (XEXP (SET_SRC (pat), 1)) != CONST_INT) 5845 return 0; 5846 return INTVAL (XEXP (SET_SRC (pat), 1)); 5847} 5848 5849/* Check for trivial functions that set up an unneeded stack 5850 frame. */ 5851static void 5852mep_reorg_noframe (rtx insns) 5853{ 5854 rtx start_frame_insn; 5855 rtx end_frame_insn = 0; 5856 int sp_adjust, sp2; 5857 rtx sp; 5858 5859 /* The first insn should be $sp = $sp + N */ 5860 while (insns && ! INSN_P (insns)) 5861 insns = NEXT_INSN (insns); 5862 if (!insns) 5863 return; 5864 5865 sp_adjust = add_sp_insn_p (insns); 5866 if (sp_adjust == 0) 5867 return; 5868 5869 start_frame_insn = insns; 5870 sp = SET_DEST (PATTERN (start_frame_insn)); 5871 5872 insns = next_real_insn (insns); 5873 5874 while (insns) 5875 { 5876 rtx next = next_real_insn (insns); 5877 if (!next) 5878 break; 5879 5880 sp2 = add_sp_insn_p (insns); 5881 if (sp2) 5882 { 5883 if (end_frame_insn) 5884 return; 5885 end_frame_insn = insns; 5886 if (sp2 != -sp_adjust) 5887 return; 5888 } 5889 else if (mep_mentioned_p (insns, sp, 0)) 5890 return; 5891 else if (CALL_P (insns)) 5892 return; 5893 5894 insns = next; 5895 } 5896 5897 if (end_frame_insn) 5898 { 5899 delete_insn (start_frame_insn); 5900 delete_insn (end_frame_insn); 5901 } 5902} 5903 5904static void 5905mep_reorg (void) 5906{ 5907 rtx insns = get_insns (); 5908 5909 /* We require accurate REG_DEAD notes. */ 5910 compute_bb_for_insn (); 5911 df_note_add_problem (); 5912 df_analyze (); 5913 5914 mep_reorg_addcombine (insns); 5915#if EXPERIMENTAL_REGMOVE_REORG 5916 /* VLIW packing has been done already, so we can't just delete things. */ 5917 if (!mep_vliw_function_p (cfun->decl)) 5918 mep_reorg_regmove (insns); 5919#endif 5920 mep_jmp_return_reorg (insns); 5921 mep_bundle_insns (insns); 5922 mep_reorg_repeat (insns); 5923 if (optimize 5924 && !profile_flag 5925 && !profile_arc_flag 5926 && TARGET_OPT_REPEAT 5927 && (!mep_interrupt_p () || mep_interrupt_saved_reg (RPB_REGNO))) 5928 mep_reorg_erepeat (insns); 5929 5930 /* This may delete *insns so make sure it's last. */ 5931 mep_reorg_noframe (insns); 5932 5933 df_finish_pass (false); 5934} 5935 5936 5937 5938/*----------------------------------------------------------------------*/ 5939/* Builtins */ 5940/*----------------------------------------------------------------------*/ 5941 5942/* Element X gives the index into cgen_insns[] of the most general 5943 implementation of intrinsic X. Unimplemented intrinsics are 5944 mapped to -1. */ 5945int mep_intrinsic_insn[ARRAY_SIZE (cgen_intrinsics)]; 5946 5947/* Element X gives the index of another instruction that is mapped to 5948 the same intrinsic as cgen_insns[X]. It is -1 when there is no other 5949 instruction. 5950 5951 Things are set up so that mep_intrinsic_chain[X] < X. */ 5952static int mep_intrinsic_chain[ARRAY_SIZE (cgen_insns)]; 5953 5954/* The bitmask for the current ISA. The ISA masks are declared 5955 in mep-intrin.h. */ 5956unsigned int mep_selected_isa; 5957 5958struct mep_config { 5959 const char *config_name; 5960 unsigned int isa; 5961}; 5962 5963static struct mep_config mep_configs[] = { 5964#ifdef COPROC_SELECTION_TABLE 5965 COPROC_SELECTION_TABLE, 5966#endif 5967 { 0, 0 } 5968}; 5969 5970/* Initialize the global intrinsics variables above. */ 5971 5972static void 5973mep_init_intrinsics (void) 5974{ 5975 size_t i; 5976 5977 /* Set MEP_SELECTED_ISA to the ISA flag for this configuration. */ 5978 mep_selected_isa = mep_configs[0].isa; 5979 if (mep_config_string != 0) 5980 for (i = 0; mep_configs[i].config_name; i++) 5981 if (strcmp (mep_config_string, mep_configs[i].config_name) == 0) 5982 { 5983 mep_selected_isa = mep_configs[i].isa; 5984 break; 5985 } 5986 5987 /* Assume all intrinsics are unavailable. */ 5988 for (i = 0; i < ARRAY_SIZE (mep_intrinsic_insn); i++) 5989 mep_intrinsic_insn[i] = -1; 5990 5991 /* Build up the global intrinsic tables. */ 5992 for (i = 0; i < ARRAY_SIZE (cgen_insns); i++) 5993 if ((cgen_insns[i].isas & mep_selected_isa) != 0) 5994 { 5995 mep_intrinsic_chain[i] = mep_intrinsic_insn[cgen_insns[i].intrinsic]; 5996 mep_intrinsic_insn[cgen_insns[i].intrinsic] = i; 5997 } 5998 /* See whether we can directly move values between one coprocessor 5999 register and another. */ 6000 for (i = 0; i < ARRAY_SIZE (mep_cmov_insns); i++) 6001 if (MEP_INTRINSIC_AVAILABLE_P (mep_cmov_insns[i])) 6002 mep_have_copro_copro_moves_p = true; 6003 6004 /* See whether we can directly move values between core and 6005 coprocessor registers. */ 6006 mep_have_core_copro_moves_p = (MEP_INTRINSIC_AVAILABLE_P (mep_cmov1) 6007 && MEP_INTRINSIC_AVAILABLE_P (mep_cmov2)); 6008 6009 mep_have_core_copro_moves_p = 1; 6010} 6011 6012/* Declare all available intrinsic functions. Called once only. */ 6013 6014static tree cp_data_bus_int_type_node; 6015static tree opaque_vector_type_node; 6016static tree v8qi_type_node; 6017static tree v4hi_type_node; 6018static tree v2si_type_node; 6019static tree v8uqi_type_node; 6020static tree v4uhi_type_node; 6021static tree v2usi_type_node; 6022 6023static tree 6024mep_cgen_regnum_to_type (enum cgen_regnum_operand_type cr) 6025{ 6026 switch (cr) 6027 { 6028 case cgen_regnum_operand_type_POINTER: return ptr_type_node; 6029 case cgen_regnum_operand_type_LONG: return long_integer_type_node; 6030 case cgen_regnum_operand_type_ULONG: return long_unsigned_type_node; 6031 case cgen_regnum_operand_type_SHORT: return short_integer_type_node; 6032 case cgen_regnum_operand_type_USHORT: return short_unsigned_type_node; 6033 case cgen_regnum_operand_type_CHAR: return char_type_node; 6034 case cgen_regnum_operand_type_UCHAR: return unsigned_char_type_node; 6035 case cgen_regnum_operand_type_SI: return intSI_type_node; 6036 case cgen_regnum_operand_type_DI: return intDI_type_node; 6037 case cgen_regnum_operand_type_VECTOR: return opaque_vector_type_node; 6038 case cgen_regnum_operand_type_V8QI: return v8qi_type_node; 6039 case cgen_regnum_operand_type_V4HI: return v4hi_type_node; 6040 case cgen_regnum_operand_type_V2SI: return v2si_type_node; 6041 case cgen_regnum_operand_type_V8UQI: return v8uqi_type_node; 6042 case cgen_regnum_operand_type_V4UHI: return v4uhi_type_node; 6043 case cgen_regnum_operand_type_V2USI: return v2usi_type_node; 6044 case cgen_regnum_operand_type_CP_DATA_BUS_INT: return cp_data_bus_int_type_node; 6045 default: 6046 return void_type_node; 6047 } 6048} 6049 6050static void 6051mep_init_builtins (void) 6052{ 6053 size_t i; 6054 6055 if (TARGET_64BIT_CR_REGS) 6056 cp_data_bus_int_type_node = long_long_integer_type_node; 6057 else 6058 cp_data_bus_int_type_node = long_integer_type_node; 6059 6060 opaque_vector_type_node = build_opaque_vector_type (intQI_type_node, 8); 6061 v8qi_type_node = build_vector_type (intQI_type_node, 8); 6062 v4hi_type_node = build_vector_type (intHI_type_node, 4); 6063 v2si_type_node = build_vector_type (intSI_type_node, 2); 6064 v8uqi_type_node = build_vector_type (unsigned_intQI_type_node, 8); 6065 v4uhi_type_node = build_vector_type (unsigned_intHI_type_node, 4); 6066 v2usi_type_node = build_vector_type (unsigned_intSI_type_node, 2); 6067 6068 (*lang_hooks.decls.pushdecl) 6069 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_data_bus_int"), 6070 cp_data_bus_int_type_node)); 6071 6072 (*lang_hooks.decls.pushdecl) 6073 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_vector"), 6074 opaque_vector_type_node)); 6075 6076 (*lang_hooks.decls.pushdecl) 6077 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v8qi"), 6078 v8qi_type_node)); 6079 (*lang_hooks.decls.pushdecl) 6080 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v4hi"), 6081 v4hi_type_node)); 6082 (*lang_hooks.decls.pushdecl) 6083 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v2si"), 6084 v2si_type_node)); 6085 6086 (*lang_hooks.decls.pushdecl) 6087 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v8uqi"), 6088 v8uqi_type_node)); 6089 (*lang_hooks.decls.pushdecl) 6090 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v4uhi"), 6091 v4uhi_type_node)); 6092 (*lang_hooks.decls.pushdecl) 6093 (build_decl (BUILTINS_LOCATION, TYPE_DECL, get_identifier ("cp_v2usi"), 6094 v2usi_type_node)); 6095 6096 /* Intrinsics like mep_cadd3 are implemented with two groups of 6097 instructions, one which uses UNSPECs and one which uses a specific 6098 rtl code such as PLUS. Instructions in the latter group belong 6099 to GROUP_KNOWN_CODE. 6100 6101 In such cases, the intrinsic will have two entries in the global 6102 tables above. The unspec form is accessed using builtin functions 6103 while the specific form is accessed using the mep_* enum in 6104 mep-intrin.h. 6105 6106 The idea is that __cop arithmetic and builtin functions have 6107 different optimization requirements. If mep_cadd3() appears in 6108 the source code, the user will surely except gcc to use cadd3 6109 rather than a work-alike such as add3. However, if the user 6110 just writes "a + b", where a or b are __cop variables, it is 6111 reasonable for gcc to choose a core instruction rather than 6112 cadd3 if it believes that is more optimal. */ 6113 for (i = 0; i < ARRAY_SIZE (cgen_insns); i++) 6114 if ((cgen_insns[i].groups & GROUP_KNOWN_CODE) == 0 6115 && mep_intrinsic_insn[cgen_insns[i].intrinsic] >= 0) 6116 { 6117 tree ret_type = void_type_node; 6118 tree bi_type; 6119 6120 if (i > 0 && cgen_insns[i].intrinsic == cgen_insns[i-1].intrinsic) 6121 continue; 6122 6123 if (cgen_insns[i].cret_p) 6124 ret_type = mep_cgen_regnum_to_type (cgen_insns[i].regnums[0].type); 6125 6126 bi_type = build_function_type (ret_type, 0); 6127 add_builtin_function (cgen_intrinsics[cgen_insns[i].intrinsic], 6128 bi_type, 6129 cgen_insns[i].intrinsic, BUILT_IN_MD, NULL, NULL); 6130 } 6131} 6132 6133/* Report the unavailablity of the given intrinsic. */ 6134 6135#if 1 6136static void 6137mep_intrinsic_unavailable (int intrinsic) 6138{ 6139 static int already_reported_p[ARRAY_SIZE (cgen_intrinsics)]; 6140 6141 if (already_reported_p[intrinsic]) 6142 return; 6143 6144 if (mep_intrinsic_insn[intrinsic] < 0) 6145 error ("coprocessor intrinsic %qs is not available in this configuration", 6146 cgen_intrinsics[intrinsic]); 6147 else if (CGEN_CURRENT_GROUP == GROUP_VLIW) 6148 error ("%qs is not available in VLIW functions", 6149 cgen_intrinsics[intrinsic]); 6150 else 6151 error ("%qs is not available in non-VLIW functions", 6152 cgen_intrinsics[intrinsic]); 6153 6154 already_reported_p[intrinsic] = 1; 6155} 6156#endif 6157 6158 6159/* See if any implementation of INTRINSIC is available to the 6160 current function. If so, store the most general implementation 6161 in *INSN_PTR and return true. Return false otherwise. */ 6162 6163static bool 6164mep_get_intrinsic_insn (int intrinsic ATTRIBUTE_UNUSED, const struct cgen_insn **insn_ptr ATTRIBUTE_UNUSED) 6165{ 6166 int i; 6167 6168 i = mep_intrinsic_insn[intrinsic]; 6169 while (i >= 0 && !CGEN_ENABLE_INSN_P (i)) 6170 i = mep_intrinsic_chain[i]; 6171 6172 if (i >= 0) 6173 { 6174 *insn_ptr = &cgen_insns[i]; 6175 return true; 6176 } 6177 return false; 6178} 6179 6180 6181/* Like mep_get_intrinsic_insn, but with extra handling for moves. 6182 If INTRINSIC is mep_cmov, but there is no pure CR <- CR move insn, 6183 try using a work-alike instead. In this case, the returned insn 6184 may have three operands rather than two. */ 6185 6186static bool 6187mep_get_move_insn (int intrinsic, const struct cgen_insn **cgen_insn) 6188{ 6189 size_t i; 6190 6191 if (intrinsic == mep_cmov) 6192 { 6193 for (i = 0; i < ARRAY_SIZE (mep_cmov_insns); i++) 6194 if (mep_get_intrinsic_insn (mep_cmov_insns[i], cgen_insn)) 6195 return true; 6196 return false; 6197 } 6198 return mep_get_intrinsic_insn (intrinsic, cgen_insn); 6199} 6200 6201 6202/* If ARG is a register operand that is the same size as MODE, convert it 6203 to MODE using a subreg. Otherwise return ARG as-is. */ 6204 6205static rtx 6206mep_convert_arg (enum machine_mode mode, rtx arg) 6207{ 6208 if (GET_MODE (arg) != mode 6209 && register_operand (arg, VOIDmode) 6210 && GET_MODE_SIZE (GET_MODE (arg)) == GET_MODE_SIZE (mode)) 6211 return simplify_gen_subreg (mode, arg, GET_MODE (arg), 0); 6212 return arg; 6213} 6214 6215 6216/* Apply regnum conversions to ARG using the description given by REGNUM. 6217 Return the new argument on success and null on failure. */ 6218 6219static rtx 6220mep_convert_regnum (const struct cgen_regnum_operand *regnum, rtx arg) 6221{ 6222 if (regnum->count == 0) 6223 return arg; 6224 6225 if (GET_CODE (arg) != CONST_INT 6226 || INTVAL (arg) < 0 6227 || INTVAL (arg) >= regnum->count) 6228 return 0; 6229 6230 return gen_rtx_REG (SImode, INTVAL (arg) + regnum->base); 6231} 6232 6233 6234/* Try to make intrinsic argument ARG match the given operand. 6235 UNSIGNED_P is true if the argument has an unsigned type. */ 6236 6237static rtx 6238mep_legitimize_arg (const struct insn_operand_data *operand, rtx arg, 6239 int unsigned_p) 6240{ 6241 if (GET_CODE (arg) == CONST_INT) 6242 { 6243 /* CONST_INTs can only be bound to integer operands. */ 6244 if (GET_MODE_CLASS (operand->mode) != MODE_INT) 6245 return 0; 6246 } 6247 else if (GET_CODE (arg) == CONST_DOUBLE) 6248 /* These hold vector constants. */; 6249 else if (GET_MODE_SIZE (GET_MODE (arg)) != GET_MODE_SIZE (operand->mode)) 6250 { 6251 /* If the argument is a different size from what's expected, we must 6252 have a value in the right mode class in order to convert it. */ 6253 if (GET_MODE_CLASS (operand->mode) != GET_MODE_CLASS (GET_MODE (arg))) 6254 return 0; 6255 6256 /* If the operand is an rvalue, promote or demote it to match the 6257 operand's size. This might not need extra instructions when 6258 ARG is a register value. */ 6259 if (operand->constraint[0] != '=') 6260 arg = convert_to_mode (operand->mode, arg, unsigned_p); 6261 } 6262 6263 /* If the operand is an lvalue, bind the operand to a new register. 6264 The caller will copy this value into ARG after the main 6265 instruction. By doing this always, we produce slightly more 6266 optimal code. */ 6267 /* But not for control registers. */ 6268 if (operand->constraint[0] == '=' 6269 && (! REG_P (arg) 6270 || ! (CONTROL_REGNO_P (REGNO (arg)) 6271 || CCR_REGNO_P (REGNO (arg)) 6272 || CR_REGNO_P (REGNO (arg))) 6273 )) 6274 return gen_reg_rtx (operand->mode); 6275 6276 /* Try simple mode punning. */ 6277 arg = mep_convert_arg (operand->mode, arg); 6278 if (operand->predicate (arg, operand->mode)) 6279 return arg; 6280 6281 /* See if forcing the argument into a register will make it match. */ 6282 if (GET_CODE (arg) == CONST_INT || GET_CODE (arg) == CONST_DOUBLE) 6283 arg = force_reg (operand->mode, arg); 6284 else 6285 arg = mep_convert_arg (operand->mode, force_reg (GET_MODE (arg), arg)); 6286 if (operand->predicate (arg, operand->mode)) 6287 return arg; 6288 6289 return 0; 6290} 6291 6292 6293/* Report that ARG cannot be passed to argument ARGNUM of intrinsic 6294 function FNNAME. OPERAND describes the operand to which ARGNUM 6295 is mapped. */ 6296 6297static void 6298mep_incompatible_arg (const struct insn_operand_data *operand, rtx arg, 6299 int argnum, tree fnname) 6300{ 6301 size_t i; 6302 6303 if (GET_CODE (arg) == CONST_INT) 6304 for (i = 0; i < ARRAY_SIZE (cgen_immediate_predicates); i++) 6305 if (operand->predicate == cgen_immediate_predicates[i].predicate) 6306 { 6307 const struct cgen_immediate_predicate *predicate; 6308 HOST_WIDE_INT argval; 6309 6310 predicate = &cgen_immediate_predicates[i]; 6311 argval = INTVAL (arg); 6312 if (argval < predicate->lower || argval >= predicate->upper) 6313 error ("argument %d of %qE must be in the range %d...%d", 6314 argnum, fnname, predicate->lower, predicate->upper - 1); 6315 else 6316 error ("argument %d of %qE must be a multiple of %d", 6317 argnum, fnname, predicate->align); 6318 return; 6319 } 6320 6321 error ("incompatible type for argument %d of %qE", argnum, fnname); 6322} 6323 6324static rtx 6325mep_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, 6326 rtx subtarget ATTRIBUTE_UNUSED, 6327 enum machine_mode mode ATTRIBUTE_UNUSED, 6328 int ignore ATTRIBUTE_UNUSED) 6329{ 6330 rtx pat, op[10], arg[10]; 6331 unsigned int a; 6332 int opindex, unsigned_p[10]; 6333 tree fndecl, args; 6334 unsigned int n_args; 6335 tree fnname; 6336 const struct cgen_insn *cgen_insn; 6337 const struct insn_data *idata; 6338 unsigned int first_arg = 0; 6339 tree return_type = void_type_node; 6340 unsigned int builtin_n_args; 6341 6342 fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); 6343 fnname = DECL_NAME (fndecl); 6344 6345 /* Find out which instruction we should emit. Note that some coprocessor 6346 intrinsics may only be available in VLIW mode, or only in normal mode. */ 6347 if (!mep_get_intrinsic_insn (DECL_FUNCTION_CODE (fndecl), &cgen_insn)) 6348 { 6349 mep_intrinsic_unavailable (DECL_FUNCTION_CODE (fndecl)); 6350 return NULL_RTX; 6351 } 6352 idata = &insn_data[cgen_insn->icode]; 6353 6354 builtin_n_args = cgen_insn->num_args; 6355 6356 if (cgen_insn->cret_p) 6357 { 6358 if (cgen_insn->cret_p > 1) 6359 builtin_n_args ++; 6360 first_arg = 1; 6361 return_type = mep_cgen_regnum_to_type (cgen_insn->regnums[0].type); 6362 builtin_n_args --; 6363 } 6364 6365 /* Evaluate each argument. */ 6366 n_args = call_expr_nargs (exp); 6367 6368 if (n_args < builtin_n_args) 6369 { 6370 error ("too few arguments to %qE", fnname); 6371 return NULL_RTX; 6372 } 6373 if (n_args > builtin_n_args) 6374 { 6375 error ("too many arguments to %qE", fnname); 6376 return NULL_RTX; 6377 } 6378 6379 for (a = first_arg; a < builtin_n_args + first_arg; a++) 6380 { 6381 tree value; 6382 6383 args = CALL_EXPR_ARG (exp, a - first_arg); 6384 6385 value = args; 6386 6387#if 0 6388 if (cgen_insn->regnums[a].reference_p) 6389 { 6390 if (TREE_CODE (value) != ADDR_EXPR) 6391 { 6392 debug_tree(value); 6393 error ("argument %d of %qE must be an address", a+1, fnname); 6394 return NULL_RTX; 6395 } 6396 value = TREE_OPERAND (value, 0); 6397 } 6398#endif 6399 6400 /* If the argument has been promoted to int, get the unpromoted 6401 value. This is necessary when sub-int memory values are bound 6402 to reference parameters. */ 6403 if (TREE_CODE (value) == NOP_EXPR 6404 && TREE_TYPE (value) == integer_type_node 6405 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))) 6406 && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))) 6407 < TYPE_PRECISION (TREE_TYPE (value)))) 6408 value = TREE_OPERAND (value, 0); 6409 6410 /* If the argument has been promoted to double, get the unpromoted 6411 SFmode value. This is necessary for FMAX support, for example. */ 6412 if (TREE_CODE (value) == NOP_EXPR 6413 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (value)) 6414 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))) 6415 && TYPE_MODE (TREE_TYPE (value)) == DFmode 6416 && TYPE_MODE (TREE_TYPE (TREE_OPERAND (value, 0))) == SFmode) 6417 value = TREE_OPERAND (value, 0); 6418 6419 unsigned_p[a] = TYPE_UNSIGNED (TREE_TYPE (value)); 6420 arg[a] = expand_expr (value, NULL, VOIDmode, EXPAND_NORMAL); 6421 arg[a] = mep_convert_regnum (&cgen_insn->regnums[a], arg[a]); 6422 if (cgen_insn->regnums[a].reference_p) 6423 { 6424 tree pointed_to = TREE_TYPE (TREE_TYPE (value)); 6425 enum machine_mode pointed_mode = TYPE_MODE (pointed_to); 6426 6427 arg[a] = gen_rtx_MEM (pointed_mode, arg[a]); 6428 } 6429 if (arg[a] == 0) 6430 { 6431 error ("argument %d of %qE must be in the range %d...%d", 6432 a + 1, fnname, 0, cgen_insn->regnums[a].count - 1); 6433 return NULL_RTX; 6434 } 6435 } 6436 6437 for (a = 0; a < first_arg; a++) 6438 { 6439 if (a == 0 && target && GET_MODE (target) == idata->operand[0].mode) 6440 arg[a] = target; 6441 else 6442 arg[a] = gen_reg_rtx (idata->operand[0].mode); 6443 } 6444 6445 /* Convert the arguments into a form suitable for the intrinsic. 6446 Report an error if this isn't possible. */ 6447 for (opindex = 0; opindex < idata->n_operands; opindex++) 6448 { 6449 a = cgen_insn->op_mapping[opindex]; 6450 op[opindex] = mep_legitimize_arg (&idata->operand[opindex], 6451 arg[a], unsigned_p[a]); 6452 if (op[opindex] == 0) 6453 { 6454 mep_incompatible_arg (&idata->operand[opindex], 6455 arg[a], a + 1 - first_arg, fnname); 6456 return NULL_RTX; 6457 } 6458 } 6459 6460 /* Emit the instruction. */ 6461 pat = idata->genfun (op[0], op[1], op[2], op[3], op[4], 6462 op[5], op[6], op[7], op[8], op[9]); 6463 6464 if (GET_CODE (pat) == SET 6465 && GET_CODE (SET_DEST (pat)) == PC 6466 && GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE) 6467 emit_jump_insn (pat); 6468 else 6469 emit_insn (pat); 6470 6471 /* Copy lvalues back to their final locations. */ 6472 for (opindex = 0; opindex < idata->n_operands; opindex++) 6473 if (idata->operand[opindex].constraint[0] == '=') 6474 { 6475 a = cgen_insn->op_mapping[opindex]; 6476 if (a >= first_arg) 6477 { 6478 if (GET_MODE_CLASS (GET_MODE (arg[a])) 6479 != GET_MODE_CLASS (GET_MODE (op[opindex]))) 6480 emit_move_insn (arg[a], gen_lowpart (GET_MODE (arg[a]), 6481 op[opindex])); 6482 else 6483 { 6484 /* First convert the operand to the right mode, then copy it 6485 into the destination. Doing the conversion as a separate 6486 step (rather than using convert_move) means that we can 6487 avoid creating no-op moves when ARG[A] and OP[OPINDEX] 6488 refer to the same register. */ 6489 op[opindex] = convert_to_mode (GET_MODE (arg[a]), 6490 op[opindex], unsigned_p[a]); 6491 if (!rtx_equal_p (arg[a], op[opindex])) 6492 emit_move_insn (arg[a], op[opindex]); 6493 } 6494 } 6495 } 6496 6497 if (first_arg > 0 && target && target != op[0]) 6498 { 6499 emit_move_insn (target, op[0]); 6500 } 6501 6502 return target; 6503} 6504 6505static bool 6506mep_vector_mode_supported_p (enum machine_mode mode ATTRIBUTE_UNUSED) 6507{ 6508 return false; 6509} 6510 6511/* A subroutine of global_reg_mentioned_p, returns 1 if *LOC mentions 6512 a global register. */ 6513 6514static int 6515global_reg_mentioned_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED) 6516{ 6517 int regno; 6518 rtx x = *loc; 6519 6520 if (! x) 6521 return 0; 6522 6523 switch (GET_CODE (x)) 6524 { 6525 case SUBREG: 6526 if (REG_P (SUBREG_REG (x))) 6527 { 6528 if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER 6529 && global_regs[subreg_regno (x)]) 6530 return 1; 6531 return 0; 6532 } 6533 break; 6534 6535 case REG: 6536 regno = REGNO (x); 6537 if (regno < FIRST_PSEUDO_REGISTER && global_regs[regno]) 6538 return 1; 6539 return 0; 6540 6541 case SCRATCH: 6542 case PC: 6543 case CC0: 6544 case CONST_INT: 6545 case CONST_DOUBLE: 6546 case CONST: 6547 case LABEL_REF: 6548 return 0; 6549 6550 case CALL: 6551 /* A non-constant call might use a global register. */ 6552 return 1; 6553 6554 default: 6555 break; 6556 } 6557 6558 return 0; 6559} 6560 6561/* Returns nonzero if X mentions a global register. */ 6562 6563static int 6564global_reg_mentioned_p (rtx x) 6565{ 6566 if (INSN_P (x)) 6567 { 6568 if (CALL_P (x)) 6569 { 6570 if (! RTL_CONST_OR_PURE_CALL_P (x)) 6571 return 1; 6572 x = CALL_INSN_FUNCTION_USAGE (x); 6573 if (x == 0) 6574 return 0; 6575 } 6576 else 6577 x = PATTERN (x); 6578 } 6579 6580 return for_each_rtx (&x, global_reg_mentioned_p_1, NULL); 6581} 6582/* Scheduling hooks for VLIW mode. 6583 6584 Conceptually this is very simple: we have a two-pack architecture 6585 that takes one core insn and one coprocessor insn to make up either 6586 a 32- or 64-bit instruction word (depending on the option bit set in 6587 the chip). I.e. in VL32 mode, we can pack one 16-bit core insn and 6588 one 16-bit cop insn; in VL64 mode we can pack one 16-bit core insn 6589 and one 48-bit cop insn or two 32-bit core/cop insns. 6590 6591 In practice, instruction selection will be a bear. Consider in 6592 VL64 mode the following insns 6593 6594 add $1, 1 6595 cmov $cr0, $0 6596 6597 these cannot pack, since the add is a 16-bit core insn and cmov 6598 is a 32-bit cop insn. However, 6599 6600 add3 $1, $1, 1 6601 cmov $cr0, $0 6602 6603 packs just fine. For good VLIW code generation in VL64 mode, we 6604 will have to have 32-bit alternatives for many of the common core 6605 insns. Not implemented. */ 6606 6607static int 6608mep_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost) 6609{ 6610 int cost_specified; 6611 6612 if (REG_NOTE_KIND (link) != 0) 6613 { 6614 /* See whether INSN and DEP_INSN are intrinsics that set the same 6615 hard register. If so, it is more important to free up DEP_INSN 6616 than it is to free up INSN. 6617 6618 Note that intrinsics like mep_mulr are handled differently from 6619 the equivalent mep.md patterns. In mep.md, if we don't care 6620 about the value of $lo and $hi, the pattern will just clobber 6621 the registers, not set them. Since clobbers don't count as 6622 output dependencies, it is often possible to reorder two mulrs, 6623 even after reload. 6624 6625 In contrast, mep_mulr() sets both $lo and $hi to specific values, 6626 so any pair of mep_mulr()s will be inter-dependent. We should 6627 therefore give the first mep_mulr() a higher priority. */ 6628 if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT 6629 && global_reg_mentioned_p (PATTERN (insn)) 6630 && global_reg_mentioned_p (PATTERN (dep_insn))) 6631 return 1; 6632 6633 /* If the dependence is an anti or output dependence, assume it 6634 has no cost. */ 6635 return 0; 6636 } 6637 6638 /* If we can't recognize the insns, we can't really do anything. */ 6639 if (recog_memoized (dep_insn) < 0) 6640 return cost; 6641 6642 /* The latency attribute doesn't apply to MeP-h1: we use the stall 6643 attribute instead. */ 6644 if (!TARGET_H1) 6645 { 6646 cost_specified = get_attr_latency (dep_insn); 6647 if (cost_specified != 0) 6648 return cost_specified; 6649 } 6650 6651 return cost; 6652} 6653 6654/* ??? We don't properly compute the length of a load/store insn, 6655 taking into account the addressing mode. */ 6656 6657static int 6658mep_issue_rate (void) 6659{ 6660 return TARGET_IVC2 ? 3 : 2; 6661} 6662 6663/* Return true if function DECL was declared with the vliw attribute. */ 6664 6665bool 6666mep_vliw_function_p (tree decl) 6667{ 6668 return lookup_attribute ("vliw", TYPE_ATTRIBUTES (TREE_TYPE (decl))) != 0; 6669} 6670 6671static rtx 6672mep_find_ready_insn (rtx *ready, int nready, enum attr_slot slot, int length) 6673{ 6674 int i; 6675 6676 for (i = nready - 1; i >= 0; --i) 6677 { 6678 rtx insn = ready[i]; 6679 if (recog_memoized (insn) >= 0 6680 && get_attr_slot (insn) == slot 6681 && get_attr_length (insn) == length) 6682 return insn; 6683 } 6684 6685 return NULL_RTX; 6686} 6687 6688static void 6689mep_move_ready_insn (rtx *ready, int nready, rtx insn) 6690{ 6691 int i; 6692 6693 for (i = 0; i < nready; ++i) 6694 if (ready[i] == insn) 6695 { 6696 for (; i < nready - 1; ++i) 6697 ready[i] = ready[i + 1]; 6698 ready[i] = insn; 6699 return; 6700 } 6701 6702 gcc_unreachable (); 6703} 6704 6705static void 6706mep_print_sched_insn (FILE *dump, rtx insn) 6707{ 6708 const char *slots = "none"; 6709 const char *name = NULL; 6710 int code; 6711 char buf[30]; 6712 6713 if (GET_CODE (PATTERN (insn)) == SET 6714 || GET_CODE (PATTERN (insn)) == PARALLEL) 6715 { 6716 switch (get_attr_slots (insn)) 6717 { 6718 case SLOTS_CORE: slots = "core"; break; 6719 case SLOTS_C3: slots = "c3"; break; 6720 case SLOTS_P0: slots = "p0"; break; 6721 case SLOTS_P0_P0S: slots = "p0,p0s"; break; 6722 case SLOTS_P0_P1: slots = "p0,p1"; break; 6723 case SLOTS_P0S: slots = "p0s"; break; 6724 case SLOTS_P0S_P1: slots = "p0s,p1"; break; 6725 case SLOTS_P1: slots = "p1"; break; 6726 default: 6727 sprintf(buf, "%d", get_attr_slots (insn)); 6728 slots = buf; 6729 break; 6730 } 6731 } 6732 if (GET_CODE (PATTERN (insn)) == USE) 6733 slots = "use"; 6734 6735 code = INSN_CODE (insn); 6736 if (code >= 0) 6737 name = get_insn_name (code); 6738 if (!name) 6739 name = "{unknown}"; 6740 6741 fprintf (dump, 6742 "insn %4d %4d %8s %s\n", 6743 code, 6744 INSN_UID (insn), 6745 name, 6746 slots); 6747} 6748 6749static int 6750mep_sched_reorder (FILE *dump ATTRIBUTE_UNUSED, 6751 int sched_verbose ATTRIBUTE_UNUSED, rtx *ready, 6752 int *pnready, int clock ATTRIBUTE_UNUSED) 6753{ 6754 int nready = *pnready; 6755 rtx core_insn, cop_insn; 6756 int i; 6757 6758 if (dump && sched_verbose > 1) 6759 { 6760 fprintf (dump, "\nsched_reorder: clock %d nready %d\n", clock, nready); 6761 for (i=0; i<nready; i++) 6762 mep_print_sched_insn (dump, ready[i]); 6763 fprintf (dump, "\n"); 6764 } 6765 6766 if (!mep_vliw_function_p (cfun->decl)) 6767 return 1; 6768 if (nready < 2) 6769 return 1; 6770 6771 /* IVC2 uses a DFA to determine what's ready and what's not. */ 6772 if (TARGET_IVC2) 6773 return nready; 6774 6775 /* We can issue either a core or coprocessor instruction. 6776 Look for a matched pair of insns to reorder. If we don't 6777 find any, don't second-guess the scheduler's priorities. */ 6778 6779 if ((core_insn = mep_find_ready_insn (ready, nready, SLOT_CORE, 2)) 6780 && (cop_insn = mep_find_ready_insn (ready, nready, SLOT_COP, 6781 TARGET_OPT_VL64 ? 6 : 2))) 6782 ; 6783 else if (TARGET_OPT_VL64 6784 && (core_insn = mep_find_ready_insn (ready, nready, SLOT_CORE, 4)) 6785 && (cop_insn = mep_find_ready_insn (ready, nready, SLOT_COP, 4))) 6786 ; 6787 else 6788 /* We didn't find a pair. Issue the single insn at the head 6789 of the ready list. */ 6790 return 1; 6791 6792 /* Reorder the two insns first. */ 6793 mep_move_ready_insn (ready, nready, core_insn); 6794 mep_move_ready_insn (ready, nready - 1, cop_insn); 6795 return 2; 6796} 6797 6798/* A for_each_rtx callback. Return true if *X is a register that is 6799 set by insn PREV. */ 6800 6801static int 6802mep_store_find_set (rtx *x, void *prev) 6803{ 6804 return REG_P (*x) && reg_set_p (*x, (const_rtx) prev); 6805} 6806 6807/* Like mep_store_bypass_p, but takes a pattern as the second argument, 6808 not the containing insn. */ 6809 6810static bool 6811mep_store_data_bypass_1 (rtx prev, rtx pat) 6812{ 6813 /* Cope with intrinsics like swcpa. */ 6814 if (GET_CODE (pat) == PARALLEL) 6815 { 6816 int i; 6817 6818 for (i = 0; i < XVECLEN (pat, 0); i++) 6819 if (mep_store_data_bypass_p (prev, XVECEXP (pat, 0, i))) 6820 return true; 6821 6822 return false; 6823 } 6824 6825 /* Check for some sort of store. */ 6826 if (GET_CODE (pat) != SET 6827 || GET_CODE (SET_DEST (pat)) != MEM) 6828 return false; 6829 6830 /* Intrinsics use patterns of the form (set (mem (scratch)) (unspec ...)). 6831 The first operand to the unspec is the store data and the other operands 6832 are used to calculate the address. */ 6833 if (GET_CODE (SET_SRC (pat)) == UNSPEC) 6834 { 6835 rtx src; 6836 int i; 6837 6838 src = SET_SRC (pat); 6839 for (i = 1; i < XVECLEN (src, 0); i++) 6840 if (for_each_rtx (&XVECEXP (src, 0, i), mep_store_find_set, prev)) 6841 return false; 6842 6843 return true; 6844 } 6845 6846 /* Otherwise just check that PREV doesn't modify any register mentioned 6847 in the memory destination. */ 6848 return !for_each_rtx (&SET_DEST (pat), mep_store_find_set, prev); 6849} 6850 6851/* Return true if INSN is a store instruction and if the store address 6852 has no true dependence on PREV. */ 6853 6854bool 6855mep_store_data_bypass_p (rtx prev, rtx insn) 6856{ 6857 return INSN_P (insn) ? mep_store_data_bypass_1 (prev, PATTERN (insn)) : false; 6858} 6859 6860/* A for_each_rtx subroutine of mep_mul_hilo_bypass_p. Return 1 if *X 6861 is a register other than LO or HI and if PREV sets *X. */ 6862 6863static int 6864mep_mul_hilo_bypass_1 (rtx *x, void *prev) 6865{ 6866 return (REG_P (*x) 6867 && REGNO (*x) != LO_REGNO 6868 && REGNO (*x) != HI_REGNO 6869 && reg_set_p (*x, (const_rtx) prev)); 6870} 6871 6872/* Return true if, apart from HI/LO, there are no true dependencies 6873 between multiplication instructions PREV and INSN. */ 6874 6875bool 6876mep_mul_hilo_bypass_p (rtx prev, rtx insn) 6877{ 6878 rtx pat; 6879 6880 pat = PATTERN (insn); 6881 if (GET_CODE (pat) == PARALLEL) 6882 pat = XVECEXP (pat, 0, 0); 6883 return (GET_CODE (pat) == SET 6884 && !for_each_rtx (&SET_SRC (pat), mep_mul_hilo_bypass_1, prev)); 6885} 6886 6887/* Return true if INSN is an ldc instruction that issues to the 6888 MeP-h1 integer pipeline. This is true for instructions that 6889 read from PSW, LP, SAR, HI and LO. */ 6890 6891bool 6892mep_ipipe_ldc_p (rtx insn) 6893{ 6894 rtx pat, src; 6895 6896 pat = PATTERN (insn); 6897 6898 /* Cope with instrinsics that set both a hard register and its shadow. 6899 The set of the hard register comes first. */ 6900 if (GET_CODE (pat) == PARALLEL) 6901 pat = XVECEXP (pat, 0, 0); 6902 6903 if (GET_CODE (pat) == SET) 6904 { 6905 src = SET_SRC (pat); 6906 6907 /* Cope with intrinsics. The first operand to the unspec is 6908 the source register. */ 6909 if (GET_CODE (src) == UNSPEC || GET_CODE (src) == UNSPEC_VOLATILE) 6910 src = XVECEXP (src, 0, 0); 6911 6912 if (REG_P (src)) 6913 switch (REGNO (src)) 6914 { 6915 case PSW_REGNO: 6916 case LP_REGNO: 6917 case SAR_REGNO: 6918 case HI_REGNO: 6919 case LO_REGNO: 6920 return true; 6921 } 6922 } 6923 return false; 6924} 6925 6926/* Create a VLIW bundle from core instruction CORE and coprocessor 6927 instruction COP. COP always satisfies INSN_P, but CORE can be 6928 either a new pattern or an existing instruction. 6929 6930 Emit the bundle in place of COP and return it. */ 6931 6932static rtx 6933mep_make_bundle (rtx core, rtx cop) 6934{ 6935 rtx insn; 6936 6937 /* If CORE is an existing instruction, remove it, otherwise put 6938 the new pattern in an INSN harness. */ 6939 if (INSN_P (core)) 6940 remove_insn (core); 6941 else 6942 core = make_insn_raw (core); 6943 6944 /* Generate the bundle sequence and replace COP with it. */ 6945 insn = gen_rtx_SEQUENCE (VOIDmode, gen_rtvec (2, core, cop)); 6946 insn = emit_insn_after (insn, cop); 6947 remove_insn (cop); 6948 6949 /* Set up the links of the insns inside the SEQUENCE. */ 6950 PREV_INSN (core) = PREV_INSN (insn); 6951 NEXT_INSN (core) = cop; 6952 PREV_INSN (cop) = core; 6953 NEXT_INSN (cop) = NEXT_INSN (insn); 6954 6955 /* Set the VLIW flag for the coprocessor instruction. */ 6956 PUT_MODE (core, VOIDmode); 6957 PUT_MODE (cop, BImode); 6958 6959 /* Derive a location for the bundle. Individual instructions cannot 6960 have their own location because there can be no assembler labels 6961 between CORE and COP. */ 6962 INSN_LOCATOR (insn) = INSN_LOCATOR (INSN_LOCATOR (core) ? core : cop); 6963 INSN_LOCATOR (core) = 0; 6964 INSN_LOCATOR (cop) = 0; 6965 6966 return insn; 6967} 6968 6969/* A helper routine for ms1_insn_dependent_p called through note_stores. */ 6970 6971static void 6972mep_insn_dependent_p_1 (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data) 6973{ 6974 rtx * pinsn = (rtx *) data; 6975 6976 if (*pinsn && reg_mentioned_p (x, *pinsn)) 6977 *pinsn = NULL_RTX; 6978} 6979 6980/* Return true if anything in insn X is (anti,output,true) dependent on 6981 anything in insn Y. */ 6982 6983static int 6984mep_insn_dependent_p (rtx x, rtx y) 6985{ 6986 rtx tmp; 6987 6988 gcc_assert (INSN_P (x)); 6989 gcc_assert (INSN_P (y)); 6990 6991 tmp = PATTERN (y); 6992 note_stores (PATTERN (x), mep_insn_dependent_p_1, &tmp); 6993 if (tmp == NULL_RTX) 6994 return 1; 6995 6996 tmp = PATTERN (x); 6997 note_stores (PATTERN (y), mep_insn_dependent_p_1, &tmp); 6998 if (tmp == NULL_RTX) 6999 return 1; 7000 7001 return 0; 7002} 7003 7004static int 7005core_insn_p (rtx insn) 7006{ 7007 if (GET_CODE (PATTERN (insn)) == USE) 7008 return 0; 7009 if (get_attr_slot (insn) == SLOT_CORE) 7010 return 1; 7011 return 0; 7012} 7013 7014/* Mark coprocessor instructions that can be bundled together with 7015 the immediately preceeding core instruction. This is later used 7016 to emit the "+" that tells the assembler to create a VLIW insn. 7017 7018 For unbundled insns, the assembler will automatically add coprocessor 7019 nops, and 16-bit core nops. Due to an apparent oversight in the 7020 spec, the assembler will _not_ automatically add 32-bit core nops, 7021 so we have to emit those here. 7022 7023 Called from mep_insn_reorg. */ 7024 7025static void 7026mep_bundle_insns (rtx insns) 7027{ 7028 rtx insn, last = NULL_RTX, first = NULL_RTX; 7029 int saw_scheduling = 0; 7030 7031 /* Only do bundling if we're in vliw mode. */ 7032 if (!mep_vliw_function_p (cfun->decl)) 7033 return; 7034 7035 /* The first insn in a bundle are TImode, the remainder are 7036 VOIDmode. After this function, the first has VOIDmode and the 7037 rest have BImode. */ 7038 7039 /* Note: this doesn't appear to be true for JUMP_INSNs. */ 7040 7041 /* First, move any NOTEs that are within a bundle, to the beginning 7042 of the bundle. */ 7043 for (insn = insns; insn ; insn = NEXT_INSN (insn)) 7044 { 7045 if (NOTE_P (insn) && first) 7046 /* Don't clear FIRST. */; 7047 7048 else if (NONJUMP_INSN_P (insn) && GET_MODE (insn) == TImode) 7049 first = insn; 7050 7051 else if (NONJUMP_INSN_P (insn) && GET_MODE (insn) == VOIDmode && first) 7052 { 7053 rtx note, prev; 7054 7055 /* INSN is part of a bundle; FIRST is the first insn in that 7056 bundle. Move all intervening notes out of the bundle. 7057 In addition, since the debug pass may insert a label 7058 whenever the current line changes, set the location info 7059 for INSN to match FIRST. */ 7060 7061 INSN_LOCATOR (insn) = INSN_LOCATOR (first); 7062 7063 note = PREV_INSN (insn); 7064 while (note && note != first) 7065 { 7066 prev = PREV_INSN (note); 7067 7068 if (NOTE_P (note)) 7069 { 7070 /* Remove NOTE from here... */ 7071 PREV_INSN (NEXT_INSN (note)) = PREV_INSN (note); 7072 NEXT_INSN (PREV_INSN (note)) = NEXT_INSN (note); 7073 /* ...and put it in here. */ 7074 NEXT_INSN (note) = first; 7075 PREV_INSN (note) = PREV_INSN (first); 7076 NEXT_INSN (PREV_INSN (note)) = note; 7077 PREV_INSN (NEXT_INSN (note)) = note; 7078 } 7079 7080 note = prev; 7081 } 7082 } 7083 7084 else if (!NONJUMP_INSN_P (insn)) 7085 first = 0; 7086 } 7087 7088 /* Now fix up the bundles. */ 7089 for (insn = insns; insn ; insn = NEXT_INSN (insn)) 7090 { 7091 if (NOTE_P (insn)) 7092 continue; 7093 7094 if (!NONJUMP_INSN_P (insn)) 7095 { 7096 last = 0; 7097 continue; 7098 } 7099 7100 /* If we're not optimizing enough, there won't be scheduling 7101 info. We detect that here. */ 7102 if (GET_MODE (insn) == TImode) 7103 saw_scheduling = 1; 7104 if (!saw_scheduling) 7105 continue; 7106 7107 if (TARGET_IVC2) 7108 { 7109 rtx core_insn = NULL_RTX; 7110 7111 /* IVC2 slots are scheduled by DFA, so we just accept 7112 whatever the scheduler gives us. However, we must make 7113 sure the core insn (if any) is the first in the bundle. 7114 The IVC2 assembler can insert whatever NOPs are needed, 7115 and allows a COP insn to be first. */ 7116 7117 if (NONJUMP_INSN_P (insn) 7118 && GET_CODE (PATTERN (insn)) != USE 7119 && GET_MODE (insn) == TImode) 7120 { 7121 for (last = insn; 7122 NEXT_INSN (last) 7123 && GET_MODE (NEXT_INSN (last)) == VOIDmode 7124 && NONJUMP_INSN_P (NEXT_INSN (last)); 7125 last = NEXT_INSN (last)) 7126 { 7127 if (core_insn_p (last)) 7128 core_insn = last; 7129 } 7130 if (core_insn_p (last)) 7131 core_insn = last; 7132 7133 if (core_insn && core_insn != insn) 7134 { 7135 /* Swap core insn to first in the bundle. */ 7136 7137 /* Remove core insn. */ 7138 if (PREV_INSN (core_insn)) 7139 NEXT_INSN (PREV_INSN (core_insn)) = NEXT_INSN (core_insn); 7140 if (NEXT_INSN (core_insn)) 7141 PREV_INSN (NEXT_INSN (core_insn)) = PREV_INSN (core_insn); 7142 7143 /* Re-insert core insn. */ 7144 PREV_INSN (core_insn) = PREV_INSN (insn); 7145 NEXT_INSN (core_insn) = insn; 7146 7147 if (PREV_INSN (core_insn)) 7148 NEXT_INSN (PREV_INSN (core_insn)) = core_insn; 7149 PREV_INSN (insn) = core_insn; 7150 7151 PUT_MODE (core_insn, TImode); 7152 PUT_MODE (insn, VOIDmode); 7153 } 7154 } 7155 7156 /* The first insn has TImode, the rest have VOIDmode */ 7157 if (GET_MODE (insn) == TImode) 7158 PUT_MODE (insn, VOIDmode); 7159 else 7160 PUT_MODE (insn, BImode); 7161 continue; 7162 } 7163 7164 PUT_MODE (insn, VOIDmode); 7165 if (recog_memoized (insn) >= 0 7166 && get_attr_slot (insn) == SLOT_COP) 7167 { 7168 if (GET_CODE (insn) == JUMP_INSN 7169 || ! last 7170 || recog_memoized (last) < 0 7171 || get_attr_slot (last) != SLOT_CORE 7172 || (get_attr_length (insn) 7173 != (TARGET_OPT_VL64 ? 8 : 4) - get_attr_length (last)) 7174 || mep_insn_dependent_p (insn, last)) 7175 { 7176 switch (get_attr_length (insn)) 7177 { 7178 case 8: 7179 break; 7180 case 6: 7181 insn = mep_make_bundle (gen_nop (), insn); 7182 break; 7183 case 4: 7184 if (TARGET_OPT_VL64) 7185 insn = mep_make_bundle (gen_nop32 (), insn); 7186 break; 7187 case 2: 7188 if (TARGET_OPT_VL64) 7189 error ("2 byte cop instructions are" 7190 " not allowed in 64-bit VLIW mode"); 7191 else 7192 insn = mep_make_bundle (gen_nop (), insn); 7193 break; 7194 default: 7195 error ("unexpected %d byte cop instruction", 7196 get_attr_length (insn)); 7197 break; 7198 } 7199 } 7200 else 7201 insn = mep_make_bundle (last, insn); 7202 } 7203 7204 last = insn; 7205 } 7206} 7207 7208 7209/* Try to instantiate INTRINSIC with the operands given in OPERANDS. 7210 Return true on success. This function can fail if the intrinsic 7211 is unavailable or if the operands don't satisfy their predicates. */ 7212 7213bool 7214mep_emit_intrinsic (int intrinsic, const rtx *operands) 7215{ 7216 const struct cgen_insn *cgen_insn; 7217 const struct insn_data *idata; 7218 rtx newop[10]; 7219 int i; 7220 7221 if (!mep_get_intrinsic_insn (intrinsic, &cgen_insn)) 7222 return false; 7223 7224 idata = &insn_data[cgen_insn->icode]; 7225 for (i = 0; i < idata->n_operands; i++) 7226 { 7227 newop[i] = mep_convert_arg (idata->operand[i].mode, operands[i]); 7228 if (!idata->operand[i].predicate (newop[i], idata->operand[i].mode)) 7229 return false; 7230 } 7231 7232 emit_insn (idata->genfun (newop[0], newop[1], newop[2], 7233 newop[3], newop[4], newop[5], 7234 newop[6], newop[7], newop[8])); 7235 7236 return true; 7237} 7238 7239 7240/* Apply the given unary intrinsic to OPERANDS[1] and store it on 7241 OPERANDS[0]. Report an error if the instruction could not 7242 be synthesized. OPERANDS[1] is a register_operand. For sign 7243 and zero extensions, it may be smaller than SImode. */ 7244 7245bool 7246mep_expand_unary_intrinsic (int ATTRIBUTE_UNUSED intrinsic, 7247 rtx * operands ATTRIBUTE_UNUSED) 7248{ 7249 return false; 7250} 7251 7252 7253/* Likewise, but apply a binary operation to OPERANDS[1] and 7254 OPERANDS[2]. OPERANDS[1] is a register_operand, OPERANDS[2] 7255 can be a general_operand. 7256 7257 IMMEDIATE and IMMEDIATE3 are intrinsics that take an immediate 7258 third operand. REG and REG3 take register operands only. */ 7259 7260bool 7261mep_expand_binary_intrinsic (int ATTRIBUTE_UNUSED immediate, 7262 int ATTRIBUTE_UNUSED immediate3, 7263 int ATTRIBUTE_UNUSED reg, 7264 int ATTRIBUTE_UNUSED reg3, 7265 rtx * operands ATTRIBUTE_UNUSED) 7266{ 7267 return false; 7268} 7269 7270static bool 7271mep_rtx_cost (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total, bool ATTRIBUTE_UNUSED speed_t) 7272{ 7273 switch (code) 7274 { 7275 case CONST_INT: 7276 if (INTVAL (x) >= -128 && INTVAL (x) < 127) 7277 *total = 0; 7278 else if (INTVAL (x) >= -32768 && INTVAL (x) < 65536) 7279 *total = 1; 7280 else 7281 *total = 3; 7282 return true; 7283 7284 case SYMBOL_REF: 7285 *total = optimize_size ? COSTS_N_INSNS (0) : COSTS_N_INSNS (1); 7286 return true; 7287 7288 case MULT: 7289 *total = (GET_CODE (XEXP (x, 1)) == CONST_INT 7290 ? COSTS_N_INSNS (3) 7291 : COSTS_N_INSNS (2)); 7292 return true; 7293 } 7294 return false; 7295} 7296 7297static int 7298mep_address_cost (rtx addr ATTRIBUTE_UNUSED, bool ATTRIBUTE_UNUSED speed_p) 7299{ 7300 return 1; 7301} 7302 7303static bool 7304mep_handle_option (size_t code, 7305 const char *arg ATTRIBUTE_UNUSED, 7306 int value ATTRIBUTE_UNUSED) 7307{ 7308 int i; 7309 7310 switch (code) 7311 { 7312 case OPT_mall_opts: 7313 target_flags |= MEP_ALL_OPTS; 7314 break; 7315 7316 case OPT_mno_opts: 7317 target_flags &= ~ MEP_ALL_OPTS; 7318 break; 7319 7320 case OPT_mcop64: 7321 target_flags |= MASK_COP; 7322 target_flags |= MASK_64BIT_CR_REGS; 7323 break; 7324 7325 case OPT_mtiny_: 7326 option_mtiny_specified = 1; 7327 7328 case OPT_mivc2: 7329 target_flags |= MASK_COP; 7330 target_flags |= MASK_64BIT_CR_REGS; 7331 target_flags |= MASK_VLIW; 7332 target_flags |= MASK_OPT_VL64; 7333 target_flags |= MASK_IVC2; 7334 7335 for (i=0; i<32; i++) 7336 fixed_regs[i+48] = 0; 7337 for (i=0; i<32; i++) 7338 call_used_regs[i+48] = 1; 7339 for (i=6; i<8; i++) 7340 call_used_regs[i+48] = 0; 7341 7342#define RN(n,s) reg_names[FIRST_CCR_REGNO + n] = s 7343 RN (0, "$csar0"); 7344 RN (1, "$cc"); 7345 RN (4, "$cofr0"); 7346 RN (5, "$cofr1"); 7347 RN (6, "$cofa0"); 7348 RN (7, "$cofa1"); 7349 RN (15, "$csar1"); 7350 7351 RN (16, "$acc0_0"); 7352 RN (17, "$acc0_1"); 7353 RN (18, "$acc0_2"); 7354 RN (19, "$acc0_3"); 7355 RN (20, "$acc0_4"); 7356 RN (21, "$acc0_5"); 7357 RN (22, "$acc0_6"); 7358 RN (23, "$acc0_7"); 7359 7360 RN (24, "$acc1_0"); 7361 RN (25, "$acc1_1"); 7362 RN (26, "$acc1_2"); 7363 RN (27, "$acc1_3"); 7364 RN (28, "$acc1_4"); 7365 RN (29, "$acc1_5"); 7366 RN (30, "$acc1_6"); 7367 RN (31, "$acc1_7"); 7368#undef RN 7369 7370 break; 7371 7372 default: 7373 break; 7374 } 7375 return TRUE; 7376} 7377 7378static void 7379mep_asm_init_sections (void) 7380{ 7381 based_section 7382 = get_unnamed_section (SECTION_WRITE, output_section_asm_op, 7383 "\t.section .based,\"aw\""); 7384 7385 tinybss_section 7386 = get_unnamed_section (SECTION_WRITE | SECTION_BSS, output_section_asm_op, 7387 "\t.section .sbss,\"aw\""); 7388 7389 sdata_section 7390 = get_unnamed_section (SECTION_WRITE, output_section_asm_op, 7391 "\t.section .sdata,\"aw\",@progbits"); 7392 7393 far_section 7394 = get_unnamed_section (SECTION_WRITE, output_section_asm_op, 7395 "\t.section .far,\"aw\""); 7396 7397 farbss_section 7398 = get_unnamed_section (SECTION_WRITE | SECTION_BSS, output_section_asm_op, 7399 "\t.section .farbss,\"aw\""); 7400 7401 frodata_section 7402 = get_unnamed_section (0, output_section_asm_op, 7403 "\t.section .frodata,\"a\""); 7404 7405 srodata_section 7406 = get_unnamed_section (0, output_section_asm_op, 7407 "\t.section .srodata,\"a\""); 7408 7409 vtext_section 7410 = get_unnamed_section (SECTION_CODE | SECTION_MEP_VLIW, output_section_asm_op, 7411 "\t.section .vtext,\"axv\"\n\t.vliw"); 7412 7413 vftext_section 7414 = get_unnamed_section (SECTION_CODE | SECTION_MEP_VLIW, output_section_asm_op, 7415 "\t.section .vftext,\"axv\"\n\t.vliw"); 7416 7417 ftext_section 7418 = get_unnamed_section (SECTION_CODE, output_section_asm_op, 7419 "\t.section .ftext,\"ax\"\n\t.core"); 7420 7421} 7422 7423#include "gt-mep.h" 7424