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

📄 xtensa.c

📁 linux下的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 "rtl.h"#include "regs.h"#include "machmode.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 "output.h"#include "libfuncs.h"#include "ggc.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  };/* 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;/* Tables of ld/st opcode names for block moves */const char *xtensa_ld_opcodes[(int) MAX_MACHINE_MODE];const char *xtensa_st_opcodes[(int) MAX_MACHINE_MODE];#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 PARAMS ((int));static enum internal_test map_test_to_internal_test PARAMS ((enum rtx_code));static rtx gen_int_relational PARAMS ((enum rtx_code, rtx, rtx, int *));static rtx gen_float_relational PARAMS ((enum rtx_code, rtx, rtx));static rtx gen_conditional_move PARAMS ((rtx));static rtx fixup_subreg_mem PARAMS ((rtx x));static enum machine_mode xtensa_find_mode_for_size PARAMS ((unsigned));static struct machine_function * xtensa_init_machine_status PARAMS ((void));static void printx PARAMS ((FILE *, signed int));static unsigned int xtensa_multibss_section_type_flags  PARAMS ((tree, const char *, int));static void xtensa_select_rtx_section  PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT));static void xtensa_encode_section_info PARAMS ((tree, int));static rtx frame_size_const;static int current_function_arg_words;static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =  REG_ALLOC_ORDER;/* This macro generates the assembly code for function entry.   FILE is a stdio stream to output the code to.   SIZE is an int: how many units of temporary storage to allocate.   Refer to the array 'regs_ever_live' to determine which registers   to save; 'regs_ever_live[I]' is nonzero if register number I   is ever used in the function.  This macro is responsible for   knowing which registers should not be saved even if used.  */#undef TARGET_ASM_FUNCTION_PROLOGUE#define TARGET_ASM_FUNCTION_PROLOGUE xtensa_function_prologue/* 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_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO  xtensa_encode_section_infostruct gcc_target targetm = TARGET_INITIALIZER;/* * Functions to test Xtensa immediate operand validity. */intxtensa_b4constu (v)     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 (v)     int v;{  return (v & 255) == 0 && (v >= -32768 && v <= 32512);}intxtensa_ai4const (v)     int v;{  return (v == -1 || (v >= 1 && v <= 15));}intxtensa_simm7 (v)     int v;{  return v >= -32 && v <= 95;}intxtensa_b4const (v)     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 (v)     int v;{  return v >= -128 && v <= 127;}intxtensa_tp7 (v)     int v;{  return (v >= 7 && v <= 22);}intxtensa_lsi4x4 (v)     int v;{  return (v & 3) == 0 && (v >= 0 && v <= 60);}intxtensa_simm12b (v)     int v;{  return v >= -2048 && v <= 2047;}intxtensa_uimm8 (v)     int v;{  return v >= 0 && v <= 255;}intxtensa_uimm8x2 (v)     int v;{  return (v & 1) == 0 && (v >= 0 && v <= 510);}intxtensa_uimm8x4 (v)     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 (x)     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 (op, mode)    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 (op, mode)    rtx op;    enum machine_mode mode;{    if (GET_CODE (op) == CONST_INT)	return xtensa_simm8 (INTVAL (op));    return register_operand (op, mode);}intnonimmed_operand (op, mode)    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 (op, mode)    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 (mode, operands)     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 (op, mode)     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 (op, mode)     rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return ((GET_CODE (op) == CONST_INT)	  && xtensa_mask_immediate ((1 << INTVAL (op)) - 1));}intsext_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (TARGET_SEXT)    return nonimmed_operand (op, mode);  return mem_operand (op, mode);}intsext_fldsz_operand (op, mode)     rtx op;

⌨️ 快捷键说明

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