📄 frv.c
字号:
/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Red Hat, Inc.This 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 "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"#include "targhooks.h"#include "integrate.h"#include "langhooks.h"#ifndef FRV_INLINE#define FRV_INLINE inline#endif/* The maximum number of distinct NOP patterns. There are three: nop, fnop and mnop. */#define NUM_NOP_PATTERNS 3/* Classification of instructions and units: integer, floating-point/media, branch and control. */enum frv_insn_group { GROUP_I, GROUP_FM, GROUP_B, GROUP_C, NUM_GROUPS };/* The DFA names of the units, in packet order. */static const char *const frv_unit_names[] ={ "c", "i0", "f0", "i1", "f1", "i2", "f2", "i3", "f3", "b0", "b1"};/* The classification of each unit in frv_unit_names[]. */static const enum frv_insn_group frv_unit_groups[ARRAY_SIZE (frv_unit_names)] ={ GROUP_C, GROUP_I, GROUP_FM, GROUP_I, GROUP_FM, GROUP_I, GROUP_FM, GROUP_I, GROUP_FM, GROUP_B, GROUP_B};/* Return the DFA unit code associated with the Nth unit of integer or floating-point group GROUP, */#define NTH_UNIT(GROUP, N) frv_unit_codes[(GROUP) + (N) * 2 + 1]/* Return the number of integer or floating-point unit UNIT (1 for I1, 2 for F2, etc.). */#define UNIT_NUMBER(UNIT) (((UNIT) - 1) / 2)/* The DFA unit number for each unit in frv_unit_names[]. */static int frv_unit_codes[ARRAY_SIZE (frv_unit_names)];/* FRV_TYPE_TO_UNIT[T] is the last unit in frv_unit_names[] that can issue an instruction of type T. The value is ARRAY_SIZE (frv_unit_names) if no instruction of type T has been seen. */static unsigned int frv_type_to_unit[TYPE_UNKNOWN + 1];/* An array of dummy nop INSNs, one for each type of nop that the target supports. */static GTY(()) rtx frv_nops[NUM_NOP_PATTERNS];/* The number of nop instructions in frv_nops[]. */static unsigned int frv_num_nops;/* Return true if instruction INSN should be packed with the following instruction. */#define PACKING_FLAG_P(INSN) (GET_MODE (INSN) == TImode)/* Set the value of PACKING_FLAG_P(INSN). */#define SET_PACKING_FLAG(INSN) PUT_MODE (INSN, TImode)#define CLEAR_PACKING_FLAG(INSN) PUT_MODE (INSN, VOIDmode)/* Loop with REG set to each hard register in rtx X. */#define FOR_EACH_REGNO(REG, X) \ for (REG = REGNO (X); \ REG < REGNO (X) + HARD_REGNO_NREGS (REGNO (X), GET_MODE (X)); \ REG++)/* Information about a relocation unspec. SYMBOL is the relocation symbol (a SYMBOL_REF or LABEL_REF), RELOC is the type of relocation and OFFSET is the constant addend. */struct frv_unspec { rtx symbol; int reloc; HOST_WIDE_INT offset;};/* 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. */#define REGSTATE_CC_MASK 0x07 /* Mask to isolate CCn for cond exec */#define REGSTATE_MODIFIED 0x08 /* reg modified in current VLIW insn */#define REGSTATE_IF_TRUE 0x10 /* reg modified in cond exec true */#define REGSTATE_IF_FALSE 0x20 /* reg modified in cond exec false */#define REGSTATE_IF_EITHER (REGSTATE_IF_TRUE | REGSTATE_IF_FALSE)typedef unsigned char regstate_t;/* 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 inconvenient 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 (void);static int frv_string_begins_with (tree, const char *);static FRV_INLINE bool frv_small_data_reloc_p (rtx, int);static FRV_INLINE bool frv_const_unspec_p (rtx, struct frv_unspec *);static void frv_print_operand_memory_reference_reg (FILE *, rtx);static void frv_print_operand_memory_reference (FILE *, rtx, int);static int frv_print_operand_jump_hint (rtx);static const char *comparison_string (enum rtx_code, rtx);static FRV_INLINE int frv_regno_ok_for_base_p (int, int);static rtx single_set_pattern (rtx);static int frv_function_contains_far_jump (void);static rtx frv_alloc_temp_reg (frv_tmp_reg_t *, enum reg_class, enum machine_mode, int, int);static rtx frv_frame_offset_rtx (int);static rtx frv_frame_mem (enum machine_mode, rtx, int);static rtx frv_dwarf_store (rtx, int);static void frv_frame_insn (rtx, rtx);static void frv_frame_access (frv_frame_accessor_t*, rtx, int);static void frv_frame_access_multi (frv_frame_accessor_t*, frv_stack_t *, int);static void frv_frame_access_standard_regs (enum frv_stack_op, frv_stack_t *);static struct machine_function *frv_init_machine_status (void);static int frv_legitimate_memory_operand (rtx, enum machine_mode, int);static rtx frv_int_to_acc (enum insn_code, int, rtx);static enum machine_mode frv_matching_accg_mode (enum machine_mode);static rtx frv_read_argument (tree *);static rtx frv_read_iacc_argument (enum machine_mode, tree *);static int frv_check_constant_argument (enum insn_code, int, rtx);static rtx frv_legitimize_target (enum insn_code, rtx);static rtx frv_legitimize_argument (enum insn_code, int, rtx);static rtx frv_legitimize_tls_address (rtx, enum tls_model);static rtx frv_expand_set_builtin (enum insn_code, tree, rtx);static rtx frv_expand_unop_builtin (enum insn_code, tree, rtx);static rtx frv_expand_binop_builtin (enum insn_code, tree, rtx);static rtx frv_expand_cut_builtin (enum insn_code, tree, rtx);static rtx frv_expand_binopimm_builtin (enum insn_code, tree, rtx);static rtx frv_expand_voidbinop_builtin (enum insn_code, tree);static rtx frv_expand_int_void2arg (enum insn_code, tree);static rtx frv_expand_prefetches (enum insn_code, tree);static rtx frv_expand_voidtriop_builtin (enum insn_code, tree);static rtx frv_expand_voidaccop_builtin (enum insn_code, tree);static rtx frv_expand_mclracc_builtin (tree);static rtx frv_expand_mrdacc_builtin (enum insn_code, tree);static rtx frv_expand_mwtacc_builtin (enum insn_code, tree);static rtx frv_expand_noargs_builtin (enum insn_code);static void frv_split_iacc_move (rtx, rtx);static rtx frv_emit_comparison (enum rtx_code, rtx, rtx);static int frv_clear_registers_used (rtx *, void *);static void frv_ifcvt_add_insn (rtx, rtx, int);static rtx frv_ifcvt_rewrite_mem (rtx, enum machine_mode, rtx);static rtx frv_ifcvt_load_value (rtx, rtx);static int frv_acc_group_1 (rtx *, void *);static unsigned int frv_insn_unit (rtx);static bool frv_issues_to_branch_unit_p (rtx);static int frv_cond_flags (rtx);static bool frv_regstate_conflict_p (regstate_t, regstate_t);static int frv_registers_conflict_p_1 (rtx *, void *);static bool frv_registers_conflict_p (rtx);static void frv_registers_update_1 (rtx, rtx, void *);static void frv_registers_update (rtx);static void frv_start_packet (void);static void frv_start_packet_block (void);static void frv_finish_packet (void (*) (void));static bool frv_pack_insn_p (rtx);static void frv_add_insn_to_packet (rtx);static void frv_insert_nop_in_packet (rtx);static bool frv_for_each_packet (void (*) (void));static bool frv_sort_insn_group_1 (enum frv_insn_group, unsigned int, unsigned int, unsigned int, unsigned int, state_t);static int frv_compare_insns (const void *, const void *);static void frv_sort_insn_group (enum frv_insn_group);static void frv_reorder_packet (void);static void frv_fill_unused_units (enum frv_insn_group);static void frv_align_label (void);static void frv_reorg_packet (void);static void frv_register_nop (rtx);static void frv_reorg (void);static void frv_pack_insns (void);static void frv_function_prologue (FILE *, HOST_WIDE_INT);static void frv_function_epilogue (FILE *, HOST_WIDE_INT);static bool frv_assemble_integer (rtx, unsigned, int);static void frv_init_builtins (void);static rtx frv_expand_builtin (tree, rtx, rtx, enum machine_mode, int);static void frv_init_libfuncs (void);static bool frv_in_small_data_p (tree);static void frv_asm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);static void frv_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int);static rtx frv_expand_builtin_saveregs (void);static bool frv_rtx_costs (rtx, int, int, int*);static void frv_asm_out_constructor (rtx, int);static void frv_asm_out_destructor (rtx, int);static bool frv_function_symbol_referenced_p (rtx);static bool frv_cannot_force_const_mem (rtx);static const char *unspec_got_name (int);static void frv_output_const_unspec (FILE *, const struct frv_unspec *);static bool frv_function_ok_for_sibcall (tree, tree);static rtx frv_struct_value_rtx (tree, int);static bool frv_must_pass_in_stack (enum machine_mode mode, tree type);static int frv_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, tree, bool);/* Initialize the GCC target structure. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -