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

📄 mt.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Target definitions for the MorphoRISC1   Copyright (C) 2005 Free Software Foundation, Inc.   Contributed by Red Hat, Inc.   This file is part of GCC.   GCC is free software; you can redistribute it and/or modify it   under the terms of the GNU General Public License as published   by the 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 of MERCHANTABILITY   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public   License for more details.   You should have received a copy of the GNU General Public License   along with GCC; see the file COPYING.  If not, write to the Free   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA   02110-1301, 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 "real.h"#include "insn-config.h"#include "conditions.h"#include "insn-attr.h"#include "recog.h"#include "toplev.h"#include "output.h"#include "integrate.h"#include "tree.h"#include "function.h"#include "expr.h"#include "optabs.h"#include "libfuncs.h"#include "flags.h"#include "tm_p.h"#include "ggc.h"#include "insn-flags.h"#include "obstack.h"#include "except.h"#include "target.h"#include "target-def.h"/* Frame pointer register mask.  */#define FP_MASK		 	 (1 << (GPR_FP))/* Link register mask.  */#define LINK_MASK	 	 (1 << (GPR_LINK))/* Given a SIZE in bytes, advance to the next word.  */#define ROUND_ADVANCE(SIZE) (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)/* A C structure for machine-specific, per-function data.   This is added to the cfun structure.  */struct machine_function GTY(()){  /* Flags if __builtin_return_address (n) with n >= 1 was used.  */  int ra_needs_full_frame;  struct rtx_def * eh_stack_adjust;  int interrupt_handler;};/* Define the information needed to generate branch and scc insns.   This is stored from the compare operation.  */struct rtx_def * mt_compare_op0;struct rtx_def * mt_compare_op1;/* Current frame information calculated by compute_frame_size.  */struct mt_frame_info current_frame_info;/* Zero structure to initialize current_frame_info.  */struct mt_frame_info zero_frame_info;/* mt doesn't have unsigned compares need a library call for this.  */struct rtx_def * mt_ucmpsi3_libcall;static int mt_flag_delayed_branch;static rtxmt_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED,			 int incoming ATTRIBUTE_UNUSED){  return gen_rtx_REG (Pmode, RETVAL_REGNUM);}/* Implement RETURN_ADDR_RTX.  */rtxmt_return_addr_rtx (int count){  if (count != 0)    return NULL_RTX;  return get_hard_reg_initial_val (Pmode, GPR_LINK);}/* The following variable value indicates the number of nops required   between the current instruction and the next instruction to avoid   any pipeline hazards.  */static int mt_nops_required = 0;static const char * mt_nop_reasons = "";/* Implement ASM_OUTPUT_OPCODE.  */const char *mt_asm_output_opcode (FILE *f ATTRIBUTE_UNUSED, const char *ptr){  if (mt_nops_required)    fprintf (f, ";# need %d nops because of %s\n\t",	     mt_nops_required, mt_nop_reasons);    while (mt_nops_required)    {      fprintf (f, "nop\n\t");      -- mt_nops_required;    }    return ptr;}/* Given an insn, return whether it's a memory operation or a branch   operation, otherwise return TYPE_ARITH.  */static enum attr_typemt_get_attr_type (rtx complete_insn){  rtx insn = PATTERN (complete_insn);  if (JUMP_P (complete_insn))    return TYPE_BRANCH;  if (CALL_P (complete_insn))    return TYPE_BRANCH;  if (GET_CODE (insn) != SET)    return TYPE_ARITH;  if (SET_DEST (insn) == pc_rtx)    return TYPE_BRANCH;  if (GET_CODE (SET_DEST (insn)) == MEM)    return TYPE_STORE;  if (GET_CODE (SET_SRC (insn)) == MEM)    return TYPE_LOAD;    return TYPE_ARITH;}/* A helper routine for insn_dependent_p called through note_stores.  */static voidinsn_dependent_p_1 (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data){  rtx * pinsn = (rtx *) data;  if (*pinsn && reg_mentioned_p (x, *pinsn))    *pinsn = NULL_RTX;}/* Return true if anything in insn X is (anti,output,true)   dependent on anything in insn Y.  */static boolinsn_dependent_p (rtx x, rtx y){  rtx tmp;  if (! INSN_P (x) || ! INSN_P (y))    return 0;  tmp = PATTERN (y);  note_stores (PATTERN (x), insn_dependent_p_1, &tmp);  if (tmp == NULL_RTX)    return true;  tmp = PATTERN (x);  note_stores (PATTERN (y), insn_dependent_p_1, &tmp);  return (tmp == NULL_RTX);}/* Return true if anything in insn X is true dependent on anything in   insn Y.  */static boolinsn_true_dependent_p (rtx x, rtx y){  rtx tmp;  if (! INSN_P (x) || ! INSN_P (y))    return 0;  tmp = PATTERN (y);  note_stores (PATTERN (x), insn_dependent_p_1, &tmp);  return (tmp == NULL_RTX);}/* The following determines the number of nops that need to be   inserted between the previous instructions and current instruction   to avoid pipeline hazards on the mt processor.  Remember that   the function is not called for asm insns.  */voidmt_final_prescan_insn (rtx   insn,			rtx * opvec ATTRIBUTE_UNUSED,			int   noperands ATTRIBUTE_UNUSED){  rtx prev_i;  enum attr_type prev_attr;  mt_nops_required = 0;  mt_nop_reasons = "";  /* ms2 constraints are dealt with in reorg.  */  if (TARGET_MS2)    return;    /* Only worry about real instructions.  */  if (! INSN_P (insn))    return;  /* Find the previous real instructions.  */  for (prev_i = PREV_INSN (insn);       prev_i != NULL	 && (! INSN_P (prev_i)	     || GET_CODE (PATTERN (prev_i)) == USE	     || GET_CODE (PATTERN (prev_i)) == CLOBBER);       prev_i = PREV_INSN (prev_i))    {      /* If we meet a barrier, there is no flow through here.  */      if (BARRIER_P (prev_i))	return;    }    /* If there isn't one then there is nothing that we need do.  */  if (prev_i == NULL || ! INSN_P (prev_i))    return;  prev_attr = mt_get_attr_type (prev_i);    /* Delayed branch slots already taken care of by delay branch scheduling.  */  if (prev_attr == TYPE_BRANCH)    return;  switch (mt_get_attr_type (insn))    {    case TYPE_LOAD:    case TYPE_STORE:      /* Avoid consecutive memory operation.  */      if  ((prev_attr == TYPE_LOAD || prev_attr == TYPE_STORE)	   && TARGET_MS1_64_001)	{	  mt_nops_required = 1;	  mt_nop_reasons = "consecutive mem ops";	}      /* Drop through.  */    case TYPE_ARITH:    case TYPE_COMPLEX:      /* One cycle of delay is required between load	 and the dependent arithmetic instruction.  */      if (prev_attr == TYPE_LOAD	  && insn_true_dependent_p (prev_i, insn))	{	  mt_nops_required = 1;	  mt_nop_reasons = "load->arith dependency delay";	}      break;    case TYPE_BRANCH:      if (insn_dependent_p (prev_i, insn))	{	  if (prev_attr == TYPE_ARITH && TARGET_MS1_64_001)	    {	      /* One cycle of delay between arith		 instructions and branch dependent on arith.  */	      mt_nops_required = 1;	      mt_nop_reasons = "arith->branch dependency delay";	    }	  else if (prev_attr == TYPE_LOAD)	    {	      /* Two cycles of delay are required		 between load and dependent branch.  */	      if (TARGET_MS1_64_001)		mt_nops_required = 2;	      else		mt_nops_required = 1;	      mt_nop_reasons = "load->branch dependency delay";	    }	}      break;    default:      fatal_insn ("mt_final_prescan_insn, invalid insn #1", insn);      break;    }}/* Print debugging information for a frame.  */static voidmt_debug_stack (struct mt_frame_info * info){  int regno;  if (!info)    {      error ("info pointer NULL");      gcc_unreachable ();    }  fprintf (stderr, "\nStack information for function %s:\n",	   ((current_function_decl && DECL_NAME (current_function_decl))	    ? IDENTIFIER_POINTER (DECL_NAME (current_function_decl))	    : "<unknown>"));  fprintf (stderr, "\ttotal_size       = %d\n", info->total_size);  fprintf (stderr, "\tpretend_size     = %d\n", info->pretend_size);  fprintf (stderr, "\targs_size        = %d\n", info->args_size);  fprintf (stderr, "\textra_size       = %d\n", info->extra_size);  fprintf (stderr, "\treg_size         = %d\n", info->reg_size);  fprintf (stderr, "\tvar_size         = %d\n", info->var_size);  fprintf (stderr, "\tframe_size       = %d\n", info->frame_size);  fprintf (stderr, "\treg_mask         = 0x%x\n", info->reg_mask);  fprintf (stderr, "\tsave_fp          = %d\n", info->save_fp);  fprintf (stderr, "\tsave_lr          = %d\n", info->save_lr);  fprintf (stderr, "\tinitialized      = %d\n", info->initialized);  fprintf (stderr, "\tsaved registers =");  /* Print out reg_mask in a more readable format.  */  for (regno = GPR_R0; regno <= GPR_LAST; regno++)    if ( (1 << regno) & info->reg_mask)      fprintf (stderr, " %s", reg_names[regno]);  putc ('\n', stderr);  fflush (stderr);}/* Print a memory address as an operand to reference that memory location.  */static voidmt_print_operand_simple_address (FILE * file, rtx addr){  if (!addr)    error ("PRINT_OPERAND_ADDRESS, null pointer");  else    switch (GET_CODE (addr))      {      case REG:	fprintf (file, "%s, #0", reg_names [REGNO (addr)]);	break;	      case PLUS:	{	  rtx reg = 0;	  rtx offset = 0;	  rtx arg0 = XEXP (addr, 0);	  rtx arg1 = XEXP (addr, 1);	  if (GET_CODE (arg0) == REG)	    {	      reg = arg0;	      offset = arg1;	      if (GET_CODE (offset) == REG)		fatal_insn ("PRINT_OPERAND_ADDRESS, 2 regs", addr);	    }	  else if (GET_CODE (arg1) == REG)	      reg = arg1, offset = arg0;	  else if (CONSTANT_P (arg0) && CONSTANT_P (arg1))	    {	      fprintf (file, "%s, #", reg_names [GPR_R0]);	      output_addr_const (file, addr);	      break;	    }	  fprintf (file, "%s, #", reg_names [REGNO (reg)]);	  output_addr_const (file, offset);	  break;	}      case LABEL_REF:      case SYMBOL_REF:      case CONST_INT:      case CONST:	output_addr_const (file, addr);	break;      default:	fatal_insn ("PRINT_OPERAND_ADDRESS, invalid insn #1", addr);	break;      }}/* Implement PRINT_OPERAND_ADDRESS.  */voidmt_print_operand_address (FILE * file, rtx addr){  if (GET_CODE (addr) == AND      && GET_CODE (XEXP (addr, 1)) == CONST_INT      && INTVAL (XEXP (addr, 1)) == -3)    mt_print_operand_simple_address (file, XEXP (addr, 0));  else    mt_print_operand_simple_address (file, addr);}/* Implement PRINT_OPERAND.  */voidmt_print_operand (FILE * file, rtx x, int code){  switch (code)    {    case '#':      /* Output a nop if there's nothing for the delay slot.  */      if (dbr_sequence_length () == 0)	fputs ("\n\tnop", file);      return;          case 'H':       fprintf(file, "#%%hi16(");      output_addr_const (file, x);      fprintf(file, ")");      return;          case 'L':       fprintf(file, "#%%lo16(");      output_addr_const (file, x);      fprintf(file, ")");      return;    case 'N':       fprintf(file, "#%ld", ~INTVAL (x));      return;    case 'z':      if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0)	{	  fputs (reg_names[GPR_R0], file);	  return;	}    case 0:      /* Handled below.  */      break;    default:      /* output_operand_lossage ("mt_print_operand: unknown code"); */      fprintf (file, "unknown code");      return;    }  switch (GET_CODE (x))    {    case REG:      fputs (reg_names [REGNO (x)], file);      break;    case CONST:    case CONST_INT:      fprintf(file, "#%ld", INTVAL (x));      break;    case MEM:      mt_print_operand_address(file, XEXP (x,0));      break;    case LABEL_REF:    case SYMBOL_REF:      output_addr_const (file, x);      break;          default:      fprintf(file, "Uknown code: %d", GET_CODE (x));      break;    }  return;}/* Implement INIT_CUMULATIVE_ARGS.  */voidmt_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype, rtx libname,			 tree fndecl ATTRIBUTE_UNUSED, int incoming){  *cum = 0;  if (TARGET_DEBUG_ARG)    {      fprintf (stderr, "\nmt_init_cumulative_args:");      if (incoming)	fputs (" incoming", stderr);

⌨️ 快捷键说明

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