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

📄 c4x.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines for assembler code output on the TMS320C[34]x   Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004   Free Software Foundation, Inc.   Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)              and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl).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.  *//* Some output-actions in c4x.md need these.  */#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 "basic-block.h"#include "real.h"#include "insn-config.h"#include "insn-attr.h"#include "conditions.h"#include "output.h"#include "function.h"#include "expr.h"#include "optabs.h"#include "libfuncs.h"#include "flags.h"#include "recog.h"#include "ggc.h"#include "cpplib.h"#include "toplev.h"#include "tm_p.h"#include "target.h"#include "target-def.h"#include "langhooks.h"rtx smulhi3_libfunc;rtx umulhi3_libfunc;rtx fix_truncqfhi2_libfunc;rtx fixuns_truncqfhi2_libfunc;rtx fix_trunchfhi2_libfunc;rtx fixuns_trunchfhi2_libfunc;rtx floathiqf2_libfunc;rtx floatunshiqf2_libfunc;rtx floathihf2_libfunc;rtx floatunshihf2_libfunc;static int c4x_leaf_function;static const char *const float_reg_names[] = FLOAT_REGISTER_NAMES;/* Array of the smallest class containing reg number REGNO, indexed by   REGNO.  Used by REGNO_REG_CLASS in c4x.h.  We assume that all these   registers are available and set the class to NO_REGS for registers    that the target switches say are unavailable.  */enum reg_class c4x_regclass_map[FIRST_PSEUDO_REGISTER] ={                                /* Reg          Modes           Saved.  */  R0R1_REGS,			/* R0           QI, QF, HF      No.  */  R0R1_REGS,			/* R1           QI, QF, HF      No.  */  R2R3_REGS,			/* R2           QI, QF, HF      No.  */  R2R3_REGS,			/* R3           QI, QF, HF      No.  */  EXT_LOW_REGS,			/* R4           QI, QF, HF      QI.  */  EXT_LOW_REGS,			/* R5           QI, QF, HF      QI.  */  EXT_LOW_REGS,			/* R6           QI, QF, HF      QF.  */  EXT_LOW_REGS,			/* R7           QI, QF, HF      QF.  */  ADDR_REGS,			/* AR0          QI              No.  */  ADDR_REGS,			/* AR1          QI              No.  */  ADDR_REGS,			/* AR2          QI              No.  */  ADDR_REGS,			/* AR3          QI              QI.  */  ADDR_REGS,			/* AR4          QI              QI.  */  ADDR_REGS,			/* AR5          QI              QI.  */  ADDR_REGS,			/* AR6          QI              QI.  */  ADDR_REGS,			/* AR7          QI              QI.  */  DP_REG,			/* DP           QI              No.  */  INDEX_REGS,			/* IR0          QI              No.  */  INDEX_REGS,			/* IR1          QI              No.  */  BK_REG,			/* BK           QI              QI.  */  SP_REG,			/* SP           QI              No.  */  ST_REG,			/* ST           CC              No.  */  NO_REGS,			/* DIE/IE                       No.  */  NO_REGS,			/* IIE/IF                       No.  */  NO_REGS,			/* IIF/IOF                      No.  */  INT_REGS,			/* RS           QI              No.  */  INT_REGS,			/* RE           QI              No.  */  RC_REG,			/* RC           QI              No.  */  EXT_REGS,			/* R8           QI, QF, HF      QI.  */  EXT_REGS,			/* R9           QI, QF, HF      No.  */  EXT_REGS,			/* R10          QI, QF, HF      No.  */  EXT_REGS,			/* R11          QI, QF, HF      No.  */};enum machine_mode c4x_caller_save_map[FIRST_PSEUDO_REGISTER] ={                                /* Reg          Modes           Saved.  */  HFmode,			/* R0           QI, QF, HF      No.  */  HFmode,			/* R1           QI, QF, HF      No.  */  HFmode,			/* R2           QI, QF, HF      No.  */  HFmode,			/* R3           QI, QF, HF      No.  */  QFmode,			/* R4           QI, QF, HF      QI.  */  QFmode,			/* R5           QI, QF, HF      QI.  */  QImode,			/* R6           QI, QF, HF      QF.  */  QImode,			/* R7           QI, QF, HF      QF.  */  QImode,			/* AR0          QI              No.  */  QImode,			/* AR1          QI              No.  */  QImode,			/* AR2          QI              No.  */  QImode,			/* AR3          QI              QI.  */  QImode,			/* AR4          QI              QI.  */  QImode,			/* AR5          QI              QI.  */  QImode,			/* AR6          QI              QI.  */  QImode,			/* AR7          QI              QI.  */  VOIDmode,			/* DP           QI              No.  */  QImode,			/* IR0          QI              No.  */  QImode,			/* IR1          QI              No.  */  QImode,			/* BK           QI              QI.  */  VOIDmode,			/* SP           QI              No.  */  VOIDmode,			/* ST           CC              No.  */  VOIDmode,			/* DIE/IE                       No.  */  VOIDmode,			/* IIE/IF                       No.  */  VOIDmode,			/* IIF/IOF                      No.  */  QImode,			/* RS           QI              No.  */  QImode,			/* RE           QI              No.  */  VOIDmode,			/* RC           QI              No.  */  QFmode,			/* R8           QI, QF, HF      QI.  */  HFmode,			/* R9           QI, QF, HF      No.  */  HFmode,			/* R10          QI, QF, HF      No.  */  HFmode,			/* R11          QI, QF, HF      No.  */};/* Test and compare insns in c4x.md store the information needed to   generate branch and scc insns here.  */rtx c4x_compare_op0;rtx c4x_compare_op1;const char *c4x_rpts_cycles_string;int c4x_rpts_cycles = 0;	/* Max. cycles for RPTS.  */const char *c4x_cpu_version_string;int c4x_cpu_version = 40;	/* CPU version C30/31/32/33/40/44.  *//* Pragma definitions.  */tree code_tree = NULL_TREE;tree data_tree = NULL_TREE;tree pure_tree = NULL_TREE;tree noreturn_tree = NULL_TREE;tree interrupt_tree = NULL_TREE;tree naked_tree = NULL_TREE;/* Forward declarations */static int c4x_isr_reg_used_p (unsigned int);static int c4x_leaf_function_p (void);static int c4x_naked_function_p (void);static int c4x_immed_float_p (rtx);static int c4x_a_register (rtx);static int c4x_x_register (rtx);static int c4x_immed_int_constant (rtx);static int c4x_immed_float_constant (rtx);static int c4x_K_constant (rtx);static int c4x_N_constant (rtx);static int c4x_O_constant (rtx);static int c4x_R_indirect (rtx);static int c4x_S_indirect (rtx);static void c4x_S_address_parse (rtx , int *, int *, int *, int *);static int c4x_valid_operands (enum rtx_code, rtx *, enum machine_mode, int);static int c4x_arn_reg_operand (rtx, enum machine_mode, unsigned int);static int c4x_arn_mem_operand (rtx, enum machine_mode, unsigned int);static void c4x_file_start (void);static void c4x_file_end (void);static void c4x_check_attribute (const char *, tree, tree, tree *);static int c4x_r11_set_p (rtx);static int c4x_rptb_valid_p (rtx, rtx);static void c4x_reorg (void);static int c4x_label_ref_used_p (rtx, rtx);static tree c4x_handle_fntype_attribute (tree *, tree, tree, int, bool *);const struct attribute_spec c4x_attribute_table[];static void c4x_insert_attributes (tree, tree *);static void c4x_asm_named_section (const char *, unsigned int, tree);static int c4x_adjust_cost (rtx, rtx, rtx, int);static void c4x_globalize_label (FILE *, const char *);static bool c4x_rtx_costs (rtx, int, int, int *);static int c4x_address_cost (rtx);static void c4x_init_libfuncs (void);static void c4x_external_libcall (rtx);static rtx c4x_struct_value_rtx (tree, int);static tree c4x_gimplify_va_arg_expr (tree, tree, tree *, tree *);/* Initialize the GCC target structure.  */#undef TARGET_ASM_BYTE_OP#define TARGET_ASM_BYTE_OP "\t.word\t"#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP NULL#undef TARGET_ASM_ALIGNED_SI_OP#define TARGET_ASM_ALIGNED_SI_OP NULL#undef TARGET_ASM_FILE_START#define TARGET_ASM_FILE_START c4x_file_start#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true#undef TARGET_ASM_FILE_END#define TARGET_ASM_FILE_END c4x_file_end#undef TARGET_ASM_EXTERNAL_LIBCALL#define TARGET_ASM_EXTERNAL_LIBCALL c4x_external_libcall#undef TARGET_ATTRIBUTE_TABLE#define TARGET_ATTRIBUTE_TABLE c4x_attribute_table#undef TARGET_INSERT_ATTRIBUTES#define TARGET_INSERT_ATTRIBUTES c4x_insert_attributes#undef TARGET_INIT_BUILTINS#define TARGET_INIT_BUILTINS c4x_init_builtins#undef TARGET_EXPAND_BUILTIN#define TARGET_EXPAND_BUILTIN c4x_expand_builtin#undef TARGET_SCHED_ADJUST_COST#define TARGET_SCHED_ADJUST_COST c4x_adjust_cost#undef TARGET_ASM_GLOBALIZE_LABEL#define TARGET_ASM_GLOBALIZE_LABEL c4x_globalize_label#undef TARGET_RTX_COSTS#define TARGET_RTX_COSTS c4x_rtx_costs#undef TARGET_ADDRESS_COST#define TARGET_ADDRESS_COST c4x_address_cost#undef TARGET_MACHINE_DEPENDENT_REORG#define TARGET_MACHINE_DEPENDENT_REORG c4x_reorg#undef TARGET_INIT_LIBFUNCS#define TARGET_INIT_LIBFUNCS c4x_init_libfuncs#undef TARGET_STRUCT_VALUE_RTX#define TARGET_STRUCT_VALUE_RTX c4x_struct_value_rtx#undef TARGET_GIMPLIFY_VA_ARG_EXPR#define TARGET_GIMPLIFY_VA_ARG_EXPR c4x_gimplify_va_arg_exprstruct gcc_target targetm = TARGET_INITIALIZER;/* Override command line options.   Called once after all options have been parsed.   Mostly we process the processor   type and sometimes adjust other TARGET_ options.  */voidc4x_override_options (void){  if (c4x_rpts_cycles_string)    c4x_rpts_cycles = atoi (c4x_rpts_cycles_string);  else    c4x_rpts_cycles = 0;  if (TARGET_C30)    c4x_cpu_version = 30;  else if (TARGET_C31)    c4x_cpu_version = 31;  else if (TARGET_C32)    c4x_cpu_version = 32;  else if (TARGET_C33)    c4x_cpu_version = 33;  else if (TARGET_C40)    c4x_cpu_version = 40;  else if (TARGET_C44)    c4x_cpu_version = 44;  else    c4x_cpu_version = 40;	         /* -mcpu=xx overrides -m40 etc.  */  if (c4x_cpu_version_string)    {      const char *p = c4x_cpu_version_string;            /* Also allow -mcpu=c30 etc.  */      if (*p == 'c' || *p == 'C')	p++;      c4x_cpu_version = atoi (p);    }  target_flags &= ~(C30_FLAG | C31_FLAG | C32_FLAG | C33_FLAG |		    C40_FLAG | C44_FLAG);  switch (c4x_cpu_version)    {    case 30: target_flags |= C30_FLAG; break;    case 31: target_flags |= C31_FLAG; break;    case 32: target_flags |= C32_FLAG; break;    case 33: target_flags |= C33_FLAG; break;    case 40: target_flags |= C40_FLAG; break;    case 44: target_flags |= C44_FLAG; break;    default:      warning ("unknown CPU version %d, using 40.\n", c4x_cpu_version);      c4x_cpu_version = 40;      target_flags |= C40_FLAG;    }  if (TARGET_C30 || TARGET_C31 || TARGET_C32 || TARGET_C33)    target_flags |= C3X_FLAG;  else    target_flags &= ~C3X_FLAG;  /* Convert foo / 8.0 into foo * 0.125, etc.  */  set_fast_math_flags (1);  /* We should phase out the following at some stage.     This provides compatibility with the old -mno-aliases option.  */  if (! TARGET_ALIASES && ! flag_argument_noalias)    flag_argument_noalias = 1;}/* This is called before c4x_override_options.  */voidc4x_optimization_options (int level ATTRIBUTE_UNUSED,			  int size ATTRIBUTE_UNUSED){  /* Scheduling before register allocation can screw up global     register allocation, especially for functions that use MPY||ADD     instructions.  The benefit we gain we get by scheduling before     register allocation is probably marginal anyhow.  */  flag_schedule_insns = 0;}/* Write an ASCII string.  */#define C4X_ASCII_LIMIT 40voidc4x_output_ascii (FILE *stream, const char *ptr, int len){  char sbuf[C4X_ASCII_LIMIT + 1];  int s, l, special, first = 1, onlys;  if (len)      fprintf (stream, "\t.byte\t");  for (s = l = 0; len > 0; --len, ++ptr)    {      onlys = 0;      /* Escape " and \ with a \".  */      special = *ptr == '\"' || *ptr == '\\';      /* If printable - add to buff.  */      if ((! TARGET_TI || ! special) && *ptr >= 0x20 && *ptr < 0x7f)	{	  if (special)	    sbuf[s++] = '\\';	  sbuf[s++] = *ptr;	  if (s < C4X_ASCII_LIMIT - 1)	    continue;	  onlys = 1;	}      if (s)	{	  if (first)	    first = 0;	  else	    {	      fputc (',', stream);	      l++;	    }	  sbuf[s] = 0;	  fprintf (stream, "\"%s\"", sbuf);	  l += s + 2;	  if (TARGET_TI && l >= 80 && len > 1)	    {	      fprintf (stream, "\n\t.byte\t");	      first = 1;	      l = 0;	    }		  s = 0;	}      if (onlys)	continue;      if (first)	first = 0;      else	{	  fputc (',', stream);	  l++;	}      fprintf (stream, "%d", *ptr);      l += 3;      if (TARGET_TI && l >= 80 && len > 1)	{	  fprintf (stream, "\n\t.byte\t");	  first = 1;	  l = 0;	}    }  if (s)    {      if (! first)	fputc (',', stream);      sbuf[s] = 0;      fprintf (stream, "\"%s\"", sbuf);      s = 0;    }  fputc ('\n', stream);}intc4x_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode){  switch (mode)    {#if Pmode != QImode    case Pmode:			/* Pointer (24/32 bits).  */#endif    case QImode:		/* Integer (32 bits).  */      return IS_INT_REGNO (regno);    case QFmode:		/* Float, Double (32 bits).  */    case HFmode:		/* Long Double (40 bits).  */      return IS_EXT_REGNO (regno);    case CCmode:		/* Condition Codes.  */    case CC_NOOVmode:		/* Condition Codes.  */      return IS_ST_REGNO (regno);    case HImode:		/* Long Long (64 bits).  */      /* We need two registers to store long longs.  Note that 	 it is much easier to constrain the first register	 to start on an even boundary.  */      return IS_INT_REGNO (regno)	&& IS_INT_REGNO (regno + 1)	&& (regno & 1) == 0;    default:      return 0;			/* We don't support these modes.  */    }  return 0;}/* Return nonzero if REGNO1 can be renamed to REGNO2.  */intc4x_hard_regno_rename_ok (unsigned int regno1, unsigned int regno2){  /* We cannot copy call saved registers from mode QI into QF or from     mode QF into QI.  */  if (IS_FLOAT_CALL_SAVED_REGNO (regno1) && IS_INT_CALL_SAVED_REGNO (regno2))    return 0;  if (IS_INT_CALL_SAVED_REGNO (regno1) && IS_FLOAT_CALL_SAVED_REGNO (regno2))    return 0;  /* We cannot copy from an extended (40 bit) register to a standard     (32 bit) register because we only set the condition codes for

⌨️ 快捷键说明

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