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

📄 cris.c

📁 gcc-you can use this code to learn something about gcc, and inquire further into linux,
💻 C
📖 第 1 页 / 共 5 页
字号:
	 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		       && cris_reg_overlap_mentioned_p (SET_DEST (exp),							cc_status.value1)))		    cc_status.value1 = 0;		  if ((cc_status.value2		       && cris_reg_overlap_mentioned_p (SET_DEST (exp),							cc_status.value2)))		    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		   && cris_reg_overlap_mentioned_p (SET_DEST (exp),						    cc_status.value1)))		cc_status.value1 = 0;	      if ((cc_status.value2		   && cris_reg_overlap_mentioned_p (SET_DEST (exp),						    cc_status.value2)))		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		    = gen_rtx_MEM (GET_MODE (XEXP (XVECEXP (exp, 0, 0), 0)),				   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		      && cris_reg_overlap_mentioned_p (XEXP						       (XVECEXP							(exp, 0, 0), 0),						       cc_status.value1))		    cc_status.value1 = 0;		  if (cc_status.value1		      && cris_reg_overlap_mentioned_p (XEXP						       (XVECEXP							(exp, 0, 1), 0),						       cc_status.value1))		    cc_status.value1 = 0;		  if (cc_status.value2		      && cris_reg_overlap_mentioned_p (XEXP						       (XVECEXP							(exp, 0, 0), 0),						       cc_status.value2))		    cc_status.value2 = 0;		  if (cc_status.value2		      && cris_reg_overlap_mentioned_p (XEXP						       (XVECEXP							(exp, 0, 1), 0),						       cc_status.value2))		    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 (){  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;}/* The ADDRESS_COST worker.  */intcris_address_cost (x)     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 constant operand to the       PLUS is always found in tem2.  */    if (GET_CODE (tem2) == CONST_INT	&& INTVAL (tem2) < 128 && INTVAL (tem2) >= -128)      return 2 / 2;    /* A BDAP -32768 .. 32767 is like BDAP quick, but with 2 extra       bytes.  */    if (GET_CODE (tem2) == CONST_INT	&& CONST_OK_FOR_LETTER_P (INTVAL (tem2), 'L'))      return (2 + 2) / 2;    /* A BDAP with some other constant is 2 bytes extra.  */    if (CONSTANT_P (tem2))      return (2 + 2 + 2) / 2;    /* BDAP with something indirect should have a higher cost than       BIAP with register.   FIXME: Should it cost like a MEM or more?  */    /* Don't need to check it, it's the only one left.       FIXME:  There was a REG test missing, perhaps there are others.       Think more.  */    return (2 + 2 + 2) / 2;  }  /* What else?  Return a high cost.  It matters only for valid     addressing modes.  */  return 10;}/* Check various objections to the side-effect.  Used in the test-part   of an anonymous insn describing an insn with a possible side-effect.   Returns nonzero if the implied side-effect is ok.   code     : PLUS or MULT   ops	    : An array of rtx:es. lreg, rreg, rval,	      The variables multop and other_op are indexes into this,	      or -1 if they are not applicable.   lreg     : The register that gets assigned in the side-effect.   rreg     : One register in the side-effect expression   rval     : The other register, or an int.   multop   : An integer to multiply rval with.   other_op : One of the entities of the main effect,	      whose mode we must consider.  */intcris_side_effect_mode_ok (code, ops, lreg, rreg, rval, multop, other_op)     enum rtx_code code;     rtx *ops;     int lreg, rreg, rval, multop, other_op;{  /* Find what value to multiply with, for rx =ry + rz * n.  */  int mult = multop < 0 ? 1 : INTVAL (ops[multop]);  rtx reg_rtx = ops[rreg];  rtx val_rtx = ops[rval];  /* The operands may be swapped.  Canonicalize them in reg_rtx and     val_rtx, where reg_rtx always is a reg (for this constraint to     match).  */  if (! BASE_P (reg_rtx))    reg_rtx = val_rtx, val_rtx = ops[rreg];  /* Don't forget to check that reg_rtx really is a reg.  If it isn't,     we have no business.  */  if (! BASE_P (reg_rtx))    return 0;  /* Don't do this when -mno-split.  */  if (!TARGET_SIDE_EFFECT_PREFIXES)    return 0;  /* The mult expression may be hidden in lreg.  FIXME:  Add more     commentary about that.  */  if (GET_CODE (val_rtx) == MULT)    {      mult = INTVAL (XEXP (val_rtx, 1));      val_rtx = XEXP (val_rtx, 0);      code = MULT;    }  /* First check the "other operand".  */  if (other_op >= 0)    {      if (GET_MODE_SIZE (GET_MODE (ops[other_op])) > UNITS_PER_WORD)	return 0;      /* Check if the lvalue register is the same as the "other	 operand".  If so, the result is undefined and we shouldn't do	 this.  FIXME:  Check again.  */      if ((BASE_P (ops[lreg])	   && BASE_P (ops[other_op])	   && REGNO (ops[lreg]) == REGNO (ops[other_op]))	  || rtx_equal_p (ops[other_op], ops[lreg]))      return 0;    }  /* Do not accept frame_pointer_rtx as any operand.  */  if (ops[lreg] == frame_pointer_rtx || ops[rreg] == frame_pointer_rtx      || ops[rval] == frame_pointer_rtx      || (other_op >= 0 && ops[other_op] == frame_pointer_rtx))    return 0;  if (code == PLUS      && ! BASE_P (val_rtx))    {      /* Do not allow rx = rx + n if a normal add or sub with same size	 would do.  */      if (rtx_equal_p (ops[lreg], reg_rtx)	  && GET_CODE (val_rtx) == CONST_INT	  && (INTVAL (val_rtx) <= 63 && INTVAL (val_rtx) >= -63))	return 0;      /* Check allowed cases, like [r(+)?].[bwd] and const.	 A symbol is not allowed with PIC.  */      if (CONSTANT_P (val_rtx))	return flag_pic == 0 || cris_symbol (val_rtx) == 0;      if (GET_CODE (val_rtx) == MEM	  && BASE_OR_AUTOINCR_P (XEXP (val_rtx, 0)))	return 1;      if (GET_CODE (val_rtx) == SIGN_EXTEND	  && GET_CODE (XEXP (val_rtx, 0)) == MEM	  && BASE_OR_AUTOINCR_P (XEXP (XEXP (val_rtx, 0), 0)))	return 1;      /* If we got here, it's not a valid addressing mode.  */      return 0;    }  else if (code == MULT	   || (code == PLUS && BASE_P (val_rtx)))    {      /* Do not allow rx = rx + ry.S, since it doesn't give better code.  */      if (rtx_equal_p (ops[lreg], reg_rtx)	  || (mult == 1 && rtx_equal_p (ops[lreg], val_rtx)))	return 0;      /* Do not allow bad multiply-values.  */      if (mult != 1 && mult != 2 && mult != 4)	return 0;      /* Only allow  r + ...  */      if (! BASE_P (reg_rtx))	return 0;      /* If we got here, all seems ok.	 (All checks need to be done above).  */      return 1;    }  /* If we get here, the caller got its initial tests wrong.  */  internal_error ("internal error: cris_side_effect_mode_ok with bad operands");}/* The function reg_overlap_mentioned_p in CVS (still as of 2001-05-16)   does not handle the case where the IN operand is strict_low_part; it   does handle it for X.  Test-case in Axis-20010516.  This function takes   care of that for THIS port.  FIXME: strict_l

⌨️ 快捷键说明

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