📄 pa.c
字号:
/* Subroutines for insn-output.c for HPPA. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Tim Moore (moore@cs.utah.edu), based on sparc.cThis file is part of GCC.GCC 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.GCC 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 GCC; 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 "coretypes.h"#include "tm.h"#include "rtl.h"#include "regs.h"#include "hard-reg-set.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "insn-attr.h"#include "flags.h"#include "tree.h"#include "output.h"#include "except.h"#include "expr.h"#include "optabs.h"#include "reload.h"#include "integrate.h"#include "function.h"#include "toplev.h"#include "ggc.h"#include "recog.h"#include "predict.h"#include "tm_p.h"#include "target.h"#include "target-def.h"/* Return nonzero if there is a bypass for the output of OUT_INSN and the fp store IN_INSN. */inthppa_fpstore_bypass_p (rtx out_insn, rtx in_insn){ enum machine_mode store_mode; enum machine_mode other_mode; rtx set; if (recog_memoized (in_insn) < 0 || get_attr_type (in_insn) != TYPE_FPSTORE || recog_memoized (out_insn) < 0) return 0; store_mode = GET_MODE (SET_SRC (PATTERN (in_insn))); set = single_set (out_insn); if (!set) return 0; other_mode = GET_MODE (SET_SRC (set)); return (GET_MODE_SIZE (store_mode) == GET_MODE_SIZE (other_mode));} #ifndef DO_FRAME_NOTES#ifdef INCOMING_RETURN_ADDR_RTX#define DO_FRAME_NOTES 1#else#define DO_FRAME_NOTES 0#endif#endifstatic void copy_reg_pointer (rtx, rtx);static void fix_range (const char *);static int hppa_address_cost (rtx);static bool hppa_rtx_costs (rtx, int, int, int *);static inline rtx force_mode (enum machine_mode, rtx);static void pa_reorg (void);static void pa_combine_instructions (void);static int pa_can_combine_p (rtx, rtx, rtx, int, rtx, rtx, rtx);static int forward_branch_p (rtx);static int shadd_constant_p (int);static void compute_zdepwi_operands (unsigned HOST_WIDE_INT, unsigned *);static int compute_movmem_length (rtx);static int compute_clrmem_length (rtx);static bool pa_assemble_integer (rtx, unsigned int, int);static void remove_useless_addtr_insns (int);static void store_reg (int, HOST_WIDE_INT, int);static void store_reg_modify (int, int, HOST_WIDE_INT);static void load_reg (int, HOST_WIDE_INT, int);static void set_reg_plus_d (int, int, HOST_WIDE_INT, int);static void pa_output_function_prologue (FILE *, HOST_WIDE_INT);static void update_total_code_bytes (int);static void pa_output_function_epilogue (FILE *, HOST_WIDE_INT);static int pa_adjust_cost (rtx, rtx, rtx, int);static int pa_adjust_priority (rtx, int);static int pa_issue_rate (void);static void pa_select_section (tree, int, unsigned HOST_WIDE_INT) ATTRIBUTE_UNUSED;static void pa_encode_section_info (tree, rtx, int);static const char *pa_strip_name_encoding (const char *);static bool pa_function_ok_for_sibcall (tree, tree);static void pa_globalize_label (FILE *, const char *) ATTRIBUTE_UNUSED;static void pa_asm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);#if !defined(USE_COLLECT2)static void pa_asm_out_constructor (rtx, int);static void pa_asm_out_destructor (rtx, int);#endifstatic void pa_init_builtins (void);static rtx hppa_builtin_saveregs (void);static tree hppa_gimplify_va_arg_expr (tree, tree, tree *, tree *);static bool pa_scalar_mode_supported_p (enum machine_mode);static void copy_fp_args (rtx) ATTRIBUTE_UNUSED;static int length_fp_args (rtx) ATTRIBUTE_UNUSED;static struct deferred_plabel *get_plabel (rtx) ATTRIBUTE_UNUSED;static inline void pa_file_start_level (void) ATTRIBUTE_UNUSED;static inline void pa_file_start_space (int) ATTRIBUTE_UNUSED;static inline void pa_file_start_file (int) ATTRIBUTE_UNUSED;static inline void pa_file_start_mcount (const char*) ATTRIBUTE_UNUSED;static void pa_elf_file_start (void) ATTRIBUTE_UNUSED;static void pa_som_file_start (void) ATTRIBUTE_UNUSED;static void pa_linux_file_start (void) ATTRIBUTE_UNUSED;static void pa_hpux64_gas_file_start (void) ATTRIBUTE_UNUSED;static void pa_hpux64_hpas_file_start (void) ATTRIBUTE_UNUSED;static void output_deferred_plabels (void);#ifdef ASM_OUTPUT_EXTERNAL_REALstatic void pa_hpux_file_end (void);#endif#ifdef HPUX_LONG_DOUBLE_LIBRARYstatic void pa_hpux_init_libfuncs (void);#endifstatic rtx pa_struct_value_rtx (tree, int);static bool pa_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, tree, bool);static int pa_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, tree, bool);static struct machine_function * pa_init_machine_status (void);/* Save the operands last given to a compare for use when we generate a scc or bcc insn. */rtx hppa_compare_op0, hppa_compare_op1;enum cmp_type hppa_branch_type;/* Which architecture we are generating code for. */enum architecture_type pa_arch;/* String to hold which architecture we are generating code for. */const char *pa_arch_string;/* String used with the -mfixed-range= option. */const char *pa_fixed_range_string;/* Which cpu we are scheduling for. */enum processor_type pa_cpu;/* String to hold which cpu we are scheduling for. */const char *pa_cpu_string;/* String used with the -munix= option. */const char *pa_unix_string;/* The UNIX standard to use for predefines and linking. */int flag_pa_unix;/* Counts for the number of callee-saved general and floating point registers which were saved by the current function's prologue. */static int gr_saved, fr_saved;static rtx find_addr_reg (rtx);/* Keep track of the number of bytes we have output in the CODE subspace during this compilation so we'll know when to emit inline long-calls. */unsigned long total_code_bytes;/* The last address of the previous function plus the number of bytes in associated thunks that have been output. This is used to determine if a thunk can use an IA-relative branch to reach its target function. */static int last_address;/* Variables to handle plabels that we discover are necessary at assembly output time. They are output after the current function. */struct deferred_plabel GTY(()){ rtx internal_label; rtx symbol;};static GTY((length ("n_deferred_plabels"))) struct deferred_plabel * deferred_plabels;static size_t n_deferred_plabels = 0;/* Initialize the GCC target structure. */#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"#undef TARGET_ASM_ALIGNED_SI_OP#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"#undef TARGET_ASM_ALIGNED_DI_OP#define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"#undef TARGET_ASM_UNALIGNED_HI_OP#define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP#undef TARGET_ASM_UNALIGNED_SI_OP#define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP#undef TARGET_ASM_UNALIGNED_DI_OP#define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP#undef TARGET_ASM_INTEGER#define TARGET_ASM_INTEGER pa_assemble_integer#undef TARGET_ASM_FUNCTION_PROLOGUE#define TARGET_ASM_FUNCTION_PROLOGUE pa_output_function_prologue#undef TARGET_ASM_FUNCTION_EPILOGUE#define TARGET_ASM_FUNCTION_EPILOGUE pa_output_function_epilogue#undef TARGET_SCHED_ADJUST_COST#define TARGET_SCHED_ADJUST_COST pa_adjust_cost#undef TARGET_SCHED_ADJUST_PRIORITY#define TARGET_SCHED_ADJUST_PRIORITY pa_adjust_priority#undef TARGET_SCHED_ISSUE_RATE#define TARGET_SCHED_ISSUE_RATE pa_issue_rate#undef TARGET_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO pa_encode_section_info#undef TARGET_STRIP_NAME_ENCODING#define TARGET_STRIP_NAME_ENCODING pa_strip_name_encoding#undef TARGET_FUNCTION_OK_FOR_SIBCALL#define TARGET_FUNCTION_OK_FOR_SIBCALL pa_function_ok_for_sibcall#undef TARGET_ASM_OUTPUT_MI_THUNK#define TARGET_ASM_OUTPUT_MI_THUNK pa_asm_output_mi_thunk#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall#undef TARGET_ASM_FILE_END#ifdef ASM_OUTPUT_EXTERNAL_REAL#define TARGET_ASM_FILE_END pa_hpux_file_end#else#define TARGET_ASM_FILE_END output_deferred_plabels#endif#if !defined(USE_COLLECT2)#undef TARGET_ASM_CONSTRUCTOR#define TARGET_ASM_CONSTRUCTOR pa_asm_out_constructor#undef TARGET_ASM_DESTRUCTOR#define TARGET_ASM_DESTRUCTOR pa_asm_out_destructor#endif#undef TARGET_INIT_BUILTINS#define TARGET_INIT_BUILTINS pa_init_builtins#undef TARGET_RTX_COSTS#define TARGET_RTX_COSTS hppa_rtx_costs#undef TARGET_ADDRESS_COST#define TARGET_ADDRESS_COST hppa_address_cost#undef TARGET_MACHINE_DEPENDENT_REORG#define TARGET_MACHINE_DEPENDENT_REORG pa_reorg#ifdef HPUX_LONG_DOUBLE_LIBRARY#undef TARGET_INIT_LIBFUNCS#define TARGET_INIT_LIBFUNCS pa_hpux_init_libfuncs#endif#undef TARGET_PROMOTE_FUNCTION_RETURN#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true#undef TARGET_PROMOTE_PROTOTYPES#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true#undef TARGET_STRUCT_VALUE_RTX#define TARGET_STRUCT_VALUE_RTX pa_struct_value_rtx#undef TARGET_RETURN_IN_MEMORY#define TARGET_RETURN_IN_MEMORY pa_return_in_memory#undef TARGET_MUST_PASS_IN_STACK#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size#undef TARGET_PASS_BY_REFERENCE#define TARGET_PASS_BY_REFERENCE pa_pass_by_reference#undef TARGET_CALLEE_COPIES#define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true#undef TARGET_ARG_PARTIAL_BYTES#define TARGET_ARG_PARTIAL_BYTES pa_arg_partial_bytes#undef TARGET_EXPAND_BUILTIN_SAVEREGS#define TARGET_EXPAND_BUILTIN_SAVEREGS hppa_builtin_saveregs#undef TARGET_GIMPLIFY_VA_ARG_EXPR#define TARGET_GIMPLIFY_VA_ARG_EXPR hppa_gimplify_va_arg_expr#undef TARGET_SCALAR_MODE_SUPPORTED_P#define TARGET_SCALAR_MODE_SUPPORTED_P pa_scalar_mode_supported_pstruct gcc_target targetm = TARGET_INITIALIZER;/* Parse the -mfixed-range= option string. */static voidfix_range (const char *const_str){ int i, first, last; char *str, *dash, *comma; /* str must be of the form REG1'-'REG2{,REG1'-'REG} where REG1 and REG2 are either register names or register numbers. The effect of this option is to mark the registers in the range from REG1 to REG2 as ``fixed'' so they won't be used by the compiler. This is used, e.g., to ensure that kernel mode code doesn't use f32-f127. */ i = strlen (const_str); str = (char *) alloca (i + 1); memcpy (str, const_str, i + 1); while (1) { dash = strchr (str, '-'); if (!dash) { warning ("value of -mfixed-range must have form REG1-REG2"); return; } *dash = '\0'; comma = strchr (dash + 1, ','); if (comma) *comma = '\0'; first = decode_reg_name (str); if (first < 0) { warning ("unknown register name: %s", str); return; } last = decode_reg_name (dash + 1); if (last < 0) { warning ("unknown register name: %s", dash + 1); return; } *dash = '-'; if (first > last) { warning ("%s-%s is an empty range", str, dash + 1); return; } for (i = first; i <= last; ++i) fixed_regs[i] = call_used_regs[i] = 1; if (!comma) break; *comma = ','; str = comma + 1; } /* Check if all floating point registers have been fixed. */ for (i = FP_REG_FIRST; i <= FP_REG_LAST; i++) if (!fixed_regs[i]) break; if (i > FP_REG_LAST) target_flags |= MASK_DISABLE_FPREGS;}voidoverride_options (void){ if (pa_cpu_string == NULL) pa_cpu_string = TARGET_SCHED_DEFAULT; if (! strcmp (pa_cpu_string, "8000")) { pa_cpu_string = "8000"; pa_cpu = PROCESSOR_8000; } else if (! strcmp (pa_cpu_string, "7100")) { pa_cpu_string = "7100"; pa_cpu = PROCESSOR_7100; } else if (! strcmp (pa_cpu_string, "700")) { pa_cpu_string = "700"; pa_cpu = PROCESSOR_700; } else if (! strcmp (pa_cpu_string, "7100LC")) { pa_cpu_string = "7100LC"; pa_cpu = PROCESSOR_7100LC; } else if (! strcmp (pa_cpu_string, "7200")) { pa_cpu_string = "7200"; pa_cpu = PROCESSOR_7200; } else if (! strcmp (pa_cpu_string, "7300")) { pa_cpu_string = "7300"; pa_cpu = PROCESSOR_7300; } else { warning ("unknown -mschedule= option (%s).\nValid options are 700, 7100, 7100LC, 7200, 7300, and 8000\n", pa_cpu_string); } /* Set the instruction architecture. */ if (pa_arch_string && ! strcmp (pa_arch_string, "1.0")) { pa_arch_string = "1.0"; pa_arch = ARCHITECTURE_10; target_flags &= ~(MASK_PA_11 | MASK_PA_20); } else if (pa_arch_string && ! strcmp (pa_arch_string, "1.1")) { pa_arch_string = "1.1";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -