⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iq2000.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines used for code generation on Vitesse IQ2000 processors   Copyright (C) 2003, 2004, 2005 Free Software Foundation, 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, 51 Franklin Street, Fifth Floor,Boston, MA 02110-1301, USA.  */#include "config.h"#include "system.h"#include "coretypes.h"#include <signal.h>#include "tm.h"#include "tree.h"#include "rtl.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 "function.h"#include "expr.h"#include "optabs.h"#include "libfuncs.h"#include "recog.h"#include "toplev.h"#include "reload.h"#include "ggc.h"#include "tm_p.h"#include "debug.h"#include "target.h"#include "target-def.h"#include "langhooks.h"/* Enumeration for all of the relational tests, so that we can build   arrays indexed by the test type, and not worry about the order   of EQ, NE, etc.  */enum internal_test  {    ITEST_EQ,    ITEST_NE,    ITEST_GT,    ITEST_GE,    ITEST_LT,    ITEST_LE,    ITEST_GTU,    ITEST_GEU,    ITEST_LTU,    ITEST_LEU,    ITEST_MAX  };struct constant;/* Structure to be filled in by compute_frame_size with register   save masks, and offsets for the current function.  */struct iq2000_frame_info{  long total_size;		/* # bytes that the entire frame takes up.  */  long var_size;		/* # bytes that variables take up.  */  long args_size;		/* # bytes that outgoing arguments take up.  */  long extra_size;		/* # bytes of extra gunk.  */  int  gp_reg_size;		/* # bytes needed to store gp regs.  */  int  fp_reg_size;		/* # bytes needed to store fp regs.  */  long mask;			/* Mask of saved gp registers.  */  long gp_save_offset;		/* Offset from vfp to store gp registers.  */  long fp_save_offset;		/* Offset from vfp to store fp registers.  */  long gp_sp_offset;		/* Offset from new sp to store gp registers.  */  long fp_sp_offset;		/* Offset from new sp to store fp registers.  */  int  initialized;		/* != 0 if frame size already calculated.  */  int  num_gp;			/* Number of gp registers saved.  */} iq2000_frame_info;struct machine_function GTY(()){  /* Current frame information, calculated by compute_frame_size.  */  long total_size;		/* # bytes that the entire frame takes up.  */  long var_size;		/* # bytes that variables take up.  */  long args_size;		/* # bytes that outgoing arguments take up.  */  long extra_size;		/* # bytes of extra gunk.  */  int  gp_reg_size;		/* # bytes needed to store gp regs.  */  int  fp_reg_size;		/* # bytes needed to store fp regs.  */  long mask;			/* Mask of saved gp registers.  */  long gp_save_offset;		/* Offset from vfp to store gp registers.  */  long fp_save_offset;		/* Offset from vfp to store fp registers.  */  long gp_sp_offset;		/* Offset from new sp to store gp registers.  */  long fp_sp_offset;		/* Offset from new sp to store fp registers.  */  int  initialized;		/* != 0 if frame size already calculated.  */  int  num_gp;			/* Number of gp registers saved.  */};/* Global variables for machine-dependent things.  *//* List of all IQ2000 punctuation characters used by print_operand.  */char iq2000_print_operand_punct[256];/* The target cpu for optimization and scheduling.  */enum processor_type iq2000_tune;/* Which instruction set architecture to use.  */int iq2000_isa;/* Cached operands, and operator to compare for use in set/branch/trap   on condition codes.  */rtx branch_cmp[2];/* What type of branch to use.  */enum cmp_type branch_type;/* Local variables.  *//* The next branch instruction is a branch likely, not branch normal.  */static int iq2000_branch_likely;/* Count of delay slots and how many are filled.  */static int dslots_load_total;static int dslots_load_filled;static int dslots_jump_total;/* # of nops needed by previous insn.  */static int dslots_number_nops;/* Number of 1/2/3 word references to data items (i.e., not jal's).  */static int num_refs[3];/* Registers to check for load delay.  */static rtx iq2000_load_reg;static rtx iq2000_load_reg2;static rtx iq2000_load_reg3;static rtx iq2000_load_reg4;/* Mode used for saving/restoring general purpose registers.  */static enum machine_mode gpr_mode;/* Initialize the GCC target structure.  */static struct machine_function* iq2000_init_machine_status (void);static bool iq2000_handle_option      (size_t, const char *, int);static void iq2000_select_rtx_section (enum machine_mode, rtx, unsigned HOST_WIDE_INT);static void iq2000_init_builtins      (void);static rtx  iq2000_expand_builtin     (tree, rtx, rtx, enum machine_mode, int);static bool iq2000_return_in_memory   (tree, tree);static void iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *,					   enum machine_mode, tree, int *,					   int);static bool iq2000_rtx_costs          (rtx, int, int, int *);static int  iq2000_address_cost       (rtx);static void iq2000_select_section     (tree, int, unsigned HOST_WIDE_INT);static bool iq2000_return_in_memory   (tree, tree);static bool iq2000_pass_by_reference  (CUMULATIVE_ARGS *, enum machine_mode,				       tree, bool);static int  iq2000_arg_partial_bytes  (CUMULATIVE_ARGS *, enum machine_mode,				       tree, bool);#undef  TARGET_INIT_BUILTINS#define TARGET_INIT_BUILTINS 		iq2000_init_builtins#undef  TARGET_EXPAND_BUILTIN#define TARGET_EXPAND_BUILTIN 		iq2000_expand_builtin#undef  TARGET_ASM_SELECT_RTX_SECTION#define TARGET_ASM_SELECT_RTX_SECTION	iq2000_select_rtx_section#undef  TARGET_HANDLE_OPTION#define TARGET_HANDLE_OPTION		iq2000_handle_option#undef  TARGET_RTX_COSTS#define TARGET_RTX_COSTS		iq2000_rtx_costs#undef  TARGET_ADDRESS_COST#define TARGET_ADDRESS_COST		iq2000_address_cost#undef  TARGET_ASM_SELECT_SECTION#define TARGET_ASM_SELECT_SECTION	iq2000_select_section#undef  TARGET_PROMOTE_FUNCTION_ARGS#define TARGET_PROMOTE_FUNCTION_ARGS	hook_bool_tree_true#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_RETURN_IN_MEMORY#define TARGET_RETURN_IN_MEMORY		iq2000_return_in_memory#undef  TARGET_PASS_BY_REFERENCE#define TARGET_PASS_BY_REFERENCE	iq2000_pass_by_reference#undef  TARGET_CALLEE_COPIES#define TARGET_CALLEE_COPIES		hook_callee_copies_named#undef  TARGET_ARG_PARTIAL_BYTES#define TARGET_ARG_PARTIAL_BYTES	iq2000_arg_partial_bytes#undef  TARGET_SETUP_INCOMING_VARARGS#define TARGET_SETUP_INCOMING_VARARGS	iq2000_setup_incoming_varargs#undef  TARGET_STRICT_ARGUMENT_NAMING#define TARGET_STRICT_ARGUMENT_NAMING	hook_bool_CUMULATIVE_ARGS_truestruct gcc_target targetm = TARGET_INITIALIZER;/* Return nonzero if we split the address into high and low parts.  */intiq2000_check_split (rtx address, enum machine_mode mode){  /* This is the same check used in simple_memory_operand.     We use it here because LO_SUM is not offsettable.  */  if (GET_MODE_SIZE (mode) > (unsigned) UNITS_PER_WORD)    return 0;  if ((GET_CODE (address) == SYMBOL_REF)      || (GET_CODE (address) == CONST	  && GET_CODE (XEXP (XEXP (address, 0), 0)) == SYMBOL_REF)      || GET_CODE (address) == LABEL_REF)    return 1;  return 0;}/* Return nonzero if REG is valid for MODE.  */intiq2000_reg_mode_ok_for_base_p (rtx reg,			       enum machine_mode mode ATTRIBUTE_UNUSED,			       int strict){  return (strict	  ? REGNO_MODE_OK_FOR_BASE_P (REGNO (reg), mode)	  : GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (reg), mode));}/* Return a nonzero value if XINSN is a legitimate address for a   memory operand of the indicated MODE.  STRICT is nonzero if this   function is called during reload.  */intiq2000_legitimate_address_p (enum machine_mode mode, rtx xinsn, int strict){  if (TARGET_DEBUG_A_MODE)    {      GO_PRINTF2 ("\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n",		  strict ? "" : "not ");      GO_DEBUG_RTX (xinsn);    }  /* Check for constant before stripping off SUBREG, so that we don't     accept (subreg (const_int)) which will fail to reload.  */  if (CONSTANT_ADDRESS_P (xinsn)      && ! (iq2000_check_split (xinsn, mode))      && ! (GET_CODE (xinsn) == CONST_INT && ! SMALL_INT (xinsn)))    return 1;  while (GET_CODE (xinsn) == SUBREG)    xinsn = SUBREG_REG (xinsn);  if (GET_CODE (xinsn) == REG      && iq2000_reg_mode_ok_for_base_p (xinsn, mode, strict))    return 1;  if (GET_CODE (xinsn) == LO_SUM)    {      rtx xlow0 = XEXP (xinsn, 0);      rtx xlow1 = XEXP (xinsn, 1);      while (GET_CODE (xlow0) == SUBREG)	xlow0 = SUBREG_REG (xlow0);      if (GET_CODE (xlow0) == REG	  && iq2000_reg_mode_ok_for_base_p (xlow0, mode, strict)	  && iq2000_check_split (xlow1, mode))	return 1;    }  if (GET_CODE (xinsn) == PLUS)    {      rtx xplus0 = XEXP (xinsn, 0);      rtx xplus1 = XEXP (xinsn, 1);      enum rtx_code code0;      enum rtx_code code1;      while (GET_CODE (xplus0) == SUBREG)	xplus0 = SUBREG_REG (xplus0);      code0 = GET_CODE (xplus0);      while (GET_CODE (xplus1) == SUBREG)	xplus1 = SUBREG_REG (xplus1);      code1 = GET_CODE (xplus1);      if (code0 == REG	  && iq2000_reg_mode_ok_for_base_p (xplus0, mode, strict))	{	  if (code1 == CONST_INT && SMALL_INT (xplus1)	      && SMALL_INT_UNSIGNED (xplus1) /* No negative offsets */)	    return 1;	}    }  if (TARGET_DEBUG_A_MODE)    GO_PRINTF ("Not a legitimate address\n");  /* The address was not legitimate.  */  return 0;}/* Returns an operand string for the given instruction's delay slot,   after updating filled delay slot statistics.   We assume that operands[0] is the target register that is set.   In order to check the next insn, most of this functionality is moved   to FINAL_PRESCAN_INSN, and we just set the global variables that   it needs.  */const char *iq2000_fill_delay_slot (const char *ret, enum delay_type type, rtx operands[],			rtx cur_insn){  rtx set_reg;  enum machine_mode mode;  rtx next_insn = cur_insn ? NEXT_INSN (cur_insn) : NULL_RTX;  int num_nops;  if (type == DELAY_LOAD || type == DELAY_FCMP)    num_nops = 1;  else    num_nops = 0;  /* Make sure that we don't put nop's after labels.  */  next_insn = NEXT_INSN (cur_insn);  while (next_insn != 0	 && (GET_CODE (next_insn) == NOTE	     || GET_CODE (next_insn) == CODE_LABEL))    next_insn = NEXT_INSN (next_insn);  dslots_load_total += num_nops;  if (TARGET_DEBUG_C_MODE      || type == DELAY_NONE      || operands == 0      || cur_insn == 0      || next_insn == 0      || GET_CODE (next_insn) == CODE_LABEL      || (set_reg = operands[0]) == 0)    {      dslots_number_nops = 0;      iq2000_load_reg  = 0;      iq2000_load_reg2 = 0;      iq2000_load_reg3 = 0;      iq2000_load_reg4 = 0;      return ret;    }  set_reg = operands[0];  if (set_reg == 0)    return ret;  while (GET_CODE (set_reg) == SUBREG)    set_reg = SUBREG_REG (set_reg);  mode = GET_MODE (set_reg);  dslots_number_nops = num_nops;  iq2000_load_reg = set_reg;  if (GET_MODE_SIZE (mode)      > (unsigned) (UNITS_PER_WORD))    iq2000_load_reg2 = gen_rtx_REG (SImode, REGNO (set_reg) + 1);  else    iq2000_load_reg2 = 0;  return ret;}/* Determine whether a memory reference takes one (based off of the GP   pointer), two (normal), or three (label + reg) instructions, and bump the   appropriate counter for -mstats.  */static voidiq2000_count_memory_refs (rtx op, int num){  int additional = 0;  int n_words = 0;  rtx addr, plus0, plus1;  enum rtx_code code0, code1;  int looping;  if (TARGET_DEBUG_B_MODE)    {      fprintf (stderr, "\n========== iq2000_count_memory_refs:\n");      debug_rtx (op);    }  /* Skip MEM if passed, otherwise handle movsi of address.  */  addr = (GET_CODE (op) != MEM) ? op : XEXP (op, 0);  /* Loop, going through the address RTL.  */  do    {      looping = FALSE;      switch (GET_CODE (addr))	{	case REG:	case CONST_INT:	case LO_SUM:	  break;	case PLUS:	  plus0 = XEXP (addr, 0);	  plus1 = XEXP (addr, 1);	  code0 = GET_CODE (plus0);	  code1 = GET_CODE (plus1);	  if (code0 == REG)	    {	      additional++;	      addr = plus1;	      looping = 1;	      continue;	    }	  if (code0 == CONST_INT)	    {	      addr = plus1;	      looping = 1;	      continue;	    }	  if (code1 == REG)	    {	      additional++;	      addr = plus0;	      looping = 1;	      continue;	    }	  if (code1 == CONST_INT)	    {	      addr = plus0;	      looping = 1;	      continue;	    }	  if (code0 == SYMBOL_REF || code0 == LABEL_REF || code0 == CONST)	    {	      addr = plus0;	      looping = 1;	      continue;	    }	  if (code1 == SYMBOL_REF || code1 == LABEL_REF || code1 == CONST)	    {	      addr = plus1;	      looping = 1;	      continue;	    }	  break;	case LABEL_REF:	  n_words = 2;		/* Always 2 words.  */	  break;	case CONST:	  addr = XEXP (addr, 0);	  looping = 1;	  continue;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -