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

📄 genemit.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Generate code from machine description to emit insns as rtl.   Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.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, 675 Mass Ave, Cambridge, MA 02139, USA.  */#include <stdio.h>#include "hconfig.h"#include "rtl.h"#include "obstack.h"static struct obstack obstack;struct obstack *rtl_obstack = &obstack;#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freeextern void free ();extern rtx read_rtx ();char *xmalloc ();static void fatal ();void fancy_abort ();static int max_opno;static int max_dup_opno;static int register_constraints;static int insn_code_number;static int insn_index_number;/* Data structure for recording the patterns of insns that have CLOBBERs.   We use this to output a function that adds these CLOBBERs to a    previously-allocated PARALLEL expression.  */struct clobber_pat{  struct clobber_ent *insns;  rtx pattern;  int first_clobber;  struct clobber_pat *next;} *clobber_list;/* Records one insn that uses the clobber list.  */struct clobber_ent{  int code_number;		/* Counts only insns.  */  struct clobber_ent *next;};static voidmax_operand_1 (x)     rtx x;{  register RTX_CODE code;  register int i;  register int len;  register char *fmt;  if (x == 0)    return;  code = GET_CODE (x);  if (code == MATCH_OPERAND && XSTR (x, 2) != 0 && *XSTR (x, 2) != '\0')    register_constraints = 1;  if (code == MATCH_SCRATCH && XSTR (x, 1) != 0 && *XSTR (x, 1) != '\0')    register_constraints = 1;  if (code == MATCH_OPERAND || code == MATCH_OPERATOR      || code == MATCH_PARALLEL)    max_opno = MAX (max_opno, XINT (x, 0));  if (code == MATCH_DUP || code == MATCH_OP_DUP || code == MATCH_PAR_DUP)    max_dup_opno = MAX (max_dup_opno, XINT (x, 0));  fmt = GET_RTX_FORMAT (code);  len = GET_RTX_LENGTH (code);  for (i = 0; i < len; i++)    {      if (fmt[i] == 'e' || fmt[i] == 'u')	max_operand_1 (XEXP (x, i));      else if (fmt[i] == 'E')	{	  int j;	  for (j = 0; j < XVECLEN (x, i); j++)	    max_operand_1 (XVECEXP (x, i, j));	}    }}static intmax_operand_vec (insn, arg)     rtx insn;     int arg;{  register int len = XVECLEN (insn, arg);  register int i;  max_opno = -1;  max_dup_opno = -1;  for (i = 0; i < len; i++)    max_operand_1 (XVECEXP (insn, arg, i));  return max_opno + 1;}static voidprint_code (code)     RTX_CODE code;{  register char *p1;  for (p1 = GET_RTX_NAME (code); *p1; p1++)    {      if (*p1 >= 'a' && *p1 <= 'z')	putchar (*p1 + 'A' - 'a');      else	putchar (*p1);    }}/* Print a C expression to construct an RTX just like X,   substituting any operand references appearing within.  */static voidgen_exp (x)     rtx x;{  register RTX_CODE code;  register int i;  register int len;  register char *fmt;  if (x == 0)    {      printf ("NULL_RTX");      return;    }  code = GET_CODE (x);  switch (code)    {    case MATCH_OPERAND:    case MATCH_DUP:      printf ("operand%d", XINT (x, 0));      return;    case MATCH_OP_DUP:      printf ("gen_rtx (GET_CODE (operand%d), GET_MODE (operand%d)",	      XINT (x, 0), XINT (x, 0));      for (i = 0; i < XVECLEN (x, 1); i++)	{	  printf (",\n\t\t");	  gen_exp (XVECEXP (x, 1, i));	}      printf (")");      return;    case MATCH_OPERATOR:      printf ("gen_rtx (GET_CODE (operand%d)", XINT (x, 0));      printf (", %smode", GET_MODE_NAME (GET_MODE (x)));      for (i = 0; i < XVECLEN (x, 2); i++)	{	  printf (",\n\t\t");	  gen_exp (XVECEXP (x, 2, i));	}      printf (")");      return;    case MATCH_PARALLEL:    case MATCH_PAR_DUP:      printf ("operand%d", XINT (x, 0));      return;    case MATCH_SCRATCH:      printf ("gen_rtx (SCRATCH, %smode, 0)", GET_MODE_NAME (GET_MODE (x)));      return;    case ADDRESS:      fatal ("ADDRESS expression code used in named instruction pattern");    case PC:      printf ("pc_rtx");      return;    case CC0:      printf ("cc0_rtx");      return;    case CONST_INT:      if (INTVAL (x) == 0)	printf ("const0_rtx");      else if (INTVAL (x) == 1)	printf ("const1_rtx");      else if (INTVAL (x) == -1)	printf ("constm1_rtx");      else if (INTVAL (x) == STORE_FLAG_VALUE)	printf ("const_true_rtx");      else	printf (#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT	     		"GEN_INT (%d)",#else		"GEN_INT (%ld)",#endif		INTVAL (x));      return;    case CONST_DOUBLE:      /* These shouldn't be written in MD files.  Instead, the appropriate	 routines in varasm.c should be called.  */      abort ();    }  printf ("gen_rtx (");  print_code (code);  printf (", %smode", GET_MODE_NAME (GET_MODE (x)));  fmt = GET_RTX_FORMAT (code);  len = GET_RTX_LENGTH (code);  for (i = 0; i < len; i++)    {      if (fmt[i] == '0')	break;      printf (", ");      if (fmt[i] == 'e' || fmt[i] == 'u')	gen_exp (XEXP (x, i));      else if (fmt[i] == 'i')	printf ("%u", XINT (x, i));      else if (fmt[i] == 's')	printf ("\"%s\"", XSTR (x, i));      else if (fmt[i] == 'E')	{	  int j;	  printf ("gen_rtvec (%d", XVECLEN (x, i));	  for (j = 0; j < XVECLEN (x, i); j++)	    {	      printf (",\n\t\t");	      gen_exp (XVECEXP (x, i, j));	    }	  printf (")");	}      else	abort ();    }  printf (")");}  /* Generate the `gen_...' function for a DEFINE_INSN.  */static voidgen_insn (insn)     rtx insn;{  int operands;  register int i;  /* See if the pattern for this insn ends with a group of CLOBBERs of (hard)     registers or MATCH_SCRATCHes.  If so, store away the information for     later. */  if (XVEC (insn, 1))    {      for (i = XVECLEN (insn, 1) - 1; i > 0; i--)	if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER	    || (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != REG		&& GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH))	  break;      if (i != XVECLEN (insn, 1) - 1)	{	  register struct clobber_pat *p;	  register struct clobber_ent *link	    = (struct clobber_ent *) xmalloc (sizeof (struct clobber_ent));	  register int j;	  link->code_number = insn_code_number;	  /* See if any previous CLOBBER_LIST entry is the same as this	     one.  */	  for (p = clobber_list; p; p = p->next)	    {	      if (p->first_clobber != i + 1		  || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1))		continue;	      for (j = i + 1; j < XVECLEN (insn, 1); j++)		{		  rtx old = XEXP (XVECEXP (p->pattern, 1, j), 0);		  rtx new = XEXP (XVECEXP (insn, 1, j), 0);		  /* OLD and NEW are the same if both are to be a SCRATCH		     of the same mode, 		     or if both are registers of the same mode and number.  */		  if (! (GET_MODE (old) == GET_MODE (new)			 && ((GET_CODE (old) == MATCH_SCRATCH			      && GET_CODE (new) == MATCH_SCRATCH)			     || (GET_CODE (old) == REG && GET_CODE (new) == REG				 && REGNO (old) == REGNO (new)))))		    break;		}      	      if (j == XVECLEN (insn, 1))		break;	    }	  if (p == 0)	    {	      p = (struct clobber_pat *) xmalloc (sizeof (struct clobber_pat));	  	      p->insns = 0;	      p->pattern = insn;	      p->first_clobber = i + 1;	      p->next = clobber_list;	      clobber_list = p;	    }	  link->next = p->insns;	  p->insns = link;	}    }  /* Don't mention instructions whose names are the null string.     They are in the machine description just to be recognized.  */  if (strlen (XSTR (insn, 0)) == 0)    return;  /* Find out how many operands this function has,     and also whether any of them have register constraints.  */  register_constraints = 0;  operands = max_operand_vec (insn, 1);  if (max_dup_opno >= operands)    fatal ("match_dup operand number has no match_operand");  /* Output the function name and argument declarations.  */  printf ("rtx\ngen_%s (", XSTR (insn, 0));  for (i = 0; i < operands; i++)    printf (i ? ", operand%d" : "operand%d", i);  printf (")\n");  for (i = 0; i < operands; i++)    printf ("     rtx operand%d;\n", i);  printf ("{\n");  /* Output code to construct and return the rtl for the instruction body */  if (XVECLEN (insn, 1) == 1)    {      printf ("  return ");      gen_exp (XVECEXP (insn, 1, 0));      printf (";\n}\n\n");    }  else    {      printf ("  return gen_rtx (PARALLEL, VOIDmode, gen_rtvec (%d", XVECLEN (insn, 1));      for (i = 0; i < XVECLEN (insn, 1); i++)	{	  printf (",\n\t\t");	  gen_exp (XVECEXP (insn, 1, i));	}      printf ("));\n}\n\n");    }}/* Generate the `gen_...' function for a DEFINE_EXPAND.  */static voidgen_expand (expand)     rtx expand;{  int operands;  register int i;  if (strlen (XSTR (expand, 0)) == 0)    fatal ("define_expand lacks a name");  if (XVEC (expand, 1) == 0)    fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0));  /* Find out how many operands this function has,     and also whether any of them have register constraints.  */  register_constraints = 0;  operands = max_operand_vec (expand, 1);  /* Output the function name and argument declarations.  */  printf ("rtx\ngen_%s (", XSTR (expand, 0));

⌨️ 快捷键说明

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