📄 ia64.c
字号:
/* Definitions of target machine for GNU compiler. Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Contributed by James E. Wilson <wilson@cygnus.com> and David Mosberger <davidm@hpl.hp.com>.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. */#include "config.h"#include "system.h"#include "rtl.h"#include "tree.h"#include "regs.h"#include "hard-reg-set.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "output.h"#include "insn-attr.h"#include "flags.h"#include "recog.h"#include "expr.h"#include "optabs.h"#include "except.h"#include "function.h"#include "ggc.h"#include "basic-block.h"#include "toplev.h"#include "sched-int.h"#include "timevar.h"#include "target.h"#include "target-def.h"#include "tm_p.h"#include "langhooks.h"/* This is used for communication between ASM_OUTPUT_LABEL and ASM_OUTPUT_LABELREF. */int ia64_asm_output_label = 0;/* Define the information needed to generate branch and scc insns. This is stored from the compare operation. */struct rtx_def * ia64_compare_op0;struct rtx_def * ia64_compare_op1;/* Register names for ia64_expand_prologue. */static const char * const ia64_reg_numbers[96] ={ "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", "r56", "r57", "r58", "r59", "r60", "r61", "r62", "r63", "r64", "r65", "r66", "r67", "r68", "r69", "r70", "r71", "r72", "r73", "r74", "r75", "r76", "r77", "r78", "r79", "r80", "r81", "r82", "r83", "r84", "r85", "r86", "r87", "r88", "r89", "r90", "r91", "r92", "r93", "r94", "r95", "r96", "r97", "r98", "r99", "r100","r101","r102","r103", "r104","r105","r106","r107","r108","r109","r110","r111", "r112","r113","r114","r115","r116","r117","r118","r119", "r120","r121","r122","r123","r124","r125","r126","r127"};/* ??? These strings could be shared with REGISTER_NAMES. */static const char * const ia64_input_reg_names[8] ={ "in0", "in1", "in2", "in3", "in4", "in5", "in6", "in7" };/* ??? These strings could be shared with REGISTER_NAMES. */static const char * const ia64_local_reg_names[80] ={ "loc0", "loc1", "loc2", "loc3", "loc4", "loc5", "loc6", "loc7", "loc8", "loc9", "loc10","loc11","loc12","loc13","loc14","loc15", "loc16","loc17","loc18","loc19","loc20","loc21","loc22","loc23", "loc24","loc25","loc26","loc27","loc28","loc29","loc30","loc31", "loc32","loc33","loc34","loc35","loc36","loc37","loc38","loc39", "loc40","loc41","loc42","loc43","loc44","loc45","loc46","loc47", "loc48","loc49","loc50","loc51","loc52","loc53","loc54","loc55", "loc56","loc57","loc58","loc59","loc60","loc61","loc62","loc63", "loc64","loc65","loc66","loc67","loc68","loc69","loc70","loc71", "loc72","loc73","loc74","loc75","loc76","loc77","loc78","loc79" };/* ??? These strings could be shared with REGISTER_NAMES. */static const char * const ia64_output_reg_names[8] ={ "out0", "out1", "out2", "out3", "out4", "out5", "out6", "out7" };/* String used with the -mfixed-range= option. */const char *ia64_fixed_range_string;/* Determines whether we use adds, addl, or movl to generate our TLS immediate offsets. */int ia64_tls_size = 22;/* String used with the -mtls-size= option. */const char *ia64_tls_size_string;/* Determines whether we run our final scheduling pass or not. We always avoid the normal second scheduling pass. */static int ia64_flag_schedule_insns2;/* Variables which are this size or smaller are put in the sdata/sbss sections. */unsigned int ia64_section_threshold;/* Structure to be filled in by ia64_compute_frame_size with register save masks and offsets for the current function. */struct ia64_frame_info{ HOST_WIDE_INT total_size; /* size of the stack frame, not including the caller's scratch area. */ HOST_WIDE_INT spill_cfa_off; /* top of the reg spill area from the cfa. */ HOST_WIDE_INT spill_size; /* size of the gr/br/fr spill area. */ HOST_WIDE_INT extra_spill_size; /* size of spill area for others. */ HARD_REG_SET mask; /* mask of saved registers. */ unsigned int gr_used_mask; /* mask of registers in use as gr spill registers or long-term scratches. */ int n_spilled; /* number of spilled registers. */ int reg_fp; /* register for fp. */ int reg_save_b0; /* save register for b0. */ int reg_save_pr; /* save register for prs. */ int reg_save_ar_pfs; /* save register for ar.pfs. */ int reg_save_ar_unat; /* save register for ar.unat. */ int reg_save_ar_lc; /* save register for ar.lc. */ int reg_save_gp; /* save register for gp. */ int n_input_regs; /* number of input registers used. */ int n_local_regs; /* number of local registers used. */ int n_output_regs; /* number of output registers used. */ int n_rotate_regs; /* number of rotating registers used. */ char need_regstk; /* true if a .regstk directive needed. */ char initialized; /* true if the data is finalized. */};/* Current frame information calculated by ia64_compute_frame_size. */static struct ia64_frame_info current_frame_info;static rtx gen_tls_get_addr PARAMS ((void));static rtx gen_thread_pointer PARAMS ((void));static int find_gr_spill PARAMS ((int));static int next_scratch_gr_reg PARAMS ((void));static void mark_reg_gr_used_mask PARAMS ((rtx, void *));static void ia64_compute_frame_size PARAMS ((HOST_WIDE_INT));static void setup_spill_pointers PARAMS ((int, rtx, HOST_WIDE_INT));static void finish_spill_pointers PARAMS ((void));static rtx spill_restore_mem PARAMS ((rtx, HOST_WIDE_INT));static void do_spill PARAMS ((rtx (*)(rtx, rtx, rtx), rtx, HOST_WIDE_INT, rtx));static void do_restore PARAMS ((rtx (*)(rtx, rtx, rtx), rtx, HOST_WIDE_INT));static rtx gen_movdi_x PARAMS ((rtx, rtx, rtx));static rtx gen_fr_spill_x PARAMS ((rtx, rtx, rtx));static rtx gen_fr_restore_x PARAMS ((rtx, rtx, rtx));static enum machine_mode hfa_element_mode PARAMS ((tree, int));static void fix_range PARAMS ((const char *));static struct machine_function * ia64_init_machine_status PARAMS ((void));static void emit_insn_group_barriers PARAMS ((FILE *, rtx));static void emit_all_insn_group_barriers PARAMS ((FILE *, rtx));static void emit_predicate_relation_info PARAMS ((void));static bool ia64_in_small_data_p PARAMS ((tree));static void ia64_encode_section_info PARAMS ((tree, int));static const char *ia64_strip_name_encoding PARAMS ((const char *));static void process_epilogue PARAMS ((void));static int process_set PARAMS ((FILE *, rtx));static rtx ia64_expand_fetch_and_op PARAMS ((optab, enum machine_mode, tree, rtx));static rtx ia64_expand_op_and_fetch PARAMS ((optab, enum machine_mode, tree, rtx));static rtx ia64_expand_compare_and_swap PARAMS ((enum machine_mode, enum machine_mode, int, tree, rtx));static rtx ia64_expand_lock_test_and_set PARAMS ((enum machine_mode, tree, rtx));static rtx ia64_expand_lock_release PARAMS ((enum machine_mode, tree, rtx));static bool ia64_assemble_integer PARAMS ((rtx, unsigned int, int));static void ia64_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));static void ia64_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));static void ia64_output_function_end_prologue PARAMS ((FILE *));static int ia64_issue_rate PARAMS ((void));static int ia64_adjust_cost PARAMS ((rtx, rtx, rtx, int));static void ia64_sched_init PARAMS ((FILE *, int, int));static void ia64_sched_finish PARAMS ((FILE *, int));static int ia64_internal_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int, int));static int ia64_sched_reorder PARAMS ((FILE *, int, rtx *, int *, int));static int ia64_sched_reorder2 PARAMS ((FILE *, int, rtx *, int *, int));static int ia64_variable_issue PARAMS ((FILE *, int, rtx, int));static void ia64_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));static void ia64_select_rtx_section PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT));static void ia64_rwreloc_select_section PARAMS ((tree, int, unsigned HOST_WIDE_INT)) ATTRIBUTE_UNUSED;static void ia64_rwreloc_unique_section PARAMS ((tree, int)) ATTRIBUTE_UNUSED;static void ia64_rwreloc_select_rtx_section PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT)) ATTRIBUTE_UNUSED;static unsigned int ia64_rwreloc_section_type_flags PARAMS ((tree, const char *, int)) ATTRIBUTE_UNUSED;static void ia64_hpux_add_extern_decl PARAMS ((const char *name)) ATTRIBUTE_UNUSED;/* Table of valid machine attributes. */static const struct attribute_spec ia64_attribute_table[] ={ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ { "syscall_linkage", 0, 0, false, true, true, NULL }, { NULL, 0, 0, false, false, false, NULL }};/* Initialize the GCC target structure. */#undef TARGET_ATTRIBUTE_TABLE#define TARGET_ATTRIBUTE_TABLE ia64_attribute_table#undef TARGET_INIT_BUILTINS#define TARGET_INIT_BUILTINS ia64_init_builtins#undef TARGET_EXPAND_BUILTIN#define TARGET_EXPAND_BUILTIN ia64_expand_builtin#undef TARGET_ASM_BYTE_OP#define TARGET_ASM_BYTE_OP "\tdata1\t"#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\tdata2\t"#undef TARGET_ASM_ALIGNED_SI_OP#define TARGET_ASM_ALIGNED_SI_OP "\tdata4\t"#undef TARGET_ASM_ALIGNED_DI_OP#define TARGET_ASM_ALIGNED_DI_OP "\tdata8\t"#undef TARGET_ASM_UNALIGNED_HI_OP#define TARGET_ASM_UNALIGNED_HI_OP "\tdata2.ua\t"#undef TARGET_ASM_UNALIGNED_SI_OP#define TARGET_ASM_UNALIGNED_SI_OP "\tdata4.ua\t"#undef TARGET_ASM_UNALIGNED_DI_OP#define TARGET_ASM_UNALIGNED_DI_OP "\tdata8.ua\t"#undef TARGET_ASM_INTEGER#define TARGET_ASM_INTEGER ia64_assemble_integer#undef TARGET_ASM_FUNCTION_PROLOGUE#define TARGET_ASM_FUNCTION_PROLOGUE ia64_output_function_prologue#undef TARGET_ASM_FUNCTION_END_PROLOGUE#define TARGET_ASM_FUNCTION_END_PROLOGUE ia64_output_function_end_prologue#undef TARGET_ASM_FUNCTION_EPILOGUE#define TARGET_ASM_FUNCTION_EPILOGUE ia64_output_function_epilogue#undef TARGET_IN_SMALL_DATA_P#define TARGET_IN_SMALL_DATA_P ia64_in_small_data_p#undef TARGET_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO ia64_encode_section_info#undef TARGET_STRIP_NAME_ENCODING#define TARGET_STRIP_NAME_ENCODING ia64_strip_name_encoding#undef TARGET_SCHED_ADJUST_COST#define TARGET_SCHED_ADJUST_COST ia64_adjust_cost#undef TARGET_SCHED_ISSUE_RATE#define TARGET_SCHED_ISSUE_RATE ia64_issue_rate#undef TARGET_SCHED_VARIABLE_ISSUE#define TARGET_SCHED_VARIABLE_ISSUE ia64_variable_issue#undef TARGET_SCHED_INIT#define TARGET_SCHED_INIT ia64_sched_init#undef TARGET_SCHED_FINISH#define TARGET_SCHED_FINISH ia64_sched_finish#undef TARGET_SCHED_REORDER#define TARGET_SCHED_REORDER ia64_sched_reorder#undef TARGET_SCHED_REORDER2#define TARGET_SCHED_REORDER2 ia64_sched_reorder2#undef TARGET_ASM_OUTPUT_MI_THUNK#define TARGET_ASM_OUTPUT_MI_THUNK ia64_output_mi_thunk#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_truestruct gcc_target targetm = TARGET_INITIALIZER;/* Return 1 if OP is a valid operand for the MEM of a CALL insn. */intcall_operand (op, mode) rtx op; enum machine_mode mode;{ if (mode != GET_MODE (op) && mode != VOIDmode) return 0; return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG || (GET_CODE (op) == SUBREG && GET_CODE (XEXP (op, 0)) == REG));}/* Return 1 if OP refers to a symbol in the sdata section. */intsdata_symbolic_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ switch (GET_CODE (op)) { case CONST: if (GET_CODE (XEXP (op, 0)) != PLUS || GET_CODE (XEXP (XEXP (op, 0), 0)) != SYMBOL_REF) break; op = XEXP (XEXP (op, 0), 0); /* FALLTHRU */ case SYMBOL_REF: if (CONSTANT_POOL_ADDRESS_P (op)) return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold; else { const char *str = XSTR (op, 0); return (str[0] == ENCODE_SECTION_INFO_CHAR && str[1] == 's'); } default: break; } return 0;}/* Return 1 if OP refers to a symbol, and is appropriate for a GOT load. */intgot_symbolic_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ switch (GET_CODE (op)) { case CONST: op = XEXP (op, 0); if (GET_CODE (op) != PLUS) return 0; if (GET_CODE (XEXP (op, 0)) != SYMBOL_REF) return 0; op = XEXP (op, 1); if (GET_CODE (op) != CONST_INT) return 0; return 1; /* Ok if we're not using GOT entries at all. */ if (TARGET_NO_PIC || TARGET_AUTO_PIC) return 1; /* "Ok" while emitting rtl, since otherwise we won't be provided with the entire offset during emission, which makes it very hard to split the offset into high and low parts. */ if (rtx_equal_function_value_matters) return 1; /* Force the low 14 bits of the constant to zero so that we do not use up so many GOT entries. */ return (INTVAL (op) & 0x3fff) == 0; case SYMBOL_REF: case LABEL_REF: return 1; default: break; } return 0;}/* Return 1 if OP refers to a symbol. */intsymbolic_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ switch (GET_CODE (op)) { case CONST: case SYMBOL_REF: case LABEL_REF: return 1; default: break; } return 0;}/* Return tls_model if OP refers to a TLS symbol. */inttls_symbolic_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ const char *str; if (GET_CODE (op) != SYMBOL_REF) return 0; str = XSTR (op, 0); if (str[0] != ENCODE_SECTION_INFO_CHAR) return 0; switch (str[1]) { case 'G': return TLS_MODEL_GLOBAL_DYNAMIC; case 'L': return TLS_MODEL_LOCAL_DYNAMIC; case 'i': return TLS_MODEL_INITIAL_EXEC; case 'l': return TLS_MODEL_LOCAL_EXEC; } return 0;}/* Return 1 if OP refers to a function. */intfunction_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ if (GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_FLAG (op)) return 1; else return 0;}/* Return 1 if OP is setjmp or a similar function. *//* ??? This is an unsatisfying solution. Should rethink. */intsetjmp_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ const char *name; int retval = 0; if (GET_CODE (op) != SYMBOL_REF) return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -