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

📄 vax.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Cost of an expression on a VAX.  This version has costs tuned for the   CVAX chip (found in the VAX 3 series) with comments for variations on   other models.  */intvax_rtx_cost (x)    register rtx x;{  register enum rtx_code code = GET_CODE (x);  enum machine_mode mode = GET_MODE (x);  register int c;  int i = 0;				/* may be modified in switch */  const char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */  switch (code)    {    case POST_INC:      return 2;    case PRE_DEC:      return 3;    case MULT:      switch (mode)	{	case DFmode:	  c = 16;		/* 4 on VAX 9000 */	  break;	case SFmode:	  c = 9;		/* 4 on VAX 9000, 12 on VAX 2 */	  break;	case DImode:	  c = 16;		/* 6 on VAX 9000, 28 on VAX 2 */	  break;	case SImode:	case HImode:	case QImode:	  c = 10;		/* 3-4 on VAX 9000, 20-28 on VAX 2 */	  break;	default:	  return MAX_COST;	/* Mode is not supported.  */	}      break;    case UDIV:      if (mode != SImode)	return MAX_COST;	/* Mode is not supported.  */      c = 17;      break;    case DIV:      if (mode == DImode)	c = 30;	/* highly variable */      else if (mode == DFmode)	/* divide takes 28 cycles if the result is not zero, 13 otherwise */	c = 24;      else	c = 11;			/* 25 on VAX 2 */      break;    case MOD:      c = 23;      break;    case UMOD:      if (mode != SImode)	return MAX_COST;	/* Mode is not supported.  */      c = 29;      break;    case FLOAT:      c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);      /* 4 on VAX 9000 */      break;    case FIX:      c = 7;			/* 17 on VAX 2 */      break;    case ASHIFT:    case LSHIFTRT:    case ASHIFTRT:      if (mode == DImode)	c = 12;      else	c = 10;			/* 6 on VAX 9000 */      break;    case ROTATE:    case ROTATERT:      c = 6;			/* 5 on VAX 2, 4 on VAX 9000 */      if (GET_CODE (XEXP (x, 1)) == CONST_INT)	fmt = "e";	/* all constant rotate counts are short */      break;    case PLUS:    case MINUS:      c = (mode == DFmode) ? 13 : 8;	/* 6/8 on VAX 9000, 16/15 on VAX 2 */      /* Small integer operands can use subl2 and addl2.  */      if ((GET_CODE (XEXP (x, 1)) == CONST_INT)	  && (unsigned HOST_WIDE_INT)(INTVAL (XEXP (x, 1)) + 63) < 127)	fmt = "e";      break;    case IOR:    case XOR:      c = 3;      break;    case AND:      /* AND is special because the first operand is complemented.  */      c = 3;      if (GET_CODE (XEXP (x, 0)) == CONST_INT)	{	  if ((unsigned HOST_WIDE_INT)~INTVAL (XEXP (x, 0)) > 63)	    c = 4;	  fmt = "e";	  i = 1;	}      break;    case NEG:      if (mode == DFmode)	return 9;      else if (mode == SFmode)	return 6;      else if (mode == DImode)	return 4;    case NOT:      return 2;    case ZERO_EXTRACT:    case SIGN_EXTRACT:      c = 15;      break;    case MEM:      if (mode == DImode || mode == DFmode)	c = 5;				/* 7 on VAX 2 */      else	c = 3;				/* 4 on VAX 2 */      x = XEXP (x, 0);      if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)	return c;      return c + vax_address_cost (x);    default:      c = 3;      break;    }  /* Now look inside the expression.  Operands which are not registers or     short constants add to the cost.     FMT and I may have been adjusted in the switch above for instructions     which require special handling */  while (*fmt++ == 'e')    {      register rtx op = XEXP (x, i++);      code = GET_CODE (op);      /* A NOT is likely to be found as the first operand of an AND	 (in which case the relevant cost is of the operand inside	 the not) and not likely to be found anywhere else.  */      if (code == NOT)	op = XEXP (op, 0), code = GET_CODE (op);      switch (code)	{	case CONST_INT:	  if ((unsigned HOST_WIDE_INT)INTVAL (op) > 63	      && GET_MODE (x) != QImode)	    c += 1;		/* 2 on VAX 2 */	  break;	case CONST:	case LABEL_REF:	case SYMBOL_REF:	  c += 1;		/* 2 on VAX 2 */	  break;	case CONST_DOUBLE:	  if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)	    {	      /* Registers are faster than floating point constants -- even		 those constants which can be encoded in a single byte.  */	      if (vax_float_literal (op))		c++;	      else		c += (GET_MODE (x) == DFmode) ? 3 : 2;	    }	  else	    {	      if (CONST_DOUBLE_HIGH (op) != 0		  || (unsigned)CONST_DOUBLE_LOW (op) > 63)		c += 2;	    }	  break;	case MEM:	  c += 1;		/* 2 on VAX 2 */	  if (GET_CODE (XEXP (op, 0)) != REG)	    c += vax_address_cost (XEXP (op, 0));	  break;	case REG:	case SUBREG:	  break;	default:	  c += 1;	  break;	}    }  return c;}#if VMS_TARGET/* Additional support code for VMS target.  *//* Linked list of all externals that are to be emitted when optimizing   for the global pointer if they haven't been declared by the end of   the program with an appropriate .comm or initialization.  */staticstruct extern_list {  struct extern_list *next;	/* next external */  const char *name;		/* name of the external */  int size;			/* external's actual size */  int in_const;			/* section type flag */} *extern_head = 0, *pending_head = 0;/* Check whether NAME is already on the external definition list.  If not,   add it to either that list or the pending definition list.  */voidvms_check_external (decl, name, pending)     tree decl;     const char *name;     int pending;{  register struct extern_list *p, *p0;  for (p = extern_head; p; p = p->next)    if (!strcmp (p->name, name))      return;  for (p = pending_head, p0 = 0; p; p0 = p, p = p->next)    if (!strcmp (p->name, name))      {	if (pending)	  return;	/* Was pending, but has now been defined; move it to other list.  */	if (p == pending_head)	  pending_head = p->next;	else	  p0->next = p->next;	p->next = extern_head;	extern_head = p;	return;      }  /* Not previously seen; create a new list entry.  */  p = (struct extern_list *) xmalloc (sizeof (struct extern_list));  p->name = name;  if (pending)    {      /* Save the size and section type and link to `pending' list.  */      p->size = (DECL_SIZE (decl) == 0) ? 0 :	TREE_INT_CST_LOW (size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),				      size_int (BITS_PER_UNIT)));      p->in_const = (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl));      p->next = pending_head;      pending_head = p;    }  else    {      /* Size and section type don't matter; link to `declared' list.  */      p->size = p->in_const = 0;        /* arbitrary init */      p->next = extern_head;      extern_head = p;    }  return;}voidvms_flush_pending_externals (file)     FILE *file;{  register struct extern_list *p;  while (pending_head)    {      /* Move next pending declaration to the "done" list.  */      p = pending_head;      pending_head = p->next;      p->next = extern_head;      extern_head = p;      /* Now output the actual declaration.  */      if (p->in_const)	const_section ();      else	data_section ();      fputs (".comm ", file);      assemble_name (file, p->name);      fprintf (file, ",%d\n", p->size);    }}static voidvms_asm_out_constructor (symbol, priority)     rtx symbol;     int priority ATTRIBUTE_UNUSED;{  fprintf (asm_out_file,".globl $$PsectAttributes_NOOVR$$__gxx_init_1\n");  data_section();  fprintf (asm_out_file,"$$PsectAttributes_NOOVR$$__gxx_init_1:\n\t.long\t");  assemble_name (asm_out_file, XSTR (symbol, 0));  fputc ('\n', asm_out_file);}static voidvms_asm_out_destructor (symbol, priority)     rtx symbol;     int priority ATTRIBUTE_UNUSED;{  fprintf (asm_out_file,".globl $$PsectAttributes_NOOVR$$__gxx_clean_1\n");  data_section();  fprintf (asm_out_file,"$$PsectAttributes_NOOVR$$__gxx_clean_1:\n\t.long\t");  assemble_name (asm_out_file, XSTR (symbol, 0));  fputc ('\n', asm_out_file);}static voidvms_select_section (exp, reloc, align)     tree exp;     int reloc ATTRIBUTE_UNUSED;     unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;{  if (TREE_CODE (exp) == VAR_DECL)    {      if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp)	  && DECL_INITIAL (exp)	  && (DECL_INITIAL (exp) == error_mark_node	      || TREE_CONSTANT (DECL_INITIAL (exp))))	{	  if (TREE_PUBLIC (exp))	    const_section ();	  else	    text_section ();	}      else	data_section ();    }  if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')    {      if (TREE_CODE (exp) == STRING_CST && flag_writable_strings)	data_section ();      else	text_section ();    }}/* Make sure that external variables are correctly addressed.  Under VMS   there is some brain damage in the linker that requires us to do this.  */static voidvms_encode_section_info (decl, first)     tree decl;     int first ATTRIBUTE_UNUSED;{  if (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))    SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;}/* This is how to output a command to make the user-level label named NAME   defined for reference from other files.  */static voidvms_globalize_label (stream, name)     FILE *stream;     const char *name;{  default_globalize_label (stream, name);  vms_check_external (NULL_TREE, name, 0);}#endif /* VMS_TARGET *//* Additional support code for VMS host.  *//* ??? This should really be in libiberty; vax.c is a target file.  */#ifdef QSORT_WORKAROUND  /*	Do not use VAXCRTL's qsort() due to a severe bug:  once you've	sorted something which has a size that's an exact multiple of 4	and is longword aligned, you cannot safely sort anything which	is either not a multiple of 4 in size or not longword aligned.	A static "move-by-longword" optimization flag inside qsort() is	never reset.  This is known to affect VMS V4.6 through VMS V5.5-1,	and was finally fixed in VMS V5.5-2.	In this work-around an insertion sort is used for simplicity.	The qsort code from glibc should probably be used instead.   */voidnot_qsort (array, count, size, compare)     void *array;     unsigned count, size;     int (*compare)();{  if (size == sizeof (short))    {      register int i;      register short *next, *prev;      short tmp, *base = array;      for (next = base, i = count - 1; i > 0; i--)	{	  prev = next++;	  if ((*compare)(next, prev) < 0)	    {	      tmp = *next;	      do  *(prev + 1) = *prev;		while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);	      *(prev + 1) = tmp;	    }	}    }  else if (size == sizeof (long))    {      register int i;      register long *next, *prev;      long tmp, *base = array;      for (next = base, i = count - 1; i > 0; i--)	{	  prev = next++;	  if ((*compare)(next, prev) < 0)	    {	      tmp = *next;	      do  *(prev + 1) = *prev;		while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);	      *(prev + 1) = tmp;	    }	}    }  else  /* arbitrary size */    {      register int i;      register char *next, *prev, *tmp = alloca (size), *base = array;      for (next = base, i = count - 1; i > 0; i--)	{   /* count-1 forward iterations */	  prev = next,  next += size;		/* increment front pointer */	  if ((*compare)(next, prev) < 0)	    {	/* found element out of order; move others up then re-insert */	      memcpy (tmp, next, size);		/* save smaller element */	      do { memcpy (prev + size, prev, size); /* move larger elem. up */		   prev -= size;		/* decrement back pointer */		 } while (prev >= base ? (*compare)(tmp, prev) < 0 : 0);	      memcpy (prev + size, tmp, size);	/* restore small element */	    }	}#ifdef USE_C_ALLOCA      alloca (0);#endif    }  return;}#endif /* QSORT_WORKAROUND *//* Return 1 if insn A follows B.  */static intfollows_p (a, b)     rtx a, b;{  register rtx p;  for (p = a; p != b; p = NEXT_INSN (p))    if (! p)      return 1;  return 0;}/* Returns 1 if we know operand OP was 0 before INSN.  */intreg_was_0_p (insn, op)     rtx insn, op;{  rtx link;  return ((link = find_reg_note (insn, REG_WAS_0, 0))	  /* Make sure the insn that stored the 0 is still present	     and doesn't follow INSN in the insn sequence.  */	  && ! INSN_DELETED_P (XEXP (link, 0))	  && GET_CODE (XEXP (link, 0)) != NOTE	  && ! follows_p (XEXP (link, 0), insn)	  /* Make sure cross jumping didn't happen here.  */	  && no_labels_between_p (XEXP (link, 0), insn)	  /* Make sure the reg hasn't been clobbered.  */	  && ! reg_set_between_p (op, XEXP (link, 0), insn));}static voidvax_output_mi_thunk (file, thunk, delta, vcall_offset, function)     FILE *file;     tree thunk ATTRIBUTE_UNUSED;     HOST_WIDE_INT delta;     HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;     tree function;{  fprintf (file, "\t.word 0x0ffc\n");					  fprintf (file, "\taddl2 $");  fprintf (file, HOST_WIDE_INT_PRINT_DEC, delta);  asm_fprintf (file, ",4(%Rap)\n");  fprintf (file, "\tjmp ");						  assemble_name (file,  XSTR (XEXP (DECL_RTL (function), 0), 0));	  fprintf (file, "+2\n");						}

⌨️ 快捷键说明

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