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

📄 cris.c

📁 gcc-you can use this code to learn something about gcc, and inquire further into linux,
💻 C
📖 第 1 页 / 共 5 页
字号:
  RTX_CODE code;  /* Mainly stolen from refers_to_regno_p in rtlanal.c.  */  code = GET_CODE (x);  switch (code)    {    case REG:      i = REGNO (x);      return !call_used_regs[i];    case SUBREG:      /* If this is a SUBREG of a hard reg, we can see exactly which	 registers are being modified.  Otherwise, handle normally.  */      i = REGNO (SUBREG_REG (x));      return !call_used_regs[i];    default:      ;    }  fmt = GET_RTX_FORMAT (code);  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)    {      if (fmt[i] == 'e')	{	  if (saved_regs_mentioned (XEXP (x, i)))	    return 1;	}      else if (fmt[i] == 'E')	{	  int j;	  for (j = XVECLEN (x, i) - 1; j >=0; j--)	    if (saved_regs_mentioned (XEXP (x, i)))	      return 1;	}    }  return 0;}/* Figure out if the insn may be put in the epilogue.  */intcris_eligible_for_epilogue_delay (insn)     rtx insn;{  /* First of all, it must be as slottable as for a delayed branch insn.  */  if (get_attr_slottable (insn) != SLOTTABLE_YES)    return 0;  /* It must not refer to the stack pointer (may be valid for some cases     that I can't think of).  */  if (reg_mentioned_p (stack_pointer_rtx, PATTERN (insn)))    return 0;  /* The frame pointer will be restored in the epilogue, before the     "ret", so it can't be referred to.  */  if (frame_pointer_needed      && reg_mentioned_p (frame_pointer_rtx, PATTERN (insn)))    return 0;  /* All saved regs are restored before the delayed insn.     This means that we cannot have any instructions that mention the     registers that are restored by the epilogue.  */  if (saved_regs_mentioned (PATTERN (insn)))    return 0;  /* It seems to be ok.  */  return 1;}/* Return the number of delay-slots in the epilogue: return 1 if it   contains "ret", else 0.  */intcris_delay_slots_for_epilogue (){  /* Check if we use a return insn, which we only do for leaf functions.     Else there is no slot to fill.  */  if (regs_ever_live[CRIS_SRP_REGNUM]      || cfun->machine->needs_return_address_on_stack != 0)    return 0;  /* By calling function_epilogue with the same parameters as from gcc     we can get info about if the epilogue can fill the delay-slot by itself.     If it is filled from the epilogue, then the corresponding string     is in save_last.      This depends on that the "size" argument to function_epilogue     always is get_frame_size.     FIXME:  Kludgy.  At least make it a separate function that is not     misnamed or abuses the stream parameter.  */  cris_target_asm_function_epilogue (NULL, get_frame_size ());  if (*save_last)    return 1;  return 0;}/* Textual function epilogue.  When file is NULL, it serves doubly as   a test for whether the epilogue can fill any "ret" delay-slots by   itself by storing the delay insn in save_last.  */static voidcris_target_asm_function_epilogue (file, size)     FILE *file;     HOST_WIDE_INT size;{  int regno;  int last_movem_reg = -1;  rtx insn = get_last_insn ();  int argspace_offset = current_function_outgoing_args_size;  int pretend =	 current_function_pretend_args_size;  int return_address_on_stack    = regs_ever_live[CRIS_SRP_REGNUM]    || cfun->machine->needs_return_address_on_stack != 0;  save_last[0] = 0;  if (file && !TARGET_PROLOGUE_EPILOGUE)    return;  if (TARGET_PDEBUG && file)    fprintf (file, ";;\n");  /* Align byte count of stack frame.  */  if (TARGET_STACK_ALIGN)    size = TARGET_ALIGN_BY_32 ? (size + 3) & ~3 : (size + 1) & ~1;  /* If the last insn was a BARRIER, we don't have to write any code,     then all returns were covered by "return" insns.  */  if (GET_CODE (insn) == NOTE)    insn = prev_nonnote_insn (insn);  if (insn      && (GET_CODE (insn) == BARRIER	  /* We must make sure that the insn really is a "return" and	     not a conditional branch.  Try to match the return exactly,	     and if it doesn't match, assume it is a conditional branch	     (and output an epilogue).  */	  || (GET_CODE (insn) == JUMP_INSN	      && GET_CODE (PATTERN (insn)) == RETURN)))    {      if (TARGET_PDEBUG && file)	fprintf (file, ";;;;;\n");      return;    }  /* Check how many saved regs we can movem.  They start at r0 and must     be contiguous.  */  for (regno = 0;       regno < FIRST_PSEUDO_REGISTER;       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]))))	 && (regno != FRAME_POINTER_REGNUM || !frame_pointer_needed)	 && regno != CRIS_SRP_REGNUM)	|| (current_function_calls_eh_return	    && (regno == EH_RETURN_DATA_REGNO (0)		|| regno == EH_RETURN_DATA_REGNO (1)		|| regno == EH_RETURN_DATA_REGNO (2)		|| regno == EH_RETURN_DATA_REGNO (3))))      {	if (regno == last_movem_reg + 1)	  last_movem_reg++;	else	  break;      }  for (regno = FIRST_PSEUDO_REGISTER - 1;       regno > last_movem_reg;       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]))))	 && (regno != FRAME_POINTER_REGNUM || !frame_pointer_needed)	 && regno != CRIS_SRP_REGNUM)	|| (current_function_calls_eh_return	    && (regno == EH_RETURN_DATA_REGNO (0)		|| regno == EH_RETURN_DATA_REGNO (1)		|| regno == EH_RETURN_DATA_REGNO (2)		|| regno == EH_RETURN_DATA_REGNO (3))))      {	if (argspace_offset)	  {	    /* There is an area for outgoing parameters located before	       the saved registers.  We have to adjust for that.  */	    if (file)	      fprintf (file, "\tAdd%s %d,$sp\n",		       ADDITIVE_SIZE_MODIFIER (argspace_offset),		       argspace_offset);	    /* Make sure we only do this once.  */	    argspace_offset = 0;	  }	/* Flush previous non-movem:ed registers.  */	if (*save_last && file)	  fprintf (file, save_last);	sprintf (save_last, "\tPop $%s\n", reg_names[regno]);      }  if (last_movem_reg != -1)    {      if (argspace_offset)	{	  /* Adjust for the outgoing parameters area, if that's not	     handled yet.  */	  if (*save_last && file)	    {	      fprintf (file, save_last);	      *save_last = 0;	    }	  if (file)	    fprintf (file, "\tAdd%s %d,$sp\n",		     ADDITIVE_SIZE_MODIFIER (argspace_offset),		     argspace_offset);	  argspace_offset = 0;	}      /* Flush previous non-movem:ed registers.  */      else if (*save_last && file)	fprintf (file, save_last);      sprintf (save_last, "\tmovem [$sp+],$%s\n", reg_names[last_movem_reg]);    }  /* Restore frame pointer if necessary.  */  if (frame_pointer_needed)    {      if (*save_last && file)	fprintf (file, save_last);      if (file)	fprintf (file, "\tmove.d $%s,$sp\n",		 reg_names[FRAME_POINTER_REGNUM]);      sprintf (save_last, "\tPop $%s\n",	       reg_names[FRAME_POINTER_REGNUM]);    }  else    {      /* If there was no frame-pointer to restore sp from, we must	 explicitly deallocate local variables.  */      /* Handle space for outgoing parameters that hasn't been handled	 yet.  */      size += argspace_offset;      if (size)	{	  if (*save_last && file)	    fprintf (file, save_last);	  sprintf (save_last, "\tadd%s %d,$sp\n",		   ADDITIVE_SIZE_MODIFIER (size), size);	}      /* If the size was not in the range for a "quick", we must flush	 it here.  */      if (size > 63)	{	  if (file)	    fprintf (file, save_last);	  *save_last = 0;	}    }  /* If this function has no pushed register parameters     (stdargs/varargs), and if it is not a leaf function, then we can     just jump-return here.  */  if (return_address_on_stack && pretend == 0)    {      if (*save_last && file)	fprintf (file, save_last);      *save_last = 0;      if (file)	{	  if (current_function_calls_eh_return)	    {	      /* The installed EH-return address is in *this* frame, so we		 need to pop it before we return.  */	      fprintf (file, "\tpop $srp\n");	      fprintf (file, "\tret\n");	      fprintf (file, "\tadd.d $%s,$sp\n", reg_names[CRIS_STACKADJ_REG]);	    }	  else	    fprintf (file, "\tJump [$sp+]\n");	  /* Do a sanity check to avoid generating invalid code.  */	  if (current_function_epilogue_delay_list)	    internal_error ("allocated but unused delay list in epilogue");	}      return;    }  /* Rather than add current_function_calls_eh_return conditions     everywhere in the following code (and not be able to test it     thoroughly), assert the assumption that all usage of     __builtin_eh_return are handled above.  */  if (current_function_calls_eh_return)    internal_error ("unexpected function type needing stack adjustment for\ __builtin_eh_return");  /* If we pushed some register parameters, then adjust the stack for     them.  */  if (pretend)    {      /* Since srp is stored on the way, we need to restore it first.  */      if (return_address_on_stack)	{	  if (*save_last && file)	    fprintf (file, save_last);	  *save_last = 0;	  if (file)	    fprintf (file, "\tpop $srp\n");	}      if (*save_last && file)	fprintf (file, save_last);      sprintf (save_last, "\tadd%s %d,$sp\n",	       ADDITIVE_SIZE_MODIFIER (pretend), pretend);    }  /* Here's where we have a delay-slot we need to fill.  */  if (file && current_function_epilogue_delay_list)    {      /* If gcc has allocated an insn for the epilogue delay slot, but	 things were arranged so we now thought we could do it	 ourselves, don't forget to flush that insn.  */      if (*save_last)	fprintf (file, save_last);      fprintf (file, "\tRet\n");      /* Output the delay-slot-insn the mandated way.  */      final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),		       file, 1, -2, 1);    }  else if (file)    {      fprintf (file, "\tRet\n");      /* If the GCC did not do it, we have to use whatever insn we have,	 or a nop.  */      if (*save_last)	fprintf (file, save_last);      else	fprintf (file, "\tnOp\n");    }}/* The PRINT_OPERAND worker.  */voidcris_print_operand (file, x, code)     FILE *file;     rtx x;     int code;{  rtx operand = x;  /* Size-strings corresponding to MULT expressions.  */  static const char *const mults[] = { "BAD:0", ".b", ".w", "BAD:3", ".d" };  /* New code entries should just be added to the switch below.  If     handling is finished, just return.  If handling was just a     modification of the operand, the modified operand should be put in     "operand", and then do a break to let default handling     (zero-modifier) output the operand.  */  switch (code)    {    case 'b':      /* Print the unsigned supplied integer as if it was signed	 and < 0, i.e print 255 or 65535 as -1, 254, 65534 as -2, etc.  */      if (GET_CODE (x) != CONST_INT	  || ! CONST_OK_FOR_LETTER_P (INTVAL (x), 'O'))	LOSE_AND_RETURN ("invalid operand for 'b' modifier", x);      fprintf (file, "%d", INTVAL (x)| (INTVAL (x) <= 255 ? ~255 : ~65535));      return;    case 'x':      /* Print assembler code for operator.  */      fprintf (file, "%s", cris_op_str (operand));      return;    case 'v':      /* Print the operand without the PIC register.  */      if (! flag_pic || ! CONSTANT_P (x) || ! cris_gotless_symbol (x))	LOSE_AND_RETURN ("invalid operand for 'v' modifier", x);      cris_pic_sympart_only++;      cris_output_addr_const (file, x);      cris_pic_sympart_only--;      return;    case 'P':      /* Print the PIC register.  Applied to a GOT-less PIC symbol for         sanity.  */      if (! flag_pic || ! CONSTANT_P (x) || ! cris_gotless_symbol (x))	LOSE_AND_RETURN ("invalid operand for 'P' modifier", x);      fprintf (file, "$%s", reg_names [PIC_OFFSET_TABLE_REGNUM]);      return;    case 'p':      /* Adjust a power of two to its log2.  */      if (GET_CODE (x) != CONST_INT || exact_log2 (INTVAL (x)) < 0 )	LOSE_AND_RETURN ("invalid operand for 'p' modifier", x);      fprintf (file, "%d", exact_log2 (INTVAL (x)));      return;    case 's':      /* For an integer, print 'b' or 'w' if <= 255 or <= 65535	 respectively.  This modifier also terminates the inhibiting         effects of the 'x' modifier.  */      cris_output_insn_is_bound = 0;      if (GET_MODE (x) == VOIDmode && GET_CODE (x) == CONST_INT)	{	  if (INTVAL (x) >= 0)	    {	      if (INTVAL (x) <= 255)		putc ('b', file);	      else if (INTVAL (x) <= 65535)		putc ('w', file);	      else		putc ('d', file);	    }	  else	    putc ('d', file);	  return;	}      /* For a non-integer, print the size of the operand.  */      putc ((GET_MODE (x) == SImode || GET_MODE (x) == SFmode)	    ? 'd' : GET_MODE (x) == HImode ? 'w'	    : GET_MODE (x) == QImode ? 'b'	    /* If none of the above, emit an erroneous size letter.  */	    : 'X',	    file);      return;    case 'z':      /* Const_int: print b for -127 <= x <= 255,	 w for -32768 <= x <= 65535, else abort.  */      if (GET_CODE (x) != CONST_INT	  || INTVAL (x) < -32768 || INTVAL (x) > 65535)	LOSE_AND_RETURN ("invalid operand for 'z' modifier", x);

⌨️ 快捷键说明

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