📄 frv.c
字号:
/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. Contributed by Red Hat, Inc.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 "insn-flags.h"#include "output.h"#include "insn-attr.h"#include "flags.h"#include "recog.h"#include "reload.h"#include "expr.h"#include "obstack.h"#include "except.h"#include "function.h"#include "optabs.h"#include "toplev.h"#include "basic-block.h"#include "tm_p.h"#include "ggc.h"#include <ctype.h>#include "target.h"#include "target-def.h"#ifndef FRV_INLINE#define FRV_INLINE inline#endif/* Temporary register allocation support structure. */typedef struct frv_tmp_reg_struct { HARD_REG_SET regs; /* possible registers to allocate */ int next_reg[N_REG_CLASSES]; /* next register to allocate per class */ }frv_tmp_reg_t;/* Register state information for VLIW re-packing phase. These values must fit within an unsigned char. */#define REGSTATE_DEAD 0x00 /* register is currently dead */#define REGSTATE_CC_MASK 0x07 /* Mask to isolate CCn for cond exec */#define REGSTATE_LIVE 0x08 /* register is live */#define REGSTATE_MODIFIED 0x10 /* reg modified in current VLIW insn */#define REGSTATE_IF_TRUE 0x20 /* reg modified in cond exec true */#define REGSTATE_IF_FALSE 0x40 /* reg modified in cond exec false */#define REGSTATE_UNUSED 0x80 /* bit for hire */#define REGSTATE_MASK 0xff /* mask for the bits to set */ /* conditional expression used */#define REGSTATE_IF_EITHER (REGSTATE_IF_TRUE | REGSTATE_IF_FALSE)/* the following is not sure in the reg_state bytes, so can have a larger value than 0xff. */#define REGSTATE_CONDJUMP 0x100 /* conditional jump done in VLIW insn *//* Used in frv_frame_accessor_t to indicate the direction of a register-to- memory move. */enum frv_stack_op{ FRV_LOAD, FRV_STORE};/* Information required by frv_frame_access. */typedef struct{ /* This field is FRV_LOAD if registers are to be loaded from the stack and FRV_STORE if they should be stored onto the stack. FRV_STORE implies the move is being done by the prologue code while FRV_LOAD implies it is being done by the epilogue. */ enum frv_stack_op op; /* The base register to use when accessing the stack. This may be the frame pointer, stack pointer, or a temporary. The choice of register depends on which part of the frame is being accessed and how big the frame is. */ rtx base; /* The offset of BASE from the bottom of the current frame, in bytes. */ int base_offset;} frv_frame_accessor_t;/* Define the information needed to generate branch and scc insns. This is stored from the compare operation. */rtx frv_compare_op0;rtx frv_compare_op1;/* Conditional execution support gathered together in one structure */typedef struct { /* Linked list of insns to add if the conditional execution conversion was successful. Each link points to an EXPR_LIST which points to the pattern of the insn to add, and the insn to be inserted before. */ rtx added_insns_list; /* Identify which registers are safe to allocate for if conversions to conditional execution. We keep the last allocated register in the register classes between COND_EXEC statements. This will mean we allocate different registers for each different COND_EXEC group if we can. This might allow the scheduler to intermix two different COND_EXEC sections. */ frv_tmp_reg_t tmp_reg; /* For nested IFs, identify which CC registers are used outside of setting via a compare isnsn, and using via a check insn. This will allow us to know if we can rewrite the register to use a different register that will be paired with the CR register controlling the nested IF-THEN blocks. */ HARD_REG_SET nested_cc_ok_rewrite; /* Temporary registers allocated to hold constants during conditional execution. */ rtx scratch_regs[FIRST_PSEUDO_REGISTER]; /* Current number of temp registers available. */ int cur_scratch_regs; /* Number of nested conditional execution blocks */ int num_nested_cond_exec; /* Map of insns that set up constants in scratch registers. */ bitmap scratch_insns_bitmap; /* Conditional execution test register (CC0..CC7) */ rtx cr_reg; /* Conditional execution compare register that is paired with cr_reg, so that nested compares can be done. The csubcc and caddcc instructions don't have enough bits to specify both a CC register to be set and a CR register to do the test on, so the same bit number is used for both. Needless to say, this is rather inconvient for GCC. */ rtx nested_cc_reg; /* Extra CR registers used for &&, ||. */ rtx extra_int_cr; rtx extra_fp_cr; /* Previous CR used in nested if, to make sure we are dealing with the same nested if as the previous statement. */ rtx last_nested_if_cr; }frv_ifcvt_t;static /* GTY(()) */ frv_ifcvt_t frv_ifcvt;/* Map register number to smallest register class. */enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];/* Map class letter into register class */enum reg_class reg_class_from_letter[256];/* Cached value of frv_stack_info */static frv_stack_t *frv_stack_cache = (frv_stack_t *)0;/* -mbranch-cost= support */const char *frv_branch_cost_string;int frv_branch_cost_int = DEFAULT_BRANCH_COST;/* -mcpu= support */const char *frv_cpu_string; /* -mcpu= option */frv_cpu_t frv_cpu_type = CPU_TYPE; /* value of -mcpu= *//* -mcond-exec-insns= support */const char *frv_condexec_insns_str; /* -mcond-exec-insns= option */int frv_condexec_insns = DEFAULT_CONDEXEC_INSNS; /* value of -mcond-exec-insns*//* -mcond-exec-temps= support */const char *frv_condexec_temps_str; /* -mcond-exec-temps= option */int frv_condexec_temps = DEFAULT_CONDEXEC_TEMPS; /* value of -mcond-exec-temps*//* -msched-lookahead=n */const char *frv_sched_lookahead_str; /* -msched-lookahead=n */int frv_sched_lookahead = 4; /* -msched-lookahead=n *//* Forward references */static int frv_default_flags_for_cpu PARAMS ((void));static int frv_string_begins_with PARAMS ((tree, const char *));static FRV_INLINE int symbol_ref_small_data_p PARAMS ((rtx));static FRV_INLINE int const_small_data_p PARAMS ((rtx));static FRV_INLINE int plus_small_data_p PARAMS ((rtx, rtx));static void frv_print_operand_memory_reference_reg PARAMS ((FILE *, rtx));static void frv_print_operand_memory_reference PARAMS ((FILE *, rtx, int));static int frv_print_operand_jump_hint PARAMS ((rtx));static FRV_INLINE int frv_regno_ok_for_base_p PARAMS ((int, int));static rtx single_set_pattern PARAMS ((rtx));static int frv_function_contains_far_jump PARAMS ((void));static rtx frv_alloc_temp_reg PARAMS ((frv_tmp_reg_t *, enum reg_class, enum machine_mode, int, int));static rtx frv_frame_offset_rtx PARAMS ((int));static rtx frv_frame_mem PARAMS ((enum machine_mode, rtx, int));static rtx frv_dwarf_store PARAMS ((rtx, int));static void frv_frame_insn PARAMS ((rtx, rtx));static void frv_frame_access PARAMS ((frv_frame_accessor_t*, rtx, int));static void frv_frame_access_multi PARAMS ((frv_frame_accessor_t*, frv_stack_t *, int));static void frv_frame_access_standard_regs PARAMS ((enum frv_stack_op, frv_stack_t *));static struct machine_function *frv_init_machine_status PARAMS ((void));static int frv_legitimate_memory_operand PARAMS ((rtx, enum machine_mode, int));static rtx frv_int_to_acc PARAMS ((enum insn_code, int, rtx));static enum machine_mode frv_matching_accg_mode PARAMS ((enum machine_mode));static rtx frv_read_argument PARAMS ((tree *));static int frv_check_constant_argument PARAMS ((enum insn_code, int, rtx));static rtx frv_legitimize_target PARAMS ((enum insn_code, rtx));static rtx frv_legitimize_argument PARAMS ((enum insn_code, int, rtx));static rtx frv_expand_set_builtin PARAMS ((enum insn_code, tree, rtx));static rtx frv_expand_unop_builtin PARAMS ((enum insn_code, tree, rtx));static rtx frv_expand_binop_builtin PARAMS ((enum insn_code, tree, rtx));static rtx frv_expand_cut_builtin PARAMS ((enum insn_code, tree, rtx));static rtx frv_expand_binopimm_builtin PARAMS ((enum insn_code, tree, rtx));static rtx frv_expand_voidbinop_builtin PARAMS ((enum insn_code, tree));static rtx frv_expand_voidtriop_builtin PARAMS ((enum insn_code, tree));static rtx frv_expand_voidaccop_builtin PARAMS ((enum insn_code, tree));static rtx frv_expand_mclracc_builtin PARAMS ((tree));static rtx frv_expand_mrdacc_builtin PARAMS ((enum insn_code, tree));static rtx frv_expand_mwtacc_builtin PARAMS ((enum insn_code, tree));static rtx frv_expand_noargs_builtin PARAMS ((enum insn_code));static rtx frv_emit_comparison PARAMS ((enum rtx_code, rtx, rtx));static int frv_clear_registers_used PARAMS ((rtx *, void *));static void frv_ifcvt_add_insn PARAMS ((rtx, rtx, int));static rtx frv_ifcvt_rewrite_mem PARAMS ((rtx, enum machine_mode, rtx));static rtx frv_ifcvt_load_value PARAMS ((rtx, rtx));static void frv_registers_update PARAMS ((rtx, unsigned char [], int [], int *, int));static int frv_registers_used_p PARAMS ((rtx, unsigned char [], int));static int frv_registers_set_p PARAMS ((rtx, unsigned char [], int));static void frv_pack_insns PARAMS ((void));static void frv_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));static void frv_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));static bool frv_assemble_integer PARAMS ((rtx, unsigned, int));static const char * frv_strip_name_encoding PARAMS ((const char *));static void frv_encode_section_info PARAMS ((tree, int));static void frv_init_builtins PARAMS ((void));static rtx frv_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));static bool frv_in_small_data_p PARAMS ((tree));static void frv_asm_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree));/* Initialize the GCC target structure. */#undef TARGET_ASM_FUNCTION_PROLOGUE#define TARGET_ASM_FUNCTION_PROLOGUE frv_function_prologue#undef TARGET_ASM_FUNCTION_EPILOGUE#define TARGET_ASM_FUNCTION_EPILOGUE frv_function_epilogue#undef TARGET_ASM_INTEGER#define TARGET_ASM_INTEGER frv_assemble_integer#undef TARGET_STRIP_NAME_ENCODING#define TARGET_STRIP_NAME_ENCODING frv_strip_name_encoding#undef TARGET_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO frv_encode_section_info#undef TARGET_INIT_BUILTINS#define TARGET_INIT_BUILTINS frv_init_builtins#undef TARGET_EXPAND_BUILTIN#define TARGET_EXPAND_BUILTIN frv_expand_builtin#undef TARGET_IN_SMALL_DATA_P#define TARGET_IN_SMALL_DATA_P frv_in_small_data_p#undef TARGET_ASM_OUTPUT_MI_THUNK#define TARGET_ASM_OUTPUT_MI_THUNK frv_asm_output_mi_thunk#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcallstruct gcc_target targetm = TARGET_INITIALIZER;/* Given a SYMBOL_REF, return true if it points to small data. */static FRV_INLINE intsymbol_ref_small_data_p (x) rtx x;{ return SDATA_NAME_P (XSTR (x, 0));}/* Given a CONST, return true if the symbol_ref points to small data. */static FRV_INLINE intconst_small_data_p (x) rtx x;{ rtx x0, x1; if (GET_CODE (XEXP (x, 0)) != PLUS) return FALSE; x0 = XEXP (XEXP (x, 0), 0); if (GET_CODE (x0) != SYMBOL_REF || !SDATA_NAME_P (XSTR (x0, 0))) return FALSE; x1 = XEXP (XEXP (x, 0), 1); if (GET_CODE (x1) != CONST_INT || !IN_RANGE_P (INTVAL (x1), -2048, 2047)) return FALSE; return TRUE;}/* Given a PLUS, return true if this is a small data reference. */static FRV_INLINE intplus_small_data_p (op0, op1) rtx op0; rtx op1;{ if (GET_MODE (op0) == SImode && GET_CODE (op0) == REG && REGNO (op0) == SDA_BASE_REG) { if (GET_CODE (op1) == SYMBOL_REF) return symbol_ref_small_data_p (op1); if (GET_CODE (op1) == CONST) return const_small_data_p (op1); } return FALSE;}static intfrv_default_flags_for_cpu (){ switch (frv_cpu_type) { case FRV_CPU_GENERIC: return MASK_DEFAULT_FRV; case FRV_CPU_FR500: case FRV_CPU_TOMCAT: return MASK_DEFAULT_FR500; case FRV_CPU_FR400: return MASK_DEFAULT_FR400; case FRV_CPU_FR300: case FRV_CPU_SIMPLE: return MASK_DEFAULT_SIMPLE; } abort ();}/* Sometimes certain combinations of command options do not make
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -