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

📄 arm.c

📁 这是一个linux 嵌入式系统中很重要的GCC编译器程序
💻 C
📖 第 1 页 / 共 5 页
字号:
rtxlegitimize_pic_address (orig, mode, reg)     rtx orig;     enum machine_mode mode;     rtx reg;{  if (GET_CODE (orig) == SYMBOL_REF)    {      rtx pic_ref, address;      rtx insn;      int subregs = 0;      if (reg == 0)	{	  if (reload_in_progress || reload_completed)	    abort ();	  else	    reg = gen_reg_rtx (Pmode);	  subregs = 1;	}#ifdef AOF_ASSEMBLER      /* The AOF assembler can generate relocations for these directly, and	 understands that the PIC register has to be added into the offset.	 */      insn = emit_insn (gen_pic_load_addr_based (reg, orig));#else      if (subregs)	address = gen_reg_rtx (Pmode);      else	address = reg;      emit_insn (gen_pic_load_addr (address, orig));      pic_ref = gen_rtx_MEM (Pmode,			     gen_rtx_PLUS (Pmode, pic_offset_table_rtx,					   address));      RTX_UNCHANGING_P (pic_ref) = 1;      insn = emit_move_insn (reg, pic_ref);#endif      current_function_uses_pic_offset_table = 1;      /* Put a REG_EQUAL note on this insn, so that it can be optimized	 by loop.  */      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,					    REG_NOTES (insn));      return reg;    }  else if (GET_CODE (orig) == CONST)    {      rtx base, offset;      if (GET_CODE (XEXP (orig, 0)) == PLUS	  && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)	return orig;      if (reg == 0)	{	  if (reload_in_progress || reload_completed)	    abort ();	  else	    reg = gen_reg_rtx (Pmode);	}      if (GET_CODE (XEXP (orig, 0)) == PLUS)	{	  base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);	  offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,					   base == reg ? 0 : reg);	}      else	abort ();      if (GET_CODE (offset) == CONST_INT)	{	  /* The base register doesn't really matter, we only want to	     test the index for the appropriate mode.  */	  GO_IF_LEGITIMATE_INDEX (mode, 0, offset, win);	  if (! reload_in_progress && ! reload_completed)	    offset = force_reg (Pmode, offset);	  else	    abort ();	win:	  if (GET_CODE (offset) == CONST_INT)	    return plus_constant_for_output (base, INTVAL (offset));	}      if (GET_MODE_SIZE (mode) > 4	  && (GET_MODE_CLASS (mode) == MODE_INT	      || TARGET_SOFT_FLOAT))	{	  emit_insn (gen_addsi3 (reg, base, offset));	  return reg;	}      return gen_rtx_PLUS (Pmode, base, offset);    }  else if (GET_CODE (orig) == LABEL_REF)    current_function_uses_pic_offset_table = 1;  return orig;}static rtx pic_rtx;intis_pic(x)     rtx x;{  if (x == pic_rtx)    return 1;  return 0;}voidarm_finalize_pic (){#ifndef AOF_ASSEMBLER  rtx l1, pic_tmp, pic_tmp2, seq;  rtx global_offset_table;  if (current_function_uses_pic_offset_table == 0)    return;  if (! flag_pic)    abort ();  start_sequence ();  l1 = gen_label_rtx ();  global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");  /* On the ARM the PC register contains 'dot + 8' at the time of the     addition.  */  pic_tmp = plus_constant (gen_rtx_LABEL_REF (Pmode, l1), 8);  if (GOT_PCREL)    pic_tmp2 = gen_rtx_CONST (VOIDmode,			    gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx));  else    pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table);  pic_rtx = gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp));    emit_insn (gen_pic_load_addr (pic_offset_table_rtx, pic_rtx));  emit_insn (gen_pic_add_dot_plus_eight (pic_offset_table_rtx, l1));  seq = gen_sequence ();  end_sequence ();  emit_insn_after (seq, get_insns ());  /* Need to emit this whether or not we obey regdecls,     since setjmp/longjmp can cause life info to screw up.  */  emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));#endif /* AOF_ASSEMBLER */}#define REG_OR_SUBREG_REG(X)						\  (GET_CODE (X) == REG							\   || (GET_CODE (X) == SUBREG && GET_CODE (SUBREG_REG (X)) == REG))#define REG_OR_SUBREG_RTX(X)			\   (GET_CODE (X) == REG ? (X) : SUBREG_REG (X))#define ARM_FRAME_RTX(X)				\  ((X) == frame_pointer_rtx || (X) == stack_pointer_rtx	\   || (X) == arg_pointer_rtx)intarm_rtx_costs (x, code)     rtx x;     enum rtx_code code;{  enum machine_mode mode = GET_MODE (x);  enum rtx_code subcode;  int extra_cost;  switch (code)    {    case MEM:      /* Memory costs quite a lot for the first word, but subsequent words	 load at the equivalent of a single insn each.  */      return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD)	      + (CONSTANT_POOL_ADDRESS_P (x) ? 4 : 0));    case DIV:    case MOD:      return 100;    case ROTATE:      if (mode == SImode && GET_CODE (XEXP (x, 1)) == REG)	return 4;      /* Fall through */    case ROTATERT:      if (mode != SImode)	return 8;      /* Fall through */    case ASHIFT: case LSHIFTRT: case ASHIFTRT:      if (mode == DImode)	return (8 + (GET_CODE (XEXP (x, 1)) == CONST_INT ? 0 : 8)		+ ((GET_CODE (XEXP (x, 0)) == REG 		    || (GET_CODE (XEXP (x, 0)) == SUBREG			&& GET_CODE (SUBREG_REG (XEXP (x, 0))) == REG))		   ? 0 : 8));      return (1 + ((GET_CODE (XEXP (x, 0)) == REG		    || (GET_CODE (XEXP (x, 0)) == SUBREG			&& GET_CODE (SUBREG_REG (XEXP (x, 0))) == REG))		   ? 0 : 4)	      + ((GET_CODE (XEXP (x, 1)) == REG		  || (GET_CODE (XEXP (x, 1)) == SUBREG		      && GET_CODE (SUBREG_REG (XEXP (x, 1))) == REG)		  || (GET_CODE (XEXP (x, 1)) == CONST_INT))		 ? 0 : 4));    case MINUS:      if (mode == DImode)	return (4 + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 8)		+ ((REG_OR_SUBREG_REG (XEXP (x, 0))		    || (GET_CODE (XEXP (x, 0)) == CONST_INT		       && const_ok_for_arm (INTVAL (XEXP (x, 0)))))		   ? 0 : 8));      if (GET_MODE_CLASS (mode) == MODE_FLOAT)	return (2 + ((REG_OR_SUBREG_REG (XEXP (x, 1))		      || (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE			  && const_double_rtx_ok_for_fpu (XEXP (x, 1))))		     ? 0 : 8)		+ ((REG_OR_SUBREG_REG (XEXP (x, 0))		    || (GET_CODE (XEXP (x, 0)) == CONST_DOUBLE			&& const_double_rtx_ok_for_fpu (XEXP (x, 0))))		   ? 0 : 8));      if (((GET_CODE (XEXP (x, 0)) == CONST_INT	    && const_ok_for_arm (INTVAL (XEXP (x, 0)))	    && REG_OR_SUBREG_REG (XEXP (x, 1))))	  || (((subcode = GET_CODE (XEXP (x, 1))) == ASHIFT	       || subcode == ASHIFTRT || subcode == LSHIFTRT	       || subcode == ROTATE || subcode == ROTATERT	       || (subcode == MULT		   && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT		   && ((INTVAL (XEXP (XEXP (x, 1), 1)) &			(INTVAL (XEXP (XEXP (x, 1), 1)) - 1)) == 0)))	      && REG_OR_SUBREG_REG (XEXP (XEXP (x, 1), 0))	      && (REG_OR_SUBREG_REG (XEXP (XEXP (x, 1), 1))		  || GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT)	      && REG_OR_SUBREG_REG (XEXP (x, 0))))	return 1;      /* Fall through */    case PLUS:       if (GET_MODE_CLASS (mode) == MODE_FLOAT)	return (2 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 8)		+ ((REG_OR_SUBREG_REG (XEXP (x, 1))		    || (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE			&& const_double_rtx_ok_for_fpu (XEXP (x, 1))))		   ? 0 : 8));      /* Fall through */    case AND: case XOR: case IOR:       extra_cost = 0;      /* Normally the frame registers will be spilt into reg+const during	 reload, so it is a bad idea to combine them with other instructions,	 since then they might not be moved outside of loops.  As a compromise	 we allow integration with ops that have a constant as their second	 operand.  */      if ((REG_OR_SUBREG_REG (XEXP (x, 0))	   && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x, 0)))	   && GET_CODE (XEXP (x, 1)) != CONST_INT)	  || (REG_OR_SUBREG_REG (XEXP (x, 0))	      && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x, 0)))))	extra_cost = 4;      if (mode == DImode)	return (4 + extra_cost + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 8)		+ ((REG_OR_SUBREG_REG (XEXP (x, 1))		    || (GET_CODE (XEXP (x, 1)) == CONST_INT			&& const_ok_for_op (INTVAL (XEXP (x, 1)), code)))		   ? 0 : 8));      if (REG_OR_SUBREG_REG (XEXP (x, 0)))	return (1 + (GET_CODE (XEXP (x, 1)) == CONST_INT ? 0 : extra_cost)		+ ((REG_OR_SUBREG_REG (XEXP (x, 1))		    || (GET_CODE (XEXP (x, 1)) == CONST_INT			&& const_ok_for_op (INTVAL (XEXP (x, 1)), code)))		   ? 0 : 4));      else if (REG_OR_SUBREG_REG (XEXP (x, 1)))	return (1 + extra_cost		+ ((((subcode = GET_CODE (XEXP (x, 0))) == ASHIFT		     || subcode == LSHIFTRT || subcode == ASHIFTRT		     || subcode == ROTATE || subcode == ROTATERT		     || (subcode == MULT			 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT			 && ((INTVAL (XEXP (XEXP (x, 0), 1)) &			      (INTVAL (XEXP (XEXP (x, 0), 1)) - 1)) == 0)))		    && (REG_OR_SUBREG_REG (XEXP (XEXP (x, 0), 0)))		    && ((REG_OR_SUBREG_REG (XEXP (XEXP (x, 0), 1)))			|| GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))		   ? 0 : 4));      return 8;    case MULT:      /* There is no point basing this on the tuning, since it is always the	 fast variant if it exists at all */      if (arm_fast_multiply && mode == DImode	  && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))	  && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND	      || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))	return 8;      if (GET_MODE_CLASS (mode) == MODE_FLOAT	  || mode == DImode)	return 30;      if (GET_CODE (XEXP (x, 1)) == CONST_INT)	{	  unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1))				      & (unsigned HOST_WIDE_INT) 0xffffffff);	  int add_cost = const_ok_for_arm (i) ? 4 : 8;	  int j;	  /* Tune as appropriate */ 	  int booth_unit_size = ((tune_flags & FL_FAST_MULT) ? 8 : 2);	  	  for (j = 0; i && j < 32; j += booth_unit_size)	    {	      i >>= booth_unit_size;	      add_cost += 2;	    }	  return add_cost;	}      return (((tune_flags & FL_FAST_MULT) ? 8 : 30)	      + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)	      + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4));    case TRUNCATE:      if (arm_fast_multiply && mode == SImode	  && GET_CODE (XEXP (x, 0)) == LSHIFTRT	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT	  && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))	      == GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)))	  && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND	      || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND))	return 8;      return 99;    case NEG:      if (GET_MODE_CLASS (mode) == MODE_FLOAT)	return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 6);      /* Fall through */    case NOT:      if (mode == DImode)	return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4);      return 1 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4);    case IF_THEN_ELSE:      if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)	return 14;      return 2;    case COMPARE:      return 1;    case ABS:      return 4 + (mode == DImode ? 4 : 0);    case SIGN_EXTEND:      if (GET_MODE (XEXP (x, 0)) == QImode)	return (4 + (mode == DImode ? 4 : 0)		+ (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));      /* Fall through */    case ZERO_EXTEND:      switch (GET_MODE (XEXP (x, 0)))	{	case QImode:	  return (1 + (mode == DImode ? 4 : 0)		  + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));	case HImode:	  return (4 + (mode == DImode ? 4 : 0)		  + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));	case SImode:	  return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));	default:	  break;	}      abort ();    default:      return 99;    }}intarm_adjust_cost (insn, link, dep, cost)     rtx insn;     rtx link;     rtx dep;     int cost;{  rtx i_pat, d_pat;  /* XXX This is not strictly true for the FPA. */  if (REG_NOTE_KIND(link) == REG_DEP_ANTI      || REG_NOTE_KIND(link) == REG_DEP_OUTPUT)    return 0;  if ((i_pat = single_set (insn)) != NULL      && GET_CODE (SET_SRC (i_pat)) == MEM      && (d_pat = single_set (dep)) != NULL      && GET_CODE (SET_DEST (d_pat)) == MEM)    {      /* This is a load after a store, there is no conflict if the load reads	 from a cached area.  Assume that loads from the stack, and from the	 constant pool are cached, and that others will miss.  This is a 	 hack. */      /*       debug_rtx (insn);      debug_rtx (dep);      debug_rtx (link);      fprintf (stderr, "costs %d\n", cost); */      if (CONSTANT_POOL_ADDRESS_P (XEXP (SET_SRC (i_pat), 0))	  || reg_mentioned_p (stack_pointer_rtx, XEXP (SET_SRC (i_pat), 0))	  || reg_mentioned_p (frame_pointer_rtx, XEXP (SET_SRC (i_pat), 0))	  || reg_mentioned_p (hard_frame_pointer_rtx, 			      XEXP (SET_SRC (i_pat), 0)))	{/* 	  fprintf (stderr, "***** Now 1\n"); */	  return 1;	}    }  return cost;}/* This code has been fixed for cross compilation. */static int fpa_consts_inited = 0;char *strings_fpa[8] = {  "0",   "1",   "2",   "3",  "4",   "5",   "0.5", "10"};static REAL_VALUE_TYPE values_fpa[8];static voidinit_fpa_table (){  int i;  REAL_VALUE_TYPE r;  for (i = 0; i < 8; i++)    {      r = REAL_VALUE_ATOF (strings_fpa[i], DFmode);      values_fpa[i] = r;    }  fpa_consts_inited = 1;}/* Return TRUE if rtx X is a valid immediate FPU constant. */intconst_double_rtx_ok_for_fpu (x)     rtx x;{  REAL_VALUE_TYPE r;  int i;  

⌨️ 快捷键说明

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