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

📄 cris.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    operation.    Currently a jumble of the old peek-inside-the-insn and the newer    check-cc-attribute methods.  */voidcris_notice_update_cc (rtx exp, rtx insn){  /* Check if user specified "-mcc-init" as a bug-workaround.  FIXME:     TARGET_CCINIT does not work; we must set CC_REVERSED as below.     Several testcases will otherwise fail, for example     gcc.c-torture/execute/20000217-1.c -O0 and -O1.  */  if (TARGET_CCINIT)    {      CC_STATUS_INIT;      return;    }  /* Slowly, we're converting to using attributes to control the setting     of condition-code status.  */  switch (get_attr_cc (insn))    {    case CC_NONE:      /* Even if it is "none", a setting may clobber a previous	 cc-value, so check.  */      if (GET_CODE (exp) == SET)	{	  if (cc_status.value1	      && modified_in_p (cc_status.value1, insn))	    cc_status.value1 = 0;	  if (cc_status.value2	      && modified_in_p (cc_status.value2, insn))	    cc_status.value2 = 0;	}      return;    case CC_CLOBBER:      CC_STATUS_INIT;      break;    case CC_NORMAL:      /* Which means, for:	 (set (cc0) (...)):	 CC is (...).	 (set (reg) (...)):	 CC is (reg) and (...) - unless (...) is 0, then CC does not change.	 CC_NO_OVERFLOW unless (...) is reg or mem.	 (set (mem) (...)):	 CC does not change.	 (set (pc) (...)):	 CC does not change.	 (parallel	  (set (reg1) (mem (bdap/biap)))	  (set (reg2) (bdap/biap))):	 CC is (reg1) and (mem (reg2))	 (parallel	  (set (mem (bdap/biap)) (reg1)) [or 0]	  (set (reg2) (bdap/biap))):	 CC does not change.	 (where reg and mem includes strict_low_parts variants thereof)	 For all others, assume CC is clobbered.	 Note that we do not have to care about setting CC_NO_OVERFLOW,	 since the overflow flag is set to 0 (i.e. right) for	 instructions where it does not have any sane sense, but where	 other flags have meanings.  (This includes shifts; the carry is	 not set by them).	 Note that there are other parallel constructs we could match,	 but we don't do that yet.  */      if (GET_CODE (exp) == SET)	{	  /* FIXME: Check when this happens.  It looks like we should	     actually do a CC_STATUS_INIT here to be safe.  */	  if (SET_DEST (exp) == pc_rtx)	    return;	  /* Record CC0 changes, so we do not have to output multiple	     test insns.  */	  if (SET_DEST (exp) == cc0_rtx)	    {	      cc_status.value1 = SET_SRC (exp);	      cc_status.value2 = 0;	      /* Handle flags for the special btstq on one bit.  */	      if (GET_CODE (SET_SRC (exp)) == ZERO_EXTRACT		  && XEXP (SET_SRC (exp), 1) == const1_rtx)		{		  if (GET_CODE (XEXP (SET_SRC (exp), 0)) == CONST_INT)		    /* Using cmpq.  */		    cc_status.flags = CC_INVERTED;		  else		    /* A one-bit btstq.  */		    cc_status.flags = CC_Z_IN_NOT_N;		}	      else		cc_status.flags = 0;	      if (GET_CODE (SET_SRC (exp)) == COMPARE)		{		  if (!REG_P (XEXP (SET_SRC (exp), 0))		      && XEXP (SET_SRC (exp), 1) != const0_rtx)		    /* For some reason gcc will not canonicalize compare		       operations, reversing the sign by itself if		       operands are in wrong order.  */		    /* (But NOT inverted; eq is still eq.) */		    cc_status.flags = CC_REVERSED;		  /* This seems to be overlooked by gcc.  FIXME: Check again.		     FIXME:  Is it really safe?  */		  cc_status.value2		    = gen_rtx_MINUS (GET_MODE (SET_SRC (exp)),				     XEXP (SET_SRC (exp), 0),				     XEXP (SET_SRC (exp), 1));		}	      return;	    }	  else if (REG_P (SET_DEST (exp))		   || (GET_CODE (SET_DEST (exp)) == STRICT_LOW_PART		       && REG_P (XEXP (SET_DEST (exp), 0))))	    {	      /* A register is set; normally CC is set to show that no		 test insn is needed.  Catch the exceptions.  */	      /* If not to cc0, then no "set"s in non-natural mode give		 ok cc0...  */	      if (GET_MODE_SIZE (GET_MODE (SET_DEST (exp))) > UNITS_PER_WORD		  || GET_MODE_CLASS (GET_MODE (SET_DEST (exp))) == MODE_FLOAT)		{		  /* ... except add:s and sub:s in DImode.  */		  if (GET_MODE (SET_DEST (exp)) == DImode		      && (GET_CODE (SET_SRC (exp)) == PLUS			  || GET_CODE (SET_SRC (exp)) == MINUS))		    {		      cc_status.flags = 0;		      cc_status.value1 = SET_DEST (exp);		      cc_status.value2 = SET_SRC (exp);		      if (cris_reg_overlap_mentioned_p (cc_status.value1,							cc_status.value2))			cc_status.value2 = 0;		      /* Add and sub may set V, which gets us			 unoptimizable results in "gt" and "le" condition			 codes.  */		      cc_status.flags |= CC_NO_OVERFLOW;		      return;		    }		}	      else if (SET_SRC (exp) == const0_rtx)		{		  /* There's no CC0 change when clearing a register or		     memory.  Just check for overlap.  */		  if (cc_status.value1		      && modified_in_p (cc_status.value1, insn))		    cc_status.value1 = 0;		  if (cc_status.value2		      && modified_in_p (cc_status.value2, insn))		    cc_status.value2 = 0;		  return;		}	      else		{		  cc_status.flags = 0;		  cc_status.value1 = SET_DEST (exp);		  cc_status.value2 = SET_SRC (exp);		  if (cris_reg_overlap_mentioned_p (cc_status.value1,						    cc_status.value2))		    cc_status.value2 = 0;		  /* Some operations may set V, which gets us		     unoptimizable results in "gt" and "le" condition		     codes.  */		  if (GET_CODE (SET_SRC (exp)) == PLUS		      || GET_CODE (SET_SRC (exp)) == MINUS		      || GET_CODE (SET_SRC (exp)) == NEG)		    cc_status.flags |= CC_NO_OVERFLOW;		  return;		}	    }	  else if (GET_CODE (SET_DEST (exp)) == MEM		   || (GET_CODE (SET_DEST (exp)) == STRICT_LOW_PART		       && GET_CODE (XEXP (SET_DEST (exp), 0)) == MEM))	    {	      /* When SET to MEM, then CC is not changed (except for		 overlap).  */	      if (cc_status.value1		  && modified_in_p (cc_status.value1, insn))		cc_status.value1 = 0;	      if (cc_status.value2		  && modified_in_p (cc_status.value2, insn))		cc_status.value2 = 0;	      return;	    }	}      else if (GET_CODE (exp) == PARALLEL)	{	  if (GET_CODE (XVECEXP (exp, 0, 0)) == SET	      && GET_CODE (XVECEXP (exp, 0, 1)) == SET	      && REG_P (XEXP (XVECEXP (exp, 0, 1), 0)))	    {	      if (REG_P (XEXP (XVECEXP (exp, 0, 0), 0))		  && GET_CODE (XEXP (XVECEXP (exp, 0, 0), 1)) == MEM)		{		  /* For "move.S [rx=ry+o],rz", say CC reflects		     value1=rz and value2=[rx] */		  cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);		  cc_status.value2		    = replace_equiv_address (XEXP (XVECEXP (exp, 0, 0), 1),					     XEXP (XVECEXP (exp, 0, 1), 0));		  cc_status.flags = 0;		  /* Huh?  A side-effect cannot change the destination		     register.  */		  if (cris_reg_overlap_mentioned_p (cc_status.value1,						    cc_status.value2))		    internal_error ("internal error: sideeffect-insn affecting main effect");		  return;		}	      else if ((REG_P (XEXP (XVECEXP (exp, 0, 0), 1))			|| XEXP (XVECEXP (exp, 0, 0), 1) == const0_rtx)		       && GET_CODE (XEXP (XVECEXP (exp, 0, 0), 0)) == MEM)		{		  /* For "move.S rz,[rx=ry+o]" and "clear.S [rx=ry+o]",		     say flags are not changed, except for overlap.  */		  if (cc_status.value1		      && modified_in_p (cc_status.value1, insn))		    cc_status.value1 = 0;		  if (cc_status.value2		      && modified_in_p (cc_status.value2, insn))		    cc_status.value2 = 0;		  return;		}	    }	}      break;    default:      /* Unknown cc_attr value.  */      abort ();    }  CC_STATUS_INIT;}/* Return != 0 if the return sequence for the current function is short,   like "ret" or "jump [sp+]".  Prior to reloading, we can't tell how   many registers must be saved, so return 0 then.  */intcris_simple_epilogue (void){  int regno;  int reglimit = STACK_POINTER_REGNUM;  int lastreg = -1;  if (! reload_completed      || frame_pointer_needed      || get_frame_size () != 0      || current_function_pretend_args_size      || current_function_args_size      || current_function_outgoing_args_size      || current_function_calls_eh_return      /* If we're not supposed to emit prologue and epilogue, we must	 not emit return-type instructions.  */      || !TARGET_PROLOGUE_EPILOGUE)    return 0;  /* We allow a "movem [sp+],rN" to sit in front if the "jump [sp+]" or     in the delay-slot of the "ret".  */  for (regno = 0; regno < reglimit; regno++)    if ((regs_ever_live[regno] && ! call_used_regs[regno])	|| (regno == (int) PIC_OFFSET_TABLE_REGNUM	    && (current_function_uses_pic_offset_table		/* It is saved anyway, if there would be a gap.  */		|| (flag_pic		    && regs_ever_live[regno + 1]		    && !call_used_regs[regno + 1]))))      {	if (lastreg != regno - 1)	  return 0;	lastreg = regno;      }  return 1;}/* Compute a (partial) cost for rtx X.  Return true if the complete   cost has been computed, and false if subexpressions should be   scanned.  In either case, *TOTAL contains the cost result.  */static boolcris_rtx_costs (rtx x, int code, int outer_code, int *total){  switch (code)    {    case CONST_INT:      {	HOST_WIDE_INT val = INTVAL (x);	if (val == 0)	  *total = 0;	else if (val < 32 && val >= -32)	  *total = 1;	/* Eight or 16 bits are a word and cycle more expensive.  */	else if (val <= 32767 && val >= -32768)	  *total = 2;	/* A 32 bit constant (or very seldom, unsigned 16 bits) costs	   another word.  FIXME: This isn't linear to 16 bits.  */	else	  *total = 4;	return true;      }    case LABEL_REF:      *total = 6;      return true;    case CONST:    case SYMBOL_REF:      /* For PIC, we need a prefix (if it isn't already there),	 and the PIC register.  For a global PIC symbol, we also	 need a read of the GOT.  */      if (flag_pic)	{	  if (cris_got_symbol (x))	    *total = 2 + 4 + 6;	  else	    *total = 2 + 6;	}      else	*total = 6;      return true;    case CONST_DOUBLE:      if (x != CONST0_RTX (GET_MODE (x) == VOIDmode ? DImode : GET_MODE (x)))	*total = 12;      else        /* Make 0.0 cheap, else test-insns will not be used.  */	*total = 0;      return true;    case MULT:      /* Identify values that are no powers of two.  Powers of 2 are         taken care of already and those values should not be changed.  */      if (GET_CODE (XEXP (x, 1)) != CONST_INT          || exact_log2 (INTVAL (XEXP (x, 1)) < 0))	{	  /* If we have a multiply insn, then the cost is between	     1 and 2 "fast" instructions.  */	  if (TARGET_HAS_MUL_INSNS)	    {	      *total = COSTS_N_INSNS (1) + COSTS_N_INSNS (1) / 2;	      return true;	    }	  /* Estimate as 4 + 4 * #ofbits.  */	  *total = COSTS_N_INSNS (132);	  return true;	}      return false;    case UDIV:    case MOD:    case UMOD:    case DIV:      if (GET_CODE (XEXP (x, 1)) != CONST_INT          || exact_log2 (INTVAL (XEXP (x, 1)) < 0))	{	  /* Estimate this as 4 + 8 * #of bits.  */	  *total = COSTS_N_INSNS (260);	  return true;	}      return false;    case AND:      if (GET_CODE (XEXP (x, 1)) == CONST_INT          /* Two constants may actually happen before optimization.  */          && GET_CODE (XEXP (x, 0)) != CONST_INT          && !CONST_OK_FOR_LETTER_P (INTVAL (XEXP (x, 1)), 'I'))	{	  *total = (rtx_cost (XEXP (x, 0), outer_code) + 2		    + 2 * GET_MODE_NUNITS (GET_MODE (XEXP (x, 0))));	  return true;	}      return false;    case ZERO_EXTEND: case SIGN_EXTEND:      *total = rtx_cost (XEXP (x, 0), outer_code);      return true;    default:      return false;    }}/* The ADDRESS_COST worker.  */static intcris_address_cost (rtx x){  /* The metric to use for the cost-macros is unclear.     The metric used here is (the number of cycles needed) / 2,     where we consider equal a cycle for a word of code and a cycle to     read memory.  */  /* The cheapest addressing modes get 0, since nothing extra is needed.  */  if (BASE_OR_AUTOINCR_P (x))    return 0;  /* An indirect mem must be a DIP.  This means two bytes extra for code,     and 4 bytes extra for memory read, i.e.  (2 + 4) / 2.  */  if (GET_CODE (x) == MEM)    return (2 + 4) / 2;  /* Assume (2 + 4) / 2 for a single constant; a dword, since it needs     an extra DIP prefix and 4 bytes of constant in most cases.     For PIC and a symbol with a GOT entry, we double the cost since we     add a [rPIC+...] offset.  A GOT-less symbol uses a BDAP prefix     equivalent to the DIP prefix for non-PIC, hence the same cost.  */  if (CONSTANT_P (x))    return flag_pic && cris_got_symbol (x) ? 2 * (2 + 4) / 2 : (2 + 4) / 2;  /* Handle BIAP and BDAP prefixes.  */  if (GET_CODE (x) == PLUS)    {      rtx tem1 = XEXP (x, 0);      rtx tem2 = XEXP (x, 1);    /* A BIAP is 2 extra bytes for the prefix insn, nothing more.  We       recognize the typical MULT which is always in tem1 because of       insn canonicalization.  */    if ((GET_CODE (tem1) == MULT && BIAP_INDEX_P (tem1))	|| REG_P (tem1))      return 2 / 2;    /* A BDAP (quick) is 2 extra bytes.  Any c

⌨️ 快捷键说明

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