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

📄 xtensa.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines for insn-output.c for Tensilica's Xtensa architecture.   Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.   Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.This file is part of GCC.GCC is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.GCC is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public Licensealong with GCC; see the file COPYING.  If not, write to the FreeSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA02111-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 "basic-block.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "insn-flags.h"#include "insn-attr.h"#include "insn-codes.h"#include "recog.h"#include "output.h"#include "tree.h"#include "expr.h"#include "flags.h"#include "reload.h"#include "tm_p.h"#include "function.h"#include "toplev.h"#include "optabs.h"#include "libfuncs.h"#include "ggc.h"#include "target.h"#include "target-def.h"#include "langhooks.h"#include "tree-gimple.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};/* Cached operands, and operator to compare for use in set/branch on   condition codes.  */rtx branch_cmp[2];/* what type of branch to use */enum cmp_type branch_type;/* Array giving truth value on whether or not a given hard register   can support a given mode.  */char xtensa_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];/* Current frame size calculated by compute_frame_size.  */unsigned xtensa_current_frame_size;/* Largest block move to handle in-line.  */#define LARGEST_MOVE_RATIO 15/* Define the structure for the machine field in struct function.  */struct machine_function GTY(()){  int accesses_prev_frame;  bool need_a7_copy;  bool vararg_a7;  rtx set_frame_ptr_insn;};/* Vector, indexed by hard register number, which contains 1 for a   register that is allowable in a candidate for leaf function   treatment.  */const char xtensa_leaf_regs[FIRST_PSEUDO_REGISTER] ={  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  1};/* Map hard register number to register class */const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER] ={  RL_REGS,	SP_REG,		RL_REGS,	RL_REGS,  RL_REGS,	RL_REGS,	RL_REGS,	GR_REGS,  RL_REGS,	RL_REGS,	RL_REGS,	RL_REGS,  RL_REGS,	RL_REGS,	RL_REGS,	RL_REGS,  AR_REGS,	AR_REGS,	BR_REGS,  FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,  FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,  FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,  FP_REGS,	FP_REGS,	FP_REGS,	FP_REGS,  ACC_REG,};/* Map register constraint character to register class.  */enum reg_class xtensa_char_to_class[256] ={  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,  NO_REGS,	NO_REGS,	NO_REGS,	NO_REGS,};static int b4const_or_zero (int);static enum internal_test map_test_to_internal_test (enum rtx_code);static rtx gen_int_relational (enum rtx_code, rtx, rtx, int *);static rtx gen_float_relational (enum rtx_code, rtx, rtx);static rtx gen_conditional_move (rtx);static rtx fixup_subreg_mem (rtx);static struct machine_function * xtensa_init_machine_status (void);static bool xtensa_return_in_msb (tree);static void printx (FILE *, signed int);static void xtensa_function_epilogue (FILE *, HOST_WIDE_INT);static rtx xtensa_builtin_saveregs (void);static unsigned int xtensa_multibss_section_type_flags (tree, const char *,							int) ATTRIBUTE_UNUSED;static void xtensa_select_rtx_section (enum machine_mode, rtx,				       unsigned HOST_WIDE_INT);static bool xtensa_rtx_costs (rtx, int, int, int *);static tree xtensa_build_builtin_va_list (void);static bool xtensa_return_in_memory (tree, tree);static tree xtensa_gimplify_va_arg_expr (tree, tree, tree *, tree *);static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =  REG_ALLOC_ORDER;/* This macro generates the assembly code for function exit,   on machines that need it.  If FUNCTION_EPILOGUE is not defined   then individual return instructions are generated for each   return statement.  Args are same as for FUNCTION_PROLOGUE.  */#undef TARGET_ASM_FUNCTION_EPILOGUE#define TARGET_ASM_FUNCTION_EPILOGUE xtensa_function_epilogue/* These hooks specify assembly directives for creating certain kinds   of integer object.  */#undef TARGET_ASM_ALIGNED_SI_OP#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"#undef TARGET_ASM_SELECT_RTX_SECTION#define TARGET_ASM_SELECT_RTX_SECTION  xtensa_select_rtx_section#undef TARGET_RTX_COSTS#define TARGET_RTX_COSTS xtensa_rtx_costs#undef TARGET_ADDRESS_COST#define TARGET_ADDRESS_COST hook_int_rtx_0#undef TARGET_BUILD_BUILTIN_VA_LIST#define TARGET_BUILD_BUILTIN_VA_LIST xtensa_build_builtin_va_list#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 xtensa_return_in_memory#undef TARGET_SPLIT_COMPLEX_ARG#define TARGET_SPLIT_COMPLEX_ARG hook_bool_tree_true#undef TARGET_MUST_PASS_IN_STACK#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size#undef TARGET_EXPAND_BUILTIN_SAVEREGS#define TARGET_EXPAND_BUILTIN_SAVEREGS xtensa_builtin_saveregs#undef TARGET_GIMPLIFY_VA_ARG_EXPR#define TARGET_GIMPLIFY_VA_ARG_EXPR xtensa_gimplify_va_arg_expr#undef TARGET_RETURN_IN_MSB#define TARGET_RETURN_IN_MSB xtensa_return_in_msbstruct gcc_target targetm = TARGET_INITIALIZER;/* * Functions to test Xtensa immediate operand validity. */intxtensa_b4constu (int v){  switch (v)    {    case 32768:    case 65536:    case 2:    case 3:    case 4:    case 5:    case 6:    case 7:    case 8:    case 10:    case 12:    case 16:    case 32:    case 64:    case 128:    case 256:      return 1;    }  return 0;}intxtensa_simm8x256 (int v){  return (v & 255) == 0 && (v >= -32768 && v <= 32512);}intxtensa_ai4const (int v){  return (v == -1 || (v >= 1 && v <= 15));}intxtensa_simm7 (int v){  return v >= -32 && v <= 95;}intxtensa_b4const (int v){  switch (v)    {    case -1:    case 1:    case 2:    case 3:    case 4:    case 5:    case 6:    case 7:    case 8:    case 10:    case 12:    case 16:    case 32:    case 64:    case 128:    case 256:      return 1;    }  return 0;}intxtensa_simm8 (int v){  return v >= -128 && v <= 127;}intxtensa_tp7 (int v){  return (v >= 7 && v <= 22);}intxtensa_lsi4x4 (int v){  return (v & 3) == 0 && (v >= 0 && v <= 60);}intxtensa_simm12b (int v){  return v >= -2048 && v <= 2047;}intxtensa_uimm8 (int v){  return v >= 0 && v <= 255;}intxtensa_uimm8x2 (int v){  return (v & 1) == 0 && (v >= 0 && v <= 510);}intxtensa_uimm8x4 (int v){  return (v & 3) == 0 && (v >= 0 && v <= 1020);}/* This is just like the standard true_regnum() function except that it   works even when reg_renumber is not initialized.  */intxt_true_regnum (rtx x){  if (GET_CODE (x) == REG)    {      if (reg_renumber	  && REGNO (x) >= FIRST_PSEUDO_REGISTER	  && reg_renumber[REGNO (x)] >= 0)	return reg_renumber[REGNO (x)];      return REGNO (x);    }  if (GET_CODE (x) == SUBREG)    {      int base = xt_true_regnum (SUBREG_REG (x));      if (base >= 0 && base < FIRST_PSEUDO_REGISTER)        return base + subreg_regno_offset (REGNO (SUBREG_REG (x)),                                           GET_MODE (SUBREG_REG (x)),                                           SUBREG_BYTE (x), GET_MODE (x));    }  return -1;}intadd_operand (rtx op, enum machine_mode mode){  if (GET_CODE (op) == CONST_INT)    return (xtensa_simm8 (INTVAL (op)) || xtensa_simm8x256 (INTVAL (op)));  return register_operand (op, mode);}intarith_operand (rtx op, enum machine_mode mode){  if (GET_CODE (op) == CONST_INT)    return xtensa_simm8 (INTVAL (op));  return register_operand (op, mode);}intnonimmed_operand (rtx op, enum machine_mode mode){  /* We cannot use the standard nonimmediate_operand() predicate because     it includes constant pool memory operands.  */  if (memory_operand (op, mode))    return !constantpool_address_p (XEXP (op, 0));  return register_operand (op, mode);}intmem_operand (rtx op, enum machine_mode mode){  /* We cannot use the standard memory_operand() predicate because     it includes constant pool memory operands.  */  if (memory_operand (op, mode))    return !constantpool_address_p (XEXP (op, 0));  return FALSE;}intxtensa_valid_move (enum machine_mode mode, rtx *operands){  /* Either the destination or source must be a register, and the     MAC16 accumulator doesn't count.  */  if (register_operand (operands[0], mode))    {      int dst_regnum = xt_true_regnum (operands[0]);      /* The stack pointer can only be assigned with a MOVSP opcode.  */      if (dst_regnum == STACK_POINTER_REGNUM)	return (mode == SImode		&& register_operand (operands[1], mode)		&& !ACC_REG_P (xt_true_regnum (operands[1])));      if (!ACC_REG_P (dst_regnum))	return true;    }  if (register_operand (operands[1], mode))    {      int src_regnum = xt_true_regnum (operands[1]);      if (!ACC_REG_P (src_regnum))	return true;    }  return FALSE;}intmask_operand (rtx op, enum machine_mode mode){  if (GET_CODE (op) == CONST_INT)    return xtensa_mask_immediate (INTVAL (op));  return register_operand (op, mode);}intextui_fldsz_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  return ((GET_CODE (op) == CONST_INT)	  && xtensa_mask_immediate ((1 << INTVAL (op)) - 1));}intsext_operand (rtx op, enum machine_mode mode){  if (TARGET_SEXT)

⌨️ 快捷键说明

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