clipper.c

来自「gcc3.2.1源代码」· C语言 代码 · 共 693 行 · 第 1/2 页

C
693
字号
/* Subroutines for insn-output.c for Clipper   Copyright (C) 1987, 1988, 1991, 1997, 1998, 1999, 2000, 2001   Free Software Foundation, Inc.   Contributed by Holger Teutsch (holger@hotbso.rhein-main.de)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 "rtl.h"#include "regs.h"#include "hard-reg-set.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "output.h"#include "insn-attr.h"#include "tree.h"#include "expr.h"#include "optabs.h"#include "libfuncs.h"#include "c-tree.h"#include "function.h"#include "flags.h"#include "recog.h"#include "tm_p.h"#include "target.h"#include "target-def.h"static void clipper_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));static void clipper_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));static void clix_asm_out_constructor PARAMS ((rtx, int));static void clix_asm_out_destructor PARAMS ((rtx, int));extern char regs_ever_live[];extern int frame_pointer_needed;static int frame_size;/* Initialize the GCC target structure.  */#undef TARGET_ASM_ALIGNED_HI_OP#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"#undef TARGET_ASM_FUNCTION_PROLOGUE#define TARGET_ASM_FUNCTION_PROLOGUE clipper_output_function_prologue#undef TARGET_ASM_FUNCTION_EPILOGUE#define TARGET_ASM_FUNCTION_EPILOGUE clipper_output_function_epiloguestruct gcc_target targetm = TARGET_INITIALIZER;/* Compute size of a clipper stack frame where 'lsize' is the required   space for local variables.  */intclipper_frame_size (lsize)     int lsize;{  int i, size;				/* total size of frame */  int save_size;  save_size = 0;			/* compute size for reg saves */  for (i = 16; i < 32; i++)    if (regs_ever_live[i] && !call_used_regs[i])      save_size += 8;  for (i = 0; i < 16; i++)    if (regs_ever_live[i] && !call_used_regs[i])      save_size += 4;  size = lsize + save_size;  size = (size + 7) & ~7;		/* align to 64 Bit */  return size;}/* Prologue and epilogue output   Function is entered with pc pushed, i.e. stack is 32 bit aligned   current_function_args_size == 0 means that the current function's args   are passed totally in registers i.e fp is not used as ap.   If frame_size is also 0 the current function does not push anything and   can run with misaligned stack -> subq $4,sp / add $4,sp on entry and exit   can be omitted.  */static voidclipper_output_function_prologue (file, lsize)     FILE *file;     HOST_WIDE_INT lsize;			/* size for locals */{  int i, offset;  int size;  frame_size = size = clipper_frame_size (lsize);  if (frame_pointer_needed)    {      fputs ("\tpushw  fp,sp\n", file);      fputs ("\tmovw   sp,fp\n", file);    }  else if (size != 0 || current_function_args_size != 0)    {      size += 4;			/* keep stack aligned */      frame_size = size;		/* must push data or access args */    }  if (size)    {      if (size < 16)	fprintf (file, "\tsubq   $%d,sp\n", size);      else	fprintf (file, "\tsubi   $%d,sp\n", size);      /* register save slots are relative to sp, because we have small positive	 displacements and this works whether we have a frame pointer or not */      offset = 0;      for (i = 16; i < 32; i++)	if (regs_ever_live[i] && !call_used_regs[i])	  {	    if (offset == 0)	      fprintf (file, "\tstord  f%d,(sp)\n", i-16);	    else	      fprintf (file, "\tstord  f%d,%d(sp)\n", i-16, offset);	    offset += 8;	  }      for (i = 0; i < 16; i++)	if (regs_ever_live[i] && !call_used_regs[i])	  {	    if (offset == 0)	      fprintf (file, "\tstorw  r%d,(sp)\n", i);	    else	      fprintf (file, "\tstorw  r%d,%d(sp)\n", i, offset);	    offset += 4;	  }    }}static voidclipper_output_function_epilogue (file, size)     FILE *file;     HOST_WIDE_INT size ATTRIBUTE_UNUSED;{  int i, offset;  if (frame_pointer_needed)    {      offset = -frame_size;      for (i = 16; i < 32; i++)	if (regs_ever_live[i] && !call_used_regs[i])	  {	    fprintf (file, "\tloadd  %d(fp),f%d\n", offset, i-16);	    offset += 8;	  }      for (i = 0; i < 16; i++)	if (regs_ever_live[i] && !call_used_regs[i])	  {	    fprintf (file, "\tloadw  %d(fp),r%d\n", offset, i);	    offset += 4;	  }      fputs ("\tmovw   fp,sp\n\tpopw   sp,fp\n\tret    sp\n",	     file);    }  else					/* no frame pointer */    {      offset = 0;      for (i = 16; i < 32; i++)	if (regs_ever_live[i] && !call_used_regs[i])	  {	    if (offset == 0)	      fprintf (file, "\tloadd  (sp),f%d\n", i-16);	    else	      fprintf (file, "\tloadd  %d(sp),f%d\n", offset, i-16);	    offset += 8;	  }      for (i = 0; i < 16; i++)	if (regs_ever_live[i] && !call_used_regs[i])	  {	    if (offset == 0)	      fprintf (file, "\tloadw  (sp),r%d\n", i);	    else	      fprintf (file, "\tloadw  %d(sp),r%d\n", offset, i);	    offset += 4;	  }      if (frame_size > 0)	{	  if (frame_size < 16)	    fprintf (file, "\taddq   $%d,sp\n", frame_size);	  else	    fprintf (file, "\taddi   $%d,sp\n", frame_size);	}      fputs ("\tret    sp\n", file);    }}/* * blockmove * * clipper_movstr () */voidclipper_movstr (operands)     rtx *operands;{  rtx dst,src,cnt,tmp,top,bottom=NULL_RTX,xops[3];  int align;  int fixed;  extern FILE *asm_out_file;  dst = operands[0];  src = operands[1];  /* don't change this operands[2]; gcc 2.3.3 doesn't honor clobber note */  align = INTVAL (operands[3]);  tmp = operands[4];  cnt = operands[5];  if (GET_CODE (operands[2]) == CONST_INT) /* fixed size move */    {      if ((fixed = INTVAL (operands[2])) <= 0)	abort ();      if (fixed <16)	output_asm_insn ("loadq  %2,%5", operands);      else	output_asm_insn ("loadi  %2,%5", operands);    }  else    {      fixed = 0;      bottom = (rtx)gen_label_rtx ();	/* need a bottom label */      xops[0] = cnt; xops[1] = bottom;      output_asm_insn ("movw   %2,%5", operands); /* count is scratch reg 5 */      output_asm_insn ("brle   %l1", xops);    }  top = (rtx)gen_label_rtx ();		/* top of loop label */  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (top));  xops[0] = src; xops[1] = tmp; xops[2] = dst;  if (fixed && (align & 0x3) == 0)	/* word aligned move with known size */    {      if (fixed >= 4)	{	  rtx xops1[2];	  output_asm_insn(	    "loadw  %a0,%1\n\taddq   $4,%0\n\tstorw  %1,%a2\n\taddq   $4,%2",			  xops);	  xops1[0] = cnt; xops1[1] = top;	  output_asm_insn ("subq   $4,%0\n\tbrgt   %l1", xops1);	}      if (fixed & 0x2)	{	  output_asm_insn ("loadh  %a0,%1\n\tstorh  %1,%a2", xops);	  if (fixed & 0x1)	    output_asm_insn ("loadb  2%a0,%1\n\tstorb  %1,2%a2", xops);	}      else	if (fixed & 0x1)	  output_asm_insn ("loadb  %a0,%1\n\tstorb  %1,%a2", xops);    }  else    {      output_asm_insn(	  "loadb  %a0,%1\n\taddq   $1,%0\n\tstorb  %1,%a2\n\taddq   $1,%2",		      xops);      xops[0] = cnt; xops[1] = top;      output_asm_insn ("subq   $1,%0\n\tbrgt   %l1", xops);    }  if (fixed == 0)    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (bottom));}voidprint_operand_address (file, addr)     FILE *file;     register rtx addr;{  rtx op0,op1;  switch (GET_CODE (addr))    {    case REG:      fprintf (file, "(%s)", reg_names[REGNO (addr)]);      break;    case PLUS:      /* can be 'symbol + reg' or 'reg + reg' */      op0 = XEXP (addr, 0);      op1 = XEXP (addr, 1);      if (GET_CODE (op0) == REG && GET_CODE (op1) == REG)	{	  fprintf (file, "[%s](%s)",		   reg_names[REGNO (op0)], reg_names[REGNO (op1)]);	  break;	}      if (GET_CODE (op0) == REG && CONSTANT_ADDRESS_P (op1))	{	  output_addr_const (file, op1);	  fprintf (file, "(%s)", reg_names[REGNO (op0)]);	  break;	}      if (GET_CODE (op1) == REG && CONSTANT_ADDRESS_P (op0))	{	  output_addr_const (file, op0);	  fprintf (file, "(%s)", reg_names[REGNO (op1)]);	  break;	}      abort ();				/* Oh no */    default:

⌨️ 快捷键说明

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