00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "coretypes.h"
00027 #include "tm.h"
00028 #include "rtl.h"
00029 #include "tree.h"
00030 #include "regs.h"
00031 #include "hard-reg-set.h"
00032 #include "real.h"
00033 #include "insn-config.h"
00034 #include "conditions.h"
00035 #include "output.h"
00036 #include "insn-attr.h"
00037 #include "flags.h"
00038 #include "recog.h"
00039 #include "expr.h"
00040 #include "optabs.h"
00041 #include "except.h"
00042 #include "function.h"
00043 #include "ggc.h"
00044 #include "basic-block.h"
00045 #include "toplev.h"
00046 #include "sched-int.h"
00047 #include "timevar.h"
00048 #include "target.h"
00049 #include "target-def.h"
00050 #include "tm_p.h"
00051 #include "hashtab.h"
00052 #include "langhooks.h"
00053 #include "cfglayout.h"
00054 #include "tree-gimple.h"
00055 #include "intl.h"
00056 #include "debug.h"
00057 #include "params.h"
00058
00059
00060
00061 int ia64_asm_output_label = 0;
00062
00063
00064
00065 struct rtx_def * ia64_compare_op0;
00066 struct rtx_def * ia64_compare_op1;
00067
00068
00069 static const char * const ia64_reg_numbers[96] =
00070 { "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
00071 "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
00072 "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
00073 "r56", "r57", "r58", "r59", "r60", "r61", "r62", "r63",
00074 "r64", "r65", "r66", "r67", "r68", "r69", "r70", "r71",
00075 "r72", "r73", "r74", "r75", "r76", "r77", "r78", "r79",
00076 "r80", "r81", "r82", "r83", "r84", "r85", "r86", "r87",
00077 "r88", "r89", "r90", "r91", "r92", "r93", "r94", "r95",
00078 "r96", "r97", "r98", "r99", "r100","r101","r102","r103",
00079 "r104","r105","r106","r107","r108","r109","r110","r111",
00080 "r112","r113","r114","r115","r116","r117","r118","r119",
00081 "r120","r121","r122","r123","r124","r125","r126","r127"};
00082
00083
00084 static const char * const ia64_input_reg_names[8] =
00085 { "in0", "in1", "in2", "in3", "in4", "in5", "in6", "in7" };
00086
00087
00088 static const char * const ia64_local_reg_names[80] =
00089 { "loc0", "loc1", "loc2", "loc3", "loc4", "loc5", "loc6", "loc7",
00090 "loc8", "loc9", "loc10","loc11","loc12","loc13","loc14","loc15",
00091 "loc16","loc17","loc18","loc19","loc20","loc21","loc22","loc23",
00092 "loc24","loc25","loc26","loc27","loc28","loc29","loc30","loc31",
00093 "loc32","loc33","loc34","loc35","loc36","loc37","loc38","loc39",
00094 "loc40","loc41","loc42","loc43","loc44","loc45","loc46","loc47",
00095 "loc48","loc49","loc50","loc51","loc52","loc53","loc54","loc55",
00096 "loc56","loc57","loc58","loc59","loc60","loc61","loc62","loc63",
00097 "loc64","loc65","loc66","loc67","loc68","loc69","loc70","loc71",
00098 "loc72","loc73","loc74","loc75","loc76","loc77","loc78","loc79" };
00099
00100
00101 static const char * const ia64_output_reg_names[8] =
00102 { "out0", "out1", "out2", "out3", "out4", "out5", "out6", "out7" };
00103
00104
00105 enum processor_type ia64_tune = PROCESSOR_ITANIUM2;
00106
00107
00108
00109 static int ia64_flag_schedule_insns2;
00110
00111
00112
00113 static int ia64_flag_var_tracking;
00114
00115
00116
00117
00118 unsigned int ia64_section_threshold;
00119
00120
00121
00122 int bundling_p = 0;
00123
00124
00125
00126
00127 struct ia64_frame_info
00128 {
00129 HOST_WIDE_INT total_size;
00130
00131 HOST_WIDE_INT spill_cfa_off;
00132 HOST_WIDE_INT spill_size;
00133 HOST_WIDE_INT extra_spill_size;
00134 HARD_REG_SET mask;
00135 unsigned int gr_used_mask;
00136
00137 int n_spilled;
00138 int reg_fp;
00139 int reg_save_b0;
00140 int reg_save_pr;
00141 int reg_save_ar_pfs;
00142 int reg_save_ar_unat;
00143 int reg_save_ar_lc;
00144 int reg_save_gp;
00145 int n_input_regs;
00146 int n_local_regs;
00147 int n_output_regs;
00148 int n_rotate_regs;
00149
00150 char need_regstk;
00151 char initialized;
00152 };
00153
00154
00155 static struct ia64_frame_info current_frame_info;
00156
00157 static int ia64_first_cycle_multipass_dfa_lookahead (void);
00158 static void ia64_dependencies_evaluation_hook (rtx, rtx);
00159 static void ia64_init_dfa_pre_cycle_insn (void);
00160 static rtx ia64_dfa_pre_cycle_insn (void);
00161 static int ia64_first_cycle_multipass_dfa_lookahead_guard (rtx);
00162 static bool ia64_first_cycle_multipass_dfa_lookahead_guard_spec (rtx);
00163 static int ia64_dfa_new_cycle (FILE *, int, rtx, int, int, int *);
00164 static void ia64_h_i_d_extended (void);
00165 static int ia64_mode_to_int (enum machine_mode);
00166 static void ia64_set_sched_flags (spec_info_t);
00167 static int ia64_speculate_insn (rtx, ds_t, rtx *);
00168 static rtx ia64_gen_spec_insn (rtx, ds_t, int, bool, bool);
00169 static bool ia64_needs_block_p (rtx);
00170 static rtx ia64_gen_check (rtx, rtx, bool);
00171 static int ia64_spec_check_p (rtx);
00172 static int ia64_spec_check_src_p (rtx);
00173 static rtx gen_tls_get_addr (void);
00174 static rtx gen_thread_pointer (void);
00175 static int find_gr_spill (int);
00176 static int next_scratch_gr_reg (void);
00177 static void mark_reg_gr_used_mask (rtx, void *);
00178 static void ia64_compute_frame_size (HOST_WIDE_INT);
00179 static void setup_spill_pointers (int, rtx, HOST_WIDE_INT);
00180 static void finish_spill_pointers (void);
00181 static rtx spill_restore_mem (rtx, HOST_WIDE_INT);
00182 static void do_spill (rtx (*)(rtx, rtx, rtx), rtx, HOST_WIDE_INT, rtx);
00183 static void do_restore (rtx (*)(rtx, rtx, rtx), rtx, HOST_WIDE_INT);
00184 static rtx gen_movdi_x (rtx, rtx, rtx);
00185 static rtx gen_fr_spill_x (rtx, rtx, rtx);
00186 static rtx gen_fr_restore_x (rtx, rtx, rtx);
00187
00188 static enum machine_mode hfa_element_mode (tree, bool);
00189 static void ia64_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
00190 tree, int *, int);
00191 static int ia64_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
00192 tree, bool);
00193 static bool ia64_function_ok_for_sibcall (tree, tree);
00194 static bool ia64_return_in_memory (tree, tree);
00195 static bool ia64_rtx_costs (rtx, int, int, int *);
00196 static void fix_range (const char *);
00197 static bool ia64_handle_option (size_t, const char *, int);
00198 static struct machine_function * ia64_init_machine_status (void);
00199 static void emit_insn_group_barriers (FILE *);
00200 static void emit_all_insn_group_barriers (FILE *);
00201 static void final_emit_insn_group_barriers (FILE *);
00202 static void emit_predicate_relation_info (void);
00203 static void ia64_reorg (void);
00204 static bool ia64_in_small_data_p (tree);
00205 static void process_epilogue (FILE *, rtx, bool, bool);
00206 static int process_set (FILE *, rtx, rtx, bool, bool);
00207
00208 static bool ia64_assemble_integer (rtx, unsigned int, int);
00209 static void ia64_output_function_prologue (FILE *, HOST_WIDE_INT);
00210 static void ia64_output_function_epilogue (FILE *, HOST_WIDE_INT);
00211 static void ia64_output_function_end_prologue (FILE *);
00212
00213 static int ia64_issue_rate (void);
00214 static int ia64_adjust_cost_2 (rtx, int, rtx, int);
00215 static void ia64_sched_init (FILE *, int, int);
00216 static void ia64_sched_init_global (FILE *, int, int);
00217 static void ia64_sched_finish_global (FILE *, int);
00218 static void ia64_sched_finish (FILE *, int);
00219 static int ia64_dfa_sched_reorder (FILE *, int, rtx *, int *, int, int);
00220 static int ia64_sched_reorder (FILE *, int, rtx *, int *, int);
00221 static int ia64_sched_reorder2 (FILE *, int, rtx *, int *, int);
00222 static int ia64_variable_issue (FILE *, int, rtx, int);
00223
00224 static struct bundle_state *get_free_bundle_state (void);
00225 static void free_bundle_state (struct bundle_state *);
00226 static void initiate_bundle_states (void);
00227 static void finish_bundle_states (void);
00228 static unsigned bundle_state_hash (const void *);
00229 static int bundle_state_eq_p (const void *, const void *);
00230 static int insert_bundle_state (struct bundle_state *);
00231 static void initiate_bundle_state_table (void);
00232 static void finish_bundle_state_table (void);
00233 static int try_issue_nops (struct bundle_state *, int);
00234 static int try_issue_insn (struct bundle_state *, rtx);
00235 static void issue_nops_and_insn (struct bundle_state *, int, rtx, int, int);
00236 static int get_max_pos (state_t);
00237 static int get_template (state_t, int);
00238
00239 static rtx get_next_important_insn (rtx, rtx);
00240 static void bundling (FILE *, int, rtx, rtx);
00241
00242 static void ia64_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
00243 HOST_WIDE_INT, tree);
00244 static void ia64_file_start (void);
00245
00246 static int ia64_hpux_reloc_rw_mask (void) ATTRIBUTE_UNUSED;
00247 static int ia64_reloc_rw_mask (void) ATTRIBUTE_UNUSED;
00248 static section *ia64_select_rtx_section (enum machine_mode, rtx,
00249 unsigned HOST_WIDE_INT);
00250 static void ia64_output_dwarf_dtprel (FILE *, int, rtx)
00251 ATTRIBUTE_UNUSED;
00252 static unsigned int ia64_section_type_flags (tree, const char *, int);
00253 static void ia64_hpux_add_extern_decl (tree decl)
00254 ATTRIBUTE_UNUSED;
00255 static void ia64_hpux_file_end (void)
00256 ATTRIBUTE_UNUSED;
00257 static void ia64_init_libfuncs (void)
00258 ATTRIBUTE_UNUSED;
00259 static void ia64_hpux_init_libfuncs (void)
00260 ATTRIBUTE_UNUSED;
00261 static void ia64_sysv4_init_libfuncs (void)
00262 ATTRIBUTE_UNUSED;
00263 static void ia64_vms_init_libfuncs (void)
00264 ATTRIBUTE_UNUSED;
00265
00266 static tree ia64_handle_model_attribute (tree *, tree, tree, int, bool *);
00267 static void ia64_encode_section_info (tree, rtx, int);
00268 static rtx ia64_struct_value_rtx (tree, int);
00269 static tree ia64_gimplify_va_arg (tree, tree, tree *, tree *);
00270 static bool ia64_scalar_mode_supported_p (enum machine_mode mode);
00271 static bool ia64_vector_mode_supported_p (enum machine_mode mode);
00272 static bool ia64_cannot_force_const_mem (rtx);
00273 static const char *ia64_mangle_fundamental_type (tree);
00274 static const char *ia64_invalid_conversion (tree, tree);
00275 static const char *ia64_invalid_unary_op (int, tree);
00276 static const char *ia64_invalid_binary_op (int, tree, tree);
00277
00278
00279 static const struct attribute_spec ia64_attribute_table[] =
00280 {
00281
00282 { "syscall_linkage", 0, 0, false, true, true, NULL },
00283 { "model", 1, 1, true, false, false, ia64_handle_model_attribute },
00284 { NULL, 0, 0, false, false, false, NULL }
00285 };
00286
00287
00288 #undef TARGET_ATTRIBUTE_TABLE
00289 #define TARGET_ATTRIBUTE_TABLE ia64_attribute_table
00290
00291 #undef TARGET_INIT_BUILTINS
00292 #define TARGET_INIT_BUILTINS ia64_init_builtins
00293
00294 #undef TARGET_EXPAND_BUILTIN
00295 #define TARGET_EXPAND_BUILTIN ia64_expand_builtin
00296
00297 #undef TARGET_ASM_BYTE_OP
00298 #define TARGET_ASM_BYTE_OP "\tdata1\t"
00299 #undef TARGET_ASM_ALIGNED_HI_OP
00300 #define TARGET_ASM_ALIGNED_HI_OP "\tdata2\t"
00301 #undef TARGET_ASM_ALIGNED_SI_OP
00302 #define TARGET_ASM_ALIGNED_SI_OP "\tdata4\t"
00303 #undef TARGET_ASM_ALIGNED_DI_OP
00304 #define TARGET_ASM_ALIGNED_DI_OP "\tdata8\t"
00305 #undef TARGET_ASM_UNALIGNED_HI_OP
00306 #define TARGET_ASM_UNALIGNED_HI_OP "\tdata2.ua\t"
00307 #undef TARGET_ASM_UNALIGNED_SI_OP
00308 #define TARGET_ASM_UNALIGNED_SI_OP "\tdata4.ua\t"
00309 #undef TARGET_ASM_UNALIGNED_DI_OP
00310 #define TARGET_ASM_UNALIGNED_DI_OP "\tdata8.ua\t"
00311 #undef TARGET_ASM_INTEGER
00312 #define TARGET_ASM_INTEGER ia64_assemble_integer
00313
00314 #undef TARGET_ASM_FUNCTION_PROLOGUE
00315 #define TARGET_ASM_FUNCTION_PROLOGUE ia64_output_function_prologue
00316 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
00317 #define TARGET_ASM_FUNCTION_END_PROLOGUE ia64_output_function_end_prologue
00318 #undef TARGET_ASM_FUNCTION_EPILOGUE
00319 #define TARGET_ASM_FUNCTION_EPILOGUE ia64_output_function_epilogue
00320
00321 #undef TARGET_IN_SMALL_DATA_P
00322 #define TARGET_IN_SMALL_DATA_P ia64_in_small_data_p
00323
00324 #undef TARGET_SCHED_ADJUST_COST_2
00325 #define TARGET_SCHED_ADJUST_COST_2 ia64_adjust_cost_2
00326 #undef TARGET_SCHED_ISSUE_RATE
00327 #define TARGET_SCHED_ISSUE_RATE ia64_issue_rate
00328 #undef TARGET_SCHED_VARIABLE_ISSUE
00329 #define TARGET_SCHED_VARIABLE_ISSUE ia64_variable_issue
00330 #undef TARGET_SCHED_INIT
00331 #define TARGET_SCHED_INIT ia64_sched_init
00332 #undef TARGET_SCHED_FINISH
00333 #define TARGET_SCHED_FINISH ia64_sched_finish
00334 #undef TARGET_SCHED_INIT_GLOBAL
00335 #define TARGET_SCHED_INIT_GLOBAL ia64_sched_init_global
00336 #undef TARGET_SCHED_FINISH_GLOBAL
00337 #define TARGET_SCHED_FINISH_GLOBAL ia64_sched_finish_global
00338 #undef TARGET_SCHED_REORDER
00339 #define TARGET_SCHED_REORDER ia64_sched_reorder
00340 #undef TARGET_SCHED_REORDER2
00341 #define TARGET_SCHED_REORDER2 ia64_sched_reorder2
00342
00343 #undef TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK
00344 #define TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK ia64_dependencies_evaluation_hook
00345
00346 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
00347 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD ia64_first_cycle_multipass_dfa_lookahead
00348
00349 #undef TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN
00350 #define TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN ia64_init_dfa_pre_cycle_insn
00351 #undef TARGET_SCHED_DFA_PRE_CYCLE_INSN
00352 #define TARGET_SCHED_DFA_PRE_CYCLE_INSN ia64_dfa_pre_cycle_insn
00353
00354 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD
00355 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD\
00356 ia64_first_cycle_multipass_dfa_lookahead_guard
00357
00358 #undef TARGET_SCHED_DFA_NEW_CYCLE
00359 #define TARGET_SCHED_DFA_NEW_CYCLE ia64_dfa_new_cycle
00360
00361 #undef TARGET_SCHED_H_I_D_EXTENDED
00362 #define TARGET_SCHED_H_I_D_EXTENDED ia64_h_i_d_extended
00363
00364 #undef TARGET_SCHED_SET_SCHED_FLAGS
00365 #define TARGET_SCHED_SET_SCHED_FLAGS ia64_set_sched_flags
00366
00367 #undef TARGET_SCHED_SPECULATE_INSN
00368 #define TARGET_SCHED_SPECULATE_INSN ia64_speculate_insn
00369
00370 #undef TARGET_SCHED_NEEDS_BLOCK_P
00371 #define TARGET_SCHED_NEEDS_BLOCK_P ia64_needs_block_p
00372
00373 #undef TARGET_SCHED_GEN_CHECK
00374 #define TARGET_SCHED_GEN_CHECK ia64_gen_check
00375
00376 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC
00377 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC\
00378 ia64_first_cycle_multipass_dfa_lookahead_guard_spec
00379
00380 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
00381 #define TARGET_FUNCTION_OK_FOR_SIBCALL ia64_function_ok_for_sibcall
00382 #undef TARGET_ARG_PARTIAL_BYTES
00383 #define TARGET_ARG_PARTIAL_BYTES ia64_arg_partial_bytes
00384
00385 #undef TARGET_ASM_OUTPUT_MI_THUNK
00386 #define TARGET_ASM_OUTPUT_MI_THUNK ia64_output_mi_thunk
00387 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
00388 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
00389
00390 #undef TARGET_ASM_FILE_START
00391 #define TARGET_ASM_FILE_START ia64_file_start
00392
00393 #undef TARGET_RTX_COSTS
00394 #define TARGET_RTX_COSTS ia64_rtx_costs
00395 #undef TARGET_ADDRESS_COST
00396 #define TARGET_ADDRESS_COST hook_int_rtx_0
00397
00398 #undef TARGET_MACHINE_DEPENDENT_REORG
00399 #define TARGET_MACHINE_DEPENDENT_REORG ia64_reorg
00400
00401 #undef TARGET_ENCODE_SECTION_INFO
00402 #define TARGET_ENCODE_SECTION_INFO ia64_encode_section_info
00403
00404 #undef TARGET_SECTION_TYPE_FLAGS
00405 #define TARGET_SECTION_TYPE_FLAGS ia64_section_type_flags
00406
00407 #ifdef HAVE_AS_TLS
00408 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
00409 #define TARGET_ASM_OUTPUT_DWARF_DTPREL ia64_output_dwarf_dtprel
00410 #endif
00411
00412
00413 #if 0
00414 #undef TARGET_PROMOTE_FUNCTION_ARGS
00415 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
00416 #endif
00417
00418
00419 #if 0
00420 #undef TARGET_PROMOTE_FUNCTION_RETURN
00421 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
00422 #endif
00423
00424
00425 #if 0
00426 #undef TARGET_PROMOTE_PROTOTYPES
00427 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
00428 #endif
00429
00430 #undef TARGET_STRUCT_VALUE_RTX
00431 #define TARGET_STRUCT_VALUE_RTX ia64_struct_value_rtx
00432 #undef TARGET_RETURN_IN_MEMORY
00433 #define TARGET_RETURN_IN_MEMORY ia64_return_in_memory
00434 #undef TARGET_SETUP_INCOMING_VARARGS
00435 #define TARGET_SETUP_INCOMING_VARARGS ia64_setup_incoming_varargs
00436 #undef TARGET_STRICT_ARGUMENT_NAMING
00437 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
00438 #undef TARGET_MUST_PASS_IN_STACK
00439 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
00440
00441 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
00442 #define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg
00443
00444 #undef TARGET_UNWIND_EMIT
00445 #define TARGET_UNWIND_EMIT process_for_unwind_directive
00446
00447 #undef TARGET_SCALAR_MODE_SUPPORTED_P
00448 #define TARGET_SCALAR_MODE_SUPPORTED_P ia64_scalar_mode_supported_p
00449 #undef TARGET_VECTOR_MODE_SUPPORTED_P
00450 #define TARGET_VECTOR_MODE_SUPPORTED_P ia64_vector_mode_supported_p
00451
00452
00453
00454 #undef TARGET_RELAXED_ORDERING
00455 #define TARGET_RELAXED_ORDERING true
00456
00457 #undef TARGET_DEFAULT_TARGET_FLAGS
00458 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | TARGET_CPU_DEFAULT)
00459 #undef TARGET_HANDLE_OPTION
00460 #define TARGET_HANDLE_OPTION ia64_handle_option
00461
00462 #undef TARGET_CANNOT_FORCE_CONST_MEM
00463 #define TARGET_CANNOT_FORCE_CONST_MEM ia64_cannot_force_const_mem
00464
00465 #undef TARGET_MANGLE_FUNDAMENTAL_TYPE
00466 #define TARGET_MANGLE_FUNDAMENTAL_TYPE ia64_mangle_fundamental_type
00467
00468 #undef TARGET_INVALID_CONVERSION
00469 #define TARGET_INVALID_CONVERSION ia64_invalid_conversion
00470 #undef TARGET_INVALID_UNARY_OP
00471 #define TARGET_INVALID_UNARY_OP ia64_invalid_unary_op
00472 #undef TARGET_INVALID_BINARY_OP
00473 #define TARGET_INVALID_BINARY_OP ia64_invalid_binary_op
00474
00475 struct gcc_target targetm = TARGET_INITIALIZER;
00476
00477 typedef enum
00478 {
00479 ADDR_AREA_NORMAL,
00480 ADDR_AREA_SMALL
00481 }
00482 ia64_addr_area;
00483
00484 static GTY(()) tree small_ident1;
00485 static GTY(()) tree small_ident2;
00486
00487 static void
00488 init_idents (void)
00489 {
00490 if (small_ident1 == 0)
00491 {
00492 small_ident1 = get_identifier ("small");
00493 small_ident2 = get_identifier ("__small__");
00494 }
00495 }
00496
00497
00498
00499 static ia64_addr_area
00500 ia64_get_addr_area (tree decl)
00501 {
00502 tree model_attr;
00503
00504 model_attr = lookup_attribute ("model", DECL_ATTRIBUTES (decl));
00505 if (model_attr)
00506 {
00507 tree id;
00508
00509 init_idents ();
00510 id = TREE_VALUE (TREE_VALUE (model_attr));
00511 if (id == small_ident1 || id == small_ident2)
00512 return ADDR_AREA_SMALL;
00513 }
00514 return ADDR_AREA_NORMAL;
00515 }
00516
00517 static tree
00518 ia64_handle_model_attribute (tree *node, tree name, tree args,
00519 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
00520 {
00521 ia64_addr_area addr_area = ADDR_AREA_NORMAL;
00522 ia64_addr_area area;
00523 tree arg, decl = *node;
00524
00525 init_idents ();
00526 arg = TREE_VALUE (args);
00527 if (arg == small_ident1 || arg == small_ident2)
00528 {
00529 addr_area = ADDR_AREA_SMALL;
00530 }
00531 else
00532 {
00533 warning (OPT_Wattributes, "invalid argument of %qs attribute",
00534 IDENTIFIER_POINTER (name));
00535 *no_add_attrs = true;
00536 }
00537
00538 switch (TREE_CODE (decl))
00539 {
00540 case VAR_DECL:
00541 if ((DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl))
00542 == FUNCTION_DECL)
00543 && !TREE_STATIC (decl))
00544 {
00545 error ("%Jan address area attribute cannot be specified for "
00546 "local variables", decl);
00547 *no_add_attrs = true;
00548 }
00549 area = ia64_get_addr_area (decl);
00550 if (area != ADDR_AREA_NORMAL && addr_area != area)
00551 {
00552 error ("address area of %q+D conflicts with previous "
00553 "declaration", decl);
00554 *no_add_attrs = true;
00555 }
00556 break;
00557
00558 case FUNCTION_DECL:
00559 error ("%Jaddress area attribute cannot be specified for functions",
00560 decl);
00561 *no_add_attrs = true;
00562 break;
00563
00564 default:
00565 warning (OPT_Wattributes, "%qs attribute ignored",
00566 IDENTIFIER_POINTER (name));
00567 *no_add_attrs = true;
00568 break;
00569 }
00570
00571 return NULL_TREE;
00572 }
00573
00574 static void
00575 ia64_encode_addr_area (tree decl, rtx symbol)
00576 {
00577 int flags;
00578
00579 flags = SYMBOL_REF_FLAGS (symbol);
00580 switch (ia64_get_addr_area (decl))
00581 {
00582 case ADDR_AREA_NORMAL: break;
00583 case ADDR_AREA_SMALL: flags |= SYMBOL_FLAG_SMALL_ADDR; break;
00584 default: gcc_unreachable ();
00585 }
00586 SYMBOL_REF_FLAGS (symbol) = flags;
00587 }
00588
00589 static void
00590 ia64_encode_section_info (tree decl, rtx rtl, int first)
00591 {
00592 default_encode_section_info (decl, rtl, first);
00593
00594
00595 if (TREE_CODE (decl) == VAR_DECL
00596 && GET_CODE (DECL_RTL (decl)) == MEM
00597 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF
00598 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
00599 ia64_encode_addr_area (decl, XEXP (rtl, 0));
00600 }
00601
00602
00603
00604 bool
00605 ia64_const_ok_for_letter_p (HOST_WIDE_INT value, char c)
00606 {
00607 switch (c)
00608 {
00609 case 'I':
00610 return CONST_OK_FOR_I (value);
00611 case 'J':
00612 return CONST_OK_FOR_J (value);
00613 case 'K':
00614 return CONST_OK_FOR_K (value);
00615 case 'L':
00616 return CONST_OK_FOR_L (value);
00617 case 'M':
00618 return CONST_OK_FOR_M (value);
00619 case 'N':
00620 return CONST_OK_FOR_N (value);
00621 case 'O':
00622 return CONST_OK_FOR_O (value);
00623 case 'P':
00624 return CONST_OK_FOR_P (value);
00625 default:
00626 return false;
00627 }
00628 }
00629
00630
00631
00632 bool
00633 ia64_const_double_ok_for_letter_p (rtx value, char c)
00634 {
00635 switch (c)
00636 {
00637 case 'G':
00638 return CONST_DOUBLE_OK_FOR_G (value);
00639 default:
00640 return false;
00641 }
00642 }
00643
00644
00645
00646 bool
00647 ia64_extra_constraint (rtx value, char c)
00648 {
00649 switch (c)
00650 {
00651 case 'Q':
00652
00653 return memory_operand(value, VOIDmode) && !MEM_VOLATILE_P (value);
00654
00655 case 'R':
00656
00657 return (GET_CODE (value) == CONST_INT
00658 && INTVAL (value) >= 1 && INTVAL (value) <= 4);
00659
00660 case 'S':
00661
00662 return (GET_CODE (value) == MEM
00663 && GET_RTX_CLASS (GET_CODE (XEXP (value, 0))) != RTX_AUTOINC
00664 && (reload_in_progress || memory_operand (value, VOIDmode)));
00665
00666 case 'T':
00667
00668 return small_addr_symbolic_operand (value, VOIDmode);
00669
00670 case 'U':
00671
00672 return value == CONST0_RTX (GET_MODE (value));
00673
00674 case 'W':
00675
00676
00677 if (GET_CODE (value) == CONST_VECTOR
00678 && GET_MODE_CLASS (GET_MODE (value)) == MODE_VECTOR_INT)
00679 {
00680 value = simplify_subreg (DImode, value, GET_MODE (value), 0);
00681 return ia64_const_ok_for_letter_p (INTVAL (value), 'J');
00682 }
00683 return false;
00684
00685 case 'Y':
00686
00687 return
00688 (GET_CODE (value) == CONST_VECTOR
00689 && GET_MODE (value) == V2SFmode
00690 && ia64_const_double_ok_for_letter_p (XVECEXP (value, 0, 0), 'G')
00691 && ia64_const_double_ok_for_letter_p (XVECEXP (value, 0, 1), 'G'));
00692
00693 default:
00694 return false;
00695 }
00696 }
00697
00698
00699
00700 int
00701 ia64_move_ok (rtx dst, rtx src)
00702 {
00703
00704
00705
00706
00707 if (GET_CODE (dst) != MEM)
00708 return 1;
00709 if (GET_CODE (src) == MEM)
00710 return 0;
00711 if (register_operand (src, VOIDmode))
00712 return 1;
00713
00714
00715 if (INTEGRAL_MODE_P (GET_MODE (dst)))
00716 return src == const0_rtx;
00717 else
00718 return GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src);
00719 }
00720
00721
00722
00723 int
00724 ia64_load_pair_ok (rtx dst, rtx src)
00725 {
00726 if (GET_CODE (dst) != REG || !FP_REGNO_P (REGNO (dst)))
00727 return 0;
00728 if (GET_CODE (src) != MEM || MEM_VOLATILE_P (src))
00729 return 0;
00730 switch (GET_CODE (XEXP (src, 0)))
00731 {
00732 case REG:
00733 case POST_INC:
00734 break;
00735 case POST_DEC:
00736 return 0;
00737 case POST_MODIFY:
00738 {
00739 rtx adjust = XEXP (XEXP (XEXP (src, 0), 1), 1);
00740
00741 if (GET_CODE (adjust) != CONST_INT
00742 || INTVAL (adjust) != GET_MODE_SIZE (GET_MODE (src)))
00743 return 0;
00744 }
00745 break;
00746 default:
00747 abort ();
00748 }
00749 return 1;
00750 }
00751
00752 int
00753 addp4_optimize_ok (rtx op1, rtx op2)
00754 {
00755 return (basereg_operand (op1, GET_MODE(op1)) !=
00756 basereg_operand (op2, GET_MODE(op2)));
00757 }
00758
00759
00760
00761
00762 int
00763 ia64_depz_field_mask (rtx rop, rtx rshift)
00764 {
00765 unsigned HOST_WIDE_INT op = INTVAL (rop);
00766 unsigned HOST_WIDE_INT shift = INTVAL (rshift);
00767
00768
00769 op >>= shift;
00770
00771
00772 return exact_log2 (op + 1);
00773 }
00774
00775
00776
00777 static enum tls_model
00778 tls_symbolic_operand_type (rtx addr)
00779 {
00780 enum tls_model tls_kind = 0;
00781
00782 if (GET_CODE (addr) == CONST)
00783 {
00784 if (GET_CODE (XEXP (addr, 0)) == PLUS
00785 && GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF)
00786 tls_kind = SYMBOL_REF_TLS_MODEL (XEXP (XEXP (addr, 0), 0));
00787 }
00788 else if (GET_CODE (addr) == SYMBOL_REF)
00789 tls_kind = SYMBOL_REF_TLS_MODEL (addr);
00790
00791 return tls_kind;
00792 }
00793
00794
00795
00796
00797 bool
00798 ia64_legitimate_constant_p (rtx x)
00799 {
00800 switch (GET_CODE (x))
00801 {
00802 case CONST_INT:
00803 case LABEL_REF:
00804 return true;
00805
00806 case CONST_DOUBLE:
00807 if (GET_MODE (x) == VOIDmode)
00808 return true;
00809 return CONST_DOUBLE_OK_FOR_G (x);
00810
00811 case CONST:
00812 case SYMBOL_REF:
00813
00814
00815
00816 if (tls_symbolic_operand_type (x) == 0)
00817 {
00818 HOST_WIDE_INT addend = 0;
00819 rtx op = x;
00820
00821 if (GET_CODE (op) == CONST
00822 && GET_CODE (XEXP (op, 0)) == PLUS
00823 && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
00824 {
00825 addend = INTVAL (XEXP (XEXP (op, 0), 1));
00826 op = XEXP (XEXP (op, 0), 0);
00827 }
00828
00829 if (any_offset_symbol_operand (op, GET_MODE (op))
00830 || function_operand (op, GET_MODE (op)))
00831 return true;
00832 if (aligned_offset_symbol_operand (op, GET_MODE (op)))
00833 return (addend & 0x3fff) == 0;
00834 return false;
00835 }
00836 return false;
00837
00838 case CONST_VECTOR:
00839 {
00840 enum machine_mode mode = GET_MODE (x);
00841
00842 if (mode == V2SFmode)
00843 return ia64_extra_constraint (x, 'Y');
00844
00845 return (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
00846 && GET_MODE_SIZE (mode) <= 8);
00847 }
00848
00849 default:
00850 return false;
00851 }
00852 }
00853
00854
00855
00856 static bool
00857 ia64_cannot_force_const_mem (rtx x)
00858 {
00859 return tls_symbolic_operand_type (x) != 0;
00860 }
00861
00862
00863
00864 bool
00865 ia64_expand_load_address (rtx dest, rtx src)
00866 {
00867 gcc_assert (GET_CODE (dest) == REG);
00868
00869
00870
00871
00872
00873 if (GET_MODE (dest) != Pmode)
00874 dest = gen_rtx_REG_offset (dest, Pmode, REGNO (dest), 0);
00875
00876 if (TARGET_NO_PIC)
00877 return false;
00878 if (small_addr_symbolic_operand (src, VOIDmode))
00879 return false;
00880
00881 if (TARGET_AUTO_PIC)
00882 emit_insn (gen_load_gprel64 (dest, src));
00883 else if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (src))
00884 emit_insn (gen_load_fptr (dest, src));
00885 else if (sdata_symbolic_operand (src, VOIDmode))
00886 emit_insn (gen_load_gprel (dest, src));
00887 else
00888 {
00889 HOST_WIDE_INT addend = 0;
00890 rtx tmp;
00891
00892
00893
00894
00895
00896
00897 if (GET_CODE (src) == CONST)
00898 {
00899 HOST_WIDE_INT hi, lo;
00900
00901 hi = INTVAL (XEXP (XEXP (src, 0), 1));
00902 lo = ((hi & 0x3fff) ^ 0x2000) - 0x2000;
00903 hi = hi - lo;
00904
00905 if (lo != 0)
00906 {
00907 addend = lo;
00908 src = plus_constant (XEXP (XEXP (src, 0), 0), hi);
00909 }
00910 }
00911
00912 tmp = gen_rtx_HIGH (Pmode, src);
00913 tmp = gen_rtx_PLUS (Pmode, tmp, pic_offset_table_rtx);
00914 emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
00915
00916 tmp = gen_rtx_LO_SUM (Pmode, dest, src);
00917 emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
00918
00919 if (addend)
00920 {
00921 tmp = gen_rtx_PLUS (Pmode, dest, GEN_INT (addend));
00922 emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
00923 }
00924 }
00925
00926 return true;
00927 }
00928
00929 static GTY(()) rtx gen_tls_tga;
00930 static rtx
00931 gen_tls_get_addr (void)
00932 {
00933 if (!gen_tls_tga)
00934 gen_tls_tga = init_one_libfunc ("__tls_get_addr");
00935 return gen_tls_tga;
00936 }
00937
00938 static GTY(()) rtx thread_pointer_rtx;
00939 static rtx
00940 gen_thread_pointer (void)
00941 {
00942 if (!thread_pointer_rtx)
00943 thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
00944 return thread_pointer_rtx;
00945 }
00946
00947 static rtx
00948 ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1,
00949 rtx orig_op1, HOST_WIDE_INT addend)
00950 {
00951 rtx tga_op1, tga_op2, tga_ret, tga_eqv, tmp, insns;
00952 rtx orig_op0 = op0;
00953 HOST_WIDE_INT addend_lo, addend_hi;
00954
00955 switch (tls_kind)
00956 {
00957 case TLS_MODEL_GLOBAL_DYNAMIC:
00958 start_sequence ();
00959
00960 tga_op1 = gen_reg_rtx (Pmode);
00961 emit_insn (gen_load_dtpmod (tga_op1, op1));
00962
00963 tga_op2 = gen_reg_rtx (Pmode);
00964 emit_insn (gen_load_dtprel (tga_op2, op1));
00965
00966 tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
00967 LCT_CONST, Pmode, 2, tga_op1,
00968 Pmode, tga_op2, Pmode);
00969
00970 insns = get_insns ();
00971 end_sequence ();
00972
00973 if (GET_MODE (op0) != Pmode)
00974 op0 = tga_ret;
00975 emit_libcall_block (insns, op0, tga_ret, op1);
00976 break;
00977
00978 case TLS_MODEL_LOCAL_DYNAMIC:
00979
00980
00981
00982
00983 start_sequence ();
00984
00985 tga_op1 = gen_reg_rtx (Pmode);
00986 emit_insn (gen_load_dtpmod (tga_op1, op1));
00987
00988 tga_op2 = const0_rtx;
00989
00990 tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
00991 LCT_CONST, Pmode, 2, tga_op1,
00992 Pmode, tga_op2, Pmode);
00993
00994 insns = get_insns ();
00995 end_sequence ();
00996
00997 tga_eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
00998 UNSPEC_LD_BASE);
00999 tmp = gen_reg_rtx (Pmode);
01000 emit_libcall_block (insns, tmp, tga_ret, tga_eqv);
01001
01002 if (!register_operand (op0, Pmode))
01003 op0 = gen_reg_rtx (Pmode);
01004 if (TARGET_TLS64)
01005 {
01006 emit_insn (gen_load_dtprel (op0, op1));
01007 emit_insn (gen_adddi3 (op0, tmp, op0));
01008 }
01009 else
01010 emit_insn (gen_add_dtprel (op0, op1, tmp));
01011 break;
01012
01013 case TLS_MODEL_INITIAL_EXEC:
01014 addend_lo = ((addend & 0x3fff) ^ 0x2000) - 0x2000;
01015 addend_hi = addend - addend_lo;
01016
01017 op1 = plus_constant (op1, addend_hi);
01018 addend = addend_lo;
01019
01020 tmp = gen_reg_rtx (Pmode);
01021 emit_insn (gen_load_tprel (tmp, op1));
01022
01023 if (!register_operand (op0, Pmode))
01024 op0 = gen_reg_rtx (Pmode);
01025 emit_insn (gen_adddi3 (op0, tmp, gen_thread_pointer ()));
01026 break;
01027
01028 case TLS_MODEL_LOCAL_EXEC:
01029 if (!register_operand (op0, Pmode))
01030 op0 = gen_reg_rtx (Pmode);
01031
01032 op1 = orig_op1;
01033 addend = 0;
01034 if (TARGET_TLS64)
01035 {
01036 emit_insn (gen_load_tprel (op0, op1));
01037 emit_insn (gen_adddi3 (op0, op0, gen_thread_pointer ()));
01038 }
01039 else
01040 emit_insn (gen_add_tprel (op0, op1, gen_thread_pointer ()));
01041 break;
01042
01043 default:
01044 gcc_unreachable ();
01045 }
01046
01047 if (addend)
01048 op0 = expand_simple_binop (Pmode, PLUS, op0, GEN_INT (addend),
01049 orig_op0, 1, OPTAB_DIRECT);
01050 if (orig_op0 == op0)
01051 return NULL_RTX;
01052 if (GET_MODE (orig_op0) == Pmode)
01053 return op0;
01054 return gen_lowpart (GET_MODE (orig_op0), op0);
01055 }
01056
01057 rtx
01058 ia64_expand_move (rtx op0, rtx op1)
01059 {
01060 enum machine_mode mode = GET_MODE (op0);
01061
01062 if (!reload_in_progress && !reload_completed && !ia64_move_ok (op0, op1))
01063 op1 = force_reg (mode, op1);
01064
01065 if ((mode == Pmode || mode == ptr_mode) && symbolic_operand (op1, VOIDmode))
01066 {
01067 HOST_WIDE_INT addend = 0;
01068 enum tls_model tls_kind;
01069 rtx sym = op1;
01070
01071 if (GET_CODE (op1) == CONST
01072 && GET_CODE (XEXP (op1, 0)) == PLUS
01073 && GET_CODE (XEXP (XEXP (op1, 0), 1)) == CONST_INT)
01074 {
01075 addend = INTVAL (XEXP (XEXP (op1, 0), 1));
01076 sym = XEXP (XEXP (op1, 0), 0);
01077 }
01078
01079 tls_kind = tls_symbolic_operand_type (sym);
01080 if (tls_kind)
01081 return ia64_expand_tls_address (tls_kind, op0, sym, op1, addend);
01082
01083 if (any_offset_symbol_operand (sym, mode))
01084 addend = 0;
01085 else if (aligned_offset_symbol_operand (sym, mode))
01086 {
01087 HOST_WIDE_INT addend_lo, addend_hi;
01088
01089 addend_lo = ((addend & 0x3fff) ^ 0x2000) - 0x2000;
01090 addend_hi = addend - addend_lo;
01091
01092 if (addend_lo != 0)
01093 {
01094 op1 = plus_constant (sym, addend_hi);
01095 addend = addend_lo;
01096 }
01097 else
01098 addend = 0;
01099 }
01100 else
01101 op1 = sym;
01102
01103 if (reload_completed)
01104 {
01105
01106 gcc_assert (addend == 0);
01107 if (ia64_expand_load_address (op0, op1))
01108 return NULL_RTX;
01109 }
01110
01111 if (addend)
01112 {
01113 rtx subtarget = no_new_pseudos ? op0 : gen_reg_rtx (mode);
01114
01115 emit_insn (gen_rtx_SET (VOIDmode, subtarget, op1));
01116
01117 op1 = expand_simple_binop (mode, PLUS, subtarget,
01118 GEN_INT (addend), op0, 1, OPTAB_DIRECT);
01119 if (op0 == op1)
01120 return NULL_RTX;
01121 }
01122 }
01123
01124 return op1;
01125 }
01126
01127
01128
01129 void
01130 ia64_emit_cond_move (rtx op0, rtx op1, rtx cond)
01131 {
01132 rtx insn, first = get_last_insn ();
01133
01134 emit_move_insn (op0, op1);
01135
01136 for (insn = get_last_insn (); insn != first; insn = PREV_INSN (insn))
01137 if (INSN_P (insn))
01138 PATTERN (insn) = gen_rtx_COND_EXEC (VOIDmode, copy_rtx (cond),
01139 PATTERN (insn));
01140 }
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157 static rtx
01158 ia64_split_tmode (rtx out[2], rtx in, bool reversed, bool dead)
01159 {
01160 rtx fixup = 0;
01161
01162 switch (GET_CODE (in))
01163 {
01164 case REG:
01165 out[reversed] = gen_rtx_REG (DImode, REGNO (in));
01166 out[!reversed] = gen_rtx_REG (DImode, REGNO (in) + 1);
01167 break;
01168
01169 case CONST_INT:
01170 case CONST_DOUBLE:
01171
01172 gcc_assert (!reversed);
01173
01174 if (GET_MODE (in) != TFmode)
01175 split_double (in, &out[0], &out[1]);
01176 else
01177
01178
01179 {
01180 REAL_VALUE_TYPE r;
01181 unsigned HOST_WIDE_INT p[2];
01182 long l[4];
01183
01184 REAL_VALUE_FROM_CONST_DOUBLE (r, in);
01185 real_to_target (l, &r, TFmode);
01186
01187 if (FLOAT_WORDS_BIG_ENDIAN)
01188 {
01189 p[0] = (((unsigned HOST_WIDE_INT) l[0]) << 32) + l[1];
01190 p[1] = (((unsigned HOST_WIDE_INT) l[2]) << 32) + l[3];
01191 }
01192 else
01193 {
01194 p[0] = (((unsigned HOST_WIDE_INT) l[3]) << 32) + l[2];
01195 p[1] = (((unsigned HOST_WIDE_INT) l[1]) << 32) + l[0];
01196 }
01197 out[0] = GEN_INT (p[0]);
01198 out[1] = GEN_INT (p[1]);
01199 }
01200 break;
01201
01202 case MEM:
01203 {
01204 rtx base = XEXP (in, 0);
01205 rtx offset;
01206
01207 switch (GET_CODE (base))
01208 {
01209 case REG:
01210 if (!reversed)
01211 {
01212 out[0] = adjust_automodify_address
01213 (in, DImode, gen_rtx_POST_INC (Pmode, base), 0);
01214 out[1] = adjust_automodify_address
01215 (in, DImode, dead ? 0 : gen_rtx_POST_DEC (Pmode, base), 8);
01216 }
01217 else
01218 {
01219
01220
01221 emit_insn (gen_adddi3 (base, base, GEN_INT (8)));
01222 out[0] = adjust_automodify_address
01223 (in, DImode, gen_rtx_POST_DEC (Pmode, base), 8);
01224 out[1] = adjust_address (in, DImode, 0);
01225 }
01226 break;
01227
01228 case POST_INC:
01229 gcc_assert (!reversed && !dead);
01230
01231
01232 out[0] = adjust_automodify_address (in, DImode, 0, 0);
01233 out[1] = adjust_automodify_address (in, DImode, 0, 8);
01234 break;
01235
01236 case POST_DEC:
01237 gcc_assert (!reversed && !dead);
01238
01239
01240 base = XEXP (base, 0);
01241 out[0] = adjust_automodify_address
01242 (in, DImode, gen_rtx_POST_INC (Pmode, base), 0);
01243 out[1] = adjust_automodify_address
01244 (in, DImode,
01245 gen_rtx_POST_MODIFY (Pmode, base, plus_constant (base, -24)),
01246 8);
01247 break;
01248
01249 case POST_MODIFY:
01250 gcc_assert (!reversed && !dead);
01251
01252
01253
01254
01255
01256
01257 offset = XEXP (base, 1);
01258 base = XEXP (base, 0);
01259
01260 out[0] = adjust_automodify_address
01261 (in, DImode, gen_rtx_POST_INC (Pmode, base), 0);
01262
01263 if (GET_CODE (XEXP (offset, 1)) == REG)
01264 {
01265
01266
01267 out[1] = adjust_automodify_address (in, DImode, 0, 8);
01268 fixup = gen_adddi3 (base, base, GEN_INT (-8));
01269 }
01270 else
01271 {
01272 gcc_assert (GET_CODE (XEXP (offset, 1)) == CONST_INT);
01273 if (INTVAL (XEXP (offset, 1)) < -256 + 8)
01274 {
01275
01276
01277
01278
01279 out[1] = adjust_automodify_address (in, DImode, base, 8);
01280 fixup = gen_adddi3
01281 (base, base, GEN_INT (INTVAL (XEXP (offset, 1)) - 8));
01282 }
01283 else
01284 {
01285
01286
01287 out[1] = adjust_automodify_address
01288 (in, DImode, gen_rtx_POST_MODIFY
01289 (Pmode, base, gen_rtx_PLUS
01290 (Pmode, base,
01291 GEN_INT (INTVAL (XEXP (offset, 1)) - 8))),
01292 8);
01293 }
01294 }
01295 break;
01296
01297 default:
01298 gcc_unreachable ();
01299 }
01300 break;
01301 }
01302
01303 default:
01304 gcc_unreachable ();
01305 }
01306
01307 return fixup;
01308 }
01309
01310
01311
01312 void
01313 ia64_split_tmode_move (rtx operands[])
01314 {
01315 rtx in[2], out[2], insn;
01316 rtx fixup[2];
01317 bool dead = false;
01318 bool reversed = false;
01319
01320
01321
01322
01323
01324
01325 if (GET_CODE (operands[1]) == MEM
01326 && reg_overlap_mentioned_p (operands[0], operands[1]))
01327 {
01328 rtx base = XEXP (operands[1], 0);
01329 while (GET_CODE (base) != REG)
01330 base = XEXP (base, 0);
01331
01332 if (REGNO (base) == REGNO (operands[0]))
01333 reversed = true;
01334 dead = true;
01335 }
01336
01337
01338
01339 if (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
01340 && REGNO (operands[0]) == REGNO (operands[1]) + 1)
01341 reversed = true;
01342
01343 fixup[0] = ia64_split_tmode (in, operands[1], reversed, dead);
01344 fixup[1] = ia64_split_tmode (out, operands[0], reversed, dead);
01345
01346 #define MAYBE_ADD_REG_INC_NOTE(INSN, EXP) \
01347 if (GET_CODE (EXP) == MEM \
01348 && (GET_CODE (XEXP (EXP, 0)) == POST_MODIFY \
01349 || GET_CODE (XEXP (EXP, 0)) == POST_INC \
01350 || GET_CODE (XEXP (EXP, 0)) == POST_DEC)) \
01351 REG_NOTES (INSN) = gen_rtx_EXPR_LIST (REG_INC, \
01352 XEXP (XEXP (EXP, 0), 0), \
01353 REG_NOTES (INSN))
01354
01355 insn = emit_insn (gen_rtx_SET (VOIDmode, out[0], in[0]));
01356 MAYBE_ADD_REG_INC_NOTE (insn, in[0]);
01357 MAYBE_ADD_REG_INC_NOTE (insn, out[0]);
01358
01359 insn = emit_insn (gen_rtx_SET (VOIDmode, out[1], in[1]));
01360 MAYBE_ADD_REG_INC_NOTE (insn, in[1]);
01361 MAYBE_ADD_REG_INC_NOTE (insn, out[1]);
01362
01363 if (fixup[0])
01364 emit_insn (fixup[0]);
01365 if (fixup[1])
01366 emit_insn (fixup[1]);
01367
01368 #undef MAYBE_ADD_REG_INC_NOTE
01369 }
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381 static rtx
01382 spill_xfmode_rfmode_operand (rtx in, int force, enum machine_mode mode)
01383 {
01384 if (GET_CODE (in) == SUBREG
01385 && GET_MODE (SUBREG_REG (in)) == TImode
01386 && GET_CODE (SUBREG_REG (in)) == REG)
01387 {
01388 rtx memt = assign_stack_temp (TImode, 16, 0);
01389 emit_move_insn (memt, SUBREG_REG (in));
01390 return adjust_address (memt, mode, 0);
01391 }
01392 else if (force && GET_CODE (in) == REG)
01393 {
01394 rtx memx = assign_stack_temp (mode, 16, 0);
01395 emit_move_insn (memx, in);
01396 return memx;
01397 }
01398 else
01399 return in;
01400 }
01401
01402
01403
01404
01405
01406 bool
01407 ia64_expand_movxf_movrf (enum machine_mode mode, rtx operands[])
01408 {
01409 rtx op0 = operands[0];
01410
01411 if (GET_CODE (op0) == SUBREG)
01412 op0 = SUBREG_REG (op0);
01413
01414
01415
01416
01417
01418
01419
01420
01421 if (GET_CODE (op0) == REG && GR_REGNO_P (REGNO (op0)))
01422 {
01423 rtx out[2];
01424
01425
01426
01427 gcc_assert (!no_new_pseudos);
01428
01429
01430 if ((GET_CODE (operands[1]) == SUBREG
01431 && GET_MODE (SUBREG_REG (operands[1])) == TImode)
01432 || (GET_CODE (operands[1]) == REG
01433 && GR_REGNO_P (REGNO (operands[1]))))
01434 {
01435 rtx op1 = operands[1];
01436
01437 if (GET_CODE (op1) == SUBREG)
01438 op1 = SUBREG_REG (op1);
01439 else
01440 op1 = gen_rtx_REG (TImode, REGNO (op1));
01441
01442 emit_move_insn (gen_rtx_REG (TImode, REGNO (op0)), op1);
01443 return true;
01444 }
01445
01446 if (GET_CODE (operands[1]) == CONST_DOUBLE)
01447 {
01448
01449 emit_move_insn (gen_rtx_REG (DImode, REGNO (op0)),
01450 operand_subword (operands[1], WORDS_BIG_ENDIAN,
01451 0, mode));
01452 emit_move_insn (gen_rtx_REG (DImode, REGNO (op0) + 1),
01453 operand_subword (operands[1], !WORDS_BIG_ENDIAN,
01454 0, mode));
01455 return true;
01456 }
01457
01458
01459 if (register_operand (operands[1], mode))
01460 operands[1] = spill_xfmode_rfmode_operand (operands[1], 1, mode);
01461
01462 gcc_assert (GET_CODE (operands[1]) == MEM);
01463
01464
01465 out[0] = gen_rtx_REG (DImode, REGNO (op0));
01466 out[1] = gen_rtx_REG (DImode, REGNO (op0) + 1);
01467
01468 emit_move_insn (out[0], adjust_address (operands[1], DImode, 0));
01469 emit_move_insn (out[1], adjust_address (operands[1], DImode, 8));
01470 return true;
01471 }
01472
01473 if (GET_CODE (operands[1]) == REG && GR_REGNO_P (REGNO (operands[1])))
01474 {
01475
01476
01477 gcc_assert (!no_new_pseudos);
01478
01479
01480
01481
01482
01483 if (register_operand (operands[0], mode))
01484 {
01485 rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
01486 op1 = gen_rtx_SUBREG (mode, op1, 0);
01487 operands[1] = spill_xfmode_rfmode_operand (op1, 0, mode);
01488 }
01489
01490 else
01491 {
01492 rtx in[2];
01493
01494 gcc_assert (GET_CODE (operands[0]) == MEM);
01495
01496
01497 in[0] = gen_rtx_REG (DImode, REGNO (operands[1]));
01498 in[1] = gen_rtx_REG (DImode, REGNO (operands[1]) + 1);
01499
01500 emit_move_insn (adjust_address (operands[0], DImode, 0), in[0]);
01501 emit_move_insn (adjust_address (operands[0], DImode, 8), in[1]);
01502 return true;
01503 }
01504 }
01505
01506 if (!reload_in_progress && !reload_completed)
01507 {
01508 operands[1] = spill_xfmode_rfmode_operand (operands[1], 0, mode);
01509
01510 if (GET_MODE (op0) == TImode && GET_CODE (op0) == REG)
01511 {
01512 rtx memt, memx, in = operands[1];
01513 if (CONSTANT_P (in))
01514 in = validize_mem (force_const_mem (mode, in));
01515 if (GET_CODE (in) == MEM)
01516 memt = adjust_address (in, TImode, 0);
01517 else
01518 {
01519 memt = assign_stack_temp (TImode, 16, 0);
01520 memx = adjust_address (memt, mode, 0);
01521 emit_move_insn (memx, in);
01522 }
01523 emit_move_insn (op0, memt);
01524 return true;
01525 }
01526
01527 if (!ia64_move_ok (operands[0], operands[1]))
01528 operands[1] = force_reg (mode, operands[1]);
01529 }
01530
01531 return false;
01532 }
01533
01534
01535
01536
01537 static GTY(()) rtx cmptf_libfunc;
01538
01539 rtx
01540 ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
01541 {
01542 rtx op0 = ia64_compare_op0, op1 = ia64_compare_op1;
01543 rtx cmp;
01544
01545
01546
01547 if (GET_MODE (op0) == BImode)
01548 {
01549 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
01550 cmp = op0;
01551 }
01552
01553
01554
01555 else if (GET_MODE (op0) == TFmode)
01556 {
01557 enum qfcmp_magic {
01558 QCMP_INV = 1,
01559 QCMP_UNORD = 2,
01560 QCMP_EQ = 4,
01561 QCMP_LT = 8,
01562 QCMP_GT = 16
01563 } magic;
01564 enum rtx_code ncode;
01565 rtx ret, insns;
01566
01567 gcc_assert (cmptf_libfunc && GET_MODE (op1) == TFmode);
01568 switch (code)
01569 {
01570
01571
01572 case EQ: magic = QCMP_EQ; ncode = NE; break;
01573 case NE: magic = QCMP_EQ; ncode = EQ; break;
01574
01575 case UNORDERED: magic = QCMP_UNORD; ncode = NE; break;
01576 case ORDERED: magic = QCMP_UNORD; ncode = EQ; break;
01577
01578
01579 case LT: magic = QCMP_LT |QCMP_INV; ncode = NE; break;
01580 case LE: magic = QCMP_LT|QCMP_EQ|QCMP_INV; ncode = NE; break;
01581 case GT: magic = QCMP_GT |QCMP_INV; ncode = NE; break;
01582 case GE: magic = QCMP_GT|QCMP_EQ|QCMP_INV; ncode = NE; break;
01583
01584
01585
01586 default: gcc_unreachable ();
01587 }
01588
01589 start_sequence ();
01590
01591 ret = emit_library_call_value (cmptf_libfunc, 0, LCT_CONST, DImode, 3,
01592 op0, TFmode, op1, TFmode,
01593 GEN_INT (magic), DImode);
01594 cmp = gen_reg_rtx (BImode);
01595 emit_insn (gen_rtx_SET (VOIDmode, cmp,
01596 gen_rtx_fmt_ee (ncode, BImode,
01597 ret, const0_rtx)));
01598
01599 insns = get_insns ();
01600 end_sequence ();
01601
01602 emit_libcall_block (insns, cmp, cmp,
01603 gen_rtx_fmt_ee (code, BImode, op0, op1));
01604 code = NE;
01605 }
01606 else
01607 {
01608 cmp = gen_reg_rtx (BImode);
01609 emit_insn (gen_rtx_SET (VOIDmode, cmp,
01610 gen_rtx_fmt_ee (code, BImode, op0, op1)));
01611 code = NE;
01612 }
01613
01614 return gen_rtx_fmt_ee (code, mode, cmp, const0_rtx);
01615 }
01616
01617
01618
01619
01620 static bool
01621 ia64_expand_vecint_compare (enum rtx_code code, enum machine_mode mode,
01622 rtx dest, rtx op0, rtx op1)
01623 {
01624 bool negate = false;
01625 rtx x;
01626
01627
01628 switch (code)
01629 {
01630 case EQ:
01631 case GT:
01632 case GTU:
01633 break;
01634
01635 case NE:
01636 case LE:
01637 case LEU:
01638 code = reverse_condition (code);
01639 negate = true;
01640 break;
01641
01642 case GE:
01643 case GEU:
01644 code = reverse_condition (code);
01645 negate = true;
01646
01647
01648 case LT:
01649 case LTU:
01650 code = swap_condition (code);
01651 x = op0, op0 = op1, op1 = x;
01652 break;
01653
01654 default:
01655 gcc_unreachable ();
01656 }
01657
01658
01659
01660 if (code == GTU)
01661 {
01662 switch (mode)
01663 {
01664 case V2SImode:
01665 {
01666 rtx t1, t2, mask;
01667
01668
01669 t1 = gen_reg_rtx (V2SImode);
01670 emit_insn (gen_subv2si3 (t1, op0, op1));
01671
01672
01673 mask = GEN_INT (-0x80000000);
01674 mask = gen_rtx_CONST_VECTOR (V2SImode, gen_rtvec (2, mask, mask));
01675 mask = force_reg (V2SImode, mask);
01676 t2 = gen_reg_rtx (V2SImode);
01677 emit_insn (gen_andv2si3 (t2, op0, mask));
01678
01679
01680
01681 x = gen_reg_rtx (V2SImode);
01682 emit_insn (gen_xorv2si3 (x, t1, t2));
01683
01684 code = GT;
01685 op0 = x;
01686 op1 = CONST0_RTX (mode);
01687 }
01688 break;
01689
01690 case V8QImode:
01691 case V4HImode:
01692
01693 x = gen_reg_rtx (mode);
01694 emit_insn (gen_rtx_SET (VOIDmode, x,
01695 gen_rtx_US_MINUS (mode, op0, op1)));
01696
01697 code = EQ;
01698 op0 = x;
01699 op1 = CONST0_RTX (mode);
01700 negate = !negate;
01701 break;
01702
01703 default:
01704 gcc_unreachable ();
01705 }
01706 }
01707
01708 x = gen_rtx_fmt_ee (code, mode, op0, op1);
01709 emit_insn (gen_rtx_SET (VOIDmode, dest, x));
01710
01711 return negate;
01712 }
01713
01714
01715
01716 void
01717 ia64_expand_vecint_cmov (rtx operands[])
01718 {
01719 enum machine_mode mode = GET_MODE (operands[0]);
01720 enum rtx_code code = GET_CODE (operands[3]);
01721 bool negate;
01722 rtx cmp, x, ot, of;
01723
01724 cmp = gen_reg_rtx (mode);
01725 negate = ia64_expand_vecint_compare (code, mode, cmp,
01726 operands[4], operands[5]);
01727
01728 ot = operands[1+negate];
01729 of = operands[2-negate];
01730
01731 if (ot == CONST0_RTX (mode))
01732 {
01733 if (of == CONST0_RTX (mode))
01734 {
01735 emit_move_insn (operands[0], ot);
01736 return;
01737 }
01738
01739 x = gen_rtx_NOT (mode, cmp);
01740 x = gen_rtx_AND (mode, x, of);
01741 emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
01742 }
01743 else if (of == CONST0_RTX (mode))
01744 {
01745 x = gen_rtx_AND (mode, cmp, ot);
01746 emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
01747 }
01748 else
01749 {
01750 rtx t, f;
01751
01752 t = gen_reg_rtx (mode);
01753 x = gen_rtx_AND (mode, cmp, operands[1+negate]);
01754 emit_insn (gen_rtx_SET (VOIDmode, t, x));
01755
01756 f = gen_reg_rtx (mode);
01757 x = gen_rtx_NOT (mode, cmp);
01758 x = gen_rtx_AND (mode, x, operands[2-negate]);
01759 emit_insn (gen_rtx_SET (VOIDmode, f, x));
01760
01761 x = gen_rtx_IOR (mode, t, f);
01762 emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
01763 }
01764 }
01765
01766
01767
01768 bool
01769 ia64_expand_vecint_minmax (enum rtx_code code, enum machine_mode mode,
01770 rtx operands[])
01771 {
01772 rtx xops[6];
01773
01774
01775 if (mode == V8QImode && (code == UMIN || code == UMAX))
01776 return false;
01777 if (mode == V4HImode && (code == SMIN || code == SMAX))
01778 return false;
01779
01780
01781 if (mode == V4HImode && code == UMAX)
01782 {
01783 rtx x, tmp = gen_reg_rtx (mode);
01784
01785 x = gen_rtx_US_MINUS (mode, operands[1], operands[2]);
01786 emit_insn (gen_rtx_SET (VOIDmode, tmp, x));
01787
01788 emit_insn (gen_addv4hi3 (operands[0], tmp, operands[2]));
01789 return true;
01790 }
01791
01792
01793 xops[0] = operands[0];
01794 xops[4] = xops[1] = operands[1];
01795 xops[5] = xops[2] = operands[2];
01796
01797 switch (code)
01798 {
01799 case UMIN:
01800 code = LTU;
01801 break;
01802 case UMAX:
01803 code = GTU;
01804 break;
01805 case SMIN:
01806 code = LT;
01807 break;
01808 case SMAX:
01809 code = GT;
01810 break;
01811 default:
01812 gcc_unreachable ();
01813 }
01814 xops[3] = gen_rtx_fmt_ee (code, VOIDmode, operands[1], operands[2]);
01815
01816 ia64_expand_vecint_cmov (xops);
01817 return true;
01818 }
01819
01820
01821
01822 void
01823 ia64_expand_widen_sum (rtx operands[3], bool unsignedp)
01824 {
01825 rtx l, h, x, s;
01826 enum machine_mode wmode, mode;
01827 rtx (*unpack_l) (rtx, rtx, rtx);
01828 rtx (*unpack_h) (rtx, rtx, rtx);
01829 rtx (*plus) (rtx, rtx, rtx);
01830
01831 wmode = GET_MODE (operands[0]);
01832 mode = GET_MODE (operands[1]);
01833
01834 switch (mode)
01835 {
01836 case V8QImode:
01837 unpack_l = gen_unpack1_l;
01838 unpack_h = gen_unpack1_h;
01839 plus = gen_addv4hi3;
01840 break;
01841 case V4HImode:
01842 unpack_l = gen_unpack2_l;
01843 unpack_h = gen_unpack2_h;
01844 plus = gen_addv2si3;
01845 break;
01846 default:
01847 gcc_unreachable ();
01848 }
01849
01850
01851 if (unsignedp)
01852 x = CONST0_RTX (mode);
01853 else
01854 {
01855 bool neg;
01856
01857 x = gen_reg_rtx (mode);
01858
01859 neg = ia64_expand_vecint_compare (LT, mode, x, operands[1],
01860 CONST0_RTX (mode));
01861 gcc_assert (!neg);
01862 }
01863
01864 l = gen_reg_rtx (wmode);
01865 h = gen_reg_rtx (wmode);
01866 s = gen_reg_rtx (wmode);
01867
01868 emit_insn (unpack_l (gen_lowpart (mode, l), operands[1], x));
01869 emit_insn (unpack_h (gen_lowpart (mode, h), operands[1], x));
01870 emit_insn (plus (s, l, operands[2]));
01871 emit_insn (plus (operands[0], h, s));
01872 }
01873
01874
01875
01876 void
01877 ia64_expand_dot_prod_v8qi (rtx operands[4], bool unsignedp)
01878 {
01879 rtx l1, l2, h1, h2, x1, x2, p1, p2, p3, p4, s1, s2, s3;
01880
01881
01882 if (unsignedp)
01883 x1 = x2 = CONST0_RTX (V8QImode);
01884 else
01885 {
01886 bool neg;
01887
01888 x1 = gen_reg_rtx (V8QImode);
01889 x2 = gen_reg_rtx (V8QImode);
01890
01891 neg = ia64_expand_vecint_compare (LT, V8QImode, x1, operands[1],
01892 CONST0_RTX (V8QImode));
01893 gcc_assert (!neg);
01894 neg = ia64_expand_vecint_compare (LT, V8QImode, x2, operands[2],
01895 CONST0_RTX (V8QImode));
01896 gcc_assert (!neg);
01897 }
01898
01899 l1 = gen_reg_rtx (V4HImode);
01900 l2 = gen_reg_rtx (V4HImode);
01901 h1 = gen_reg_rtx (V4HImode);
01902 h2 = gen_reg_rtx (V4HImode);
01903
01904 emit_insn (gen_unpack1_l (gen_lowpart (V8QImode, l1), operands[1], x1));
01905 emit_insn (gen_unpack1_l (gen_lowpart (V8QImode, l2), operands[2], x2));
01906 emit_insn (gen_unpack1_h (gen_lowpart (V8QImode, h1), operands[1], x1));
01907 emit_insn (gen_unpack1_h (gen_lowpart (V8QImode, h2), operands[2], x2));
01908
01909 p1 = gen_reg_rtx (V2SImode);
01910 p2 = gen_reg_rtx (V2SImode);
01911 p3 = gen_reg_rtx (V2SImode);
01912 p4 = gen_reg_rtx (V2SImode);
01913 emit_insn (gen_pmpy2_r (p1, l1, l2));
01914 emit_insn (gen_pmpy2_l (p2, l1, l2));
01915 emit_insn (gen_pmpy2_r (p3, h1, h2));
01916 emit_insn (gen_pmpy2_l (p4, h1, h2));
01917
01918 s1 = gen_reg_rtx (V2SImode);
01919 s2 = gen_reg_rtx (V2SImode);
01920 s3 = gen_reg_rtx (V2SImode);
01921 emit_insn (gen_addv2si3 (s1, p1, p2));
01922 emit_insn (gen_addv2si3 (s2, p3, p4));
01923 emit_insn (gen_addv2si3 (s3, s1, operands[3]));
01924 emit_insn (gen_addv2si3 (operands[0], s2, s3));
01925 }
01926
01927
01928
01929 void
01930 ia64_expand_call (rtx retval, rtx addr, rtx nextarg ATTRIBUTE_UNUSED,
01931 int sibcall_p)
01932 {
01933 rtx insn, b0;
01934
01935 addr = XEXP (addr, 0);
01936 addr = convert_memory_address (DImode, addr);
01937 b0 = gen_rtx_REG (DImode, R_BR (0));
01938
01939
01940 if (TARGET_NO_PIC || TARGET_AUTO_PIC)
01941 {
01942 if (sibcall_p)
01943 insn = gen_sibcall_nogp (addr);
01944 else if (! retval)
01945 insn = gen_call_nogp (addr, b0);
01946 else
01947 insn = gen_call_value_nogp (retval, addr, b0);
01948 insn = emit_call_insn (insn);
01949 }
01950 else
01951 {
01952 if (sibcall_p)
01953 insn = gen_sibcall_gp (addr);
01954 else if (! retval)
01955 insn = gen_call_gp (addr, b0);
01956 else
01957 insn = gen_call_value_gp (retval, addr, b0);
01958 insn = emit_call_insn (insn);
01959
01960 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
01961 }
01962
01963 if (sibcall_p)
01964 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), b0);
01965 }
01966
01967 void
01968 ia64_reload_gp (void)
01969 {
01970 rtx tmp;
01971
01972 if (current_frame_info.reg_save_gp)
01973 tmp = gen_rtx_REG (DImode, current_frame_info.reg_save_gp);
01974 else
01975 {
01976 HOST_WIDE_INT offset;
01977
01978 offset = (current_frame_info.spill_cfa_off
01979 + current_frame_info.spill_size);
01980 if (frame_pointer_needed)
01981 {
01982 tmp = hard_frame_pointer_rtx;
01983 offset = -offset;
01984 }
01985 else
01986 {
01987 tmp = stack_pointer_rtx;
01988 offset = current_frame_info.total_size - offset;
01989 }
01990
01991 if (CONST_OK_FOR_I (offset))
01992 emit_insn (gen_adddi3 (pic_offset_table_rtx,
01993 tmp, GEN_INT (offset)));
01994 else
01995 {
01996 emit_move_insn (pic_offset_table_rtx, GEN_INT (offset));
01997 emit_insn (gen_adddi3 (pic_offset_table_rtx,
01998 pic_offset_table_rtx, tmp));
01999 }
02000
02001 tmp = gen_rtx_MEM (DImode, pic_offset_table_rtx);
02002 }
02003
02004 emit_move_insn (pic_offset_table_rtx, tmp);
02005 }
02006
02007 void
02008 ia64_split_call (rtx retval, rtx addr, rtx retaddr, rtx scratch_r,
02009 rtx scratch_b, int noreturn_p, int sibcall_p)
02010 {
02011 rtx insn;
02012 bool is_desc = false;
02013
02014
02015
02016 if (REG_P (addr) && GR_REGNO_P (REGNO (addr)))
02017 {
02018 rtx tmp;
02019 bool addr_dead_p;
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033 addr_dead_p = ((noreturn_p || sibcall_p
02034 || TEST_HARD_REG_BIT (regs_invalidated_by_call,
02035 REGNO (addr)))
02036 && !FUNCTION_ARG_REGNO_P (REGNO (addr)));
02037
02038
02039 tmp = gen_rtx_POST_INC (Pmode, addr);
02040 tmp = gen_rtx_MEM (Pmode, tmp);
02041 emit_move_insn (scratch_r, tmp);
02042 emit_move_insn (scratch_b, scratch_r);
02043
02044
02045
02046 if (!addr_dead_p)
02047 tmp = gen_rtx_POST_DEC (Pmode, addr);
02048 else
02049 tmp = addr;
02050 tmp = gen_rtx_MEM (Pmode, tmp);
02051 emit_move_insn (pic_offset_table_rtx, tmp);
02052
02053 is_desc = true;
02054 addr = scratch_b;
02055 }
02056
02057 if (sibcall_p)
02058 insn = gen_sibcall_nogp (addr);
02059 else if (retval)
02060 insn = gen_call_value_nogp (retval, addr, retaddr);
02061 else
02062 insn = gen_call_nogp (addr, retaddr);
02063 emit_call_insn (insn);
02064
02065 if ((!TARGET_CONST_GP || is_desc) && !noreturn_p && !sibcall_p)
02066 ia64_reload_gp ();
02067 }
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088 void
02089 ia64_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
02090 rtx old_dst, rtx new_dst)
02091 {
02092 enum machine_mode mode = GET_MODE (mem);
02093 rtx old_reg, new_reg, cmp_reg, ar_ccv, label;
02094 enum insn_code icode;
02095
02096
02097 if ((mode == SImode || mode == DImode)
02098 && (code == PLUS || code == MINUS)
02099 && fetchadd_operand (val, mode))
02100 {
02101 if (code == MINUS)
02102 val = GEN_INT (-INTVAL (val));
02103
02104 if (!old_dst)
02105 old_dst = gen_reg_rtx (mode);
02106
02107 emit_insn (gen_memory_barrier ());
02108
02109 if (mode == SImode)
02110 icode = CODE_FOR_fetchadd_acq_si;
02111 else
02112 icode = CODE_FOR_fetchadd_acq_di;
02113 emit_insn (GEN_FCN (icode) (old_dst, mem, val));
02114
02115 if (new_dst)
02116 {
02117 new_reg = expand_simple_binop (mode, PLUS, old_dst, val, new_dst,
02118 true, OPTAB_WIDEN);
02119 if (new_reg != new_dst)
02120 emit_move_insn (new_dst, new_reg);
02121 }
02122 return;
02123 }
02124
02125
02126
02127 gcc_assert (MEM_VOLATILE_P (mem));
02128
02129 old_reg = gen_reg_rtx (DImode);
02130 cmp_reg = gen_reg_rtx (DImode);
02131 label = gen_label_rtx ();
02132
02133 if (mode != DImode)
02134 {
02135 val = simplify_gen_subreg (DImode, val, mode, 0);
02136 emit_insn (gen_extend_insn (cmp_reg, mem, DImode, mode, 1));
02137 }
02138 else
02139 emit_move_insn (cmp_reg, mem);
02140
02141 emit_label (label);
02142
02143 ar_ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
02144 emit_move_insn (old_reg, cmp_reg);
02145 emit_move_insn (ar_ccv, cmp_reg);
02146
02147 if (old_dst)
02148 emit_move_insn (old_dst, gen_lowpart (mode, cmp_reg));
02149
02150 new_reg = cmp_reg;
02151 if (code == NOT)
02152 {
02153 new_reg = expand_simple_unop (DImode, NOT, new_reg, NULL_RTX, true);
02154 code = AND;
02155 }
02156 new_reg = expand_simple_binop (DImode, code, new_reg, val, NULL_RTX,
02157 true, OPTAB_DIRECT);
02158
02159 if (mode != DImode)
02160 new_reg = gen_lowpart (mode, new_reg);
02161 if (new_dst)
02162 emit_move_insn (new_dst, new_reg);
02163
02164 switch (mode)
02165 {
02166 case QImode: icode = CODE_FOR_cmpxchg_rel_qi; break;
02167 case HImode: icode = CODE_FOR_cmpxchg_rel_hi; break;
02168 case SImode: icode = CODE_FOR_cmpxchg_rel_si; break;
02169 case DImode: icode = CODE_FOR_cmpxchg_rel_di; break;
02170 default:
02171 gcc_unreachable ();
02172 }
02173
02174 emit_insn (GEN_FCN (icode) (cmp_reg, mem, ar_ccv, new_reg));
02175
02176 emit_cmp_and_jump_insns (cmp_reg, old_reg, NE, NULL, DImode, true, label);
02177 }
02178
02179
02180
02181 static void
02182 ia64_file_start (void)
02183 {
02184
02185
02186
02187
02188 ia64_flag_var_tracking = flag_var_tracking;
02189 flag_var_tracking = 0;
02190
02191 default_file_start ();
02192 emit_safe_across_calls ();
02193 }
02194
02195 void
02196 emit_safe_across_calls (void)
02197 {
02198 unsigned int rs, re;
02199 int out_state;
02200
02201 rs = 1;
02202 out_state = 0;
02203 while (1)
02204 {
02205 while (rs < 64 && call_used_regs[PR_REG (rs)])
02206 rs++;
02207 if (rs >= 64)
02208 break;
02209 for (re = rs + 1; re < 64 && ! call_used_regs[PR_REG (re)]; re++)
02210 continue;
02211 if (out_state == 0)
02212 {
02213 fputs ("\t.pred.safe_across_calls ", asm_out_file);
02214 out_state = 1;
02215 }
02216 else
02217 fputc (',', asm_out_file);
02218 if (re == rs + 1)
02219 fprintf (asm_out_file, "p%u", rs);
02220 else
02221 fprintf (asm_out_file, "p%u-p%u", rs, re - 1);
02222 rs = re + 1;
02223 }
02224 if (out_state)
02225 fputc ('\n', asm_out_file);
02226 }
02227
02228
02229
02230
02231
02232
02233 static int
02234 find_gr_spill (int try_locals)
02235 {
02236 int regno;
02237
02238
02239
02240 if (current_function_is_leaf)
02241 {
02242 for (regno = GR_REG (1); regno <= GR_REG (31); regno++)
02243 if (! regs_ever_live[regno]
02244 && call_used_regs[regno]
02245 && ! fixed_regs[regno]
02246 && ! global_regs[regno]
02247 && ((current_frame_info.gr_used_mask >> regno) & 1) == 0)
02248 {
02249 current_frame_info.gr_used_mask |= 1 << regno;
02250 return regno;
02251 }
02252 }
02253
02254 if (try_locals)
02255 {
02256 regno = current_frame_info.n_local_regs;
02257
02258
02259
02260 if (regno < (80 - frame_pointer_needed))
02261 {
02262 current_frame_info.n_local_regs = regno + 1;
02263 return LOC_REG (0) + regno;
02264 }
02265 }
02266
02267
02268 return 0;
02269 }
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280 static int last_scratch_gr_reg;
02281
02282 static int
02283 next_scratch_gr_reg (void)
02284 {
02285 int i, regno;
02286
02287 for (i = 0; i < 32; ++i)
02288 {
02289 regno = (last_scratch_gr_reg + i + 1) & 31;
02290 if (call_used_regs[regno]
02291 && ! fixed_regs[regno]
02292 && ! global_regs[regno]
02293 && ((current_frame_info.gr_used_mask >> regno) & 1) == 0)
02294 {
02295 last_scratch_gr_reg = regno;
02296 return regno;
02297 }
02298 }
02299
02300
02301 gcc_unreachable ();
02302 }
02303
02304
02305
02306
02307 static void
02308 mark_reg_gr_used_mask (rtx reg, void *data ATTRIBUTE_UNUSED)
02309 {
02310 unsigned int regno = REGNO (reg);
02311 if (regno < 32)
02312 {
02313 unsigned int i, n = hard_regno_nregs[regno][GET_MODE (reg)];
02314 for (i = 0; i < n; ++i)
02315 current_frame_info.gr_used_mask |= 1 << (regno + i);
02316 }
02317 }
02318
02319
02320
02321
02322
02323 static void
02324 ia64_compute_frame_size (HOST_WIDE_INT size)
02325 {
02326 HOST_WIDE_INT total_size;
02327 HOST_WIDE_INT spill_size = 0;
02328 HOST_WIDE_INT extra_spill_size = 0;
02329 HOST_WIDE_INT pretend_args_size;
02330 HARD_REG_SET mask;
02331 int n_spilled = 0;
02332 int spilled_gr_p = 0;
02333 int spilled_fr_p = 0;
02334 unsigned int regno;
02335 int i;
02336
02337 if (current_frame_info.initialized)
02338 return;
02339
02340 memset (¤t_frame_info, 0, sizeof current_frame_info);
02341 CLEAR_HARD_REG_SET (mask);
02342
02343
02344 diddle_return_value (mark_reg_gr_used_mask, NULL);
02345
02346
02347 if (cfun->machine->ia64_eh_epilogue_sp)
02348 mark_reg_gr_used_mask (cfun->machine->ia64_eh_epilogue_sp, NULL);
02349 if (cfun->machine->ia64_eh_epilogue_bsp)
02350 mark_reg_gr_used_mask (cfun->machine->ia64_eh_epilogue_bsp, NULL);
02351
02352
02353
02354
02355
02356
02357
02358 regno = LOC_REG (78) + ! frame_pointer_needed;
02359 for (; regno >= LOC_REG (0); regno--)
02360 if (regs_ever_live[regno])
02361 break;
02362 current_frame_info.n_local_regs = regno - LOC_REG (0) + 1;
02363
02364
02365
02366
02367
02368 if (cfun->machine->n_varargs > 0
02369 || lookup_attribute ("syscall_linkage",
02370 TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
02371 current_frame_info.n_input_regs = 8;
02372 else
02373 {
02374 for (regno = IN_REG (7); regno >= IN_REG (0); regno--)
02375 if (regs_ever_live[regno])
02376 break;
02377 current_frame_info.n_input_regs = regno - IN_REG (0) + 1;
02378 }
02379
02380 for (regno = OUT_REG (7); regno >= OUT_REG (0); regno--)
02381 if (regs_ever_live[regno])
02382 break;
02383 i = regno - OUT_REG (0) + 1;
02384
02385 #ifndef PROFILE_HOOK
02386
02387
02388
02389
02390 if (current_function_profile)
02391 i = MAX (i, 1);
02392 #endif
02393 current_frame_info.n_output_regs = i;
02394
02395
02396 current_frame_info.n_rotate_regs = 0;
02397
02398
02399
02400
02401
02402 for (regno = FR_REG (2); regno <= FR_REG (127); regno++)
02403 if (regs_ever_live[regno] && ! call_used_regs[regno])
02404 {
02405 SET_HARD_REG_BIT (mask, regno);
02406 spill_size += 16;
02407 n_spilled += 1;
02408 spilled_fr_p = 1;
02409 }
02410
02411 for (regno = GR_REG (1); regno <= GR_REG (31); regno++)
02412 if (regs_ever_live[regno] && ! call_used_regs[regno])
02413 {
02414 SET_HARD_REG_BIT (mask, regno);
02415 spill_size += 8;
02416 n_spilled += 1;
02417 spilled_gr_p = 1;
02418 }
02419
02420 for (regno = BR_REG (1); regno <= BR_REG (7); regno++)
02421 if (regs_ever_live[regno] && ! call_used_regs[regno])
02422 {
02423 SET_HARD_REG_BIT (mask, regno);
02424 spill_size += 8;
02425 n_spilled += 1;
02426 }
02427
02428
02429
02430
02431 if (frame_pointer_needed)
02432 {
02433 current_frame_info.reg_fp = find_gr_spill (1);
02434
02435
02436
02437
02438 if (current_frame_info.reg_fp == 0)
02439 {
02440 current_frame_info.reg_fp = LOC_REG (79);
02441 current_frame_info.n_local_regs++;
02442 }
02443 }
02444
02445 if (! current_function_is_leaf)
02446 {
02447
02448
02449
02450 SET_HARD_REG_BIT (mask, BR_REG (0));
02451
02452 current_frame_info.reg_save_b0 = find_gr_spill (1);
02453 if (current_frame_info.reg_save_b0 == 0)
02454 {
02455 extra_spill_size += 8;
02456 n_spilled += 1;
02457 }
02458
02459
02460 SET_HARD_REG_BIT (mask, AR_PFS_REGNUM);
02461 current_frame_info.reg_save_ar_pfs = find_gr_spill (1);
02462 if (current_frame_info.reg_save_ar_pfs == 0)
02463 {
02464 extra_spill_size += 8;
02465 n_spilled += 1;
02466 }
02467
02468
02469
02470 current_frame_info.reg_save_gp
02471 = (current_function_calls_setjmp ? 0 : find_gr_spill (1));
02472 if (current_frame_info.reg_save_gp == 0)
02473 {
02474 SET_HARD_REG_BIT (mask, GR_REG (1));
02475 spill_size += 8;
02476 n_spilled += 1;
02477 }
02478 }
02479 else
02480 {
02481 if (regs_ever_live[BR_REG (0)] && ! call_used_regs[BR_REG (0)])
02482 {
02483 SET_HARD_REG_BIT (mask, BR_REG (0));
02484 extra_spill_size += 8;
02485 n_spilled += 1;
02486 }
02487
02488 if (regs_ever_live[AR_PFS_REGNUM])
02489 {
02490 SET_HARD_REG_BIT (mask, AR_PFS_REGNUM);
02491 current_frame_info.reg_save_ar_pfs = find_gr_spill (1);
02492 if (current_frame_info.reg_save_ar_pfs == 0)
02493 {
02494 extra_spill_size += 8;
02495 n_spilled += 1;
02496 }
02497 }
02498 }
02499
02500
02501
02502
02503
02504
02505
02506 if (current_frame_info.reg_fp != 0
02507 && current_frame_info.reg_save_b0 == current_frame_info.reg_fp + 1
02508 && current_frame_info.reg_save_ar_pfs == current_frame_info.reg_fp + 2)
02509 {
02510 current_frame_info.reg_save_b0 = current_frame_info.reg_fp;
02511 current_frame_info.reg_save_ar_pfs = current_frame_info.reg_fp + 1;
02512 current_frame_info.reg_fp = current_frame_info.reg_fp + 2;
02513 }
02514
02515
02516 for (regno = PR_REG (0); regno <= PR_REG (63); regno++)
02517 if (regs_ever_live[regno] && ! call_used_regs[regno])
02518 break;
02519 if (regno <= PR_REG (63))
02520 {
02521 SET_HARD_REG_BIT (mask, PR_REG (0));
02522 current_frame_info.reg_save_pr = find_gr_spill (1);
02523 if (current_frame_info.reg_save_pr == 0)
02524 {
02525 extra_spill_size += 8;
02526 n_spilled += 1;
02527 }
02528
02529
02530
02531 for (regno = PR_REG (0); regno <= PR_REG (63); regno++)
02532 regs_ever_live[regno] = 1;
02533 }
02534
02535
02536
02537
02538 if (spilled_gr_p || cfun->machine->n_varargs
02539 || regs_ever_live[AR_UNAT_REGNUM])
02540 {
02541 regs_ever_live[AR_UNAT_REGNUM] = 1;
02542 SET_HARD_REG_BIT (mask, AR_UNAT_REGNUM);
02543 current_frame_info.reg_save_ar_unat = find_gr_spill (spill_size == 0);
02544 if (current_frame_info.reg_save_ar_unat == 0)
02545 {
02546 extra_spill_size += 8;
02547 n_spilled += 1;
02548 }
02549 }
02550
02551 if (regs_ever_live[AR_LC_REGNUM])
02552 {
02553 SET_HARD_REG_BIT (mask, AR_LC_REGNUM);
02554 current_frame_info.reg_save_ar_lc = find_gr_spill (spill_size == 0);
02555 if (current_frame_info.reg_save_ar_lc == 0)
02556 {
02557 extra_spill_size += 8;
02558 n_spilled += 1;
02559 }
02560 }
02561
02562
02563
02564
02565 if (spilled_fr_p)
02566 pretend_args_size = IA64_STACK_ALIGN (current_function_pretend_args_size);
02567 else
02568 pretend_args_size = current_function_pretend_args_size;
02569
02570 total_size = (spill_size + extra_spill_size + size + pretend_args_size
02571 + current_function_outgoing_args_size);
02572 total_size = IA64_STACK_ALIGN (total_size);
02573
02574
02575
02576
02577 if (current_function_is_leaf)
02578 total_size = MAX (0, total_size - 16);
02579
02580 current_frame_info.total_size = total_size;
02581 current_frame_info.spill_cfa_off = pretend_args_size - 16;
02582 current_frame_info.spill_size = spill_size;
02583 current_frame_info.extra_spill_size = extra_spill_size;
02584 COPY_HARD_REG_SET (current_frame_info.mask, mask);
02585 current_frame_info.n_spilled = n_spilled;
02586 current_frame_info.initialized = reload_completed;
02587 }
02588
02589
02590
02591 HOST_WIDE_INT
02592 ia64_initial_elimination_offset (int from, int to)
02593 {
02594 HOST_WIDE_INT offset;
02595
02596 ia64_compute_frame_size (get_frame_size ());
02597 switch (from)
02598 {
02599 case FRAME_POINTER_REGNUM:
02600 switch (to)
02601 {
02602 case HARD_FRAME_POINTER_REGNUM:
02603 if (current_function_is_leaf)
02604 offset = -current_frame_info.total_size;
02605 else
02606 offset = -(current_frame_info.total_size
02607 - current_function_outgoing_args_size - 16);
02608 break;
02609
02610 case STACK_POINTER_REGNUM:
02611 if (current_function_is_leaf)
02612 offset = 0;
02613 else
02614 offset = 16 + current_function_outgoing_args_size;
02615 break;
02616
02617 default:
02618 gcc_unreachable ();
02619 }
02620 break;
02621
02622 case ARG_POINTER_REGNUM:
02623
02624
02625 switch (to)
02626 {
02627 case HARD_FRAME_POINTER_REGNUM:
02628 offset = 16 - current_function_pretend_args_size;
02629 break;
02630
02631 case STACK_POINTER_REGNUM:
02632 offset = (current_frame_info.total_size
02633 + 16 - current_function_pretend_args_size);
02634 break;
02635
02636 default:
02637 gcc_unreachable ();
02638 }
02639 break;
02640
02641 default:
02642 gcc_unreachable ();
02643 }
02644
02645 return offset;
02646 }
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658 struct spill_fill_data
02659 {
02660 rtx init_after;
02661 rtx init_reg[2];
02662 rtx iter_reg[2];
02663 rtx *prev_addr[2];
02664 rtx prev_insn[2];
02665 HOST_WIDE_INT prev_off[2];
02666 int n_iter;
02667 int next_iter;
02668 unsigned int save_gr_used_mask;
02669 };
02670
02671 static struct spill_fill_data spill_fill_data;
02672
02673 static void
02674 setup_spill_pointers (int n_spills, rtx init_reg, HOST_WIDE_INT cfa_off)
02675 {
02676 int i;
02677
02678 spill_fill_data.init_after = get_last_insn ();
02679 spill_fill_data.init_reg[0] = init_reg;
02680 spill_fill_data.init_reg[1] = init_reg;
02681 spill_fill_data.prev_addr[0] = NULL;
02682 spill_fill_data.prev_addr[1] = NULL;
02683 spill_fill_data.prev_insn[0] = NULL;
02684 spill_fill_data.prev_insn[1] = NULL;
02685 spill_fill_data.prev_off[0] = cfa_off;
02686 spill_fill_data.prev_off[1] = cfa_off;
02687 spill_fill_data.next_iter = 0;
02688 spill_fill_data.save_gr_used_mask = current_frame_info.gr_used_mask;
02689
02690 spill_fill_data.n_iter = 1 + (n_spills > 2);
02691 for (i = 0; i < spill_fill_data.n_iter; ++i)
02692 {
02693 int regno = next_scratch_gr_reg ();
02694 spill_fill_data.iter_reg[i] = gen_rtx_REG (DImode, regno);
02695 current_frame_info.gr_used_mask |= 1 << regno;
02696 }
02697 }
02698
02699 static void
02700 finish_spill_pointers (void)
02701 {
02702 current_frame_info.gr_used_mask = spill_fill_data.save_gr_used_mask;
02703 }
02704
02705 static rtx
02706 spill_restore_mem (rtx reg, HOST_WIDE_INT cfa_off)
02707 {
02708 int iter = spill_fill_data.next_iter;
02709 HOST_WIDE_INT disp = spill_fill_data.prev_off[iter] - cfa_off;
02710 rtx disp_rtx = GEN_INT (disp);
02711 rtx mem;
02712
02713 if (spill_fill_data.prev_addr[iter])
02714 {
02715 if (CONST_OK_FOR_N (disp))
02716 {
02717 *spill_fill_data.prev_addr[iter]
02718 = gen_rtx_POST_MODIFY (DImode, spill_fill_data.iter_reg[iter],
02719 gen_rtx_PLUS (DImode,
02720 spill_fill_data.iter_reg[iter],
02721 disp_rtx));
02722 REG_NOTES (spill_fill_data.prev_insn[iter])
02723 = gen_rtx_EXPR_LIST (REG_INC, spill_fill_data.iter_reg[iter],
02724 REG_NOTES (spill_fill_data.prev_insn[iter]));
02725 }
02726 else
02727 {
02728
02729 if (! CONST_OK_FOR_I (disp))
02730 {
02731 rtx tmp = gen_rtx_REG (DImode, next_scratch_gr_reg ());
02732 emit_move_insn (tmp, disp_rtx);
02733 disp_rtx = tmp;
02734 }
02735 emit_insn (gen_adddi3 (spill_fill_data.iter_reg[iter],
02736 spill_fill_data.iter_reg[iter], disp_rtx));
02737 }
02738 }
02739
02740
02741
02742
02743 else if (disp == 0
02744 && spill_fill_data.init_reg[iter] == stack_pointer_rtx
02745 && frame_pointer_needed)
02746 {
02747 mem = gen_rtx_MEM (GET_MODE (reg), hard_frame_pointer_rtx);
02748 set_mem_alias_set (mem, get_varargs_alias_set ());
02749 return mem;
02750 }
02751 else
02752 {
02753 rtx seq, insn;
02754
02755 if (disp == 0)
02756 seq = gen_movdi (spill_fill_data.iter_reg[iter],
02757 spill_fill_data.init_reg[iter]);
02758 else
02759 {
02760 start_sequence ();
02761
02762 if (! CONST_OK_FOR_I (disp))
02763 {
02764 rtx tmp = gen_rtx_REG (DImode, next_scratch_gr_reg ());
02765 emit_move_insn (tmp, disp_rtx);
02766 disp_rtx = tmp;
02767 }
02768
02769 emit_insn (gen_adddi3 (spill_fill_data.iter_reg[iter],
02770 spill_fill_data.init_reg[iter],
02771 disp_rtx));
02772
02773 seq = get_insns ();
02774 end_sequence ();
02775 }
02776
02777
02778 if (spill_fill_data.init_after)
02779 insn = emit_insn_after (seq, spill_fill_data.init_after);
02780 else
02781 {
02782 rtx first = get_insns ();
02783 if (first)
02784 insn = emit_insn_before (seq, first);
02785 else
02786 insn = emit_insn (seq);
02787 }
02788 spill_fill_data.init_after = insn;
02789
02790
02791
02792
02793
02794
02795
02796 if (disp == 0)
02797 REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
02798 REG_NOTES (insn));
02799 }
02800
02801 mem = gen_rtx_MEM (GET_MODE (reg), spill_fill_data.iter_reg[iter]);
02802
02803
02804
02805
02806 set_mem_alias_set (mem, get_varargs_alias_set ());
02807
02808 spill_fill_data.prev_addr[iter] = &XEXP (mem, 0);
02809 spill_fill_data.prev_off[iter] = cfa_off;
02810
02811 if (++iter >= spill_fill_data.n_iter)
02812 iter = 0;
02813 spill_fill_data.next_iter = iter;
02814
02815 return mem;
02816 }
02817
02818 static void
02819 do_spill (rtx (*move_fn) (rtx, rtx, rtx), rtx reg, HOST_WIDE_INT cfa_off,
02820 rtx frame_reg)
02821 {
02822 int iter = spill_fill_data.next_iter;
02823 rtx mem, insn;
02824
02825 mem = spill_restore_mem (reg, cfa_off);
02826 insn = emit_insn ((*move_fn) (mem, reg, GEN_INT (cfa_off)));
02827 spill_fill_data.prev_insn[iter] = insn;
02828
02829 if (frame_reg)
02830 {
02831 rtx base;
02832 HOST_WIDE_INT off;
02833
02834 RTX_FRAME_RELATED_P (insn) = 1;
02835
02836
02837
02838
02839
02840 if (frame_pointer_needed)
02841 {
02842 base = hard_frame_pointer_rtx;
02843 off = - cfa_off;
02844 }
02845 else
02846 {
02847 base = stack_pointer_rtx;
02848 off = current_frame_info.total_size - cfa_off;
02849 }
02850
02851 REG_NOTES (insn)
02852 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
02853 gen_rtx_SET (VOIDmode,
02854 gen_rtx_MEM (GET_MODE (reg),
02855 plus_constant (base, off)),
02856 frame_reg),
02857 REG_NOTES (insn));
02858 }
02859 }
02860
02861 static void
02862 do_restore (rtx (*move_fn) (rtx, rtx, rtx), rtx reg, HOST_WIDE_INT cfa_off)
02863 {
02864 int iter = spill_fill_data.next_iter;
02865 rtx insn;
02866
02867 insn = emit_insn ((*move_fn) (reg, spill_restore_mem (reg, cfa_off),
02868 GEN_INT (cfa_off)));
02869 spill_fill_data.prev_insn[iter] = insn;
02870 }
02871
02872
02873
02874
02875
02876 static rtx
02877 gen_movdi_x (rtx dest, rtx src, rtx offset ATTRIBUTE_UNUSED)
02878 {
02879 return gen_movdi (dest, src);
02880 }
02881
02882 static rtx
02883 gen_fr_spill_x (rtx dest, rtx src, rtx offset ATTRIBUTE_UNUSED)
02884 {
02885 return gen_fr_spill (dest, src);
02886 }
02887
02888 static rtx
02889 gen_fr_restore_x (rtx dest, rtx src, rtx offset ATTRIBUTE_UNUSED)
02890 {
02891 return gen_fr_restore (dest, src);
02892 }
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914
02915
02916 void
02917 ia64_expand_prologue (void)
02918 {
02919 rtx insn, ar_pfs_save_reg, ar_unat_save_reg;
02920 int i, epilogue_p, regno, alt_regno, cfa_off, n_varargs;
02921 rtx reg, alt_reg;
02922
02923 ia64_compute_frame_size (get_frame_size ());
02924 last_scratch_gr_reg = 15;
02925
02926
02927
02928
02929 if (optimize)
02930 {
02931 edge e;
02932 edge_iterator ei;
02933
02934 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
02935 if ((e->flags & EDGE_FAKE) == 0
02936 && (e->flags & EDGE_FALLTHRU) != 0)
02937 break;
02938 epilogue_p = (e != NULL);
02939 }
02940 else
02941 epilogue_p = 1;
02942
02943
02944
02945
02946
02947 if (! TARGET_REG_NAMES)
02948 {
02949 int inputs = current_frame_info.n_input_regs;
02950 int locals = current_frame_info.n_local_regs;
02951 int outputs = current_frame_info.n_output_regs;
02952
02953 for (i = 0; i < inputs; i++)
02954 reg_names[IN_REG (i)] = ia64_reg_numbers[i];
02955 for (i = 0; i < locals; i++)
02956 reg_names[LOC_REG (i)] = ia64_reg_numbers[inputs + i];
02957 for (i = 0; i < outputs; i++)
02958 reg_names[OUT_REG (i)] = ia64_reg_numbers[inputs + locals + i];
02959 }
02960
02961
02962
02963
02964
02965
02966
02967
02968 if (current_frame_info.reg_fp)
02969 {
02970 const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM];
02971 reg_names[HARD_FRAME_POINTER_REGNUM]
02972 = reg_names[current_frame_info.reg_fp];
02973 reg_names[current_frame_info.reg_fp] = tmp;
02974 }
02975
02976
02977 if (current_frame_info.n_local_regs == 0
02978 && current_frame_info.n_output_regs == 0
02979 && current_frame_info.n_input_regs <= current_function_args_info.int_regs
02980 && !TEST_HARD_REG_BIT (current_frame_info.mask, AR_PFS_REGNUM))
02981 {
02982
02983
02984 current_frame_info.need_regstk = (TARGET_REG_NAMES != 0);
02985 ar_pfs_save_reg = NULL_RTX;
02986 }
02987 else
02988 {
02989 current_frame_info.need_regstk = 0;
02990
02991 if (current_frame_info.reg_save_ar_pfs)
02992 regno = current_frame_info.reg_save_ar_pfs;
02993 else
02994 regno = next_scratch_gr_reg ();
02995 ar_pfs_save_reg = gen_rtx_REG (DImode, regno);
02996
02997 insn = emit_insn (gen_alloc (ar_pfs_save_reg,
02998 GEN_INT (current_frame_info.n_input_regs),
02999 GEN_INT (current_frame_info.n_local_regs),
03000 GEN_INT (current_frame_info.n_output_regs),
03001 GEN_INT (current_frame_info.n_rotate_regs)));
03002 RTX_FRAME_RELATED_P (insn) = (current_frame_info.reg_save_ar_pfs != 0);
03003 }
03004
03005
03006
03007 n_varargs = cfun->machine->n_varargs;
03008 setup_spill_pointers (current_frame_info.n_spilled + n_varargs,
03009 stack_pointer_rtx, 0);
03010
03011 if (frame_pointer_needed)
03012 {
03013 insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
03014 RTX_FRAME_RELATED_P (insn) = 1;
03015 }
03016
03017 if (current_frame_info.total_size != 0)
03018 {
03019 rtx frame_size_rtx = GEN_INT (- current_frame_info.total_size);
03020 rtx offset;
03021
03022 if (CONST_OK_FOR_I (- current_frame_info.total_size))
03023 offset = frame_size_rtx;
03024 else
03025 {
03026 regno = next_scratch_gr_reg ();
03027 offset = gen_rtx_REG (DImode, regno);
03028 emit_move_insn (offset, frame_size_rtx);
03029 }
03030
03031 insn = emit_insn (gen_adddi3 (stack_pointer_rtx,
03032 stack_pointer_rtx, offset));
03033
03034 if (! frame_pointer_needed)
03035 {
03036 RTX_FRAME_RELATED_P (insn) = 1;
03037 if (GET_CODE (offset) != CONST_INT)
03038 {
03039 REG_NOTES (insn)
03040 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03041 gen_rtx_SET (VOIDmode,
03042 stack_pointer_rtx,
03043 gen_rtx_PLUS (DImode,
03044 stack_pointer_rtx,
03045 frame_size_rtx)),
03046 REG_NOTES (insn));
03047 }
03048 }
03049
03050
03051
03052
03053
03054 emit_insn (gen_blockage ());
03055 }
03056
03057
03058 if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM))
03059 {
03060 if (current_frame_info.reg_save_ar_unat)
03061 ar_unat_save_reg
03062 = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_unat);
03063 else
03064 {
03065 alt_regno = next_scratch_gr_reg ();
03066 ar_unat_save_reg = gen_rtx_REG (DImode, alt_regno);
03067 current_frame_info.gr_used_mask |= 1 << alt_regno;
03068 }
03069
03070 reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM);
03071 insn = emit_move_insn (ar_unat_save_reg, reg);
03072 RTX_FRAME_RELATED_P (insn) = (current_frame_info.reg_save_ar_unat != 0);
03073
03074
03075
03076 if (! epilogue_p && current_frame_info.reg_save_ar_unat)
03077 emit_insn (gen_prologue_use (ar_unat_save_reg));
03078 }
03079 else
03080 ar_unat_save_reg = NULL_RTX;
03081
03082
03083
03084
03085
03086 cfa_off = -16;
03087 for (regno = GR_ARG_FIRST + 7; n_varargs > 0; --n_varargs, --regno)
03088 {
03089 reg = gen_rtx_REG (DImode, regno);
03090 do_spill (gen_gr_spill, reg, cfa_off += 8, NULL_RTX);
03091 }
03092
03093
03094 cfa_off = (current_frame_info.spill_cfa_off
03095 + current_frame_info.spill_size
03096 + current_frame_info.extra_spill_size);
03097
03098
03099 if (TEST_HARD_REG_BIT (current_frame_info.mask, PR_REG (0)))
03100 {
03101 reg = gen_rtx_REG (DImode, PR_REG (0));
03102 if (current_frame_info.reg_save_pr != 0)
03103 {
03104 alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_pr);
03105 insn = emit_move_insn (alt_reg, reg);
03106
03107
03108
03109 RTX_FRAME_RELATED_P (insn) = 1;
03110 REG_NOTES (insn)
03111 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03112 gen_rtx_SET (VOIDmode, alt_reg, reg),
03113 REG_NOTES (insn));
03114
03115
03116
03117 if (! epilogue_p)
03118 emit_insn (gen_prologue_use (alt_reg));
03119 }
03120 else
03121 {
03122 alt_regno = next_scratch_gr_reg ();
03123 alt_reg = gen_rtx_REG (DImode, alt_regno);
03124 insn = emit_move_insn (alt_reg, reg);
03125 do_spill (gen_movdi_x, alt_reg, cfa_off, reg);
03126 cfa_off -= 8;
03127 }
03128 }
03129
03130
03131 if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM)
03132 && current_frame_info.reg_save_ar_unat == 0)
03133 {
03134 reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM);
03135 do_spill (gen_movdi_x, ar_unat_save_reg, cfa_off, reg);
03136 cfa_off -= 8;
03137 }
03138
03139
03140
03141
03142 if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_PFS_REGNUM)
03143 && current_frame_info.reg_save_ar_pfs == 0)
03144 {
03145 reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
03146 do_spill (gen_movdi_x, ar_pfs_save_reg, cfa_off, reg);
03147 cfa_off -= 8;
03148 }
03149
03150 if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_LC_REGNUM))
03151 {
03152 reg = gen_rtx_REG (DImode, AR_LC_REGNUM);
03153 if (current_frame_info.reg_save_ar_lc != 0)
03154 {
03155 alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_lc);
03156 insn = emit_move_insn (alt_reg, reg);
03157 RTX_FRAME_RELATED_P (insn) = 1;
03158
03159
03160
03161 if (! epilogue_p)
03162 emit_insn (gen_prologue_use (alt_reg));
03163 }
03164 else
03165 {
03166 alt_regno = next_scratch_gr_reg ();
03167 alt_reg = gen_rtx_REG (DImode, alt_regno);
03168 emit_move_insn (alt_reg, reg);
03169 do_spill (gen_movdi_x, alt_reg, cfa_off, reg);
03170 cfa_off -= 8;
03171 }
03172 }
03173
03174
03175 if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
03176 {
03177 reg = gen_rtx_REG (DImode, BR_REG (0));
03178 if (current_frame_info.reg_save_b0 != 0)
03179 {
03180 alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
03181 insn = emit_move_insn (alt_reg, reg);
03182 RTX_FRAME_RELATED_P (insn) = 1;
03183
03184
03185
03186 if (! epilogue_p)
03187 emit_insn (gen_prologue_use (alt_reg));
03188 }
03189 else
03190 {
03191 alt_regno = next_scratch_gr_reg ();
03192 alt_reg = gen_rtx_REG (DImode, alt_regno);
03193 emit_move_insn (alt_reg, reg);
03194 do_spill (gen_movdi_x, alt_reg, cfa_off, reg);
03195 cfa_off -= 8;
03196 }
03197 }
03198
03199 if (current_frame_info.reg_save_gp)
03200 {
03201 insn = emit_move_insn (gen_rtx_REG (DImode,
03202 current_frame_info.reg_save_gp),
03203 pic_offset_table_rtx);
03204
03205
03206
03207
03208 REG_NOTES (insn)
03209 = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, REG_NOTES (insn));
03210 }
03211
03212
03213 gcc_assert (cfa_off == (current_frame_info.spill_cfa_off
03214 + current_frame_info.spill_size));
03215
03216
03217 for (regno = GR_REG (1); regno <= GR_REG (31); ++regno)
03218 if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
03219 {
03220 reg = gen_rtx_REG (DImode, regno);
03221 do_spill (gen_gr_spill, reg, cfa_off, reg);
03222 cfa_off -= 8;
03223 }
03224
03225
03226 for (regno = BR_REG (1); regno <= BR_REG (7); ++regno)
03227 if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
03228 {
03229 alt_regno = next_scratch_gr_reg ();
03230 alt_reg = gen_rtx_REG (DImode, alt_regno);
03231 reg = gen_rtx_REG (DImode, regno);
03232 emit_move_insn (alt_reg, reg);
03233 do_spill (gen_movdi_x, alt_reg, cfa_off, reg);
03234 cfa_off -= 8;
03235 }
03236
03237
03238 for (regno = FR_REG (2); regno <= FR_REG (127); ++regno)
03239 if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
03240 {
03241 gcc_assert (!(cfa_off & 15));
03242 reg = gen_rtx_REG (XFmode, regno);
03243 do_spill (gen_fr_spill_x, reg, cfa_off, reg);
03244 cfa_off -= 16;
03245 }
03246
03247 gcc_assert (cfa_off == current_frame_info.spill_cfa_off);
03248
03249 finish_spill_pointers ();
03250 }
03251
03252
03253
03254
03255
03256
03257
03258
03259 void
03260 ia64_expand_epilogue (int sibcall_p)
03261 {
03262 rtx insn, reg, alt_reg, ar_unat_save_reg;
03263 int regno, alt_regno, cfa_off;
03264
03265 ia64_compute_frame_size (get_frame_size ());
03266
03267
03268
03269
03270 if (frame_pointer_needed)
03271 setup_spill_pointers (current_frame_info.n_spilled,
03272 hard_frame_pointer_rtx, 0);
03273 else
03274 setup_spill_pointers (current_frame_info.n_spilled, stack_pointer_rtx,
03275 current_frame_info.total_size);
03276
03277 if (current_frame_info.total_size != 0)
03278 {
03279
03280
03281
03282 emit_insn (gen_blockage ());
03283 }
03284
03285
03286 cfa_off = (current_frame_info.spill_cfa_off
03287 + current_frame_info.spill_size
03288 + current_frame_info.extra_spill_size);
03289
03290
03291 if (TEST_HARD_REG_BIT (current_frame_info.mask, PR_REG (0)))
03292 {
03293 if (current_frame_info.reg_save_pr != 0)
03294 alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_pr);
03295 else
03296 {
03297 alt_regno = next_scratch_gr_reg ();
03298 alt_reg = gen_rtx_REG (DImode, alt_regno);
03299 do_restore (gen_movdi_x, alt_reg, cfa_off);
03300 cfa_off -= 8;
03301 }
03302 reg = gen_rtx_REG (DImode, PR_REG (0));
03303 emit_move_insn (reg, alt_reg);
03304 }
03305
03306
03307
03308
03309
03310 if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM))
03311 {
03312 if (current_frame_info.reg_save_ar_unat != 0)
03313 ar_unat_save_reg
03314 = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_unat);
03315 else
03316 {
03317 alt_regno = next_scratch_gr_reg ();
03318 ar_unat_save_reg = gen_rtx_REG (DImode, alt_regno);
03319 current_frame_info.gr_used_mask |= 1 << alt_regno;
03320 do_restore (gen_movdi_x, ar_unat_save_reg, cfa_off);
03321 cfa_off -= 8;
03322 }
03323 }
03324 else
03325 ar_unat_save_reg = NULL_RTX;
03326
03327 if (current_frame_info.reg_save_ar_pfs != 0)
03328 {
03329 alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_pfs);
03330 reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
03331 emit_move_insn (reg, alt_reg);
03332 }
03333 else if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_PFS_REGNUM))
03334 {
03335 alt_regno = next_scratch_gr_reg ();
03336 alt_reg = gen_rtx_REG (DImode, alt_regno);
03337 do_restore (gen_movdi_x, alt_reg, cfa_off);
03338 cfa_off -= 8;
03339 reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
03340 emit_move_insn (reg, alt_reg);
03341 }
03342
03343 if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_LC_REGNUM))
03344 {
03345 if (current_frame_info.reg_save_ar_lc != 0)
03346 alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_lc);
03347 else
03348 {
03349 alt_regno = next_scratch_gr_reg ();
03350 alt_reg = gen_rtx_REG (DImode, alt_regno);
03351 do_restore (gen_movdi_x, alt_reg, cfa_off);
03352 cfa_off -= 8;
03353 }
03354 reg = gen_rtx_REG (DImode, AR_LC_REGNUM);
03355 emit_move_insn (reg, alt_reg);
03356 }
03357
03358
03359 if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
03360 {
03361 if (current_frame_info.reg_save_b0 != 0)
03362 alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
03363 else
03364 {
03365 alt_regno = next_scratch_gr_reg ();
03366 alt_reg = gen_rtx_REG (DImode, alt_regno);
03367 do_restore (gen_movdi_x, alt_reg, cfa_off);
03368 cfa_off -= 8;
03369 }
03370 reg = gen_rtx_REG (DImode, BR_REG (0));
03371 emit_move_insn (reg, alt_reg);
03372 }
03373
03374
03375 gcc_assert (cfa_off == (current_frame_info.spill_cfa_off
03376 + current_frame_info.spill_size));
03377
03378
03379
03380 if (TEST_HARD_REG_BIT (current_frame_info.mask, GR_REG (1)))
03381 cfa_off -= 8;
03382
03383
03384 for (regno = GR_REG (2); regno <= GR_REG (31); ++regno)
03385 if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
03386 {
03387 reg = gen_rtx_REG (DImode, regno);
03388 do_restore (gen_gr_restore, reg, cfa_off);
03389 cfa_off -= 8;
03390 }
03391
03392
03393 for (regno = BR_REG (1); regno <= BR_REG (7); ++regno)
03394 if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
03395 {
03396 alt_regno = next_scratch_gr_reg ();
03397 alt_reg = gen_rtx_REG (DImode, alt_regno);
03398 do_restore (gen_movdi_x, alt_reg, cfa_off);
03399 cfa_off -= 8;
03400 reg = gen_rtx_REG (DImode, regno);
03401 emit_move_insn (reg, alt_reg);
03402 }
03403
03404
03405 for (regno = FR_REG (2); regno <= FR_REG (127); ++regno)
03406 if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
03407 {
03408 gcc_assert (!(cfa_off & 15));
03409 reg = gen_rtx_REG (XFmode, regno);
03410 do_restore (gen_fr_restore_x, reg, cfa_off);
03411 cfa_off -= 16;
03412 }
03413
03414
03415 if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM))
03416 {
03417 reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM);
03418 emit_move_insn (reg, ar_unat_save_reg);
03419 }
03420
03421 gcc_assert (cfa_off == current_frame_info.spill_cfa_off);
03422
03423 finish_spill_pointers ();
03424
03425 if (current_frame_info.total_size || cfun->machine->ia64_eh_epilogue_sp)
03426 {
03427
03428
03429
03430
03431 emit_insn (gen_blockage ());
03432 }
03433
03434 if (cfun->machine->ia64_eh_epilogue_sp)
03435 emit_move_insn (stack_pointer_rtx, cfun->machine->ia64_eh_epilogue_sp);
03436 else if (frame_pointer_needed)
03437 {
03438 insn = emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
03439 RTX_FRAME_RELATED_P (insn) = 1;
03440 }
03441 else if (current_frame_info.total_size)
03442 {
03443 rtx offset, frame_size_rtx;
03444
03445 frame_size_rtx = GEN_INT (current_frame_info.total_size);
03446 if (CONST_OK_FOR_I (current_frame_info.total_size))
03447 offset = frame_size_rtx;
03448 else
03449 {
03450 regno = next_scratch_gr_reg ();
03451 offset = gen_rtx_REG (DImode, regno);
03452 emit_move_insn (offset, frame_size_rtx);
03453 }
03454
03455 insn = emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
03456 offset));
03457
03458 RTX_FRAME_RELATED_P (insn) = 1;
03459 if (GET_CODE (offset) != CONST_INT)
03460 {
03461 REG_NOTES (insn)
03462 = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
03463 gen_rtx_SET (VOIDmode,
03464 stack_pointer_rtx,
03465 gen_rtx_PLUS (DImode,
03466 stack_pointer_rtx,
03467 frame_size_rtx)),
03468 REG_NOTES (insn));
03469 }
03470 }
03471
03472 if (cfun->machine->ia64_eh_epilogue_bsp)
03473 emit_insn (gen_set_bsp (cfun->machine->ia64_eh_epilogue_bsp));
03474
03475 if (! sibcall_p)
03476 emit_jump_insn (gen_return_internal (gen_rtx_REG (DImode, BR_REG (0))));
03477 else
03478 {
03479 int fp = GR_REG (2);
03480
03481
03482
03483
03484
03485 if (current_frame_info.reg_fp && current_frame_info.reg_fp == GR_REG (2))
03486 fp = HARD_FRAME_POINTER_REGNUM;
03487
03488
03489
03490
03491
03492
03493
03494
03495 if (current_frame_info.n_input_regs != 0)
03496 {
03497 rtx n_inputs = GEN_INT (current_frame_info.n_input_regs);
03498 insn = emit_insn (gen_alloc (gen_rtx_REG (DImode, fp),
03499 const0_rtx, const0_rtx,
03500 n_inputs, const0_rtx));
03501 RTX_FRAME_RELATED_P (insn) = 1;
03502 }
03503 }
03504 }
03505
03506
03507
03508
03509 int
03510 ia64_direct_return (void)
03511 {
03512 if (reload_completed && ! frame_pointer_needed)
03513 {
03514 ia64_compute_frame_size (get_frame_size ());
03515
03516 return (current_frame_info.total_size == 0
03517 && current_frame_info.n_spilled == 0
03518 && current_frame_info.reg_save_b0 == 0
03519 && current_frame_info.reg_save_pr == 0
03520 && current_frame_info.reg_save_ar_pfs == 0
03521 && current_frame_info.reg_save_ar_unat == 0
03522 && current_frame_info.reg_save_ar_lc == 0);
03523 }
03524 return 0;
03525 }
03526
03527
03528
03529
03530 rtx
03531 ia64_return_addr_rtx (HOST_WIDE_INT count, rtx frame ATTRIBUTE_UNUSED)
03532 {
03533 if (count != 0)
03534 return NULL;
03535 return gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_RET_ADDR);
03536 }
03537
03538
03539
03540
03541 void
03542 ia64_split_return_addr_rtx (rtx dest)
03543 {
03544 rtx src;
03545
03546 if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
03547 {
03548 if (current_frame_info.reg_save_b0 != 0)
03549 src = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
03550 else
03551 {
03552 HOST_WIDE_INT off;
03553 unsigned int regno;
03554
03555
03556
03557 off = (current_frame_info.spill_cfa_off
03558 + current_frame_info.spill_size);
03559 for (regno = GR_REG (1); regno <= GR_REG (31); ++regno)
03560 if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
03561 off -= 8;
03562
03563
03564 if (frame_pointer_needed)
03565 src = hard_frame_pointer_rtx;
03566 else
03567 {
03568 src = stack_pointer_rtx;
03569 off += current_frame_info.total_size;
03570 }
03571
03572
03573 if (CONST_OK_FOR_I (off))
03574 emit_insn (gen_adddi3 (dest, src, GEN_INT (off)));
03575 else
03576 {
03577 emit_move_insn (dest, GEN_INT (off));
03578 emit_insn (gen_adddi3 (dest, src, dest));
03579 }
03580
03581 src = gen_rtx_MEM (Pmode, dest);
03582 }
03583 }
03584 else
03585 src = gen_rtx_REG (DImode, BR_REG (0));
03586
03587 emit_move_insn (dest, src);
03588 }
03589
03590 int
03591 ia64_hard_regno_rename_ok (int from, int to)
03592 {
03593
03594 if (to == current_frame_info.reg_fp
03595 || to == current_frame_info.reg_save_b0
03596 || to == current_frame_info.reg_save_pr
03597 || to == current_frame_info.reg_save_ar_pfs
03598 || to == current_frame_info.reg_save_ar_unat
03599 || to == current_frame_info.reg_save_ar_lc)
03600 return 0;
03601
03602 if (from == current_frame_info.reg_fp
03603 || from == current_frame_info.reg_save_b0
03604 || from == current_frame_info.reg_save_pr
03605 || from == current_frame_info.reg_save_ar_pfs
03606 || from == current_frame_info.reg_save_ar_unat
03607 || from == current_frame_info.reg_save_ar_lc)
03608 return 0;
03609
03610
03611 if (OUT_REGNO_P (to) && to >= OUT_REG (current_frame_info.n_output_regs))
03612 return 0;
03613
03614
03615 if (PR_REGNO_P (from) && PR_REGNO_P (to))
03616 return (from & 1) == (to & 1);
03617
03618 return 1;
03619 }
03620
03621
03622
03623
03624 static bool
03625 ia64_assemble_integer (rtx x, unsigned int size, int aligned_p)
03626 {
03627 if (size == POINTER_SIZE / BITS_PER_UNIT
03628 && !(TARGET_NO_PIC || TARGET_AUTO_PIC)
03629 && GET_CODE (x) == SYMBOL_REF
03630 && SYMBOL_REF_FUNCTION_P (x))
03631 {
03632 static const char * const directive[2][2] = {
03633
03634 { "\tdata8.ua\t@fptr(", "\tdata4.ua\t@fptr("},
03635 { "\tdata8\t@fptr(", "\tdata4\t@fptr("}
03636 };
03637 fputs (directive[(aligned_p != 0)][POINTER_SIZE == 32], asm_out_file);
03638 output_addr_const (asm_out_file, x);
03639 fputs (")\n", asm_out_file);
03640 return true;
03641 }
03642 return default_assemble_integer (x, size, aligned_p);
03643 }
03644
03645
03646
03647 static void
03648 ia64_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
03649 {
03650 int mask, grsave, grsave_prev;
03651
03652 if (current_frame_info.need_regstk)
03653 fprintf (file, "\t.regstk %d, %d, %d, %d\n",
03654 current_frame_info.n_input_regs,
03655 current_frame_info.n_local_regs,
03656 current_frame_info.n_output_regs,
03657 current_frame_info.n_rotate_regs);
03658
03659 if (!flag_unwind_tables && (!flag_exceptions || USING_SJLJ_EXCEPTIONS))
03660 return;
03661
03662
03663
03664 mask = 0;
03665 grsave = grsave_prev = 0;
03666 if (current_frame_info.reg_save_b0 != 0)
03667 {
03668 mask |= 8;
03669 grsave = grsave_prev = current_frame_info.reg_save_b0;
03670 }
03671 if (current_frame_info.reg_save_ar_pfs != 0
03672 && (grsave_prev == 0
03673 || current_frame_info.reg_save_ar_pfs == grsave_prev + 1))
03674 {
03675 mask |= 4;
03676 if (grsave_prev == 0)
03677 grsave = current_frame_info.reg_save_ar_pfs;
03678 grsave_prev = current_frame_info.reg_save_ar_pfs;
03679 }
03680 if (current_frame_info.reg_fp != 0
03681 && (grsave_prev == 0
03682 || current_frame_info.reg_fp == grsave_prev + 1))
03683 {
03684 mask |= 2;
03685 if (grsave_prev == 0)
03686 grsave = HARD_FRAME_POINTER_REGNUM;
03687 grsave_prev = current_frame_info.reg_fp;
03688 }
03689 if (current_frame_info.reg_save_pr != 0
03690 && (grsave_prev == 0
03691 || current_frame_info.reg_save_pr == grsave_prev + 1))
03692 {
03693 mask |= 1;
03694 if (grsave_prev == 0)
03695 grsave = current_frame_info.reg_save_pr;
03696 }
03697
03698 if (mask && TARGET_GNU_AS)
03699 fprintf (file, "\t.prologue %d, %d\n", mask,
03700 ia64_dbx_register_number (grsave));
03701 else
03702 fputs ("\t.prologue\n", file);
03703
03704
03705
03706 if (current_frame_info.spill_cfa_off != -16)
03707 fprintf (file, "\t.spill %ld\n",
03708 (long) (current_frame_info.spill_cfa_off
03709 + current_frame_info.spill_size));
03710 }
03711
03712
03713
03714 static void
03715 ia64_output_function_end_prologue (FILE *file)
03716 {
03717 if (!flag_unwind_tables && (!flag_exceptions || USING_SJLJ_EXCEPTIONS))
03718 return;
03719
03720 fputs ("\t.body\n", file);
03721 }
03722
03723
03724
03725 static void
03726 ia64_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
03727 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
03728 {
03729 int i;
03730
03731 if (current_frame_info.reg_fp)
03732 {
03733 const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM];
03734 reg_names[HARD_FRAME_POINTER_REGNUM]
03735 = reg_names[current_frame_info.reg_fp];
03736 reg_names[current_frame_info.reg_fp] = tmp;
03737 }
03738 if (! TARGET_REG_NAMES)
03739 {
03740 for (i = 0; i < current_frame_info.n_input_regs; i++)
03741 reg_names[IN_REG (i)] = ia64_input_reg_names[i];
03742 for (i = 0; i < current_frame_info.n_local_regs; i++)
03743 reg_names[LOC_REG (i)] = ia64_local_reg_names[i];
03744 for (i = 0; i < current_frame_info.n_output_regs; i++)
03745 reg_names[OUT_REG (i)] = ia64_output_reg_names[i];
03746 }
03747
03748 current_frame_info.initialized = 0;
03749 }
03750
03751 int
03752 ia64_dbx_register_number (int regno)
03753 {
03754
03755
03756
03757 if (current_frame_info.reg_fp)
03758 {
03759 if (regno == HARD_FRAME_POINTER_REGNUM)
03760 regno = current_frame_info.reg_fp;
03761 else if (regno == current_frame_info.reg_fp)
03762 regno = HARD_FRAME_POINTER_REGNUM;
03763 }
03764
03765 if (IN_REGNO_P (regno))
03766 return 32 + regno - IN_REG (0);
03767 else if (LOC_REGNO_P (regno))
03768 return 32 + current_frame_info.n_input_regs + regno - LOC_REG (0);
03769 else if (OUT_REGNO_P (regno))
03770 return (32 + current_frame_info.n_input_regs
03771 + current_frame_info.n_local_regs + regno - OUT_REG (0));
03772 else
03773 return regno;
03774 }
03775
03776 void
03777 ia64_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain)
03778 {
03779 rtx addr_reg, eight = GEN_INT (8);
03780
03781
03782
03783 if (!TARGET_GNU_AS)
03784 {
03785 static bool declared_ia64_trampoline = false;
03786
03787 if (!declared_ia64_trampoline)
03788 {
03789 declared_ia64_trampoline = true;
03790 (*targetm.asm_out.globalize_label) (asm_out_file,
03791 "__ia64_trampoline");
03792 }
03793 }
03794
03795
03796 addr = convert_memory_address (Pmode, addr);
03797 fnaddr = convert_memory_address (Pmode, fnaddr);
03798 static_chain = convert_memory_address (Pmode, static_chain);
03799
03800
03801 addr_reg = gen_reg_rtx (Pmode);
03802 emit_move_insn (addr_reg, addr);
03803
03804
03805
03806 emit_move_insn (gen_rtx_MEM (Pmode, addr_reg),
03807 gen_rtx_SYMBOL_REF (Pmode, "__ia64_trampoline"));
03808 emit_insn (gen_adddi3 (addr_reg, addr_reg, eight));
03809
03810 emit_move_insn (gen_rtx_MEM (Pmode, addr_reg),
03811 copy_to_reg (plus_constant (addr, 16)));
03812 emit_insn (gen_adddi3 (addr_reg, addr_reg, eight));
03813
03814
03815 emit_move_insn (gen_rtx_MEM (Pmode, addr_reg), fnaddr);
03816 emit_insn (gen_adddi3 (addr_reg, addr_reg, eight));
03817
03818
03819 emit_move_insn (gen_rtx_MEM (Pmode, addr_reg), static_chain);
03820 }
03821
03822
03823
03824
03825
03826
03827 static void
03828 ia64_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
03829 tree type, int * pretend_size,
03830 int second_time ATTRIBUTE_UNUSED)
03831 {
03832 CUMULATIVE_ARGS next_cum = *cum;
03833
03834
03835 ia64_function_arg_advance (&next_cum, mode, type, 1);
03836
03837 if (next_cum.words < MAX_ARGUMENT_SLOTS)
03838 {
03839 int n = MAX_ARGUMENT_SLOTS - next_cum.words;
03840 *pretend_size = n * UNITS_PER_WORD;
03841 cfun->machine->n_varargs = n;
03842 }
03843 }
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857 static enum machine_mode
03858 hfa_element_mode (tree type, bool nested)
03859 {
03860 enum machine_mode element_mode = VOIDmode;
03861 enum machine_mode mode;
03862 enum tree_code code = TREE_CODE (type);
03863 int know_element_mode = 0;
03864 tree t;
03865
03866 if (!nested && (!TYPE_SIZE (type) || integer_zerop (TYPE_SIZE (type))))
03867 return VOIDmode;
03868
03869 switch (code)
03870 {
03871 case VOID_TYPE: case INTEGER_TYPE: case ENUMERAL_TYPE:
03872 case BOOLEAN_TYPE: case POINTER_TYPE:
03873 case OFFSET_TYPE: case REFERENCE_TYPE: case METHOD_TYPE:
03874 case LANG_TYPE: case FUNCTION_TYPE:
03875 return VOIDmode;
03876
03877
03878
03879
03880 case COMPLEX_TYPE:
03881 if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT
03882 && TYPE_MODE (type) != TCmode)
03883 return GET_MODE_INNER (TYPE_MODE (type));
03884 else
03885 return VOIDmode;
03886
03887 case REAL_TYPE:
03888
03889
03890 if (nested && TYPE_MODE (type) != TFmode)
03891 return TYPE_MODE (type);
03892 else
03893 return VOIDmode;
03894
03895 case ARRAY_TYPE:
03896 return hfa_element_mode (TREE_TYPE (type), 1);
03897
03898 case RECORD_TYPE:
03899 case UNION_TYPE:
03900 case QUAL_UNION_TYPE:
03901 for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t))
03902 {
03903 if (TREE_CODE (t) != FIELD_DECL)
03904 continue;
03905
03906 mode = hfa_element_mode (TREE_TYPE (t), 1);
03907 if (know_element_mode)
03908 {
03909 if (mode != element_mode)
03910 return VOIDmode;
03911 }
03912 else if (GET_MODE_CLASS (mode) != MODE_FLOAT)
03913 return VOIDmode;
03914 else
03915 {
03916 know_element_mode = 1;
03917 element_mode = mode;
03918 }
03919 }
03920 return element_mode;
03921
03922 default:
03923
03924
03925
03926
03927 return VOIDmode;
03928 }
03929
03930 return VOIDmode;
03931 }
03932
03933
03934
03935 static int
03936 ia64_function_arg_words (tree type, enum machine_mode mode)
03937 {
03938 int words;
03939
03940 if (mode == BLKmode)
03941 words = int_size_in_bytes (type);
03942 else
03943 words = GET_MODE_SIZE (mode);
03944
03945 return (words + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
03946 }
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
03960
03961 static int
03962 ia64_function_arg_offset (CUMULATIVE_ARGS *cum, tree type, int words)
03963 {
03964 if ((cum->words & 1) == 0)
03965 return 0;
03966
03967 if (type
03968 && TREE_CODE (type) != INTEGER_TYPE
03969 && TREE_CODE (type) != REAL_TYPE)
03970 return TYPE_ALIGN (type) > 8 * BITS_PER_UNIT;
03971 else
03972 return words > 1;
03973 }
03974
03975
03976
03977
03978
03979
03980 rtx
03981 ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
03982 int named, int incoming)
03983 {
03984 int basereg = (incoming ? GR_ARG_FIRST : AR_ARG_FIRST);
03985 int words = ia64_function_arg_words (type, mode);
03986 int offset = ia64_function_arg_offset (cum, type, words);
03987 enum machine_mode hfa_mode = VOIDmode;
03988
03989
03990 if (cum->words + offset >= MAX_ARGUMENT_SLOTS)
03991 return 0;
03992
03993
03994 if (type)
03995 hfa_mode = hfa_element_mode (type, 0);
03996
03997
03998
03999 if (hfa_mode != VOIDmode && (! cum->prototype || named))
04000 {
04001 rtx loc[16];
04002 int i = 0;
04003 int fp_regs = cum->fp_regs;
04004 int int_regs = cum->words + offset;
04005 int hfa_size = GET_MODE_SIZE (hfa_mode);
04006 int byte_size;
04007 int args_byte_size;
04008
04009
04010
04011
04012
04013
04014
04015
04016
04017
04018
04019 byte_size = ((mode == BLKmode)
04020 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
04021 args_byte_size = int_regs * UNITS_PER_WORD;
04022 offset = 0;
04023 for (; (offset < byte_size && fp_regs < MAX_ARGUMENT_SLOTS
04024 && args_byte_size < (MAX_ARGUMENT_SLOTS * UNITS_PER_WORD)); i++)
04025 {
04026 loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
04027 gen_rtx_REG (hfa_mode, (FR_ARG_FIRST
04028 + fp_regs)),
04029 GEN_INT (offset));
04030 offset += hfa_size;
04031 args_byte_size += hfa_size;
04032 fp_regs++;
04033 }
04034
04035
04036 if (! cum->prototype)
04037 offset = 0;
04038
04039
04040 else if (byte_size != offset)
04041 int_regs += offset / UNITS_PER_WORD;
04042
04043
04044
04045 for (; offset < byte_size && int_regs < MAX_ARGUMENT_SLOTS; i++)
04046 {
04047 enum machine_mode gr_mode = DImode;
04048 unsigned int gr_size;
04049
04050
04051
04052
04053
04054
04055 if (offset & 0x4)
04056 gr_mode = SImode;
04057
04058
04059
04060 else if (byte_size - offset == 4)
04061 gr_mode = SImode;
04062
04063 loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
04064 gen_rtx_REG (gr_mode, (basereg
04065 + int_regs)),
04066 GEN_INT (offset));
04067
04068 gr_size = GET_MODE_SIZE (gr_mode);
04069 offset += gr_size;
04070 if (gr_size == UNITS_PER_WORD
04071 || (gr_size < UNITS_PER_WORD && offset % UNITS_PER_WORD == 0))
04072 int_regs++;
04073 else if (gr_size > UNITS_PER_WORD)
04074 int_regs += gr_size / UNITS_PER_WORD;
04075 }
04076 return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
04077 }
04078
04079
04080
04081
04082 else if (mode == TFmode || mode == TCmode
04083 || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
04084 {
04085 int byte_size = ((mode == BLKmode)
04086 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
04087 if (BYTES_BIG_ENDIAN
04088 && (mode == BLKmode || (type && AGGREGATE_TYPE_P (type)))
04089 && byte_size < UNITS_PER_WORD
04090 && byte_size > 0)
04091 {
04092 rtx gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
04093 gen_rtx_REG (DImode,
04094 (basereg + cum->words
04095 + offset)),
04096 const0_rtx);
04097 return gen_rtx_PARALLEL (mode, gen_rtvec (1, gr_reg));
04098 }
04099 else
04100 return gen_rtx_REG (mode, basereg + cum->words + offset);
04101
04102 }
04103
04104
04105
04106 else if (cum->prototype)
04107 {
04108 if (named)
04109 return gen_rtx_REG (mode, FR_ARG_FIRST + cum->fp_regs);
04110
04111
04112
04113 else if (BYTES_BIG_ENDIAN && mode == SFmode)
04114 return gen_rtx_PARALLEL (mode,
04115 gen_rtvec (1,
04116 gen_rtx_EXPR_LIST (VOIDmode,
04117 gen_rtx_REG (DImode, basereg + cum->words + offset),
04118 const0_rtx)));
04119 else
04120 return gen_rtx_REG (mode, basereg + cum->words + offset);
04121 }
04122
04123
04124 else
04125 {
04126
04127 enum machine_mode inner_mode =
04128 (BYTES_BIG_ENDIAN && mode == SFmode) ? DImode : mode;
04129
04130 rtx fp_reg = gen_rtx_EXPR_LIST (VOIDmode,
04131 gen_rtx_REG (mode, (FR_ARG_FIRST
04132 + cum->fp_regs)),
04133 const0_rtx);
04134 rtx gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
04135 gen_rtx_REG (inner_mode,
04136 (basereg + cum->words
04137 + offset)),
04138 const0_rtx);
04139
04140 return gen_rtx_PARALLEL (mode, gen_rtvec (2, fp_reg, gr_reg));
04141 }
04142 }
04143
04144
04145
04146
04147
04148 static int
04149 ia64_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
04150 tree type, bool named ATTRIBUTE_UNUSED)
04151 {
04152 int words = ia64_function_arg_words (type, mode);
04153 int offset = ia64_function_arg_offset (cum, type, words);
04154
04155
04156 if (cum->words + offset >= MAX_ARGUMENT_SLOTS)
04157 return 0;
04158
04159
04160
04161
04162
04163
04164 if (words + cum->words + offset <= MAX_ARGUMENT_SLOTS)
04165 return 0;
04166
04167 return (MAX_ARGUMENT_SLOTS - cum->words - offset) * UNITS_PER_WORD;
04168 }
04169
04170
04171
04172
04173 void
04174 ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
04175 tree type, int named)
04176 {
04177 int words = ia64_function_arg_words (type, mode);
04178 int offset = ia64_function_arg_offset (cum, type, words);
04179 enum machine_mode hfa_mode = VOIDmode;
04180
04181
04182 if (cum->words >= MAX_ARGUMENT_SLOTS)
04183 return;
04184
04185 cum->words += words + offset;
04186
04187
04188 if (type)
04189 hfa_mode = hfa_element_mode (type, 0);
04190
04191
04192
04193 if (hfa_mode != VOIDmode && (! cum->prototype || named))
04194 {
04195 int fp_regs = cum->fp_regs;
04196
04197 int int_regs = cum->words - words;
04198 int hfa_size = GET_MODE_SIZE (hfa_mode);
04199 int byte_size;
04200 int args_byte_size;
04201
04202
04203
04204
04205
04206
04207
04208
04209
04210
04211
04212 byte_size = ((mode == BLKmode)
04213 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
04214 args_byte_size = int_regs * UNITS_PER_WORD;
04215 offset = 0;
04216 for (; (offset < byte_size && fp_regs < MAX_ARGUMENT_SLOTS
04217 && args_byte_size < (MAX_ARGUMENT_SLOTS * UNITS_PER_WORD));)
04218 {
04219 offset += hfa_size;
04220 args_byte_size += hfa_size;
04221 fp_regs++;
04222 }
04223
04224 cum->fp_regs = fp_regs;
04225 }
04226
04227
04228
04229
04230 else if (mode == TFmode || mode == TCmode
04231 || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
04232 cum->int_regs = cum->words;
04233
04234
04235
04236 else if (cum->prototype)
04237 {
04238 if (! named)
04239 cum->int_regs = cum->words;
04240 else
04241
04242 cum->fp_regs += (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT ? 2 : 1);
04243 }
04244
04245
04246 else
04247 {
04248
04249 cum->fp_regs += (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT ? 2 : 1);
04250 cum->int_regs = cum->words;
04251 }
04252 }
04253
04254
04255
04256
04257
04258 int
04259 ia64_function_arg_boundary (enum machine_mode mode, tree type)
04260 {
04261
04262 if (mode == TFmode && TARGET_HPUX && TARGET_ILP32)
04263 return PARM_BOUNDARY * 2;
04264
04265 if (type)
04266 {
04267 if (TYPE_ALIGN (type) > PARM_BOUNDARY)
04268 return PARM_BOUNDARY * 2;
04269 else
04270 return PARM_BOUNDARY;
04271 }
04272
04273 if (GET_MODE_BITSIZE (mode) > PARM_BOUNDARY)
04274 return PARM_BOUNDARY * 2;
04275 else
04276 return PARM_BOUNDARY;
04277 }
04278
04279
04280
04281
04282 static bool
04283 ia64_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
04284 {
04285
04286
04287 if (lookup_attribute ("syscall_linkage",
04288 TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
04289 return false;
04290
04291
04292
04293 return decl && (*targetm.binds_local_p) (decl);
04294 }
04295
04296
04297
04298
04299 static tree
04300 ia64_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
04301 {
04302
04303 if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
04304 {
04305 tree ptrtype = build_pointer_type (type);
04306 tree addr = std_gimplify_va_arg_expr (valist, ptrtype, pre_p, post_p);
04307 return build_va_arg_indirect_ref (addr);
04308 }
04309
04310
04311
04312
04313
04314 if ((TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == INTEGER_TYPE)
04315 ? int_size_in_bytes (type) > 8 : TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
04316 {
04317 tree t = build2 (PLUS_EXPR, TREE_TYPE (valist), valist,
04318 build_int_cst (NULL_TREE, 2 * UNITS_PER_WORD - 1));
04319 t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
04320 build_int_cst (NULL_TREE, -2 * UNITS_PER_WORD));
04321 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
04322 gimplify_and_add (t, pre_p);
04323 }
04324
04325 return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
04326 }
04327
04328
04329
04330
04331 static bool
04332 ia64_return_in_memory (tree valtype, tree fntype ATTRIBUTE_UNUSED)
04333 {
04334 enum machine_mode mode;
04335 enum machine_mode hfa_mode;
04336 HOST_WIDE_INT byte_size;
04337
04338 mode = TYPE_MODE (valtype);
04339 byte_size = GET_MODE_SIZE (mode);
04340 if (mode == BLKmode)
04341 {
04342 byte_size = int_size_in_bytes (valtype);
04343 if (byte_size < 0)
04344 return true;
04345 }
04346
04347
04348
04349 hfa_mode = hfa_element_mode (valtype, 0);
04350 if (hfa_mode != VOIDmode)
04351 {
04352 int hfa_size = GET_MODE_SIZE (hfa_mode);
04353
04354 if (byte_size / hfa_size > MAX_ARGUMENT_SLOTS)
04355 return true;
04356 else
04357 return false;
04358 }
04359 else if (byte_size > UNITS_PER_WORD * MAX_INT_RETURN_SLOTS)
04360 return true;
04361 else
04362 return false;
04363 }
04364
04365
04366
04367 rtx
04368 ia64_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
04369 {
04370 enum machine_mode mode;
04371 enum machine_mode hfa_mode;
04372
04373 mode = TYPE_MODE (valtype);
04374 hfa_mode = hfa_element_mode (valtype, 0);
04375
04376 if (hfa_mode != VOIDmode)
04377 {
04378 rtx loc[8];
04379 int i;
04380 int hfa_size;
04381 int byte_size;
04382 int offset;
04383
04384 hfa_size = GET_MODE_SIZE (hfa_mode);
04385 byte_size = ((mode == BLKmode)
04386 ? int_size_in_bytes (valtype) : GET_MODE_SIZE (mode));
04387 offset = 0;
04388 for (i = 0; offset < byte_size; i++)
04389 {
04390 loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
04391 gen_rtx_REG (hfa_mode, FR_ARG_FIRST + i),
04392 GEN_INT (offset));
04393 offset += hfa_size;
04394 }
04395 return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
04396 }
04397 else if (FLOAT_TYPE_P (valtype) && mode != TFmode && mode != TCmode)
04398 return gen_rtx_REG (mode, FR_ARG_FIRST);
04399 else
04400 {
04401 bool need_parallel = false;
04402
04403
04404
04405
04406 if (BYTES_BIG_ENDIAN
04407 && (mode == BLKmode || (valtype && AGGREGATE_TYPE_P (valtype))))
04408 need_parallel = true;
04409
04410
04411
04412
04413
04414
04415 else if (mode == XFmode || mode == XCmode || mode == RFmode)
04416 need_parallel = true;
04417
04418 if (need_parallel)
04419 {
04420 rtx loc[8];
04421 int offset;
04422 int bytesize;
04423 int i;
04424
04425 offset = 0;
04426 bytesize = int_size_in_bytes (valtype);
04427
04428
04429 if (bytesize == 0)
04430 return gen_rtx_REG (mode, GR_RET_FIRST);
04431 for (i = 0; offset < bytesize; i++)
04432 {
04433 loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
04434 gen_rtx_REG (DImode,
04435 GR_RET_FIRST + i),
04436 GEN_INT (offset));
04437 offset += UNITS_PER_WORD;
04438 }
04439 return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
04440 }
04441
04442 return gen_rtx_REG (mode, GR_RET_FIRST);
04443 }
04444 }
04445
04446
04447
04448
04449 static void
04450 ia64_output_dwarf_dtprel (FILE *file, int size, rtx x)
04451 {
04452 gcc_assert (size == 4 || size == 8);
04453 if (size == 4)
04454 fputs ("\tdata4.ua\t@dtprel(", file);
04455 else
04456 fputs ("\tdata8.ua\t@dtprel(", file);
04457 output_addr_const (file, x);
04458 fputs (")", file);
04459 }
04460
04461
04462
04463
04464
04465
04466 void
04467 ia64_print_operand_address (FILE * stream ATTRIBUTE_UNUSED,
04468 rtx address ATTRIBUTE_UNUSED)
04469 {
04470 }
04471
04472
04473
04474
04475
04476
04477
04478
04479
04480
04481
04482
04483
04484
04485
04486
04487
04488
04489
04490
04491
04492
04493
04494
04495 void
04496 ia64_print_operand (FILE * file, rtx x, int code)
04497 {
04498 const char *str;
04499
04500 switch (code)
04501 {
04502 case 0:
04503
04504 break;
04505
04506 case 'C':
04507 {
04508 enum rtx_code c = swap_condition (GET_CODE (x));
04509 fputs (GET_RTX_NAME (c), file);
04510 return;
04511 }
04512
04513 case 'D':
04514 switch (GET_CODE (x))
04515 {
04516 case NE:
04517 str = "neq";
04518 break;
04519 case UNORDERED:
04520 str = "unord";
04521 break;
04522 case ORDERED:
04523 str = "ord";
04524 break;
04525 default:
04526 str = GET_RTX_NAME (GET_CODE (x));
04527 break;
04528 }
04529 fputs (str, file);
04530 return;
04531
04532 case 'E':
04533 fprintf (file, HOST_WIDE_INT_PRINT_DEC, 32 - INTVAL (x));
04534 return;
04535
04536 case 'e':
04537 fprintf (file, HOST_WIDE_INT_PRINT_DEC, 64 - INTVAL (x));
04538 return;
04539
04540 case 'F':
04541 if (x == CONST0_RTX (GET_MODE (x)))
04542 str = reg_names [FR_REG (0)];
04543 else if (x == CONST1_RTX (GET_MODE (x)))
04544 str = reg_names [FR_REG (1)];
04545 else
04546 {
04547 gcc_assert (GET_CODE (x) == REG);
04548 str = reg_names [REGNO (x)];
04549 }
04550 fputs (str, file);
04551 return;
04552
04553 case 'I':
04554 fputs (reg_names [REGNO (x) + 1], file);
04555 return;
04556
04557 case 'J':
04558 case 'j':
04559 {
04560 unsigned int regno = REGNO (XEXP (x, 0));
04561 if (GET_CODE (x) == EQ)
04562 regno += 1;
04563 if (code == 'j')
04564 regno ^= 1;
04565 fputs (reg_names [regno], file);
04566 }
04567 return;
04568
04569 case 'O':
04570 if (MEM_VOLATILE_P (x))
04571 fputs(".acq", file);
04572 return;
04573
04574 case 'P':
04575 {
04576 HOST_WIDE_INT value;
04577
04578 switch (GET_CODE (XEXP (x, 0)))
04579 {
04580 default:
04581 return;
04582
04583 case POST_MODIFY:
04584 x = XEXP (XEXP (XEXP (x, 0), 1), 1);
04585 if (GET_CODE (x) == CONST_INT)
04586 value = INTVAL (x);
04587 else
04588 {
04589 gcc_assert (GET_CODE (x) == REG);
04590 fprintf (file, ", %s", reg_names[REGNO (x)]);
04591 return;
04592 }
04593 break;
04594
04595 case POST_INC:
04596 value = GET_MODE_SIZE (GET_MODE (x));
04597 break;
04598
04599 case POST_DEC:
04600 value = - (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (x));
04601 break;
04602 }
04603
04604 fprintf (file, ", " HOST_WIDE_INT_PRINT_DEC, value);
04605 return;
04606 }
04607
04608 case 'Q':
04609 if (MEM_VOLATILE_P (x))
04610 fputs(".rel", file);
04611 return;
04612
04613 case 'S':
04614 fprintf (file, "%d", exact_log2 (INTVAL (x)));
04615 return;
04616
04617 case 'T':
04618 if (! TARGET_GNU_AS && GET_CODE (x) == CONST_INT)
04619 {
04620 fprintf (file, "0x%x", (int) INTVAL (x) & 0xffffffff);
04621 return;
04622 }
04623 break;
04624
04625 case 'U':
04626 if (! TARGET_GNU_AS && GET_CODE (x) == CONST_INT)
04627 {
04628 const char *prefix = "0x";
04629 if (INTVAL (x) & 0x80000000)
04630 {
04631 fprintf (file, "0xffffffff");
04632 prefix = "";
04633 }
04634 fprintf (file, "%s%x", prefix, (int) INTVAL (x) & 0xffffffff);
04635 return;
04636 }
04637 break;
04638
04639 case 'X':
04640 {
04641 unsigned int regno = REGNO (x);
04642 fprintf (file, "%s, %s", reg_names [regno], reg_names [regno + 1]);
04643 }
04644 return;
04645
04646 case 'r':
04647
04648
04649 if (GET_CODE (x) == REG)
04650 fputs (reg_names[REGNO (x)], file);
04651 else if (x == CONST0_RTX (GET_MODE (x)))
04652 fputs ("r0", file);
04653 else if (GET_CODE (x) == CONST_INT)
04654 output_addr_const (file, x);
04655 else
04656 output_operand_lossage ("invalid %%r value");
04657 return;
04658
04659 case 'v':
04660 gcc_assert (GET_CODE (x) == CONST_VECTOR);
04661 x = simplify_subreg (DImode, x, GET_MODE (x), 0);
04662 break;
04663
04664 case '+':
04665 {
04666 const char *which;
04667
04668
04669
04670 x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
04671 if (x)
04672 {
04673 int pred_val = INTVAL (XEXP (x, 0));
04674
04675
04676 if (pred_val < REG_BR_PROB_BASE / 50
04677 && br_prob_note_reliable_p (x))
04678 which = ".spnt";
04679 else if (pred_val < REG_BR_PROB_BASE / 2)
04680 which = ".dpnt";
04681 else if (pred_val < REG_BR_PROB_BASE / 100 * 98
04682 || !br_prob_note_reliable_p (x))
04683 which = ".dptk";
04684 else
04685 which = ".sptk";
04686 }
04687 else if (GET_CODE (current_output_insn) == CALL_INSN)
04688 which = ".sptk";
04689 else
04690 which = ".dptk";
04691
04692 fputs (which, file);
04693 return;
04694 }
04695
04696 case ',':
04697 x = current_insn_predicate;
04698 if (x)
04699 {
04700 unsigned int regno = REGNO (XEXP (x, 0));
04701 if (GET_CODE (x) == EQ)
04702 regno += 1;
04703 fprintf (file, "(%s) ", reg_names [regno]);
04704 }
04705 return;
04706
04707 default:
04708 output_operand_lossage ("ia64_print_operand: unknown code");
04709 return;
04710 }
04711
04712 switch (GET_CODE (x))
04713 {
04714
04715 case POST_INC:
04716 case POST_DEC:
04717 case POST_MODIFY:
04718 x = XEXP (x, 0);
04719
04720
04721 case REG:
04722 fputs (reg_names [REGNO (x)], file);
04723 break;
04724
04725 case MEM:
04726 {
04727 rtx addr = XEXP (x, 0);
04728 if (GET_RTX_CLASS (GET_CODE (addr)) == RTX_AUTOINC)
04729 addr = XEXP (addr, 0);
04730 fprintf (file, "[%s]", reg_names [REGNO (addr)]);
04731 break;
04732 }
04733
04734 default:
04735 output_addr_const (file, x);
04736 break;
04737 }
04738
04739 return;
04740 }
04741
04742
04743
04744
04745
04746
04747 static bool
04748 ia64_rtx_costs (rtx x, int code, int outer_code, int *total)
04749 {
04750 switch (code)
04751 {
04752 case CONST_INT:
04753 switch (outer_code)
04754 {
04755 case SET:
04756 *total = CONST_OK_FOR_J (INTVAL (x)) ? 0 : COSTS_N_INSNS (1);
04757 return true;
04758 case PLUS:
04759 if (CONST_OK_FOR_I (INTVAL (x)))
04760 *total = 0;
04761 else if (CONST_OK_FOR_J (INTVAL (x)))
04762 *total = 1;
04763 else
04764 *total = COSTS_N_INSNS (1);
04765 return true;
04766 default:
04767 if (CONST_OK_FOR_K (INTVAL (x)) || CONST_OK_FOR_L (INTVAL (x)))
04768 *total = 0;
04769 else
04770 *total = COSTS_N_INSNS (1);
04771 return true;
04772 }
04773
04774 case CONST_DOUBLE:
04775 *total = COSTS_N_INSNS (1);
04776 return true;
04777
04778 case CONST:
04779 case SYMBOL_REF:
04780 case LABEL_REF:
04781 *total = COSTS_N_INSNS (3);
04782 return true;
04783
04784 case MULT:
04785
04786
04787
04788
04789
04790 if (GET_MODE_SIZE (GET_MODE (x)) > 2)
04791 *total = COSTS_N_INSNS (10);
04792 else
04793 *total = COSTS_N_INSNS (2);
04794 return true;
04795
04796 case PLUS:
04797 case MINUS:
04798 case ASHIFT:
04799 case ASHIFTRT:
04800 case LSHIFTRT:
04801 *total = COSTS_N_INSNS (1);
04802 return true;
04803
04804 case DIV:
04805 case UDIV:
04806 case MOD:
04807 case UMOD:
04808
04809
04810 *total = COSTS_N_INSNS (60);
04811 return true;
04812
04813 default:
04814 return false;
04815 }
04816 }
04817
04818
04819
04820
04821 int
04822 ia64_register_move_cost (enum machine_mode mode, enum reg_class from,
04823 enum reg_class to)
04824 {
04825
04826 if (to == ADDL_REGS)
04827 to = GR_REGS;
04828 if (from == ADDL_REGS)
04829 from = GR_REGS;
04830
04831
04832
04833 if (from < to)
04834 {
04835 enum reg_class tmp = to;
04836 to = from, from = tmp;
04837 }
04838
04839
04840
04841
04842
04843 if (mode == XFmode || mode == RFmode)
04844 {
04845 if (to != GR_REGS || from != GR_REGS)
04846 return MEMORY_MOVE_COST (mode, to, 0);
04847 else
04848 return 3;
04849 }
04850
04851 switch (to)
04852 {
04853 case PR_REGS:
04854
04855 if (from == PR_REGS)
04856 return 3;
04857
04858 if (from != GR_REGS)
04859 return MEMORY_MOVE_COST (mode, to, 0);
04860 break;
04861
04862 case BR_REGS:
04863
04864 if (from != GR_REGS && from != GR_AND_BR_REGS)
04865 return MEMORY_MOVE_COST (mode, to, 0);
04866 break;
04867
04868 case AR_I_REGS:
04869 case AR_M_REGS:
04870
04871 if (from != GR_REGS)
04872 return MEMORY_MOVE_COST (mode, to, 0);
04873 break;
04874
04875 case GR_REGS:
04876 case FR_REGS:
04877 case FP_REGS:
04878 case GR_AND_FR_REGS:
04879 case GR_AND_BR_REGS:
04880 case ALL_REGS:
04881 break;
04882
04883 default:
04884 gcc_unreachable ();
04885 }
04886
04887 return 2;
04888 }
04889
04890
04891
04892
04893 enum reg_class
04894 ia64_preferred_reload_class (rtx x, enum reg_class class)
04895 {
04896 switch (class)
04897 {
04898 case FR_REGS:
04899 case FP_REGS:
04900
04901
04902
04903 if (MEM_P (x) && MEM_VOLATILE_P (x))
04904 return NO_REGS;
04905
04906
04907 if (CONSTANT_P (x))
04908 return NO_REGS;
04909 break;
04910
04911 case AR_M_REGS:
04912 case AR_I_REGS:
04913 if (!OBJECT_P (x))
04914 return NO_REGS;
04915 break;
04916
04917 default:
04918 break;
04919 }
04920
04921 return class;
04922 }
04923
04924
04925
04926
04927
04928
04929 enum reg_class
04930 ia64_secondary_reload_class (enum reg_class class,
04931 enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
04932 {
04933 int regno = -1;
04934
04935 if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
04936 regno = true_regnum (x);
04937
04938 switch (class)
04939 {
04940 case BR_REGS:
04941 case AR_M_REGS:
04942 case AR_I_REGS:
04943
04944
04945
04946
04947
04948
04949
04950
04951
04952
04953
04954
04955 if (regno >= 0 && ! GENERAL_REGNO_P (regno))
04956 return GR_REGS;
04957
04958
04959
04960 if (GET_CODE (x) == MEM)
04961 return GR_REGS;
04962 break;
04963
04964 case FR_REGS:
04965 case FP_REGS:
04966
04967 if (regno >= 0 && ! (FR_REGNO_P (regno) || GENERAL_REGNO_P (regno)))
04968 return GR_REGS;
04969
04970
04971
04972
04973
04974
04975
04976
04977 if (GET_CODE (x) == MEM
04978 && (GET_MODE (x) == SImode || GET_MODE (x) == HImode
04979 || GET_MODE (x) == QImode))
04980 return GR_REGS;
04981
04982
04983
04984
04985 if (GET_CODE (x) == CONST_INT)
04986 return GR_REGS;
04987
04988
04989
04990 if (GET_CODE (x) == PLUS)
04991 return GR_REGS;
04992 break;
04993
04994 case PR_REGS:
04995
04996
04997
04998
04999
05000
05001 if (GET_CODE (x) == MEM)
05002 return GR_REGS;
05003
05004
05005
05006 if (regno >= 0 && ! GENERAL_REGNO_P (regno) && ! PR_REGNO_P (regno))
05007 return GR_REGS;
05008 break;
05009
05010 default:
05011 break;
05012 }
05013
05014 return NO_REGS;
05015 }
05016
05017
05018
05019
05020
05021 void
05022 ia64_asm_output_external (FILE *file, tree decl, const char *name)
05023 {
05024 int save_referenced;
05025
05026
05027
05028
05029 if (TARGET_GNU_AS
05030 && (!TARGET_HPUX_LD
05031 || TREE_CODE (decl) != FUNCTION_DECL
05032 || strstr (name, "__builtin_") == name))
05033 return;
05034
05035
05036
05037
05038
05039
05040
05041 if (! strcmp (name, "__builtin_next_arg")
05042 || ! strcmp (name, "alloca")
05043 || ! strcmp (name, "__builtin_constant_p")
05044 || ! strcmp (name, "__builtin_args_info"))
05045 return;
05046
05047 if (TARGET_HPUX_LD)
05048 ia64_hpux_add_extern_decl (decl);
05049 else
05050 {
05051
05052
05053 save_referenced = TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl));
05054 if (TREE_CODE (decl) == FUNCTION_DECL)
05055 ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
05056 (*targetm.asm_out.globalize_label) (file, name);
05057 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = save_referenced;
05058 }
05059 }
05060
05061
05062
05063 static void
05064 fix_range (const char *const_str)
05065 {
05066 int i, first, last;
05067 char *str, *dash, *comma;
05068
05069
05070
05071
05072
05073
05074
05075 i = strlen (const_str);
05076 str = (char *) alloca (i + 1);
05077 memcpy (str, const_str, i + 1);
05078
05079 while (1)
05080 {
05081 dash = strchr (str, '-');
05082 if (!dash)
05083 {
05084 warning (0, "value of -mfixed-range must have form REG1-REG2");
05085 return;
05086 }
05087 *dash = '\0';
05088
05089 comma = strchr (dash + 1, ',');
05090 if (comma)
05091 *comma = '\0';
05092
05093 first = decode_reg_name (str);
05094 if (first < 0)
05095 {
05096 warning (0, "unknown register name: %s", str);
05097 return;
05098 }
05099
05100 last = decode_reg_name (dash + 1);
05101 if (last < 0)
05102 {
05103 warning (0, "unknown register name: %s", dash + 1);
05104 return;
05105 }
05106
05107 *dash = '-';
05108
05109 if (first > last)
05110 {
05111 warning (0, "%s-%s is an empty range", str, dash + 1);
05112 return;
05113 }
05114
05115 for (i = first; i <= last; ++i)
05116 fixed_regs[i] = call_used_regs[i] = 1;
05117
05118 if (!comma)
05119 break;
05120
05121 *comma = ',';
05122 str = comma + 1;
05123 }
05124 }
05125
05126
05127
05128 static bool
05129 ia64_handle_option (size_t code, const char *arg, int value)
05130 {
05131 switch (code)
05132 {
05133 case OPT_mfixed_range_:
05134 fix_range (arg);
05135 return true;
05136
05137 case OPT_mtls_size_:
05138 if (value != 14 && value != 22 && value != 64)
05139 error ("bad value %<%s%> for -mtls-size= switch", arg);
05140 return true;
05141
05142 case OPT_mtune_:
05143 {
05144 static struct pta
05145 {
05146 const char *name;
05147 enum processor_type processor;
05148 }
05149 const processor_alias_table[] =
05150 {
05151 {"itanium", PROCESSOR_ITANIUM},
05152 {"itanium1", PROCESSOR_ITANIUM},
05153 {"merced", PROCESSOR_ITANIUM},
05154 {"itanium2", PROCESSOR_ITANIUM2},
05155 {"mckinley", PROCESSOR_ITANIUM2},
05156 };
05157 int const pta_size = ARRAY_SIZE (processor_alias_table);
05158 int i;
05159
05160 for (i = 0; i < pta_size; i++)
05161 if (!strcmp (arg, processor_alias_table[i].name))
05162 {
05163 ia64_tune = processor_alias_table[i].processor;
05164 break;
05165 }
05166 if (i == pta_size)
05167 error ("bad value %<%s%> for -mtune= switch", arg);
05168 return true;
05169 }
05170
05171 default:
05172 return true;
05173 }
05174 }
05175
05176
05177
05178 void
05179 ia64_override_options (void)
05180 {
05181 if (TARGET_AUTO_PIC)
05182 target_flags |= MASK_CONST_GP;
05183
05184 if (TARGET_INLINE_SQRT == INL_MIN_LAT)
05185 {
05186 warning (0, "not yet implemented: latency-optimized inline square root");
05187 TARGET_INLINE_SQRT = INL_MAX_THR;
05188 }
05189
05190 ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload;
05191 flag_schedule_insns_after_reload = 0;
05192
05193 ia64_section_threshold = g_switch_set ? g_switch_value : IA64_DEFAULT_GVALUE;
05194
05195 init_machine_status = ia64_init_machine_status;
05196 }
05197
05198 static struct machine_function *
05199 ia64_init_machine_status (void)
05200 {
05201 return ggc_alloc_cleared (sizeof (struct machine_function));
05202 }
05203
05204 static enum attr_itanium_class ia64_safe_itanium_class (rtx);
05205 static enum attr_type ia64_safe_type (rtx);
05206
05207 static enum attr_itanium_class
05208 ia64_safe_itanium_class (rtx insn)
05209 {
05210 if (recog_memoized (insn) >= 0)
05211 return get_attr_itanium_class (insn);
05212 else
05213 return ITANIUM_CLASS_UNKNOWN;
05214 }
05215
05216 static enum attr_type
05217 ia64_safe_type (rtx insn)
05218 {
05219 if (recog_memoized (insn) >= 0)
05220 return get_attr_type (insn);
05221 else
05222 return TYPE_UNKNOWN;
05223 }
05224
05225
05226
05227
05228
05229
05230
05231
05232
05233
05234 #define REG_RP (BR_REG (0))
05235 #define REG_AR_CFM (FIRST_PSEUDO_REGISTER + 1)
05236
05237
05238 #define REG_VOLATILE (FIRST_PSEUDO_REGISTER + 2)
05239 #define AR_UNAT_BIT_0 (FIRST_PSEUDO_REGISTER + 3)
05240 #define NUM_REGS (AR_UNAT_BIT_0 + 64)
05241
05242
05243
05244
05245
05246
05247
05248
05249
05250
05251
05252
05253
05254
05255
05256
05257
05258
05259
05260
05261
05262 struct reg_write_state
05263 {
05264 unsigned int write_count : 2;
05265 unsigned int first_pred : 16;
05266 unsigned int written_by_fp : 1;
05267 unsigned int written_by_and : 1;
05268 unsigned int written_by_or : 1;
05269 };
05270
05271
05272 struct reg_write_state rws_sum[NUM_REGS];
05273
05274
05275 struct reg_write_state rws_insn[NUM_REGS];
05276
05277
05278
05279
05280 static int first_instruction;
05281
05282
05283
05284 struct reg_flags
05285 {
05286 unsigned int is_write : 1;
05287 unsigned int is_fp : 1;
05288 unsigned int is_branch : 1;
05289 unsigned int is_and : 1;
05290 unsigned int is_or : 1;
05291 unsigned int is_sibcall : 1;
05292 };
05293
05294 static void rws_update (struct reg_write_state *, int, struct reg_flags, int);
05295 static int rws_access_regno (int, struct reg_flags, int);
05296 static int rws_access_reg (rtx, struct reg_flags, int);
05297 static void update_set_flags (rtx, struct reg_flags *);
05298 static int set_src_needs_barrier (rtx, struct reg_flags, int);
05299 static int rtx_needs_barrier (rtx, struct reg_flags, int);
05300 static void init_insn_group_barriers (void);
05301 static int group_barrier_needed (rtx);
05302 static int safe_group_barrier_needed (rtx);
05303
05304
05305
05306
05307 static void
05308 rws_update (struct reg_write_state *rws, int regno, struct reg_flags flags, int pred)
05309 {
05310 if (pred)
05311 rws[regno].write_count++;
05312 else
05313 rws[regno].write_count = 2;
05314 rws[regno].written_by_fp |= flags.is_fp;
05315
05316 rws[regno].written_by_and = flags.is_and;
05317 rws[regno].written_by_or = flags.is_or;
05318 rws[regno].first_pred = pred;
05319 }
05320
05321
05322
05323
05324
05325 static int
05326 rws_access_regno (int regno, struct reg_flags flags, int pred)
05327 {
05328 int need_barrier = 0;
05329
05330 gcc_assert (regno < NUM_REGS);
05331
05332 if (! PR_REGNO_P (regno))
05333 flags.is_and = flags.is_or = 0;
05334
05335 if (flags.is_write)
05336 {
05337 int write_count;
05338
05339
05340 gcc_assert (!rws_insn[regno].write_count);
05341
05342
05343 rws_update (rws_insn, regno, flags, pred);
05344 write_count = rws_sum[regno].write_count;
05345
05346 switch (write_count)
05347 {
05348 case 0:
05349
05350 rws_update (rws_sum, regno, flags, pred);
05351 break;
05352
05353 case 1:
05354
05355
05356
05357
05358 if (flags.is_and && rws_sum[regno].written_by_and)
05359 ;
05360 else if (flags.is_or && rws_sum[regno].written_by_or)
05361 ;
05362 else if ((rws_sum[regno].first_pred ^ 1) != pred)
05363 need_barrier = 1;
05364 rws_update (rws_sum, regno, flags, pred);
05365 break;
05366
05367 case 2:
05368
05369
05370 if (flags.is_and && rws_sum[regno].written_by_and)
05371 ;
05372 else if (flags.is_or && rws_sum[regno].written_by_or)
05373 ;
05374 else
05375 need_barrier = 1;
05376 rws_sum[regno].written_by_and = flags.is_and;
05377 rws_sum[regno].written_by_or = flags.is_or;
05378 break;
05379
05380 default:
05381 gcc_unreachable ();
05382 }
05383 }
05384 else
05385 {
05386 if (flags.is_branch)
05387 {
05388
05389
05390
05391 if (REGNO_REG_CLASS (regno) == BR_REGS || regno == AR_PFS_REGNUM)
05392
05393
05394
05395
05396
05397 return 0;
05398
05399 if (REGNO_REG_CLASS (regno) == PR_REGS
05400 && ! rws_sum[regno].written_by_fp)
05401
05402
05403
05404 return 0;
05405 }
05406
05407 if (flags.is_and && rws_sum[regno].written_by_and)
05408 return 0;
05409 if (flags.is_or && rws_sum[regno].written_by_or)
05410 return 0;
05411
05412 switch (rws_sum[regno].write_count)
05413 {
05414 case 0:
05415
05416 break;
05417
05418 case 1:
05419
05420
05421
05422
05423 if ((rws_sum[regno].first_pred ^ 1) != pred)
05424 need_barrier = 1;
05425 break;
05426
05427 case 2:
05428
05429
05430 need_barrier = 1;
05431 break;
05432
05433 default:
05434 gcc_unreachable ();
05435 }
05436 }
05437
05438 return need_barrier;
05439 }
05440
05441 static int
05442 rws_access_reg (rtx reg, struct reg_flags flags, int pred)
05443 {
05444 int regno = REGNO (reg);
05445 int n = HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg));
05446
05447 if (n == 1)
05448 return rws_access_regno (regno, flags, pred);
05449 else
05450 {
05451 int need_barrier = 0;
05452 while (--n >= 0)
05453 need_barrier |= rws_access_regno (regno + n, flags, pred);
05454 return need_barrier;
05455 }
05456 }
05457
05458
05459
05460
05461 static void
05462 update_set_flags (rtx x, struct reg_flags *pflags)
05463 {
05464 rtx src = SET_SRC (x);
05465
05466 switch (GET_CODE (src))
05467 {
05468 case CALL:
05469 return;
05470
05471 case IF_THEN_ELSE:
05472
05473
05474
05475
05476
05477
05478
05479
05480
05481
05482 return;
05483
05484 default:
05485 if (COMPARISON_P (src)
05486 && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (src, 0))))
05487
05488
05489
05490 pflags->is_fp = 1;
05491
05492
05493
05494
05495 else if (GET_CODE (src) == AND)
05496 pflags->is_and = 1;
05497 else if (GET_CODE (src) == IOR)
05498 pflags->is_or = 1;
05499
05500 break;
05501 }
05502 }
05503
05504
05505
05506
05507
05508
05509 static int
05510 set_src_needs_barrier (rtx x, struct reg_flags flags, int pred)
05511 {
05512 int need_barrier = 0;
05513 rtx dst;
05514 rtx src = SET_SRC (x);
05515
05516 if (GET_CODE (src) == CALL)
05517
05518
05519 return rtx_needs_barrier (src, flags, pred);
05520 else if (SET_DEST (x) == pc_rtx)
05521 {
05522
05523
05524
05525 if (!ia64_spec_check_src_p (src))
05526 flags.is_branch = 1;
05527 return rtx_needs_barrier (src, flags, pred);
05528 }
05529
05530 if (ia64_spec_check_src_p (src))
05531
05532
05533 {
05534 gcc_assert (REG_P (XEXP (src, 2)));
05535 need_barrier = rtx_needs_barrier (XEXP (src, 2), flags, pred);
05536
05537
05538 src = XEXP (src, 1);
05539 }
05540
05541 need_barrier |= rtx_needs_barrier (src, flags, pred);
05542
05543 dst = SET_DEST (x);
05544 if (GET_CODE (dst) == ZERO_EXTRACT)
05545 {
05546 need_barrier |= rtx_needs_barrier (XEXP (dst, 1), flags, pred);
05547 need_barrier |= rtx_needs_barrier (XEXP (dst, 2), flags, pred);
05548 }
05549 return need_barrier;
05550 }
05551
05552
05553
05554
05555
05556 static int
05557 rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
05558 {
05559 int i, j;
05560 int is_complemented = 0;
05561 int need_barrier = 0;
05562 const char *format_ptr;
05563 struct reg_flags new_flags;
05564 rtx cond;
05565
05566 if (! x)
05567 return 0;
05568
05569 new_flags = flags;
05570
05571 switch (GET_CODE (x))
05572 {
05573 case SET:
05574 update_set_flags (x, &new_flags);
05575 need_barrier = set_src_needs_barrier (x, new_flags, pred);
05576 if (GET_CODE (SET_SRC (x)) != CALL)
05577 {
05578 new_flags.is_write = 1;
05579 need_barrier |= rtx_needs_barrier (SET_DEST (x), new_flags, pred);
05580 }
05581 break;
05582
05583 case CALL:
05584 new_flags.is_write = 0;
05585 need_barrier |= rws_access_regno (AR_EC_REGNUM, new_flags, pred);
05586
05587
05588
05589 if (! flags.is_sibcall && ! rws_insn[REG_AR_CFM].write_count)
05590 {
05591 new_flags.is_write = 1;
05592 need_barrier |= rws_access_regno (REG_RP, new_flags, pred);
05593 need_barrier |= rws_access_regno (AR_PFS_REGNUM, new_flags, pred);
05594 need_barrier |= rws_access_regno (REG_AR_CFM, new_flags, pred);
05595 }
05596 break;
05597
05598 case COND_EXEC:
05599
05600
05601 cond = COND_EXEC_TEST (x);
05602 gcc_assert (!pred);
05603 need_barrier = rtx_needs_barrier (cond, flags, 0);
05604
05605 if (GET_CODE (cond) == EQ)
05606 is_complemented = 1;
05607 cond = XEXP (cond, 0);
05608 gcc_assert (GET_CODE (cond) == REG
05609 && REGNO_REG_CLASS (REGNO (cond)) == PR_REGS);
05610 pred = REGNO (cond);
05611 if (is_complemented)
05612 ++pred;
05613
05614 need_barrier |= rtx_needs_barrier (COND_EXEC_CODE (x), flags, pred);
05615 return need_barrier;
05616
05617 case CLOBBER:
05618 case USE:
05619
05620 break;
05621
05622 case ASM_OPERANDS:
05623 case ASM_INPUT:
05624
05625
05626 if (GET_CODE (x) != ASM_OPERANDS
05627 || (MEM_VOLATILE_P (x) && TARGET_VOL_ASM_STOP))
05628 {
05629
05630
05631 if (! rws_insn[REG_VOLATILE].write_count)
05632 {
05633 new_flags.is_write = 1;
05634 rws_access_regno (REG_VOLATILE, new_flags, pred);
05635 }
05636 return 1;
05637 }
05638
05639
05640
05641
05642
05643
05644 for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; --i)
05645 if (rtx_needs_barrier (ASM_OPERANDS_INPUT (x, i), flags, pred))
05646 need_barrier = 1;
05647 break;
05648
05649 case PARALLEL:
05650 for (i = XVECLEN (x, 0) - 1; i >= 0; --i)
05651 {
05652 rtx pat = XVECEXP (x, 0, i);
05653 switch (GET_CODE (pat))
05654 {
05655 case SET:
05656 update_set_flags (pat, &new_flags);
05657 need_barrier |= set_src_needs_barrier (pat, new_flags, pred);
05658 break;
05659
05660 case USE:
05661 case CALL:
05662 case ASM_OPERANDS:
05663 need_barrier |= rtx_needs_barrier (pat, flags, pred);
05664 break;
05665
05666 case CLOBBER:
05667 case RETURN:
05668 break;
05669
05670 default:
05671 gcc_unreachable ();
05672 }
05673 }
05674 for (i = XVECLEN (x, 0) - 1; i >= 0; --i)
05675 {
05676 rtx pat = XVECEXP (x, 0, i);
05677 if (GET_CODE (pat) == SET)
05678 {
05679 if (GET_CODE (SET_SRC (pat)) != CALL)
05680 {
05681 new_flags.is_write = 1;
05682 need_barrier |= rtx_needs_barrier (SET_DEST (pat), new_flags,
05683 pred);
05684 }
05685 }
05686 else if (GET_CODE (pat) == CLOBBER || GET_CODE (pat) == RETURN)
05687 need_barrier |= rtx_needs_barrier (pat, flags, pred);
05688 }
05689 break;
05690
05691 case SUBREG:
05692 need_barrier |= rtx_needs_barrier (SUBREG_REG (x), flags, pred);
05693 break;
05694 case REG:
05695 if (REGNO (x) == AR_UNAT_REGNUM)
05696 {
05697 for (i = 0; i < 64; ++i)
05698 need_barrier |= rws_access_regno (AR_UNAT_BIT_0 + i, flags, pred);
05699 }
05700 else
05701 need_barrier = rws_access_reg (x, flags, pred);
05702 break;
05703
05704 case MEM:
05705
05706 new_flags.is_write = 0;
05707 need_barrier = rtx_needs_barrier (XEXP (x, 0), new_flags, pred);
05708 break;
05709
05710 case CONST_INT: case CONST_DOUBLE: case CONST_VECTOR:
05711 case SYMBOL_REF: case LABEL_REF: case CONST:
05712 break;
05713
05714
05715 case POST_INC: case POST_DEC:
05716 gcc_assert (GET_CODE (XEXP (x, 0)) == REG);
05717
05718 new_flags.is_write = 0;
05719 need_barrier = rws_access_reg (XEXP (x, 0), new_flags, pred);
05720 new_flags.is_write = 1;
05721 need_barrier |= rws_access_reg (XEXP (x, 0), new_flags, pred);
05722 break;
05723
05724 case POST_MODIFY:
05725 gcc_assert (GET_CODE (XEXP (x, 0)) == REG);
05726
05727 new_flags.is_write = 0;
05728 need_barrier = rws_access_reg (XEXP (x, 0), new_flags, pred);
05729 need_barrier |= rtx_needs_barrier (XEXP (x, 1), new_flags, pred);
05730 new_flags.is_write = 1;
05731 need_barrier |= rws_access_reg (XEXP (x, 0), new_flags, pred);
05732 break;
05733
05734
05735 case COMPARE: case PLUS: case MINUS: case MULT: case DIV:
05736 case MOD: case UDIV: case UMOD: case AND: case IOR:
05737 case XOR: case ASHIFT: case ROTATE: case ASHIFTRT: case LSHIFTRT:
05738 case ROTATERT: case SMIN: case SMAX: case UMIN: case UMAX:
05739 case NE: case EQ: case GE: case GT: case LE:
05740 case LT: case GEU: case GTU: case LEU: case LTU:
05741 need_barrier = rtx_needs_barrier (XEXP (x, 0), new_flags, pred);
05742 need_barrier |= rtx_needs_barrier (XEXP (x, 1), new_flags, pred);
05743 break;
05744
05745 case NEG: case NOT: case SIGN_EXTEND: case ZERO_EXTEND:
05746 case TRUNCATE: case FLOAT_EXTEND: case FLOAT_TRUNCATE: case FLOAT:
05747 case FIX: case UNSIGNED_FLOAT: case UNSIGNED_FIX: case ABS:
05748 case SQRT: case FFS: case POPCOUNT:
05749 need_barrier = rtx_needs_barrier (XEXP (x, 0), flags, pred);
05750 break;
05751
05752 case VEC_SELECT:
05753
05754
05755
05756
05757 need_barrier = rtx_needs_barrier (XEXP (x, 0), flags, pred);
05758 break;
05759
05760 case UNSPEC:
05761 switch (XINT (x, 1))
05762 {
05763 case UNSPEC_LTOFF_DTPMOD:
05764 case UNSPEC_LTOFF_DTPREL:
05765 case UNSPEC_DTPREL:
05766 case UNSPEC_LTOFF_TPREL:
05767 case UNSPEC_TPREL:
05768 case UNSPEC_PRED_REL_MUTEX:
05769 case UNSPEC_PIC_CALL:
05770 case UNSPEC_MF:
05771 case UNSPEC_FETCHADD_ACQ:
05772 case UNSPEC_BSP_VALUE:
05773 case UNSPEC_FLUSHRS:
05774 case UNSPEC_BUNDLE_SELECTOR:
05775 break;
05776
05777 case UNSPEC_GR_SPILL:
05778 case UNSPEC_GR_RESTORE:
05779 {
05780 HOST_WIDE_INT offset = INTVAL (XVECEXP (x, 0, 1));
05781 HOST_WIDE_INT bit = (offset >> 3) & 63;
05782
05783 need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
05784 new_flags.is_write = (XINT (x, 1) == UNSPEC_GR_SPILL);
05785 need_barrier |= rws_access_regno (AR_UNAT_BIT_0 + bit,
05786 new_flags, pred);
05787 break;
05788 }
05789
05790 case UNSPEC_FR_SPILL:
05791 case UNSPEC_FR_RESTORE:
05792 case UNSPEC_GETF_EXP:
05793 case UNSPEC_SETF_EXP:
05794 case UNSPEC_ADDP4:
05795 case UNSPEC_FR_SQRT_RECIP_APPROX:
05796 case UNSPEC_LDA:
05797 case UNSPEC_LDS:
05798 case UNSPEC_LDSA:
05799 case UNSPEC_CHKACLR:
05800 case UNSPEC_CHKS:
05801 need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
05802 break;
05803
05804 case UNSPEC_FR_RECIP_APPROX:
05805 case UNSPEC_SHRP:
05806 case UNSPEC_COPYSIGN:
05807 need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
05808 need_barrier |= rtx_needs_barrier (XVECEXP (x, 0, 1), flags, pred);
05809 break;
05810
05811 case UNSPEC_CMPXCHG_ACQ:
05812 need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 1), flags, pred);
05813 need_barrier |= rtx_needs_barrier (XVECEXP (x, 0, 2), flags, pred);
05814 break;
05815
05816 default:
05817 gcc_unreachable ();
05818 }
05819 break;
05820
05821 case UNSPEC_VOLATILE:
05822 switch (XINT (x, 1))
05823 {
05824 case UNSPECV_ALLOC:
05825
05826
05827
05828
05829
05830
05831
05832 rws_access_regno (AR_PFS_REGNUM, flags, pred);
05833
05834 new_flags.is_write = 1;
05835 rws_access_regno (REG_AR_CFM, new_flags, pred);
05836 return 1;
05837
05838 case UNSPECV_SET_BSP:
05839 need_barrier = 1;
05840 break;
05841
05842 case UNSPECV_BLOCKAGE:
05843 case UNSPECV_INSN_GROUP_BARRIER:
05844 case UNSPECV_BREAK:
05845 case UNSPECV_PSAC_ALL:
05846 case UNSPECV_PSAC_NORMAL:
05847 return 0;
05848
05849 default:
05850 gcc_unreachable ();
05851 }
05852 break;
05853
05854 case RETURN:
05855 new_flags.is_write = 0;
05856 need_barrier = rws_access_regno (REG_RP, flags, pred);
05857 need_barrier |= rws_access_regno (AR_PFS_REGNUM, flags, pred);
05858
05859 new_flags.is_write = 1;
05860 need_barrier |= rws_access_regno (AR_EC_REGNUM, new_flags, pred);
05861 need_barrier |= rws_access_regno (REG_AR_CFM, new_flags, pred);
05862 break;
05863
05864 default:
05865 format_ptr = GET_RTX_FORMAT (GET_CODE (x));
05866 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
05867 switch (format_ptr[i])
05868 {
05869 case '0':
05870 case 'i':
05871 case 'n':
05872 case 'w':
05873 case 's':
05874 case 'S':
05875 break;
05876
05877 case 'e':
05878 if (rtx_needs_barrier (XEXP (x, i), flags, pred))
05879 need_barrier = 1;
05880 break;
05881
05882 case 'E':
05883 for (j = XVECLEN (x, i) - 1; j >= 0; --j)
05884 if (rtx_needs_barrier (XVECEXP (x, i, j), flags, pred))
05885 need_barrier = 1;
05886 break;
05887
05888 default:
05889 gcc_unreachable ();
05890 }
05891 break;
05892 }
05893 return need_barrier;
05894 }
05895
05896
05897
05898
05899 static void
05900 init_insn_group_barriers (void)
05901 {
05902 memset (rws_sum, 0, sizeof (rws_sum));
05903 first_instruction = 1;
05904 }
05905
05906
05907
05908
05909
05910 static int
05911 group_barrier_needed (rtx insn)
05912 {
05913 rtx pat;
05914 int need_barrier = 0;
05915 struct reg_flags flags;
05916
05917 memset (&flags, 0, sizeof (flags));
05918 switch (GET_CODE (insn))
05919 {
05920 case NOTE:
05921 break;
05922
05923 case BARRIER:
05924
05925 break;
05926
05927 case CODE_LABEL:
05928 memset (rws_insn, 0, sizeof (rws_insn));
05929 return 1;
05930
05931 case CALL_INSN:
05932 flags.is_branch = 1;
05933 flags.is_sibcall = SIBLING_CALL_P (insn);
05934 memset (rws_insn, 0, sizeof (rws_insn));
05935
05936
05937 if ((pat = prev_active_insn (insn))
05938 && GET_CODE (pat) == CALL_INSN)
05939 {
05940 need_barrier = 1;
05941 break;
05942 }
05943
05944 need_barrier = rtx_needs_barrier (PATTERN (insn), flags, 0);
05945 break;
05946
05947 case JUMP_INSN:
05948 if (!ia64_spec_check_p (insn))
05949 flags.is_branch = 1;
05950
05951
05952 if ((pat = prev_active_insn (insn))
05953 && GET_CODE (pat) == CALL_INSN)
05954 {
05955 need_barrier = 1;
05956 break;
05957 }
05958
05959
05960 case INSN:
05961 if (GET_CODE (PATTERN (insn)) == USE
05962 || GET_CODE (PATTERN (insn)) == CLOBBER)
05963
05964
05965
05966 break;
05967
05968 pat = PATTERN (insn);
05969
05970
05971 switch (recog_memoized (insn))
05972 {
05973
05974
05975 case CODE_FOR_epilogue_deallocate_stack:
05976 case CODE_FOR_prologue_allocate_stack:
05977 pat = XVECEXP (pat, 0, 0);
05978 break;
05979
05980
05981
05982 case CODE_FOR_doloop_end_internal:
05983 pat = XVECEXP (pat, 0, 1);
05984 break;
05985
05986
05987 case CODE_FOR_pred_rel_mutex:
05988 case CODE_FOR_prologue_use:
05989 return 0;
05990
05991 default:
05992 break;
05993 }
05994
05995 memset (rws_insn, 0, sizeof (rws_insn));
05996 need_barrier = rtx_needs_barrier (pat, flags, 0);
05997
05998
05999
06000 if (! need_barrier)
06001 need_barrier = rws_access_regno (REG_VOLATILE, flags, 0);
06002 break;
06003
06004 default:
06005 gcc_unreachable ();
06006 }
06007
06008 if (first_instruction && INSN_P (insn)
06009 && ia64_safe_itanium_class (insn) != ITANIUM_CLASS_IGNORE
06010 && GET_CODE (PATTERN (insn)) != USE
06011 && GET_CODE (PATTERN (insn)) != CLOBBER)
06012 {
06013 need_barrier = 0;
06014 first_instruction = 0;
06015 }
06016
06017 return need_barrier;
06018 }
06019
06020
06021
06022 static int
06023 safe_group_barrier_needed (rtx insn)
06024 {
06025 struct reg_write_state rws_saved[NUM_REGS];
06026 int saved_first_instruction;
06027 int t;
06028
06029 memcpy (rws_saved, rws_sum, NUM_REGS * sizeof *rws_saved);
06030 saved_first_instruction = first_instruction;
06031
06032 t = group_barrier_needed (insn);
06033
06034 memcpy (rws_sum, rws_saved, NUM_REGS * sizeof *rws_saved);
06035 first_instruction = saved_first_instruction;
06036
06037 return t;
06038 }
06039
06040
06041
06042
06043
06044
06045
06046
06047 static void
06048 emit_insn_group_barriers (FILE *dump)
06049 {
06050 rtx insn;
06051 rtx last_label = 0;
06052 int insns_since_last_label = 0;
06053
06054 init_insn_group_barriers ();
06055
06056 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
06057 {
06058 if (GET_CODE (insn) == CODE_LABEL)
06059 {
06060 if (insns_since_last_label)
06061 last_label = insn;
06062 insns_since_last_label = 0;
06063 }
06064 else if (GET_CODE (insn) == NOTE
06065 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
06066 {
06067 if (insns_since_last_label)
06068 last_label = insn;
06069 insns_since_last_label = 0;
06070 }
06071 else if (GET_CODE (insn) == INSN
06072 && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
06073 && XINT (PATTERN (insn), 1) == UNSPECV_INSN_GROUP_BARRIER)
06074 {
06075 init_insn_group_barriers ();
06076 last_label = 0;
06077 }
06078 else if (INSN_P (insn))
06079 {
06080 insns_since_last_label = 1;
06081
06082 if (group_barrier_needed (insn))
06083 {
06084 if (last_label)
06085 {
06086 if (dump)
06087 fprintf (dump, "Emitting stop before label %d\n",
06088 INSN_UID (last_label));
06089 emit_insn_before (gen_insn_group_barrier (GEN_INT (3)), last_label);
06090 insn = last_label;
06091
06092 init_insn_group_barriers ();
06093 last_label = 0;
06094 }
06095 }
06096 }
06097 }
06098 }
06099
06100
06101
06102
06103 static void
06104 emit_all_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
06105 {
06106 rtx insn;
06107
06108 init_insn_group_barriers ();
06109
06110 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
06111 {
06112 if (GET_CODE (insn) == BARRIER)
06113 {
06114 rtx last = prev_active_insn (insn);
06115
06116 if (! last)
06117 continue;
06118 if (GET_CODE (last) == JUMP_INSN
06119 && GET_CODE (PATTERN (last)) == ADDR_DIFF_VEC)
06120 last = prev_active_insn (last);
06121 if (recog_memoized (last) != CODE_FOR_insn_group_barrier)
06122 emit_insn_after (gen_insn_group_barrier (GEN_INT (3)), last);
06123
06124 init_insn_group_barriers ();
06125 }
06126 else if (INSN_P (insn))
06127 {
06128 if (recog_memoized (insn) == CODE_FOR_insn_group_barrier)
06129 init_insn_group_barriers ();
06130 else if (group_barrier_needed (insn))
06131 {
06132 emit_insn_before (gen_insn_group_barrier (GEN_INT (3)), insn);
06133 init_insn_group_barriers ();
06134 group_barrier_needed (insn);
06135 }
06136 }
06137 }
06138 }
06139
06140
06141
06142
06143
06144 #define NR_BUNDLES 10
06145
06146
06147
06148 static const char *bundle_name [NR_BUNDLES] =
06149 {
06150 ".mii",
06151 ".mmi",
06152 ".mfi",
06153 ".mmf",
06154 #if NR_BUNDLES == 10
06155 ".bbb",
06156 ".mbb",
06157 #endif
06158 ".mib",
06159 ".mmb",
06160 ".mfb",
06161 ".mlx"
06162 };
06163
06164
06165
06166 int ia64_final_schedule = 0;
06167
06168
06169
06170 static int _0mii_, _0mmi_, _0mfi_, _0mmf_;
06171 static int _0bbb_, _0mbb_, _0mib_, _0mmb_, _0mfb_, _0mlx_;
06172
06173 static int _1mii_, _1mmi_, _1mfi_, _1mmf_;
06174 static int _1bbb_, _1mbb_, _1mib_, _1mmb_, _1mfb_, _1mlx_;
06175
06176 static int pos_1, pos_2, pos_3, pos_4, pos_5, pos_6;
06177
06178
06179
06180 static rtx dfa_stop_insn;
06181
06182
06183
06184 static rtx last_scheduled_insn;
06185
06186
06187
06188 static size_t dfa_state_size;
06189
06190
06191
06192
06193 static state_t temp_dfa_state = NULL;
06194
06195
06196
06197
06198 static state_t prev_cycle_state = NULL;
06199
06200
06201
06202
06203 static char *stops_p = NULL;
06204
06205
06206
06207
06208 static int *spec_check_no = NULL;
06209
06210
06211 static int max_uid = 0;
06212
06213
06214
06215 static int stop_before_p = 0;
06216
06217
06218
06219
06220 static int clocks_length;
06221
06222
06223
06224
06225
06226 static int *clocks;
06227
06228
06229
06230
06231 static int *add_cycles;
06232
06233
06234 static int pending_data_specs = 0;
06235
06236 static rtx ia64_single_set (rtx);
06237 static void ia64_emit_insn_before (rtx, rtx);
06238
06239
06240
06241 const char *
06242 get_bundle_name (int b)
06243 {
06244 return bundle_name[b];
06245 }
06246
06247
06248
06249
06250 static int
06251 ia64_issue_rate (void)
06252 {
06253 return 6;
06254 }
06255
06256
06257
06258 static rtx
06259 ia64_single_set (rtx insn)
06260 {
06261 rtx x = PATTERN (insn), ret;
06262 if (GET_CODE (x) == COND_EXEC)
06263 x = COND_EXEC_CODE (x);
06264 if (GET_CODE (x) == SET)
06265 return x;
06266
06267
06268
06269
06270 switch (recog_memoized (insn))
06271 {
06272 case CODE_FOR_prologue_allocate_stack:
06273 case CODE_FOR_epilogue_deallocate_stack:
06274 ret = XVECEXP (x, 0, 0);
06275 break;
06276
06277 default:
06278 ret = single_set_2 (insn, x);
06279 break;
06280 }
06281
06282 return ret;
06283 }
06284
06285
06286
06287
06288
06289 static int
06290 ia64_adjust_cost_2 (rtx insn, int dep_type1, rtx dep_insn, int cost)
06291 {
06292 enum reg_note dep_type = (enum reg_note) dep_type1;
06293 enum attr_itanium_class dep_class;
06294 enum attr_itanium_class insn_class;
06295
06296 if (dep_type != REG_DEP_OUTPUT)
06297 return cost;
06298
06299 insn_class = ia64_safe_itanium_class (insn);
06300 dep_class = ia64_safe_itanium_class (dep_insn);
06301 if (dep_class == ITANIUM_CLASS_ST || dep_class == ITANIUM_CLASS_STF
06302 || insn_class == ITANIUM_CLASS_ST || insn_class == ITANIUM_CLASS_STF)
06303 return 0;
06304
06305 return cost;
06306 }
06307
06308
06309
06310
06311 static void
06312 ia64_emit_insn_before (rtx insn, rtx before)
06313 {
06314 emit_insn_before (insn, before);
06315 }
06316
06317
06318
06319
06320
06321
06322 static void
06323 ia64_dependencies_evaluation_hook (rtx head, rtx tail)
06324 {
06325 rtx insn, link, next, next_tail;
06326
06327
06328
06329
06330 if (!reload_completed)
06331 return;
06332
06333 next_tail = NEXT_INSN (tail);
06334 for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
06335 if (INSN_P (insn))
06336 insn->call = 0;
06337 for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
06338 if (INSN_P (insn)
06339 && ia64_safe_itanium_class (insn) == ITANIUM_CLASS_IALU)
06340 {
06341 for (link = INSN_DEPEND (insn); link != 0; link = XEXP (link, 1))
06342 {
06343 enum attr_itanium_class c;
06344
06345 if (REG_NOTE_KIND (link) != REG_DEP_TRUE)
06346 continue;
06347 next = XEXP (link, 0);
06348 c = ia64_safe_itanium_class (next);
06349 if ((c == ITANIUM_CLASS_ST
06350 || c == ITANIUM_CLASS_STF)
06351 && ia64_st_address_bypass_p (insn, next))
06352 break;
06353 else if ((c == ITANIUM_CLASS_LD
06354 || c == ITANIUM_CLASS_FLD
06355 || c == ITANIUM_CLASS_FLDP)
06356 && ia64_ld_address_bypass_p (insn, next))
06357 break;
06358 }
06359 insn->call = link != 0;
06360 }
06361 }
06362
06363
06364
06365 static void
06366 ia64_sched_init (FILE *dump ATTRIBUTE_UNUSED,
06367 int sched_verbose ATTRIBUTE_UNUSED,
06368 int max_ready ATTRIBUTE_UNUSED)
06369 {
06370 #ifdef ENABLE_CHECKING
06371 rtx insn;
06372
06373 if (reload_completed)
06374 for (insn = NEXT_INSN (current_sched_info->prev_head);
06375 insn != current_sched_info->next_tail;
06376 insn = NEXT_INSN (insn))
06377 gcc_assert (!SCHED_GROUP_P (insn));
06378 #endif
06379 last_scheduled_insn = NULL_RTX;
06380 init_insn_group_barriers ();
06381 }
06382
06383
06384
06385 static void
06386 ia64_sched_init_global (FILE *dump ATTRIBUTE_UNUSED,
06387 int sched_verbose ATTRIBUTE_UNUSED,
06388 int max_ready ATTRIBUTE_UNUSED)
06389 {
06390 gcc_assert (!pending_data_specs);
06391 }
06392
06393
06394 static void
06395 ia64_sched_finish_global (FILE *dump ATTRIBUTE_UNUSED,
06396 int sched_verbose ATTRIBUTE_UNUSED)
06397 {
06398 free (spec_check_no);
06399 spec_check_no = 0;
06400 max_uid = 0;
06401 }
06402
06403
06404
06405
06406 static int
06407 ia64_dfa_sched_reorder (FILE *dump, int sched_verbose, rtx *ready,
06408 int *pn_ready, int clock_var ATTRIBUTE_UNUSED,
06409 int reorder_type)
06410 {
06411 int n_asms;
06412 int n_ready = *pn_ready;
06413 rtx *e_ready = ready + n_ready;
06414 rtx *insnp;
06415
06416 if (sched_verbose)
06417 fprintf (dump, "// ia64_dfa_sched_reorder (type %d):\n", reorder_type);
06418
06419 if (reorder_type == 0)
06420 {
06421
06422 n_asms = 0;
06423 for (insnp = ready; insnp < e_ready; insnp++)
06424 if (insnp < e_ready)
06425 {
06426 rtx insn = *insnp;
06427 enum attr_type t = ia64_safe_type (insn);
06428 if (t == TYPE_UNKNOWN)
06429 {
06430 if (GET_CODE (PATTERN (insn)) == ASM_INPUT
06431 || asm_noperands (PATTERN (insn)) >= 0)
06432 {
06433 rtx lowest = ready[n_asms];
06434 ready[n_asms] = insn;
06435 *insnp = lowest;
06436 n_asms++;
06437 }
06438 else
06439 {
06440 rtx highest = ready[n_ready - 1];
06441 ready[n_ready - 1] = insn;
06442 *insnp = highest;
06443 return 1;
06444 }
06445 }
06446 }
06447
06448 if (n_asms < n_ready)
06449 {
06450
06451 ready += n_asms;
06452 n_ready -= n_asms;
06453 }
06454 else if (n_ready > 0)
06455 return 1;
06456 }
06457
06458 if (ia64_final_schedule)
06459 {
06460 int deleted = 0;
06461 int nr_need_stop = 0;
06462
06463 for (insnp = ready; insnp < e_ready; insnp++)
06464 if (safe_group_barrier_needed (*insnp))
06465 nr_need_stop++;
06466
06467 if (reorder_type == 1 && n_ready == nr_need_stop)
06468 return 0;
06469 if (reorder_type == 0)
06470 return 1;
06471 insnp = e_ready;
06472
06473
06474 while (insnp-- > ready + deleted)
06475 while (insnp >= ready + deleted)
06476 {
06477 rtx insn = *insnp;
06478 if (! safe_group_barrier_needed (insn))
06479 break;
06480 memmove (ready + 1, ready, (insnp - ready) * sizeof (rtx));
06481 *ready = insn;
06482 deleted++;
06483 }
06484 n_ready -= deleted;
06485 ready += deleted;
06486 }
06487
06488 return 1;
06489 }
06490
06491
06492
06493
06494 static int
06495 ia64_sched_reorder (FILE *dump, int sched_verbose, rtx *ready, int *pn_ready,
06496 int clock_var)
06497 {
06498 return ia64_dfa_sched_reorder (dump, sched_verbose, ready,
06499 pn_ready, clock_var, 0);
06500 }
06501
06502
06503
06504
06505 static int
06506 ia64_sched_reorder2 (FILE *dump ATTRIBUTE_UNUSED,
06507 int sched_verbose ATTRIBUTE_UNUSED, rtx *ready,
06508 int *pn_ready, int clock_var)
06509 {
06510 if (ia64_tune == PROCESSOR_ITANIUM && reload_completed && last_scheduled_insn)
06511 clocks [INSN_UID (last_scheduled_insn)] = clock_var;
06512 return ia64_dfa_sched_reorder (dump, sched_verbose, ready, pn_ready,
06513 clock_var, 1);
06514 }
06515
06516
06517
06518
06519 static int
06520 ia64_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
06521 int sched_verbose ATTRIBUTE_UNUSED,
06522 rtx insn ATTRIBUTE_UNUSED,
06523 int can_issue_more ATTRIBUTE_UNUSED)
06524 {
06525 if (current_sched_info->flags & DO_SPECULATION)
06526
06527
06528 {
06529 if (DONE_SPEC (insn) & BEGIN_DATA)
06530 pending_data_specs++;
06531 if (CHECK_SPEC (insn) & BEGIN_DATA)
06532 pending_data_specs--;
06533 }
06534
06535 last_scheduled_insn = insn;
06536 memcpy (prev_cycle_state, curr_state, dfa_state_size);
06537 if (reload_completed)
06538 {
06539 int needed = group_barrier_needed (insn);
06540
06541 gcc_assert (!needed);
06542 if (GET_CODE (insn) == CALL_INSN)
06543 init_insn_group_barriers ();
06544 stops_p [INSN_UID (insn)] = stop_before_p;
06545 stop_before_p = 0;
06546 }
06547 return 1;
06548 }
06549
06550
06551
06552
06553 static int
06554 ia64_first_cycle_multipass_dfa_lookahead_guard (rtx insn)
06555 {
06556 gcc_assert (insn && INSN_P (insn));
06557 return ((!reload_completed
06558 || !safe_group_barrier_needed (insn))
06559 && ia64_first_cycle_multipass_dfa_lookahead_guard_spec (insn));
06560 }
06561
06562
06563
06564
06565 static bool
06566 ia64_first_cycle_multipass_dfa_lookahead_guard_spec (rtx insn)
06567 {
06568 gcc_assert (insn && INSN_P (insn));
06569
06570
06571 return (pending_data_specs < 16
06572 || !(TODO_SPEC (insn) & BEGIN_DATA));
06573 }
06574
06575
06576
06577
06578
06579 static rtx dfa_pre_cycle_insn;
06580
06581
06582
06583
06584
06585 static int
06586 ia64_dfa_new_cycle (FILE *dump, int verbose, rtx insn, int last_clock,
06587 int clock, int *sort_p)
06588 {
06589 int setup_clocks_p = FALSE;
06590
06591 gcc_assert (insn && INSN_P (insn));
06592 if ((reload_completed && safe_group_barrier_needed (insn))
06593 || (last_scheduled_insn
06594 && (GET_CODE (last_scheduled_insn) == CALL_INSN
06595 || GET_CODE (PATTERN (last_scheduled_insn)) == ASM_INPUT
06596 || asm_noperands (PATTERN (last_scheduled_insn)) >= 0)))
06597 {
06598 init_insn_group_barriers ();
06599 if (verbose && dump)
06600 fprintf (dump, "// Stop should be before %d%s\n", INSN_UID (insn),
06601 last_clock == clock ? " + cycle advance" : "");
06602 stop_before_p = 1;
06603 if (last_clock == clock)
06604 {
06605 state_transition (curr_state, dfa_stop_insn);
06606 if (TARGET_EARLY_STOP_BITS)
06607 *sort_p = (last_scheduled_insn == NULL_RTX
06608 || GET_CODE (last_scheduled_insn) != CALL_INSN);
06609 else
06610 *sort_p = 0;
06611 return 1;
06612 }
06613 else if (reload_completed)
06614 setup_clocks_p = TRUE;
06615 if (GET_CODE (PATTERN (last_scheduled_insn)) == ASM_INPUT
06616 || asm_noperands (PATTERN (last_scheduled_insn)) >= 0)
06617 state_reset (curr_state);
06618 else
06619 {
06620 memcpy (curr_state, prev_cycle_state, dfa_state_size);
06621 state_transition (curr_state, dfa_stop_insn);
06622 state_transition (curr_state, dfa_pre_cycle_insn);
06623 state_transition (curr_state, NULL);
06624 }
06625 }
06626 else if (reload_completed)
06627 setup_clocks_p = TRUE;
06628 if (setup_clocks_p && ia64_tune == PROCESSOR_ITANIUM
06629 && GET_CODE (PATTERN (insn)) != ASM_INPUT
06630 && asm_noperands (PATTERN (insn)) < 0)
06631 {
06632 enum attr_itanium_class c = ia64_safe_itanium_class (insn);
06633
06634 if (c != ITANIUM_CLASS_MMMUL && c != ITANIUM_CLASS_MMSHF)
06635 {
06636 rtx link;
06637 int d = -1;
06638
06639 for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
06640 if (REG_NOTE_KIND (link) == 0)
06641 {
06642 enum attr_itanium_class dep_class;
06643 rtx dep_insn = XEXP (link, 0);
06644
06645 dep_class = ia64_safe_itanium_class (dep_insn);
06646 if ((dep_class == ITANIUM_CLASS_MMMUL
06647 || dep_class == ITANIUM_CLASS_MMSHF)
06648 && last_clock - clocks [INSN_UID (dep_insn)] < 4
06649 && (d < 0
06650 || last_clock - clocks [INSN_UID (dep_insn)] < d))
06651 d = last_clock - clocks [INSN_UID (dep_insn)];
06652 }
06653 if (d >= 0)
06654 add_cycles [INSN_UID (insn)] = 3 - d;
06655 }
06656 }
06657 return 0;
06658 }
06659
06660
06661
06662 static void
06663 ia64_h_i_d_extended (void)
06664 {
06665 if (current_sched_info->flags & DO_SPECULATION)
06666 {
06667 int new_max_uid = get_max_uid () + 1;
06668
06669 spec_check_no = xrecalloc (spec_check_no, new_max_uid,
06670 max_uid, sizeof (*spec_check_no));
06671 max_uid = new_max_uid;
06672 }
06673
06674 if (stops_p != NULL)
06675 {
06676 int new_clocks_length = get_max_uid () + 1;
06677
06678 stops_p = xrecalloc (stops_p, new_clocks_length, clocks_length, 1);
06679
06680 if (ia64_tune == PROCESSOR_ITANIUM)
06681 {
06682 clocks = xrecalloc (clocks, new_clocks_length, clocks_length,
06683 sizeof (int));
06684 add_cycles = xrecalloc (add_cycles, new_clocks_length, clocks_length,
06685 sizeof (int));
06686 }
06687
06688 clocks_length = new_clocks_length;
06689 }
06690 }
06691
06692
06693 enum SPEC_MODES
06694 {
06695 SPEC_MODE_INVALID = -1,
06696 SPEC_MODE_FIRST = 0,
06697 SPEC_MODE_FOR_EXTEND_FIRST = 1,
06698 SPEC_MODE_FOR_EXTEND_LAST = 3,
06699 SPEC_MODE_LAST = 8
06700 };
06701
06702
06703 static int
06704 ia64_mode_to_int (enum machine_mode mode)
06705 {
06706 switch (mode)
06707 {
06708 case BImode: return 0;
06709 case QImode: return 1;
06710 case HImode: return 2;
06711 case SImode: return 3;
06712 case DImode: return 4;
06713 case SFmode: return 5;
06714 case DFmode: return 6;
06715 case XFmode: return 7;
06716 case TImode:
06717
06718
06719
06720 return SPEC_MODE_INVALID;
06721 default: return SPEC_MODE_INVALID;
06722 }
06723 }
06724
06725
06726 static void
06727 ia64_set_sched_flags (spec_info_t spec_info)
06728 {
06729 unsigned int *flags = &(current_sched_info->flags);
06730
06731 if (*flags & SCHED_RGN
06732 || *flags & SCHED_EBB)
06733 {
06734 int mask = 0;
06735
06736 if ((mflag_sched_br_data_spec && !reload_completed && optimize > 0)
06737 || (mflag_sched_ar_data_spec && reload_completed))
06738 {
06739 mask |= BEGIN_DATA;
06740
06741 if ((mflag_sched_br_in_data_spec && !reload_completed)
06742 || (mflag_sched_ar_in_data_spec && reload_completed))
06743 mask |= BE_IN_DATA;
06744 }
06745
06746 if (mflag_sched_control_spec)
06747 {
06748 mask |= BEGIN_CONTROL;
06749
06750 if (mflag_sched_in_control_spec)
06751 mask |= BE_IN_CONTROL;
06752 }
06753
06754 gcc_assert (*flags & USE_GLAT);
06755
06756 if (mask)
06757 {
06758 *flags |= USE_DEPS_LIST | DETACH_LIFE_INFO | DO_SPECULATION;
06759
06760 spec_info->mask = mask;
06761 spec_info->flags = 0;
06762
06763 if ((mask & DATA_SPEC) && mflag_sched_prefer_non_data_spec_insns)
06764 spec_info->flags |= PREFER_NON_DATA_SPEC;
06765
06766 if ((mask & CONTROL_SPEC)
06767 && mflag_sched_prefer_non_control_spec_insns)
06768 spec_info->flags |= PREFER_NON_CONTROL_SPEC;
06769
06770 if (mflag_sched_spec_verbose)
06771 {
06772 if (sched_verbose >= 1)
06773 spec_info->dump = sched_dump;
06774 else
06775 spec_info->dump = stderr;
06776 }
06777 else
06778 spec_info->dump = 0;
06779
06780 if (mflag_sched_count_spec_in_critical_path)
06781 spec_info->flags |= COUNT_SPEC_IN_CRITICAL_PATH;
06782 }
06783 }
06784 }
06785
06786
06787
06788
06789
06790
06791 static int
06792 ia64_speculate_insn (rtx insn, ds_t ts, rtx *new_pat)
06793 {
06794 rtx pat, reg, mem, mem_reg;
06795 int mode_no, gen_p = 1;
06796 bool extend_p;
06797
06798 gcc_assert (!(ts & ~BEGIN_SPEC) && ts);
06799
06800 pat = PATTERN (insn);
06801
06802 if (GET_CODE (pat) == COND_EXEC)
06803 pat = COND_EXEC_CODE (pat);
06804
06805
06806 if (GET_CODE (pat) != SET)
06807 return -1;
06808
06809 reg = SET_DEST (pat);
06810
06811 if (!REG_P (reg) || !(GR_REGNO_P (REGNO (reg)) || FP_REGNO_P (REGNO (reg))))
06812 return -1;
06813
06814
06815 mem = SET_SRC (pat);
06816
06817
06818 if (GET_CODE (mem) == ZERO_EXTEND)
06819 {
06820 mem = XEXP (mem, 0);
06821 extend_p = true;
06822 }
06823 else
06824 extend_p = false;
06825
06826
06827 if (GET_CODE (mem) == UNSPEC)
06828 {
06829 int code;
06830
06831 code = XINT (mem, 1);
06832 if (code != UNSPEC_LDA && code != UNSPEC_LDS && code != UNSPEC_LDSA)
06833 return -1;
06834
06835 if ((code == UNSPEC_LDA && !(ts & BEGIN_CONTROL))
06836 || (code == UNSPEC_LDS && !(ts & BEGIN_DATA))
06837 || code == UNSPEC_LDSA)
06838 gen_p = 0;
06839
06840 mem = XVECEXP (mem, 0, 0);
06841 gcc_assert (MEM_P (mem));
06842 }
06843
06844
06845 if (!MEM_P (mem))
06846 return -1;
06847
06848
06849 mem_reg = XEXP (mem, 0);
06850 if (!REG_P (mem_reg))
06851 return -1;
06852
06853
06854
06855 mode_no = ia64_mode_to_int (GET_MODE (mem));
06856
06857 if (mode_no == SPEC_MODE_INVALID
06858 || (extend_p
06859 && !(SPEC_MODE_FOR_EXTEND_FIRST <= mode_no
06860 && mode_no <= SPEC_MODE_FOR_EXTEND_LAST)))
06861 return -1;
06862
06863 extract_insn_cached (insn);
06864 gcc_assert (reg == recog_data.operand[0] && mem == recog_data.operand[1]);
06865
06866 *new_pat = ia64_gen_spec_insn (insn, ts, mode_no, gen_p != 0, extend_p);
06867
06868 return gen_p;
06869 }
06870
06871 enum
06872 {
06873
06874 SPEC_GEN_EXTEND_OFFSET = SPEC_MODE_LAST - SPEC_MODE_FOR_EXTEND_FIRST + 1,
06875
06876 SPEC_N = (SPEC_MODE_LAST
06877 + SPEC_MODE_FOR_EXTEND_LAST - SPEC_MODE_FOR_EXTEND_FIRST + 2)
06878 };
06879
06880 enum SPEC_GEN_LD_MAP
06881 {
06882
06883 SPEC_GEN_A = 0 * SPEC_N,
06884
06885 SPEC_GEN_S = 1 * SPEC_N,
06886
06887 SPEC_GEN_SA = 2 * SPEC_N,
06888
06889
06890 SPEC_GEN_SA_FOR_S = 3 * SPEC_N
06891 };
06892
06893
06894 enum SPEC_GEN_CHECK_OFFSET
06895 {
06896 SPEC_GEN_CHKA_FOR_A_OFFSET = 4 * SPEC_N - SPEC_GEN_A,
06897 SPEC_GEN_CHKA_FOR_SA_OFFSET = 4 * SPEC_N - SPEC_GEN_SA
06898 };
06899
06900
06901
06902
06903
06904 static rtx
06905 ia64_gen_spec_insn (rtx insn, ds_t ts, int mode_no, bool gen_p, bool extend_p)
06906 {
06907 rtx pat, new_pat;
06908 int load_no;
06909 int shift = 0;
06910
06911 static rtx (* const gen_load[]) (rtx, rtx) = {
06912 gen_movbi_advanced,
06913 gen_movqi_advanced,
06914 gen_movhi_advanced,
06915 gen_movsi_advanced,
06916 gen_movdi_advanced,
06917 gen_movsf_advanced,
06918 gen_movdf_advanced,
06919 gen_movxf_advanced,
06920 gen_movti_advanced,
06921 gen_zero_extendqidi2_advanced,
06922 gen_zero_extendhidi2_advanced,
06923 gen_zero_extendsidi2_advanced,
06924
06925 gen_movbi_speculative,
06926 gen_movqi_speculative,
06927 gen_movhi_speculative,
06928 gen_movsi_speculative,
06929 gen_movdi_speculative,
06930 gen_movsf_speculative,
06931 gen_movdf_speculative,
06932 gen_movxf_speculative,
06933 gen_movti_speculative,
06934 gen_zero_extendqidi2_speculative,
06935 gen_zero_extendhidi2_speculative,
06936 gen_zero_extendsidi2_speculative,
06937
06938 gen_movbi_speculative_advanced,
06939 gen_movqi_speculative_advanced,
06940 gen_movhi_speculative_advanced,
06941 gen_movsi_speculative_advanced,
06942 gen_movdi_speculative_advanced,
06943 gen_movsf_speculative_advanced,
06944 gen_movdf_speculative_advanced,
06945 gen_movxf_speculative_advanced,
06946 gen_movti_speculative_advanced,
06947 gen_zero_extendqidi2_speculative_advanced,
06948 gen_zero_extendhidi2_speculative_advanced,
06949 gen_zero_extendsidi2_speculative_advanced,
06950
06951 gen_movbi_speculative_advanced,
06952 gen_movqi_speculative_advanced,
06953 gen_movhi_speculative_advanced,
06954 gen_movsi_speculative_advanced,
06955 gen_movdi_speculative_advanced,
06956 gen_movsf_speculative_advanced,
06957 gen_movdf_speculative_advanced,
06958 gen_movxf_speculative_advanced,
06959 gen_movti_speculative_advanced,
06960 gen_zero_extendqidi2_speculative_advanced,
06961 gen_zero_extendhidi2_speculative_advanced,
06962 gen_zero_extendsidi2_speculative_advanced
06963 };
06964
06965 load_no = extend_p ? mode_no + SPEC_GEN_EXTEND_OFFSET : mode_no;
06966
06967 if (ts & BEGIN_DATA)
06968 {
06969
06970
06971
06972
06973 if (ts & BEGIN_CONTROL)
06974 {
06975 load_no += SPEC_GEN_SA;
06976
06977 if (!mflag_sched_ldc)
06978 shift = SPEC_GEN_CHKA_FOR_SA_OFFSET;
06979 }
06980 else
06981 {
06982 load_no += SPEC_GEN_A;
06983
06984 if (!mflag_sched_ldc)
06985 shift = SPEC_GEN_CHKA_FOR_A_OFFSET;
06986 }
06987 }
06988 else if (ts & BEGIN_CONTROL)
06989 {
06990
06991 if (!mflag_control_ldc)
06992 load_no += SPEC_GEN_S;
06993 else
06994 {
06995 gcc_assert (mflag_sched_ldc);
06996 load_no += SPEC_GEN_SA_FOR_S;
06997 }
06998 }
06999 else
07000 gcc_unreachable ();
07001
07002
07003
07004 spec_check_no[INSN_UID (insn)] = load_no + shift + 1;
07005
07006 if (!gen_p)
07007 return 0;
07008
07009 new_pat = gen_load[load_no] (copy_rtx (recog_data.operand[0]),
07010 copy_rtx (recog_data.operand[1]));
07011
07012 pat = PATTERN (insn);
07013 if (GET_CODE (pat) == COND_EXEC)
07014 new_pat = gen_rtx_COND_EXEC (VOIDmode, copy_rtx
07015 (COND_EXEC_TEST (pat)), new_pat);
07016
07017 return new_pat;
07018 }
07019
07020
07021 enum { SPEC_GEN_CHECK_MUTATION_OFFSET = 5 * SPEC_N };
07022
07023
07024 static bool
07025 ia64_needs_block_p (rtx insn)
07026 {
07027 int check_no;
07028
07029 check_no = spec_check_no[INSN_UID(insn)] - 1;
07030 gcc_assert (0 <= check_no && check_no < SPEC_GEN_CHECK_MUTATION_OFFSET);
07031
07032 return ((SPEC_GEN_S <= check_no && check_no < SPEC_GEN_S + SPEC_N)
07033 || (4 * SPEC_N <= check_no && check_no < 4 * SPEC_N + SPEC_N));
07034 }
07035
07036
07037
07038
07039 static rtx
07040 ia64_gen_check (rtx insn, rtx label, bool mutate_p)
07041 {
07042 rtx op1, pat, check_pat;
07043
07044 static rtx (* const gen_check[]) (rtx, rtx) = {
07045 gen_movbi_clr,
07046 gen_movqi_clr,
07047 gen_movhi_clr,
07048 gen_movsi_clr,
07049 gen_movdi_clr,
07050 gen_movsf_clr,
07051 gen_movdf_clr,
07052 gen_movxf_clr,
07053 gen_movti_clr,
07054 gen_zero_extendqidi2_clr,
07055 gen_zero_extendhidi2_clr,
07056 gen_zero_extendsidi2_clr,
07057
07058 gen_speculation_check_bi,
07059 gen_speculation_check_qi,
07060 gen_speculation_check_hi,
07061 gen_speculation_check_si,
07062 gen_speculation_check_di,
07063 gen_speculation_check_sf,
07064 gen_speculation_check_df,
07065 gen_speculation_check_xf,
07066 gen_speculation_check_ti,
07067 gen_speculation_check_di,
07068 gen_speculation_check_di,
07069 gen_speculation_check_di,
07070
07071 gen_movbi_clr,
07072 gen_movqi_clr,
07073 gen_movhi_clr,
07074 gen_movsi_clr,
07075 gen_movdi_clr,
07076 gen_movsf_clr,
07077 gen_movdf_clr,
07078 gen_movxf_clr,
07079 gen_movti_clr,
07080 gen_zero_extendqidi2_clr,
07081 gen_zero_extendhidi2_clr,
07082 gen_zero_extendsidi2_clr,
07083
07084 gen_movbi_clr,
07085 gen_movqi_clr,
07086 gen_movhi_clr,
07087 gen_movsi_clr,
07088 gen_movdi_clr,
07089 gen_movsf_clr,
07090 gen_movdf_clr,
07091 gen_movxf_clr,
07092 gen_movti_clr,
07093 gen_zero_extendqidi2_clr,
07094 gen_zero_extendhidi2_clr,
07095 gen_zero_extendsidi2_clr,
07096
07097 gen_advanced_load_check_clr_bi,
07098 gen_advanced_load_check_clr_qi,
07099 gen_advanced_load_check_clr_hi,
07100 gen_advanced_load_check_clr_si,
07101 gen_advanced_load_check_clr_di,
07102 gen_advanced_load_check_clr_sf,
07103 gen_advanced_load_check_clr_df,
07104 gen_advanced_load_check_clr_xf,
07105 gen_advanced_load_check_clr_ti,
07106 gen_advanced_load_check_clr_di,
07107 gen_advanced_load_check_clr_di,
07108 gen_advanced_load_check_clr_di,
07109
07110
07111 gen_advanced_load_check_clr_bi,
07112 gen_advanced_load_check_clr_qi,
07113 gen_advanced_load_check_clr_hi,
07114 gen_advanced_load_check_clr_si,
07115 gen_advanced_load_check_clr_di,
07116 gen_advanced_load_check_clr_sf,
07117 gen_advanced_load_check_clr_df,
07118 gen_advanced_load_check_clr_xf,
07119 gen_advanced_load_check_clr_ti,
07120 gen_advanced_load_check_clr_di,
07121 gen_advanced_load_check_clr_di,
07122 gen_advanced_load_check_clr_di,
07123
07124 0,0,0,0,0,0,0,0,0,0,0,0,
07125
07126 gen_advanced_load_check_clr_bi,
07127 gen_advanced_load_check_clr_qi,
07128 gen_advanced_load_check_clr_hi,
07129 gen_advanced_load_check_clr_si,
07130 gen_advanced_load_check_clr_di,
07131 gen_advanced_load_check_clr_sf,
07132 gen_advanced_load_check_clr_df,
07133 gen_advanced_load_check_clr_xf,
07134 gen_advanced_load_check_clr_ti,
07135 gen_advanced_load_check_clr_di,
07136 gen_advanced_load_check_clr_di,
07137 gen_advanced_load_check_clr_di,
07138
07139 gen_speculation_check_bi,
07140 gen_speculation_check_qi,
07141 gen_speculation_check_hi,
07142 gen_speculation_check_si,
07143 gen_speculation_check_di,
07144 gen_speculation_check_sf,
07145 gen_speculation_check_df,
07146 gen_speculation_check_xf,
07147 gen_speculation_check_ti,
07148 gen_speculation_check_di,
07149 gen_speculation_check_di,
07150 gen_speculation_check_di
07151 };
07152
07153 extract_insn_cached (insn);
07154
07155 if (label)
07156 {
07157 gcc_assert (mutate_p || ia64_needs_block_p (insn));
07158 op1 = label;
07159 }
07160 else
07161 {
07162 gcc_assert (!mutate_p && !ia64_needs_block_p (insn));
07163 op1 = copy_rtx (recog_data.operand[1]);
07164 }
07165
07166 if (mutate_p)
07167
07168
07169
07170
07171
07172 {
07173 rtx link;
07174 int check_no = 0;
07175 rtx orig_pat = ORIG_PAT (insn);
07176
07177 for (link = RESOLVED_DEPS (insn); link; link = XEXP (link, 1))
07178 {
07179 rtx x = XEXP (link, 0);
07180
07181 if (ORIG_PAT (x) == orig_pat)
07182 check_no = spec_check_no[INSN_UID (x)];
07183 }
07184 gcc_assert (check_no);
07185
07186 spec_check_no[INSN_UID (insn)] = (check_no
07187 + SPEC_GEN_CHECK_MUTATION_OFFSET);
07188 }
07189
07190 check_pat = (gen_check[spec_check_no[INSN_UID (insn)] - 1]
07191 (copy_rtx (recog_data.operand[0]), op1));
07192
07193 pat = PATTERN (insn);
07194 if (GET_CODE (pat) == COND_EXEC)
07195 check_pat = gen_rtx_COND_EXEC (VOIDmode, copy_rtx (COND_EXEC_TEST (pat)),
07196 check_pat);
07197
07198 return check_pat;
07199 }
07200
07201
07202 static int
07203 ia64_spec_check_p (rtx x)
07204 {
07205 x = PATTERN (x);
07206 if (GET_CODE (x) == COND_EXEC)
07207 x = COND_EXEC_CODE (x);
07208 if (GET_CODE (x) == SET)
07209 return ia64_spec_check_src_p (SET_SRC (x));
07210 return 0;
07211 }
07212
07213
07214 static int
07215 ia64_spec_check_src_p (rtx src)
07216 {
07217 if (GET_CODE (src) == IF_THEN_ELSE)
07218 {
07219 rtx t;
07220
07221 t = XEXP (src, 0);
07222 if (GET_CODE (t) == NE)
07223 {
07224 t = XEXP (t, 0);
07225
07226 if (GET_CODE (t) == UNSPEC)
07227 {
07228 int code;
07229
07230 code = XINT (t, 1);
07231
07232 if (code == UNSPEC_CHKACLR
07233 || code == UNSPEC_CHKS
07234 || code == UNSPEC_LDCCLR)
07235 {
07236 gcc_assert (code != 0);
07237 return code;
07238 }
07239 }
07240 }
07241 }
07242 return 0;
07243 }
07244
07245
07246
07247
07248
07249
07250
07251 struct bundle_state
07252 {
07253
07254
07255 int unique_num;
07256 rtx insn;
07257
07258 short before_nops_num, after_nops_num;
07259 int insn_num;
07260
07261 int cost;
07262 int accumulated_insns_num;
07263
07264 int branch_deviation;
07265 struct bundle_state *next;
07266 struct bundle_state *originator;
07267
07268 struct bundle_state *allocated_states_chain;
07269
07270 state_t dfa_state;
07271 };
07272
07273
07274
07275 static struct bundle_state **index_to_bundle_states;
07276
07277
07278
07279 static int bundle_states_num;
07280
07281
07282
07283 static struct bundle_state *allocated_bundle_states_chain;
07284
07285
07286
07287
07288 static struct bundle_state *free_bundle_state_chain;
07289
07290
07291
07292
07293 static struct bundle_state *
07294 get_free_bundle_state (void)
07295 {
07296 struct bundle_state *result;
07297
07298 if (free_bundle_state_chain != NULL)
07299 {
07300 result = free_bundle_state_chain;
07301 free_bundle_state_chain = result->next;
07302 }
07303 else
07304 {
07305 result = xmalloc (sizeof (struct bundle_state));
07306 result->dfa_state = xmalloc (dfa_state_size);
07307 result->allocated_states_chain = allocated_bundle_states_chain;
07308 allocated_bundle_states_chain = result;
07309 }
07310 result->unique_num = bundle_states_num++;
07311 return result;
07312
07313 }
07314
07315
07316
07317 static void
07318 free_bundle_state (struct bundle_state *state)
07319 {
07320 state->next = free_bundle_state_chain;
07321 free_bundle_state_chain = state;
07322 }
07323
07324
07325
07326 static void
07327 initiate_bundle_states (void)
07328 {
07329 bundle_states_num = 0;
07330 free_bundle_state_chain = NULL;
07331 allocated_bundle_states_chain = NULL;
07332 }
07333
07334
07335
07336 static void
07337 finish_bundle_states (void)
07338 {
07339 struct bundle_state *curr_state, *next_state;
07340
07341 for (curr_state = allocated_bundle_states_chain;
07342 curr_state != NULL;
07343 curr_state = next_state)
07344 {
07345 next_state = curr_state->allocated_states_chain;
07346 free (curr_state->dfa_state);
07347 free (curr_state);
07348 }
07349 }
07350
07351
07352
07353
07354 static htab_t bundle_state_table;
07355
07356
07357
07358 static unsigned
07359 bundle_state_hash (const void *bundle_state)
07360 {
07361 const struct bundle_state *state = (struct bundle_state *) bundle_state;
07362 unsigned result, i;
07363
07364 for (result = i = 0; i < dfa_state_size; i++)
07365 result += (((unsigned char *) state->dfa_state) [i]
07366 << ((i % CHAR_BIT) * 3 + CHAR_BIT));
07367 return result + state->insn_num;
07368 }
07369
07370
07371
07372 static int
07373 bundle_state_eq_p (const void *bundle_state_1, const void *bundle_state_2)
07374 {
07375 const struct bundle_state * state1 = (struct bundle_state *) bundle_state_1;
07376 const struct bundle_state * state2 = (struct bundle_state *) bundle_state_2;
07377
07378 return (state1->insn_num == state2->insn_num
07379 && memcmp (state1->dfa_state, state2->dfa_state,
07380 dfa_state_size) == 0);
07381 }
07382
07383
07384
07385
07386
07387 static int
07388 insert_bundle_state (struct bundle_state *bundle_state)
07389 {
07390 void **entry_ptr;
07391
07392 entry_ptr = htab_find_slot (bundle_state_table, bundle_state, 1);
07393 if (*entry_ptr == NULL)
07394 {
07395 bundle_state->next = index_to_bundle_states [bundle_state->insn_num];
07396 index_to_bundle_states [bundle_state->insn_num] = bundle_state;
07397 *entry_ptr = (void *) bundle_state;
07398 return TRUE;
07399 }
07400 else if (bundle_state->cost < ((struct bundle_state *) *entry_ptr)->cost
07401 || (bundle_state->cost == ((struct bundle_state *) *entry_ptr)->cost
07402 && (((struct bundle_state *)*entry_ptr)->accumulated_insns_num
07403 > bundle_state->accumulated_insns_num
07404 || (((struct bundle_state *)
07405 *entry_ptr)->accumulated_insns_num
07406 == bundle_state->accumulated_insns_num
07407 && ((struct bundle_state *)
07408 *entry_ptr)->branch_deviation
07409 > bundle_state->branch_deviation))))
07410
07411 {
07412 struct bundle_state temp;
07413
07414 temp = *(struct bundle_state *) *entry_ptr;
07415 *(struct bundle_state *) *entry_ptr = *bundle_state;
07416 ((struct bundle_state *) *entry_ptr)->next = temp.next;
07417 *bundle_state = temp;
07418 }
07419 return FALSE;
07420 }
07421
07422
07423
07424 static void
07425 initiate_bundle_state_table (void)
07426 {
07427 bundle_state_table = htab_create (50, bundle_state_hash, bundle_state_eq_p,
07428 (htab_del) 0);
07429 }
07430
07431
07432
07433 static void
07434 finish_bundle_state_table (void)
07435 {
07436 htab_delete (bundle_state_table);
07437 }
07438
07439
07440
07441
07442
07443
07444 static rtx ia64_nop;
07445
07446
07447
07448
07449
07450 static int
07451 try_issue_nops (struct bundle_state *curr_state, int nops_num)
07452 {
07453 int i;
07454
07455 for (i = 0; i < nops_num; i++)
07456 if (state_transition (curr_state->dfa_state, ia64_nop) >= 0)
07457 {
07458 free_bundle_state (curr_state);
07459 return FALSE;
07460 }
07461 return TRUE;
07462 }
07463
07464
07465
07466
07467
07468 static int
07469 try_issue_insn (struct bundle_state *curr_state, rtx insn)
07470 {
07471 if (insn && state_transition (curr_state->dfa_state, insn) >= 0)
07472 {
07473 free_bundle_state (curr_state);
07474 return FALSE;
07475 }
07476 return TRUE;
07477 }
07478
07479
07480
07481
07482
07483
07484
07485
07486 static void
07487 issue_nops_and_insn (struct bundle_state *originator, int before_nops_num,
07488 rtx insn, int try_bundle_end_p, int only_bundle_end_p)
07489 {
07490 struct bundle_state *curr_state;
07491
07492 curr_state = get_free_bundle_state ();
07493 memcpy (curr_state->dfa_state, originator->dfa_state, dfa_state_size);
07494 curr_state->insn = insn;
07495 curr_state->insn_num = originator->insn_num + 1;
07496 curr_state->cost = originator->cost;
07497 curr_state->originator = originator;
07498 curr_state->before_nops_num = before_nops_num;
07499 curr_state->after_nops_num = 0;
07500 curr_state->accumulated_insns_num
07501 = originator->accumulated_insns_num + before_nops_num;
07502 curr_state->branch_deviation = originator->branch_deviation;
07503 gcc_assert (insn);
07504 if (INSN_CODE (insn) == CODE_FOR_insn_group_barrier)
07505 {
07506 gcc_assert (GET_MODE (insn) != TImode);
07507 if (!try_issue_nops (curr_state, before_nops_num))
07508 return;
07509 if (!try_issue_insn (curr_state, insn))
07510 return;
07511 memcpy (temp_dfa_state, curr_state->dfa_state, dfa_state_size);
07512 if (state_transition (temp_dfa_state, dfa_pre_cycle_insn) >= 0
07513 && curr_state->accumulated_insns_num % 3 != 0)
07514 {
07515 free_bundle_state (curr_state);
07516 return;
07517 }
07518 }
07519 else if (GET_MODE (insn) != TImode)
07520 {
07521 if (!try_issue_nops (curr_state, before_nops_num))
07522 return;
07523 if (!try_issue_insn (curr_state, insn))
07524 return;
07525 curr_state->accumulated_insns_num++;
07526 gcc_assert (GET_CODE (PATTERN (insn)) != ASM_INPUT
07527 && asm_noperands (PATTERN (insn)) < 0);
07528
07529 if (ia64_safe_type (insn) == TYPE_L)
07530 curr_state->accumulated_insns_num++;
07531 }
07532 else
07533 {
07534
07535
07536
07537
07538
07539 if (before_nops_num > 0 && get_attr_first_insn (insn) == FIRST_INSN_YES)
07540 {
07541 free_bundle_state (curr_state);
07542 return;
07543 }
07544
07545 state_transition (curr_state->dfa_state, dfa_pre_cycle_insn);
07546 state_transition (curr_state->dfa_state, NULL);
07547 curr_state->cost++;
07548 if (!try_issue_nops (curr_state, before_nops_num))
07549 return;
07550 if (!try_issue_insn (curr_state, insn))
07551 return;
07552 curr_state->accumulated_insns_num++;
07553 if (GET_CODE (PATTERN (insn)) == ASM_INPUT
07554 || asm_noperands (PATTERN (insn)) >= 0)
07555 {
07556
07557 curr_state->after_nops_num
07558 = 3 - curr_state->accumulated_insns_num % 3;
07559 curr_state->accumulated_insns_num
07560 += 3 - curr_state->accumulated_insns_num % 3;
07561 }
07562 else if (ia64_safe_type (insn) == TYPE_L)
07563 curr_state->accumulated_insns_num++;
07564 }
07565 if (ia64_safe_type (insn) == TYPE_B)
07566 curr_state->branch_deviation
07567 += 2 - (curr_state->accumulated_insns_num - 1) % 3;
07568 if (try_bundle_end_p && curr_state->accumulated_insns_num % 3 != 0)
07569 {
07570 if (!only_bundle_end_p && insert_bundle_state (curr_state))
07571 {
07572 state_t dfa_state;
07573 struct bundle_state *curr_state1;
07574 struct bundle_state *allocated_states_chain;
07575
07576 curr_state1 = get_free_bundle_state ();
07577 dfa_state = curr_state1->dfa_state;
07578 allocated_states_chain = curr_state1->allocated_states_chain;
07579 *curr_state1 = *curr_state;
07580 curr_state1->dfa_state = dfa_state;
07581 curr_state1->allocated_states_chain = allocated_states_chain;
07582 memcpy (curr_state1->dfa_state, curr_state->dfa_state,
07583 dfa_state_size);
07584 curr_state = curr_state1;
07585 }
07586 if (!try_issue_nops (curr_state,
07587 3 - curr_state->accumulated_insns_num % 3))
07588 return;
07589 curr_state->after_nops_num
07590 = 3 - curr_state->accumulated_insns_num % 3;
07591 curr_state->accumulated_insns_num
07592 += 3 - curr_state->accumulated_insns_num % 3;
07593 }
07594 if (!insert_bundle_state (curr_state))
07595 free_bundle_state (curr_state);
07596 return;
07597 }
07598
07599
07600
07601
07602 static int
07603 get_max_pos (state_t state)
07604 {
07605 if (cpu_unit_reservation_p (state, pos_6))
07606 return 6;
07607 else if (cpu_unit_reservation_p (state, pos_5))
07608 return 5;
07609 else if (cpu_unit_reservation_p (state, pos_4))
07610 return 4;
07611 else if (cpu_unit_reservation_p (state, pos_3))
07612 return 3;
07613 else if (cpu_unit_reservation_p (state, pos_2))
07614 return 2;
07615 else if (cpu_unit_reservation_p (state, pos_1))
07616 return 1;
07617 else
07618 return 0;
07619 }
07620
07621
07622
07623
07624
07625
07626
07627
07628
07629
07630
07631 static int
07632 get_template (state_t state, int pos)
07633 {
07634 switch (pos)
07635 {
07636 case 3:
07637 if (cpu_unit_reservation_p (state, _0mmi_))
07638 return 1;
07639 else if (cpu_unit_reservation_p (state, _0mii_))
07640 return 0;
07641 else if (cpu_unit_reservation_p (state, _0mmb_))
07642 return 7;
07643 else if (cpu_unit_reservation_p (state, _0mib_))
07644 return 6;
07645 else if (cpu_unit_reservation_p (state, _0mbb_))
07646 return 5;
07647 else if (cpu_unit_reservation_p (state, _0bbb_))
07648 return 4;
07649 else if (cpu_unit_reservation_p (state, _0mmf_))
07650 return 3;
07651 else if (cpu_unit_reservation_p (state, _0mfi_))
07652 return 2;
07653 else if (cpu_unit_reservation_p (state, _0mfb_))
07654 return 8;
07655 else if (cpu_unit_reservation_p (state, _0mlx_))
07656 return 9;
07657 else
07658 gcc_unreachable ();
07659 case 6:
07660 if (cpu_unit_reservation_p (state, _1mmi_))
07661 return 1;
07662 else if (cpu_unit_reservation_p (state, _1mii_))
07663 return 0;
07664 else if (cpu_unit_reservation_p (state, _1mmb_))
07665 return 7;
07666 else if (cpu_unit_reservation_p (state, _1mib_))
07667 return 6;
07668 else if (cpu_unit_reservation_p (state, _1mbb_))
07669 return 5;
07670 else if (cpu_unit_reservation_p (state, _1bbb_))
07671 return 4;
07672 else if (_1mmf_ >= 0 && cpu_unit_reservation_p (state, _1mmf_))
07673 return 3;
07674 else if (cpu_unit_reservation_p (state, _1mfi_))
07675 return 2;
07676 else if (cpu_unit_reservation_p (state, _1mfb_))
07677 return 8;
07678 else if (cpu_unit_reservation_p (state, _1mlx_))
07679 return 9;
07680 else
07681 gcc_unreachable ();
07682 default:
07683 gcc_unreachable ();
07684 }
07685 }
07686
07687
07688
07689
07690 static rtx
07691 get_next_important_insn (rtx insn, rtx tail)
07692 {
07693 for (; insn && insn != tail; insn = NEXT_INSN (insn))
07694 if (INSN_P (insn)
07695 && ia64_safe_itanium_class (insn) != ITANIUM_CLASS_IGNORE
07696 && GET_CODE (PATTERN (insn)) != USE
07697 && GET_CODE (PATTERN (insn)) != CLOBBER)
07698 return insn;
07699 return NULL_RTX;
07700 }
07701
07702
07703
07704 static void
07705 ia64_add_bundle_selector_before (int template0, rtx insn)
07706 {
07707 rtx b = gen_bundle_selector (GEN_INT (template0));
07708
07709 ia64_emit_insn_before (b, insn);
07710 #if NR_BUNDLES == 10
07711 if ((template0 == 4 || template0 == 5)
07712 && (flag_unwind_tables || (flag_exceptions && !USING_SJLJ_EXCEPTIONS)))
07713 {
07714 int i;
07715 rtx note = NULL_RTX;
07716
07717
07718
07719
07720
07721
07722 insn = PREV_INSN (insn);
07723 for (i = 0; i < 3; i++)
07724 {
07725 do
07726 insn = next_active_insn (insn);
07727 while (GET_CODE (insn) == INSN
07728 && get_attr_empty (insn) == EMPTY_YES);
07729 if (GET_CODE (insn) == CALL_INSN)
07730 note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
07731 else if (note)
07732 {
07733 int code;
07734
07735 gcc_assert ((code = recog_memoized (insn)) == CODE_FOR_nop
07736 || code == CODE_FOR_nop_b);
07737 if (find_reg_note (insn, REG_EH_REGION, NULL_RTX))
07738 note = NULL_RTX;
07739 else
07740 REG_NOTES (insn)
07741 = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (note, 0),
07742 REG_NOTES (insn));
07743 }
07744 }
07745 }
07746 #endif
07747 }
07748
07749
07750
07751
07752
07753
07754
07755
07756
07757
07758
07759
07760
07761
07762
07763
07764
07765
07766
07767
07768
07769
07770
07771
07772
07773
07774
07775
07776
07777
07778
07779
07780
07781
07782
07783
07784
07785
07786
07787
07788 static void
07789 bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
07790 {
07791 struct bundle_state *curr_state, *next_state, *best_state;
07792 rtx insn, next_insn;
07793 int insn_num;
07794 int i, bundle_end_p, only_bundle_end_p, asm_p;
07795 int pos = 0, max_pos, template0, template1;
07796 rtx b;
07797 rtx nop;
07798 enum attr_type type;
07799
07800 insn_num = 0;
07801
07802 for (insn = NEXT_INSN (prev_head_insn);
07803 insn && insn != tail;
07804 insn = NEXT_INSN (insn))
07805 if (INSN_P (insn))
07806 insn_num++;
07807 if (insn_num == 0)
07808 return;
07809 bundling_p = 1;
07810 dfa_clean_insn_cache ();
07811 initiate_bundle_state_table ();
07812 index_to_bundle_states = xmalloc ((insn_num + 2)
07813 * sizeof (struct bundle_state *));
07814
07815 curr_state = get_free_bundle_state ();
07816 curr_state->insn = NULL;
07817 curr_state->before_nops_num = 0;
07818 curr_state->after_nops_num = 0;
07819 curr_state->insn_num = 0;
07820 curr_state->cost = 0;
07821 curr_state->accumulated_insns_num = 0;
07822 curr_state->branch_deviation = 0;
07823 curr_state->next = NULL;
07824 curr_state->originator = NULL;
07825 state_reset (curr_state->dfa_state);
07826 index_to_bundle_states [0] = curr_state;
07827 insn_num = 0;
07828
07829 for (insn = NEXT_INSN (prev_head_insn);
07830 insn != tail;
07831 insn = NEXT_INSN (insn))
07832 if (INSN_P (insn)
07833 && (ia64_safe_itanium_class (insn) == ITANIUM_CLASS_IGNORE
07834 || GET_CODE (PATTERN (insn)) == USE
07835 || GET_CODE (PATTERN (insn)) == CLOBBER)
07836 && GET_MODE (insn) == TImode)
07837 {
07838 PUT_MODE (insn, VOIDmode);
07839 for (next_insn = NEXT_INSN (insn);
07840 next_insn != tail;
07841 next_insn = NEXT_INSN (next_insn))
07842 if (INSN_P (next_insn)
07843 && ia64_safe_itanium_class (next_insn) != ITANIUM_CLASS_IGNORE
07844 && GET_CODE (PATTERN (next_insn)) != USE
07845 && GET_CODE (PATTERN (next_insn)) != CLOBBER)
07846 {
07847 PUT_MODE (next_insn, TImode);
07848 break;
07849 }
07850 }
07851
07852 for (insn = get_next_important_insn (NEXT_INSN (prev_head_insn), tail);
07853 insn != NULL_RTX;
07854 insn = next_insn)
07855 {
07856 gcc_assert (INSN_P (insn)
07857 && ia64_safe_itanium_class (insn) != ITANIUM_CLASS_IGNORE
07858 && GET_CODE (PATTERN (insn)) != USE
07859 && GET_CODE (PATTERN (insn)) != CLOBBER);
07860 type = ia64_safe_type (insn);
07861 next_insn = get_next_important_insn (NEXT_INSN (insn), tail);
07862 insn_num++;
07863 index_to_bundle_states [insn_num] = NULL;
07864 for (curr_state = index_to_bundle_states [insn_num - 1];
07865 curr_state != NULL;
07866 curr_state = next_state)
07867 {
07868 pos = curr_state->accumulated_insns_num % 3;
07869 next_state = curr_state->next;
07870
07871
07872
07873 only_bundle_end_p
07874 = (next_insn != NULL_RTX
07875 && INSN_CODE (insn) == CODE_FOR_insn_group_barrier
07876 && ia64_safe_type (next_insn) == TYPE_UNKNOWN);
07877
07878
07879 bundle_end_p
07880 = (only_bundle_end_p || next_insn == NULL_RTX
07881 || (GET_MODE (next_insn) == TImode
07882 && INSN_CODE (insn) != CODE_FOR_insn_group_barrier));
07883 if (type == TYPE_F || type == TYPE_B || type == TYPE_L
07884 || type == TYPE_S
07885
07886
07887
07888
07889 || ((type == TYPE_M || type == TYPE_A)
07890 && ia64_tune == PROCESSOR_ITANIUM
07891 && !bundle_end_p && pos == 1))
07892 issue_nops_and_insn (curr_state, 2, insn, bundle_end_p,
07893 only_bundle_end_p);
07894 issue_nops_and_insn (curr_state, 1, insn, bundle_end_p,
07895 only_bundle_end_p);
07896 issue_nops_and_insn (curr_state, 0, insn, bundle_end_p,
07897 only_bundle_end_p);
07898 }
07899 gcc_assert (index_to_bundle_states [insn_num]);
07900 for (curr_state = index_to_bundle_states [insn_num];
07901 curr_state != NULL;
07902 curr_state = curr_state->next)
07903 if (verbose >= 2 && dump)
07904 {
07905
07906
07907
07908
07909 struct DFA_chip
07910 {
07911 unsigned short one_automaton_state;
07912 unsigned short oneb_automaton_state;
07913 unsigned short two_automaton_state;
07914 unsigned short twob_automaton_state;
07915 };
07916
07917 fprintf
07918 (dump,
07919 "// Bundle state %d (orig %d, cost %d, nops %d/%d, insns %d, branch %d, state %d) for %d\n",
07920 curr_state->unique_num,
07921 (curr_state->originator == NULL
07922 ? -1 : curr_state->originator->unique_num),
07923 curr_state->cost,
07924 curr_state->before_nops_num, curr_state->after_nops_num,
07925 curr_state->accumulated_insns_num, curr_state->branch_deviation,
07926 (ia64_tune == PROCESSOR_ITANIUM
07927 ? ((struct DFA_chip *) curr_state->dfa_state)->oneb_automaton_state
07928 : ((struct DFA_chip *) curr_state->dfa_state)->twob_automaton_state),
07929 INSN_UID (insn));
07930 }
07931 }
07932
07933
07934
07935 gcc_assert (index_to_bundle_states [insn_num]);
07936
07937 best_state = NULL;
07938 for (curr_state = index_to_bundle_states [insn_num];
07939 curr_state != NULL;
07940 curr_state = curr_state->next)
07941
07942
07943
07944
07945 if (curr_state->accumulated_insns_num % 3 == 0
07946 && (best_state == NULL || best_state->cost > curr_state->cost
07947 || (best_state->cost == curr_state->cost
07948 && (curr_state->accumulated_insns_num
07949 < best_state->accumulated_insns_num
07950 || (curr_state->accumulated_insns_num
07951 == best_state->accumulated_insns_num
07952 && curr_state->branch_deviation
07953 < best_state->branch_deviation)))))
07954 best_state = curr_state;
07955
07956 insn_num = best_state->before_nops_num;
07957 template0 = template1 = -1;
07958 for (curr_state = best_state;
07959 curr_state->originator != NULL;
07960 curr_state = curr_state->originator)
07961 {
07962 insn = curr_state->insn;
07963 asm_p = (GET_CODE (PATTERN (insn)) == ASM_INPUT
07964 || asm_noperands (PATTERN (insn)) >= 0);
07965 insn_num++;
07966 if (verbose >= 2 && dump)
07967 {
07968 struct DFA_chip
07969 {
07970 unsigned short one_automaton_state;
07971 unsigned short oneb_automaton_state;
07972 unsigned short two_automaton_state;
07973 unsigned short twob_automaton_state;
07974 };
07975
07976 fprintf
07977 (dump,
07978 "// Best %d (orig %d, cost %d, nops %d/%d, insns %d, branch %d, state %d) for %d\n",
07979 curr_state->unique_num,
07980 (curr_state->originator == NULL
07981 ? -1 : curr_state->originator->unique_num),
07982 curr_state->cost,
07983 curr_state->before_nops_num, curr_state->after_nops_num,
07984 curr_state->accumulated_insns_num, curr_state->branch_deviation,
07985 (ia64_tune == PROCESSOR_ITANIUM
07986 ? ((struct DFA_chip *) curr_state->dfa_state)->oneb_automaton_state
07987 : ((struct DFA_chip *) curr_state->dfa_state)->twob_automaton_state),
07988 INSN_UID (insn));
07989 }
07990
07991
07992
07993 max_pos = get_max_pos (curr_state->dfa_state);
07994 if (max_pos == 6
07995
07996
07997 || (max_pos == 3 && template0 < 0))
07998 {
07999
08000
08001 pos = max_pos;
08002 if (max_pos == 3)
08003 template0 = get_template (curr_state->dfa_state, 3);
08004 else
08005 {
08006 template1 = get_template (curr_state->dfa_state, 3);
08007 template0 = get_template (curr_state->dfa_state, 6);
08008 }
08009 }
08010 if (max_pos > 3 && template1 < 0)
08011
08012 {
08013 gcc_assert (pos <= 3);
08014 template1 = get_template (curr_state->dfa_state, 3);
08015 pos += 3;
08016 }
08017 if (!asm_p)
08018
08019 for (i = 0; i < curr_state->after_nops_num; i++)
08020 {
08021 nop = gen_nop ();
08022 emit_insn_after (nop, insn);
08023 pos--;
08024 gcc_assert (pos >= 0);
08025 if (pos % 3 == 0)
08026 {
08027
08028
08029 gcc_assert (template0 >= 0);
08030 ia64_add_bundle_selector_before (template0, nop);
08031
08032
08033
08034 template0 = template1;
08035 template1 = -1;
08036 }
08037 }
08038
08039
08040 if (INSN_CODE (insn) != CODE_FOR_insn_group_barrier
08041 && GET_CODE (PATTERN (insn)) != ASM_INPUT
08042 && asm_noperands (PATTERN (insn)) < 0)
08043 pos--;
08044
08045 if (ia64_safe_type (insn) == TYPE_L)
08046 pos--;
08047 gcc_assert (pos >= 0);
08048 if (pos % 3 == 0
08049 && INSN_CODE (insn) != CODE_FOR_insn_group_barrier
08050 && GET_CODE (PATTERN (insn)) != ASM_INPUT
08051 && asm_noperands (PATTERN (insn)) < 0)
08052 {
08053
08054
08055 gcc_assert (template0 >= 0);
08056 ia64_add_bundle_selector_before (template0, insn);
08057 b = PREV_INSN (insn);
08058 insn = b;
08059
08060
08061 template0 = template1;
08062 template1 = -1;
08063 }
08064
08065 for (i = 0; i < curr_state->before_nops_num; i++)
08066 {
08067 nop = gen_nop ();
08068 ia64_emit_insn_before (nop, insn);
08069 nop = PREV_INSN (insn);
08070 insn = nop;
08071 pos--;
08072 gcc_assert (pos >= 0);
08073 if (pos % 3 == 0)
08074 {
08075
08076
08077 gcc_assert (template0 >= 0);
08078 ia64_add_bundle_selector_before (template0, insn);
08079 b = PREV_INSN (insn);
08080 insn = b;
08081 template0 = template1;
08082 template1 = -1;
08083 }
08084 }
08085 }
08086 if (ia64_tune == PROCESSOR_ITANIUM)
08087
08088
08089
08090
08091
08092 for (insn = get_next_important_insn (NEXT_INSN (prev_head_insn), tail);
08093 insn != NULL_RTX;
08094 insn = next_insn)
08095 {
08096 gcc_assert (INSN_P (insn)
08097 && ia64_safe_itanium_class (insn) != ITANIUM_CLASS_IGNORE
08098 && GET_CODE (PATTERN (insn)) != USE
08099 && GET_CODE (PATTERN (insn)) != CLOBBER);
08100 next_insn = get_next_important_insn (NEXT_INSN (insn), tail);
08101 if (INSN_UID (insn) < clocks_length && add_cycles [INSN_UID (insn)])
08102
08103 {
08104 rtx last;
08105 int i, j, n;
08106 int pred_stop_p;
08107
08108
08109
08110
08111
08112 last = prev_active_insn (insn);
08113 pred_stop_p = recog_memoized (last) == CODE_FOR_insn_group_barrier;
08114 if (pred_stop_p)
08115 last = prev_active_insn (last);
08116 n = 0;
08117 for (;; last = prev_active_insn (last))
08118 if (recog_memoized (last) == CODE_FOR_bundle_selector)
08119 {
08120 template0 = XINT (XVECEXP (PATTERN (last), 0, 0), 0);
08121 if (template0 == 9)
08122
08123
08124
08125 PATTERN (last)
08126 = gen_bundle_selector (const2_rtx);
08127 break;
08128 }
08129 else if (recog_memoized (last) != CODE_FOR_insn_group_barrier
08130 && (ia64_safe_itanium_class (last)
08131 != ITANIUM_CLASS_IGNORE))
08132 n++;
08133
08134
08135
08136
08137 gcc_assert ((!pred_stop_p || n)
08138 && n <= 2
08139 && (template0 != 9 || !n));
08140
08141 for (j = 3 - n; j > 0; j --)
08142 ia64_emit_insn_before (gen_nop (), insn);
08143
08144
08145 add_cycles [INSN_UID (insn)]--;
08146 if (!pred_stop_p || add_cycles [INSN_UID (insn)])
08147 ia64_emit_insn_before (gen_insn_group_barrier (GEN_INT (3)),
08148 insn);
08149 if (pred_stop_p)
08150 add_cycles [INSN_UID (insn)]--;
08151 for (i = add_cycles [INSN_UID (insn)]; i > 0; i--)
08152 {
08153
08154 ia64_emit_insn_before (gen_bundle_selector (const0_rtx),
08155 insn);
08156 ia64_emit_insn_before (gen_nop (), insn);
08157 ia64_emit_insn_before (gen_nop (), insn);
08158 if (i > 1)
08159 {
08160
08161
08162 ia64_emit_insn_before
08163 (gen_insn_group_barrier (GEN_INT (3)), insn);
08164 i--;
08165 }
08166 ia64_emit_insn_before (gen_nop (), insn);
08167 ia64_emit_insn_before (gen_insn_group_barrier (GEN_INT (3)),
08168 insn);
08169 }
08170
08171
08172 ia64_add_bundle_selector_before (template0, insn);
08173
08174
08175 for (j = n; j > 0; j --)
08176 ia64_emit_insn_before (gen_nop (), insn);
08177
08178 if (pred_stop_p)
08179 ia64_emit_insn_before (gen_insn_group_barrier (GEN_INT (3)),
08180 insn);
08181 }
08182 }
08183 free (index_to_bundle_states);
08184 finish_bundle_state_table ();
08185 bundling_p = 0;
08186 dfa_clean_insn_cache ();
08187 }
08188
08189
08190
08191
08192 static void
08193 ia64_sched_finish (FILE *dump, int sched_verbose)
08194 {
08195 if (sched_verbose)
08196 fprintf (dump, "// Finishing schedule.\n");
08197 if (!reload_completed)
08198 return;
08199 if (reload_completed)
08200 {
08201 final_emit_insn_group_barriers (dump);
08202 bundling (dump, sched_verbose, current_sched_info->prev_head,
08203 current_sched_info->next_tail);
08204 if (sched_verbose && dump)
08205 fprintf (dump, "// finishing %d-%d\n",
08206 INSN_UID (NEXT_INSN (current_sched_info->prev_head)),
08207 INSN_UID (PREV_INSN (current_sched_info->next_tail)));
08208
08209 return;
08210 }
08211 }
08212
08213
08214
08215 static void
08216 final_emit_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
08217 {
08218 rtx insn;
08219 int need_barrier_p = 0;
08220 rtx prev_insn = NULL_RTX;
08221
08222 init_insn_group_barriers ();
08223
08224 for (insn = NEXT_INSN (current_sched_info->prev_head);
08225 insn != current_sched_info->next_tail;
08226 insn = NEXT_INSN (insn))
08227 {
08228 if (GET_CODE (insn) == BARRIER)
08229 {
08230 rtx last = prev_active_insn (insn);
08231
08232 if (! last)
08233 continue;
08234 if (GET_CODE (last) == JUMP_INSN
08235 && GET_CODE (PATTERN (last)) == ADDR_DIFF_VEC)
08236 last = prev_active_insn (last);
08237 if (recog_memoized (last) != CODE_FOR_insn_group_barrier)
08238 emit_insn_after (gen_insn_group_barrier (GEN_INT (3)), last);
08239
08240 init_insn_group_barriers ();
08241 need_barrier_p = 0;
08242 prev_insn = NULL_RTX;
08243 }
08244 else if (INSN_P (insn))
08245 {
08246 if (recog_memoized (insn) == CODE_FOR_insn_group_barrier)
08247 {
08248 init_insn_group_barriers ();
08249 need_barrier_p = 0;
08250 prev_insn = NULL_RTX;
08251 }
08252 else if (need_barrier_p || group_barrier_needed (insn))
08253 {
08254 if (TARGET_EARLY_STOP_BITS)
08255 {
08256 rtx last;
08257
08258 for (last = insn;
08259 last != current_sched_info->prev_head;
08260 last = PREV_INSN (last))
08261 if (INSN_P (last) && GET_MODE (last) == TImode
08262 && stops_p [INSN_UID (last)])
08263 break;
08264 if (last == current_sched_info->prev_head)
08265 last = insn;
08266 last = prev_active_insn (last);
08267 if (last
08268 && recog_memoized (last) != CODE_FOR_insn_group_barrier)
08269 emit_insn_after (gen_insn_group_barrier (GEN_INT (3)),
08270 last);
08271 init_insn_group_barriers ();
08272 for (last = NEXT_INSN (last);
08273 last != insn;
08274 last = NEXT_INSN (last))
08275 if (INSN_P (last))
08276 group_barrier_needed (last);
08277 }
08278 else
08279 {
08280 emit_insn_before (gen_insn_group_barrier (GEN_INT (3)),
08281 insn);
08282 init_insn_group_barriers ();
08283 }
08284 group_barrier_needed (insn);
08285 prev_insn = NULL_RTX;
08286 }
08287 else if (recog_memoized (insn) >= 0)
08288 prev_insn = insn;
08289 need_barrier_p = (GET_CODE (insn) == CALL_INSN
08290 || GET_CODE (PATTERN (insn)) == ASM_INPUT
08291 || asm_noperands (PATTERN (insn)) >= 0);
08292 }
08293 }
08294 }
08295
08296
08297
08298
08299
08300
08301 static int
08302 ia64_first_cycle_multipass_dfa_lookahead (void)
08303 {
08304 return (reload_completed ? 6 : 4);
08305 }
08306
08307
08308
08309 static void
08310 ia64_init_dfa_pre_cycle_insn (void)
08311 {
08312 if (temp_dfa_state == NULL)
08313 {
08314 dfa_state_size = state_size ();
08315 temp_dfa_state = xmalloc (dfa_state_size);
08316 prev_cycle_state = xmalloc (dfa_state_size);
08317 }
08318 dfa_pre_cycle_insn = make_insn_raw (gen_pre_cycle ());
08319 PREV_INSN (dfa_pre_cycle_insn) = NEXT_INSN (dfa_pre_cycle_insn) = NULL_RTX;
08320 recog_memoized (dfa_pre_cycle_insn);
08321 dfa_stop_insn = make_insn_raw (gen_insn_group_barrier (GEN_INT (3)));
08322 PREV_INSN (dfa_stop_insn) = NEXT_INSN (dfa_stop_insn) = NULL_RTX;
08323 recog_memoized (dfa_stop_insn);
08324 }
08325
08326
08327
08328
08329 static rtx
08330 ia64_dfa_pre_cycle_insn (void)
08331 {
08332 return dfa_pre_cycle_insn;
08333 }
08334
08335
08336
08337
08338 int
08339 ia64_st_address_bypass_p (rtx producer, rtx consumer)
08340 {
08341 rtx dest, reg, mem;
08342
08343 gcc_assert (producer && consumer);
08344 dest = ia64_single_set (producer);
08345 gcc_assert (dest);
08346 reg = SET_DEST (dest);
08347 gcc_assert (reg);
08348 if (GET_CODE (reg) == SUBREG)
08349 reg = SUBREG_REG (reg);
08350 gcc_assert (GET_CODE (reg) == REG);
08351
08352 dest = ia64_single_set (consumer);
08353 gcc_assert (dest);
08354 mem = SET_DEST (dest);
08355 gcc_assert (mem && GET_CODE (mem) == MEM);
08356 return reg_mentioned_p (reg, mem);
08357 }
08358
08359
08360
08361
08362 int
08363 ia64_ld_address_bypass_p (rtx producer, rtx consumer)
08364 {
08365 rtx dest, src, reg, mem;
08366
08367 gcc_assert (producer && consumer);
08368 dest = ia64_single_set (producer);
08369 gcc_assert (dest);
08370 reg = SET_DEST (dest);
08371 gcc_assert (reg);
08372 if (GET_CODE (reg) == SUBREG)
08373 reg = SUBREG_REG (reg);
08374 gcc_assert (GET_CODE (reg) == REG);
08375
08376 src = ia64_single_set (consumer);
08377 gcc_assert (src);
08378 mem = SET_SRC (src);
08379 gcc_assert (mem);
08380
08381 if (GET_CODE (mem) == UNSPEC && XVECLEN (mem, 0) > 0)
08382 mem = XVECEXP (mem, 0, 0);
08383 else if (GET_CODE (mem) == IF_THEN_ELSE)
08384
08385 {
08386 gcc_assert (XINT (XEXP (XEXP (mem, 0), 0), 1) == UNSPEC_LDCCLR);
08387 mem = XEXP (mem, 1);
08388 }
08389
08390 while (GET_CODE (mem) == SUBREG || GET_CODE (mem) == ZERO_EXTEND)
08391 mem = XEXP (mem, 0);
08392
08393 if (GET_CODE (mem) == UNSPEC)
08394 {
08395 int c = XINT (mem, 1);
08396
08397 gcc_assert (c == UNSPEC_LDA || c == UNSPEC_LDS || c == UNSPEC_LDSA);
08398 mem = XVECEXP (mem, 0, 0);
08399 }
08400
08401
08402 gcc_assert (GET_CODE (mem) == LO_SUM || GET_CODE (mem) == MEM);
08403
08404 return reg_mentioned_p (reg, mem);
08405 }
08406
08407
08408
08409
08410
08411 int
08412 ia64_produce_address_p (rtx insn)
08413 {
08414 return insn->call;
08415 }
08416
08417
08418
08419
08420
08421
08422
08423 static void
08424 emit_predicate_relation_info (void)
08425 {
08426 basic_block bb;
08427
08428 FOR_EACH_BB_REVERSE (bb)
08429 {
08430 int r;
08431 rtx head = BB_HEAD (bb);
08432
08433
08434 if (GET_CODE (head) != CODE_LABEL)
08435 continue;
08436 if (GET_CODE (NEXT_INSN (head)) == NOTE
08437 && NOTE_LINE_NUMBER (NEXT_INSN (head)) == NOTE_INSN_BASIC_BLOCK)
08438 head = NEXT_INSN (head);
08439
08440
08441
08442 for (r = PR_REG (2); r < PR_REG (64); r += 2)
08443 if (REGNO_REG_SET_P (bb->il.rtl->global_live_at_start, r))
08444 {
08445 rtx p = gen_rtx_REG (BImode, r);
08446 rtx n = emit_insn_after (gen_pred_rel_mutex (p), head);
08447 if (head == BB_END (bb))
08448 BB_END (bb) = n;
08449 head = n;
08450 }
08451 }
08452
08453
08454
08455
08456
08457 FOR_EACH_BB_REVERSE (bb)
08458 {
08459 rtx insn = BB_HEAD (bb);
08460
08461 while (1)
08462 {
08463 if (GET_CODE (insn) == CALL_INSN
08464 && GET_CODE (PATTERN (insn)) == COND_EXEC
08465 && find_reg_note (insn, REG_NORETURN, NULL_RTX))
08466 {
08467 rtx b = emit_insn_before (gen_safe_across_calls_all (), insn);
08468 rtx a = emit_insn_after (gen_safe_across_calls_normal (), insn);
08469 if (BB_HEAD (bb) == insn)
08470 BB_HEAD (bb) = b;
08471 if (BB_END (bb) == insn)
08472 BB_END (bb) = a;
08473 }
08474
08475 if (insn == BB_END (bb))
08476 break;
08477 insn = NEXT_INSN (insn);
08478 }
08479 }
08480 }
08481
08482
08483
08484 static void
08485 ia64_reorg (void)
08486 {
08487
08488
08489 compute_bb_for_insn ();
08490
08491
08492 if (optimize == 0)
08493 split_all_insns (0);
08494
08495
08496
08497 update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
08498
08499 if (optimize && ia64_flag_schedule_insns2)
08500 {
08501 timevar_push (TV_SCHED2);
08502 ia64_final_schedule = 1;
08503
08504 initiate_bundle_states ();
08505 ia64_nop = make_insn_raw (gen_nop ());
08506 PREV_INSN (ia64_nop) = NEXT_INSN (ia64_nop) = NULL_RTX;
08507 recog_memoized (ia64_nop);
08508 clocks_length = get_max_uid () + 1;
08509 stops_p = xcalloc (1, clocks_length);
08510 if (ia64_tune == PROCESSOR_ITANIUM)
08511 {
08512 clocks = xcalloc (clocks_length, sizeof (int));
08513 add_cycles = xcalloc (clocks_length, sizeof (int));
08514 }
08515 if (ia64_tune == PROCESSOR_ITANIUM2)
08516 {
08517 pos_1 = get_cpu_unit_code ("2_1");
08518 pos_2 = get_cpu_unit_code ("2_2");
08519 pos_3 = get_cpu_unit_code ("2_3");
08520 pos_4 = get_cpu_unit_code ("2_4");
08521 pos_5 = get_cpu_unit_code ("2_5");
08522 pos_6 = get_cpu_unit_code ("2_6");
08523 _0mii_ = get_cpu_unit_code ("2b_0mii.");
08524 _0mmi_ = get_cpu_unit_code ("2b_0mmi.");
08525 _0mfi_ = get_cpu_unit_code ("2b_0mfi.");
08526 _0mmf_ = get_cpu_unit_code ("2b_0mmf.");
08527 _0bbb_ = get_cpu_unit_code ("2b_0bbb.");
08528 _0mbb_ = get_cpu_unit_code ("2b_0mbb.");
08529 _0mib_ = get_cpu_unit_code ("2b_0mib.");
08530 _0mmb_ = get_cpu_unit_code ("2b_0mmb.");
08531 _0mfb_ = get_cpu_unit_code ("2b_0mfb.");
08532 _0mlx_ = get_cpu_unit_code ("2b_0mlx.");
08533 _1mii_ = get_cpu_unit_code ("2b_1mii.");
08534 _1mmi_ = get_cpu_unit_code ("2b_1mmi.");
08535 _1mfi_ = get_cpu_unit_code ("2b_1mfi.");
08536 _1mmf_ = get_cpu_unit_code ("2b_1mmf.");
08537 _1bbb_ = get_cpu_unit_code ("2b_1bbb.");
08538 _1mbb_ = get_cpu_unit_code ("2b_1mbb.");
08539 _1mib_ = get_cpu_unit_code ("2b_1mib.");
08540 _1mmb_ = get_cpu_unit_code ("2b_1mmb.");
08541 _1mfb_ = get_cpu_unit_code ("2b_1mfb.");
08542 _1mlx_ = get_cpu_unit_code ("2b_1mlx.");
08543 }
08544 else
08545 {
08546 pos_1 = get_cpu_unit_code ("1_1");
08547 pos_2 = get_cpu_unit_code ("1_2");
08548 pos_3 = get_cpu_unit_code ("1_3");
08549 pos_4 = get_cpu_unit_code ("1_4");
08550 pos_5 = get_cpu_unit_code ("1_5");
08551 pos_6 = get_cpu_unit_code ("1_6");
08552 _0mii_ = get_cpu_unit_code ("1b_0mii.");
08553 _0mmi_ = get_cpu_unit_code ("1b_0mmi.");
08554 _0mfi_ = get_cpu_unit_code ("1b_0mfi.");
08555 _0mmf_ = get_cpu_unit_code ("1b_0mmf.");
08556 _0bbb_ = get_cpu_unit_code ("1b_0bbb.");
08557 _0mbb_ = get_cpu_unit_code ("1b_0mbb.");
08558 _0mib_ = get_cpu_unit_code ("1b_0mib.");
08559 _0mmb_ = get_cpu_unit_code ("1b_0mmb.");
08560 _0mfb_ = get_cpu_unit_code ("1b_0mfb.");
08561 _0mlx_ = get_cpu_unit_code ("1b_0mlx.");
08562 _1mii_ = get_cpu_unit_code ("1b_1mii.");
08563 _1mmi_ = get_cpu_unit_code ("1b_1mmi.");
08564 _1mfi_ = get_cpu_unit_code ("1b_1mfi.");
08565 _1mmf_ = get_cpu_unit_code ("1b_1mmf.");
08566 _1bbb_ = get_cpu_unit_code ("1b_1bbb.");
08567 _1mbb_ = get_cpu_unit_code ("1b_1mbb.");
08568 _1mib_ = get_cpu_unit_code ("1b_1mib.");
08569 _1mmb_ = get_cpu_unit_code ("1b_1mmb.");
08570 _1mfb_ = get_cpu_unit_code ("1b_1mfb.");
08571 _1mlx_ = get_cpu_unit_code ("1b_1mlx.");
08572 }
08573 schedule_ebbs ();
08574 finish_bundle_states ();
08575 if (ia64_tune == PROCESSOR_ITANIUM)
08576 {
08577 free (add_cycles);
08578 free (clocks);
08579 }
08580 free (stops_p);
08581 stops_p = NULL;
08582 emit_insn_group_barriers (dump_file);
08583
08584 ia64_final_schedule = 0;
08585 timevar_pop (TV_SCHED2);
08586 }
08587 else
08588 emit_all_insn_group_barriers (dump_file);
08589
08590
08591
08592
08593 if (flag_unwind_tables || (flag_exceptions && !USING_SJLJ_EXCEPTIONS))
08594 {
08595 rtx insn;
08596 int saw_stop = 0;
08597
08598 insn = get_last_insn ();
08599 if (! INSN_P (insn))
08600 insn = prev_active_insn (insn);
08601
08602 while (GET_CODE (insn) == INSN && get_attr_empty (insn) == EMPTY_YES)
08603 {
08604 if (GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
08605 && XINT (PATTERN (insn), 1) == UNSPECV_INSN_GROUP_BARRIER)
08606 saw_stop = 1;
08607 insn = prev_active_insn (insn);
08608 }
08609 if (GET_CODE (insn) == CALL_INSN)
08610 {
08611 if (! saw_stop)
08612 emit_insn (gen_insn_group_barrier (GEN_INT (3)));
08613 emit_insn (gen_break_f ());
08614 emit_insn (gen_insn_group_barrier (GEN_INT (3)));
08615 }
08616 }
08617
08618 emit_predicate_relation_info ();
08619
08620 if (ia64_flag_var_tracking)
08621 {
08622 timevar_push (TV_VAR_TRACKING);
08623 variable_tracking_main ();
08624 timevar_pop (TV_VAR_TRACKING);
08625 }
08626 }
08627
08628
08629
08630 int
08631 ia64_epilogue_uses (int regno)
08632 {
08633 switch (regno)
08634 {
08635 case R_GR (1):
08636
08637
08638
08639
08640 return !(TARGET_AUTO_PIC || TARGET_NO_PIC);
08641
08642 case IN_REG (0): case IN_REG (1): case IN_REG (2): case IN_REG (3):
08643 case IN_REG (4): case IN_REG (5): case IN_REG (6): case IN_REG (7):
08644
08645
08646
08647
08648
08649
08650 return lookup_attribute ("syscall_linkage",
08651 TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))) != NULL;
08652
08653 case R_BR (0):
08654
08655
08656 return 1;
08657
08658 case AR_PFS_REGNUM:
08659
08660 return 1;
08661
08662 default:
08663 return 0;
08664 }
08665 }
08666
08667
08668
08669 int
08670 ia64_eh_uses (int regno)
08671 {
08672 if (! reload_completed)
08673 return 0;
08674
08675 if (current_frame_info.reg_save_b0
08676 && regno == current_frame_info.reg_save_b0)
08677 return 1;
08678 if (current_frame_info.reg_save_pr
08679 && regno == current_frame_info.reg_save_pr)
08680 return 1;
08681 if (current_frame_info.reg_save_ar_pfs
08682 && regno == current_frame_info.reg_save_ar_pfs)
08683 return 1;
08684 if (current_frame_info.reg_save_ar_unat
08685 && regno == current_frame_info.reg_save_ar_unat)
08686 return 1;
08687 if (current_frame_info.reg_save_ar_lc
08688 && regno == current_frame_info.reg_save_ar_lc)
08689 return 1;
08690
08691 return 0;
08692 }
08693
08694
08695
08696
08697
08698
08699
08700
08701 static bool
08702 ia64_in_small_data_p (tree exp)
08703 {
08704 if (TARGET_NO_SDATA)
08705 return false;
08706
08707
08708 if (TREE_CODE (exp) == STRING_CST)
08709 return false;
08710
08711
08712 if (TREE_CODE (exp) == FUNCTION_DECL)
08713 return false;
08714
08715 if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
08716 {
08717 const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
08718
08719 if (strcmp (section, ".sdata") == 0
08720 || strncmp (section, ".sdata.", 7) == 0
08721 || strncmp (section, ".gnu.linkonce.s.", 16) == 0
08722 || strcmp (section, ".sbss") == 0
08723 || strncmp (section, ".sbss.", 6) == 0
08724 || strncmp (section, ".gnu.linkonce.sb.", 17) == 0)
08725 return true;
08726 }
08727 else
08728 {
08729 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
08730
08731
08732
08733 if (size > 0 && size <= ia64_section_threshold)
08734 return true;
08735 }
08736
08737 return false;
08738 }
08739
08740
08741
08742
08743
08744 static bool last_block;
08745
08746
08747
08748 static bool need_copy_state;
08749
08750 #ifndef MAX_ARTIFICIAL_LABEL_BYTES
08751 # define MAX_ARTIFICIAL_LABEL_BYTES 30
08752 #endif
08753
08754
08755
08756
08757
08758
08759
08760
08761 static const char *
08762 ia64_emit_deleted_label_after_insn (rtx insn)
08763 {
08764 char label[MAX_ARTIFICIAL_LABEL_BYTES];
08765 rtx lb = gen_label_rtx ();
08766 rtx label_insn = emit_label_after (lb, insn);
08767
08768 LABEL_PRESERVE_P (lb) = 1;
08769
08770 delete_insn (label_insn);
08771
08772 ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (label_insn));
08773
08774 return xstrdup (label);
08775 }
08776
08777
08778
08779 static void
08780 ia64_dwarf2out_def_steady_cfa (rtx insn)
08781 {
08782 rtx fp = frame_pointer_needed
08783 ? hard_frame_pointer_rtx
08784 : stack_pointer_rtx;
08785
08786 dwarf2out_def_cfa
08787 (ia64_emit_deleted_label_after_insn (insn),
08788 REGNO (fp),
08789 ia64_initial_elimination_offset
08790 (REGNO (arg_pointer_rtx), REGNO (fp))
08791 + ARG_POINTER_CFA_OFFSET (current_function_decl));
08792 }
08793
08794
08795
08796
08797
08798 #define IA64_CHANGE_CFA_IN_EPILOGUE 0
08799
08800
08801
08802 static void
08803 process_epilogue (FILE *asm_out_file, rtx insn, bool unwind, bool frame)
08804 {
08805
08806
08807
08808 if (!last_block)
08809 {
08810 if (unwind)
08811 fprintf (asm_out_file, "\t.label_state %d\n",
08812 ++cfun->machine->state_num);
08813 need_copy_state = true;
08814 }
08815
08816 if (unwind)
08817 fprintf (asm_out_file, "\t.restore sp\n");
08818 if (IA64_CHANGE_CFA_IN_EPILOGUE && frame)
08819 dwarf2out_def_cfa (ia64_emit_deleted_label_after_insn (insn),
08820 STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
08821 }
08822
08823
08824
08825
08826 static int
08827 process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame)
08828 {
08829 rtx src = SET_SRC (pat);
08830 rtx dest = SET_DEST (pat);
08831 int src_regno, dest_regno;
08832
08833
08834 if (GET_CODE (src) == UNSPEC_VOLATILE
08835 && XINT (src, 1) == UNSPECV_ALLOC
08836 && GET_CODE (dest) == REG)
08837 {
08838 dest_regno = REGNO (dest);
08839
08840
08841
08842 if (dest_regno == current_frame_info.reg_save_ar_pfs)
08843 {
08844 if (unwind)
08845 fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
08846 ia64_dbx_register_number (dest_regno));
08847 }
08848 else
08849 {
08850
08851
08852
08853
08854
08855
08856 if (current_frame_info.total_size == 0 && !frame_pointer_needed)
08857
08858 process_epilogue (asm_out_file, insn, unwind, frame);
08859 if (unwind)
08860 fprintf (asm_out_file, "\t.prologue\n");
08861 }
08862 return 1;
08863 }
08864
08865
08866 if (GET_CODE (dest) == REG && REGNO (dest) == STACK_POINTER_REGNUM)
08867 {
08868 if (GET_CODE (src) == PLUS)
08869 {
08870 rtx op0 = XEXP (src, 0);
08871 rtx op1 = XEXP (src, 1);
08872
08873 gcc_assert (op0 == dest && GET_CODE (op1) == CONST_INT);
08874
08875 if (INTVAL (op1) < 0)
08876 {
08877 gcc_assert (!frame_pointer_needed);
08878 if (unwind)
08879 fprintf (asm_out_file, "\t.fframe "HOST_WIDE_INT_PRINT_DEC"\n",
08880 -INTVAL (op1));
08881 if (frame)
08882 ia64_dwarf2out_def_steady_cfa (insn);
08883 }
08884 else
08885 process_epilogue (asm_out_file, insn, unwind, frame);
08886 }
08887 else
08888 {
08889 gcc_assert (GET_CODE (src) == REG
08890 && REGNO (src) == HARD_FRAME_POINTER_REGNUM);
08891 process_epilogue (asm_out_file, insn, unwind, frame);
08892 }
08893
08894 return 1;
08895 }
08896
08897
08898 if (GET_CODE (dest) == REG && GET_CODE (src) == REG)
08899 {
08900 src_regno = REGNO (src);
08901 dest_regno = REGNO (dest);
08902
08903 switch (src_regno)
08904 {
08905 case BR_REG (0):
08906
08907 gcc_assert (dest_regno == current_frame_info.reg_save_b0);
08908 if (unwind)
08909 fprintf (asm_out_file, "\t.save rp, r%d\n",
08910 ia64_dbx_register_number (dest_regno));
08911 return 1;
08912
08913 case PR_REG (0):
08914 gcc_assert (dest_regno == current_frame_info.reg_save_pr);
08915 if (unwind)
08916 fprintf (asm_out_file, "\t.save pr, r%d\n",
08917 ia64_dbx_register_number (dest_regno));
08918 return 1;
08919
08920 case AR_UNAT_REGNUM:
08921 gcc_assert (dest_regno == current_frame_info.reg_save_ar_unat);
08922 if (unwind)
08923 fprintf (asm_out_file, "\t.save ar.unat, r%d\n",
08924 ia64_dbx_register_number (dest_regno));
08925 return 1;
08926
08927 case AR_LC_REGNUM:
08928 gcc_assert (dest_regno == current_frame_info.reg_save_ar_lc);
08929 if (unwind)
08930 fprintf (asm_out_file, "\t.save ar.lc, r%d\n",
08931 ia64_dbx_register_number (dest_regno));
08932 return 1;
08933
08934 case STACK_POINTER_REGNUM:
08935 gcc_assert (dest_regno == HARD_FRAME_POINTER_REGNUM
08936 && frame_pointer_needed);
08937 if (unwind)
08938 fprintf (asm_out_file, "\t.vframe r%d\n",
08939 ia64_dbx_register_number (dest_regno));
08940 if (frame)
08941 ia64_dwarf2out_def_steady_cfa (insn);
08942 return 1;
08943
08944 default:
08945
08946 gcc_unreachable ();
08947 }
08948 }
08949
08950
08951 if (GET_CODE (dest) == MEM && GET_CODE (src) == REG)
08952 {
08953 long off;
08954 rtx base;
08955 const char *saveop;
08956
08957 if (GET_CODE (XEXP (dest, 0)) == REG)
08958 {
08959 base = XEXP (dest, 0);
08960 off = 0;
08961 }
08962 else
08963 {
08964 gcc_assert (GET_CODE (XEXP (dest, 0)) == PLUS
08965 && GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT);
08966 base = XEXP (XEXP (dest, 0), 0);
08967 off = INTVAL (XEXP (XEXP (dest, 0), 1));
08968 }
08969
08970 if (base == hard_frame_pointer_rtx)
08971 {
08972 saveop = ".savepsp";
08973 off = - off;
08974 }
08975 else
08976 {
08977 gcc_assert (base == stack_pointer_rtx);
08978 saveop = ".savesp";
08979 }
08980
08981 src_regno = REGNO (src);
08982 switch (src_regno)
08983 {
08984 case BR_REG (0):
08985 gcc_assert (!current_frame_info.reg_save_b0);
08986 if (unwind)
08987 fprintf (asm_out_file, "\t%s rp, %ld\n", saveop, off);
08988 return 1;
08989
08990 case PR_REG (0):
08991 gcc_assert (!current_frame_info.reg_save_pr);
08992 if (unwind)
08993 fprintf (asm_out_file, "\t%s pr, %ld\n", saveop, off);
08994 return 1;
08995
08996 case AR_LC_REGNUM:
08997 gcc_assert (!current_frame_info.reg_save_ar_lc);
08998 if (unwind)
08999 fprintf (asm_out_file, "\t%s ar.lc, %ld\n", saveop, off);
09000 return 1;
09001
09002 case AR_PFS_REGNUM:
09003 gcc_assert (!current_frame_info.reg_save_ar_pfs);
09004 if (unwind)
09005 fprintf (asm_out_file, "\t%s ar.pfs, %ld\n", saveop, off);
09006 return 1;
09007
09008 case AR_UNAT_REGNUM:
09009 gcc_assert (!current_frame_info.reg_save_ar_unat);
09010 if (unwind)
09011 fprintf (asm_out_file, "\t%s ar.unat, %ld\n", saveop, off);
09012 return 1;
09013
09014 case GR_REG (4):
09015 case GR_REG (5):
09016 case GR_REG (6):
09017 case GR_REG (7):
09018 if (unwind)
09019 fprintf (asm_out_file, "\t.save.g 0x%x\n",
09020 1 << (src_regno - GR_REG (4)));
09021 return 1;
09022
09023 case BR_REG (1):
09024 case BR_REG (2):
09025 case BR_REG (3):
09026 case BR_REG (4):
09027 case BR_REG (5):
09028 if (unwind)
09029 fprintf (asm_out_file, "\t.save.b 0x%x\n",
09030 1 << (src_regno - BR_REG (1)));
09031 return 1;
09032
09033 case FR_REG (2):
09034 case FR_REG (3):
09035 case FR_REG (4):
09036 case FR_REG (5):
09037 if (unwind)
09038 fprintf (asm_out_file, "\t.save.f 0x%x\n",
09039 1 << (src_regno - FR_REG (2)));
09040 return 1;
09041
09042 case FR_REG (16): case FR_REG (17): case FR_REG (18): case FR_REG (19):
09043 case FR_REG (20): case FR_REG (21): case FR_REG (22): case FR_REG (23):
09044 case FR_REG (24): case FR_REG (25): case FR_REG (26): case FR_REG (27):
09045 case FR_REG (28): case FR_REG (29): case FR_REG (30): case FR_REG (31):
09046 if (unwind)
09047 fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n",
09048 1 << (src_regno - FR_REG (12)));
09049 return 1;
09050
09051 default:
09052 return 0;
09053 }
09054 }
09055
09056 return 0;
09057 }
09058
09059
09060
09061
09062 void
09063 process_for_unwind_directive (FILE *asm_out_file, rtx insn)
09064 {
09065 bool unwind = (flag_unwind_tables
09066 || (flag_exceptions && !USING_SJLJ_EXCEPTIONS));
09067 bool frame = dwarf2out_do_frame ();
09068
09069 if (unwind || frame)
09070 {
09071 rtx pat;
09072
09073 if (GET_CODE (insn) == NOTE
09074 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
09075 {
09076 last_block = NOTE_BASIC_BLOCK (insn)->next_bb == EXIT_BLOCK_PTR;
09077
09078
09079 if (need_copy_state)
09080 {
09081 if (unwind)
09082 {
09083 fprintf (asm_out_file, "\t.body\n");
09084 fprintf (asm_out_file, "\t.copy_state %d\n",
09085 cfun->machine->state_num);
09086 }
09087 if (IA64_CHANGE_CFA_IN_EPILOGUE && frame)
09088 ia64_dwarf2out_def_steady_cfa (insn);
09089 need_copy_state = false;
09090 }
09091 }
09092
09093 if (GET_CODE (insn) == NOTE || ! RTX_FRAME_RELATED_P (insn))
09094 return;
09095
09096 pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
09097 if (pat)
09098 pat = XEXP (pat, 0);
09099 else
09100 pat = PATTERN (insn);
09101
09102 switch (GET_CODE (pat))
09103 {
09104 case SET:
09105 process_set (asm_out_file, pat, insn, unwind, frame);
09106 break;
09107
09108 case PARALLEL:
09109 {
09110 int par_index;
09111 int limit = XVECLEN (pat, 0);
09112 for (par_index = 0; par_index < limit; par_index++)
09113 {
09114 rtx x = XVECEXP (pat, 0, par_index);
09115 if (GET_CODE (x) == SET)
09116 process_set (asm_out_file, x, insn, unwind, frame);
09117 }
09118 break;
09119 }
09120
09121 default:
09122 gcc_unreachable ();
09123 }
09124 }
09125 }
09126
09127
09128 enum ia64_builtins
09129 {
09130 IA64_BUILTIN_BSP,
09131 IA64_BUILTIN_FLUSHRS
09132 };
09133
09134 void
09135 ia64_init_builtins (void)
09136 {
09137 tree fpreg_type;
09138 tree float80_type;
09139
09140
09141 fpreg_type = make_node (REAL_TYPE);
09142 TYPE_PRECISION (fpreg_type) = 82;
09143 layout_type (fpreg_type);
09144 (*lang_hooks.types.register_builtin_type) (fpreg_type, "__fpreg");
09145
09146
09147 float80_type = make_node (REAL_TYPE);
09148 TYPE_PRECISION (float80_type) = 80;
09149 layout_type (float80_type);
09150 (*lang_hooks.types.register_builtin_type) (float80_type, "__float80");
09151
09152
09153 if (!TARGET_HPUX)
09154 {
09155 tree float128_type = make_node (REAL_TYPE);
09156 TYPE_PRECISION (float128_type) = 128;
09157 layout_type (float128_type);
09158 (*lang_hooks.types.register_builtin_type) (float128_type, "__float128");
09159 }
09160 else
09161
09162 (*lang_hooks.types.register_builtin_type) (long_double_type_node,
09163 "__float128");
09164
09165 #define def_builtin(name, type, code) \
09166 lang_hooks.builtin_function ((name), (type), (code), BUILT_IN_MD, \
09167 NULL, NULL_TREE)
09168
09169 def_builtin ("__builtin_ia64_bsp",
09170 build_function_type (ptr_type_node, void_list_node),
09171 IA64_BUILTIN_BSP);
09172
09173 def_builtin ("__builtin_ia64_flushrs",
09174 build_function_type (void_type_node, void_list_node),
09175 IA64_BUILTIN_FLUSHRS);
09176
09177 #undef def_builtin
09178 }
09179
09180 rtx
09181 ia64_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
09182 enum machine_mode mode ATTRIBUTE_UNUSED,
09183 int ignore ATTRIBUTE_UNUSED)
09184 {
09185 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
09186 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
09187
09188 switch (fcode)
09189 {
09190 case IA64_BUILTIN_BSP:
09191 if (! target || ! register_operand (target, DImode))
09192 target = gen_reg_rtx (DImode);
09193 emit_insn (gen_bsp_value (target));
09194 #ifdef POINTERS_EXTEND_UNSIGNED
09195 target = convert_memory_address (ptr_mode, target);
09196 #endif
09197 return target;
09198
09199 case IA64_BUILTIN_FLUSHRS:
09200 emit_insn (gen_flushrs ());
09201 return const0_rtx;
09202
09203 default:
09204 break;
09205 }
09206
09207 return NULL_RTX;
09208 }
09209
09210
09211
09212
09213 enum direction
09214 ia64_hpux_function_arg_padding (enum machine_mode mode, tree type)
09215 {
09216
09217
09218 if (type && AGGREGATE_TYPE_P (type)
09219 && int_size_in_bytes (type) < UNITS_PER_WORD)
09220 return upward;
09221
09222
09223 return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
09224 }
09225
09226
09227
09228
09229
09230 struct extern_func_list GTY(())
09231 {
09232 struct extern_func_list *next;
09233 tree decl;
09234 };
09235
09236 static GTY(()) struct extern_func_list *extern_func_head;
09237
09238 static void
09239 ia64_hpux_add_extern_decl (tree decl)
09240 {
09241 struct extern_func_list *p = ggc_alloc (sizeof (struct extern_func_list));
09242
09243 p->decl = decl;
09244 p->next = extern_func_head;
09245 extern_func_head = p;
09246 }
09247
09248
09249
09250 static void
09251 ia64_hpux_file_end (void)
09252 {
09253 struct extern_func_list *p;
09254
09255 for (p = extern_func_head; p; p = p->next)
09256 {
09257 tree decl = p->decl;
09258 tree id = DECL_ASSEMBLER_NAME (decl);
09259
09260 gcc_assert (id);
09261
09262 if (!TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (id))
09263 {
09264 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
09265
09266 TREE_ASM_WRITTEN (decl) = 1;
09267 (*targetm.asm_out.globalize_label) (asm_out_file, name);
09268 fputs (TYPE_ASM_OP, asm_out_file);
09269 assemble_name (asm_out_file, name);
09270 fprintf (asm_out_file, "," TYPE_OPERAND_FMT "\n", "function");
09271 }
09272 }
09273
09274 extern_func_head = 0;
09275 }
09276
09277
09278
09279
09280
09281
09282 static void
09283 ia64_init_libfuncs (void)
09284 {
09285 set_optab_libfunc (sdiv_optab, SImode, "__divsi3");
09286 set_optab_libfunc (udiv_optab, SImode, "__udivsi3");
09287 set_optab_libfunc (smod_optab, SImode, "__modsi3");
09288 set_optab_libfunc (umod_optab, SImode, "__umodsi3");
09289
09290 set_optab_libfunc (add_optab, TFmode, "_U_Qfadd");
09291 set_optab_libfunc (sub_optab, TFmode, "_U_Qfsub");
09292 set_optab_libfunc (smul_optab, TFmode, "_U_Qfmpy");
09293 set_optab_libfunc (sdiv_optab, TFmode, "_U_Qfdiv");
09294 set_optab_libfunc (neg_optab, TFmode, "_U_Qfneg");
09295
09296 set_conv_libfunc (sext_optab, TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad");
09297 set_conv_libfunc (sext_optab, TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad");
09298 set_conv_libfunc (sext_optab, TFmode, XFmode, "_U_Qfcnvff_f80_to_quad");
09299 set_conv_libfunc (trunc_optab, SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl");
09300 set_conv_libfunc (trunc_optab, DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl");
09301 set_conv_libfunc (trunc_optab, XFmode, TFmode, "_U_Qfcnvff_quad_to_f80");
09302
09303 set_conv_libfunc (sfix_optab, SImode, TFmode, "_U_Qfcnvfxt_quad_to_sgl");
09304 set_conv_libfunc (sfix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl");
09305 set_conv_libfunc (sfix_optab, TImode, TFmode, "_U_Qfcnvfxt_quad_to_quad");
09306 set_conv_libfunc (ufix_optab, SImode, TFmode, "_U_Qfcnvfxut_quad_to_sgl");
09307 set_conv_libfunc (ufix_optab, DImode, TFmode, "_U_Qfcnvfxut_quad_to_dbl");
09308
09309 set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad");
09310 set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad");
09311 set_conv_libfunc (sfloat_optab, TFmode, TImode, "_U_Qfcnvxf_quad_to_quad");
09312
09313
09314 set_conv_libfunc (ufloat_optab, TFmode, DImode, "_U_Qfcnvxuf_dbl_to_quad");
09315 }
09316
09317
09318
09319 static void
09320 ia64_hpux_init_libfuncs (void)
09321 {
09322 ia64_init_libfuncs ();
09323
09324
09325
09326
09327
09328
09329 set_optab_libfunc (sdiv_optab, SImode, 0);
09330 set_optab_libfunc (udiv_optab, SImode, 0);
09331 set_optab_libfunc (smod_optab, SImode, 0);
09332 set_optab_libfunc (umod_optab, SImode, 0);
09333
09334 set_optab_libfunc (sdiv_optab, DImode, "__milli_divI");
09335 set_optab_libfunc (udiv_optab, DImode, "__milli_divU");
09336 set_optab_libfunc (smod_optab, DImode, "__milli_remI");
09337 set_optab_libfunc (umod_optab, DImode, "__milli_remU");
09338
09339
09340 set_optab_libfunc (smin_optab, TFmode, "_U_Qfmin");
09341 set_optab_libfunc (smax_optab, TFmode, "_U_Qfmax");
09342 set_optab_libfunc (abs_optab, TFmode, "_U_Qfabs");
09343
09344
09345 cmptf_libfunc = init_one_libfunc ("_U_Qfcmp");
09346
09347
09348 set_optab_libfunc (eq_optab, TFmode, 0);
09349 set_optab_libfunc (ne_optab, TFmode, 0);
09350 set_optab_libfunc (gt_optab, TFmode, 0);
09351 set_optab_libfunc (ge_optab, TFmode, 0);
09352 set_optab_libfunc (lt_optab, TFmode, 0);
09353 set_optab_libfunc (le_optab, TFmode, 0);
09354 }
09355
09356
09357
09358 static void
09359 ia64_vms_init_libfuncs (void)
09360 {
09361 set_optab_libfunc (sdiv_optab, SImode, "OTS$DIV_I");
09362 set_optab_libfunc (sdiv_optab, DImode, "OTS$DIV_L");
09363 set_optab_libfunc (udiv_optab, SImode, "OTS$DIV_UI");
09364 set_optab_libfunc (udiv_optab, DImode, "OTS$DIV_UL");
09365 set_optab_libfunc (smod_optab, SImode, "OTS$REM_I");
09366 set_optab_libfunc (smod_optab, DImode, "OTS$REM_L");
09367 set_optab_libfunc (umod_optab, SImode, "OTS$REM_UI");
09368 set_optab_libfunc (umod_optab, DImode, "OTS$REM_UL");
09369 }
09370
09371
09372
09373
09374 static void
09375 ia64_sysv4_init_libfuncs (void)
09376 {
09377 ia64_init_libfuncs ();
09378
09379
09380
09381
09382 set_optab_libfunc (eq_optab, TFmode, "_U_Qfeq");
09383 set_optab_libfunc (ne_optab, TFmode, "_U_Qfne");
09384 set_optab_libfunc (gt_optab, TFmode, "_U_Qfgt");
09385 set_optab_libfunc (ge_optab, TFmode, "_U_Qfge");
09386 set_optab_libfunc (lt_optab, TFmode, "_U_Qflt");
09387 set_optab_libfunc (le_optab, TFmode, "_U_Qfle");
09388
09389
09390
09391 }
09392
09393
09394
09395 static int
09396 ia64_hpux_reloc_rw_mask (void)
09397 {
09398 return 3;
09399 }
09400
09401
09402
09403
09404
09405 static int
09406 ia64_reloc_rw_mask (void)
09407 {
09408 return flag_pic ? 3 : 2;
09409 }
09410
09411
09412
09413
09414 static section *
09415 ia64_select_rtx_section (enum machine_mode mode, rtx x,
09416 unsigned HOST_WIDE_INT align)
09417 {
09418 if (GET_MODE_SIZE (mode) > 0
09419 && GET_MODE_SIZE (mode) <= ia64_section_threshold
09420 && !TARGET_NO_SDATA)
09421 return sdata_section;
09422 else
09423 return default_elf_select_rtx_section (mode, x, align);
09424 }
09425
09426 static unsigned int
09427 ia64_section_type_flags (tree decl, const char *name, int reloc)
09428 {
09429 unsigned int flags = 0;
09430
09431 if (strcmp (name, ".sdata") == 0
09432 || strncmp (name, ".sdata.", 7) == 0
09433 || strncmp (name, ".gnu.linkonce.s.", 16) == 0
09434 || strncmp (name, ".sdata2.", 8) == 0
09435 || strncmp (name, ".gnu.linkonce.s2.", 17) == 0
09436 || strcmp (name, ".sbss") == 0
09437 || strncmp (name, ".sbss.", 6) == 0
09438 || strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
09439 flags = SECTION_SMALL;
09440
09441 flags |= default_section_type_flags (decl, name, reloc);
09442 return flags;
09443 }
09444
09445
09446
09447
09448
09449 static bool
09450 ia64_struct_retval_addr_is_first_parm_p (tree fntype)
09451 {
09452 tree ret_type = TREE_TYPE (fntype);
09453
09454
09455
09456
09457
09458
09459
09460 return (abi_version_at_least (2)
09461 && ret_type
09462 && TYPE_MODE (ret_type) == BLKmode
09463 && TREE_ADDRESSABLE (ret_type)
09464 && strcmp (lang_hooks.name, "GNU C++") == 0);
09465 }
09466
09467
09468
09469
09470
09471
09472
09473 static void
09474 ia64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
09475 HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
09476 tree function)
09477 {
09478 rtx this, insn, funexp;
09479 unsigned int this_parmno;
09480 unsigned int this_regno;
09481
09482 reload_completed = 1;
09483 epilogue_completed = 1;
09484 no_new_pseudos = 1;
09485 reset_block_changes ();
09486
09487
09488 last_scratch_gr_reg = 15;
09489
09490 memset (¤t_frame_info, 0, sizeof (current_frame_info));
09491 current_frame_info.spill_cfa_off = -16;
09492 current_frame_info.n_input_regs = 1;
09493 current_frame_info.need_regstk = (TARGET_REG_NAMES != 0);
09494
09495
09496 emit_note (NOTE_INSN_PROLOGUE_END);
09497
09498
09499
09500
09501 this_parmno
09502 = (ia64_struct_retval_addr_is_first_parm_p (TREE_TYPE (thunk))
09503 ? 1 : 0);
09504 this_regno = IN_REG (this_parmno);
09505 if (!TARGET_REG_NAMES)
09506 reg_names[this_regno] = ia64_reg_numbers[this_parmno];
09507
09508 this = gen_rtx_REG (Pmode, this_regno);
09509 if (TARGET_ILP32)
09510 {
09511 rtx tmp = gen_rtx_REG (ptr_mode, this_regno);
09512 REG_POINTER (tmp) = 1;
09513 if (delta && CONST_OK_FOR_I (delta))
09514 {
09515 emit_insn (gen_ptr_extend_plus_imm (this, tmp, GEN_INT (delta)));
09516 delta = 0;
09517 }
09518 else
09519 emit_insn (gen_ptr_extend (this, tmp));
09520 }
09521
09522
09523 if (delta)
09524 {
09525 rtx delta_rtx = GEN_INT (delta);
09526
09527 if (!CONST_OK_FOR_I (delta))
09528 {
09529 rtx tmp = gen_rtx_REG (Pmode, 2);
09530 emit_move_insn (tmp, delta_rtx);
09531 delta_rtx = tmp;
09532 }
09533 emit_insn (gen_adddi3 (this, this, delta_rtx));
09534 }
09535
09536
09537 if (vcall_offset)
09538 {
09539 rtx vcall_offset_rtx = GEN_INT (vcall_offset);
09540 rtx tmp = gen_rtx_REG (Pmode, 2);
09541
09542 if (TARGET_ILP32)
09543 {
09544 rtx t = gen_rtx_REG (ptr_mode, 2);
09545 REG_POINTER (t) = 1;
09546 emit_move_insn (t, gen_rtx_MEM (ptr_mode, this));
09547 if (CONST_OK_FOR_I (vcall_offset))
09548 {
09549 emit_insn (gen_ptr_extend_plus_imm (tmp, t,
09550 vcall_offset_rtx));
09551 vcall_offset = 0;
09552 }
09553 else
09554 emit_insn (gen_ptr_extend (tmp, t));
09555 }
09556 else
09557 emit_move_insn (tmp, gen_rtx_MEM (Pmode, this));
09558
09559 if (vcall_offset)
09560 {
09561 if (!CONST_OK_FOR_J (vcall_offset))
09562 {
09563 rtx tmp2 = gen_rtx_REG (Pmode, next_scratch_gr_reg ());
09564 emit_move_insn (tmp2, vcall_offset_rtx);
09565 vcall_offset_rtx = tmp2;
09566 }
09567 emit_insn (gen_adddi3 (tmp, tmp, vcall_offset_rtx));
09568 }
09569
09570 if (TARGET_ILP32)
09571 emit_move_insn (gen_rtx_REG (ptr_mode, 2),
09572 gen_rtx_MEM (ptr_mode, tmp));
09573 else
09574 emit_move_insn (tmp, gen_rtx_MEM (Pmode, tmp));
09575
09576 emit_insn (gen_adddi3 (this, this, tmp));
09577 }
09578
09579
09580 if (! TREE_USED (function))
09581 {
09582 assemble_external (function);
09583 TREE_USED (function) = 1;
09584 }
09585 funexp = XEXP (DECL_RTL (function), 0);
09586 funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
09587 ia64_expand_call (NULL_RTX, funexp, NULL_RTX, 1);
09588 insn = get_last_insn ();
09589 SIBLING_CALL_P (insn) = 1;
09590
09591
09592 reload_completed = 1;
09593 epilogue_completed = 1;
09594 try_split (PATTERN (insn), insn, 0);
09595
09596 emit_barrier ();
09597
09598
09599
09600
09601
09602
09603 insn_locators_initialize ();
09604 emit_all_insn_group_barriers (NULL);
09605 insn = get_insns ();
09606 shorten_branches (insn);
09607 final_start_function (insn, file, 1);
09608 final (insn, file, 1);
09609 final_end_function ();
09610
09611 reload_completed = 0;
09612 epilogue_completed = 0;
09613 no_new_pseudos = 0;
09614 }
09615
09616
09617
09618 static rtx
09619 ia64_struct_value_rtx (tree fntype,
09620 int incoming ATTRIBUTE_UNUSED)
09621 {
09622 if (fntype && ia64_struct_retval_addr_is_first_parm_p (fntype))
09623 return NULL_RTX;
09624 return gen_rtx_REG (Pmode, GR_REG (8));
09625 }
09626
09627 static bool
09628 ia64_scalar_mode_supported_p (enum machine_mode mode)
09629 {
09630 switch (mode)
09631 {
09632 case QImode:
09633 case HImode:
09634 case SImode:
09635 case DImode:
09636 case TImode:
09637 return true;
09638
09639 case SFmode:
09640 case DFmode:
09641 case XFmode:
09642 case RFmode:
09643 return true;
09644
09645 case TFmode:
09646 return TARGET_HPUX;
09647
09648 default:
09649 return false;
09650 }
09651 }
09652
09653 static bool
09654 ia64_vector_mode_supported_p (enum machine_mode mode)
09655 {
09656 switch (mode)
09657 {
09658 case V8QImode:
09659 case V4HImode:
09660 case V2SImode:
09661 return true;
09662
09663 case V2SFmode:
09664 return true;
09665
09666 default:
09667 return false;
09668 }
09669 }
09670
09671
09672
09673 void
09674 ia64_output_function_profiler (FILE *file, int labelno)
09675 {
09676 bool indirect_call;
09677
09678
09679
09680
09681
09682
09683
09684 if (cfun->static_chain_decl && !TARGET_NO_PIC && !TARGET_AUTO_PIC)
09685 {
09686 gcc_assert (STATIC_CHAIN_REGNUM == 15);
09687 indirect_call = true;
09688 }
09689 else
09690 indirect_call = false;
09691
09692 if (TARGET_GNU_AS)
09693 fputs ("\t.prologue 4, r40\n", file);
09694 else
09695 fputs ("\t.prologue\n\t.save ar.pfs, r40\n", file);
09696 fputs ("\talloc out0 = ar.pfs, 8, 0, 4, 0\n", file);
09697
09698 if (NO_PROFILE_COUNTERS)
09699 fputs ("\tmov out3 = r0\n", file);
09700 else
09701 {
09702 char buf[20];
09703 ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
09704
09705 if (TARGET_AUTO_PIC)
09706 fputs ("\tmovl out3 = @gprel(", file);
09707 else
09708 fputs ("\taddl out3 = @ltoff(", file);
09709 assemble_name (file, buf);
09710 if (TARGET_AUTO_PIC)
09711 fputs (")\n", file);
09712 else
09713 fputs ("), r1\n", file);
09714 }
09715
09716 if (indirect_call)
09717 fputs ("\taddl r14 = @ltoff(@fptr(_mcount)), r1\n", file);
09718 fputs ("\t;;\n", file);
09719
09720 fputs ("\t.save rp, r42\n", file);
09721 fputs ("\tmov out2 = b0\n", file);
09722 if (indirect_call)
09723 fputs ("\tld8 r14 = [r14]\n\t;;\n", file);
09724 fputs ("\t.body\n", file);
09725 fputs ("\tmov out1 = r1\n", file);
09726 if (indirect_call)
09727 {
09728 fputs ("\tld8 r16 = [r14], 8\n\t;;\n", file);
09729 fputs ("\tmov b6 = r16\n", file);
09730 fputs ("\tld8 r1 = [r14]\n", file);
09731 fputs ("\tbr.call.sptk.many b0 = b6\n\t;;\n", file);
09732 }
09733 else
09734 fputs ("\tbr.call.sptk.many b0 = _mcount\n\t;;\n", file);
09735 }
09736
09737 static GTY(()) rtx mcount_func_rtx;
09738 static rtx
09739 gen_mcount_func_rtx (void)
09740 {
09741 if (!mcount_func_rtx)
09742 mcount_func_rtx = init_one_libfunc ("_mcount");
09743 return mcount_func_rtx;
09744 }
09745
09746 void
09747 ia64_profile_hook (int labelno)
09748 {
09749 rtx label, ip;
09750
09751 if (NO_PROFILE_COUNTERS)
09752 label = const0_rtx;
09753 else
09754 {
09755 char buf[30];
09756 const char *label_name;
09757 ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
09758 label_name = (*targetm.strip_name_encoding) (ggc_strdup (buf));
09759 label = gen_rtx_SYMBOL_REF (Pmode, label_name);
09760 SYMBOL_REF_FLAGS (label) = SYMBOL_FLAG_LOCAL;
09761 }
09762 ip = gen_reg_rtx (Pmode);
09763 emit_insn (gen_ip_value (ip));
09764 emit_library_call (gen_mcount_func_rtx (), LCT_NORMAL,
09765 VOIDmode, 3,
09766 gen_rtx_REG (Pmode, BR_REG (0)), Pmode,
09767 ip, Pmode,
09768 label, Pmode);
09769 }
09770
09771
09772
09773 static const char *
09774 ia64_mangle_fundamental_type (tree type)
09775 {
09776
09777
09778 if (!TARGET_HPUX && TYPE_MODE (type) == TFmode)
09779 return "g";
09780
09781
09782
09783 if (TYPE_MODE (type) == XFmode)
09784 return TARGET_HPUX ? "u9__float80" : "e";
09785 if (TYPE_MODE (type) == RFmode)
09786 return "u7__fpreg";
09787 return NULL;
09788 }
09789
09790
09791
09792 static const char *
09793 ia64_invalid_conversion (tree fromtype, tree totype)
09794 {
09795
09796 if (TYPE_MODE (fromtype) == RFmode
09797 && TYPE_MODE (totype) != RFmode
09798 && TYPE_MODE (totype) != VOIDmode)
09799 return N_("invalid conversion from %<__fpreg%>");
09800 if (TYPE_MODE (totype) == RFmode
09801 && TYPE_MODE (fromtype) != RFmode)
09802 return N_("invalid conversion to %<__fpreg%>");
09803 return NULL;
09804 }
09805
09806
09807
09808 static const char *
09809 ia64_invalid_unary_op (int op, tree type)
09810 {
09811
09812 if (TYPE_MODE (type) == RFmode
09813 && op != CONVERT_EXPR
09814 && op != ADDR_EXPR)
09815 return N_("invalid operation on %<__fpreg%>");
09816 return NULL;
09817 }
09818
09819
09820
09821 static const char *
09822 ia64_invalid_binary_op (int op ATTRIBUTE_UNUSED, tree type1, tree type2)
09823 {
09824
09825 if (TYPE_MODE (type1) == RFmode || TYPE_MODE (type2) == RFmode)
09826 return N_("invalid operation on %<__fpreg%>");
09827 return NULL;
09828 }
09829
09830
09831 void
09832 ia64_optimization_options (int level ATTRIBUTE_UNUSED,
09833 int size ATTRIBUTE_UNUSED)
09834 {
09835
09836 set_param_value ("max-sched-extend-regions-iters", 2);
09837 }
09838
09839 #include "gt-ia64.h"