00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "rtl.h"
00026 #include "tree.h"
00027 #include "regs.h"
00028 #include "hard-reg-set.h"
00029 #include "real.h"
00030 #include "insn-config.h"
00031 #include "conditions.h"
00032 #include "output.h"
00033 #include "insn-attr.h"
00034 #include "flags.h"
00035 #include "recog.h"
00036 #include "expr.h"
00037 #include "optabs.h"
00038 #include "except.h"
00039 #include "function.h"
00040 #include "ggc.h"
00041 #include "basic-block.h"
00042 #include "toplev.h"
00043 #include "sched-int.h"
00044 #include "timevar.h"
00045 #include "target.h"
00046 #include "target-def.h"
00047 #include "tm_p.h"
00048 #include "langhooks.h"
00049
00050
00051
00052 int ia64_asm_output_label = 0;
00053
00054
00055
00056 struct rtx_def * ia64_compare_op0;
00057 struct rtx_def * ia64_compare_op1;
00058
00059
00060 static const char * const ia64_reg_numbers[96] =
00061 { "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
00062 "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
00063 "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
00064 "r56", "r57", "r58", "r59", "r60", "r61", "r62", "r63",
00065 "r64", "r65", "r66", "r67", "r68", "r69", "r70", "r71",
00066 "r72", "r73", "r74", "r75", "r76", "r77", "r78", "r79",
00067 "r80", "r81", "r82", "r83", "r84", "r85", "r86", "r87",
00068 "r88", "r89", "r90", "r91", "r92", "r93", "r94", "r95",
00069 "r96", "r97", "r98", "r99", "r100","r101","r102","r103",
00070 "r104","r105","r106","r107","r108","r109","r110","r111",
00071 "r112","r113","r114","r115","r116","r117","r118","r119",
00072 "r120","r121","r122","r123","r124","r125","r126","r127"};
00073
00074
00075 static const char * const ia64_input_reg_names[8] =
00076 { "in0", "in1", "in2", "in3", "in4", "in5", "in6", "in7" };
00077
00078
00079 static const char * const ia64_local_reg_names[80] =
00080 { "loc0", "loc1", "loc2", "loc3", "loc4", "loc5", "loc6", "loc7",
00081 "loc8", "loc9", "loc10","loc11","loc12","loc13","loc14","loc15",
00082 "loc16","loc17","loc18","loc19","loc20","loc21","loc22","loc23",
00083 "loc24","loc25","loc26","loc27","loc28","loc29","loc30","loc31",
00084 "loc32","loc33","loc34","loc35","loc36","loc37","loc38","loc39",
00085 "loc40","loc41","loc42","loc43","loc44","loc45","loc46","loc47",
00086 "loc48","loc49","loc50","loc51","loc52","loc53","loc54","loc55",
00087 "loc56","loc57","loc58","loc59","loc60","loc61","loc62","loc63",
00088 "loc64","loc65","loc66","loc67","loc68","loc69","loc70","loc71",
00089 "loc72","loc73","loc74","loc75","loc76","loc77","loc78","loc79" };
00090
00091
00092 static const char * const ia64_output_reg_names[8] =
00093 { "out0", "out1", "out2", "out3", "out4", "out5", "out6", "out7" };
00094
00095
00096 const char *ia64_fixed_range_string;
00097
00098
00099
00100 int ia64_tls_size = 22;
00101
00102
00103 const char *ia64_tls_size_string;
00104
00105
00106
00107 static int ia64_flag_schedule_insns2;
00108
00109
00110
00111
00112 unsigned int ia64_section_threshold;
00113
00114
00115
00116
00117 struct ia64_frame_info
00118 {
00119 HOST_WIDE_INT total_size;
00120
00121 HOST_WIDE_INT spill_cfa_off;
00122 HOST_WIDE_INT spill_size;
00123 HOST_WIDE_INT extra_spill_size;
00124 HARD_REG_SET mask;
00125 unsigned int gr_used_mask;
00126
00127 int n_spilled;
00128 int reg_fp;
00129 int reg_save_b0;
00130 int reg_save_pr;
00131 int reg_save_ar_pfs;
00132 int reg_save_ar_unat;
00133 int reg_save_ar_lc;
00134 int reg_save_gp;
00135 int n_input_regs;
00136 int n_local_regs;
00137 int n_output_regs;
00138 int n_rotate_regs;
00139
00140 char need_regstk;
00141 char initialized;
00142 };
00143
00144
00145 static struct ia64_frame_info current_frame_info;
00146
00147 static rtx gen_tls_get_addr PARAMS ((void));
00148 static rtx gen_thread_pointer PARAMS ((void));
00149 static int find_gr_spill PARAMS ((int));
00150 static int next_scratch_gr_reg PARAMS ((void));
00151 static void mark_reg_gr_used_mask PARAMS ((rtx, void *));
00152 static void ia64_compute_frame_size PARAMS ((HOST_WIDE_INT));
00153 static void setup_spill_pointers PARAMS ((int, rtx, HOST_WIDE_INT));
00154 static void finish_spill_pointers PARAMS ((void));
00155 static rtx spill_restore_mem PARAMS ((rtx, HOST_WIDE_INT));
00156 static void do_spill PARAMS ((rtx (*)(rtx, rtx, rtx), rtx, HOST_WIDE_INT, rtx));
00157 static void do_restore PARAMS ((rtx (*)(rtx, rtx, rtx), rtx, HOST_WIDE_INT));
00158 static rtx gen_movdi_x PARAMS ((rtx, rtx, rtx));
00159 static rtx gen_fr_spill_x PARAMS ((rtx, rtx, rtx));
00160 static rtx gen_fr_restore_x PARAMS ((rtx, rtx, rtx));
00161
00162 static enum machine_mode hfa_element_mode PARAMS ((tree, int));
00163 static void fix_range PARAMS ((const char *));
00164 static struct machine_function * ia64_init_machine_status PARAMS ((void));
00165 static void emit_insn_group_barriers PARAMS ((FILE *, rtx));
00166 static void emit_all_insn_group_barriers PARAMS ((FILE *, rtx));
00167 static void emit_predicate_relation_info PARAMS ((void));
00168 static bool ia64_in_small_data_p PARAMS ((tree));
00169 static void ia64_encode_section_info PARAMS ((tree, int));
00170 static const char *ia64_strip_name_encoding PARAMS ((const char *));
00171 static void process_epilogue PARAMS ((void));
00172 static int process_set PARAMS ((FILE *, rtx));
00173
00174 static rtx ia64_expand_fetch_and_op PARAMS ((optab, enum machine_mode,
00175 tree, rtx));
00176 static rtx ia64_expand_op_and_fetch PARAMS ((optab, enum machine_mode,
00177 tree, rtx));
00178 static rtx ia64_expand_compare_and_swap PARAMS ((enum machine_mode, int,
00179 tree, rtx));
00180 static rtx ia64_expand_lock_test_and_set PARAMS ((enum machine_mode,
00181 tree, rtx));
00182 static rtx ia64_expand_lock_release PARAMS ((enum machine_mode, tree, rtx));
00183 static bool ia64_assemble_integer PARAMS ((rtx, unsigned int, int));
00184 static void ia64_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
00185 static void ia64_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00186 static void ia64_output_function_end_prologue PARAMS ((FILE *));
00187
00188 static int ia64_issue_rate PARAMS ((void));
00189 static int ia64_adjust_cost PARAMS ((rtx, rtx, rtx, int));
00190 static void ia64_sched_init PARAMS ((FILE *, int, int));
00191 static void ia64_sched_finish PARAMS ((FILE *, int));
00192 static int ia64_internal_sched_reorder PARAMS ((FILE *, int, rtx *,
00193 int *, int, int));
00194 static int ia64_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));
00195 static int ia64_sched_reorder2 PARAMS ((FILE *, int, rtx *, int *, int));
00196 static int ia64_variable_issue PARAMS ((FILE *, int, rtx, int));
00197
00198 static void ia64_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
00199 HOST_WIDE_INT, tree));
00200
00201 static void ia64_select_rtx_section PARAMS ((enum machine_mode, rtx,
00202 unsigned HOST_WIDE_INT));
00203 static void ia64_rwreloc_select_section PARAMS ((tree, int,
00204 unsigned HOST_WIDE_INT))
00205 ATTRIBUTE_UNUSED;
00206 static void ia64_rwreloc_unique_section PARAMS ((tree, int))
00207 ATTRIBUTE_UNUSED;
00208 static void ia64_rwreloc_select_rtx_section PARAMS ((enum machine_mode, rtx,
00209 unsigned HOST_WIDE_INT))
00210 ATTRIBUTE_UNUSED;
00211 static unsigned int ia64_rwreloc_section_type_flags
00212 PARAMS ((tree, const char *, int))
00213 ATTRIBUTE_UNUSED;
00214
00215 static void ia64_hpux_add_extern_decl PARAMS ((const char *name))
00216 ATTRIBUTE_UNUSED;
00217
00218
00219 static const struct attribute_spec ia64_attribute_table[] =
00220 {
00221
00222 { "syscall_linkage", 0, 0, false, true, true, NULL },
00223 { NULL, 0, 0, false, false, false, NULL }
00224 };
00225
00226
00227 #undef TARGET_ATTRIBUTE_TABLE
00228 #define TARGET_ATTRIBUTE_TABLE ia64_attribute_table
00229
00230 #undef TARGET_INIT_BUILTINS
00231 #define TARGET_INIT_BUILTINS ia64_init_builtins
00232
00233 #undef TARGET_EXPAND_BUILTIN
00234 #define TARGET_EXPAND_BUILTIN ia64_expand_builtin
00235
00236 #undef TARGET_ASM_BYTE_OP
00237 #define TARGET_ASM_BYTE_OP "\tdata1\t"
00238 #undef TARGET_ASM_ALIGNED_HI_OP
00239 #define TARGET_ASM_ALIGNED_HI_OP "\tdata2\t"
00240 #undef TARGET_ASM_ALIGNED_SI_OP
00241 #define TARGET_ASM_ALIGNED_SI_OP "\tdata4\t"
00242 #undef TARGET_ASM_ALIGNED_DI_OP
00243 #define TARGET_ASM_ALIGNED_DI_OP "\tdata8\t"
00244 #undef TARGET_ASM_UNALIGNED_HI_OP
00245 #define TARGET_ASM_UNALIGNED_HI_OP "\tdata2.ua\t"
00246 #undef TARGET_ASM_UNALIGNED_SI_OP
00247 #define TARGET_ASM_UNALIGNED_SI_OP "\tdata4.ua\t"
00248 #undef TARGET_ASM_UNALIGNED_DI_OP
00249 #define TARGET_ASM_UNALIGNED_DI_OP "\tdata8.ua\t"
00250 #undef TARGET_ASM_INTEGER
00251 #define TARGET_ASM_INTEGER ia64_assemble_integer
00252
00253 #undef TARGET_ASM_FUNCTION_PROLOGUE
00254 #define TARGET_ASM_FUNCTION_PROLOGUE ia64_output_function_prologue
00255 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
00256 #define TARGET_ASM_FUNCTION_END_PROLOGUE ia64_output_function_end_prologue
00257 #undef TARGET_ASM_FUNCTION_EPILOGUE
00258 #define TARGET_ASM_FUNCTION_EPILOGUE ia64_output_function_epilogue
00259
00260 #undef TARGET_IN_SMALL_DATA_P
00261 #define TARGET_IN_SMALL_DATA_P ia64_in_small_data_p
00262 #undef TARGET_ENCODE_SECTION_INFO
00263 #define TARGET_ENCODE_SECTION_INFO ia64_encode_section_info
00264 #undef TARGET_STRIP_NAME_ENCODING
00265 #define TARGET_STRIP_NAME_ENCODING ia64_strip_name_encoding
00266
00267 #undef TARGET_SCHED_ADJUST_COST
00268 #define TARGET_SCHED_ADJUST_COST ia64_adjust_cost
00269 #undef TARGET_SCHED_ISSUE_RATE
00270 #define TARGET_SCHED_ISSUE_RATE ia64_issue_rate
00271 #undef TARGET_SCHED_VARIABLE_ISSUE
00272 #define TARGET_SCHED_VARIABLE_ISSUE ia64_variable_issue
00273 #undef TARGET_SCHED_INIT
00274 #define TARGET_SCHED_INIT ia64_sched_init
00275 #undef TARGET_SCHED_FINISH
00276 #define TARGET_SCHED_FINISH ia64_sched_finish
00277 #undef TARGET_SCHED_REORDER
00278 #define TARGET_SCHED_REORDER ia64_sched_reorder
00279 #undef TARGET_SCHED_REORDER2
00280 #define TARGET_SCHED_REORDER2 ia64_sched_reorder2
00281
00282 #ifdef HAVE_AS_TLS
00283 #undef TARGET_HAVE_TLS
00284 #define TARGET_HAVE_TLS true
00285 #endif
00286
00287 #undef TARGET_ASM_OUTPUT_MI_THUNK
00288 #define TARGET_ASM_OUTPUT_MI_THUNK ia64_output_mi_thunk
00289 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
00290 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
00291
00292 struct gcc_target targetm = TARGET_INITIALIZER;
00293
00294
00295
00296 int
00297 call_operand (op, mode)
00298 rtx op;
00299 enum machine_mode mode;
00300 {
00301 if (mode != GET_MODE (op) && mode != VOIDmode)
00302 return 0;
00303
00304 return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG
00305 || (GET_CODE (op) == SUBREG && GET_CODE (XEXP (op, 0)) == REG));
00306 }
00307
00308
00309
00310 int
00311 sdata_symbolic_operand (op, mode)
00312 rtx op;
00313 enum machine_mode mode ATTRIBUTE_UNUSED;
00314 {
00315 switch (GET_CODE (op))
00316 {
00317 case CONST:
00318 if (GET_CODE (XEXP (op, 0)) != PLUS
00319 || GET_CODE (XEXP (XEXP (op, 0), 0)) != SYMBOL_REF)
00320 break;
00321 op = XEXP (XEXP (op, 0), 0);
00322
00323
00324 case SYMBOL_REF:
00325 if (CONSTANT_POOL_ADDRESS_P (op))
00326 return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold;
00327 else
00328 {
00329 const char *str = XSTR (op, 0);
00330 return (str[0] == ENCODE_SECTION_INFO_CHAR && str[1] == 's');
00331 }
00332
00333 default:
00334 break;
00335 }
00336
00337 return 0;
00338 }
00339
00340
00341
00342 int
00343 got_symbolic_operand (op, mode)
00344 rtx op;
00345 enum machine_mode mode ATTRIBUTE_UNUSED;
00346 {
00347 switch (GET_CODE (op))
00348 {
00349 case CONST:
00350 op = XEXP (op, 0);
00351 if (GET_CODE (op) != PLUS)
00352 return 0;
00353 if (GET_CODE (XEXP (op, 0)) != SYMBOL_REF)
00354 return 0;
00355 op = XEXP (op, 1);
00356 if (GET_CODE (op) != CONST_INT)
00357 return 0;
00358
00359 return 1;
00360
00361
00362 if (TARGET_NO_PIC || TARGET_AUTO_PIC)
00363 return 1;
00364
00365
00366
00367
00368 if (rtx_equal_function_value_matters)
00369 return 1;
00370
00371
00372
00373 return (INTVAL (op) & 0x3fff) == 0;
00374
00375 case SYMBOL_REF:
00376 case LABEL_REF:
00377 return 1;
00378
00379 default:
00380 break;
00381 }
00382 return 0;
00383 }
00384
00385
00386
00387 int
00388 symbolic_operand (op, mode)
00389 rtx op;
00390 enum machine_mode mode ATTRIBUTE_UNUSED;
00391 {
00392 switch (GET_CODE (op))
00393 {
00394 case CONST:
00395 case SYMBOL_REF:
00396 case LABEL_REF:
00397 return 1;
00398
00399 default:
00400 break;
00401 }
00402 return 0;
00403 }
00404
00405
00406
00407 int
00408 tls_symbolic_operand (op, mode)
00409 rtx op;
00410 enum machine_mode mode ATTRIBUTE_UNUSED;
00411 {
00412 const char *str;
00413
00414 if (GET_CODE (op) != SYMBOL_REF)
00415 return 0;
00416 str = XSTR (op, 0);
00417 if (str[0] != ENCODE_SECTION_INFO_CHAR)
00418 return 0;
00419 switch (str[1])
00420 {
00421 case 'G':
00422 return TLS_MODEL_GLOBAL_DYNAMIC;
00423 case 'L':
00424 return TLS_MODEL_LOCAL_DYNAMIC;
00425 case 'i':
00426 return TLS_MODEL_INITIAL_EXEC;
00427 case 'l':
00428 return TLS_MODEL_LOCAL_EXEC;
00429 }
00430 return 0;
00431 }
00432
00433
00434
00435
00436 int
00437 function_operand (op, mode)
00438 rtx op;
00439 enum machine_mode mode ATTRIBUTE_UNUSED;
00440 {
00441 if (GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_FLAG (op))
00442 return 1;
00443 else
00444 return 0;
00445 }
00446
00447
00448
00449
00450
00451 int
00452 setjmp_operand (op, mode)
00453 rtx op;
00454 enum machine_mode mode ATTRIBUTE_UNUSED;
00455 {
00456 const char *name;
00457 int retval = 0;
00458
00459 if (GET_CODE (op) != SYMBOL_REF)
00460 return 0;
00461
00462 name = XSTR (op, 0);
00463
00464
00465
00466
00467 if (name[0] == '_')
00468 {
00469 if (name[1] == '_' && name[2] == 'x')
00470 name += 3;
00471 else if (name[1] == '_')
00472 name += 2;
00473 else
00474 name += 1;
00475 }
00476
00477 if (name[0] == 's')
00478 {
00479 retval
00480 = ((name[1] == 'e'
00481 && (! strcmp (name, "setjmp")
00482 || ! strcmp (name, "setjmp_syscall")))
00483 || (name[1] == 'i'
00484 && ! strcmp (name, "sigsetjmp"))
00485 || (name[1] == 'a'
00486 && ! strcmp (name, "savectx")));
00487 }
00488 else if ((name[0] == 'q' && name[1] == 's'
00489 && ! strcmp (name, "qsetjmp"))
00490 || (name[0] == 'v' && name[1] == 'f'
00491 && ! strcmp (name, "vfork")))
00492 retval = 1;
00493
00494 return retval;
00495 }
00496
00497
00498
00499
00500
00501
00502
00503 int
00504 move_operand (op, mode)
00505 rtx op;
00506 enum machine_mode mode;
00507 {
00508 if (! TARGET_NO_PIC && symbolic_operand (op, mode))
00509 return 0;
00510
00511 return general_operand (op, mode);
00512 }
00513
00514
00515
00516 int
00517 gr_register_operand (op, mode)
00518 rtx op;
00519 enum machine_mode mode;
00520 {
00521 if (! register_operand (op, mode))
00522 return 0;
00523 if (GET_CODE (op) == SUBREG)
00524 op = SUBREG_REG (op);
00525 if (GET_CODE (op) == REG)
00526 {
00527 unsigned int regno = REGNO (op);
00528 if (regno < FIRST_PSEUDO_REGISTER)
00529 return GENERAL_REGNO_P (regno);
00530 }
00531 return 1;
00532 }
00533
00534
00535
00536 int
00537 fr_register_operand (op, mode)
00538 rtx op;
00539 enum machine_mode mode;
00540 {
00541 if (! register_operand (op, mode))
00542 return 0;
00543 if (GET_CODE (op) == SUBREG)
00544 op = SUBREG_REG (op);
00545 if (GET_CODE (op) == REG)
00546 {
00547 unsigned int regno = REGNO (op);
00548 if (regno < FIRST_PSEUDO_REGISTER)
00549 return FR_REGNO_P (regno);
00550 }
00551 return 1;
00552 }
00553
00554
00555
00556 int
00557 grfr_register_operand (op, mode)
00558 rtx op;
00559 enum machine_mode mode;
00560 {
00561 if (! register_operand (op, mode))
00562 return 0;
00563 if (GET_CODE (op) == SUBREG)
00564 op = SUBREG_REG (op);
00565 if (GET_CODE (op) == REG)
00566 {
00567 unsigned int regno = REGNO (op);
00568 if (regno < FIRST_PSEUDO_REGISTER)
00569 return GENERAL_REGNO_P (regno) || FR_REGNO_P (regno);
00570 }
00571 return 1;
00572 }
00573
00574
00575
00576 int
00577 gr_nonimmediate_operand (op, mode)
00578 rtx op;
00579 enum machine_mode mode;
00580 {
00581 if (! nonimmediate_operand (op, mode))
00582 return 0;
00583 if (GET_CODE (op) == SUBREG)
00584 op = SUBREG_REG (op);
00585 if (GET_CODE (op) == REG)
00586 {
00587 unsigned int regno = REGNO (op);
00588 if (regno < FIRST_PSEUDO_REGISTER)
00589 return GENERAL_REGNO_P (regno);
00590 }
00591 return 1;
00592 }
00593
00594
00595
00596 int
00597 fr_nonimmediate_operand (op, mode)
00598 rtx op;
00599 enum machine_mode mode;
00600 {
00601 if (! nonimmediate_operand (op, mode))
00602 return 0;
00603 if (GET_CODE (op) == SUBREG)
00604 op = SUBREG_REG (op);
00605 if (GET_CODE (op) == REG)
00606 {
00607 unsigned int regno = REGNO (op);
00608 if (regno < FIRST_PSEUDO_REGISTER)
00609 return FR_REGNO_P (regno);
00610 }
00611 return 1;
00612 }
00613
00614
00615
00616 int
00617 grfr_nonimmediate_operand (op, mode)
00618 rtx op;
00619 enum machine_mode mode;
00620 {
00621 if (! nonimmediate_operand (op, mode))
00622 return 0;
00623 if (GET_CODE (op) == SUBREG)
00624 op = SUBREG_REG (op);
00625 if (GET_CODE (op) == REG)
00626 {
00627 unsigned int regno = REGNO (op);
00628 if (regno < FIRST_PSEUDO_REGISTER)
00629 return GENERAL_REGNO_P (regno) || FR_REGNO_P (regno);
00630 }
00631 return 1;
00632 }
00633
00634
00635
00636 int
00637 gr_reg_or_0_operand (op, mode)
00638 rtx op;
00639 enum machine_mode mode;
00640 {
00641 return (op == const0_rtx || gr_register_operand (op, mode));
00642 }
00643
00644
00645
00646 int
00647 gr_reg_or_5bit_operand (op, mode)
00648 rtx op;
00649 enum machine_mode mode;
00650 {
00651 return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) < 32)
00652 || GET_CODE (op) == CONSTANT_P_RTX
00653 || gr_register_operand (op, mode));
00654 }
00655
00656
00657
00658 int
00659 gr_reg_or_6bit_operand (op, mode)
00660 rtx op;
00661 enum machine_mode mode;
00662 {
00663 return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op)))
00664 || GET_CODE (op) == CONSTANT_P_RTX
00665 || gr_register_operand (op, mode));
00666 }
00667
00668
00669
00670 int
00671 gr_reg_or_8bit_operand (op, mode)
00672 rtx op;
00673 enum machine_mode mode;
00674 {
00675 return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
00676 || GET_CODE (op) == CONSTANT_P_RTX
00677 || gr_register_operand (op, mode));
00678 }
00679
00680
00681
00682 int
00683 grfr_reg_or_8bit_operand (op, mode)
00684 rtx op;
00685 enum machine_mode mode;
00686 {
00687 return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
00688 || GET_CODE (op) == CONSTANT_P_RTX
00689 || grfr_register_operand (op, mode));
00690 }
00691
00692
00693
00694
00695 int
00696 gr_reg_or_8bit_adjusted_operand (op, mode)
00697 rtx op;
00698 enum machine_mode mode;
00699 {
00700 return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op)))
00701 || GET_CODE (op) == CONSTANT_P_RTX
00702 || gr_register_operand (op, mode));
00703 }
00704
00705
00706
00707
00708
00709
00710 int
00711 gr_reg_or_8bit_and_adjusted_operand (op, mode)
00712 rtx op;
00713 enum machine_mode mode;
00714 {
00715 return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op))
00716 && CONST_OK_FOR_L (INTVAL (op)))
00717 || GET_CODE (op) == CONSTANT_P_RTX
00718 || gr_register_operand (op, mode));
00719 }
00720
00721
00722
00723 int
00724 gr_reg_or_14bit_operand (op, mode)
00725 rtx op;
00726 enum machine_mode mode;
00727 {
00728 return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op)))
00729 || GET_CODE (op) == CONSTANT_P_RTX
00730 || gr_register_operand (op, mode));
00731 }
00732
00733
00734
00735 int
00736 gr_reg_or_22bit_operand (op, mode)
00737 rtx op;
00738 enum machine_mode mode;
00739 {
00740 return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_J (INTVAL (op)))
00741 || GET_CODE (op) == CONSTANT_P_RTX
00742 || gr_register_operand (op, mode));
00743 }
00744
00745
00746
00747 int
00748 shift_count_operand (op, mode)
00749 rtx op;
00750 enum machine_mode mode ATTRIBUTE_UNUSED;
00751 {
00752 return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op)))
00753 || GET_CODE (op) == CONSTANT_P_RTX);
00754 }
00755
00756
00757
00758 int
00759 shift_32bit_count_operand (op, mode)
00760 rtx op;
00761 enum machine_mode mode ATTRIBUTE_UNUSED;
00762 {
00763 return ((GET_CODE (op) == CONST_INT
00764 && (INTVAL (op) >= 0 && INTVAL (op) < 32))
00765 || GET_CODE (op) == CONSTANT_P_RTX);
00766 }
00767
00768
00769
00770 int
00771 shladd_operand (op, mode)
00772 rtx op;
00773 enum machine_mode mode ATTRIBUTE_UNUSED;
00774 {
00775 return (GET_CODE (op) == CONST_INT
00776 && (INTVAL (op) == 2 || INTVAL (op) == 4
00777 || INTVAL (op) == 8 || INTVAL (op) == 16));
00778 }
00779
00780
00781
00782 int
00783 fetchadd_operand (op, mode)
00784 rtx op;
00785 enum machine_mode mode ATTRIBUTE_UNUSED;
00786 {
00787 return (GET_CODE (op) == CONST_INT
00788 && (INTVAL (op) == -16 || INTVAL (op) == -8 ||
00789 INTVAL (op) == -4 || INTVAL (op) == -1 ||
00790 INTVAL (op) == 1 || INTVAL (op) == 4 ||
00791 INTVAL (op) == 8 || INTVAL (op) == 16));
00792 }
00793
00794
00795
00796 int
00797 fr_reg_or_fp01_operand (op, mode)
00798 rtx op;
00799 enum machine_mode mode;
00800 {
00801 return ((GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (op))
00802 || fr_register_operand (op, mode));
00803 }
00804
00805
00806
00807
00808 int
00809 destination_operand (op, mode)
00810 rtx op;
00811 enum machine_mode mode;
00812 {
00813 if (! nonimmediate_operand (op, mode))
00814 return 0;
00815 if (GET_CODE (op) == MEM
00816 && GET_CODE (XEXP (op, 0)) == POST_MODIFY
00817 && GET_CODE (XEXP (XEXP (XEXP (op, 0), 1), 1)) == REG)
00818 return 0;
00819 return 1;
00820 }
00821
00822
00823
00824 int
00825 not_postinc_memory_operand (op, mode)
00826 rtx op;
00827 enum machine_mode mode;
00828 {
00829 return (memory_operand (op, mode)
00830 && GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != 'a');
00831 }
00832
00833
00834
00835
00836 int
00837 normal_comparison_operator (op, mode)
00838 register rtx op;
00839 enum machine_mode mode;
00840 {
00841 enum rtx_code code = GET_CODE (op);
00842 return ((mode == VOIDmode || GET_MODE (op) == mode)
00843 && (code == EQ || code == NE
00844 || code == GT || code == LE || code == GTU || code == LEU));
00845 }
00846
00847
00848
00849
00850 int
00851 adjusted_comparison_operator (op, mode)
00852 register rtx op;
00853 enum machine_mode mode;
00854 {
00855 enum rtx_code code = GET_CODE (op);
00856 return ((mode == VOIDmode || GET_MODE (op) == mode)
00857 && (code == LT || code == GE || code == LTU || code == GEU));
00858 }
00859
00860
00861
00862 int
00863 signed_inequality_operator (op, mode)
00864 register rtx op;
00865 enum machine_mode mode;
00866 {
00867 enum rtx_code code = GET_CODE (op);
00868 return ((mode == VOIDmode || GET_MODE (op) == mode)
00869 && (code == GE || code == GT
00870 || code == LE || code == LT));
00871 }
00872
00873
00874
00875 int
00876 predicate_operator (op, mode)
00877 register rtx op;
00878 enum machine_mode mode;
00879 {
00880 enum rtx_code code = GET_CODE (op);
00881 return ((GET_MODE (op) == mode || mode == VOIDmode)
00882 && (code == EQ || code == NE));
00883 }
00884
00885
00886
00887 int
00888 condop_operator (op, mode)
00889 register rtx op;
00890 enum machine_mode mode;
00891 {
00892 enum rtx_code code = GET_CODE (op);
00893 return ((GET_MODE (op) == mode || mode == VOIDmode)
00894 && (code == PLUS || code == MINUS || code == AND
00895 || code == IOR || code == XOR));
00896 }
00897
00898
00899
00900 int
00901 ar_lc_reg_operand (op, mode)
00902 register rtx op;
00903 enum machine_mode mode;
00904 {
00905 return (GET_MODE (op) == DImode
00906 && (mode == DImode || mode == VOIDmode)
00907 && GET_CODE (op) == REG
00908 && REGNO (op) == AR_LC_REGNUM);
00909 }
00910
00911
00912
00913 int
00914 ar_ccv_reg_operand (op, mode)
00915 register rtx op;
00916 enum machine_mode mode;
00917 {
00918 return ((GET_MODE (op) == mode || mode == VOIDmode)
00919 && GET_CODE (op) == REG
00920 && REGNO (op) == AR_CCV_REGNUM);
00921 }
00922
00923
00924
00925 int
00926 ar_pfs_reg_operand (op, mode)
00927 register rtx op;
00928 enum machine_mode mode;
00929 {
00930 return ((GET_MODE (op) == mode || mode == VOIDmode)
00931 && GET_CODE (op) == REG
00932 && REGNO (op) == AR_PFS_REGNUM);
00933 }
00934
00935
00936
00937 int
00938 general_tfmode_operand (op, mode)
00939 rtx op;
00940 enum machine_mode mode;
00941 {
00942 if (! general_operand (op, mode))
00943 return 0;
00944 if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == ADDRESSOF)
00945 return 0;
00946 return 1;
00947 }
00948
00949
00950
00951 int
00952 destination_tfmode_operand (op, mode)
00953 rtx op;
00954 enum machine_mode mode;
00955 {
00956 if (! destination_operand (op, mode))
00957 return 0;
00958 if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == ADDRESSOF)
00959 return 0;
00960 return 1;
00961 }
00962
00963
00964
00965 int
00966 tfreg_or_fp01_operand (op, mode)
00967 rtx op;
00968 enum machine_mode mode;
00969 {
00970 if (GET_CODE (op) == SUBREG)
00971 return 0;
00972 return fr_reg_or_fp01_operand (op, mode);
00973 }
00974
00975
00976
00977 int
00978 basereg_operand (op, mode)
00979 rtx op;
00980 enum machine_mode mode;
00981 {
00982
00983
00984
00985
00986 return (register_operand (op, mode) &&
00987 REG_POINTER ((GET_CODE (op) == SUBREG) ? SUBREG_REG (op) : op));
00988 }
00989
00990
00991
00992 int
00993 ia64_move_ok (dst, src)
00994 rtx dst, src;
00995 {
00996
00997
00998
00999
01000 if (GET_CODE (dst) != MEM)
01001 return 1;
01002 if (GET_CODE (src) == MEM)
01003 return 0;
01004 if (register_operand (src, VOIDmode))
01005 return 1;
01006
01007
01008 if (INTEGRAL_MODE_P (GET_MODE (dst)))
01009 return src == const0_rtx;
01010 else
01011 return GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src);
01012 }
01013
01014
01015
01016
01017 int
01018 addp4_optimize_ok (op1, op2)
01019 rtx op1, op2;
01020 {
01021
01022 if (!strcmp (lang_hooks.name, "GNU C++"))
01023 return 0;
01024
01025 return (basereg_operand (op1, GET_MODE(op1)) !=
01026 basereg_operand (op2, GET_MODE(op2)));
01027 }
01028
01029
01030
01031
01032 int
01033 ia64_depz_field_mask (rop, rshift)
01034 rtx rop, rshift;
01035 {
01036 unsigned HOST_WIDE_INT op = INTVAL (rop);
01037 unsigned HOST_WIDE_INT shift = INTVAL (rshift);
01038
01039
01040 op >>= shift;
01041
01042
01043 return exact_log2 (op + 1);
01044 }
01045
01046
01047
01048
01049 void
01050 ia64_expand_load_address (dest, src, scratch)
01051 rtx dest, src, scratch;
01052 {
01053 rtx temp;
01054
01055
01056
01057 if (! register_operand (dest, DImode))
01058 if (! scratch || ! register_operand (scratch, DImode))
01059 temp = gen_reg_rtx (DImode);
01060 else
01061 temp = scratch;
01062 else
01063 temp = dest;
01064
01065 if (tls_symbolic_operand (src, Pmode))
01066 abort ();
01067
01068 if (TARGET_AUTO_PIC)
01069 emit_insn (gen_load_gprel64 (temp, src));
01070 else if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_FLAG (src))
01071 emit_insn (gen_load_fptr (temp, src));
01072 else if ((GET_MODE (src) == Pmode || GET_MODE (src) == ptr_mode)
01073 && sdata_symbolic_operand (src, VOIDmode))
01074 emit_insn (gen_load_gprel (temp, src));
01075 else if (GET_CODE (src) == CONST
01076 && GET_CODE (XEXP (src, 0)) == PLUS
01077 && GET_CODE (XEXP (XEXP (src, 0), 1)) == CONST_INT
01078 && (INTVAL (XEXP (XEXP (src, 0), 1)) & 0x1fff) != 0)
01079 {
01080 rtx subtarget = no_new_pseudos ? temp : gen_reg_rtx (DImode);
01081 rtx sym = XEXP (XEXP (src, 0), 0);
01082 HOST_WIDE_INT ofs, hi, lo;
01083
01084
01085
01086 ofs = INTVAL (XEXP (XEXP (src, 0), 1));
01087 lo = ((ofs & 0x3fff) ^ 0x2000) - 0x2000;
01088 hi = ofs - lo;
01089
01090 if (! scratch)
01091 scratch = no_new_pseudos ? subtarget : gen_reg_rtx (DImode);
01092
01093 emit_insn (gen_load_symptr (subtarget, plus_constant (sym, hi),
01094 scratch));
01095 emit_insn (gen_adddi3 (temp, subtarget, GEN_INT (lo)));
01096 }
01097 else
01098 {
01099 rtx insn;
01100 if (! scratch)
01101 scratch = no_new_pseudos ? temp : gen_reg_rtx (DImode);
01102
01103 insn = emit_insn (gen_load_symptr (temp, src, scratch));
01104 #ifdef POINTERS_EXTEND_UNSIGNED
01105 if (GET_MODE (temp) != GET_MODE (src))
01106 src = convert_memory_address (GET_MODE (temp), src);
01107 #endif
01108 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, src, REG_NOTES (insn));
01109 }
01110
01111 if (temp != dest)
01112 {
01113 if (GET_MODE (dest) != GET_MODE (temp))
01114 temp = convert_to_mode (GET_MODE (dest), temp, 0);
01115 emit_move_insn (dest, temp);
01116 }
01117 }
01118
01119 static GTY(()) rtx gen_tls_tga;
01120 static rtx
01121 gen_tls_get_addr ()
01122 {
01123 if (!gen_tls_tga)
01124 {
01125 gen_tls_tga = init_one_libfunc ("__tls_get_addr");
01126 }
01127 return gen_tls_tga;
01128 }
01129
01130 static GTY(()) rtx thread_pointer_rtx;
01131 static rtx
01132 gen_thread_pointer ()
01133 {
01134 if (!thread_pointer_rtx)
01135 {
01136 thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
01137 RTX_UNCHANGING_P (thread_pointer_rtx) = 1;
01138 }
01139 return thread_pointer_rtx;
01140 }
01141
01142 rtx
01143 ia64_expand_move (op0, op1)
01144 rtx op0, op1;
01145 {
01146 enum machine_mode mode = GET_MODE (op0);
01147
01148 if (!reload_in_progress && !reload_completed && !ia64_move_ok (op0, op1))
01149 op1 = force_reg (mode, op1);
01150
01151 if (mode == Pmode || mode == ptr_mode)
01152 {
01153 enum tls_model tls_kind;
01154 if ((tls_kind = tls_symbolic_operand (op1, Pmode)))
01155 {
01156 rtx tga_op1, tga_op2, tga_ret, tga_eqv, tmp, insns;
01157
01158 switch (tls_kind)
01159 {
01160 case TLS_MODEL_GLOBAL_DYNAMIC:
01161 start_sequence ();
01162
01163 tga_op1 = gen_reg_rtx (Pmode);
01164 emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
01165 tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
01166 RTX_UNCHANGING_P (tga_op1) = 1;
01167
01168 tga_op2 = gen_reg_rtx (Pmode);
01169 emit_insn (gen_load_ltoff_dtprel (tga_op2, op1));
01170 tga_op2 = gen_rtx_MEM (Pmode, tga_op2);
01171 RTX_UNCHANGING_P (tga_op2) = 1;
01172
01173 tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
01174 LCT_CONST, Pmode, 2, tga_op1,
01175 Pmode, tga_op2, Pmode);
01176
01177 insns = get_insns ();
01178 end_sequence ();
01179
01180 emit_libcall_block (insns, op0, tga_ret, op1);
01181 return NULL_RTX;
01182
01183 case TLS_MODEL_LOCAL_DYNAMIC:
01184
01185
01186
01187
01188 start_sequence ();
01189
01190 tga_op1 = gen_reg_rtx (Pmode);
01191 emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
01192 tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
01193 RTX_UNCHANGING_P (tga_op1) = 1;
01194
01195 tga_op2 = const0_rtx;
01196
01197 tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
01198 LCT_CONST, Pmode, 2, tga_op1,
01199 Pmode, tga_op2, Pmode);
01200
01201 insns = get_insns ();
01202 end_sequence ();
01203
01204 tga_eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
01205 UNSPEC_LD_BASE);
01206 tmp = gen_reg_rtx (Pmode);
01207 emit_libcall_block (insns, tmp, tga_ret, tga_eqv);
01208
01209 if (register_operand (op0, Pmode))
01210 tga_ret = op0;
01211 else
01212 tga_ret = gen_reg_rtx (Pmode);
01213 if (TARGET_TLS64)
01214 {
01215 emit_insn (gen_load_dtprel (tga_ret, op1));
01216 emit_insn (gen_adddi3 (tga_ret, tmp, tga_ret));
01217 }
01218 else
01219 emit_insn (gen_add_dtprel (tga_ret, tmp, op1));
01220 if (tga_ret == op0)
01221 return NULL_RTX;
01222 op1 = tga_ret;
01223 break;
01224
01225 case TLS_MODEL_INITIAL_EXEC:
01226 tmp = gen_reg_rtx (Pmode);
01227 emit_insn (gen_load_ltoff_tprel (tmp, op1));
01228 tmp = gen_rtx_MEM (Pmode, tmp);
01229 RTX_UNCHANGING_P (tmp) = 1;
01230 tmp = force_reg (Pmode, tmp);
01231
01232 if (register_operand (op0, Pmode))
01233 op1 = op0;
01234 else
01235 op1 = gen_reg_rtx (Pmode);
01236 emit_insn (gen_adddi3 (op1, tmp, gen_thread_pointer ()));
01237 if (op1 == op0)
01238 return NULL_RTX;
01239 break;
01240
01241 case TLS_MODEL_LOCAL_EXEC:
01242 if (register_operand (op0, Pmode))
01243 tmp = op0;
01244 else
01245 tmp = gen_reg_rtx (Pmode);
01246 if (TARGET_TLS64)
01247 {
01248 emit_insn (gen_load_tprel (tmp, op1));
01249 emit_insn (gen_adddi3 (tmp, gen_thread_pointer (), tmp));
01250 }
01251 else
01252 emit_insn (gen_add_tprel (tmp, gen_thread_pointer (), op1));
01253 if (tmp == op0)
01254 return NULL_RTX;
01255 op1 = tmp;
01256 break;
01257
01258 default:
01259 abort ();
01260 }
01261 }
01262 else if (!TARGET_NO_PIC &&
01263 (symbolic_operand (op1, Pmode) ||
01264 symbolic_operand (op1, ptr_mode)))
01265 {
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282 if (rtx_equal_function_value_matters
01283 && GET_CODE (op1) != LABEL_REF
01284 && ! (GET_CODE (op1) == SYMBOL_REF
01285 && (SYMBOL_REF_FLAG (op1)
01286 || CONSTANT_POOL_ADDRESS_P (op1)
01287 || STRING_POOL_ADDRESS_P (op1))))
01288 if (GET_MODE (op1) == DImode)
01289 emit_insn (gen_movdi_symbolic (op0, op1));
01290 else
01291 emit_insn (gen_movsi_symbolic (op0, op1));
01292 else
01293 ia64_expand_load_address (op0, op1, NULL_RTX);
01294 return NULL_RTX;
01295 }
01296 }
01297
01298 return op1;
01299 }
01300
01301
01302
01303 rtx
01304 ia64_split_timode (out, in, scratch)
01305 rtx out[2];
01306 rtx in, scratch;
01307 {
01308 switch (GET_CODE (in))
01309 {
01310 case REG:
01311 out[0] = gen_rtx_REG (DImode, REGNO (in));
01312 out[1] = gen_rtx_REG (DImode, REGNO (in) + 1);
01313 return NULL_RTX;
01314
01315 case MEM:
01316 {
01317 rtx base = XEXP (in, 0);
01318
01319 switch (GET_CODE (base))
01320 {
01321 case REG:
01322 out[0] = adjust_address (in, DImode, 0);
01323 break;
01324 case POST_MODIFY:
01325 base = XEXP (base, 0);
01326 out[0] = adjust_address (in, DImode, 0);
01327 break;
01328
01329
01330
01331
01332
01333 case POST_INC:
01334 base = XEXP (base, 0);
01335 out[0]
01336 = change_address (in, DImode,
01337 gen_rtx_POST_MODIFY
01338 (Pmode, base, plus_constant (base, 16)));
01339 break;
01340 case POST_DEC:
01341 base = XEXP (base, 0);
01342 out[0]
01343 = change_address (in, DImode,
01344 gen_rtx_POST_MODIFY
01345 (Pmode, base, plus_constant (base, -16)));
01346 break;
01347 default:
01348 abort ();
01349 }
01350
01351 if (scratch == NULL_RTX)
01352 abort ();
01353 out[1] = change_address (in, DImode, scratch);
01354 return gen_adddi3 (scratch, base, GEN_INT (8));
01355 }
01356
01357 case CONST_INT:
01358 case CONST_DOUBLE:
01359 split_double (in, &out[0], &out[1]);
01360 return NULL_RTX;
01361
01362 default:
01363 abort ();
01364 }
01365 }
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377 rtx
01378 spill_tfmode_operand (in, force)
01379 rtx in;
01380 int force;
01381 {
01382 if (GET_CODE (in) == SUBREG
01383 && GET_MODE (SUBREG_REG (in)) == TImode
01384 && GET_CODE (SUBREG_REG (in)) == REG)
01385 {
01386 rtx mem = gen_mem_addressof (SUBREG_REG (in), NULL_TREE, true);
01387 return gen_rtx_MEM (TFmode, copy_to_reg (XEXP (mem, 0)));
01388 }
01389 else if (force && GET_CODE (in) == REG)
01390 {
01391 rtx mem = gen_mem_addressof (in, NULL_TREE, true);
01392 return gen_rtx_MEM (TFmode, copy_to_reg (XEXP (mem, 0)));
01393 }
01394 else if (GET_CODE (in) == MEM
01395 && GET_CODE (XEXP (in, 0)) == ADDRESSOF)
01396 return change_address (in, TFmode, copy_to_reg (XEXP (in, 0)));
01397 else
01398 return in;
01399 }
01400
01401
01402
01403
01404 rtx
01405 ia64_expand_compare (code, mode)
01406 enum rtx_code code;
01407 enum machine_mode mode;
01408 {
01409 rtx op0 = ia64_compare_op0, op1 = ia64_compare_op1;
01410 rtx cmp;
01411
01412
01413
01414 if (GET_MODE (op0) == BImode)
01415 {
01416 if ((code == NE || code == EQ) && op1 == const0_rtx)
01417 cmp = op0;
01418 else
01419 abort ();
01420 }
01421 else
01422 {
01423 cmp = gen_reg_rtx (BImode);
01424 emit_insn (gen_rtx_SET (VOIDmode, cmp,
01425 gen_rtx_fmt_ee (code, BImode, op0, op1)));
01426 code = NE;
01427 }
01428
01429 return gen_rtx_fmt_ee (code, mode, cmp, const0_rtx);
01430 }
01431
01432
01433 void
01434 ia64_expand_call (retval, addr, nextarg, sibcall_p)
01435 rtx retval;
01436 rtx addr;
01437 rtx nextarg ATTRIBUTE_UNUSED;
01438 int sibcall_p;
01439 {
01440 rtx insn, b0;
01441
01442 addr = XEXP (addr, 0);
01443 b0 = gen_rtx_REG (DImode, R_BR (0));
01444
01445
01446 if (TARGET_NO_PIC || TARGET_AUTO_PIC)
01447 {
01448 if (sibcall_p)
01449 insn = gen_sibcall_nogp (addr);
01450 else if (! retval)
01451 insn = gen_call_nogp (addr, b0);
01452 else
01453 insn = gen_call_value_nogp (retval, addr, b0);
01454 insn = emit_call_insn (insn);
01455 }
01456 else
01457 {
01458 if (sibcall_p)
01459 insn = gen_sibcall_gp (addr);
01460 else if (! retval)
01461 insn = gen_call_gp (addr, b0);
01462 else
01463 insn = gen_call_value_gp (retval, addr, b0);
01464 insn = emit_call_insn (insn);
01465
01466 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
01467 }
01468
01469 if (sibcall_p)
01470 {
01471 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), b0);
01472 use_reg (&CALL_INSN_FUNCTION_USAGE (insn),
01473 gen_rtx_REG (DImode, AR_PFS_REGNUM));
01474 }
01475 }
01476 void
01477 ia64_reload_gp ()
01478 {
01479 rtx tmp;
01480
01481 if (current_frame_info.reg_save_gp)
01482 tmp = gen_rtx_REG (DImode, current_frame_info.reg_save_gp);
01483 else
01484 {
01485 HOST_WIDE_INT offset;
01486
01487 offset = (current_frame_info.spill_cfa_off
01488 + current_frame_info.spill_size);
01489 if (frame_pointer_needed)
01490 {
01491 tmp = hard_frame_pointer_rtx;
01492 offset = -offset;
01493 }
01494 else
01495 {
01496 tmp = stack_pointer_rtx;
01497 offset = current_frame_info.total_size - offset;
01498 }
01499
01500 if (CONST_OK_FOR_I (offset))
01501 emit_insn (gen_adddi3 (pic_offset_table_rtx,
01502 tmp, GEN_INT (offset)));
01503 else
01504 {
01505 emit_move_insn (pic_offset_table_rtx, GEN_INT (offset));
01506 emit_insn (gen_adddi3 (pic_offset_table_rtx,
01507 pic_offset_table_rtx, tmp));
01508 }
01509
01510 tmp = gen_rtx_MEM (DImode, pic_offset_table_rtx);
01511 }
01512
01513 emit_move_insn (pic_offset_table_rtx, tmp);
01514 }
01515
01516 void
01517 ia64_split_call (retval, addr, retaddr, scratch_r, scratch_b,
01518 noreturn_p, sibcall_p)
01519 rtx retval, addr, retaddr, scratch_r, scratch_b;
01520 int noreturn_p, sibcall_p;
01521 {
01522 rtx insn;
01523 bool is_desc = false;
01524
01525
01526
01527 if (REG_P (addr))
01528 {
01529 rtx tmp;
01530 bool addr_dead_p;
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544 addr_dead_p = ((noreturn_p || sibcall_p
01545 || TEST_HARD_REG_BIT (regs_invalidated_by_call,
01546 REGNO (addr)))
01547 && !FUNCTION_ARG_REGNO_P (REGNO (addr)));
01548
01549
01550 tmp = gen_rtx_POST_INC (Pmode, addr);
01551 tmp = gen_rtx_MEM (Pmode, tmp);
01552 emit_move_insn (scratch_r, tmp);
01553 emit_move_insn (scratch_b, scratch_r);
01554
01555
01556
01557 if (!addr_dead_p)
01558 tmp = gen_rtx_POST_DEC (Pmode, addr);
01559 else
01560 tmp = addr;
01561 tmp = gen_rtx_MEM (Pmode, tmp);
01562 emit_move_insn (pic_offset_table_rtx, tmp);
01563
01564 is_desc = true;
01565 addr = scratch_b;
01566 }
01567
01568 if (sibcall_p)
01569 insn = gen_sibcall_nogp (addr);
01570 else if (retval)
01571 insn = gen_call_value_nogp (retval, addr, retaddr);
01572 else
01573 insn = gen_call_nogp (addr, retaddr);
01574 emit_call_insn (insn);
01575
01576 if ((!TARGET_CONST_GP || is_desc) && !noreturn_p && !sibcall_p)
01577 ia64_reload_gp ();
01578 }
01579
01580
01581
01582 void
01583 emit_safe_across_calls (f)
01584 FILE *f;
01585 {
01586 unsigned int rs, re;
01587 int out_state;
01588
01589 rs = 1;
01590 out_state = 0;
01591 while (1)
01592 {
01593 while (rs < 64 && call_used_regs[PR_REG (rs)])
01594 rs++;
01595 if (rs >= 64)
01596 break;
01597 for (re = rs + 1; re < 64 && ! call_used_regs[PR_REG (re)]; re++)
01598 continue;
01599 if (out_state == 0)
01600 {
01601 fputs ("\t.pred.safe_across_calls ", f);
01602 out_state = 1;
01603 }
01604 else
01605 fputc (',', f);
01606 if (re == rs + 1)
01607 fprintf (f, "p%u", rs);
01608 else
01609 fprintf (f, "p%u-p%u", rs, re - 1);
01610 rs = re + 1;
01611 }
01612 if (out_state)
01613 fputc ('\n', f);
01614 }
01615
01616
01617
01618
01619
01620
01621 static int
01622 find_gr_spill (try_locals)
01623 int try_locals;
01624 {
01625 int regno;
01626
01627
01628
01629 if (current_function_is_leaf)
01630 {
01631 for (regno = GR_REG (1); regno <= GR_REG (31); regno++)
01632 if (! regs_ever_live[regno]
01633 && call_used_regs[regno]
01634 && ! fixed_regs[regno]
01635 && ! global_regs[regno]
01636 && ((current_frame_info.gr_used_mask >> regno) & 1) == 0)
01637 {
01638 current_frame_info.gr_used_mask |= 1 << regno;
01639 return regno;
01640 }
01641 }
01642
01643 if (try_locals)
01644 {
01645 regno = current_frame_info.n_local_regs;
01646
01647
01648
01649 if (regno < (80 - frame_pointer_needed))
01650 {
01651 current_frame_info.n_local_regs = regno + 1;
01652 return LOC_REG (0) + regno;
01653 }
01654 }
01655
01656
01657 return 0;
01658 }
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669 static int last_scratch_gr_reg;
01670
01671 static int
01672 next_scratch_gr_reg ()
01673 {
01674 int i, regno;
01675
01676 for (i = 0; i < 32; ++i)
01677 {
01678 regno = (last_scratch_gr_reg + i + 1) & 31;
01679 if (call_used_regs[regno]
01680 && ! fixed_regs[regno]
01681 && ! global_regs[regno]
01682 && ((current_frame_info.gr_used_mask >> regno) & 1) == 0)
01683 {
01684 last_scratch_gr_reg = regno;
01685 return regno;
01686 }
01687 }
01688
01689
01690 abort ();
01691 }
01692
01693
01694
01695
01696 static void
01697 mark_reg_gr_used_mask (reg, data)
01698 rtx reg;
01699 void *data ATTRIBUTE_UNUSED;
01700 {
01701 unsigned int regno = REGNO (reg);
01702 if (regno < 32)
01703 {
01704 unsigned int i, n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
01705 for (i = 0; i < n; ++i)
01706 current_frame_info.gr_used_mask |= 1 << (regno + i);
01707 }
01708 }
01709
01710
01711
01712
01713
01714 static void
01715 ia64_compute_frame_size (size)
01716 HOST_WIDE_INT size;
01717 {
01718 HOST_WIDE_INT total_size;
01719 HOST_WIDE_INT spill_size = 0;
01720 HOST_WIDE_INT extra_spill_size = 0;
01721 HOST_WIDE_INT pretend_args_size;
01722 HARD_REG_SET mask;
01723 int n_spilled = 0;
01724 int spilled_gr_p = 0;
01725 int spilled_fr_p = 0;
01726 unsigned int regno;
01727 int i;
01728
01729 if (current_frame_info.initialized)
01730 return;
01731
01732 memset (¤t_frame_info, 0, sizeof current_frame_info);
01733 CLEAR_HARD_REG_SET (mask);
01734
01735
01736 diddle_return_value (mark_reg_gr_used_mask, NULL);
01737
01738
01739 if (cfun->machine->ia64_eh_epilogue_sp)
01740 mark_reg_gr_used_mask (cfun->machine->ia64_eh_epilogue_sp, NULL);
01741 if (cfun->machine->ia64_eh_epilogue_bsp)
01742 mark_reg_gr_used_mask (cfun->machine->ia64_eh_epilogue_bsp, NULL);
01743
01744
01745
01746
01747
01748
01749
01750 regno = LOC_REG (78) + ! frame_pointer_needed;
01751 for (; regno >= LOC_REG (0); regno--)
01752 if (regs_ever_live[regno])
01753 break;
01754 current_frame_info.n_local_regs = regno - LOC_REG (0) + 1;
01755
01756
01757
01758
01759
01760 if (cfun->machine->n_varargs > 0
01761 || lookup_attribute ("syscall_linkage",
01762 TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
01763 current_frame_info.n_input_regs = 8;
01764 else
01765 {
01766 for (regno = IN_REG (7); regno >= IN_REG (0); regno--)
01767 if (regs_ever_live[regno])
01768 break;
01769 current_frame_info.n_input_regs = regno - IN_REG (0) + 1;
01770 }
01771
01772 for (regno = OUT_REG (7); regno >= OUT_REG (0); regno--)
01773 if (regs_ever_live[regno])
01774 break;
01775 i = regno - OUT_REG (0) + 1;
01776
01777
01778
01779
01780
01781 if (current_function_profile)
01782 i = MAX (i, 1);
01783 current_frame_info.n_output_regs = i;
01784
01785
01786 current_frame_info.n_rotate_regs = 0;
01787
01788
01789
01790
01791
01792 for (regno = FR_REG (2); regno <= FR_REG (127); regno++)
01793 if (regs_ever_live[regno] && ! call_used_regs[regno])
01794 {
01795 SET_HARD_REG_BIT (mask, regno);
01796 spill_size += 16;
01797 n_spilled += 1;
01798 spilled_fr_p = 1;
01799 }
01800
01801 for (regno = GR_REG (1); regno <= GR_REG (31); regno++)
01802 if (regs_ever_live[regno] && ! call_used_regs[regno])
01803 {
01804 SET_HARD_REG_BIT (mask, regno);
01805 spill_size += 8;
01806 n_spilled += 1;
01807 spilled_gr_p = 1;
01808 }
01809
01810 for (regno = BR_REG (1); regno <= BR_REG (7); regno++)
01811 if (regs_ever_live[regno] && ! call_used_regs[regno])
01812 {
01813 SET_HARD_REG_BIT (mask, regno);
01814 spill_size += 8;
01815 n_spilled += 1;
01816 }
01817
01818
01819
01820
01821 if (frame_pointer_needed)
01822 {
01823 current_frame_info.reg_fp = find_gr_spill (1);
01824
01825
01826
01827
01828 if (current_frame_info.reg_fp == 0)
01829 {
01830 current_frame_info.reg_fp = LOC_REG (79);
01831 current_frame_info.n_local_regs++;
01832 }
01833 }
01834
01835 if (! current_function_is_leaf)
01836 {
01837
01838
01839
01840 SET_HARD_REG_BIT (mask, BR_REG (0));
01841
01842 current_frame_info.reg_save_b0 = find_gr_spill (1);
01843 if (current_frame_info.reg_save_b0 == 0)
01844 {
01845 spill_size += 8;
01846 n_spilled += 1;
01847 }
01848
01849
01850 SET_HARD_REG_BIT (mask, AR_PFS_REGNUM);
01851 current_frame_info.reg_save_ar_pfs = find_gr_spill (1);
01852 if (current_frame_info.reg_save_ar_pfs == 0)
01853 {
01854 extra_spill_size += 8;
01855 n_spilled += 1;
01856 }
01857
01858
01859
01860 current_frame_info.reg_save_gp
01861 = (current_function_calls_setjmp ? 0 : find_gr_spill (1));
01862 if (current_frame_info.reg_save_gp == 0)
01863 {
01864 SET_HARD_REG_BIT (mask, GR_REG (1));
01865 spill_size += 8;
01866 n_spilled += 1;
01867 }
01868 }
01869 else
01870 {
01871 if (regs_ever_live[BR_REG (0)] && ! call_used_regs[BR_REG (0)])
01872 {
01873 SET_HARD_REG_BIT (mask, BR_REG (0));
01874 spill_size += 8;
01875 n_spilled += 1;
01876 }
01877
01878 if (regs_ever_live[AR_PFS_REGNUM])
01879 {
01880 SET_HARD_REG_BIT (mask, AR_PFS_REGNUM);
01881 current_frame_info.reg_save_ar_pfs = find_gr_spill (1);
01882 if (current_frame_info.reg_save_ar_pfs == 0)
01883 {
01884 extra_spill_size += 8;
01885 n_spilled += 1;
01886 }
01887 }
01888 }
01889
01890
01891
01892
01893
01894
01895
01896 if (current_frame_info.reg_fp != 0
01897 && current_frame_info.reg_save_b0 == current_frame_info.reg_fp + 1
01898 && current_frame_info.reg_save_ar_pfs == current_frame_info.reg_fp + 2)
01899 {
01900 current_frame_info.reg_save_b0 = current_frame_info.reg_fp;
01901 current_frame_info.reg_save_ar_pfs = current_frame_info.reg_fp + 1;
01902 current_frame_info.reg_fp = current_frame_info.reg_fp + 2;
01903 }
01904
01905
01906 for (regno = PR_REG (0); regno <= PR_REG (63); regno++)
01907 if (regs_ever_live[regno] && ! call_used_regs[regno])
01908 break;
01909 if (regno <= PR_REG (63))
01910 {
01911 SET_HARD_REG_BIT (mask, PR_REG (0));
01912 current_frame_info.reg_save_pr = find_gr_spill (1);
01913 if (current_frame_info.reg_save_pr == 0)
01914 {
01915 extra_spill_size += 8;
01916 n_spilled += 1;
01917 }
01918
01919
01920
01921 for (regno = PR_REG (0); regno <= PR_REG (63); regno++)
01922 regs_ever_live[regno] = 1;
01923 }
01924
01925
01926
01927
01928 if (spilled_gr_p || cfun->machine->n_varargs
01929 || regs_ever_live[AR_UNAT_REGNUM])
01930 {
01931 regs_ever_live[AR_UNAT_REGNUM] = 1;
01932 SET_HARD_REG_BIT (mask, AR_UNAT_REGNUM);
01933 current_frame_info.reg_save_ar_unat = find_gr_spill (spill_size == 0);
01934 if (current_frame_info.reg_save_ar_unat == 0)
01935 {
01936 extra_spill_size += 8;
01937 n_spilled += 1;
01938 }
01939 }
01940
01941 if (regs_ever_live[AR_LC_REGNUM])
01942 {
01943 SET_HARD_REG_BIT (mask, AR_LC_REGNUM);
01944 current_frame_info.reg_save_ar_lc = find_gr_spill (spill_size == 0);
01945 if (current_frame_info.reg_save_ar_lc == 0)
01946 {
01947 extra_spill_size += 8;
01948 n_spilled += 1;
01949 }
01950 }
01951
01952
01953
01954
01955 if (spilled_fr_p)
01956 pretend_args_size = IA64_STACK_ALIGN (current_function_pretend_args_size);
01957 else
01958 pretend_args_size = current_function_pretend_args_size;
01959
01960 total_size = (spill_size + extra_spill_size + size + pretend_args_size
01961 + current_function_outgoing_args_size);
01962 total_size = IA64_STACK_ALIGN (total_size);
01963
01964
01965
01966
01967 if (current_function_is_leaf)
01968 total_size = MAX (0, total_size - 16);
01969
01970 current_frame_info.total_size = total_size;
01971 current_frame_info.spill_cfa_off = pretend_args_size - 16;
01972 current_frame_info.spill_size = spill_size;
01973 current_frame_info.extra_spill_size = extra_spill_size;
01974 COPY_HARD_REG_SET (current_frame_info.mask, mask);
01975 current_frame_info.n_spilled = n_spilled;
01976 current_frame_info.initialized = reload_completed;
01977 }
01978
01979
01980
01981 HOST_WIDE_INT
01982 ia64_initial_elimination_offset (from, to)
01983 int from, to;
01984 {
01985 HOST_WIDE_INT offset;
01986
01987 ia64_compute_frame_size (get_frame_size ());
01988 switch (from)
01989 {
01990 case FRAME_POINTER_REGNUM:
01991 if (to == HARD_FRAME_POINTER_REGNUM)
01992 {
01993 if (current_function_is_leaf)
01994 offset = -current_frame_info.total_size;
01995 else
01996 offset = -(current_frame_info.total_size
01997 - current_function_outgoing_args_size - 16);
01998 }
01999 else if (to == STACK_POINTER_REGNUM)
02000 {
02001 if (current_function_is_leaf)
02002 offset = 0;
02003 else
02004 offset = 16 + current_function_outgoing_args_size;
02005 }
02006 else
02007 abort ();
02008 break;
02009
02010 case ARG_POINTER_REGNUM:
02011
02012
02013 if (to == HARD_FRAME_POINTER_REGNUM)
02014 offset = 16 - current_function_pretend_args_size;
02015 else if (to == STACK_POINTER_REGNUM)
02016 offset = (current_frame_info.total_size
02017 + 16 - current_function_pretend_args_size);
02018 else
02019 abort ();
02020 break;
02021
02022 case RETURN_ADDRESS_POINTER_REGNUM:
02023 offset = 0;
02024 break;
02025
02026 default:
02027 abort ();
02028 }
02029
02030 return offset;
02031 }
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043 struct spill_fill_data
02044 {
02045 rtx init_after;
02046 rtx init_reg[2];
02047 rtx iter_reg[2];
02048 rtx *prev_addr[2];
02049 rtx prev_insn[2];
02050 HOST_WIDE_INT prev_off[2];
02051 int n_iter;
02052 int next_iter;
02053 unsigned int save_gr_used_mask;
02054 };
02055
02056 static struct spill_fill_data spill_fill_data;
02057
02058 static void
02059 setup_spill_pointers (n_spills, init_reg, cfa_off)
02060 int n_spills;
02061 rtx init_reg;
02062 HOST_WIDE_INT cfa_off;
02063 {
02064 int i;
02065
02066 spill_fill_data.init_after = get_last_insn ();
02067 spill_fill_data.init_reg[0] = init_reg;
02068 spill_fill_data.init_reg[1] = init_reg;
02069 spill_fill_data.prev_addr[0] = NULL;
02070 spill_fill_data.prev_addr[1] = NULL;
02071 spill_fill_data.prev_insn[0] = NULL;
02072 spill_fill_data.prev_insn[1] = NULL;
02073 spill_fill_data.prev_off[0] = cfa_off;
02074 spill_fill_data.prev_off[1] = cfa_off;
02075 spill_fill_data.next_iter = 0;
02076 spill_fill_data.save_gr_used_mask = current_frame_info.gr_used_mask;
02077
02078 spill_fill_data.n_iter = 1 + (n_spills > 2);
02079 for (i = 0; i < spill_fill_data.n_iter; ++i)
02080 {
02081 int regno = next_scratch_gr_reg ();
02082 spill_fill_data.iter_reg[i] = gen_rtx_REG (DImode, regno);
02083 current_frame_info.gr_used_mask |= 1 << regno;
02084 }
02085 }
02086
02087 static void
02088 finish_spill_pointers ()
02089 {
02090 current_frame_info.gr_used_mask = spill_fill_data.save_gr_used_mask;
02091 }
02092
02093 static rtx
02094 spill_restore_mem (reg, cfa_off)
02095 rtx reg;
02096 HOST_WIDE_INT cfa_off;
02097 {
02098 int iter = spill_fill_data.next_iter;
02099 HOST_WIDE_INT disp = spill_fill_data.prev_off[iter] - cfa_off;
02100 rtx disp_rtx = GEN_INT (disp);
02101 rtx mem;
02102
02103 if (spill_fill_data.prev_addr[iter])
02104 {
02105 if (CONST_OK_FOR_N (disp))
02106 {
02107 *spill_fill_data.prev_addr[iter]
02108 = gen_rtx_POST_MODIFY (DImode, spill_fill_data.iter_reg[iter],
02109 gen_rtx_PLUS (DImode,
02110 spill_fill_data.iter_reg[iter],
02111 disp_rtx));
02112 REG_NOTES (spill_fill_data.prev_insn[iter])
02113 = gen_rtx_EXPR_LIST (REG_INC, spill_fill_data.iter_reg[iter],
02114 REG_NOTES (spill_fill_data.prev_insn[iter]));
02115 }
02116 else
02117 {
02118
02119 if (! CONST_OK_FOR_I (disp))
02120 {
02121 rtx tmp = gen_rtx_REG (DImode, next_scratch_gr_reg ());
02122 emit_move_insn (tmp, disp_rtx);
02123 disp_rtx = tmp;
02124 }
02125 emit_insn (gen_adddi3 (spill_fill_data.iter_reg[iter],
02126 spill_fill_data.iter_reg[iter], disp_rtx));
02127 }
02128 }
02129
02130
02131
02132
02133 else if (disp == 0
02134 && spill_fill_data.init_reg[iter] == stack_pointer_rtx
02135 && frame_pointer_needed)
02136 {
02137 mem = gen_rtx_MEM (GET_MODE (reg), hard_frame_pointer_rtx);
02138 set_mem_alias_set (mem, get_varargs_alias_set ());
02139 return mem;
02140 }
02141 else
02142 {
02143 rtx seq, insn;
02144
02145 if (disp == 0)
02146 seq = gen_movdi (spill_fill_data.iter_reg[iter],
02147 spill_fill_data.init_reg[iter]);
02148 else
02149 {
02150 start_sequence ();
02151
02152 if (! CONST_OK_FOR_I (disp))
02153 {
02154 rtx tmp = gen_rtx_REG (DImode, next_scratch_gr_reg ());
02155 emit_move_insn (tmp, disp_rtx);
02156 disp_rtx = tmp;
02157 }
02158
02159 emit_insn (gen_adddi3 (spill_fill_data.iter_reg[iter],
02160 spill_fill_data.init_reg[iter],
02161 disp_rtx));
02162
02163 seq = get_insns ();
02164 end_sequence ();
02165 }
02166
02167
02168 if (spill_fill_data.init_after)
02169 insn = emit_insn_after (seq, spill_fill_data.init_after);
02170 else
02171 {
02172 rtx first = get_insns ();
02173 if (first)
02174 insn = emit_insn_before (seq, first);
02175 else
02176 insn = emit_insn (seq);
02177 }
02178 spill_fill_data.init_after = insn;
02179
02180
02181
02182
02183
02184
02185
02186 if (disp == 0)
02187 REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
02188 REG_NOTES (insn));
02189 }
02190
02191 mem = gen_rtx_MEM (GET_MODE (reg), spill_fill_data.iter_reg[iter]);
02192
02193
02194
02195
02196 set_mem_alias_set (mem, get_varargs_alias_set ());
02197
02198 spill_fill_data.prev_addr[iter] = &XEXP (mem, 0);
02199 spill_fill_data.prev_off[iter] = cfa_off;
02200
02201 if (++iter >= spill_fill_data.n_iter)
02202 iter = 0;
02203 spill_fill_data.next_iter = iter;
02204
02205 return mem;
02206 }
02207
02208 static void
02209 do_spill (move_fn, reg, cfa_off, frame_reg)
02210 rtx (*move_fn) PARAMS ((rtx, rtx, rtx));
02211 rtx reg, frame_reg;
02212 HOST_WIDE_INT cfa_off;
02213 {
02214 int iter = spill_fill_data.next_iter;
02215 rtx mem, insn;
02216
02217 mem = spill_restore_mem (reg, cfa_off);
02218 insn = emit_insn ((*move_fn) (mem, reg, GEN_INT (cfa_off)));
02219 spill_fill_data.prev_insn[iter] = insn;
02220
02221 if (frame_reg)
02222 {
02223 rtx base;
02224 HOST_WIDE_INT off;
02225
02226 RTX_FRAME_RELATED_P (insn) = 1;
02227
02228
02229
02230
02231
02232 if (frame_pointer_needed)
02233 {
02234 base = hard_frame_pointer_rtx;
02235 off = - cfa_off;
02236 }
02237 else
02238 {
02239 base = stack_pointer_rtx;
02240 off = current_frame_info.total_size - cfa_off;
02241 }
02242
02243 REG_NOTES (insn)
02244 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
02245 gen_rtx_SET (VOIDmode,
02246 gen_rtx_MEM (GET_MODE (reg),
02247 plus_constant (base, off)),
02248 frame_reg),
02249 REG_NOTES (insn));
02250 }
02251 }
02252
02253 static void
02254 do_restore (move_fn, reg, cfa_off)
02255 rtx (*move_fn) PARAMS ((rtx, rtx, rtx));
02256 rtx reg;
02257 HOST_WIDE_INT cfa_off;
02258 {
02259 int iter = spill_fill_data.next_iter;
02260 rtx insn;
02261
02262 insn = emit_insn ((*move_fn) (reg, spill_restore_mem (reg, cfa_off),
02263 GEN_INT (cfa_off)));
02264 spill_fill_data.prev_insn[iter] = insn;
02265 }
02266
02267
02268
02269
02270
02271 static rtx
02272 gen_movdi_x (dest, src, offset)
02273 rtx dest, src;
02274 rtx offset ATTRIBUTE_UNUSED;
02275 {
02276 return gen_movdi (dest, src);
02277 }
02278
02279 static rtx
02280 gen_fr_spill_x (dest, src, offset)
02281 rtx dest, src;
02282 rtx offset ATTRIBUTE_UNUSED;
02283 {
02284 return gen_fr_spill (dest, src);
02285 }
02286
02287 static rtx
02288 gen_fr_restore_x (dest, src, offset)
02289 rtx dest, src;
02290 rtx offset ATTRIBUTE_UNUSED;
02291 {
02292 return gen_fr_restore (dest, src);
02293 }
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317 void
02318 ia64_expand_prologue ()
02319 {
02320 rtx insn, ar_pfs_save_reg, ar_unat_save_reg;
02321 int i, epilogue_p, regno, alt_regno, cfa_off, n_varargs;
02322 rtx reg, alt_reg;
02323
02324 ia64_compute_frame_size (get_frame_size ());
02325 last_scratch_gr_reg = 15;
02326
02327
02328
02329
02330 if (optimize)
02331 {
02332 edge e;
02333
02334 for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
02335 if ((e->flags & EDGE_FAKE) == 0
02336 && (e->flags & EDGE_FALLTHRU) != 0)
02337 break;
02338 epilogue_p = (e != NULL);
02339 }
02340 else
02341 epilogue_p = 1;
02342
02343
02344
02345
02346
02347 if (! TARGET_REG_NAMES)
02348 {
02349 int inputs = current_frame_info.n_input_regs;
02350 int locals = current_frame_info.n_local_regs;
02351 int outputs = current_frame_info.n_output_regs;
02352
02353 for (i = 0; i < inputs; i++)
02354 reg_names[IN_REG (i)] = ia64_reg_numbers[i];
02355 for (i = 0; i < locals; i++)
02356 reg_names[LOC_REG (i)] = ia64_reg_numbers[inputs + i];
02357 for (i = 0; i < outputs; i++)
02358 reg_names[OUT_REG (i)] = ia64_reg_numbers[inputs + locals + i];
02359 }
02360
02361
02362
02363
02364
02365
02366
02367
02368 if (current_frame_info.reg_fp)
02369 {
02370 const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM];
02371 reg_names[HARD_FRAME_POINTER_REGNUM]
02372 = reg_names[current_frame_info.reg_fp];
02373 reg_names[current_frame_info.reg_fp] = tmp;
02374 }
02375
02376
02377
02378
02379
02380
02381
02382
02383 if (regs_ever_live[RETURN_ADDRESS_POINTER_REGNUM]
02384 && current_frame_info.reg_save_b0 != 0)
02385 XINT (return_address_pointer_rtx, 0) = current_frame_info.reg_save_b0;
02386
02387
02388 if (current_frame_info.n_local_regs == 0
02389 && current_frame_info.n_output_regs == 0
02390 && current_frame_info.n_input_regs <= current_function_args_info.int_regs
02391 && !TEST_HARD_REG_BIT (current_frame_info.mask, AR_PFS_REGNUM))
02392 {
02393
02394
02395 current_frame_info.need_regstk = (TARGET_REG_NAMES != 0);
02396 ar_pfs_save_reg = NULL_RTX;
02397 }
02398 else
02399 {
02400 current_frame_info.need_regstk = 0;
02401
02402 if (current_frame_info.reg_save_ar_pfs)
02403 regno = current_frame_info.reg_save_ar_pfs;
02404 else
02405 regno = next_scratch_gr_reg ();
02406 ar_pfs_save_reg = gen_rtx_REG (DImode, regno);
02407
02408 insn = emit_insn (gen_alloc (ar_pfs_save_reg,
02409 GEN_INT (current_frame_info.n_input_regs),
02410 GEN_INT (current_frame_info.n_local_regs),
02411 GEN_INT (current_frame_info.n_output_regs),
02412 GEN_INT (current_frame_info.n_rotate_regs)));
02413 RTX_FRAME_RELATED_P (insn) = (current_frame_info.reg_save_ar_pfs != 0);
02414 }
02415
02416
02417
02418 n_varargs = cfun->machine->n_varargs;
02419 setup_spill_pointers (current_frame_info.n_spilled + n_varargs,
02420 stack_pointer_rtx, 0);
02421
02422 if (frame_pointer_needed)
02423 {
02424 insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
02425 RTX_FRAME_RELATED_P (insn) = 1;
02426 }
02427
02428 if (current_frame_info.total_size != 0)
02429 {
02430 rtx frame_size_rtx = GEN_INT (- current_frame_info.total_size);
02431 rtx offset;
02432
02433 if (CONST_OK_FOR_I (- current_frame_info.total_size))
02434 offset = frame_size_rtx;
02435 else
02436 {
02437 regno = next_scratch_gr_reg ();
02438 offset = gen_rtx_REG (DImode, regno);
02439 emit_move_insn (offset, frame_size_rtx);
02440 }
02441
02442 insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
02443 stack_pointer_rtx, offset));
02444
02445 if (! frame_pointer_needed)
02446 {
02447 RTX_FRAME_RELATED_P (insn) = 1;
02448 if (GET_CODE (offset) != CONST_INT)
02449 {
02450 REG_NOTES (insn)
02451 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
02452 gen_rtx_SET (VOIDmode,
02453 stack_pointer_rtx,
02454 gen_rtx_PLUS (DImode,
02455 stack_pointer_rtx,
02456 frame_size_rtx)),
02457 REG_NOTES (insn));
02458 }
02459 }
02460
02461
02462
02463
02464
02465 emit_insn (gen_blockage ());
02466 }
02467
02468
02469 if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM))
02470 {
02471 if (current_frame_info.reg_save_ar_unat)
02472 ar_unat_save_reg
02473 = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_unat);
02474 else
02475 {
02476 alt_regno = next_scratch_gr_reg ();
02477 ar_unat_save_reg = gen_rtx_REG (DImode, alt_regno);
02478 current_frame_info.gr_used_mask |= 1 << alt_regno;
02479 }
02480
02481 reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM);
02482 insn = emit_move_insn (ar_unat_save_reg, reg);
02483 RTX_FRAME_RELATED_P (insn) = (current_frame_info.reg_save_ar_unat != 0);
02484
02485
02486
02487 if (! epilogue_p && current_frame_info.reg_save_ar_unat)
02488 emit_insn (gen_prologue_use (ar_unat_save_reg));
02489 }
02490 else
02491 ar_unat_save_reg = NULL_RTX;
02492
02493
02494
02495
02496
02497 cfa_off = -16;
02498 for (regno = GR_ARG_FIRST + 7; n_varargs > 0; --n_varargs, --regno)
02499 {
02500 reg = gen_rtx_REG (DImode, regno);
02501 do_spill (gen_gr_spill, reg, cfa_off += 8, NULL_RTX);
02502 }
02503
02504
02505 cfa_off = (current_frame_info.spill_cfa_off
02506 + current_frame_info.spill_size
02507 + current_frame_info.extra_spill_size);
02508
02509
02510 if (TEST_HARD_REG_BIT (current_frame_info.mask, PR_REG (0)))
02511 {
02512 reg = gen_rtx_REG (DImode, PR_REG (0));
02513 if (current_frame_info.reg_save_pr != 0)
02514 {
02515 alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_pr);
02516 insn = emit_move_insn (alt_reg, reg);
02517
02518
02519
02520 RTX_FRAME_RELATED_P (insn) = 1;
02521 REG_NOTES (insn)
02522 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
02523 gen_rtx_SET (VOIDmode, alt_reg, reg),
02524 REG_NOTES (insn));
02525
02526
02527
02528 if (! epilogue_p)
02529 emit_insn (gen_prologue_use (alt_reg));
02530 }
02531 else
02532 {
02533 alt_regno = next_scratch_gr_reg ();
02534 alt_reg = gen_rtx_REG (DImode, alt_regno);
02535 insn = emit_move_insn (alt_reg, reg);
02536 do_spill (gen_movdi_x, alt_reg, cfa_off, reg);
02537 cfa_off -= 8;
02538 }
02539 }
02540
02541
02542 if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM)
02543 && current_frame_info.reg_save_ar_unat == 0)
02544 {
02545 reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM);
02546 do_spill (gen_movdi_x, ar_unat_save_reg, cfa_off, reg);
02547 cfa_off -= 8;
02548 }
02549
02550
02551
02552
02553 if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_PFS_REGNUM)
02554 && current_frame_info.reg_save_ar_pfs == 0)
02555 {
02556 reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
02557 do_spill (gen_movdi_x, ar_pfs_save_reg, cfa_off, reg);
02558 cfa_off -= 8;
02559 }
02560
02561 if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_LC_REGNUM))
02562 {
02563 reg = gen_rtx_REG (DImode, AR_LC_REGNUM);
02564 if (current_frame_info.reg_save_ar_lc != 0)
02565 {
02566 alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_lc);
02567 insn = emit_move_insn (alt_reg, reg);
02568 RTX_FRAME_RELATED_P (insn) = 1;
02569
02570
02571
02572 if (! epilogue_p)
02573 emit_insn (gen_prologue_use (alt_reg));
02574 }
02575 else
02576 {
02577 alt_regno = next_scratch_gr_reg ();
02578 alt_reg = gen_rtx_REG (DImode, alt_regno);
02579 emit_move_insn (alt_reg, reg);
02580 do_spill (gen_movdi_x, alt_reg, cfa_off, reg);
02581 cfa_off -= 8;
02582 }
02583 }
02584
02585 if (current_frame_info.reg_save_gp)
02586 {
02587 insn = emit_move_insn (gen_rtx_REG (DImode,
02588 current_frame_info.reg_save_gp),
02589 pic_offset_table_rtx);
02590
02591
02592
02593
02594 REG_NOTES (insn)
02595 = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, REG_NOTES (insn));
02596 }
02597
02598
02599 if (cfa_off != (current_frame_info.spill_cfa_off
02600 + current_frame_info.spill_size))
02601 abort ();
02602
02603
02604 for (regno = GR_REG (1); regno <= GR_REG (31); ++regno)
02605 if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
02606 {
02607 reg = gen_rtx_REG (DImode, regno);
02608 do_spill (gen_gr_spill, reg, cfa_off, reg);
02609 cfa_off -= 8;
02610 }
02611
02612
02613
02614 if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
02615 {
02616 reg = gen_rtx_REG (DImode, BR_REG (0));
02617 if (current_frame_info.reg_save_b0 != 0)
02618 {
02619 alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
02620 insn = emit_move_insn (alt_reg, reg);
02621 RTX_FRAME_RELATED_P (insn) = 1;
02622
02623
02624
02625 if (! epilogue_p)
02626 emit_insn (gen_prologue_use (alt_reg));
02627 }
02628 else
02629 {
02630 alt_regno = next_scratch_gr_reg ();
02631 alt_reg = gen_rtx_REG (DImode, alt_regno);
02632 emit_move_insn (alt_reg, reg);
02633 do_spill (gen_movdi_x, alt_reg, cfa_off, reg);
02634 cfa_off -= 8;
02635 }
02636 }
02637
02638
02639 for (regno = BR_REG (1); regno <= BR_REG (7); ++regno)
02640 if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
02641 {
02642 alt_regno = next_scratch_gr_reg ();
02643 alt_reg = gen_rtx_REG (DImode, alt_regno);
02644 reg = gen_rtx_REG (DImode, regno);
02645 emit_move_insn (alt_reg, reg);
02646 do_spill (gen_movdi_x, alt_reg, cfa_off, reg);
02647 cfa_off -= 8;
02648 }
02649
02650
02651 for (regno = FR_REG (2); regno <= FR_REG (127); ++regno)
02652 if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
02653 {
02654 if (cfa_off & 15)
02655 abort ();
02656 reg = gen_rtx_REG (TFmode, regno);
02657 do_spill (gen_fr_spill_x, reg, cfa_off, reg);
02658 cfa_off -= 16;
02659 }
02660
02661 if (cfa_off != current_frame_info.spill_cfa_off)
02662 abort ();
02663
02664 finish_spill_pointers ();
02665 }
02666
02667
02668
02669
02670
02671
02672
02673
02674 void
02675 ia64_expand_epilogue (sibcall_p)
02676 int sibcall_p;
02677 {
02678 rtx insn, reg, alt_reg, ar_unat_save_reg;
02679 int regno, alt_regno, cfa_off;
02680
02681 ia64_compute_frame_size (get_frame_size ());
02682
02683
02684
02685
02686 if (frame_pointer_needed)
02687 setup_spill_pointers (current_frame_info.n_spilled,
02688 hard_frame_pointer_rtx, 0);
02689 else
02690 setup_spill_pointers (current_frame_info.n_spilled, stack_pointer_rtx,
02691 current_frame_info.total_size);
02692
02693 if (current_frame_info.total_size != 0)
02694 {
02695
02696
02697
02698 emit_insn (gen_blockage ());
02699 }
02700
02701
02702 cfa_off = (current_frame_info.spill_cfa_off
02703 + current_frame_info.spill_size
02704 + current_frame_info.extra_spill_size);
02705
02706
02707 if (TEST_HARD_REG_BIT (current_frame_info.mask, PR_REG (0)))
02708 {
02709 if (current_frame_info.reg_save_pr != 0)
02710 alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_pr);
02711 else
02712 {
02713 alt_regno = next_scratch_gr_reg ();
02714 alt_reg = gen_rtx_REG (DImode, alt_regno);
02715 do_restore (gen_movdi_x, alt_reg, cfa_off);
02716 cfa_off -= 8;
02717 }
02718 reg = gen_rtx_REG (DImode, PR_REG (0));
02719 emit_move_insn (reg, alt_reg);
02720 }
02721
02722
02723
02724
02725
02726 if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM))
02727 {
02728 if (current_frame_info.reg_save_ar_unat != 0)
02729 ar_unat_save_reg
02730 = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_unat);
02731 else
02732 {
02733 alt_regno = next_scratch_gr_reg ();
02734 ar_unat_save_reg = gen_rtx_REG (DImode, alt_regno);
02735 current_frame_info.gr_used_mask |= 1 << alt_regno;
02736 do_restore (gen_movdi_x, ar_unat_save_reg, cfa_off);
02737 cfa_off -= 8;
02738 }
02739 }
02740 else
02741 ar_unat_save_reg = NULL_RTX;
02742
02743 if (current_frame_info.reg_save_ar_pfs != 0)
02744 {
02745 alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_pfs);
02746 reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
02747 emit_move_insn (reg, alt_reg);
02748 }
02749 else if (! current_function_is_leaf)
02750 {
02751 alt_regno = next_scratch_gr_reg ();
02752 alt_reg = gen_rtx_REG (DImode, alt_regno);
02753 do_restore (gen_movdi_x, alt_reg, cfa_off);
02754 cfa_off -= 8;
02755 reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
02756 emit_move_insn (reg, alt_reg);
02757 }
02758
02759 if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_LC_REGNUM))
02760 {
02761 if (current_frame_info.reg_save_ar_lc != 0)
02762 alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_lc);
02763 else
02764 {
02765 alt_regno = next_scratch_gr_reg ();
02766 alt_reg = gen_rtx_REG (DImode, alt_regno);
02767 do_restore (gen_movdi_x, alt_reg, cfa_off);
02768 cfa_off -= 8;
02769 }
02770 reg = gen_rtx_REG (DImode, AR_LC_REGNUM);
02771 emit_move_insn (reg, alt_reg);
02772 }
02773
02774
02775 if (cfa_off != (current_frame_info.spill_cfa_off
02776 + current_frame_info.spill_size))
02777 abort ();
02778
02779
02780
02781 if (TEST_HARD_REG_BIT (current_frame_info.mask, GR_REG (1)))
02782 cfa_off -= 8;
02783
02784
02785 for (regno = GR_REG (2); regno <= GR_REG (31); ++regno)
02786 if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
02787 {
02788 reg = gen_rtx_REG (DImode, regno);
02789 do_restore (gen_gr_restore, reg, cfa_off);
02790 cfa_off -= 8;
02791 }
02792
02793
02794
02795 if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
02796 {
02797 if (current_frame_info.reg_save_b0 != 0)
02798 alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
02799 else
02800 {
02801 alt_regno = next_scratch_gr_reg ();
02802 alt_reg = gen_rtx_REG (DImode, alt_regno);
02803 do_restore (gen_movdi_x, alt_reg, cfa_off);
02804 cfa_off -= 8;
02805 }
02806 reg = gen_rtx_REG (DImode, BR_REG (0));
02807 emit_move_insn (reg, alt_reg);
02808 }
02809
02810 for (regno = BR_REG (1); regno <= BR_REG (7); ++regno)
02811 if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
02812 {
02813 alt_regno = next_scratch_gr_reg ();
02814 alt_reg = gen_rtx_REG (DImode, alt_regno);
02815 do_restore (gen_movdi_x, alt_reg, cfa_off);
02816 cfa_off -= 8;
02817 reg = gen_rtx_REG (DImode, regno);
02818 emit_move_insn (reg, alt_reg);
02819 }
02820
02821
02822 for (regno = FR_REG (2); regno <= FR_REG (127); ++regno)
02823 if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
02824 {
02825 if (cfa_off & 15)
02826 abort ();
02827 reg = gen_rtx_REG (TFmode, regno);
02828 do_restore (gen_fr_restore_x, reg, cfa_off);
02829 cfa_off -= 16;
02830 }
02831
02832
02833 if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM))
02834 {
02835 reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM);
02836 emit_move_insn (reg, ar_unat_save_reg);
02837 }
02838
02839 if (cfa_off != current_frame_info.spill_cfa_off)
02840 abort ();
02841
02842 finish_spill_pointers ();
02843
02844 if (current_frame_info.total_size || cfun->machine->ia64_eh_epilogue_sp)
02845 {
02846
02847
02848
02849
02850 emit_insn (gen_blockage ());
02851 }
02852
02853 if (cfun->machine->ia64_eh_epilogue_sp)
02854 emit_move_insn (stack_pointer_rtx, cfun->machine->ia64_eh_epilogue_sp);
02855 else if (frame_pointer_needed)
02856 {
02857 insn = emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
02858 RTX_FRAME_RELATED_P (insn) = 1;
02859 }
02860 else if (current_frame_info.total_size)
02861 {
02862 rtx offset, frame_size_rtx;
02863
02864 frame_size_rtx = GEN_INT (current_frame_info.total_size);
02865 if (CONST_OK_FOR_I (current_frame_info.total_size))
02866 offset = frame_size_rtx;
02867 else
02868 {
02869 regno = next_scratch_gr_reg ();
02870 offset = gen_rtx_REG (DImode, regno);
02871 emit_move_insn (offset, frame_size_rtx);
02872 }
02873
02874 insn = emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
02875 offset));
02876
02877 RTX_FRAME_RELATED_P (insn) = 1;
02878 if (GET_CODE (offset) != CONST_INT)
02879 {
02880 REG_NOTES (insn)
02881 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
02882 gen_rtx_SET (VOIDmode,
02883 stack_pointer_rtx,
02884 gen_rtx_PLUS (DImode,
02885 stack_pointer_rtx,
02886 frame_size_rtx)),
02887 REG_NOTES (insn));
02888 }
02889 }
02890
02891 if (cfun->machine->ia64_eh_epilogue_bsp)
02892 emit_insn (gen_set_bsp (cfun->machine->ia64_eh_epilogue_bsp));
02893
02894 if (! sibcall_p)
02895 emit_jump_insn (gen_return_internal (gen_rtx_REG (DImode, BR_REG (0))));
02896 else
02897 {
02898 int fp = GR_REG (2);
02899
02900
02901
02902
02903
02904 if (current_frame_info.reg_fp && current_frame_info.reg_fp == GR_REG (2))
02905 fp = HARD_FRAME_POINTER_REGNUM;
02906
02907
02908
02909
02910
02911
02912
02913
02914 if (current_frame_info.n_input_regs != 0)
02915 emit_insn (gen_alloc (gen_rtx_REG (DImode, fp),
02916 GEN_INT (0), GEN_INT (0),
02917 GEN_INT (current_frame_info.n_input_regs),
02918 GEN_INT (0)));
02919 }
02920 }
02921
02922
02923
02924
02925 int
02926 ia64_direct_return ()
02927 {
02928 if (reload_completed && ! frame_pointer_needed)
02929 {
02930 ia64_compute_frame_size (get_frame_size ());
02931
02932 return (current_frame_info.total_size == 0
02933 && current_frame_info.n_spilled == 0
02934 && current_frame_info.reg_save_b0 == 0
02935 && current_frame_info.reg_save_pr == 0
02936 && current_frame_info.reg_save_ar_pfs == 0
02937 && current_frame_info.reg_save_ar_unat == 0
02938 && current_frame_info.reg_save_ar_lc == 0);
02939 }
02940 return 0;
02941 }
02942
02943 int
02944 ia64_hard_regno_rename_ok (from, to)
02945 int from;
02946 int to;
02947 {
02948
02949 if (to == current_frame_info.reg_fp
02950 || to == current_frame_info.reg_save_b0
02951 || to == current_frame_info.reg_save_pr
02952 || to == current_frame_info.reg_save_ar_pfs
02953 || to == current_frame_info.reg_save_ar_unat
02954 || to == current_frame_info.reg_save_ar_lc)
02955 return 0;
02956
02957 if (from == current_frame_info.reg_fp
02958 || from == current_frame_info.reg_save_b0
02959 || from == current_frame_info.reg_save_pr
02960 || from == current_frame_info.reg_save_ar_pfs
02961 || from == current_frame_info.reg_save_ar_unat
02962 || from == current_frame_info.reg_save_ar_lc)
02963 return 0;
02964
02965
02966 if (OUT_REGNO_P (to) && to >= OUT_REG (current_frame_info.n_output_regs))
02967 return 0;
02968
02969
02970 if (PR_REGNO_P (from) && PR_REGNO_P (to))
02971 return (from & 1) == (to & 1);
02972
02973 return 1;
02974 }
02975
02976
02977
02978
02979 static bool
02980 ia64_assemble_integer (x, size, aligned_p)
02981 rtx x;
02982 unsigned int size;
02983 int aligned_p;
02984 {
02985 if (size == (TARGET_ILP32 ? 4 : 8)
02986 && aligned_p
02987 && !(TARGET_NO_PIC || TARGET_AUTO_PIC)
02988 && GET_CODE (x) == SYMBOL_REF
02989 && SYMBOL_REF_FLAG (x))
02990 {
02991 if (TARGET_ILP32)
02992 fputs ("\tdata4\t@fptr(", asm_out_file);
02993 else
02994 fputs ("\tdata8\t@fptr(", asm_out_file);
02995 output_addr_const (asm_out_file, x);
02996 fputs (")\n", asm_out_file);
02997 return true;
02998 }
02999 return default_assemble_integer (x, size, aligned_p);
03000 }
03001
03002
03003
03004 static void
03005 ia64_output_function_prologue (file, size)
03006 FILE *file;
03007 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
03008 {
03009 int mask, grsave, grsave_prev;
03010
03011 if (current_frame_info.need_regstk)
03012 fprintf (file, "\t.regstk %d, %d, %d, %d\n",
03013 current_frame_info.n_input_regs,
03014 current_frame_info.n_local_regs,
03015 current_frame_info.n_output_regs,
03016 current_frame_info.n_rotate_regs);
03017
03018 if (!flag_unwind_tables && (!flag_exceptions || USING_SJLJ_EXCEPTIONS))
03019 return;
03020
03021
03022
03023 mask = 0;
03024 grsave = grsave_prev = 0;
03025 if (current_frame_info.reg_save_b0 != 0)
03026 {
03027 mask |= 8;
03028 grsave = grsave_prev = current_frame_info.reg_save_b0;
03029 }
03030 if (current_frame_info.reg_save_ar_pfs != 0
03031 && (grsave_prev == 0
03032 || current_frame_info.reg_save_ar_pfs == grsave_prev + 1))
03033 {
03034 mask |= 4;
03035 if (grsave_prev == 0)
03036 grsave = current_frame_info.reg_save_ar_pfs;
03037 grsave_prev = current_frame_info.reg_save_ar_pfs;
03038 }
03039 if (current_frame_info.reg_fp != 0
03040 && (grsave_prev == 0
03041 || current_frame_info.reg_fp == grsave_prev + 1))
03042 {
03043 mask |= 2;
03044 if (grsave_prev == 0)
03045 grsave = HARD_FRAME_POINTER_REGNUM;
03046 grsave_prev = current_frame_info.reg_fp;
03047 }
03048 if (current_frame_info.reg_save_pr != 0
03049 && (grsave_prev == 0
03050 || current_frame_info.reg_save_pr == grsave_prev + 1))
03051 {
03052 mask |= 1;
03053 if (grsave_prev == 0)
03054 grsave = current_frame_info.reg_save_pr;
03055 }
03056
03057 if (mask)
03058 fprintf (file, "\t.prologue %d, %d\n", mask,
03059 ia64_dbx_register_number (grsave));
03060 else
03061 fputs ("\t.prologue\n", file);
03062
03063
03064
03065 if (current_frame_info.spill_cfa_off != -16)
03066 fprintf (file, "\t.spill %ld\n",
03067 (long) (current_frame_info.spill_cfa_off
03068 + current_frame_info.spill_size));
03069 }
03070
03071
03072
03073 static void
03074 ia64_output_function_end_prologue (file)
03075 FILE *file;
03076 {
03077 if (!flag_unwind_tables && (!flag_exceptions || USING_SJLJ_EXCEPTIONS))
03078 return;
03079
03080 fputs ("\t.body\n", file);
03081 }
03082
03083
03084
03085 static void
03086 ia64_output_function_epilogue (file, size)
03087 FILE *file ATTRIBUTE_UNUSED;
03088 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
03089 {
03090 int i;
03091
03092
03093 XINT (return_address_pointer_rtx, 0) = RETURN_ADDRESS_POINTER_REGNUM;
03094
03095 if (current_frame_info.reg_fp)
03096 {
03097 const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM];
03098 reg_names[HARD_FRAME_POINTER_REGNUM]
03099 = reg_names[current_frame_info.reg_fp];
03100 reg_names[current_frame_info.reg_fp] = tmp;
03101 }
03102 if (! TARGET_REG_NAMES)
03103 {
03104 for (i = 0; i < current_frame_info.n_input_regs; i++)
03105 reg_names[IN_REG (i)] = ia64_input_reg_names[i];
03106 for (i = 0; i < current_frame_info.n_local_regs; i++)
03107 reg_names[LOC_REG (i)] = ia64_local_reg_names[i];
03108 for (i = 0; i < current_frame_info.n_output_regs; i++)
03109 reg_names[OUT_REG (i)] = ia64_output_reg_names[i];
03110 }
03111
03112 current_frame_info.initialized = 0;
03113 }
03114
03115 int
03116 ia64_dbx_register_number (regno)
03117 int regno;
03118 {
03119
03120
03121
03122 if (current_frame_info.reg_fp)
03123 {
03124 if (regno == HARD_FRAME_POINTER_REGNUM)
03125 regno = current_frame_info.reg_fp;
03126 else if (regno == current_frame_info.reg_fp)
03127 regno = HARD_FRAME_POINTER_REGNUM;
03128 }
03129
03130 if (IN_REGNO_P (regno))
03131 return 32 + regno - IN_REG (0);
03132 else if (LOC_REGNO_P (regno))
03133 return 32 + current_frame_info.n_input_regs + regno - LOC_REG (0);
03134 else if (OUT_REGNO_P (regno))
03135 return (32 + current_frame_info.n_input_regs
03136 + current_frame_info.n_local_regs + regno - OUT_REG (0));
03137 else
03138 return regno;
03139 }
03140
03141 void
03142 ia64_initialize_trampoline (addr, fnaddr, static_chain)
03143 rtx addr, fnaddr, static_chain;
03144 {
03145 rtx addr_reg, eight = GEN_INT (8);
03146
03147
03148 addr_reg = gen_reg_rtx (Pmode);
03149 emit_move_insn (addr_reg, addr);
03150
03151
03152
03153 emit_move_insn (gen_rtx_MEM (Pmode, addr_reg),
03154 gen_rtx_SYMBOL_REF (Pmode, "__ia64_trampoline"));
03155 emit_insn (gen_adddi3 (addr_reg, addr_reg, eight));
03156
03157 emit_move_insn (gen_rtx_MEM (Pmode, addr_reg),
03158 copy_to_reg (plus_constant (addr, 16)));
03159 emit_insn (gen_adddi3 (addr_reg, addr_reg, eight));
03160
03161
03162 emit_move_insn (gen_rtx_MEM (Pmode, addr_reg), fnaddr);
03163 emit_insn (gen_adddi3 (addr_reg, addr_reg, eight));
03164
03165
03166 emit_move_insn (gen_rtx_MEM (Pmode, addr_reg), static_chain);
03167 }
03168
03169
03170
03171
03172
03173
03174 void
03175 ia64_setup_incoming_varargs (cum, int_mode, type, pretend_size, second_time)
03176 CUMULATIVE_ARGS cum;
03177 int int_mode;
03178 tree type;
03179 int * pretend_size;
03180 int second_time ATTRIBUTE_UNUSED;
03181 {
03182
03183 ia64_function_arg_advance (&cum, int_mode, type, 1);
03184
03185 if (cum.words < MAX_ARGUMENT_SLOTS)
03186 {
03187 int n = MAX_ARGUMENT_SLOTS - cum.words;
03188 *pretend_size = n * UNITS_PER_WORD;
03189 cfun->machine->n_varargs = n;
03190 }
03191 }
03192
03193
03194
03195
03196
03197
03198
03199
03200
03201 static enum machine_mode
03202 hfa_element_mode (type, nested)
03203 tree type;
03204 int nested;
03205 {
03206 enum machine_mode element_mode = VOIDmode;
03207 enum machine_mode mode;
03208 enum tree_code code = TREE_CODE (type);
03209 int know_element_mode = 0;
03210 tree t;
03211
03212 switch (code)
03213 {
03214 case VOID_TYPE: case INTEGER_TYPE: case ENUMERAL_TYPE:
03215 case BOOLEAN_TYPE: case CHAR_TYPE: case POINTER_TYPE:
03216 case OFFSET_TYPE: case REFERENCE_TYPE: case METHOD_TYPE:
03217 case FILE_TYPE: case SET_TYPE: case LANG_TYPE:
03218 case FUNCTION_TYPE:
03219 return VOIDmode;
03220
03221
03222
03223
03224 case COMPLEX_TYPE:
03225 if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT
03226 && (TYPE_MODE (type) != TCmode || INTEL_EXTENDED_IEEE_FORMAT))
03227 return mode_for_size (GET_MODE_UNIT_SIZE (TYPE_MODE (type))
03228 * BITS_PER_UNIT, MODE_FLOAT, 0);
03229 else
03230 return VOIDmode;
03231
03232 case REAL_TYPE:
03233
03234
03235 if (nested && (TYPE_MODE (type) != TFmode || INTEL_EXTENDED_IEEE_FORMAT))
03236 return TYPE_MODE (type);
03237 else
03238 return VOIDmode;
03239
03240 case ARRAY_TYPE:
03241 return hfa_element_mode (TREE_TYPE (type), 1);
03242
03243 case RECORD_TYPE:
03244 case UNION_TYPE:
03245 case QUAL_UNION_TYPE:
03246 for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
03247 {
03248 if (TREE_CODE (t) != FIELD_DECL)
03249 continue;
03250
03251 mode = hfa_element_mode (TREE_TYPE (t), 1);
03252 if (know_element_mode)
03253 {
03254 if (mode != element_mode)
03255 return VOIDmode;
03256 }
03257 else if (GET_MODE_CLASS (mode) != MODE_FLOAT)
03258 return VOIDmode;
03259 else
03260 {
03261 know_element_mode = 1;
03262 element_mode = mode;
03263 }
03264 }
03265 return element_mode;
03266
03267 default:
03268
03269
03270
03271
03272 return VOIDmode;
03273 }
03274
03275 return VOIDmode;
03276 }
03277
03278
03279
03280
03281
03282
03283
03284 rtx
03285 ia64_function_arg (cum, mode, type, named, incoming)
03286 CUMULATIVE_ARGS *cum;
03287 enum machine_mode mode;
03288 tree type;
03289 int named;
03290 int incoming;
03291 {
03292 int basereg = (incoming ? GR_ARG_FIRST : AR_ARG_FIRST);
03293 int words = (((mode == BLKmode ? int_size_in_bytes (type)
03294 : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1)
03295 / UNITS_PER_WORD);
03296 int offset = 0;
03297 enum machine_mode hfa_mode = VOIDmode;
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307 if ((type ? (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
03308 : (words > 1))
03309 && (cum->words & 1))
03310 offset = 1;
03311
03312
03313 if (cum->words + offset >= MAX_ARGUMENT_SLOTS)
03314 return 0;
03315
03316
03317 if (type)
03318 hfa_mode = hfa_element_mode (type, 0);
03319
03320
03321
03322 if (hfa_mode != VOIDmode && (! cum->prototype || named))
03323 {
03324 rtx loc[16];
03325 int i = 0;
03326 int fp_regs = cum->fp_regs;
03327 int int_regs = cum->words + offset;
03328 int hfa_size = GET_MODE_SIZE (hfa_mode);
03329 int byte_size;
03330 int args_byte_size;
03331
03332
03333
03334
03335
03336
03337
03338
03339
03340
03341
03342 byte_size = ((mode == BLKmode)
03343 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
03344 args_byte_size = int_regs * UNITS_PER_WORD;
03345 offset = 0;
03346 for (; (offset < byte_size && fp_regs < MAX_ARGUMENT_SLOTS
03347 && args_byte_size < (MAX_ARGUMENT_SLOTS * UNITS_PER_WORD)); i++)
03348 {
03349 loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
03350 gen_rtx_REG (hfa_mode, (FR_ARG_FIRST
03351 + fp_regs)),
03352 GEN_INT (offset));
03353 offset += hfa_size;
03354 args_byte_size += hfa_size;
03355 fp_regs++;
03356 }
03357
03358
03359 if (! cum->prototype)
03360 offset = 0;
03361
03362
03363 else if (byte_size != offset)
03364 int_regs += offset / UNITS_PER_WORD;
03365
03366
03367
03368 for (; offset < byte_size && int_regs < MAX_ARGUMENT_SLOTS; i++)
03369 {
03370 enum machine_mode gr_mode = DImode;
03371
03372
03373
03374
03375
03376
03377 if (offset & 0x4)
03378 gr_mode = SImode;
03379
03380
03381
03382 else if (byte_size - offset == 4)
03383 gr_mode = SImode;
03384
03385 if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
03386 gr_mode = hfa_mode;
03387
03388 loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
03389 gen_rtx_REG (gr_mode, (basereg
03390 + int_regs)),
03391 GEN_INT (offset));
03392 offset += GET_MODE_SIZE (gr_mode);
03393 int_regs += GET_MODE_SIZE (gr_mode) <= UNITS_PER_WORD
03394 ? 1 : GET_MODE_SIZE (gr_mode) / UNITS_PER_WORD;
03395 }
03396
03397
03398 if (i == 1)
03399 return XEXP (loc[0], 0);
03400 else
03401 return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
03402 }
03403
03404
03405
03406
03407 else if (((mode == TFmode) && ! INTEL_EXTENDED_IEEE_FORMAT)
03408 || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
03409 {
03410 int byte_size = ((mode == BLKmode)
03411 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
03412 if (BYTES_BIG_ENDIAN
03413 && (mode == BLKmode || (type && AGGREGATE_TYPE_P (type)))
03414 && byte_size < UNITS_PER_WORD
03415 && byte_size > 0)
03416 {
03417 rtx gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
03418 gen_rtx_REG (DImode,
03419 (basereg + cum->words
03420 + offset)),
03421 const0_rtx);
03422 return gen_rtx_PARALLEL (mode, gen_rtvec (1, gr_reg));
03423 }
03424 else
03425 return gen_rtx_REG (mode, basereg + cum->words + offset);
03426
03427 }
03428
03429
03430
03431 else if (cum->prototype)
03432 {
03433 if (! named)
03434 return gen_rtx_REG (mode, basereg + cum->words + offset);
03435 else
03436 return gen_rtx_REG (mode, FR_ARG_FIRST + cum->fp_regs);
03437 }
03438
03439
03440 else
03441 {
03442 rtx fp_reg = gen_rtx_EXPR_LIST (VOIDmode,
03443 gen_rtx_REG (mode, (FR_ARG_FIRST
03444 + cum->fp_regs)),
03445 const0_rtx);
03446 rtx gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
03447 gen_rtx_REG (mode,
03448 (basereg + cum->words
03449 + offset)),
03450 const0_rtx);
03451
03452 return gen_rtx_PARALLEL (mode, gen_rtvec (2, fp_reg, gr_reg));
03453 }
03454 }
03455
03456
03457
03458
03459
03460 int
03461 ia64_function_arg_partial_nregs (cum, mode, type, named)
03462 CUMULATIVE_ARGS *cum;
03463 enum machine_mode mode;
03464 tree type;
03465 int named ATTRIBUTE_UNUSED;
03466 {
03467 int words = (((mode == BLKmode ? int_size_in_bytes (type)
03468 : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1)
03469 / UNITS_PER_WORD);
03470 int offset = 0;
03471
03472
03473
03474 if ((type ? (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
03475 : (words > 1))
03476 && (cum->words & 1))
03477 offset = 1;
03478
03479
03480 if (cum->words + offset >= MAX_ARGUMENT_SLOTS)
03481 return 0;
03482
03483
03484
03485
03486
03487
03488 if (words + cum->words + offset <= MAX_ARGUMENT_SLOTS)
03489 return 0;
03490
03491 return MAX_ARGUMENT_SLOTS - cum->words - offset;
03492 }
03493
03494
03495
03496
03497 void
03498 ia64_function_arg_advance (cum, mode, type, named)
03499 CUMULATIVE_ARGS *cum;
03500 enum machine_mode mode;
03501 tree type;
03502 int named;
03503 {
03504 int words = (((mode == BLKmode ? int_size_in_bytes (type)
03505 : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1)
03506 / UNITS_PER_WORD);
03507 int offset = 0;
03508 enum machine_mode hfa_mode = VOIDmode;
03509
03510
03511 if (cum->words >= MAX_ARGUMENT_SLOTS)
03512 return;
03513
03514
03515
03516 if ((type ? (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
03517 : (words > 1))
03518 && (cum->words & 1))
03519 offset = 1;
03520
03521 cum->words += words + offset;
03522
03523
03524 if (type)
03525 hfa_mode = hfa_element_mode (type, 0);
03526
03527
03528
03529 if (hfa_mode != VOIDmode && (! cum->prototype || named))
03530 {
03531 int fp_regs = cum->fp_regs;
03532
03533 int int_regs = cum->words - words;
03534 int hfa_size = GET_MODE_SIZE (hfa_mode);
03535 int byte_size;
03536 int args_byte_size;
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548 byte_size = ((mode == BLKmode)
03549 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
03550 args_byte_size = int_regs * UNITS_PER_WORD;
03551 offset = 0;
03552 for (; (offset < byte_size && fp_regs < MAX_ARGUMENT_SLOTS
03553 && args_byte_size < (MAX_ARGUMENT_SLOTS * UNITS_PER_WORD));)
03554 {
03555 offset += hfa_size;
03556 args_byte_size += hfa_size;
03557 fp_regs++;
03558 }
03559
03560 cum->fp_regs = fp_regs;
03561 }
03562
03563
03564
03565
03566 else if (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS)
03567 cum->int_regs = cum->words;
03568
03569
03570
03571 else if (cum->prototype)
03572 {
03573 if (! named)
03574 cum->int_regs = cum->words;
03575 else
03576
03577 cum->fp_regs += (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT ? 2 : 1);
03578 }
03579
03580
03581 else
03582 {
03583
03584 cum->fp_regs += (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT ? 2 : 1);
03585 cum->int_regs = cum->words;
03586 }
03587 }
03588
03589
03590
03591
03592 int
03593 ia64_function_arg_pass_by_reference (cum, mode, type, named)
03594 CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
03595 enum machine_mode mode ATTRIBUTE_UNUSED;
03596 tree type;
03597 int named ATTRIBUTE_UNUSED;
03598 {
03599 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
03600 }
03601
03602
03603
03604
03605 rtx
03606 ia64_va_arg (valist, type)
03607 tree valist, type;
03608 {
03609 tree t;
03610
03611
03612 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
03613 {
03614 rtx addr = std_expand_builtin_va_arg (valist, build_pointer_type (type));
03615 return gen_rtx_MEM (ptr_mode, force_reg (Pmode, addr));
03616 }
03617
03618
03619
03620 if (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
03621 {
03622 t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
03623 build_int_2 (2 * UNITS_PER_WORD - 1, 0));
03624 t = build (BIT_AND_EXPR, TREE_TYPE (t), t,
03625 build_int_2 (-2 * UNITS_PER_WORD, -1));
03626 t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
03627 TREE_SIDE_EFFECTS (t) = 1;
03628 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03629 }
03630
03631 return std_expand_builtin_va_arg (valist, type);
03632 }
03633
03634
03635
03636
03637 int
03638 ia64_return_in_memory (valtype)
03639 tree valtype;
03640 {
03641 enum machine_mode mode;
03642 enum machine_mode hfa_mode;
03643 HOST_WIDE_INT byte_size;
03644
03645 mode = TYPE_MODE (valtype);
03646 byte_size = GET_MODE_SIZE (mode);
03647 if (mode == BLKmode)
03648 {
03649 byte_size = int_size_in_bytes (valtype);
03650 if (byte_size < 0)
03651 return 1;
03652 }
03653
03654
03655
03656 hfa_mode = hfa_element_mode (valtype, 0);
03657 if (hfa_mode != VOIDmode)
03658 {
03659 int hfa_size = GET_MODE_SIZE (hfa_mode);
03660
03661 if (byte_size / hfa_size > MAX_ARGUMENT_SLOTS)
03662 return 1;
03663 else
03664 return 0;
03665 }
03666 else if (byte_size > UNITS_PER_WORD * MAX_INT_RETURN_SLOTS)
03667 return 1;
03668 else
03669 return 0;
03670 }
03671
03672
03673
03674 rtx
03675 ia64_function_value (valtype, func)
03676 tree valtype;
03677 tree func ATTRIBUTE_UNUSED;
03678 {
03679 enum machine_mode mode;
03680 enum machine_mode hfa_mode;
03681
03682 mode = TYPE_MODE (valtype);
03683 hfa_mode = hfa_element_mode (valtype, 0);
03684
03685 if (hfa_mode != VOIDmode)
03686 {
03687 rtx loc[8];
03688 int i;
03689 int hfa_size;
03690 int byte_size;
03691 int offset;
03692
03693 hfa_size = GET_MODE_SIZE (hfa_mode);
03694 byte_size = ((mode == BLKmode)
03695 ? int_size_in_bytes (valtype) : GET_MODE_SIZE (mode));
03696 offset = 0;
03697 for (i = 0; offset < byte_size; i++)
03698 {
03699 loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
03700 gen_rtx_REG (hfa_mode, FR_ARG_FIRST + i),
03701 GEN_INT (offset));
03702 offset += hfa_size;
03703 }
03704
03705 if (i == 1)
03706 return XEXP (loc[0], 0);
03707 else
03708 return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
03709 }
03710 else if (FLOAT_TYPE_P (valtype) &&
03711 ((mode != TFmode) || INTEL_EXTENDED_IEEE_FORMAT))
03712 return gen_rtx_REG (mode, FR_ARG_FIRST);
03713 else
03714 {
03715 if (BYTES_BIG_ENDIAN
03716 && (mode == BLKmode || (valtype && AGGREGATE_TYPE_P (valtype))))
03717 {
03718 rtx loc[8];
03719 int offset;
03720 int bytesize;
03721 int i;
03722
03723 offset = 0;
03724 bytesize = int_size_in_bytes (valtype);
03725 for (i = 0; offset < bytesize; i++)
03726 {
03727 loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
03728 gen_rtx_REG (DImode,
03729 GR_RET_FIRST + i),
03730 GEN_INT (offset));
03731 offset += UNITS_PER_WORD;
03732 }
03733 return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
03734 }
03735 else
03736 return gen_rtx_REG (mode, GR_RET_FIRST);
03737 }
03738 }
03739
03740
03741
03742
03743
03744
03745 void
03746 ia64_print_operand_address (stream, address)
03747 FILE * stream ATTRIBUTE_UNUSED;
03748 rtx address ATTRIBUTE_UNUSED;
03749 {
03750 }
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772 void
03773 ia64_print_operand (file, x, code)
03774 FILE * file;
03775 rtx x;
03776 int code;
03777 {
03778 const char *str;
03779
03780 switch (code)
03781 {
03782 case 0:
03783
03784 break;
03785
03786 case 'C':
03787 {
03788 enum rtx_code c = swap_condition (GET_CODE (x));
03789 fputs (GET_RTX_NAME (c), file);
03790 return;
03791 }
03792
03793 case 'D':
03794 switch (GET_CODE (x))
03795 {
03796 case NE:
03797 str = "neq";
03798 break;
03799 case UNORDERED:
03800 str = "unord";
03801 break;
03802 case ORDERED:
03803 str = "ord";
03804 break;
03805 default:
03806 str = GET_RTX_NAME (GET_CODE (x));
03807 break;
03808 }
03809 fputs (str, file);
03810 return;
03811
03812 case 'E':
03813 fprintf (file, HOST_WIDE_INT_PRINT_DEC, 32 - INTVAL (x));
03814 return;
03815
03816 case 'e':
03817 fprintf (file, HOST_WIDE_INT_PRINT_DEC, 64 - INTVAL (x));
03818 return;
03819
03820 case 'F':
03821 if (x == CONST0_RTX (GET_MODE (x)))
03822 str = reg_names [FR_REG (0)];
03823 else if (x == CONST1_RTX (GET_MODE (x)))
03824 str = reg_names [FR_REG (1)];
03825 else if (GET_CODE (x) == REG)
03826 str = reg_names [REGNO (x)];
03827 else
03828 abort ();
03829 fputs (str, file);
03830 return;
03831
03832 case 'I':
03833 fputs (reg_names [REGNO (x) + 1], file);
03834 return;
03835
03836 case 'J':
03837 case 'j':
03838 {
03839 unsigned int regno = REGNO (XEXP (x, 0));
03840 if (GET_CODE (x) == EQ)
03841 regno += 1;
03842 if (code == 'j')
03843 regno ^= 1;
03844 fputs (reg_names [regno], file);
03845 }
03846 return;
03847
03848 case 'O':
03849 if (MEM_VOLATILE_P (x))
03850 fputs(".acq", file);
03851 return;
03852
03853 case 'P':
03854 {
03855 HOST_WIDE_INT value;
03856
03857 switch (GET_CODE (XEXP (x, 0)))
03858 {
03859 default:
03860 return;
03861
03862 case POST_MODIFY:
03863 x = XEXP (XEXP (XEXP (x, 0), 1), 1);
03864 if (GET_CODE (x) == CONST_INT)
03865 value = INTVAL (x);
03866 else if (GET_CODE (x) == REG)
03867 {
03868 fprintf (file, ", %s", reg_names[REGNO (x)]);
03869 return;
03870 }
03871 else
03872 abort ();
03873 break;
03874
03875 case POST_INC:
03876 value = GET_MODE_SIZE (GET_MODE (x));
03877 break;
03878
03879 case POST_DEC:
03880 value = - (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (x));
03881 break;
03882 }
03883
03884 putc (',', file);
03885 putc (' ', file);
03886 fprintf (file, HOST_WIDE_INT_PRINT_DEC, value);
03887 return;
03888 }
03889
03890 case 'Q':
03891 if (MEM_VOLATILE_P (x))
03892 fputs(".rel", file);
03893 return;
03894
03895 case 'S':
03896 fprintf (file, "%d", exact_log2 (INTVAL (x)));
03897 return;
03898
03899 case 'T':
03900 if (! TARGET_GNU_AS && GET_CODE (x) == CONST_INT)
03901 {
03902 fprintf (file, "0x%x", (int) INTVAL (x) & 0xffffffff);
03903 return;
03904 }
03905 break;
03906
03907 case 'U':
03908 if (! TARGET_GNU_AS && GET_CODE (x) == CONST_INT)
03909 {
03910 const char *prefix = "0x";
03911 if (INTVAL (x) & 0x80000000)
03912 {
03913 fprintf (file, "0xffffffff");
03914 prefix = "";
03915 }
03916 fprintf (file, "%s%x", prefix, (int) INTVAL (x) & 0xffffffff);
03917 return;
03918 }
03919 break;
03920
03921 case 'r':
03922
03923
03924 if (GET_CODE (x) == REG)
03925 fputs (reg_names[REGNO (x)], file);
03926 else if (x == CONST0_RTX (GET_MODE (x)))
03927 fputs ("r0", file);
03928 else if (GET_CODE (x) == CONST_INT)
03929 output_addr_const (file, x);
03930 else
03931 output_operand_lossage ("invalid %%r value");
03932 return;
03933
03934 case '+':
03935 {
03936 const char *which;
03937
03938
03939
03940 x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
03941 if (x)
03942 {
03943 int pred_val = INTVAL (XEXP (x, 0));
03944
03945
03946 if (pred_val < REG_BR_PROB_BASE / 50)
03947 which = ".spnt";
03948 else if (pred_val < REG_BR_PROB_BASE / 2)
03949 which = ".dpnt";
03950 else if (pred_val < REG_BR_PROB_BASE / 100 * 98)
03951 which = ".dptk";
03952 else
03953 which = ".sptk";
03954 }
03955 else if (GET_CODE (current_output_insn) == CALL_INSN)
03956 which = ".sptk";
03957 else
03958 which = ".dptk";
03959
03960 fputs (which, file);
03961 return;
03962 }
03963
03964 case ',':
03965 x = current_insn_predicate;
03966 if (x)
03967 {
03968 unsigned int regno = REGNO (XEXP (x, 0));
03969 if (GET_CODE (x) == EQ)
03970 regno += 1;
03971 fprintf (file, "(%s) ", reg_names [regno]);
03972 }
03973 return;
03974
03975 default:
03976 output_operand_lossage ("ia64_print_operand: unknown code");
03977 return;
03978 }
03979
03980 switch (GET_CODE (x))
03981 {
03982
03983 case POST_INC:
03984 case POST_DEC:
03985 case POST_MODIFY:
03986 x = XEXP (x, 0);
03987
03988
03989 case REG:
03990 fputs (reg_names [REGNO (x)], file);
03991 break;
03992
03993 case MEM:
03994 {
03995 rtx addr = XEXP (x, 0);
03996 if (GET_RTX_CLASS (GET_CODE (addr)) == 'a')
03997 addr = XEXP (addr, 0);
03998 fprintf (file, "[%s]", reg_names [REGNO (addr)]);
03999 break;
04000 }
04001
04002 default:
04003 output_addr_const (file, x);
04004 break;
04005 }
04006
04007 return;
04008 }
04009
04010
04011
04012
04013 int
04014 ia64_register_move_cost (mode, from, to)
04015 enum machine_mode mode;
04016 enum reg_class from, to;
04017 {
04018
04019 if (to == ADDL_REGS)
04020 to = GR_REGS;
04021 if (from == ADDL_REGS)
04022 from = GR_REGS;
04023
04024
04025
04026 if (from < to)
04027 {
04028 enum reg_class tmp = to;
04029 to = from, from = tmp;
04030 }
04031
04032
04033
04034
04035
04036 if (mode == TFmode)
04037 {
04038 if (to != GR_REGS || from != GR_REGS)
04039 return MEMORY_MOVE_COST (mode, to, 0);
04040 else
04041 return 3;
04042 }
04043
04044 switch (to)
04045 {
04046 case PR_REGS:
04047
04048 if (from == PR_REGS)
04049 return 3;
04050
04051 if (from != GR_REGS)
04052 return MEMORY_MOVE_COST (mode, to, 0);
04053 break;
04054
04055 case BR_REGS:
04056
04057 if (from != GR_REGS && from != GR_AND_BR_REGS)
04058 return MEMORY_MOVE_COST (mode, to, 0);
04059 break;
04060
04061 case AR_I_REGS:
04062 case AR_M_REGS:
04063
04064 if (from != GR_REGS)
04065 return MEMORY_MOVE_COST (mode, to, 0);
04066 break;
04067
04068 case GR_REGS:
04069 case FR_REGS:
04070 case GR_AND_FR_REGS:
04071 case GR_AND_BR_REGS:
04072 case ALL_REGS:
04073 break;
04074
04075 default:
04076 abort ();
04077 }
04078
04079 return 2;
04080 }
04081
04082
04083
04084
04085
04086
04087 enum reg_class
04088 ia64_secondary_reload_class (class, mode, x)
04089 enum reg_class class;
04090 enum machine_mode mode ATTRIBUTE_UNUSED;
04091 rtx x;
04092 {
04093 int regno = -1;
04094
04095 if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
04096 regno = true_regnum (x);
04097
04098 switch (class)
04099 {
04100 case BR_REGS:
04101 case AR_M_REGS:
04102 case AR_I_REGS:
04103
04104
04105
04106
04107
04108
04109
04110
04111
04112
04113
04114
04115 if (regno >= 0 && ! GENERAL_REGNO_P (regno))
04116 return GR_REGS;
04117
04118
04119
04120 if (GET_CODE (x) == MEM)
04121 return GR_REGS;
04122 break;
04123
04124 case FR_REGS:
04125
04126 if (regno >= 0 && ! (FR_REGNO_P (regno) || GENERAL_REGNO_P (regno)))
04127 return GR_REGS;
04128
04129
04130
04131
04132
04133
04134
04135
04136 if (GET_CODE (x) == MEM
04137 && (GET_MODE (x) == SImode || GET_MODE (x) == HImode
04138 || GET_MODE (x) == QImode))
04139 return GR_REGS;
04140
04141
04142
04143
04144 if (GET_CODE (x) == CONST_INT)
04145 return GR_REGS;
04146
04147
04148
04149 if (GET_CODE (x) == PLUS)
04150 return GR_REGS;
04151 break;
04152
04153 case PR_REGS:
04154
04155
04156
04157
04158
04159
04160 if (GET_CODE (x) == MEM)
04161 return GR_REGS;
04162
04163
04164
04165 if (regno >= 0 && ! GENERAL_REGNO_P (regno) && ! PR_REGNO_P (regno))
04166 return GR_REGS;
04167 break;
04168
04169 case GR_REGS:
04170
04171
04172 if (mode == TImode)
04173 return GR_REGS;
04174 break;
04175
04176 default:
04177 break;
04178 }
04179
04180 return NO_REGS;
04181 }
04182
04183
04184
04185
04186 void
04187 ia64_asm_output_external (file, decl, name)
04188 FILE *file;
04189 tree decl;
04190 const char *name;
04191 {
04192 int save_referenced;
04193
04194
04195
04196
04197 if (TARGET_GNU_AS
04198 && (!TARGET_HPUX_LD
04199 || TREE_CODE (decl) != FUNCTION_DECL
04200 || strstr(name, "__builtin_") == name))
04201 return;
04202
04203
04204
04205
04206
04207
04208
04209 if (! strcmp (name, "__builtin_next_arg")
04210 || ! strcmp (name, "alloca")
04211 || ! strcmp (name, "__builtin_constant_p")
04212 || ! strcmp (name, "__builtin_args_info"))
04213 return;
04214
04215 if (TARGET_HPUX_LD)
04216 ia64_hpux_add_extern_decl (name);
04217 else
04218 {
04219
04220
04221 save_referenced = TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl));
04222 if (TREE_CODE (decl) == FUNCTION_DECL)
04223 ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
04224 (*targetm.asm_out.globalize_label) (file, name);
04225 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = save_referenced;
04226 }
04227 }
04228
04229
04230
04231 static void
04232 fix_range (const_str)
04233 const char *const_str;
04234 {
04235 int i, first, last;
04236 char *str, *dash, *comma;
04237
04238
04239
04240
04241
04242
04243
04244 i = strlen (const_str);
04245 str = (char *) alloca (i + 1);
04246 memcpy (str, const_str, i + 1);
04247
04248 while (1)
04249 {
04250 dash = strchr (str, '-');
04251 if (!dash)
04252 {
04253 warning ("value of -mfixed-range must have form REG1-REG2");
04254 return;
04255 }
04256 *dash = '\0';
04257
04258 comma = strchr (dash + 1, ',');
04259 if (comma)
04260 *comma = '\0';
04261
04262 first = decode_reg_name (str);
04263 if (first < 0)
04264 {
04265 warning ("unknown register name: %s", str);
04266 return;
04267 }
04268
04269 last = decode_reg_name (dash + 1);
04270 if (last < 0)
04271 {
04272 warning ("unknown register name: %s", dash + 1);
04273 return;
04274 }
04275
04276 *dash = '-';
04277
04278 if (first > last)
04279 {
04280 warning ("%s-%s is an empty range", str, dash + 1);
04281 return;
04282 }
04283
04284 for (i = first; i <= last; ++i)
04285 fixed_regs[i] = call_used_regs[i] = 1;
04286
04287 if (!comma)
04288 break;
04289
04290 *comma = ',';
04291 str = comma + 1;
04292 }
04293 }
04294
04295 static struct machine_function *
04296 ia64_init_machine_status ()
04297 {
04298 return ggc_alloc_cleared (sizeof (struct machine_function));
04299 }
04300
04301
04302
04303 void
04304 ia64_override_options ()
04305 {
04306 if (TARGET_AUTO_PIC)
04307 target_flags |= MASK_CONST_GP;
04308
04309 if (TARGET_INLINE_FLOAT_DIV_LAT && TARGET_INLINE_FLOAT_DIV_THR)
04310 {
04311 warning ("cannot optimize floating point division for both latency and throughput");
04312 target_flags &= ~MASK_INLINE_FLOAT_DIV_THR;
04313 }
04314
04315 if (TARGET_INLINE_INT_DIV_LAT && TARGET_INLINE_INT_DIV_THR)
04316 {
04317 warning ("cannot optimize integer division for both latency and throughput");
04318 target_flags &= ~MASK_INLINE_INT_DIV_THR;
04319 }
04320
04321 if (ia64_fixed_range_string)
04322 fix_range (ia64_fixed_range_string);
04323
04324 if (ia64_tls_size_string)
04325 {
04326 char *end;
04327 unsigned long tmp = strtoul (ia64_tls_size_string, &end, 10);
04328 if (*end || (tmp != 14 && tmp != 22 && tmp != 64))
04329 error ("bad value (%s) for -mtls-size= switch", ia64_tls_size_string);
04330 else
04331 ia64_tls_size = tmp;
04332 }
04333
04334 ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload;
04335 flag_schedule_insns_after_reload = 0;
04336
04337 ia64_section_threshold = g_switch_set ? g_switch_value : IA64_DEFAULT_GVALUE;
04338
04339 init_machine_status = ia64_init_machine_status;
04340
04341
04342 if (INTEL_EXTENDED_IEEE_FORMAT)
04343 real_format_for_mode[TFmode - QFmode] = &ieee_extended_intel_128_format;
04344 }
04345
04346 static enum attr_itanium_requires_unit0 ia64_safe_itanium_requires_unit0 PARAMS((rtx));
04347 static enum attr_itanium_class ia64_safe_itanium_class PARAMS((rtx));
04348 static enum attr_type ia64_safe_type PARAMS((rtx));
04349
04350 static enum attr_itanium_requires_unit0
04351 ia64_safe_itanium_requires_unit0 (insn)
04352 rtx insn;
04353 {
04354 if (recog_memoized (insn) >= 0)
04355 return get_attr_itanium_requires_unit0 (insn);
04356 else
04357 return ITANIUM_REQUIRES_UNIT0_NO;
04358 }
04359
04360 static enum attr_itanium_class
04361 ia64_safe_itanium_class (insn)
04362 rtx insn;
04363 {
04364 if (recog_memoized (insn) >= 0)
04365 return get_attr_itanium_class (insn);
04366 else
04367 return ITANIUM_CLASS_UNKNOWN;
04368 }
04369
04370 static enum attr_type
04371 ia64_safe_type (insn)
04372 rtx insn;
04373 {
04374 if (recog_memoized (insn) >= 0)
04375 return get_attr_type (insn);
04376 else
04377 return TYPE_UNKNOWN;
04378 }
04379
04380
04381
04382
04383
04384
04385
04386
04387
04388
04389 #define REG_GP (GR_REG (1))
04390 #define REG_RP (BR_REG (0))
04391 #define REG_AR_CFM (FIRST_PSEUDO_REGISTER + 1)
04392
04393
04394 #define REG_VOLATILE (FIRST_PSEUDO_REGISTER + 2)
04395 #define AR_UNAT_BIT_0 (FIRST_PSEUDO_REGISTER + 3)
04396 #define NUM_REGS (AR_UNAT_BIT_0 + 64)
04397
04398
04399
04400
04401
04402
04403
04404
04405
04406
04407
04408
04409
04410
04411
04412
04413
04414
04415
04416
04417
04418 struct reg_write_state
04419 {
04420 unsigned int write_count : 2;
04421 unsigned int first_pred : 16;
04422 unsigned int written_by_fp : 1;
04423 unsigned int written_by_and : 1;
04424 unsigned int written_by_or : 1;
04425 };
04426
04427
04428 struct reg_write_state rws_sum[NUM_REGS];
04429
04430
04431 struct reg_write_state rws_insn[NUM_REGS];
04432
04433
04434
04435
04436 static int first_instruction;
04437
04438
04439
04440 struct reg_flags
04441 {
04442 unsigned int is_write : 1;
04443 unsigned int is_fp : 1;
04444 unsigned int is_branch : 1;
04445 unsigned int is_and : 1;
04446 unsigned int is_or : 1;
04447 unsigned int is_sibcall : 1;
04448 };
04449
04450 static void rws_update PARAMS ((struct reg_write_state *, int,
04451 struct reg_flags, int));
04452 static int rws_access_regno PARAMS ((int, struct reg_flags, int));
04453 static int rws_access_reg PARAMS ((rtx, struct reg_flags, int));
04454 static void update_set_flags PARAMS ((rtx, struct reg_flags *, int *, rtx *));
04455 static int set_src_needs_barrier PARAMS ((rtx, struct reg_flags, int, rtx));
04456 static int rtx_needs_barrier PARAMS ((rtx, struct reg_flags, int));
04457 static void init_insn_group_barriers PARAMS ((void));
04458 static int group_barrier_needed_p PARAMS ((rtx));
04459 static int safe_group_barrier_needed_p PARAMS ((rtx));
04460
04461
04462
04463
04464 static void
04465 rws_update (rws, regno, flags, pred)
04466 struct reg_write_state *rws;
04467 int regno;
04468 struct reg_flags flags;
04469 int pred;
04470 {
04471 if (pred)
04472 rws[regno].write_count++;
04473 else
04474 rws[regno].write_count = 2;
04475 rws[regno].written_by_fp |= flags.is_fp;
04476
04477 rws[regno].written_by_and = flags.is_and;
04478 rws[regno].written_by_or = flags.is_or;
04479 rws[regno].first_pred = pred;
04480 }
04481
04482
04483
04484
04485
04486 static int
04487 rws_access_regno (regno, flags, pred)
04488 int regno;
04489 struct reg_flags flags;
04490 int pred;
04491 {
04492 int need_barrier = 0;
04493
04494 if (regno >= NUM_REGS)
04495 abort ();
04496
04497 if (! PR_REGNO_P (regno))
04498 flags.is_and = flags.is_or = 0;
04499
04500 if (flags.is_write)
04501 {
04502 int write_count;
04503
04504
04505 if (rws_insn[regno].write_count > 0)
04506 abort ();
04507
04508
04509 rws_update (rws_insn, regno, flags, pred);
04510 write_count = rws_sum[regno].write_count;
04511
04512 switch (write_count)
04513 {
04514 case 0:
04515
04516 rws_update (rws_sum, regno, flags, pred);
04517 break;
04518
04519 case 1:
04520
04521
04522
04523
04524 if (flags.is_and && rws_sum[regno].written_by_and)
04525 ;
04526 else if (flags.is_or && rws_sum[regno].written_by_or)
04527 ;
04528 else if ((rws_sum[regno].first_pred ^ 1) != pred)
04529 need_barrier = 1;
04530 rws_update (rws_sum, regno, flags, pred);
04531 break;
04532
04533 case 2:
04534
04535
04536 if (flags.is_and && rws_sum[regno].written_by_and)
04537 ;
04538 else if (flags.is_or && rws_sum[regno].written_by_or)
04539 ;
04540 else
04541 need_barrier = 1;
04542 rws_sum[regno].written_by_and = flags.is_and;
04543 rws_sum[regno].written_by_or = flags.is_or;
04544 break;
04545
04546 default:
04547 abort ();
04548 }
04549 }
04550 else
04551 {
04552 if (flags.is_branch)
04553 {
04554
04555
04556
04557 if (REGNO_REG_CLASS (regno) == BR_REGS || regno == AR_PFS_REGNUM)
04558
04559
04560
04561
04562
04563 return 0;
04564
04565 if (REGNO_REG_CLASS (regno) == PR_REGS
04566 && ! rws_sum[regno].written_by_fp)
04567
04568
04569
04570 return 0;
04571 }
04572
04573 if (flags.is_and && rws_sum[regno].written_by_and)
04574 return 0;
04575 if (flags.is_or && rws_sum[regno].written_by_or)
04576 return 0;
04577
04578 switch (rws_sum[regno].write_count)
04579 {
04580 case 0:
04581
04582 break;
04583
04584 case 1:
04585
04586
04587
04588
04589 if ((rws_sum[regno].first_pred ^ 1) != pred)
04590 need_barrier = 1;
04591 break;
04592
04593 case 2:
04594
04595
04596 need_barrier = 1;
04597 break;
04598
04599 default:
04600 abort ();
04601 }
04602 }
04603
04604 return need_barrier;
04605 }
04606
04607 static int
04608 rws_access_reg (reg, flags, pred)
04609 rtx reg;
04610 struct reg_flags flags;
04611 int pred;
04612 {
04613 int regno = REGNO (reg);
04614 int n = HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg));
04615
04616 if (n == 1)
04617 return rws_access_regno (regno, flags, pred);
04618 else
04619 {
04620 int need_barrier = 0;
04621 while (--n >= 0)
04622 need_barrier |= rws_access_regno (regno + n, flags, pred);
04623 return need_barrier;
04624 }
04625 }
04626
04627
04628
04629
04630 static void
04631 update_set_flags (x, pflags, ppred, pcond)
04632 rtx x;
04633 struct reg_flags *pflags;
04634 int *ppred;
04635 rtx *pcond;
04636 {
04637 rtx src = SET_SRC (x);
04638
04639 *pcond = 0;
04640
04641 switch (GET_CODE (src))
04642 {
04643 case CALL:
04644 return;
04645
04646 case IF_THEN_ELSE:
04647 if (SET_DEST (x) == pc_rtx)
04648
04649 return;
04650 else
04651 {
04652 int is_complemented = 0;
04653
04654
04655 rtx cond = XEXP (src, 0);
04656 if (GET_CODE (cond) == EQ)
04657 is_complemented = 1;
04658 cond = XEXP (cond, 0);
04659 if (GET_CODE (cond) != REG
04660 && REGNO_REG_CLASS (REGNO (cond)) != PR_REGS)
04661 abort ();
04662 *pcond = cond;
04663 if (XEXP (src, 1) == SET_DEST (x)
04664 || XEXP (src, 2) == SET_DEST (x))
04665 {
04666
04667
04668
04669
04670 if (XEXP (src, 1) == SET_DEST (x))
04671 is_complemented = ! is_complemented;
04672
04673 *ppred = REGNO (cond);
04674 if (is_complemented)
04675 ++*ppred;
04676 }
04677
04678
04679
04680
04681
04682
04683
04684
04685 }
04686
04687
04688 default:
04689 if (GET_RTX_CLASS (GET_CODE (src)) == '<'
04690 && GET_MODE_CLASS (GET_MODE (XEXP (src, 0))) == MODE_FLOAT)
04691
04692
04693
04694 pflags->is_fp = 1;
04695
04696
04697
04698
04699 else if (GET_CODE (src) == AND)
04700 pflags->is_and = 1;
04701 else if (GET_CODE (src) == IOR)
04702 pflags->is_or = 1;
04703
04704 break;
04705 }
04706 }
04707
04708
04709
04710
04711
04712
04713 static int
04714 set_src_needs_barrier (x, flags, pred, cond)
04715 rtx x;
04716 struct reg_flags flags;
04717 int pred;
04718 rtx cond;
04719 {
04720 int need_barrier = 0;
04721 rtx dst;
04722 rtx src = SET_SRC (x);
04723
04724 if (GET_CODE (src) == CALL)
04725
04726
04727 return rtx_needs_barrier (src, flags, pred);
04728 else if (SET_DEST (x) == pc_rtx)
04729 {
04730
04731
04732
04733 flags.is_branch = 1;
04734 return rtx_needs_barrier (src, flags, pred);
04735 }
04736
04737 need_barrier = rtx_needs_barrier (src, flags, pred);
04738
04739
04740 if (cond)
04741 need_barrier |= rws_access_reg (cond, flags, 0);
04742
04743 dst = SET_DEST (x);
04744 if (GET_CODE (dst) == ZERO_EXTRACT)
04745 {
04746 need_barrier |= rtx_needs_barrier (XEXP (dst, 1), flags, pred);
04747 need_barrier |= rtx_needs_barrier (XEXP (dst, 2), flags, pred);
04748 dst = XEXP (dst, 0);
04749 }
04750 return need_barrier;
04751 }
04752
04753
04754
04755
04756
04757 static int
04758 rtx_needs_barrier (x, flags, pred)
04759 rtx x;
04760 struct reg_flags flags;
04761 int pred;
04762 {
04763 int i, j;
04764 int is_complemented = 0;
04765 int need_barrier = 0;
04766 const char *format_ptr;
04767 struct reg_flags new_flags;
04768 rtx cond = 0;
04769
04770 if (! x)
04771 return 0;
04772
04773 new_flags = flags;
04774
04775 switch (GET_CODE (x))
04776 {
04777 case SET:
04778 update_set_flags (x, &new_flags, &pred, &cond);
04779 need_barrier = set_src_needs_barrier (x, new_flags, pred, cond);
04780 if (GET_CODE (SET_SRC (x)) != CALL)
04781 {
04782 new_flags.is_write = 1;
04783 need_barrier |= rtx_needs_barrier (SET_DEST (x), new_flags, pred);
04784 }
04785 break;
04786
04787 case CALL:
04788 new_flags.is_write = 0;
04789 need_barrier |= rws_access_regno (AR_EC_REGNUM, new_flags, pred);
04790
04791
04792
04793 if (! flags.is_sibcall && ! rws_insn[REG_AR_CFM].write_count)
04794 {
04795 new_flags.is_write = 1;
04796 need_barrier |= rws_access_regno (REG_RP, new_flags, pred);
04797 need_barrier |= rws_access_regno (AR_PFS_REGNUM, new_flags, pred);
04798 need_barrier |= rws_access_regno (REG_AR_CFM, new_flags, pred);
04799 }
04800 break;
04801
04802 case COND_EXEC:
04803
04804
04805 cond = COND_EXEC_TEST (x);
04806 if (pred)
04807 abort ();
04808 need_barrier = rtx_needs_barrier (cond, flags, 0);
04809
04810 if (GET_CODE (cond) == EQ)
04811 is_complemented = 1;
04812 cond = XEXP (cond, 0);
04813 if (GET_CODE (cond) != REG
04814 && REGNO_REG_CLASS (REGNO (cond)) != PR_REGS)
04815 abort ();
04816 pred = REGNO (cond);
04817 if (is_complemented)
04818 ++pred;
04819
04820 need_barrier |= rtx_needs_barrier (COND_EXEC_CODE (x), flags, pred);
04821 return need_barrier;
04822
04823 case CLOBBER:
04824 case USE:
04825
04826 break;
04827
04828 case ASM_OPERANDS:
04829 case ASM_INPUT:
04830
04831
04832 if (GET_CODE (x) != ASM_OPERANDS
04833 || (MEM_VOLATILE_P (x) && TARGET_VOL_ASM_STOP))
04834 {
04835
04836
04837 if (! rws_insn[REG_VOLATILE].write_count)
04838 {
04839 new_flags.is_write = 1;
04840 rws_access_regno (REG_VOLATILE, new_flags, pred);
04841 }
04842 return 1;
04843 }
04844
04845
04846
04847
04848
04849
04850 for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; --i)
04851 if (rtx_needs_barrier (ASM_OPERANDS_INPUT (x, i), flags, pred))
04852 need_barrier = 1;
04853 break;
04854
04855 case PARALLEL:
04856 for (i = XVECLEN (x, 0) - 1; i >= 0; --i)
04857 {
04858 rtx pat = XVECEXP (x, 0, i);
04859 if (GET_CODE (pat) == SET)
04860 {
04861 update_set_flags (pat, &new_flags, &pred, &cond);
04862 need_barrier |= set_src_needs_barrier (pat, new_flags, pred, cond);
04863 }
04864 else if (GET_CODE (pat) == USE
04865 || GET_CODE (pat) == CALL
04866 || GET_CODE (pat) == ASM_OPERANDS)
04867 need_barrier |= rtx_needs_barrier (pat, flags, pred);
04868 else if (GET_CODE (pat) != CLOBBER && GET_CODE (pat) != RETURN)
04869 abort ();
04870 }
04871 for (i = XVECLEN (x, 0) - 1; i >= 0; --i)
04872 {
04873 rtx pat = XVECEXP (x, 0, i);
04874 if (GET_CODE (pat) == SET)
04875 {
04876 if (GET_CODE (SET_SRC (pat)) != CALL)
04877 {
04878 new_flags.is_write = 1;
04879 need_barrier |= rtx_needs_barrier (SET_DEST (pat), new_flags,
04880 pred);
04881 }
04882 }
04883 else if (GET_CODE (pat) == CLOBBER || GET_CODE (pat) == RETURN)
04884 need_barrier |= rtx_needs_barrier (pat, flags, pred);
04885 }
04886 break;
04887
04888 case SUBREG:
04889 x = SUBREG_REG (x);
04890
04891 case REG:
04892 if (REGNO (x) == AR_UNAT_REGNUM)
04893 {
04894 for (i = 0; i < 64; ++i)
04895 need_barrier |= rws_access_regno (AR_UNAT_BIT_0 + i, flags, pred);
04896 }
04897 else
04898 need_barrier = rws_access_reg (x, flags, pred);
04899 break;
04900
04901 case MEM:
04902
04903 new_flags.is_write = 0;
04904 need_barrier = rtx_needs_barrier (XEXP (x, 0), new_flags, pred);
04905 break;
04906
04907 case CONST_INT: case CONST_DOUBLE:
04908 case SYMBOL_REF: case LABEL_REF: case CONST:
04909 break;
04910
04911
04912 case POST_INC: case POST_DEC:
04913 if (GET_CODE (XEXP (x, 0)) != REG)
04914 abort ();
04915
04916 new_flags.is_write = 0;
04917 need_barrier = rws_access_reg (XEXP (x, 0), new_flags, pred);
04918 new_flags.is_write = 1;
04919 need_barrier |= rws_access_reg (XEXP (x, 0), new_flags, pred);
04920 break;
04921
04922 case POST_MODIFY:
04923 if (GET_CODE (XEXP (x, 0)) != REG)
04924 abort ();
04925
04926 new_flags.is_write = 0;
04927 need_barrier = rws_access_reg (XEXP (x, 0), new_flags, pred);
04928 need_barrier |= rtx_needs_barrier (XEXP (x, 1), new_flags, pred);
04929 new_flags.is_write = 1;
04930 need_barrier |= rws_access_reg (XEXP (x, 0), new_flags, pred);
04931 break;
04932
04933
04934 case COMPARE: case PLUS: case MINUS: case MULT: case DIV:
04935 case MOD: case UDIV: case UMOD: case AND: case IOR:
04936 case XOR: case ASHIFT: case ROTATE: case ASHIFTRT: case LSHIFTRT:
04937 case ROTATERT: case SMIN: case SMAX: case UMIN: case UMAX:
04938 case NE: case EQ: case GE: case GT: case LE:
04939 case LT: case GEU: case GTU: case LEU: case LTU:
04940 need_barrier = rtx_needs_barrier (XEXP (x, 0), new_flags, pred);
04941 need_barrier |= rtx_needs_barrier (XEXP (x, 1), new_flags, pred);
04942 break;
04943
04944 case NEG: case NOT: case SIGN_EXTEND: case ZERO_EXTEND:
04945 case TRUNCATE: case FLOAT_EXTEND: case FLOAT_TRUNCATE: case FLOAT:
04946 case FIX: case UNSIGNED_FLOAT: case UNSIGNED_FIX: case ABS:
04947 case SQRT: case FFS:
04948 need_barrier = rtx_needs_barrier (XEXP (x, 0), flags, pred);
04949 break;
04950
04951 case UNSPEC:
04952 switch (XINT (x, 1))
04953 {
04954 case UNSPEC_LTOFF_DTPMOD:
04955 case UNSPEC_LTOFF_DTPREL:
04956 case UNSPEC_DTPREL:
04957 case UNSPEC_LTOFF_TPREL:
04958 case UNSPEC_TPREL:
04959 case UNSPEC_PRED_REL_MUTEX:
04960 case UNSPEC_PIC_CALL:
04961 case UNSPEC_MF:
04962 case UNSPEC_FETCHADD_ACQ:
04963 case UNSPEC_BSP_VALUE:
04964 case UNSPEC_FLUSHRS:
04965 case UNSPEC_BUNDLE_SELECTOR:
04966 break;
04967
04968 case UNSPEC_GR_SPILL:
04969 case UNSPEC_GR_RESTORE:
04970 {
04971 HOST_WIDE_INT offset = INTVAL (XVECEXP (x, 0, 1));
04972 HOST_WIDE_INT bit = (offset >> 3) & 63;
04973
04974 need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
04975 new_flags.is_write = (XINT (x, 1) == 1);
04976 need_barrier |= rws_access_regno (AR_UNAT_BIT_0 + bit,
04977 new_flags, pred);
04978 break;
04979 }
04980
04981 case UNSPEC_FR_SPILL:
04982 case UNSPEC_FR_RESTORE:
04983 case UNSPEC_POPCNT:
04984 need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
04985 break;
04986
04987 case UNSPEC_ADDP4:
04988 need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
04989 break;
04990
04991 case UNSPEC_FR_RECIP_APPROX:
04992 need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
04993 need_barrier |= rtx_needs_barrier (XVECEXP (x, 0, 1), flags, pred);
04994 break;
04995
04996 case UNSPEC_CMPXCHG_ACQ:
04997 need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 1), flags, pred);
04998 need_barrier |= rtx_needs_barrier (XVECEXP (x, 0, 2), flags, pred);
04999 break;
05000
05001 default:
05002 abort ();
05003 }
05004 break;
05005
05006 case UNSPEC_VOLATILE:
05007 switch (XINT (x, 1))
05008 {
05009 case UNSPECV_ALLOC:
05010
05011
05012
05013
05014
05015
05016
05017 rws_access_regno (AR_PFS_REGNUM, flags, pred);
05018
05019 new_flags.is_write = 1;
05020 rws_access_regno (REG_AR_CFM, new_flags, pred);
05021 return 1;
05022
05023 case UNSPECV_SET_BSP:
05024 need_barrier = 1;
05025 break;
05026
05027 case UNSPECV_BLOCKAGE:
05028 case UNSPECV_INSN_GROUP_BARRIER:
05029 case UNSPECV_BREAK:
05030 case UNSPECV_PSAC_ALL:
05031 case UNSPECV_PSAC_NORMAL:
05032 return 0;
05033
05034 default:
05035 abort ();
05036 }
05037 break;
05038
05039 case RETURN:
05040 new_flags.is_write = 0;
05041 need_barrier = rws_access_regno (REG_RP, flags, pred);
05042 need_barrier |= rws_access_regno (AR_PFS_REGNUM, flags, pred);
05043
05044 new_flags.is_write = 1;
05045 need_barrier |= rws_access_regno (AR_EC_REGNUM, new_flags, pred);
05046 need_barrier |= rws_access_regno (REG_AR_CFM, new_flags, pred);
05047 break;
05048
05049 default:
05050 format_ptr = GET_RTX_FORMAT (GET_CODE (x));
05051 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
05052 switch (format_ptr[i])
05053 {
05054 case '0':
05055 case 'i':
05056 case 'n':
05057 case 'w':
05058 case 's':
05059 case 'S':
05060 break;
05061
05062 case 'e':
05063 if (rtx_needs_barrier (XEXP (x, i), flags, pred))
05064 need_barrier = 1;
05065 break;
05066
05067 case 'E':
05068 for (j = XVECLEN (x, i) - 1; j >= 0; --j)
05069 if (rtx_needs_barrier (XVECEXP (x, i, j), flags, pred))
05070 need_barrier = 1;
05071 break;
05072
05073 default:
05074 abort ();
05075 }
05076 break;
05077 }
05078 return need_barrier;
05079 }
05080
05081
05082
05083
05084 static void
05085 init_insn_group_barriers ()
05086 {
05087 memset (rws_sum, 0, sizeof (rws_sum));
05088 first_instruction = 1;
05089 }
05090
05091
05092
05093
05094
05095 static int
05096 group_barrier_needed_p (insn)
05097 rtx insn;
05098 {
05099 rtx pat;
05100 int need_barrier = 0;
05101 struct reg_flags flags;
05102
05103 memset (&flags, 0, sizeof (flags));
05104 switch (GET_CODE (insn))
05105 {
05106 case NOTE:
05107 break;
05108
05109 case BARRIER:
05110
05111 break;
05112
05113 case CODE_LABEL:
05114 memset (rws_insn, 0, sizeof (rws_insn));
05115 return 1;
05116
05117 case CALL_INSN:
05118 flags.is_branch = 1;
05119 flags.is_sibcall = SIBLING_CALL_P (insn);
05120 memset (rws_insn, 0, sizeof (rws_insn));
05121
05122
05123 if ((pat = prev_active_insn (insn))
05124 && GET_CODE (pat) == CALL_INSN)
05125 {
05126 need_barrier = 1;
05127 break;
05128 }
05129
05130 need_barrier = rtx_needs_barrier (PATTERN (insn), flags, 0);
05131 break;
05132
05133 case JUMP_INSN:
05134 flags.is_branch = 1;
05135
05136
05137 if ((pat = prev_active_insn (insn))
05138 && GET_CODE (pat) == CALL_INSN)
05139 {
05140 need_barrier = 1;
05141 break;
05142 }
05143
05144
05145 case INSN:
05146 if (GET_CODE (PATTERN (insn)) == USE
05147 || GET_CODE (PATTERN (insn)) == CLOBBER)
05148
05149
05150
05151 break;
05152
05153 pat = PATTERN (insn);
05154
05155
05156 switch (recog_memoized (insn))
05157 {
05158
05159
05160 case CODE_FOR_epilogue_deallocate_stack:
05161 case CODE_FOR_prologue_allocate_stack:
05162 pat = XVECEXP (pat, 0, 0);
05163 break;
05164
05165
05166
05167 case CODE_FOR_doloop_end_internal:
05168 pat = XVECEXP (pat, 0, 1);
05169 break;
05170
05171
05172 case CODE_FOR_pred_rel_mutex:
05173 case CODE_FOR_prologue_use:
05174 return 0;
05175
05176 default:
05177 break;
05178 }
05179
05180 memset (rws_insn, 0, sizeof (rws_insn));
05181 need_barrier = rtx_needs_barrier (pat, flags, 0);
05182
05183
05184
05185 if (! need_barrier)
05186 need_barrier = rws_access_regno (REG_VOLATILE, flags, 0);
05187 break;
05188
05189 default:
05190 abort ();
05191 }
05192
05193 if (first_instruction)
05194 {
05195 need_barrier = 0;
05196 first_instruction = 0;
05197 }
05198
05199 return need_barrier;
05200 }
05201
05202
05203
05204 static int
05205 safe_group_barrier_needed_p (insn)
05206 rtx insn;
05207 {
05208 struct reg_write_state rws_saved[NUM_REGS];
05209 int saved_first_instruction;
05210 int t;
05211
05212 memcpy (rws_saved, rws_sum, NUM_REGS * sizeof *rws_saved);
05213 saved_first_instruction = first_instruction;
05214
05215 t = group_barrier_needed_p (insn);
05216
05217 memcpy (rws_sum, rws_saved, NUM_REGS * sizeof *rws_saved);
05218 first_instruction = saved_first_instruction;
05219
05220 return t;
05221 }
05222
05223
05224
05225
05226
05227
05228
05229
05230 static void
05231 emit_insn_group_barriers (dump, insns)
05232 FILE *dump;
05233 rtx insns;
05234 {
05235 rtx insn;
05236 rtx last_label = 0;
05237 int insns_since_last_label = 0;
05238
05239 init_insn_group_barriers ();
05240
05241 for (insn = insns; insn; insn = NEXT_INSN (insn))
05242 {
05243 if (GET_CODE (insn) == CODE_LABEL)
05244 {
05245 if (insns_since_last_label)
05246 last_label = insn;
05247 insns_since_last_label = 0;
05248 }
05249 else if (GET_CODE (insn) == NOTE
05250 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
05251 {
05252 if (insns_since_last_label)
05253 last_label = insn;
05254 insns_since_last_label = 0;
05255 }
05256 else if (GET_CODE (insn) == INSN
05257 && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
05258 && XINT (PATTERN (insn), 1) == UNSPECV_INSN_GROUP_BARRIER)
05259 {
05260 init_insn_group_barriers ();
05261 last_label = 0;
05262 }
05263 else if (INSN_P (insn))
05264 {
05265 insns_since_last_label = 1;
05266
05267 if (group_barrier_needed_p (insn))
05268 {
05269 if (last_label)
05270 {
05271 if (dump)
05272 fprintf (dump, "Emitting stop before label %d\n",
05273 INSN_UID (last_label));
05274 emit_insn_before (gen_insn_group_barrier (GEN_INT (3)), last_label);
05275 insn = last_label;
05276
05277 init_insn_group_barriers ();
05278 last_label = 0;
05279 }
05280 }
05281 }
05282 }
05283 }
05284
05285
05286
05287
05288 static void
05289 emit_all_insn_group_barriers (dump, insns)
05290 FILE *dump ATTRIBUTE_UNUSED;
05291 rtx insns;
05292 {
05293 rtx insn;
05294
05295 init_insn_group_barriers ();
05296
05297 for (insn = insns; insn; insn = NEXT_INSN (insn))
05298 {
05299 if (GET_CODE (insn) == BARRIER)
05300 {
05301 rtx last = prev_active_insn (insn);
05302
05303 if (! last)
05304 continue;
05305 if (GET_CODE (last) == JUMP_INSN
05306 && GET_CODE (PATTERN (last)) == ADDR_DIFF_VEC)
05307 last = prev_active_insn (last);
05308 if (recog_memoized (last) != CODE_FOR_insn_group_barrier)
05309 emit_insn_after (gen_insn_group_barrier (GEN_INT (3)), last);
05310
05311 init_insn_group_barriers ();
05312 }
05313 else if (INSN_P (insn))
05314 {
05315 if (recog_memoized (insn) == CODE_FOR_insn_group_barrier)
05316 init_insn_group_barriers ();
05317 else if (group_barrier_needed_p (insn))
05318 {
05319 emit_insn_before (gen_insn_group_barrier (GEN_INT (3)), insn);
05320 init_insn_group_barriers ();
05321 group_barrier_needed_p (insn);
05322 }
05323 }
05324 }
05325 }
05326
05327 static int errata_find_address_regs PARAMS ((rtx *, void *));
05328 static void errata_emit_nops PARAMS ((rtx));
05329 static void fixup_errata PARAMS ((void));
05330
05331
05332
05333
05334 static struct group
05335 {
05336 HARD_REG_SET p_reg_set;
05337 HARD_REG_SET gr_reg_conditionally_set;
05338 } last_group[2];
05339
05340
05341 static int group_idx;
05342
05343
05344
05345
05346 static int
05347 errata_find_address_regs (xp, data)
05348 rtx *xp;
05349 void *data ATTRIBUTE_UNUSED;
05350 {
05351 rtx x = *xp;
05352 if (GET_CODE (x) != MEM)
05353 return 0;
05354 x = XEXP (x, 0);
05355 if (GET_CODE (x) == POST_MODIFY)
05356 x = XEXP (x, 0);
05357 if (GET_CODE (x) == REG)
05358 {
05359 struct group *prev_group = last_group + (group_idx ^ 1);
05360 if (TEST_HARD_REG_BIT (prev_group->gr_reg_conditionally_set,
05361 REGNO (x)))
05362 return 1;
05363 return -1;
05364 }
05365 return 0;
05366 }
05367
05368
05369
05370
05371 static void
05372 errata_emit_nops (insn)
05373 rtx insn;
05374 {
05375 struct group *this_group = last_group + group_idx;
05376 struct group *prev_group = last_group + (group_idx ^ 1);
05377 rtx pat = PATTERN (insn);
05378 rtx cond = GET_CODE (pat) == COND_EXEC ? COND_EXEC_TEST (pat) : 0;
05379 rtx real_pat = cond ? COND_EXEC_CODE (pat) : pat;
05380 enum attr_type type;
05381 rtx set = real_pat;
05382
05383 if (GET_CODE (real_pat) == USE
05384 || GET_CODE (real_pat) == CLOBBER
05385 || GET_CODE (real_pat) == ASM_INPUT
05386 || GET_CODE (real_pat) == ADDR_VEC
05387 || GET_CODE (real_pat) == ADDR_DIFF_VEC
05388 || asm_noperands (PATTERN (insn)) >= 0)
05389 return;
05390
05391
05392
05393
05394 if (GET_CODE (set) == PARALLEL)
05395 {
05396 int i;
05397 set = XVECEXP (real_pat, 0, 0);
05398 for (i = 1; i < XVECLEN (real_pat, 0); i++)
05399 if (GET_CODE (XVECEXP (real_pat, 0, i)) != USE
05400 && GET_CODE (XVECEXP (real_pat, 0, i)) != CLOBBER)
05401 {
05402 set = 0;
05403 break;
05404 }
05405 }
05406
05407 if (set && GET_CODE (set) != SET)
05408 set = 0;
05409
05410 type = get_attr_type (insn);
05411
05412 if (type == TYPE_F
05413 && set && REG_P (SET_DEST (set)) && PR_REGNO_P (REGNO (SET_DEST (set))))
05414 SET_HARD_REG_BIT (this_group->p_reg_set, REGNO (SET_DEST (set)));
05415
05416 if ((type == TYPE_M || type == TYPE_A) && cond && set
05417 && REG_P (SET_DEST (set))
05418 && GET_CODE (SET_SRC (set)) != PLUS
05419 && GET_CODE (SET_SRC (set)) != MINUS
05420 && (GET_CODE (SET_SRC (set)) != ASHIFT
05421 || !shladd_operand (XEXP (SET_SRC (set), 1), VOIDmode))
05422 && (GET_CODE (SET_SRC (set)) != MEM
05423 || GET_CODE (XEXP (SET_SRC (set), 0)) != POST_MODIFY)
05424 && GENERAL_REGNO_P (REGNO (SET_DEST (set))))
05425 {
05426 if (GET_RTX_CLASS (GET_CODE (cond)) != '<'
05427 || ! REG_P (XEXP (cond, 0)))
05428 abort ();
05429
05430 if (TEST_HARD_REG_BIT (prev_group->p_reg_set, REGNO (XEXP (cond, 0))))
05431 SET_HARD_REG_BIT (this_group->gr_reg_conditionally_set, REGNO (SET_DEST (set)));
05432 }
05433 if (for_each_rtx (&real_pat, errata_find_address_regs, NULL))
05434 {
05435 emit_insn_before (gen_insn_group_barrier (GEN_INT (3)), insn);
05436 emit_insn_before (gen_nop (), insn);
05437 emit_insn_before (gen_insn_group_barrier (GEN_INT (3)), insn);
05438 group_idx = 0;
05439 memset (last_group, 0, sizeof last_group);
05440 }
05441 }
05442
05443
05444
05445 static void
05446 fixup_errata ()
05447 {
05448 rtx insn;
05449
05450 if (! TARGET_B_STEP)
05451 return;
05452
05453 group_idx = 0;
05454 memset (last_group, 0, sizeof last_group);
05455
05456 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
05457 {
05458 if (!INSN_P (insn))
05459 continue;
05460
05461 if (ia64_safe_type (insn) == TYPE_S)
05462 {
05463 group_idx ^= 1;
05464 memset (last_group + group_idx, 0, sizeof last_group[group_idx]);
05465 }
05466 else
05467 errata_emit_nops (insn);
05468 }
05469 }
05470
05471
05472
05473
05474 struct bundle
05475 {
05476
05477
05478 int possible_stop;
05479
05480 enum attr_type t[3];
05481
05482 const char *name;
05483 };
05484
05485 #define NR_BUNDLES 10
05486
05487
05488
05489 static const struct bundle bundle[NR_BUNDLES] =
05490 {
05491 { 2, { TYPE_M, TYPE_I, TYPE_I }, ".mii" },
05492 { 1, { TYPE_M, TYPE_M, TYPE_I }, ".mmi" },
05493 { 0, { TYPE_M, TYPE_F, TYPE_I }, ".mfi" },
05494 { 0, { TYPE_M, TYPE_M, TYPE_F }, ".mmf" },
05495 #if NR_BUNDLES == 10
05496 { 0, { TYPE_B, TYPE_B, TYPE_B }, ".bbb" },
05497 { 0, { TYPE_M, TYPE_B, TYPE_B }, ".mbb" },
05498 #endif
05499 { 0, { TYPE_M, TYPE_I, TYPE_B }, ".mib" },
05500 { 0, { TYPE_M, TYPE_M, TYPE_B }, ".mmb" },
05501 { 0, { TYPE_M, TYPE_F, TYPE_B }, ".mfb" },
05502
05503
05504
05505 { 0, { TYPE_M, TYPE_L, TYPE_X }, ".mlx" }
05506 };
05507
05508
05509
05510
05511 struct ia64_packet
05512 {
05513 const struct bundle *t1, *t2;
05514
05515
05516 int first_split;
05517
05518
05519 enum attr_type t[6];
05520 };
05521
05522
05523 #define NR_PACKETS (NR_BUNDLES * NR_BUNDLES)
05524 static struct ia64_packet packets[NR_PACKETS];
05525
05526
05527
05528 static const char *const type_names[] =
05529 {
05530 "UNKNOWN", "A", "I", "M", "F", "B", "L", "X", "S"
05531 };
05532
05533
05534 int ia64_final_schedule = 0;
05535
05536 static int itanium_split_issue PARAMS ((const struct ia64_packet *, int));
05537 static rtx ia64_single_set PARAMS ((rtx));
05538 static int insn_matches_slot PARAMS ((const struct ia64_packet *, enum attr_type, int, rtx));
05539 static void ia64_emit_insn_before PARAMS ((rtx, rtx));
05540 static void maybe_rotate PARAMS ((FILE *));
05541 static void finish_last_head PARAMS ((FILE *, int));
05542 static void rotate_one_bundle PARAMS ((FILE *));
05543 static void rotate_two_bundles PARAMS ((FILE *));
05544 static void nop_cycles_until PARAMS ((int, FILE *));
05545 static void cycle_end_fill_slots PARAMS ((FILE *));
05546 static int packet_matches_p PARAMS ((const struct ia64_packet *, int, int *));
05547 static int get_split PARAMS ((const struct ia64_packet *, int));
05548 static int find_best_insn PARAMS ((rtx *, enum attr_type *, int,
05549 const struct ia64_packet *, int));
05550 static void find_best_packet PARAMS ((int *, const struct ia64_packet **,
05551 rtx *, enum attr_type *, int));
05552 static int itanium_reorder PARAMS ((FILE *, rtx *, rtx *, int));
05553 static void dump_current_packet PARAMS ((FILE *));
05554 static void schedule_stop PARAMS ((FILE *));
05555 static rtx gen_nop_type PARAMS ((enum attr_type));
05556 static void ia64_emit_nops PARAMS ((void));
05557
05558
05559
05560 const char *
05561 get_bundle_name (b)
05562 int b;
05563 {
05564 return bundle[b].name;
05565 }
05566
05567
05568
05569
05570 static int
05571 itanium_split_issue (p, begin)
05572 const struct ia64_packet *p;
05573 int begin;
05574 {
05575 int type_count[TYPE_S];
05576 int i;
05577 int split = 6;
05578
05579 if (begin < 3)
05580 {
05581
05582 if (p->t[0] == TYPE_M && p->t[1] == TYPE_M && p->t[2] == TYPE_F)
05583 return 3;
05584 if (p->t[3] == TYPE_M && p->t[4] == TYPE_M && p->t[5] == TYPE_F)
05585 return 3;
05586
05587 if (p->t[1] == TYPE_B)
05588 return 3;
05589
05590 if (p->t[2] == TYPE_B && p->t[3] == TYPE_B)
05591 return 3;
05592 }
05593
05594 memset (type_count, 0, sizeof type_count);
05595 for (i = begin; i < split; i++)
05596 {
05597 enum attr_type t0 = p->t[i];
05598
05599 enum attr_type t = (t0 == TYPE_L ? TYPE_F
05600 : t0 == TYPE_X ? TYPE_I
05601 : t0);
05602
05603
05604
05605 int max = (t == TYPE_B ? 3 : 2);
05606 if (type_count[t] == max)
05607 return i;
05608
05609 type_count[t]++;
05610 }
05611 return split;
05612 }
05613
05614
05615
05616 static int
05617 ia64_issue_rate ()
05618 {
05619 return 6;
05620 }
05621
05622
05623
05624 static rtx
05625 ia64_single_set (insn)
05626 rtx insn;
05627 {
05628 rtx x = PATTERN (insn), ret;
05629 if (GET_CODE (x) == COND_EXEC)
05630 x = COND_EXEC_CODE (x);
05631 if (GET_CODE (x) == SET)
05632 return x;
05633
05634
05635
05636
05637 switch (recog_memoized (insn))
05638 {
05639 case CODE_FOR_prologue_allocate_stack:
05640 case CODE_FOR_epilogue_deallocate_stack:
05641 ret = XVECEXP (x, 0, 0);
05642 break;
05643
05644 default:
05645 ret = single_set_2 (insn, x);
05646 break;
05647 }
05648
05649 return ret;
05650 }
05651
05652
05653
05654
05655 static int
05656 ia64_adjust_cost (insn, link, dep_insn, cost)
05657 rtx insn, link, dep_insn;
05658 int cost;
05659 {
05660 enum attr_type dep_type;
05661 enum attr_itanium_class dep_class;
05662 enum attr_itanium_class insn_class;
05663 rtx dep_set, set, src, addr;
05664
05665 if (GET_CODE (PATTERN (insn)) == CLOBBER
05666 || GET_CODE (PATTERN (insn)) == USE
05667 || GET_CODE (PATTERN (dep_insn)) == CLOBBER
05668 || GET_CODE (PATTERN (dep_insn)) == USE
05669
05670 || GET_CODE (insn) == CALL_INSN
05671 || ia64_safe_type (insn) == TYPE_S)
05672 return 0;
05673
05674 if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT
05675 || REG_NOTE_KIND (link) == REG_DEP_ANTI)
05676 return 0;
05677
05678 dep_type = ia64_safe_type (dep_insn);
05679 dep_class = ia64_safe_itanium_class (dep_insn);
05680 insn_class = ia64_safe_itanium_class (insn);
05681
05682
05683
05684 dep_set = ia64_single_set (dep_insn);
05685 set = ia64_single_set (insn);
05686
05687 if (dep_type != TYPE_F
05688 && dep_set
05689 && GET_CODE (SET_DEST (dep_set)) == REG
05690 && PR_REG (REGNO (SET_DEST (dep_set)))
05691 && GET_CODE (insn) == JUMP_INSN)
05692 return 0;
05693
05694 if (dep_set && GET_CODE (SET_DEST (dep_set)) == MEM)
05695 {
05696
05697
05698
05699
05700
05701 return 0;
05702 }
05703
05704 src = set ? SET_SRC (set) : 0;
05705 addr = 0;
05706 if (set)
05707 {
05708 if (GET_CODE (SET_DEST (set)) == MEM)
05709 addr = XEXP (SET_DEST (set), 0);
05710 else if (GET_CODE (SET_DEST (set)) == SUBREG
05711 && GET_CODE (SUBREG_REG (SET_DEST (set))) == MEM)
05712 addr = XEXP (SUBREG_REG (SET_DEST (set)), 0);
05713 else
05714 {
05715 addr = src;
05716 if (GET_CODE (addr) == UNSPEC && XVECLEN (addr, 0) > 0)
05717 addr = XVECEXP (addr, 0, 0);
05718 while (GET_CODE (addr) == SUBREG || GET_CODE (addr) == ZERO_EXTEND)
05719 addr = XEXP (addr, 0);
05720
05721
05722 if (GET_CODE (addr) == MEM || GET_CODE (addr) == LO_SUM)
05723 addr = XEXP (addr, 0);
05724 else
05725 addr = 0;
05726 }
05727 }
05728
05729 if (addr && GET_CODE (addr) == POST_MODIFY)
05730 addr = XEXP (addr, 0);
05731
05732 set = ia64_single_set (dep_insn);
05733
05734 if ((dep_class == ITANIUM_CLASS_IALU
05735 || dep_class == ITANIUM_CLASS_ILOG
05736 || dep_class == ITANIUM_CLASS_LD)
05737 && (insn_class == ITANIUM_CLASS_LD
05738 || insn_class == ITANIUM_CLASS_ST))
05739 {
05740 if (! addr || ! set)
05741 abort ();
05742
05743
05744
05745 if (reg_overlap_mentioned_p (SET_DEST (set), addr))
05746 return cost + 1;
05747 }
05748
05749 if ((dep_class == ITANIUM_CLASS_IALU
05750 || dep_class == ITANIUM_CLASS_ILOG
05751 || dep_class == ITANIUM_CLASS_LD)
05752 && (insn_class == ITANIUM_CLASS_MMMUL
05753 || insn_class == ITANIUM_CLASS_MMSHF
05754 || insn_class == ITANIUM_CLASS_MMSHFI))
05755 return 3;
05756
05757 if (dep_class == ITANIUM_CLASS_FMAC
05758 && (insn_class == ITANIUM_CLASS_FMISC
05759 || insn_class == ITANIUM_CLASS_FCVTFX
05760 || insn_class == ITANIUM_CLASS_XMPY))
05761 return 7;
05762
05763 if ((dep_class == ITANIUM_CLASS_FMAC
05764 || dep_class == ITANIUM_CLASS_FMISC
05765 || dep_class == ITANIUM_CLASS_FCVTFX
05766 || dep_class == ITANIUM_CLASS_XMPY)
05767 && insn_class == ITANIUM_CLASS_STF)
05768 return 8;
05769
05770
05771
05772 if ((dep_class == ITANIUM_CLASS_MMMUL
05773 || dep_class == ITANIUM_CLASS_MMSHF
05774 || dep_class == ITANIUM_CLASS_MMSHFI)
05775 && insn_class != ITANIUM_CLASS_MMMUL
05776 && insn_class != ITANIUM_CLASS_MMSHF
05777 && insn_class != ITANIUM_CLASS_MMSHFI)
05778 return 4;
05779
05780 return cost;
05781 }
05782
05783
05784 static struct
05785 {
05786
05787 int first_slot;
05788
05789 int cur;
05790
05791 const struct ia64_packet *packet;
05792
05793
05794 int split;
05795
05796
05797
05798
05799 enum attr_type types[6];
05800 rtx insns[6];
05801 int stopbit[6];
05802
05803 int last_was_stop;
05804 } sched_data;
05805
05806
05807
05808
05809 static rtx *sched_ready;
05810 static enum attr_type *sched_types;
05811
05812
05813
05814
05815 static int
05816 insn_matches_slot (p, itype, slot, insn)
05817 const struct ia64_packet *p;
05818 enum attr_type itype;
05819 int slot;
05820 rtx insn;
05821 {
05822 enum attr_itanium_requires_unit0 u0;
05823 enum attr_type stype = p->t[slot];
05824
05825 if (insn)
05826 {
05827 u0 = ia64_safe_itanium_requires_unit0 (insn);
05828 if (u0 == ITANIUM_REQUIRES_UNIT0_YES)
05829 {
05830 int i;
05831 for (i = sched_data.first_slot; i < slot; i++)
05832 if (p->t[i] == stype
05833 || (stype == TYPE_F && p->t[i] == TYPE_L)
05834 || (stype == TYPE_I && p->t[i] == TYPE_X))
05835 return 0;
05836 }
05837 if (GET_CODE (insn) == CALL_INSN)
05838 {
05839
05840
05841
05842
05843
05844 if (slot < 3)
05845 {
05846 if (p->t[1] == TYPE_B)
05847 return 0;
05848 }
05849 else
05850 {
05851 if (p->t[4] == TYPE_B)
05852 return 0;
05853 }
05854 }
05855 }
05856
05857 if (itype == stype)
05858 return 1;
05859 if (itype == TYPE_A)
05860 return stype == TYPE_M || stype == TYPE_I;
05861 return 0;
05862 }
05863
05864
05865
05866
05867 static void
05868 ia64_emit_insn_before (insn, before)
05869 rtx insn, before;
05870 {
05871 emit_insn_before (insn, before);
05872 }
05873
05874
05875
05876
05877
05878
05879
05880
05881
05882 static void
05883 finish_last_head (dump, start)
05884 FILE *dump;
05885 int start;
05886 {
05887 const struct ia64_packet *p = sched_data.packet;
05888 const struct bundle *b = start == 0 ? p->t1 : p->t2;
05889 int bundle_type = b - bundle;
05890 rtx insn;
05891 int i;
05892
05893 if (! ia64_final_schedule)
05894 return;
05895
05896 for (i = start; sched_data.insns[i] == 0; i++)
05897 if (i == start + 3)
05898 abort ();
05899 insn = sched_data.insns[i];
05900
05901 if (dump)
05902 fprintf (dump, "// Emitting template before %d: %s\n",
05903 INSN_UID (insn), b->name);
05904
05905 ia64_emit_insn_before (gen_bundle_selector (GEN_INT (bundle_type)), insn);
05906 }
05907
05908
05909
05910
05911
05912
05913
05914
05915
05916 static void
05917 cycle_end_fill_slots (dump)
05918 FILE *dump;
05919 {
05920 const struct ia64_packet *packet = sched_data.packet;
05921 int slot, i;
05922 enum attr_type tmp_types[6];
05923 rtx tmp_insns[6];
05924
05925 memcpy (tmp_types, sched_data.types, 6 * sizeof (enum attr_type));
05926 memcpy (tmp_insns, sched_data.insns, 6 * sizeof (rtx));
05927
05928 for (i = slot = sched_data.first_slot; i < sched_data.cur; i++)
05929 {
05930 enum attr_type t = tmp_types[i];
05931 if (t != ia64_safe_type (tmp_insns[i]))
05932 abort ();
05933 while (! insn_matches_slot (packet, t, slot, tmp_insns[i]))
05934 {
05935 if (slot > sched_data.split)
05936 abort ();
05937 if (dump)
05938 fprintf (dump, "// Packet needs %s, have %s\n",
05939 type_names[packet->t[slot]], type_names[t]);
05940 sched_data.types[slot] = packet->t[slot];
05941 sched_data.insns[slot] = 0;
05942 sched_data.stopbit[slot] = 0;
05943
05944
05945
05946 if (packet->t[slot] == TYPE_L)
05947 abort ();
05948
05949 slot++;
05950 }
05951
05952
05953
05954 sched_data.types[slot] = packet->t[slot];
05955 sched_data.insns[slot] = tmp_insns[i];
05956 sched_data.stopbit[slot] = 0;
05957 slot++;
05958
05959
05960 if (t == TYPE_L)
05961 {
05962 sched_data.types[slot] = packet->t[slot];
05963 sched_data.insns[slot] = 0;
05964 sched_data.stopbit[slot] = 0;
05965 slot++;
05966 }
05967 }
05968
05969
05970
05971 #if 0
05972 while (slot < sched_data.split)
05973 {
05974 sched_data.types[slot] = packet->t[slot];
05975 sched_data.insns[slot] = 0;
05976 sched_data.stopbit[slot] = 0;
05977 slot++;
05978 }
05979 #endif
05980
05981 sched_data.first_slot = sched_data.cur = slot;
05982 }
05983
05984
05985
05986
05987
05988 static void
05989 rotate_one_bundle (dump)
05990 FILE *dump;
05991 {
05992 if (dump)
05993 fprintf (dump, "// Rotating one bundle.\n");
05994
05995 finish_last_head (dump, 0);
05996 if (sched_data.cur > 3)
05997 {
05998 sched_data.cur -= 3;
05999 sched_data.first_slot -= 3;
06000 memmove (sched_data.types,
06001 sched_data.types + 3,
06002 sched_data.cur * sizeof *sched_data.types);
06003 memmove (sched_data.stopbit,
06004 sched_data.stopbit + 3,
06005 sched_data.cur * sizeof *sched_data.stopbit);
06006 memmove (sched_data.insns,
06007 sched_data.insns + 3,
06008 sched_data.cur * sizeof *sched_data.insns);
06009 sched_data.packet
06010 = &packets[(sched_data.packet->t2 - bundle) * NR_BUNDLES];
06011 }
06012 else
06013 {
06014 sched_data.cur = 0;
06015 sched_data.first_slot = 0;
06016 }
06017 }
06018
06019 static void
06020 rotate_two_bundles (dump)
06021 FILE *dump;
06022 {
06023 if (dump)
06024 fprintf (dump, "// Rotating two bundles.\n");
06025
06026 if (sched_data.cur == 0)
06027 return;
06028
06029 finish_last_head (dump, 0);
06030 if (sched_data.cur > 3)
06031 finish_last_head (dump, 3);
06032 sched_data.cur = 0;
06033 sched_data.first_slot = 0;
06034 }
06035
06036
06037
06038 static void
06039 ia64_sched_init (dump, sched_verbose, max_ready)
06040 FILE *dump ATTRIBUTE_UNUSED;
06041 int sched_verbose ATTRIBUTE_UNUSED;
06042 int max_ready;
06043 {
06044 static int initialized = 0;
06045
06046 if (! initialized)
06047 {
06048 int b1, b2, i;
06049
06050 initialized = 1;
06051
06052 for (i = b1 = 0; b1 < NR_BUNDLES; b1++)
06053 {
06054 const struct bundle *t1 = bundle + b1;
06055 for (b2 = 0; b2 < NR_BUNDLES; b2++, i++)
06056 {
06057 const struct bundle *t2 = bundle + b2;
06058
06059 packets[i].t1 = t1;
06060 packets[i].t2 = t2;
06061 }
06062 }
06063 for (i = 0; i < NR_PACKETS; i++)
06064 {
06065 int j;
06066 for (j = 0; j < 3; j++)
06067 packets[i].t[j] = packets[i].t1->t[j];
06068 for (j = 0; j < 3; j++)
06069 packets[i].t[j + 3] = packets[i].t2->t[j];
06070 packets[i].first_split = itanium_split_issue (packets + i, 0);
06071 }
06072
06073 }
06074
06075 init_insn_group_barriers ();
06076
06077 memset (&sched_data, 0, sizeof sched_data);
06078 sched_types = (enum attr_type *) xmalloc (max_ready
06079 * sizeof (enum attr_type));
06080 sched_ready = (rtx *) xmalloc (max_ready * sizeof (rtx));
06081 }
06082
06083
06084
06085
06086
06087
06088
06089 static int
06090 packet_matches_p (p, split, pslot)
06091 const struct ia64_packet *p;
06092 int split;
06093 int *pslot;
06094 {
06095 int filled = sched_data.cur;
06096 int first = sched_data.first_slot;
06097 int i, slot;
06098
06099
06100
06101 if (first > 0 && sched_data.stopbit[0] && p->t1->possible_stop != 1)
06102 return 0;
06103 if (first > 1 && sched_data.stopbit[1] && p->t1->possible_stop != 2)
06104 return 0;
06105
06106 for (i = 0; i < first; i++)
06107 if (! insn_matches_slot (p, sched_data.types[i], i,
06108 sched_data.insns[i]))
06109 return 0;
06110 for (i = slot = first; i < filled; i++)
06111 {
06112 while (slot < split)
06113 {
06114 if (insn_matches_slot (p, sched_data.types[i], slot,
06115 sched_data.insns[i]))
06116 break;
06117 slot++;
06118 }
06119 if (slot == split)
06120 return 0;
06121 slot++;
06122 }
06123
06124 if (pslot)
06125 *pslot = slot;
06126 return 1;
06127 }
06128
06129
06130
06131
06132
06133
06134 static int
06135 get_split (p, first)
06136 const struct ia64_packet *p;
06137 int first;
06138 {
06139 if (first == 0)
06140 return p->first_split;
06141 return itanium_split_issue (p, first);
06142 }
06143
06144
06145
06146
06147
06148 static int
06149 find_best_insn (ready, types, n_ready, p, slot)
06150 rtx *ready;
06151 enum attr_type *types;
06152 int n_ready;
06153 const struct ia64_packet *p;
06154 int slot;
06155 {
06156 int best = -1;
06157 int best_pri = 0;
06158 while (n_ready-- > 0)
06159 {
06160 rtx insn = ready[n_ready];
06161 if (! insn)
06162 continue;
06163 if (best >= 0 && INSN_PRIORITY (ready[n_ready]) < best_pri)
06164 break;
06165
06166
06167 if (best >= 0 && types[n_ready] == TYPE_A)
06168 continue;
06169 if (insn_matches_slot (p, types[n_ready], slot, insn))
06170 {
06171 best = n_ready;
06172 best_pri = INSN_PRIORITY (ready[best]);
06173
06174
06175
06176 if (types[n_ready] != TYPE_A
06177 && ia64_safe_itanium_requires_unit0 (ready[n_ready]))
06178 break;
06179 break;
06180 }
06181 }
06182 return best;
06183 }
06184
06185
06186
06187
06188
06189
06190
06191 static void
06192 find_best_packet (pbest, ppacket, ready, types, n_ready)
06193 int *pbest;
06194 const struct ia64_packet **ppacket;
06195 rtx *ready;
06196 enum attr_type *types;
06197 int n_ready;
06198 {
06199 int first = sched_data.first_slot;
06200 int best = 0;
06201 int lowest_end = 6;
06202 const struct ia64_packet *best_packet = NULL;
06203 int i;
06204
06205 for (i = 0; i < NR_PACKETS; i++)
06206 {
06207 const struct ia64_packet *p = packets + i;
06208 int slot;
06209 int split = get_split (p, first);
06210 int win = 0;
06211 int first_slot, last_slot;
06212 int b_nops = 0;
06213
06214 if (! packet_matches_p (p, split, &first_slot))
06215 continue;
06216
06217 memcpy (sched_ready, ready, n_ready * sizeof (rtx));
06218
06219 win = 0;
06220 last_slot = 6;
06221 for (slot = first_slot; slot < split; slot++)
06222 {
06223 int insn_nr;
06224
06225
06226
06227 if (first_slot == 0 && win == 0 && slot == 3)
06228 {
06229 win = -1;
06230 break;
06231 }
06232
06233 insn_nr = find_best_insn (sched_ready, types, n_ready, p, slot);
06234 if (insn_nr >= 0)
06235 {
06236 sched_ready[insn_nr] = 0;
06237 last_slot = slot;
06238 win++;
06239 }
06240 else if (p->t[slot] == TYPE_B)
06241 b_nops++;
06242 }
06243
06244
06245 if (last_slot < 3)
06246 {
06247 if (p->t[1] == TYPE_B && (b_nops || last_slot < 2))
06248 win = -1;
06249 }
06250 else
06251 {
06252 if (p->t[4] == TYPE_B && (b_nops || last_slot < 5))
06253 win = -1;
06254 }
06255
06256 if (win > best
06257 || (win == best && last_slot < lowest_end))
06258 {
06259 best = win;
06260 lowest_end = last_slot;
06261 best_packet = p;
06262 }
06263 }
06264 *pbest = best;
06265 *ppacket = best_packet;
06266 }
06267
06268
06269
06270
06271
06272
06273
06274
06275
06276 static int
06277 itanium_reorder (dump, ready, e_ready, may_fail)
06278 FILE *dump;
06279 rtx *ready;
06280 rtx *e_ready;
06281 int may_fail;
06282 {
06283 const struct ia64_packet *best_packet;
06284 int n_ready = e_ready - ready;
06285 int first = sched_data.first_slot;
06286 int i, best, best_split, filled;
06287
06288 for (i = 0; i < n_ready; i++)
06289 sched_types[i] = ia64_safe_type (ready[i]);
06290
06291 find_best_packet (&best, &best_packet, ready, sched_types, n_ready);
06292
06293 if (best == 0)
06294 {
06295 if (may_fail)
06296 return 0;
06297 abort ();
06298 }
06299
06300 if (dump)
06301 {
06302 fprintf (dump, "// Selected bundles: %s %s (%d insns)\n",
06303 best_packet->t1->name,
06304 best_packet->t2 ? best_packet->t2->name : NULL, best);
06305 }
06306
06307 best_split = itanium_split_issue (best_packet, first);
06308 packet_matches_p (best_packet, best_split, &filled);
06309
06310 for (i = filled; i < best_split; i++)
06311 {
06312 int insn_nr;
06313
06314 insn_nr = find_best_insn (ready, sched_types, n_ready, best_packet, i);
06315 if (insn_nr >= 0)
06316 {
06317 rtx insn = ready[insn_nr];
06318 memmove (ready + insn_nr, ready + insn_nr + 1,
06319 (n_ready - insn_nr - 1) * sizeof (rtx));
06320 memmove (sched_types + insn_nr, sched_types + insn_nr + 1,
06321 (n_ready - insn_nr - 1) * sizeof (enum attr_type));
06322 ready[--n_ready] = insn;
06323 }
06324 }
06325
06326 sched_data.packet = best_packet;
06327 sched_data.split = best_split;
06328 return 1;
06329 }
06330
06331
06332
06333 static void
06334 dump_current_packet (dump)
06335 FILE *dump;
06336 {
06337 int i;
06338 fprintf (dump, "// %d slots filled:", sched_data.cur);
06339 for (i = 0; i < sched_data.first_slot; i++)
06340 {
06341 rtx insn = sched_data.insns[i];
06342 fprintf (dump, " %s", type_names[sched_data.types[i]]);
06343 if (insn)
06344 fprintf (dump, "/%s", type_names[ia64_safe_type (insn)]);
06345 if (sched_data.stopbit[i])
06346 fprintf (dump, " ;;");
06347 }
06348 fprintf (dump, " :::");
06349 for (i = sched_data.first_slot; i < sched_data.cur; i++)
06350 {
06351 rtx insn = sched_data.insns[i];
06352 enum attr_type t = ia64_safe_type (insn);
06353 fprintf (dump, " (%d) %s", INSN_UID (insn), type_names[t]);
06354 }
06355 fprintf (dump, "\n");
06356 }
06357
06358
06359
06360
06361 static void
06362 schedule_stop (dump)
06363 FILE *dump;
06364 {
06365 const struct ia64_packet *best = sched_data.packet;
06366 int i;
06367 int best_stop = 6;
06368
06369 if (dump)
06370 fprintf (dump, "// Stop bit, cur = %d.\n", sched_data.cur);
06371
06372 if (sched_data.cur == 0)
06373 {
06374 if (dump)
06375 fprintf (dump, "// At start of bundle, so nothing to do.\n");
06376
06377 rotate_two_bundles (NULL);
06378 return;
06379 }
06380
06381 for (i = -1; i < NR_PACKETS; i++)
06382 {
06383
06384
06385 const struct ia64_packet *p = (i >= 0 ? packets + i : sched_data.packet);
06386 int split = get_split (p, sched_data.first_slot);
06387 const struct bundle *compare;
06388 int next, stoppos;
06389
06390 if (! packet_matches_p (p, split, &next))
06391 continue;
06392
06393 compare = next > 3 ? p->t2 : p->t1;
06394
06395 stoppos = 3;
06396 if (compare->possible_stop)
06397 stoppos = compare->possible_stop;
06398 if (next > 3)
06399 stoppos += 3;
06400
06401 if (stoppos < next || stoppos >= best_stop)
06402 {
06403 if (compare->possible_stop == 0)
06404 continue;
06405 stoppos = (next > 3 ? 6 : 3);
06406 }
06407 if (stoppos < next || stoppos >= best_stop)
06408 continue;
06409
06410 if (dump)
06411 fprintf (dump, "// switching from %s %s to %s %s (stop at %d)\n",
06412 best->t1->name, best->t2->name, p->t1->name, p->t2->name,
06413 stoppos);
06414
06415 best_stop = stoppos;
06416 best = p;
06417 }
06418
06419 sched_data.packet = best;
06420 cycle_end_fill_slots (dump);
06421 while (sched_data.cur < best_stop)
06422 {
06423 sched_data.types[sched_data.cur] = best->t[sched_data.cur];
06424 sched_data.insns[sched_data.cur] = 0;
06425 sched_data.stopbit[sched_data.cur] = 0;
06426 sched_data.cur++;
06427 }
06428 sched_data.stopbit[sched_data.cur - 1] = 1;
06429 sched_data.first_slot = best_stop;
06430
06431 if (dump)
06432 dump_current_packet (dump);
06433 }
06434
06435
06436
06437
06438 static void
06439 maybe_rotate (dump)
06440 FILE *dump;
06441 {
06442 cycle_end_fill_slots (dump);
06443 if (sched_data.cur == 6)
06444 rotate_two_bundles (dump);
06445 else if (sched_data.cur >= 3)
06446 rotate_one_bundle (dump);
06447 sched_data.first_slot = sched_data.cur;
06448 }
06449
06450
06451 static int prev_cycle;
06452
06453
06454
06455 static int prev_first;
06456
06457
06458
06459
06460 static void
06461 nop_cycles_until (clock_var, dump)
06462 int clock_var;
06463 FILE *dump;
06464 {
06465 int prev_clock = prev_cycle;
06466 int cycles_left = clock_var - prev_clock;
06467 bool did_stop = false;
06468
06469
06470 if (sched_data.cur == 3)
06471 {
06472 sched_emit_insn (gen_insn_group_barrier (GEN_INT (3)));
06473 did_stop = true;
06474 maybe_rotate (dump);
06475 }
06476 else if (sched_data.cur > 0)
06477 {
06478 int need_stop = 0;
06479 int split = itanium_split_issue (sched_data.packet, prev_first);
06480
06481 if (sched_data.cur < 3 && split > 3)
06482 {
06483 split = 3;
06484 need_stop = 1;
06485 }
06486
06487 if (split > sched_data.cur)
06488 {
06489 int i;
06490 for (i = sched_data.cur; i < split; i++)
06491 {
06492 rtx t = sched_emit_insn (gen_nop_type (sched_data.packet->t[i]));
06493 sched_data.types[i] = sched_data.packet->t[i];
06494 sched_data.insns[i] = t;
06495 sched_data.stopbit[i] = 0;
06496 }
06497 sched_data.cur = split;
06498 }
06499
06500 if (! need_stop && sched_data.cur > 0 && sched_data.cur < 6
06501 && cycles_left > 1)
06502 {
06503 int i;
06504 for (i = sched_data.cur; i < 6; i++)
06505 {
06506 rtx t = sched_emit_insn (gen_nop_type (sched_data.packet->t[i]));
06507 sched_data.types[i] = sched_data.packet->t[i];
06508 sched_data.insns[i] = t;
06509 sched_data.stopbit[i] = 0;
06510 }
06511 sched_data.cur = 6;
06512 cycles_left--;
06513 need_stop = 1;
06514 }
06515
06516 if (need_stop || sched_data.cur == 6)
06517 {
06518 sched_emit_insn (gen_insn_group_barrier (GEN_INT (3)));
06519 did_stop = true;
06520 }
06521 maybe_rotate (dump);
06522 }
06523
06524 cycles_left--;
06525 while (cycles_left > 0)
06526 {
06527 sched_emit_insn (gen_bundle_selector (GEN_INT (0)));
06528 sched_emit_insn (gen_nop_type (TYPE_M));
06529 sched_emit_insn (gen_nop_type (TYPE_I));
06530 if (cycles_left > 1)
06531 {
06532 sched_emit_insn (gen_insn_group_barrier (GEN_INT (2)));
06533 cycles_left--;
06534 }
06535 sched_emit_insn (gen_nop_type (TYPE_I));
06536 sched_emit_insn (gen_insn_group_barrier (GEN_INT (3)));
06537 did_stop = true;
06538 cycles_left--;
06539 }
06540
06541 if (did_stop)
06542 init_insn_group_barriers ();
06543 }
06544
06545
06546
06547
06548 static int
06549 ia64_internal_sched_reorder (dump, sched_verbose, ready, pn_ready,
06550 reorder_type, clock_var)
06551 FILE *dump ATTRIBUTE_UNUSED;
06552 int sched_verbose ATTRIBUTE_UNUSED;
06553 rtx *ready;
06554 int *pn_ready;
06555 int reorder_type, clock_var;
06556 {
06557 int n_asms;
06558 int n_ready = *pn_ready;
06559 rtx *e_ready = ready + n_ready;
06560 rtx *insnp;
06561
06562 if (sched_verbose)
06563 {
06564 fprintf (dump, "// ia64_sched_reorder (type %d):\n", reorder_type);
06565 dump_current_packet (dump);
06566 }
06567
06568
06569
06570
06571
06572
06573 if (reorder_type == 0 && clock_var > 0 && ia64_final_schedule)
06574 {
06575 for (insnp = ready; insnp < e_ready; insnp++)
06576 {
06577 rtx insn = *insnp, link;
06578 enum attr_itanium_class t = ia64_safe_itanium_class (insn);
06579
06580 if (t == ITANIUM_CLASS_MMMUL
06581 || t == ITANIUM_CLASS_MMSHF
06582 || t == ITANIUM_CLASS_MMSHFI)
06583 continue;
06584
06585 for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
06586 if (REG_NOTE_KIND (link) == 0)
06587 {
06588 rtx other = XEXP (link, 0);
06589 enum attr_itanium_class t0 = ia64_safe_itanium_class (other);
06590 if (t0 == ITANIUM_CLASS_MMSHF || t0 == ITANIUM_CLASS_MMMUL)
06591 {
06592 nop_cycles_until (clock_var, sched_verbose ? dump : NULL);
06593 goto out;
06594 }
06595 }
06596 }
06597 }
06598 out:
06599
06600 prev_first = sched_data.first_slot;
06601 prev_cycle = clock_var;
06602
06603 if (reorder_type == 0)
06604 maybe_rotate (sched_verbose ? dump : NULL);
06605
06606
06607 n_asms = 0;
06608 for (insnp = ready; insnp < e_ready; insnp++)
06609 if (insnp < e_ready)
06610 {
06611 rtx insn = *insnp;
06612 enum attr_type t = ia64_safe_type (insn);
06613 if (t == TYPE_UNKNOWN)
06614 {
06615 if (GET_CODE (PATTERN (insn)) == ASM_INPUT
06616 || asm_noperands (PATTERN (insn)) >= 0)
06617 {
06618 rtx lowest = ready[n_asms];
06619 ready[n_asms] = insn;
06620 *insnp = lowest;
06621 n_asms++;
06622 }
06623 else
06624 {
06625 rtx highest = ready[n_ready - 1];
06626 ready[n_ready - 1] = insn;
06627 *insnp = highest;
06628 if (ia64_final_schedule && group_barrier_needed_p (insn))
06629 {
06630 schedule_stop (sched_verbose ? dump : NULL);
06631 sched_data.last_was_stop = 1;
06632 maybe_rotate (sched_verbose ? dump : NULL);
06633 }
06634
06635 return 1;
06636 }
06637 }
06638 }
06639 if (n_asms < n_ready)
06640 {
06641
06642 ready += n_asms;
06643 n_ready -= n_asms;
06644 }
06645 else if (n_ready > 0)
06646 {
06647
06648 if (ia64_final_schedule && group_barrier_needed_p (ready[n_ready - 1]))
06649 {
06650 schedule_stop (sched_verbose ? dump : NULL);
06651 sched_data.last_was_stop = 1;
06652 maybe_rotate (sched_verbose ? dump : NULL);
06653 }
06654 cycle_end_fill_slots (sched_verbose ? dump : NULL);
06655 return 1;
06656 }
06657
06658 if (ia64_final_schedule)
06659 {
06660 int nr_need_stop = 0;
06661
06662 for (insnp = ready; insnp < e_ready; insnp++)
06663 if (safe_group_barrier_needed_p (*insnp))
06664 nr_need_stop++;
06665
06666
06667
06668
06669
06670
06671
06672
06673 if ((reorder_type == 0 && nr_need_stop)
06674 || (reorder_type == 1 && n_ready == nr_need_stop))
06675 {
06676 schedule_stop (sched_verbose ? dump : NULL);
06677 sched_data.last_was_stop = 1;
06678 maybe_rotate (sched_verbose ? dump : NULL);
06679 if (reorder_type == 1)
06680 return 0;
06681 }
06682 else
06683 {
06684 int deleted = 0;
06685 insnp = e_ready;
06686
06687
06688 while (insnp-- > ready + deleted)
06689 while (insnp >= ready + deleted)
06690 {
06691 rtx insn = *insnp;
06692 if (! safe_group_barrier_needed_p (insn))
06693 break;
06694 memmove (ready + 1, ready, (insnp - ready) * sizeof (rtx));
06695 *ready = insn;
06696 deleted++;
06697 }
06698 n_ready -= deleted;
06699 ready += deleted;
06700 if (deleted != nr_need_stop)
06701 abort ();
06702 }
06703 }
06704
06705 return itanium_reorder (sched_verbose ? dump : NULL,
06706 ready, e_ready, reorder_type == 1);
06707 }
06708
06709 static int
06710 ia64_sched_reorder (dump, sched_verbose, ready, pn_ready, clock_var)
06711 FILE *dump;
06712 int sched_verbose;
06713 rtx *ready;
06714 int *pn_ready;
06715 int clock_var;
06716 {
06717 return ia64_internal_sched_reorder (dump, sched_verbose, ready,
06718 pn_ready, 0, clock_var);
06719 }
06720
06721
06722
06723
06724 static int
06725 ia64_sched_reorder2 (dump, sched_verbose, ready, pn_ready, clock_var)
06726 FILE *dump ATTRIBUTE_UNUSED;
06727 int sched_verbose ATTRIBUTE_UNUSED;
06728 rtx *ready;
06729 int *pn_ready;
06730 int clock_var;
06731 {
06732 if (sched_data.last_was_stop)
06733 return 0;
06734
06735
06736
06737
06738 if (sched_data.first_slot == 1
06739 && sched_data.stopbit[0]
06740 && ((sched_data.cur == 4
06741 && (sched_data.types[1] == TYPE_M || sched_data.types[1] == TYPE_A)
06742 && (sched_data.types[2] == TYPE_I || sched_data.types[2] == TYPE_A)
06743 && (sched_data.types[3] != TYPE_M && sched_data.types[3] != TYPE_A))
06744 || (sched_data.cur == 3
06745 && (sched_data.types[1] == TYPE_M
06746 || sched_data.types[1] == TYPE_A)
06747 && (sched_data.types[2] != TYPE_M
06748 && sched_data.types[2] != TYPE_I
06749 && sched_data.types[2] != TYPE_A))))
06750
06751 {
06752 int i, best;
06753 rtx stop = sched_data.insns[1];
06754
06755
06756 while (1)
06757 {
06758 int insn_code;
06759
06760 stop = PREV_INSN (stop);
06761 if (GET_CODE (stop) != INSN)
06762 abort ();
06763 insn_code = recog_memoized (stop);
06764
06765
06766
06767
06768
06769 if (insn_code == CODE_FOR_pred_rel_mutex
06770 || insn_code == CODE_FOR_prologue_use)
06771 continue;
06772
06773 if (insn_code == CODE_FOR_insn_group_barrier)
06774 break;
06775 abort ();
06776 }
06777
06778
06779 if (INTVAL (XVECEXP (PATTERN (stop), 0, 0)) != 1)
06780 abort ();
06781 XVECEXP (PATTERN (stop), 0, 0) = GEN_INT (3);
06782
06783 sched_data.stopbit[0] = 0;
06784 sched_data.stopbit[2] = 1;
06785
06786 sched_data.types[5] = sched_data.types[3];
06787 sched_data.types[4] = sched_data.types[2];
06788 sched_data.types[3] = sched_data.types[1];
06789 sched_data.insns[5] = sched_data.insns[3];
06790 sched_data.insns[4] = sched_data.insns[2];
06791 sched_data.insns[3] = sched_data.insns[1];
06792 sched_data.stopbit[5] = sched_data.stopbit[4] = sched_data.stopbit[3] = 0;
06793 sched_data.cur += 2;
06794 sched_data.first_slot = 3;
06795 for (i = 0; i < NR_PACKETS; i++)
06796 {
06797 const struct ia64_packet *p = packets + i;
06798 if (p->t[0] == TYPE_M && p->t[1] == TYPE_F && p->t[2] == TYPE_B)
06799 {
06800 sched_data.packet = p;
06801 break;
06802 }
06803 }
06804 rotate_one_bundle (sched_verbose ? dump : NULL);
06805
06806 best = 6;
06807 for (i = 0; i < NR_PACKETS; i++)
06808 {
06809 const struct ia64_packet *p = packets + i;
06810 int split = get_split (p, sched_data.first_slot);
06811 int next;
06812
06813
06814 if (p->t[1] == TYPE_B)
06815 continue;
06816
06817 if (packet_matches_p (p, split, &next) && next < best)
06818 {
06819 best = next;
06820 sched_data.packet = p;
06821 sched_data.split = split;
06822 }
06823 }
06824 if (best == 6)
06825 abort ();
06826 }
06827
06828 if (*pn_ready > 0)
06829 {
06830 int more = ia64_internal_sched_reorder (dump, sched_verbose,
06831 ready, pn_ready, 1,
06832 clock_var);
06833 if (more)
06834 return more;
06835
06836 if (sched_data.cur == sched_data.first_slot)
06837 return 0;
06838 }
06839
06840 if (sched_verbose)
06841 fprintf (dump, "// Can't issue more this cycle; updating type array.\n");
06842
06843 cycle_end_fill_slots (sched_verbose ? dump : NULL);
06844 if (sched_verbose)
06845 dump_current_packet (dump);
06846 return 0;
06847 }
06848
06849
06850
06851
06852 static int
06853 ia64_variable_issue (dump, sched_verbose, insn, can_issue_more)
06854 FILE *dump;
06855 int sched_verbose;
06856 rtx insn;
06857 int can_issue_more ATTRIBUTE_UNUSED;
06858 {
06859 enum attr_type t = ia64_safe_type (insn);
06860
06861 if (sched_data.last_was_stop)
06862 {
06863 int t = sched_data.first_slot;
06864 if (t == 0)
06865 t = 3;
06866 ia64_emit_insn_before (gen_insn_group_barrier (GEN_INT (t)), insn);
06867 init_insn_group_barriers ();
06868 sched_data.last_was_stop = 0;
06869 }
06870
06871 if (t == TYPE_UNKNOWN)
06872 {
06873 if (sched_verbose)
06874 fprintf (dump, "// Ignoring type %s\n", type_names[t]);
06875 if (GET_CODE (PATTERN (insn)) == ASM_INPUT
06876 || asm_noperands (PATTERN (insn)) >= 0)
06877 {
06878
06879 rotate_two_bundles (sched_verbose ? dump : NULL);
06880 if (ia64_final_schedule)
06881 group_barrier_needed_p (insn);
06882 }
06883 return 1;
06884 }
06885
06886
06887
06888 if (ia64_final_schedule
06889 && group_barrier_needed_p (insn))
06890 abort ();
06891
06892 sched_data.stopbit[sched_data.cur] = 0;
06893 sched_data.insns[sched_data.cur] = insn;
06894 sched_data.types[sched_data.cur] = t;
06895
06896 sched_data.cur++;
06897 if (sched_verbose)
06898 fprintf (dump, "// Scheduling insn %d of type %s\n",
06899 INSN_UID (insn), type_names[t]);
06900
06901 if (GET_CODE (insn) == CALL_INSN && ia64_final_schedule)
06902 {
06903 schedule_stop (sched_verbose ? dump : NULL);
06904 sched_data.last_was_stop = 1;
06905 }
06906
06907 return 1;
06908 }
06909
06910
06911
06912 static void
06913 ia64_sched_finish (dump, sched_verbose)
06914 FILE *dump;
06915 int sched_verbose;
06916 {
06917 if (sched_verbose)
06918 fprintf (dump, "// Finishing schedule.\n");
06919 rotate_two_bundles (NULL);
06920 free (sched_types);
06921 free (sched_ready);
06922 }
06923
06924
06925
06926
06927
06928
06929 static void
06930 emit_predicate_relation_info ()
06931 {
06932 basic_block bb;
06933
06934 FOR_EACH_BB_REVERSE (bb)
06935 {
06936 int r;
06937 rtx head = bb->head;
06938
06939
06940 if (GET_CODE (head) != CODE_LABEL)
06941 continue;
06942 if (GET_CODE (NEXT_INSN (head)) == NOTE
06943 && NOTE_LINE_NUMBER (NEXT_INSN (head)) == NOTE_INSN_BASIC_BLOCK)
06944 head = NEXT_INSN (head);
06945
06946 for (r = PR_REG (0); r < PR_REG (64); r += 2)
06947 if (REGNO_REG_SET_P (bb->global_live_at_start, r))
06948 {
06949 rtx p = gen_rtx_REG (BImode, r);
06950 rtx n = emit_insn_after (gen_pred_rel_mutex (p), head);
06951 if (head == bb->end)
06952 bb->end = n;
06953 head = n;
06954 }
06955 }
06956
06957
06958
06959
06960
06961 FOR_EACH_BB_REVERSE (bb)
06962 {
06963 rtx insn = bb->head;
06964
06965 while (1)
06966 {
06967 if (GET_CODE (insn) == CALL_INSN
06968 && GET_CODE (PATTERN (insn)) == COND_EXEC
06969 && find_reg_note (insn, REG_NORETURN, NULL_RTX))
06970 {
06971 rtx b = emit_insn_before (gen_safe_across_calls_all (), insn);
06972 rtx a = emit_insn_after (gen_safe_across_calls_normal (), insn);
06973 if (bb->head == insn)
06974 bb->head = b;
06975 if (bb->end == insn)
06976 bb->end = a;
06977 }
06978
06979 if (insn == bb->end)
06980 break;
06981 insn = NEXT_INSN (insn);
06982 }
06983 }
06984 }
06985
06986
06987
06988
06989 static rtx
06990 gen_nop_type (t)
06991 enum attr_type t;
06992 {
06993 switch (t)
06994 {
06995 case TYPE_M:
06996 return gen_nop_m ();
06997 case TYPE_I:
06998 return gen_nop_i ();
06999 case TYPE_B:
07000 return gen_nop_b ();
07001 case TYPE_F:
07002 return gen_nop_f ();
07003 case TYPE_X:
07004 return gen_nop_x ();
07005 default:
07006 abort ();
07007 }
07008 }
07009
07010
07011
07012
07013 static void
07014 ia64_emit_nops ()
07015 {
07016 rtx insn;
07017 const struct bundle *b = 0;
07018 int bundle_pos = 0;
07019
07020 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
07021 {
07022 rtx pat;
07023 enum attr_type t;
07024 pat = INSN_P (insn) ? PATTERN (insn) : const0_rtx;
07025 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
07026 continue;
07027 if ((GET_CODE (pat) == UNSPEC && XINT (pat, 1) == UNSPEC_BUNDLE_SELECTOR)
07028 || GET_CODE (insn) == CODE_LABEL)
07029 {
07030 if (b)
07031 while (bundle_pos < 3)
07032 {
07033 emit_insn_before (gen_nop_type (b->t[bundle_pos]), insn);
07034 bundle_pos++;
07035 }
07036 if (GET_CODE (insn) != CODE_LABEL)
07037 b = bundle + INTVAL (XVECEXP (pat, 0, 0));
07038 else
07039 b = 0;
07040 bundle_pos = 0;
07041 continue;
07042 }
07043 else if (GET_CODE (pat) == UNSPEC_VOLATILE
07044 && XINT (pat, 1) == UNSPECV_INSN_GROUP_BARRIER)
07045 {
07046 int t = INTVAL (XVECEXP (pat, 0, 0));
07047 if (b)
07048 while (bundle_pos < t)
07049 {
07050 emit_insn_before (gen_nop_type (b->t[bundle_pos]), insn);
07051 bundle_pos++;
07052 }
07053 continue;
07054 }
07055
07056 if (bundle_pos == 3)
07057 b = 0;
07058
07059 if (b && INSN_P (insn))
07060 {
07061 t = ia64_safe_type (insn);
07062 if (asm_noperands (PATTERN (insn)) >= 0
07063 || GET_CODE (PATTERN (insn)) == ASM_INPUT)
07064 {
07065 while (bundle_pos < 3)
07066 {
07067 emit_insn_before (gen_nop_type (b->t[bundle_pos]), insn);
07068 bundle_pos++;
07069 }
07070 continue;
07071 }
07072
07073 if (t == TYPE_UNKNOWN)
07074 continue;
07075 while (bundle_pos < 3)
07076 {
07077 if (t == b->t[bundle_pos]
07078 || (t == TYPE_A && (b->t[bundle_pos] == TYPE_M
07079 || b->t[bundle_pos] == TYPE_I)))
07080 break;
07081
07082 emit_insn_before (gen_nop_type (b->t[bundle_pos]), insn);
07083 bundle_pos++;
07084 }
07085 if (bundle_pos < 3)
07086 bundle_pos++;
07087 }
07088 }
07089 }
07090
07091
07092
07093 void
07094 ia64_reorg (insns)
07095 rtx insns;
07096 {
07097
07098
07099 compute_bb_for_insn ();
07100
07101
07102 if (optimize == 0)
07103 split_all_insns (0);
07104
07105
07106
07107 update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
07108
07109 if (ia64_flag_schedule_insns2)
07110 {
07111 timevar_push (TV_SCHED2);
07112 ia64_final_schedule = 1;
07113 schedule_ebbs (rtl_dump_file);
07114 ia64_final_schedule = 0;
07115 timevar_pop (TV_SCHED2);
07116
07117
07118
07119 emit_insn_group_barriers (rtl_dump_file, insns);
07120 ia64_emit_nops ();
07121 }
07122 else
07123 emit_all_insn_group_barriers (rtl_dump_file, insns);
07124
07125
07126
07127
07128 if (flag_unwind_tables || (flag_exceptions && !USING_SJLJ_EXCEPTIONS))
07129 {
07130 rtx insn;
07131 int saw_stop = 0;
07132
07133 insn = get_last_insn ();
07134 if (! INSN_P (insn))
07135 insn = prev_active_insn (insn);
07136 if (GET_CODE (insn) == INSN
07137 && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
07138 && XINT (PATTERN (insn), 1) == UNSPECV_INSN_GROUP_BARRIER)
07139 {
07140 saw_stop = 1;
07141 insn = prev_active_insn (insn);
07142 }
07143 if (GET_CODE (insn) == CALL_INSN)
07144 {
07145 if (! saw_stop)
07146 emit_insn (gen_insn_group_barrier (GEN_INT (3)));
07147 emit_insn (gen_break_f ());
07148 emit_insn (gen_insn_group_barrier (GEN_INT (3)));
07149 }
07150 }
07151
07152 fixup_errata ();
07153 emit_predicate_relation_info ();
07154 }
07155
07156
07157
07158 int
07159 ia64_epilogue_uses (regno)
07160 int regno;
07161 {
07162 switch (regno)
07163 {
07164 case R_GR (1):
07165
07166
07167
07168
07169
07170 return (TARGET_CONST_GP && !(TARGET_AUTO_PIC || TARGET_NO_PIC));
07171
07172 case IN_REG (0): case IN_REG (1): case IN_REG (2): case IN_REG (3):
07173 case IN_REG (4): case IN_REG (5): case IN_REG (6): case IN_REG (7):
07174
07175
07176
07177
07178
07179
07180 return lookup_attribute ("syscall_linkage",
07181 TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))) != NULL;
07182
07183 case R_BR (0):
07184
07185
07186 return 1;
07187
07188 case AR_PFS_REGNUM:
07189
07190 return 1;
07191
07192 default:
07193 return 0;
07194 }
07195 }
07196
07197
07198
07199 int
07200 ia64_eh_uses (regno)
07201 int regno;
07202 {
07203 if (! reload_completed)
07204 return 0;
07205
07206 if (current_frame_info.reg_save_b0
07207 && regno == current_frame_info.reg_save_b0)
07208 return 1;
07209 if (current_frame_info.reg_save_pr
07210 && regno == current_frame_info.reg_save_pr)
07211 return 1;
07212 if (current_frame_info.reg_save_ar_pfs
07213 && regno == current_frame_info.reg_save_ar_pfs)
07214 return 1;
07215 if (current_frame_info.reg_save_ar_unat
07216 && regno == current_frame_info.reg_save_ar_unat)
07217 return 1;
07218 if (current_frame_info.reg_save_ar_lc
07219 && regno == current_frame_info.reg_save_ar_lc)
07220 return 1;
07221
07222 return 0;
07223 }
07224
07225
07226
07227
07228
07229
07230
07231
07232
07233
07234
07235
07236
07237
07238
07239
07240
07241
07242
07243 static bool
07244 ia64_in_small_data_p (exp)
07245 tree exp;
07246 {
07247 if (TARGET_NO_SDATA)
07248 return false;
07249
07250 if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
07251 {
07252 const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
07253 if (strcmp (section, ".sdata") == 0
07254 || strcmp (section, ".sbss") == 0)
07255 return true;
07256 }
07257 else
07258 {
07259 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
07260
07261
07262
07263 if (size > 0 && size <= ia64_section_threshold)
07264 return true;
07265 }
07266
07267 return false;
07268 }
07269
07270 static void
07271 ia64_encode_section_info (decl, first)
07272 tree decl;
07273 int first ATTRIBUTE_UNUSED;
07274 {
07275 const char *symbol_str;
07276 bool is_local;
07277 rtx symbol;
07278 char encoding = 0;
07279
07280 if (TREE_CODE (decl) == FUNCTION_DECL)
07281 {
07282 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
07283 return;
07284 }
07285
07286
07287 if (TREE_CODE (decl) != VAR_DECL
07288 || GET_CODE (DECL_RTL (decl)) != MEM
07289 || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
07290 return;
07291
07292 symbol = XEXP (DECL_RTL (decl), 0);
07293 symbol_str = XSTR (symbol, 0);
07294
07295 is_local = (*targetm.binds_local_p) (decl);
07296
07297 if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
07298 encoding = " GLil"[decl_tls_model (decl)];
07299
07300 else if (is_local && ia64_in_small_data_p (decl))
07301 encoding = 's';
07302
07303
07304 if (encoding)
07305 {
07306 char *newstr;
07307 size_t len;
07308
07309 if (symbol_str[0] == ENCODE_SECTION_INFO_CHAR)
07310 {
07311 if (encoding == symbol_str[1])
07312 return;
07313
07314 abort ();
07315 }
07316
07317 len = strlen (symbol_str);
07318 newstr = alloca (len + 3);
07319 newstr[0] = ENCODE_SECTION_INFO_CHAR;
07320 newstr[1] = encoding;
07321 memcpy (newstr + 2, symbol_str, len + 1);
07322
07323 XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2);
07324 }
07325
07326
07327
07328
07329
07330 else if (symbol_str[0] == ENCODE_SECTION_INFO_CHAR)
07331 XSTR (symbol, 0) = ggc_strdup (symbol_str + 2);
07332 }
07333
07334 static const char *
07335 ia64_strip_name_encoding (str)
07336 const char *str;
07337 {
07338 if (str[0] == ENCODE_SECTION_INFO_CHAR)
07339 str += 2;
07340 if (str[0] == '*')
07341 str++;
07342 return str;
07343 }
07344
07345
07346
07347
07348 bool
07349 ia64_function_ok_for_sibcall (decl)
07350 tree decl;
07351 {
07352
07353 if (decl)
07354 return true;
07355
07356
07357
07358
07359 return !ia64_epilogue_uses (R_GR (1));
07360 }
07361
07362
07363
07364
07365
07366 static bool last_block;
07367
07368
07369
07370 static bool need_copy_state;
07371
07372
07373
07374 static void
07375 process_epilogue ()
07376 {
07377
07378
07379
07380 if (!last_block)
07381 {
07382 fprintf (asm_out_file, "\t.label_state 1\n");
07383 need_copy_state = true;
07384 }
07385
07386 fprintf (asm_out_file, "\t.restore sp\n");
07387 }
07388
07389
07390
07391
07392 static int
07393 process_set (asm_out_file, pat)
07394 FILE *asm_out_file;
07395 rtx pat;
07396 {
07397 rtx src = SET_SRC (pat);
07398 rtx dest = SET_DEST (pat);
07399 int src_regno, dest_regno;
07400
07401
07402 if (GET_CODE (src) == UNSPEC_VOLATILE
07403 && XINT (src, 1) == UNSPECV_ALLOC
07404 && GET_CODE (dest) == REG)
07405 {
07406 dest_regno = REGNO (dest);
07407
07408
07409
07410 if (dest_regno != current_frame_info.reg_save_ar_pfs)
07411 abort ();
07412
07413 fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
07414 ia64_dbx_register_number (dest_regno));
07415 return 1;
07416 }
07417
07418
07419 if (GET_CODE (dest) == REG && REGNO (dest) == STACK_POINTER_REGNUM)
07420 {
07421 if (GET_CODE (src) == PLUS)
07422 {
07423 rtx op0 = XEXP (src, 0);
07424 rtx op1 = XEXP (src, 1);
07425 if (op0 == dest && GET_CODE (op1) == CONST_INT)
07426 {
07427 if (INTVAL (op1) < 0)
07428 {
07429 fputs ("\t.fframe ", asm_out_file);
07430 fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC,
07431 -INTVAL (op1));
07432 fputc ('\n', asm_out_file);
07433 }
07434 else
07435 process_epilogue ();
07436 }
07437 else
07438 abort ();
07439 }
07440 else if (GET_CODE (src) == REG
07441 && REGNO (src) == HARD_FRAME_POINTER_REGNUM)
07442 process_epilogue ();
07443 else
07444 abort ();
07445
07446 return 1;
07447 }
07448
07449
07450 if (GET_CODE (dest) == REG && GET_CODE (src) == REG)
07451 {
07452 src_regno = REGNO (src);
07453 dest_regno = REGNO (dest);
07454
07455 switch (src_regno)
07456 {
07457 case BR_REG (0):
07458
07459 if (dest_regno != current_frame_info.reg_save_b0)
07460 abort ();
07461 fprintf (asm_out_file, "\t.save rp, r%d\n",
07462 ia64_dbx_register_number (dest_regno));
07463 return 1;
07464
07465 case PR_REG (0):
07466 if (dest_regno != current_frame_info.reg_save_pr)
07467 abort ();
07468 fprintf (asm_out_file, "\t.save pr, r%d\n",
07469 ia64_dbx_register_number (dest_regno));
07470 return 1;
07471
07472 case AR_UNAT_REGNUM:
07473 if (dest_regno != current_frame_info.reg_save_ar_unat)
07474 abort ();
07475 fprintf (asm_out_file, "\t.save ar.unat, r%d\n",
07476 ia64_dbx_register_number (dest_regno));
07477 return 1;
07478
07479 case AR_LC_REGNUM:
07480 if (dest_regno != current_frame_info.reg_save_ar_lc)
07481 abort ();
07482 fprintf (asm_out_file, "\t.save ar.lc, r%d\n",
07483 ia64_dbx_register_number (dest_regno));
07484 return 1;
07485
07486 case STACK_POINTER_REGNUM:
07487 if (dest_regno != HARD_FRAME_POINTER_REGNUM
07488 || ! frame_pointer_needed)
07489 abort ();
07490 fprintf (asm_out_file, "\t.vframe r%d\n",
07491 ia64_dbx_register_number (dest_regno));
07492 return 1;
07493
07494 default:
07495
07496 abort ();
07497 }
07498 }
07499
07500
07501 if (GET_CODE (dest) == MEM && GET_CODE (src) == REG)
07502 {
07503 long off;
07504 rtx base;
07505 const char *saveop;
07506
07507 if (GET_CODE (XEXP (dest, 0)) == REG)
07508 {
07509 base = XEXP (dest, 0);
07510 off = 0;
07511 }
07512 else if (GET_CODE (XEXP (dest, 0)) == PLUS
07513 && GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT)
07514 {
07515 base = XEXP (XEXP (dest, 0), 0);
07516 off = INTVAL (XEXP (XEXP (dest, 0), 1));
07517 }
07518 else
07519 abort ();
07520
07521 if (base == hard_frame_pointer_rtx)
07522 {
07523 saveop = ".savepsp";
07524 off = - off;
07525 }
07526 else if (base == stack_pointer_rtx)
07527 saveop = ".savesp";
07528 else
07529 abort ();
07530
07531 src_regno = REGNO (src);
07532 switch (src_regno)
07533 {
07534 case BR_REG (0):
07535 if (current_frame_info.reg_save_b0 != 0)
07536 abort ();
07537 fprintf (asm_out_file, "\t%s rp, %ld\n", saveop, off);
07538 return 1;
07539
07540 case PR_REG (0):
07541 if (current_frame_info.reg_save_pr != 0)
07542 abort ();
07543 fprintf (asm_out_file, "\t%s pr, %ld\n", saveop, off);
07544 return 1;
07545
07546 case AR_LC_REGNUM:
07547 if (current_frame_info.reg_save_ar_lc != 0)
07548 abort ();
07549 fprintf (asm_out_file, "\t%s ar.lc, %ld\n", saveop, off);
07550 return 1;
07551
07552 case AR_PFS_REGNUM:
07553 if (current_frame_info.reg_save_ar_pfs != 0)
07554 abort ();
07555 fprintf (asm_out_file, "\t%s ar.pfs, %ld\n", saveop, off);
07556 return 1;
07557
07558 case AR_UNAT_REGNUM:
07559 if (current_frame_info.reg_save_ar_unat != 0)
07560 abort ();
07561 fprintf (asm_out_file, "\t%s ar.unat, %ld\n", saveop, off);
07562 return 1;
07563
07564 case GR_REG (4):
07565 case GR_REG (5):
07566 case GR_REG (6):
07567 case GR_REG (7):
07568 fprintf (asm_out_file, "\t.save.g 0x%x\n",
07569 1 << (src_regno - GR_REG (4)));
07570 return 1;
07571
07572 case BR_REG (1):
07573 case BR_REG (2):
07574 case BR_REG (3):
07575 case BR_REG (4):
07576 case BR_REG (5):
07577 fprintf (asm_out_file, "\t.save.b 0x%x\n",
07578 1 << (src_regno - BR_REG (1)));
07579 return 1;
07580
07581 case FR_REG (2):
07582 case FR_REG (3):
07583 case FR_REG (4):
07584 case FR_REG (5):
07585 fprintf (asm_out_file, "\t.save.f 0x%x\n",
07586 1 << (src_regno - FR_REG (2)));
07587 return 1;
07588
07589 case FR_REG (16): case FR_REG (17): case FR_REG (18): case FR_REG (19):
07590 case FR_REG (20): case FR_REG (21): case FR_REG (22): case FR_REG (23):
07591 case FR_REG (24): case FR_REG (25): case FR_REG (26): case FR_REG (27):
07592 case FR_REG (28): case FR_REG (29): case FR_REG (30): case FR_REG (31):
07593 fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n",
07594 1 << (src_regno - FR_REG (12)));
07595 return 1;
07596
07597 default:
07598 return 0;
07599 }
07600 }
07601
07602 return 0;
07603 }
07604
07605
07606
07607
07608 void
07609 process_for_unwind_directive (asm_out_file, insn)
07610 FILE *asm_out_file;
07611 rtx insn;
07612 {
07613 if (flag_unwind_tables
07614 || (flag_exceptions && !USING_SJLJ_EXCEPTIONS))
07615 {
07616 rtx pat;
07617
07618 if (GET_CODE (insn) == NOTE
07619 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
07620 {
07621 last_block = NOTE_BASIC_BLOCK (insn)->next_bb == EXIT_BLOCK_PTR;
07622
07623
07624 if (need_copy_state)
07625 {
07626 fprintf (asm_out_file, "\t.body\n");
07627 fprintf (asm_out_file, "\t.copy_state 1\n");
07628 need_copy_state = false;
07629 }
07630 }
07631
07632 if (GET_CODE (insn) == NOTE || ! RTX_FRAME_RELATED_P (insn))
07633 return;
07634
07635 pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
07636 if (pat)
07637 pat = XEXP (pat, 0);
07638 else
07639 pat = PATTERN (insn);
07640
07641 switch (GET_CODE (pat))
07642 {
07643 case SET:
07644 process_set (asm_out_file, pat);
07645 break;
07646
07647 case PARALLEL:
07648 {
07649 int par_index;
07650 int limit = XVECLEN (pat, 0);
07651 for (par_index = 0; par_index < limit; par_index++)
07652 {
07653 rtx x = XVECEXP (pat, 0, par_index);
07654 if (GET_CODE (x) == SET)
07655 process_set (asm_out_file, x);
07656 }
07657 break;
07658 }
07659
07660 default:
07661 abort ();
07662 }
07663 }
07664 }
07665
07666
07667 void
07668 ia64_init_builtins ()
07669 {
07670 tree psi_type_node = build_pointer_type (integer_type_node);
07671 tree pdi_type_node = build_pointer_type (long_integer_type_node);
07672
07673
07674 tree si_ftype_psi_si_si
07675 = build_function_type_list (integer_type_node,
07676 psi_type_node, integer_type_node,
07677 integer_type_node, NULL_TREE);
07678
07679
07680 tree di_ftype_pdi_di_di
07681 = build_function_type_list (long_integer_type_node,
07682 pdi_type_node, long_integer_type_node,
07683 long_integer_type_node, NULL_TREE);
07684
07685 tree void_ftype_void
07686 = build_function_type (void_type_node, void_list_node);
07687
07688
07689 tree si_ftype_psi_si
07690 = build_function_type_list (integer_type_node,
07691 psi_type_node, integer_type_node, NULL_TREE);
07692
07693
07694 tree di_ftype_pdi_di
07695 = build_function_type_list (long_integer_type_node,
07696 pdi_type_node, long_integer_type_node,
07697 NULL_TREE);
07698
07699
07700 tree void_ftype_psi
07701 = build_function_type_list (void_type_node, psi_type_node, NULL_TREE);
07702
07703
07704 tree void_ftype_pdi
07705 = build_function_type_list (void_type_node, pdi_type_node, NULL_TREE);
07706
07707 #define def_builtin(name, type, code) \
07708 builtin_function ((name), (type), (code), BUILT_IN_MD, NULL, NULL_TREE)
07709
07710 def_builtin ("__sync_val_compare_and_swap_si", si_ftype_psi_si_si,
07711 IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI);
07712 def_builtin ("__sync_val_compare_and_swap_di", di_ftype_pdi_di_di,
07713 IA64_BUILTIN_VAL_COMPARE_AND_SWAP_DI);
07714 def_builtin ("__sync_bool_compare_and_swap_si", si_ftype_psi_si_si,
07715 IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_SI);
07716 def_builtin ("__sync_bool_compare_and_swap_di", di_ftype_pdi_di_di,
07717 IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_DI);
07718
07719 def_builtin ("__sync_synchronize", void_ftype_void,
07720 IA64_BUILTIN_SYNCHRONIZE);
07721
07722 def_builtin ("__sync_lock_test_and_set_si", si_ftype_psi_si,
07723 IA64_BUILTIN_LOCK_TEST_AND_SET_SI);
07724 def_builtin ("__sync_lock_test_and_set_di", di_ftype_pdi_di,
07725 IA64_BUILTIN_LOCK_TEST_AND_SET_DI);
07726 def_builtin ("__sync_lock_release_si", void_ftype_psi,
07727 IA64_BUILTIN_LOCK_RELEASE_SI);
07728 def_builtin ("__sync_lock_release_di", void_ftype_pdi,
07729 IA64_BUILTIN_LOCK_RELEASE_DI);
07730
07731 def_builtin ("__builtin_ia64_bsp",
07732 build_function_type (ptr_type_node, void_list_node),
07733 IA64_BUILTIN_BSP);
07734
07735 def_builtin ("__builtin_ia64_flushrs",
07736 build_function_type (void_type_node, void_list_node),
07737 IA64_BUILTIN_FLUSHRS);
07738
07739 def_builtin ("__sync_fetch_and_add_si", si_ftype_psi_si,
07740 IA64_BUILTIN_FETCH_AND_ADD_SI);
07741 def_builtin ("__sync_fetch_and_sub_si", si_ftype_psi_si,
07742 IA64_BUILTIN_FETCH_AND_SUB_SI);
07743 def_builtin ("__sync_fetch_and_or_si", si_ftype_psi_si,
07744 IA64_BUILTIN_FETCH_AND_OR_SI);
07745 def_builtin ("__sync_fetch_and_and_si", si_ftype_psi_si,
07746 IA64_BUILTIN_FETCH_AND_AND_SI);
07747 def_builtin ("__sync_fetch_and_xor_si", si_ftype_psi_si,
07748 IA64_BUILTIN_FETCH_AND_XOR_SI);
07749 def_builtin ("__sync_fetch_and_nand_si", si_ftype_psi_si,
07750 IA64_BUILTIN_FETCH_AND_NAND_SI);
07751
07752 def_builtin ("__sync_add_and_fetch_si", si_ftype_psi_si,
07753 IA64_BUILTIN_ADD_AND_FETCH_SI);
07754 def_builtin ("__sync_sub_and_fetch_si", si_ftype_psi_si,
07755 IA64_BUILTIN_SUB_AND_FETCH_SI);
07756 def_builtin ("__sync_or_and_fetch_si", si_ftype_psi_si,
07757 IA64_BUILTIN_OR_AND_FETCH_SI);
07758 def_builtin ("__sync_and_and_fetch_si", si_ftype_psi_si,
07759 IA64_BUILTIN_AND_AND_FETCH_SI);
07760 def_builtin ("__sync_xor_and_fetch_si", si_ftype_psi_si,
07761 IA64_BUILTIN_XOR_AND_FETCH_SI);
07762 def_builtin ("__sync_nand_and_fetch_si", si_ftype_psi_si,
07763 IA64_BUILTIN_NAND_AND_FETCH_SI);
07764
07765 def_builtin ("__sync_fetch_and_add_di", di_ftype_pdi_di,
07766 IA64_BUILTIN_FETCH_AND_ADD_DI);
07767 def_builtin ("__sync_fetch_and_sub_di", di_ftype_pdi_di,
07768 IA64_BUILTIN_FETCH_AND_SUB_DI);
07769 def_builtin ("__sync_fetch_and_or_di", di_ftype_pdi_di,
07770 IA64_BUILTIN_FETCH_AND_OR_DI);
07771 def_builtin ("__sync_fetch_and_and_di", di_ftype_pdi_di,
07772 IA64_BUILTIN_FETCH_AND_AND_DI);
07773 def_builtin ("__sync_fetch_and_xor_di", di_ftype_pdi_di,
07774 IA64_BUILTIN_FETCH_AND_XOR_DI);
07775 def_builtin ("__sync_fetch_and_nand_di", di_ftype_pdi_di,
07776 IA64_BUILTIN_FETCH_AND_NAND_DI);
07777
07778 def_builtin ("__sync_add_and_fetch_di", di_ftype_pdi_di,
07779 IA64_BUILTIN_ADD_AND_FETCH_DI);
07780 def_builtin ("__sync_sub_and_fetch_di", di_ftype_pdi_di,
07781 IA64_BUILTIN_SUB_AND_FETCH_DI);
07782 def_builtin ("__sync_or_and_fetch_di", di_ftype_pdi_di,
07783 IA64_BUILTIN_OR_AND_FETCH_DI);
07784 def_builtin ("__sync_and_and_fetch_di", di_ftype_pdi_di,
07785 IA64_BUILTIN_AND_AND_FETCH_DI);
07786 def_builtin ("__sync_xor_and_fetch_di", di_ftype_pdi_di,
07787 IA64_BUILTIN_XOR_AND_FETCH_DI);
07788 def_builtin ("__sync_nand_and_fetch_di", di_ftype_pdi_di,
07789 IA64_BUILTIN_NAND_AND_FETCH_DI);
07790
07791 #undef def_builtin
07792 }
07793
07794
07795
07796
07797
07798
07799
07800
07801
07802
07803
07804
07805
07806 static rtx
07807 ia64_expand_fetch_and_op (binoptab, mode, arglist, target)
07808 optab binoptab;
07809 enum machine_mode mode;
07810 tree arglist;
07811 rtx target;
07812 {
07813 rtx ret, label, tmp, ccv, insn, mem, value;
07814 tree arg0, arg1;
07815
07816 arg0 = TREE_VALUE (arglist);
07817 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07818 mem = expand_expr (arg0, NULL_RTX, Pmode, 0);
07819 #ifdef POINTERS_EXTEND_UNSIGNED
07820 if (GET_MODE(mem) != Pmode)
07821 mem = convert_memory_address (Pmode, mem);
07822 #endif
07823 value = expand_expr (arg1, NULL_RTX, mode, 0);
07824
07825 mem = gen_rtx_MEM (mode, force_reg (Pmode, mem));
07826 MEM_VOLATILE_P (mem) = 1;
07827
07828 if (target && register_operand (target, mode))
07829 ret = target;
07830 else
07831 ret = gen_reg_rtx (mode);
07832
07833 emit_insn (gen_mf ());
07834
07835
07836 if (binoptab == add_optab && fetchadd_operand (value, VOIDmode))
07837 {
07838 if (mode == SImode)
07839 insn = gen_fetchadd_acq_si (ret, mem, value);
07840 else
07841 insn = gen_fetchadd_acq_di (ret, mem, value);
07842 emit_insn (insn);
07843 return ret;
07844 }
07845
07846 tmp = gen_reg_rtx (mode);
07847 ccv = gen_rtx_REG (mode, AR_CCV_REGNUM);
07848 emit_move_insn (tmp, mem);
07849
07850 label = gen_label_rtx ();
07851 emit_label (label);
07852 emit_move_insn (ret, tmp);
07853 emit_move_insn (ccv, tmp);
07854
07855
07856
07857 if (binoptab == one_cmpl_optab)
07858 {
07859 tmp = expand_unop (mode, binoptab, tmp, NULL, OPTAB_WIDEN);
07860 binoptab = and_optab;
07861 }
07862 tmp = expand_binop (mode, binoptab, tmp, value, tmp, 1, OPTAB_WIDEN);
07863
07864 if (mode == SImode)
07865 insn = gen_cmpxchg_acq_si (tmp, mem, tmp, ccv);
07866 else
07867 insn = gen_cmpxchg_acq_di (tmp, mem, tmp, ccv);
07868 emit_insn (insn);
07869
07870 emit_cmp_and_jump_insns (tmp, ret, NE, 0, mode, 1, label);
07871
07872 return ret;
07873 }
07874
07875
07876
07877
07878
07879
07880
07881
07882
07883
07884
07885
07886
07887 static rtx
07888 ia64_expand_op_and_fetch (binoptab, mode, arglist, target)
07889 optab binoptab;
07890 enum machine_mode mode;
07891 tree arglist;
07892 rtx target;
07893 {
07894 rtx old, label, tmp, ret, ccv, insn, mem, value;
07895 tree arg0, arg1;
07896
07897 arg0 = TREE_VALUE (arglist);
07898 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07899 mem = expand_expr (arg0, NULL_RTX, Pmode, 0);
07900 #ifdef POINTERS_EXTEND_UNSIGNED
07901 if (GET_MODE(mem) != Pmode)
07902 mem = convert_memory_address (Pmode, mem);
07903 #endif
07904
07905 value = expand_expr (arg1, NULL_RTX, mode, 0);
07906
07907 mem = gen_rtx_MEM (mode, force_reg (Pmode, mem));
07908 MEM_VOLATILE_P (mem) = 1;
07909
07910 if (target && ! register_operand (target, mode))
07911 target = NULL_RTX;
07912
07913 emit_insn (gen_mf ());
07914 tmp = gen_reg_rtx (mode);
07915 old = gen_reg_rtx (mode);
07916 ccv = gen_rtx_REG (mode, AR_CCV_REGNUM);
07917
07918 emit_move_insn (tmp, mem);
07919
07920 label = gen_label_rtx ();
07921 emit_label (label);
07922 emit_move_insn (old, tmp);
07923 emit_move_insn (ccv, tmp);
07924
07925
07926
07927 if (binoptab == one_cmpl_optab)
07928 {
07929 tmp = expand_unop (mode, binoptab, tmp, NULL, OPTAB_WIDEN);
07930 binoptab = and_optab;
07931 }
07932 ret = expand_binop (mode, binoptab, tmp, value, target, 1, OPTAB_WIDEN);
07933
07934 if (mode == SImode)
07935 insn = gen_cmpxchg_acq_si (tmp, mem, ret, ccv);
07936 else
07937 insn = gen_cmpxchg_acq_di (tmp, mem, ret, ccv);
07938 emit_insn (insn);
07939
07940 emit_cmp_and_jump_insns (tmp, old, NE, 0, mode, 1, label);
07941
07942 return ret;
07943 }
07944
07945
07946
07947
07948
07949
07950
07951
07952
07953
07954
07955 static rtx
07956 ia64_expand_compare_and_swap (mode, boolp, arglist, target)
07957 enum machine_mode mode;
07958 int boolp;
07959 tree arglist;
07960 rtx target;
07961 {
07962 tree arg0, arg1, arg2;
07963 rtx mem, old, new, ccv, tmp, insn;
07964
07965 arg0 = TREE_VALUE (arglist);
07966 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
07967 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
07968 mem = expand_expr (arg0, NULL_RTX, ptr_mode, 0);
07969 old = expand_expr (arg1, NULL_RTX, mode, 0);
07970 new = expand_expr (arg2, NULL_RTX, mode, 0);
07971
07972 mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
07973 MEM_VOLATILE_P (mem) = 1;
07974
07975 if (! register_operand (old, mode))
07976 old = copy_to_mode_reg (mode, old);
07977 if (! register_operand (new, mode))
07978 new = copy_to_mode_reg (mode, new);
07979
07980 if (! boolp && target && register_operand (target, mode))
07981 tmp = target;
07982 else
07983 tmp = gen_reg_rtx (mode);
07984
07985 ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
07986 if (mode == DImode)
07987 emit_move_insn (ccv, old);
07988 else
07989 {
07990 rtx ccvtmp = gen_reg_rtx (DImode);
07991 emit_insn (gen_zero_extendsidi2 (ccvtmp, old));
07992 emit_move_insn (ccv, ccvtmp);
07993 }
07994 emit_insn (gen_mf ());
07995 if (mode == SImode)
07996 insn = gen_cmpxchg_acq_si (tmp, mem, new, ccv);
07997 else
07998 insn = gen_cmpxchg_acq_di (tmp, mem, new, ccv);
07999 emit_insn (insn);
08000
08001 if (boolp)
08002 {
08003 if (! target)
08004 target = gen_reg_rtx (mode);
08005 return emit_store_flag_force (target, EQ, tmp, old, mode, 1, 1);
08006 }
08007 else
08008 return tmp;
08009 }
08010
08011
08012
08013 static rtx
08014 ia64_expand_lock_test_and_set (mode, arglist, target)
08015 enum machine_mode mode;
08016 tree arglist;
08017 rtx target;
08018 {
08019 tree arg0, arg1;
08020 rtx mem, new, ret, insn;
08021
08022 arg0 = TREE_VALUE (arglist);
08023 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
08024 mem = expand_expr (arg0, NULL_RTX, ptr_mode, 0);
08025 new = expand_expr (arg1, NULL_RTX, mode, 0);
08026
08027 mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
08028 MEM_VOLATILE_P (mem) = 1;
08029 if (! register_operand (new, mode))
08030 new = copy_to_mode_reg (mode, new);
08031
08032 if (target && register_operand (target, mode))
08033 ret = target;
08034 else
08035 ret = gen_reg_rtx (mode);
08036
08037 if (mode == SImode)
08038 insn = gen_xchgsi (ret, mem, new);
08039 else
08040 insn = gen_xchgdi (ret, mem, new);
08041 emit_insn (insn);
08042
08043 return ret;
08044 }
08045
08046
08047
08048 static rtx
08049 ia64_expand_lock_release (mode, arglist, target)
08050 enum machine_mode mode;
08051 tree arglist;
08052 rtx target ATTRIBUTE_UNUSED;
08053 {
08054 tree arg0;
08055 rtx mem;
08056
08057 arg0 = TREE_VALUE (arglist);
08058 mem = expand_expr (arg0, NULL_RTX, ptr_mode, 0);
08059
08060 mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
08061 MEM_VOLATILE_P (mem) = 1;
08062
08063 emit_move_insn (mem, const0_rtx);
08064
08065 return const0_rtx;
08066 }
08067
08068 rtx
08069 ia64_expand_builtin (exp, target, subtarget, mode, ignore)
08070 tree exp;
08071 rtx target;
08072 rtx subtarget ATTRIBUTE_UNUSED;
08073 enum machine_mode mode ATTRIBUTE_UNUSED;
08074 int ignore ATTRIBUTE_UNUSED;
08075 {
08076 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
08077 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
08078 tree arglist = TREE_OPERAND (exp, 1);
08079
08080 switch (fcode)
08081 {
08082 case IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_SI:
08083 case IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI:
08084 case IA64_BUILTIN_LOCK_TEST_AND_SET_SI:
08085 case IA64_BUILTIN_LOCK_RELEASE_SI:
08086 case IA64_BUILTIN_FETCH_AND_ADD_SI:
08087 case IA64_BUILTIN_FETCH_AND_SUB_SI:
08088 case IA64_BUILTIN_FETCH_AND_OR_SI:
08089 case IA64_BUILTIN_FETCH_AND_AND_SI:
08090 case IA64_BUILTIN_FETCH_AND_XOR_SI:
08091 case IA64_BUILTIN_FETCH_AND_NAND_SI:
08092 case IA64_BUILTIN_ADD_AND_FETCH_SI:
08093 case IA64_BUILTIN_SUB_AND_FETCH_SI:
08094 case IA64_BUILTIN_OR_AND_FETCH_SI:
08095 case IA64_BUILTIN_AND_AND_FETCH_SI:
08096 case IA64_BUILTIN_XOR_AND_FETCH_SI:
08097 case IA64_BUILTIN_NAND_AND_FETCH_SI:
08098 mode = SImode;
08099 break;
08100
08101 case IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_DI:
08102 case IA64_BUILTIN_VAL_COMPARE_AND_SWAP_DI:
08103 case IA64_BUILTIN_LOCK_TEST_AND_SET_DI:
08104 case IA64_BUILTIN_LOCK_RELEASE_DI:
08105 case IA64_BUILTIN_FETCH_AND_ADD_DI:
08106 case IA64_BUILTIN_FETCH_AND_SUB_DI:
08107 case IA64_BUILTIN_FETCH_AND_OR_DI:
08108 case IA64_BUILTIN_FETCH_AND_AND_DI:
08109 case IA64_BUILTIN_FETCH_AND_XOR_DI:
08110 case IA64_BUILTIN_FETCH_AND_NAND_DI:
08111 case IA64_BUILTIN_ADD_AND_FETCH_DI:
08112 case IA64_BUILTIN_SUB_AND_FETCH_DI:
08113 case IA64_BUILTIN_OR_AND_FETCH_DI:
08114 case IA64_BUILTIN_AND_AND_FETCH_DI:
08115 case IA64_BUILTIN_XOR_AND_FETCH_DI:
08116 case IA64_BUILTIN_NAND_AND_FETCH_DI:
08117 mode = DImode;
08118 break;
08119
08120 default:
08121 break;
08122 }
08123
08124 switch (fcode)
08125 {
08126 case IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_SI:
08127 case IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_DI:
08128 return ia64_expand_compare_and_swap (mode, 1, arglist, target);
08129
08130 case IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI:
08131 case IA64_BUILTIN_VAL_COMPARE_AND_SWAP_DI:
08132 return ia64_expand_compare_and_swap (mode, 0, arglist, target);
08133
08134 case IA64_BUILTIN_SYNCHRONIZE:
08135 emit_insn (gen_mf ());
08136 return const0_rtx;
08137
08138 case IA64_BUILTIN_LOCK_TEST_AND_SET_SI:
08139 case IA64_BUILTIN_LOCK_TEST_AND_SET_DI:
08140 return ia64_expand_lock_test_and_set (mode, arglist, target);
08141
08142 case IA64_BUILTIN_LOCK_RELEASE_SI:
08143 case IA64_BUILTIN_LOCK_RELEASE_DI:
08144 return ia64_expand_lock_release (mode, arglist, target);
08145
08146 case IA64_BUILTIN_BSP:
08147 if (! target || ! register_operand (target, DImode))
08148 target = gen_reg_rtx (DImode);
08149 emit_insn (gen_bsp_value (target));
08150 return target;
08151
08152 case IA64_BUILTIN_FLUSHRS:
08153 emit_insn (gen_flushrs ());
08154 return const0_rtx;
08155
08156 case IA64_BUILTIN_FETCH_AND_ADD_SI:
08157 case IA64_BUILTIN_FETCH_AND_ADD_DI:
08158 return ia64_expand_fetch_and_op (add_optab, mode, arglist, target);
08159
08160 case IA64_BUILTIN_FETCH_AND_SUB_SI:
08161 case IA64_BUILTIN_FETCH_AND_SUB_DI:
08162 return ia64_expand_fetch_and_op (sub_optab, mode, arglist, target);
08163
08164 case IA64_BUILTIN_FETCH_AND_OR_SI:
08165 case IA64_BUILTIN_FETCH_AND_OR_DI:
08166 return ia64_expand_fetch_and_op (ior_optab, mode, arglist, target);
08167
08168 case IA64_BUILTIN_FETCH_AND_AND_SI:
08169 case IA64_BUILTIN_FETCH_AND_AND_DI:
08170 return ia64_expand_fetch_and_op (and_optab, mode, arglist, target);
08171
08172 case IA64_BUILTIN_FETCH_AND_XOR_SI:
08173 case IA64_BUILTIN_FETCH_AND_XOR_DI:
08174 return ia64_expand_fetch_and_op (xor_optab, mode, arglist, target);
08175
08176 case IA64_BUILTIN_FETCH_AND_NAND_SI:
08177 case IA64_BUILTIN_FETCH_AND_NAND_DI:
08178 return ia64_expand_fetch_and_op (one_cmpl_optab, mode, arglist, target);
08179
08180 case IA64_BUILTIN_ADD_AND_FETCH_SI:
08181 case IA64_BUILTIN_ADD_AND_FETCH_DI:
08182 return ia64_expand_op_and_fetch (add_optab, mode, arglist, target);
08183
08184 case IA64_BUILTIN_SUB_AND_FETCH_SI:
08185 case IA64_BUILTIN_SUB_AND_FETCH_DI:
08186 return ia64_expand_op_and_fetch (sub_optab, mode, arglist, target);
08187
08188 case IA64_BUILTIN_OR_AND_FETCH_SI:
08189 case IA64_BUILTIN_OR_AND_FETCH_DI:
08190 return ia64_expand_op_and_fetch (ior_optab, mode, arglist, target);
08191
08192 case IA64_BUILTIN_AND_AND_FETCH_SI:
08193 case IA64_BUILTIN_AND_AND_FETCH_DI:
08194 return ia64_expand_op_and_fetch (and_optab, mode, arglist, target);
08195
08196 case IA64_BUILTIN_XOR_AND_FETCH_SI:
08197 case IA64_BUILTIN_XOR_AND_FETCH_DI:
08198 return ia64_expand_op_and_fetch (xor_optab, mode, arglist, target);
08199
08200 case IA64_BUILTIN_NAND_AND_FETCH_SI:
08201 case IA64_BUILTIN_NAND_AND_FETCH_DI:
08202 return ia64_expand_op_and_fetch (one_cmpl_optab, mode, arglist, target);
08203
08204 default:
08205 break;
08206 }
08207
08208 return NULL_RTX;
08209 }
08210
08211
08212
08213
08214 enum direction
08215 ia64_hpux_function_arg_padding (mode, type)
08216 enum machine_mode mode;
08217 tree type;
08218 {
08219
08220
08221 if (type && AGGREGATE_TYPE_P (type)
08222 && int_size_in_bytes (type) < UNITS_PER_WORD)
08223 return upward;
08224
08225
08226
08227
08228 return((mode == BLKmode
08229 ? (type && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
08230 && int_size_in_bytes (type) < (PARM_BOUNDARY / BITS_PER_UNIT))
08231 : GET_MODE_BITSIZE (mode) < PARM_BOUNDARY)
08232 ? downward : upward);
08233 }
08234
08235
08236
08237
08238
08239 struct extern_func_list
08240 {
08241 struct extern_func_list *next;
08242 char *name;
08243 } *extern_func_head = 0;
08244
08245 static void
08246 ia64_hpux_add_extern_decl (name)
08247 const char *name;
08248 {
08249 struct extern_func_list *p;
08250
08251 p = (struct extern_func_list *) xmalloc (sizeof (struct extern_func_list));
08252 p->name = xmalloc (strlen (name) + 1);
08253 strcpy(p->name, name);
08254 p->next = extern_func_head;
08255 extern_func_head = p;
08256 }
08257
08258
08259
08260 void
08261 ia64_hpux_asm_file_end (file)
08262 FILE *file;
08263 {
08264 while (extern_func_head)
08265 {
08266 const char *real_name;
08267 tree decl;
08268
08269 real_name = (* targetm.strip_name_encoding) (extern_func_head->name);
08270 decl = maybe_get_identifier (real_name);
08271
08272 if (!decl
08273 || (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl)))
08274 {
08275 if (decl)
08276 TREE_ASM_WRITTEN (decl) = 1;
08277 (*targetm.asm_out.globalize_label) (file, extern_func_head->name);
08278 fprintf (file, "%s", TYPE_ASM_OP);
08279 assemble_name (file, extern_func_head->name);
08280 putc (',', file);
08281 fprintf (file, TYPE_OPERAND_FMT, "function");
08282 putc ('\n', file);
08283 }
08284 extern_func_head = extern_func_head->next;
08285 }
08286 }
08287
08288
08289
08290
08291
08292 static void
08293 ia64_select_rtx_section (mode, x, align)
08294 enum machine_mode mode;
08295 rtx x;
08296 unsigned HOST_WIDE_INT align;
08297 {
08298 if (GET_MODE_SIZE (mode) > 0
08299 && GET_MODE_SIZE (mode) <= ia64_section_threshold)
08300 sdata_section ();
08301 else
08302 default_elf_select_rtx_section (mode, x, align);
08303 }
08304
08305
08306
08307
08308 static void
08309 ia64_rwreloc_select_section (exp, reloc, align)
08310 tree exp;
08311 int reloc;
08312 unsigned HOST_WIDE_INT align;
08313 {
08314 default_elf_select_section_1 (exp, reloc, align, true);
08315 }
08316
08317 static void
08318 ia64_rwreloc_unique_section (decl, reloc)
08319 tree decl;
08320 int reloc;
08321 {
08322 default_unique_section_1 (decl, reloc, true);
08323 }
08324
08325 static void
08326 ia64_rwreloc_select_rtx_section (mode, x, align)
08327 enum machine_mode mode;
08328 rtx x;
08329 unsigned HOST_WIDE_INT align;
08330 {
08331 int save_pic = flag_pic;
08332 flag_pic = 1;
08333 ia64_select_rtx_section (mode, x, align);
08334 flag_pic = save_pic;
08335 }
08336
08337 static unsigned int
08338 ia64_rwreloc_section_type_flags (decl, name, reloc)
08339 tree decl;
08340 const char *name;
08341 int reloc;
08342 {
08343 return default_section_type_flags_1 (decl, name, reloc, true);
08344 }
08345
08346
08347
08348
08349
08350
08351
08352
08353 static void
08354 ia64_output_mi_thunk (file, thunk, delta, vcall_offset, function)
08355 FILE *file;
08356 tree thunk ATTRIBUTE_UNUSED;
08357 HOST_WIDE_INT delta;
08358 HOST_WIDE_INT vcall_offset;
08359 tree function;
08360 {
08361 rtx this, insn, funexp;
08362
08363 reload_completed = 1;
08364 no_new_pseudos = 1;
08365
08366
08367 last_scratch_gr_reg = 15;
08368
08369 memset (¤t_frame_info, 0, sizeof (current_frame_info));
08370 current_frame_info.spill_cfa_off = -16;
08371 current_frame_info.n_input_regs = 1;
08372 current_frame_info.need_regstk = (TARGET_REG_NAMES != 0);
08373
08374 if (!TARGET_REG_NAMES)
08375 reg_names[IN_REG (0)] = ia64_reg_numbers[0];
08376
08377
08378 emit_note (NULL, NOTE_INSN_PROLOGUE_END);
08379
08380 this = gen_rtx_REG (Pmode, IN_REG (0));
08381
08382
08383 if (delta)
08384 {
08385 rtx delta_rtx = GEN_INT (delta);
08386
08387 if (!CONST_OK_FOR_I (delta))
08388 {
08389 rtx tmp = gen_rtx_REG (Pmode, 2);
08390 emit_move_insn (tmp, delta_rtx);
08391 delta_rtx = tmp;
08392 }
08393 emit_insn (gen_adddi3 (this, this, delta_rtx));
08394 }
08395
08396
08397 if (vcall_offset)
08398 {
08399 rtx vcall_offset_rtx = GEN_INT (vcall_offset);
08400 rtx tmp = gen_rtx_REG (Pmode, 2);
08401
08402 emit_move_insn (tmp, gen_rtx_MEM (Pmode, this));
08403
08404 if (!CONST_OK_FOR_J (vcall_offset))
08405 {
08406 rtx tmp2 = gen_rtx_REG (Pmode, next_scratch_gr_reg ());
08407 emit_move_insn (tmp2, vcall_offset_rtx);
08408 vcall_offset_rtx = tmp2;
08409 }
08410 emit_insn (gen_adddi3 (tmp, tmp, vcall_offset_rtx));
08411
08412 emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
08413
08414 emit_insn (gen_adddi3 (this, this, tmp));
08415 }
08416
08417
08418 if (! TREE_USED (function))
08419 {
08420 assemble_external (function);
08421 TREE_USED (function) = 1;
08422 }
08423 funexp = XEXP (DECL_RTL (function), 0);
08424 funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
08425 ia64_expand_call (NULL_RTX, funexp, NULL_RTX, 1);
08426 insn = get_last_insn ();
08427 SIBLING_CALL_P (insn) = 1;
08428
08429
08430 reload_completed = 1;
08431 try_split (PATTERN (insn), insn, 0);
08432
08433 emit_barrier ();
08434
08435
08436
08437
08438
08439
08440 insn = get_insns ();
08441 emit_all_insn_group_barriers (NULL, insn);
08442 shorten_branches (insn);
08443 final_start_function (insn, file, 1);
08444 final (insn, file, 1, 0);
08445 final_end_function ();
08446
08447 reload_completed = 0;
08448 no_new_pseudos = 0;
08449 }
08450
08451 #include "gt-ia64.h"