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

📄 a29k.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 3 页
字号:
      break;    }}/* Given INSN, which is either an INSN or a SEQUENCE generated to   perform a memory operation, look for any MEMs in either a SET_DEST or   a SET_SRC and copy the in-struct, unchanging, and volatile flags from   REF into each of the MEMs found.  If REF is not a MEM, don't do   anything.  */voida29k_set_memflags (insn, ref)     rtx insn;     rtx ref;{  /* Note that it is always safe to get these flags, though they won't     be what we think if REF is not a MEM.  */  int in_struct_p = MEM_IN_STRUCT_P (ref);  int scalar_p = MEM_SCALAR_P (ref);  int volatile_p = MEM_VOLATILE_P (ref);  int unchanging_p = RTX_UNCHANGING_P (ref);  if (GET_CODE (ref) != MEM      || (! in_struct_p && ! volatile_p && ! unchanging_p))    return;  a29k_set_memflags_1 (insn, in_struct_p, scalar_p, volatile_p, unchanging_p);}/* Return 1 if OP is a comparison operator that we have in floating-point.  */intfp_comparison_operator (op, mode)     rtx op;     enum machine_mode mode;{  return ((mode == VOIDmode || mode == GET_MODE (op))	  && (GET_CODE (op) == EQ || GET_CODE (op) == GT ||	      GET_CODE (op) == GE));}/* Return 1 if OP is a valid branch comparison.  */intbranch_operator (op, mode)     rtx op;     enum machine_mode mode;{  return ((mode == VOIDmode || mode == GET_MODE (op))	  && (GET_CODE (op) == GE || GET_CODE (op) == LT));}/* Return 1 if OP is a load multiple operation.  It is known to be a   PARALLEL and the first three sections will be tested.  */intload_multiple_operation (op, mode)     rtx op;     enum machine_mode mode;{  int count = XVECLEN (op, 0) - 2;  int dest_regno;  rtx src_addr;  int i;  /* Perform a quick check so we don't blow up below.  */  if (count <= 1      || GET_CODE (XVECEXP (op, 0, 0)) != SET      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)    return 0;  dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));  src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);  for (i = 1; i < count; i++)    {      rtx elt = XVECEXP (op, 0, i + 2);      if (GET_CODE (elt) != SET	  || GET_CODE (SET_DEST (elt)) != REG	  || GET_MODE (SET_DEST (elt)) != SImode	  || REGNO (SET_DEST (elt)) != dest_regno + i	  || GET_CODE (SET_SRC (elt)) != MEM	  || GET_MODE (SET_SRC (elt)) != SImode	  || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS	  || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)	  || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT	  || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4)	return 0;    }  return 1;}/* Similar, but tests for store multiple.  */intstore_multiple_operation (op, mode)     rtx op;     enum machine_mode mode;{  int num_special = TARGET_NO_STOREM_BUG ? 2 : 1;  int count = XVECLEN (op, 0) - num_special;  int src_regno;  rtx dest_addr;  int i;  /* Perform a quick check so we don't blow up below.  */  if (count <= 1      || GET_CODE (XVECEXP (op, 0, 0)) != SET      || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM      || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)    return 0;  src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));  dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);  for (i = 1; i < count; i++)    {      rtx elt = XVECEXP (op, 0, i + num_special);      if (GET_CODE (elt) != SET	  || GET_CODE (SET_SRC (elt)) != REG	  || GET_MODE (SET_SRC (elt)) != SImode	  || REGNO (SET_SRC (elt)) != src_regno + i	  || GET_CODE (SET_DEST (elt)) != MEM	  || GET_MODE (SET_DEST (elt)) != SImode	  || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS	  || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)	  || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT	  || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4)	return 0;    }  return 1;}/* Given a special register REG and MASK, a value being masked against a   quantity to which the special register is set, return 1 if the masking   operation is built-in to the setting of that special register.  */intmasks_bits_for_special (reg, mask)     rtx reg;     rtx mask;{   int needed_mask_value;  if (GET_CODE (reg) != REG || GET_CODE (mask) != CONST_INT)    abort ();  switch (REGNO (reg))    {    case R_BP:    case R_INT:      needed_mask_value = 3;      break;    case R_FC:      needed_mask_value = 31;      break;    case R_CR:    case R_LRU:      needed_mask_value = 255;      break;    case R_FPE:      needed_mask_value = 511;      break;    case R_MMU:      needed_mask_value = 0x3ff;      break;    case R_OPS:    case R_CPS:    case R_RBP:    case R_FPS:      needed_mask_value = 0xffff;      break;    case R_VAB:      needed_mask_value = 0xffff0000;      break;    case R_Q:    case R_CFG:    case R_CHA:    case R_CHD:    case R_CHC:    case R_TMC:    case R_TMR:    case R_PC0:    case R_PC1:    case R_PC2:      return 0;    default:      abort ();    }   return (INTVAL (mask) & ~ needed_mask_value) == 0;}/* Return nonzero if this label is that of the return point, but there is   a non-null epilogue.  */intepilogue_operand (op, mode)     rtx op;     enum machine_mode mode;{  return next_active_insn (op) == 0 && a29k_first_epilogue_insn != 0;}/* Return the register class of a scratch register needed to copy IN into   or out of a register in CLASS in MODE.  If it can be done directly,   NO_REGS is returned.  */enum reg_classsecondary_reload_class (class, mode, in)     enum reg_class class;     enum machine_mode mode;     rtx in;{  int regno = -1;  enum rtx_code code = GET_CODE (in);  if (! CONSTANT_P (in))    {      regno = true_regnum (in);      /* A pseudo is the same as memory.  */      if (regno == -1 || regno >= FIRST_PSEUDO_REGISTER)	code = MEM;    }  /* If we are transferring between memory and a multi-word mode, we need     CR.  */  if (code == MEM && GET_MODE_SIZE (mode) > UNITS_PER_WORD)    return CR_REGS;  /* If between memory and a mode smaller than a word without DW being     enabled, we need BP.  */  if (code == MEM && ! TARGET_DW_ENABLE      && GET_MODE_SIZE (mode) < UNITS_PER_WORD)    return BP_REGS;  /* Otherwise, we can place anything into GENERAL_REGS and can put     GENERAL_REGS into anything.  */  if (class == GENERAL_REGS      || (regno != -1	  && (regno < R_BP	      || (regno >= R_KR (0) && regno <= R_KR (31)))))    return NO_REGS;  /* We can place 16-bit constants into a special register.  */  if (code == CONST_INT      && (GET_MODE_BITSIZE (mode) <= 16 || (unsigned) INTVAL (in) <= 65535)      && (class == BP_REGS || class == Q_REGS || class == SPECIAL_REGS))    return NO_REGS;  /* Otherwise, we need GENERAL_REGS.  */  return GENERAL_REGS;}/* START is the zero-based incoming argument register index used (0 is 160,   i.e., the first incoming argument register) and COUNT is the number used.   Mark the corresponding incoming registers as neither fixed nor call used.   For each register used for incoming arguments, we have one less local   register that can be used.  So also mark some high-numbered registers as   fixed.   Return the first register number to use for the argument.  */intincoming_reg (start, count)     int start;     int count;{  int i;  /* We only use 16 argument registers, so truncate at the end of the     area.  */  if (start + count > 16)    count = 16 - start;  if (! TARGET_NO_REUSE_ARGS)    /* Mark all the used registers as not fixed and saved over calls.  */    for (i = R_AR (start); i < R_AR (start + count); i++)      {	fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 0;	CLEAR_HARD_REG_BIT (fixed_reg_set, i);	CLEAR_HARD_REG_BIT (call_used_reg_set, i);	CLEAR_HARD_REG_BIT (call_fixed_reg_set, i);      }  /* Shorten the maximum size of the frame.     Remember that R_AR(-1,-2) are place holders for the caller's lr0,lr1.     Make sure to keep the frame rounded to an even boundary.  Rounding up     to an 8 byte boundary will use a slot.  Otherwise a frame with 121 local     regs and 5 arguments will overrun the stack (121+1 + 5 + 2 > 128).  */  /* ??? An alternative would be to never allocate one reg.  */  for (i = (R_AR (0) - 2 - start - count) & ~1; i < R_AR (0) - 2 - start; i++)    {      fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1;      SET_HARD_REG_BIT (fixed_reg_set, i);      SET_HARD_REG_BIT (call_used_reg_set, i);      SET_HARD_REG_BIT (call_fixed_reg_set, i);    }  return R_AR (start);}/* Add CLOBBERs to CALL_INSN_FUNCTION_USAGE chain of INSN indicating   that LR2 up to, but not including, OP are clobbered.  If OP is   zero, indicate all parameter registers are clobbered.  */voida29k_clobbers_to (insn, op)     rtx insn;     rtx op;{  int i;  int high_regno;  if (op == 0)    high_regno = R_LR (18);  else if (GET_CODE (op) != REG || REGNO (op) < R_LR (0)	   || REGNO (op) > R_LR (18))    abort ();  else    high_regno = REGNO (op);  for (i = R_LR (2); i < high_regno; i++)    CALL_INSN_FUNCTION_USAGE (insn)      = gen_rtx (EXPR_LIST, VOIDmode,		 gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, i)),		 CALL_INSN_FUNCTION_USAGE (insn));}/* These routines are used in finding insns to fill delay slots in the   epilogue.  *//* Return 1 if the current function will adjust the register stack.  */intneeds_regstack_p (){  int i;  rtx insn;  if (frame_pointer_needed)    return 1;  /* If any local register is used, we need to adjust the regstack.  */  for (i = R_LR (127); i >= R_LR (0); i --)    if (regs_ever_live[i])      return 1;  /* We need a register stack if we make any calls.  */  for (insn = get_insns (); insn; insn = next_insn (insn))    if (GET_CODE (insn) == CALL_INSN	|| (GET_CODE (insn) == INSN	    && GET_CODE (PATTERN (insn)) == SEQUENCE	    && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN))      return 1;  /* Otherwise, we don't.  */  return 0;}/* Return 1 if X uses a local register.  */intuses_local_reg_p (x)     rtx x;{  char *fmt;  int i, j;  switch (GET_CODE (x))    {    case REG:      return REGNO (x) >= R_LR (0) && REGNO (x) <= R_FP;    case CONST_INT:    case CONST:    case PC:    case CC0:    case LABEL_REF:    case SYMBOL_REF:      return 0;    }  fmt = GET_RTX_FORMAT (GET_CODE (x));  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	{	  if (uses_local_reg_p (XEXP (x, i)))	    return 1;	}      else if (fmt[i] == 'E')	{	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)	    if (uses_local_reg_p (XVECEXP (x, i, j)))	      return 1;	}    }  return 0;}/* Returns 1 if this function is known to have a null epilogue.  */intnull_epilogue (){  return (reload_completed && ! needs_regstack_p ()	  && get_frame_size () == 0	  && current_function_pretend_args_size == 0);}/* Write out the assembler form of an operand.  Recognize the following   special options:	%N means write the low-order 8 bits of the negative of the constant	%Q means write a QImode operand (truncate constants to 8 bits)	%M means write the low-order 16 bits of the constant	%m means write the low-order 16 bits shifted left 16 bits	%C means write the low-order 8 bits of the complement of the constant	%b means write `f' is this is a reversed condition, `t' otherwise	%B means write `t' is this is a reversed condition, `f' otherwise	%J means write the 29k opcode part for a comparison operation	%e means write the label with an extra `X' is this is the epilogue	               otherwise the normal label name	%E means write nothing if this insn has a delay slot,		       a nop unless this is the epilogue label, in which case		       write the first epilogue insn	%F means write just the normal operand if the insn has a delay slot;		       otherwise, this is a recursive call so output the		       symbol + 4 and write the first prologue insn in the		       delay slot.	%L means write the register number plus one ("low order" register)		       or the low-order part of a multi-word constant	%O means write the register number plus two	%P means write the register number plus three ("low order" of TImode)	%S means write the number of words in the mode of the operand,		       minus one (for CR)        %V means write the number of elements in a PARALLEL minus 1	%# means write nothing if we have a delay slot, "\n\tnop" otherwise	%* means write the register name for TPC.  */voidprint_operand (file, x, code)     FILE *file;     rtx x;     char code;{  char buf[100];  /* These macros test for integers and extract the low-order bits.  */#define INT_P(X)  \((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE)	\ && GET_MODE (X) == VOIDmode)#define INT_LOWPART(X) \  (GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X))  switch (code)    {    case 'Q':      if (GET_CODE (x) == REG)	break;      else if (! INT_P (x))	output_operand_lossage ("invalid %%Q value");      fprintf (file, "%d", INT_LOWPART (x) & 0xff);      return;    case 'C':      if (! INT_P (x))	output_operand_lossage ("invalid %%C value");      fprintf (file, "%d", (~ INT_LOWPART (x)) & 0xff);      return;    case 'N':      if (! INT_P (x))	output_operand_lossage ("invalid %%N value");      fprintf (file, "%d", (- INT_LOWPART (x)) & 0xff);      return;    case 'M':      if (! INT_P (x))	output_operand_lossage ("invalid %%M value");      fprintf (file, "%d", INT_LOWPART (x) & 0xffff);      return;    case 'm':      if (! INT_P (x))	output_operand_lossage ("invalid %%m value");      fprintf (file, "%d", (INT_LOWPART (x) & 0xffff) << 16);      return;    case 'b':      if (GET_CODE (x) == GE)	fprintf (file, "f");      else	fprintf (file, "t");

⌨️ 快捷键说明

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