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

📄 mn10200.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Subroutines for insn-output.c for Matsushita MN10200 series   Copyright (C) 1997 Free Software Foundation, Inc.   Contributed by Jeff Law (law@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 <stdio.h>#include "rtl.h"#include "regs.h"#include "hard-reg-set.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "insn-flags.h"#include "output.h"#include "insn-attr.h"#include "flags.h"#include "recog.h"#include "expr.h"#include "tree.h"#include "obstack.h"/* Global registers known to hold the value zero.   Normally we'd depend on CSE and combine to put zero into a   register and re-use it.   However, on the mn10x00 processors we implicitly use the constant   zero in tst instructions, so we might be able to do better by   loading the value into a register in the prologue, then re-useing   that register throughout the function.   We could perform similar optimizations for other constants, but with   gcse due soon, it doesn't seem worth the effort.   These variables hold a rtx for a register known to hold the value   zero throughout the entire function, or NULL if no register of   the appropriate class has such a value throughout the life of the   function.  */rtx zero_dreg;rtx zero_areg;/* Note whether or not we need an out of line epilogue.  */static int out_of_line_epilogue;/* Indicate this file was compiled by gcc and what optimization   level was used.  */voidasm_file_start (file)     FILE *file;{  fprintf (file, "#\tGCC For the Matsushita MN10200\n");  if (optimize)    fprintf (file, "# -O%d\n", optimize);  else    fprintf (file, "\n\n");  output_file_directive (file, main_input_filename);}/* Print operand X using operand code CODE to assembly language output file   FILE.  */voidprint_operand (file, x, code)     FILE *file;     rtx x;     int code;{  switch (code)    {      case 'b':      case 'B':	/* These are normal and reversed branches.  */	switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))	  {	  case NE:	    fprintf (file, "ne");	    break;	  case EQ:	    fprintf (file, "eq");	    break;	  case GE:	    fprintf (file, "ge");	    break;	  case GT:	    fprintf (file, "gt");	    break;	  case LE:	    fprintf (file, "le");	    break;	  case LT:	    fprintf (file, "lt");	    break;	  case GEU:	    fprintf (file, "cc");	    break;	  case GTU:	    fprintf (file, "hi");	    break;	  case LEU:	    fprintf (file, "ls");	    break;	  case LTU:	    fprintf (file, "cs");	    break;	  default:	    abort ();	  }	break;      case 'C':	/* This is used for the operand to a call instruction;	   if it's a REG, enclose it in parens, else output	   the operand normally.  */	if (GET_CODE (x) == REG)	  {	    fputc ('(', file);	    print_operand (file, x, 0);	    fputc (')', file);	  }	else	  print_operand (file, x, 0);	break;           /* These are the least significant word in a 32bit value.	 'o' allows us to sign extend a constant if doing so	 makes for more compact code.  */      case 'L':      case 'o':	switch (GET_CODE (x))	  {	  case MEM:	    fputc ('(', file);	    output_address (XEXP (x, 0));	    fputc (')', file);	    break;	  case REG:	    fprintf (file, "%s", reg_names[REGNO (x)]);	    break;	  case SUBREG:	    fprintf (file, "%s",		     reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);	    break;	  case CONST_DOUBLE:	    if (code == 'L')	      {		long val;		REAL_VALUE_TYPE rv;		REAL_VALUE_FROM_CONST_DOUBLE (rv, x);		REAL_VALUE_TO_TARGET_SINGLE (rv, val);		print_operand_address (file, GEN_INT (val & 0xffff));	      }	    else	      {		long val;		REAL_VALUE_TYPE rv;		REAL_VALUE_FROM_CONST_DOUBLE (rv, x);		REAL_VALUE_TO_TARGET_SINGLE (rv, val);		val &= 0xffff;		val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000;		print_operand_address (file, GEN_INT (val));	      }	    break;	  case CONST_INT:	    if (code == 'L')	      print_operand_address (file, GEN_INT ((INTVAL (x) & 0xffff)));	    else	      {	        unsigned int val = INTVAL (x) & 0xffff;		val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000;		print_operand_address (file, GEN_INT (val));	      }	    break;	  default:	    abort ();	  }	break;      /* Similarly, but for the most significant word.  */      case 'H':      case 'h':	switch (GET_CODE (x))	  {	  case MEM:	    fputc ('(', file);	    x = adj_offsettable_operand (x, 2);	    output_address (XEXP (x, 0));	    fputc (')', file);	    break;	  case REG:	    fprintf (file, "%s", reg_names[REGNO (x) + 1]);	    break;	  case SUBREG:	    fprintf (file, "%s",		     reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)] + 1);	    break;	  case CONST_DOUBLE:	    if (code == 'H')	      {		long val;		REAL_VALUE_TYPE rv;		REAL_VALUE_FROM_CONST_DOUBLE (rv, x);		REAL_VALUE_TO_TARGET_SINGLE (rv, val);		print_operand_address (file, GEN_INT ((val >> 16) & 0xffff));	      }	    else	      {		long val;		REAL_VALUE_TYPE rv;		REAL_VALUE_FROM_CONST_DOUBLE (rv, x);		REAL_VALUE_TO_TARGET_SINGLE (rv, val);		val = (val >> 16) & 0xffff;		val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000;		print_operand_address (file, GEN_INT (val));	      }	    break;	  case CONST_INT:	    if (code == 'H')	      print_operand_address (file,				     GEN_INT ((INTVAL (x) >> 16) & 0xffff));	    else	      {	        unsigned int val = (INTVAL (x) >> 16) & 0xffff;		val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000;		print_operand_address (file, GEN_INT (val));	      }	    break;	  default:	    abort ();	  }	break;      /* Output ~CONST_INT.  */      case 'N':	if (GET_CODE (x) != CONST_INT)	  abort ();        fprintf (file, "%d", ~INTVAL (x));        break;      /* An address which can not be register indirect, if it is	 register indirect, then turn it into reg + disp.  */      case 'A':	if (GET_CODE (x) != MEM)	  abort ();	if (GET_CODE (XEXP (x, 0)) == REG)	  x = gen_rtx (PLUS, PSImode, XEXP (x, 0), GEN_INT (0));	else	  x = XEXP (x, 0);	fputc ('(', file);	output_address (x);	fputc (')', file);	break;      case 'Z':        print_operand (file, XEXP (x, 1), 0);	break;      /* More cases where we can sign-extend a CONST_INT if it	 results in more compact code.  */      case 's':      case 'S':	if (GET_CODE (x) == CONST_INT)	  {	    int val = INTVAL (x);	    if (code == 's')	      x = GEN_INT (((val & 0xffff) ^ (~0x7fff)) + 0x8000);	    else	      x = GEN_INT (((val & 0xff) ^ (~0x7f)) + 0x80);	  }        /* FALL THROUGH */      default:	switch (GET_CODE (x))	  {	  case MEM:	    fputc ('(', file);	    output_address (XEXP (x, 0));	    fputc (')', file);	    break;	  case REG:	    fprintf (file, "%s", reg_names[REGNO (x)]);	    break;	  case SUBREG:	    fprintf (file, "%s",		     reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)]);	    break;	  case CONST_INT:	  case CONST_DOUBLE:	  case SYMBOL_REF:	  case CONST:	  case LABEL_REF:	  case CODE_LABEL:	    print_operand_address (file, x);	    break;	  default:	    abort ();	  }	break;   }}/* Output assembly language output for the address ADDR to FILE.  */voidprint_operand_address (file, addr)     FILE *file;     rtx addr;{  switch (GET_CODE (addr))    {    case REG:      print_operand (file, addr, 0);      break;    case PLUS:      {	rtx base, index;	/* The base and index could be in any order, so we have	   to figure out which is the base and which is the index.	   Uses the same code as GO_IF_LEGITIMATE_ADDRESS.  */	if (REG_P (XEXP (addr, 0))	    && REG_OK_FOR_BASE_P (XEXP (addr, 0)))	  base = XEXP (addr, 0), index = XEXP (addr, 1);	else if (REG_P (XEXP (addr, 1))	    && REG_OK_FOR_BASE_P (XEXP (addr, 1)))	  base = XEXP (addr, 1), index = XEXP (addr, 0);      	else	  abort ();	print_operand (file, index, 0);	fputc (',', file);	print_operand (file, base, 0);;	break;      }    case SYMBOL_REF:      output_addr_const (file, addr);      break;    default:      output_addr_const (file, addr);      break;    }}/* Count the number of tst insns which compare an address register   with zero.  */static void count_tst_insns (areg_countp)     int *areg_countp;{  rtx insn;  /* Assume no tst insns exist.  */  *areg_countp = 0;  /* If not optimizing, then quit now.  */  if (!optimize)    return;  /* Walk through all the insns.  */  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))    {      rtx pat;      /* Ignore anything that is not a normal INSN.  */      if (GET_CODE (insn) != INSN)	continue;      /* Ignore anything that isn't a SET.  */      pat = PATTERN (insn);      if (GET_CODE (pat) != SET)	continue;      /* Check for a tst insn.  */      if (SET_DEST (pat) == cc0_rtx	  && GET_CODE (SET_SRC (pat)) == REG	  && REGNO_REG_CLASS (REGNO (SET_SRC (pat))) == ADDRESS_REGS)	(*areg_countp)++;    }}/* Return the total size (in bytes) of the current function's frame.   This is the size of the register save area + the size of locals,   spills, etc.  */inttotal_frame_size (){  unsigned int size = get_frame_size ();  unsigned int outgoing_args_size = current_function_outgoing_args_size;  int i;  /* First figure out if we're going to use an out of line     prologue, if so we have to make space for all the     registers, even if we don't use them.  */  if (optimize && !current_function_needs_context && !frame_pointer_needed)    {      int inline_count, outline_count;      /* Compute how many bytes an inline prologue would take.         Each address register store takes two bytes, each data register	 store takes three bytes.  */      inline_count = 0;      if (regs_ever_live[5])	inline_count += 2;      if (regs_ever_live[6])	inline_count += 2;      if (regs_ever_live[2])	inline_count += 3;      if (regs_ever_live[3])	inline_count += 3;      /* If this function has any stack, then the stack adjustment	 will take two (or more) bytes.  */      if (size || outgoing_args_size	  || regs_ever_live[5] || regs_ever_live[6]	  || regs_ever_live[2] || regs_ever_live[3])      inline_count += 2;      /* Multiply the current count by two and add one to account for the	 epilogue insns.  */      inline_count = inline_count * 2 + 1;          /* Now compute how many bytes an out of line sequence would take.  */      /* A relaxed jsr will be three bytes.  */      outline_count = 3;      /* If there are outgoing arguments, then we will need a stack	 pointer adjustment after the call to the prologue, two	 more bytes.  */      outline_count += (outgoing_args_size == 0 ? 0 : 2);      /* If there is some local frame to allocate, it will need to be	 done before the call to the prologue, two more bytes.  */      if (get_frame_size () != 0)	outline_count += 2;      /* Now account for the epilogue, multiply the base count by two,	 then deal with optimizing away the rts instruction.  */      outline_count = outline_count * 2 + 1;      if (get_frame_size () == 0 && outgoing_args_size == 0)	outline_count -= 1;      /* If an out of line prologue is smaller, use it.  */      if (inline_count > outline_count)	return size + outgoing_args_size + 16;    }  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)    {      if (regs_ever_live[i] && !call_used_regs[i] && ! fixed_regs[i]	  || (i == FRAME_POINTER_REGNUM && frame_pointer_needed))	size += 4;    }  return (size + outgoing_args_size);}/* Expand the prologue into RTL.  */voidexpand_prologue (){  unsigned int size = total_frame_size ();  unsigned int outgoing_args_size = current_function_outgoing_args_size;  int offset, i;  zero_areg = NULL_RTX;  zero_dreg = NULL_RTX;  /* If optimizing, see if we should do an out of line prologue/epilogue     sequence.     We don't support out of line prologues if the current function     needs a context or frame pointer.  */  if (optimize && !current_function_needs_context && !frame_pointer_needed)    {      int inline_count, outline_count, areg_count;

⌨️ 快捷键说明

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