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

📄 c4x.c

📁 gcc-you can use this code to learn something about gcc, and inquire further into linux,
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Subroutines for assembler code output on the TMS320C[34]x   Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001   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 GNU CC.GNU CC 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.GNU CC 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 GNU CC; 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 "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 "loop.h"#include "recog.h"#include "c-tree.h"#include "ggc.h"#include "cpplib.h"#include "toplev.h"#include "tm_p.h"#include "target.h"#include "target-def.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;/* Forward declarations */static int c4x_isr_reg_used_p PARAMS ((unsigned int));static int c4x_leaf_function_p PARAMS ((void));static int c4x_assembler_function_p PARAMS ((void));static int c4x_immed_float_p PARAMS ((rtx));static int c4x_a_register PARAMS ((rtx));static int c4x_x_register PARAMS ((rtx));static int c4x_immed_int_constant PARAMS ((rtx));static int c4x_immed_float_constant PARAMS ((rtx));static int c4x_K_constant PARAMS ((rtx));static int c4x_N_constant PARAMS ((rtx));static int c4x_O_constant PARAMS ((rtx));static int c4x_R_indirect PARAMS ((rtx));static int c4x_S_indirect PARAMS ((rtx));static void c4x_S_address_parse PARAMS ((rtx , int *, int *, int *, int *));static int c4x_valid_operands PARAMS ((enum rtx_code, rtx *,				       enum machine_mode, int));static int c4x_arn_reg_operand PARAMS ((rtx, enum machine_mode, unsigned int));static int c4x_arn_mem_operand PARAMS ((rtx, enum machine_mode, unsigned int));static void c4x_check_attribute PARAMS ((const char *, tree, tree, tree *));static int c4x_r11_set_p PARAMS ((rtx));static int c4x_rptb_valid_p PARAMS ((rtx, rtx));static int c4x_label_ref_used_p PARAMS ((rtx, rtx));static tree c4x_handle_fntype_attribute PARAMS ((tree *, tree, tree, int, bool *));const struct attribute_spec c4x_attribute_table[];static void c4x_insert_attributes PARAMS ((tree, tree *));static void c4x_asm_named_section PARAMS ((const char *, unsigned int));static int c4x_adjust_cost PARAMS ((rtx, rtx, rtx, int));static void c4x_encode_section_info PARAMS ((tree, int));static void c4x_globalize_label PARAMS ((FILE *, const char *));/* 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_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_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO c4x_encode_section_info#undef TARGET_ASM_GLOBALIZE_LABEL#define TARGET_ASM_GLOBALIZE_LABEL c4x_globalize_labelstruct 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 (){  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;  /* We're C4X floating point, not IEEE floating point.  */  memset (real_format_for_mode, 0, sizeof real_format_for_mode);  real_format_for_mode[QFmode - QFmode] = &c4x_single_format;  real_format_for_mode[HFmode - QFmode] = &c4x_extended_format;}/* This is called before c4x_override_options.  */voidc4x_optimization_options (level, size)     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 (stream, ptr, len)     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 (regno, mode)     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 (regno1, regno2)     unsigned int regno1;     unsigned int regno2;{  /* We can not 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     extended registers.  */  if (IS_EXT_REGNO (regno1) && ! IS_EXT_REGNO (regno2))    return 0;  if (IS_EXT_REGNO (regno2) && ! IS_EXT_REGNO (regno1))    return 0;  return 1;}/* The TI C3x C compiler register argument runtime model uses 6 registers,   AR2, R2, R3, RC, RS, RE.   The first two floating point arguments (float, double, long double)   that are found scanning from left to right are assigned to R2 and R3.   The remaining integer (char, short, int, long) or pointer arguments   are assigned to the remaining registers in the order AR2, R2, R3,   RC, RS, RE when scanning left to right, except for the last named   argument prior to an ellipsis denoting variable number of   arguments.  We don't have to worry about the latter condition since   function.c treats the last named argument as anonymous (unnamed).   All arguments that cannot be passed in registers are pushed onto

⌨️ 快捷键说明

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