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

📄 sh.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Output routines for GCC for Hitachi / SuperH SH.   Copyright (C) 1993, 1994, 1995, 1997, 1997, 1998, 1999, 2000, 2001, 2002,   2004 Free Software Foundation, Inc.   Contributed by Steve Chamberlain (sac@cygnus.com).   Improved by Jim Wilson (wilson@cygnus.com). 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.  */#include "config.h"#include "system.h"#include "insn-config.h"#include "rtl.h"#include "tree.h"#include "flags.h"#include "expr.h"#include "optabs.h"#include "function.h"#include "regs.h"#include "hard-reg-set.h"#include "output.h"#include "insn-attr.h"#include "toplev.h"#include "recog.h"#include "c-pragma.h"#include "integrate.h"#include "tm_p.h"#include "target.h"#include "target-def.h"#include "real.h"#include "langhooks.h"int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;#define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0)#define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1)/* These are some macros to abstract register modes.  */#define CONST_OK_FOR_ADD(size) \  (TARGET_SHMEDIA ? CONST_OK_FOR_P (size) : CONST_OK_FOR_I (size))#define GEN_MOV (*(TARGET_SHMEDIA64 ? gen_movdi : gen_movsi))#define GEN_ADD3 (*(TARGET_SHMEDIA64 ? gen_adddi3 : gen_addsi3))#define GEN_SUB3 (*(TARGET_SHMEDIA64 ? gen_subdi3 : gen_subsi3))/* Set to 1 by expand_prologue() when the function is an interrupt handler.  */int current_function_interrupt;/* ??? The pragma interrupt support will not work for SH3.  *//* This is set by #pragma interrupt and #pragma trapa, and causes gcc to   output code for the next function appropriate for an interrupt handler.  */int pragma_interrupt;/* This is set by the trap_exit attribute for functions.   It specifies   a trap number to be used in a trapa instruction at function exit   (instead of an rte instruction).  */int trap_exit;/* This is used by the sp_switch attribute for functions.  It specifies   a variable holding the address of the stack the interrupt function   should switch to/from at entry/exit.  */rtx sp_switch;/* This is set by #pragma trapa, and is similar to the above, except that   the compiler doesn't emit code to preserve all registers.  */static int pragma_trapa;/* This is set by #pragma nosave_low_regs.  This is useful on the SH3,   which has a separate set of low regs for User and Supervisor modes.   This should only be used for the lowest level of interrupts.  Higher levels   of interrupts must save the registers in case they themselves are   interrupted.  */int pragma_nosave_low_regs;/* This is used for communication between SETUP_INCOMING_VARARGS and   sh_expand_prologue.  */int current_function_anonymous_args;/* Global variables for machine-dependent things.  *//* Which cpu are we scheduling for.  */enum processor_type sh_cpu;/* Saved operands from the last compare to use when we generate an scc   or bcc insn.  */rtx sh_compare_op0;rtx sh_compare_op1;/* Provides the class number of the smallest class containing   reg number.  */int regno_reg_class[FIRST_PSEUDO_REGISTER] ={  R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,  FP0_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, 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, 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, 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,  TARGET_REGS, TARGET_REGS, TARGET_REGS, TARGET_REGS,  TARGET_REGS, TARGET_REGS, TARGET_REGS, TARGET_REGS,  DF_REGS, DF_REGS, DF_REGS, DF_REGS,  DF_REGS, DF_REGS, DF_REGS, DF_REGS,  NO_REGS, GENERAL_REGS, PR_REGS, T_REGS,  MAC_REGS, MAC_REGS, FPUL_REGS, FPSCR_REGS,  GENERAL_REGS,};char sh_register_names[FIRST_PSEUDO_REGISTER] \  [MAX_REGISTER_NAME_LENGTH + 1] = SH_REGISTER_NAMES_INITIALIZER;char sh_additional_register_names[ADDREGNAMES_SIZE] \  [MAX_ADDITIONAL_REGISTER_NAME_LENGTH + 1]  = SH_ADDITIONAL_REGISTER_NAMES_INITIALIZER;/* Provide reg_class from a letter such as appears in the machine   description.  *: target independently reserved letter.   reg_class_from_letter['e'] is set to NO_REGS for TARGET_FMOVD.  */enum reg_class reg_class_from_letter[] ={  /* a */ ALL_REGS,  /* b */ TARGET_REGS, /* c */ FPSCR_REGS, /* d */ DF_REGS,  /* e */ FP_REGS,   /* f */ FP_REGS,  /* g **/ NO_REGS,     /* h */ NO_REGS,  /* i **/ NO_REGS,  /* j */ NO_REGS,  /* k */ SIBCALL_REGS, /* l */ PR_REGS,  /* m **/ NO_REGS,  /* n **/ NO_REGS, /* o **/ NO_REGS,     /* p **/ NO_REGS,  /* q */ NO_REGS,   /* r **/ NO_REGS, /* s **/ NO_REGS,     /* t */ T_REGS,  /* u */ NO_REGS,   /* v */ NO_REGS,  /* w */ FP0_REGS,     /* x */ MAC_REGS,  /* y */ FPUL_REGS, /* z */ R0_REGS};int assembler_dialect;static void split_branches PARAMS ((rtx));static int branch_dest PARAMS ((rtx));static void force_into PARAMS ((rtx, rtx));static void print_slot PARAMS ((rtx));static rtx add_constant PARAMS ((rtx, enum machine_mode, rtx));static void dump_table PARAMS ((rtx));static int hi_const PARAMS ((rtx));static int broken_move PARAMS ((rtx));static int mova_p PARAMS ((rtx));static rtx find_barrier PARAMS ((int, rtx, rtx));static int noncall_uses_reg PARAMS ((rtx, rtx, rtx *));static rtx gen_block_redirect PARAMS ((rtx, int, int));static void output_stack_adjust PARAMS ((int, rtx, int, rtx (*) (rtx)));static rtx frame_insn PARAMS ((rtx));static rtx push PARAMS ((int));static void pop PARAMS ((int));static void push_regs PARAMS ((HOST_WIDE_INT *));static void calc_live_regs PARAMS ((int *, HOST_WIDE_INT *));static void mark_use PARAMS ((rtx, rtx *));static HOST_WIDE_INT rounded_frame_size PARAMS ((int));static rtx mark_constant_pool_use PARAMS ((rtx));const struct attribute_spec sh_attribute_table[];static tree sh_handle_interrupt_handler_attribute PARAMS ((tree *, tree, tree, int, bool *));static tree sh_handle_sp_switch_attribute PARAMS ((tree *, tree, tree, int, bool *));static tree sh_handle_trap_exit_attribute PARAMS ((tree *, tree, tree, int, bool *));static void sh_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));static void sh_insert_attributes PARAMS ((tree, tree *));static int sh_adjust_cost PARAMS ((rtx, rtx, rtx, int));static int sh_use_dfa_interface PARAMS ((void));static int sh_issue_rate PARAMS ((void));static bool sh_cannot_modify_jumps_p PARAMS ((void));static bool sh_ms_bitfield_layout_p PARAMS ((tree));static void sh_encode_section_info PARAMS ((tree, int));static const char *sh_strip_name_encoding PARAMS ((const char *));static void sh_init_builtins PARAMS ((void));static void sh_media_init_builtins PARAMS ((void));static rtx sh_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));static int flow_dependent_p PARAMS ((rtx, rtx));static void flow_dependent_p_1 PARAMS ((rtx, rtx, void *));/* Initialize the GCC target structure.  */#undef TARGET_ATTRIBUTE_TABLE#define TARGET_ATTRIBUTE_TABLE sh_attribute_table/* The next two are used for debug info when compiling with -gdwarf.  */#undef TARGET_ASM_UNALIGNED_HI_OP#define TARGET_ASM_UNALIGNED_HI_OP "\t.uaword\t"#undef TARGET_ASM_UNALIGNED_SI_OP#define TARGET_ASM_UNALIGNED_SI_OP "\t.ualong\t"/* These are NULLed out on non-SH5 in OVERRIDE_OPTIONS.  */#undef TARGET_ASM_UNALIGNED_DI_OP#define TARGET_ASM_UNALIGNED_DI_OP "\t.uaquad\t"#undef TARGET_ASM_ALIGNED_DI_OP#define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"#undef TARGET_ASM_FUNCTION_EPILOGUE#define TARGET_ASM_FUNCTION_EPILOGUE sh_output_function_epilogue#undef TARGET_INSERT_ATTRIBUTES#define TARGET_INSERT_ATTRIBUTES sh_insert_attributes#undef TARGET_SCHED_ADJUST_COST#define TARGET_SCHED_ADJUST_COST sh_adjust_cost#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE #define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE \				sh_use_dfa_interface#undef TARGET_SCHED_ISSUE_RATE#define TARGET_SCHED_ISSUE_RATE sh_issue_rate#undef TARGET_CANNOT_MODIFY_JUMPS_P#define TARGET_CANNOT_MODIFY_JUMPS_P sh_cannot_modify_jumps_p#undef TARGET_MS_BITFIELD_LAYOUT_P#define TARGET_MS_BITFIELD_LAYOUT_P sh_ms_bitfield_layout_p#undef TARGET_ENCODE_SECTION_INFO#define TARGET_ENCODE_SECTION_INFO sh_encode_section_info#undef TARGET_STRIP_NAME_ENCODING#define TARGET_STRIP_NAME_ENCODING sh_strip_name_encoding#undef TARGET_INIT_BUILTINS#define TARGET_INIT_BUILTINS sh_init_builtins#undef TARGET_EXPAND_BUILTIN#define TARGET_EXPAND_BUILTIN sh_expand_builtinstruct gcc_target targetm = TARGET_INITIALIZER;/* Print the operand address in x to the stream.  */voidprint_operand_address (stream, x)     FILE *stream;     rtx x;{  switch (GET_CODE (x))    {    case REG:    case SUBREG:      fprintf (stream, "@%s", reg_names[true_regnum (x)]);      break;    case PLUS:      {	rtx base = XEXP (x, 0);	rtx index = XEXP (x, 1);	switch (GET_CODE (index))	  {	  case CONST_INT:	    fprintf (stream, "@(%d,%s)", (int) INTVAL (index),		     reg_names[true_regnum (base)]);	    break;	  case REG:	  case SUBREG:	    {	      int base_num = true_regnum (base);	      int index_num = true_regnum (index);	      fprintf (stream, "@(r0,%s)",		       reg_names[MAX (base_num, index_num)]);	      break;	    }	  default:	    debug_rtx (x);	    abort ();	  }      }      break;    case PRE_DEC:      fprintf (stream, "@-%s", reg_names[true_regnum (XEXP (x, 0))]);      break;    case POST_INC:      fprintf (stream, "@%s+", reg_names[true_regnum (XEXP (x, 0))]);      break;    default:      x = mark_constant_pool_use (x);      output_addr_const (stream, x);      break;    }}/* Print operand x (an rtx) in assembler syntax to file stream   according to modifier code.   '.'  print a .s if insn needs delay slot   ','  print LOCAL_LABEL_PREFIX   '@'  print trap, rte or rts depending upon pragma interruptness   '#'  output a nop if there is nothing to put in the delay slot   '''  print likelyhood suffix (/u for unlikely).   'O'  print a constant without the #   'R'  print the LSW of a dp value - changes if in little endian   'S'  print the MSW of a dp value - changes if in little endian   'T'  print the next word of a dp value - same as 'R' in big endian mode.   'M'  print an `x' if `m' will print `base,index'.   'N'  print 'r63' if the operand is (const_int 0).   'm'  print a pair `base,offset' or `base,index', for LD and ST.   'u'  prints the lowest 16 bits of CONST_INT, as an unsigned value.   'o'  output an operator.  */voidprint_operand (stream, x, code)     FILE *stream;     rtx x;     int code;{  switch (code)    {    case '.':      if (final_sequence	  && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))	  && get_attr_length (XVECEXP (final_sequence, 0, 1)))	fprintf (stream, ASSEMBLER_DIALECT ? "/s" : ".s");      break;    case ',':      fprintf (stream, "%s", LOCAL_LABEL_PREFIX);      break;    case '@':      if (trap_exit)	fprintf (stream, "trapa #%d", trap_exit);      else if (sh_cfun_interrupt_handler_p ())	fprintf (stream, "rte");      else	fprintf (stream, "rts");      break;    case '#':      /* Output a nop if there's nothing in the delay slot.  */      if (dbr_sequence_length () == 0)	fprintf (stream, "\n\tnop");      break;    case '\'':      {	rtx note = find_reg_note (current_output_insn, REG_BR_PROB, 0);	if (note && INTVAL (XEXP (note, 0)) * 2 < REG_BR_PROB_BASE)	  fputs ("/u", stream);	break;      }    case 'O':      x = mark_constant_pool_use (x);      output_addr_const (stream, x);      break;    case 'R':      fputs (reg_names[REGNO (x) + LSW], (stream));      break;    case 'S':      fputs (reg_names[REGNO (x) + MSW], (stream));      break;    case 'T':      /* Next word of a double.  */      switch (GET_CODE (x))	{	case REG:	  fputs (reg_names[REGNO (x) + 1], (stream));	  break;	case MEM:	  if (GET_CODE (XEXP (x, 0)) != PRE_DEC	      && GET_CODE (XEXP (x, 0)) != POST_INC)	    x = adjust_address (x, SImode, 4);	  print_operand_address (stream, XEXP (x, 0));	  break;	default:	  break;	}      break;    case 'o':      switch (GET_CODE (x))	{	case PLUS:  fputs ("add", stream); break;	case MINUS: fputs ("sub", stream); break;	case MULT:  fputs ("mul", stream); break;	case DIV:   fputs ("div", stream); break;	case EQ:    fputs ("eq",  stream); break;	case NE:    fputs ("ne",  stream); break;	case GT:  case LT:  fputs ("gt",  stream); break;	case GE:  case LE:  fputs ("ge",  stream); break;	case GTU: case LTU: fputs ("gtu", stream); break;	case GEU: case LEU: fputs ("geu", stream); break;	default:	  break;	}      break;    case 'M':      if (GET_CODE (x) == MEM	  && GET_CODE (XEXP (x, 0)) == PLUS	  && (GET_CODE (XEXP (XEXP (x, 0), 1)) == REG	      || GET_CODE (XEXP (XEXP (x, 0), 1)) == SUBREG))	fputc ('x', stream);      break;    case 'm':      if (GET_CODE (x) != MEM)	abort ();      x = XEXP (x, 0);      switch (GET_CODE (x))	{	case REG:	case SUBREG:	  print_operand (stream, x, 0);	  fputs (", 0", stream);	  break;	case PLUS:	  print_operand (stream, XEXP (x, 0), 0);	  fputs (", ", stream);	  print_operand (stream, XEXP (x, 1), 0);	  break;	default:	  abort ();	}      break;    case 'N':

⌨️ 快捷键说明

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