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

📄 iq2000.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines used for code generation on Vitesse IQ2000 processors   Copyright (C) 2003, 2004 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, 59 Temple Place - Suite 330,Boston, MA 02111-1307, 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;/* Strings to hold which cpu and instruction set architecture to use.  */const char * iq2000_cpu_string;	  /* For -mcpu=<xxx>.  */const char * iq2000_arch_string;  /* For -march=<xxx>.  *//* 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;/* The target cpu for code generation.  */static enum processor_type iq2000_arch;/* 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 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_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 1 if OP can be used as an operand where a register or 16 bit unsigned   integer is needed.  */intuns_arith_operand (rtx op, enum machine_mode mode){  if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (op))    return 1;  return register_operand (op, mode);}/* Return 1 if OP can be used as an operand where a 16 bit integer is needed.  */intarith_operand (rtx op, enum machine_mode mode){  if (GET_CODE (op) == CONST_INT && SMALL_INT (op))    return 1;  return register_operand (op, mode);}/* Return 1 if OP is a integer which fits in 16 bits.  */intsmall_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  return (GET_CODE (op) == CONST_INT && SMALL_INT (op));}/* Return 1 if OP is a 32 bit integer which is too big to be loaded with one   instruction.  */intlarge_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  HOST_WIDE_INT value;  if (GET_CODE (op) != CONST_INT)    return 0;  value = INTVAL (op);  /* IOR reg,$r0,value.  */  if ((value & ~ ((HOST_WIDE_INT) 0x0000ffff)) == 0)    return 0;  /* SUBU reg,$r0,value.  */  if (((unsigned HOST_WIDE_INT) (value + 32768)) <= 32767)    return 0;  /* LUI reg,value >> 16.  */  if ((value & 0x0000ffff) == 0)    return 0;  return 1;}/* Return 1 if OP is a register or the constant 0.  */intreg_or_0_operand (rtx op, enum machine_mode mode){  switch (GET_CODE (op))    {    case CONST_INT:      return INTVAL (op) == 0;    case CONST_DOUBLE:      return op == CONST0_RTX (mode);    case REG:    case SUBREG:      return register_operand (op, mode);    default:      break;    }  return 0;}/* Return 1 if OP is a memory operand that fits in a single instruction   (i.e., register + small offset).  */intsimple_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  rtx addr, plus0, plus1;  /* Eliminate non-memory operations.  */  if (GET_CODE (op) != MEM)    return 0;  /* Dword operations really put out 2 instructions, so eliminate them.  */  if (GET_MODE_SIZE (GET_MODE (op)) > (unsigned) UNITS_PER_WORD)    return 0;  /* Decode the address now.  */  addr = XEXP (op, 0);  switch (GET_CODE (addr))    {    case REG:    case LO_SUM:      return 1;    case CONST_INT:      return SMALL_INT (addr);    case PLUS:      plus0 = XEXP (addr, 0);      plus1 = XEXP (addr, 1);      if (GET_CODE (plus0) == REG	  && GET_CODE (plus1) == CONST_INT && SMALL_INT (plus1)	  && SMALL_INT_UNSIGNED (plus1) /* No negative offsets.  */)	return 1;      else if (GET_CODE (plus1) == REG	       && GET_CODE (plus0) == CONST_INT && SMALL_INT (plus0)	       && SMALL_INT_UNSIGNED (plus1) /* No negative offsets.  */)	return 1;      else	return 0;    case SYMBOL_REF:      return 0;    default:      break;    }  return 0;}/* Return nonzero if the code of this rtx pattern is EQ or NE.  */intequality_op (rtx op, enum machine_mode mode){  if (mode != GET_MODE (op))    return 0;  return GET_CODE (op) == EQ || GET_CODE (op) == NE;}/* Return nonzero if the code is a relational operations (EQ, LE, etc).  */intcmp_op (rtx op, enum machine_mode mode){  if (mode != GET_MODE (op))    return 0;  return COMPARISON_P (op);}/* Return nonzero if the operand is either the PC or a label_ref.  */intpc_or_label_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  if (op == pc_rtx)    return 1;  if (GET_CODE (op) == LABEL_REF)    return 1;  return 0;}/* Return nonzero if OP is a valid operand for a call instruction.  */intcall_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  return (CONSTANT_ADDRESS_P (op)	  || (GET_CODE (op) == REG && op != arg_pointer_rtx	      && ! (REGNO (op) >= FIRST_PSEUDO_REGISTER		    && REGNO (op) <= LAST_VIRTUAL_REGISTER)));}/* Return nonzero if OP is valid as a source operand for a move instruction.  */intmove_operand (rtx op, enum machine_mode mode){  /* Accept any general operand after reload has started; doing so     avoids losing if reload does an in-place replacement of a register     with a SYMBOL_REF or CONST.  */  return (general_operand (op, mode)	  && (! (iq2000_check_split (op, mode))	      || reload_in_progress || reload_completed));}/* Return nonzero if OP is a constant power of 2.  */intpower_of_2_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  int intval;  if (GET_CODE (op) != CONST_INT)    return 0;  else    intval = INTVAL (op);  return ((intval & ((unsigned)(intval) - 1)) == 0);}/* 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)

⌨️ 快捷键说明

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