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

📄 arc.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	  if (epilogue_delay)	    {	      final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1);	    }	}      /* Emit the return instruction.  */      {	static const int regs[4] = {	  0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM	};	fprintf (file, "\tj.d %s\n", reg_names[regs[fn_type]]);      }      /* If the only register saved is the return address, we need a	 nop, unless we have an instruction to put into it.  Otherwise	 we don't since reloading multiple registers doesn't reference	 the register being loaded.  */      if (ARC_INTERRUPT_P (fn_type))	fprintf (file, "\tadd %s,%s,16\n", sp_str, sp_str);      else if (epilogue_delay != NULL_RTX)	{	  if (frame_pointer_needed && !fp_restored_p)	    abort ();	  if (restored < size)	    abort ();	  final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1);	}      else if (frame_pointer_needed && !fp_restored_p)	{	  if (!SMALL_INT (frame_size))	    abort ();	  /* Note that we restore fp and sp here!  */	  fprintf (file, "\tld.a %s,[%s,%d]\n", fp_str, sp_str, frame_size);	}      else if (restored < size)	{	  if (!SMALL_INT (size - restored))	    abort ();	  fprintf (file, "\tadd %s,%s,%d\n",		   sp_str, sp_str, size - restored);	}      else	fprintf (file, "\tnop\n");    }  /* Reset state info for each function.  */  current_frame_info = zero_frame_info;  arc_compute_function_type (NULL_TREE);}/* Define the number of delay slots needed for the function epilogue.   Interrupt handlers can't have any epilogue delay slots (it's always needed   for something else, I think).  For normal functions, we have to worry about   using call-saved regs as they'll be restored before the delay slot insn.   Functions with non-empty frames already have enough choices for the epilogue   delay slot so for now we only consider functions with empty frames.  */intarc_delay_slots_for_epilogue (){  if (arc_compute_function_type (current_function_decl) != ARC_FUNCTION_NORMAL)    return 0;  if (!current_frame_info.initialized)    (void) arc_compute_frame_size (get_frame_size ());  if (current_frame_info.total_size == 0)    return 1;  return 0;}/* Return true if TRIAL is a valid insn for the epilogue delay slot.   Any single length instruction which doesn't reference the stack or frame   pointer or any call-saved register is OK.  SLOT will always be 0.  */intarc_eligible_for_epilogue_delay (trial, slot)     rtx trial;     int slot;{  if (slot != 0)    abort ();  if (get_attr_length (trial) == 1      /* If registers where saved, presumably there's more than enough	 possibilities for the delay slot.  The alternative is something	 more complicated (of course, if we expanded the epilogue as rtl	 this problem would go away).  */      /* ??? Note that this will always be true since only functions with	 empty frames have epilogue delay slots.  See	 arc_delay_slots_for_epilogue.  */      && current_frame_info.gmask == 0      && ! reg_mentioned_p (stack_pointer_rtx, PATTERN (trial))      && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (trial)))    return 1;  return 0;}/* PIC *//* Emit special PIC prologues and epilogues.  */voidarc_finalize_pic (){  /* nothing to do */}/* Return true if OP is a shift operator.  */intshift_operator (op, mode)     rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  switch (GET_CODE (op))    {    case ASHIFTRT:    case LSHIFTRT:    case ASHIFT:      return 1;    default:      return 0;    }}/* Output the assembler code for doing a shift.   We go to a bit of trouble to generate efficient code as the ARC only has   single bit shifts.  This is taken from the h8300 port.  We only have one   mode of shifting and can't access individual bytes like the h8300 can, so   this is greatly simplified (at the expense of not generating hyper-   efficient code).   This function is not used if the variable shift insns are present.  *//* ??? We assume the output operand is the same as operand 1.   This can be optimized (deleted) in the case of 1 bit shifts.  *//* ??? We use the loop register here.  We don't use it elsewhere (yet) and   using it here will give us a chance to play with it.  */const char *output_shift (operands)     rtx *operands;{  rtx shift = operands[3];  enum machine_mode mode = GET_MODE (shift);  enum rtx_code code = GET_CODE (shift);  const char *shift_one;  if (mode != SImode)    abort ();  switch (code)    {    case ASHIFT:   shift_one = "asl %0,%0"; break;    case ASHIFTRT: shift_one = "asr %0,%0"; break;    case LSHIFTRT: shift_one = "lsr %0,%0"; break;    default:       abort ();    }  if (GET_CODE (operands[2]) != CONST_INT)    {      if (optimize)	output_asm_insn ("mov lp_count,%2", operands);      else	output_asm_insn ("mov %4,%2", operands);      goto shiftloop;    }  else    {      int n = INTVAL (operands[2]);      /* If the count is negative, make it 0.  */      if (n < 0)	n = 0;      /* If the count is too big, truncate it.         ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to	 do the intuitive thing.  */      else if (n > GET_MODE_BITSIZE (mode))	n = GET_MODE_BITSIZE (mode);      /* First see if we can do them inline.  */      if (n <= 8)	{	  while (--n >= 0)	    output_asm_insn (shift_one, operands);	}      /* See if we can use a rotate/and.  */      else if (n == BITS_PER_WORD - 1)	{	  switch (code)	    {	    case ASHIFT :	      output_asm_insn ("and %0,%0,1\n\tror %0,%0", operands);	      break;	    case ASHIFTRT :	      /* The ARC doesn't have a rol insn.  Use something else.  */	      output_asm_insn ("asl.f 0,%0\n\tsbc %0,0,0", operands);	      break;	    case LSHIFTRT :	      /* The ARC doesn't have a rol insn.  Use something else.  */	      output_asm_insn ("asl.f 0,%0\n\tadc %0,0,0", operands);	      break;	    default:	      break;	    }	}      /* Must loop.  */      else	{	  char buf[100];	  if (optimize)	    output_asm_insn ("mov lp_count,%c2", operands);	  else	    output_asm_insn ("mov %4,%c2", operands);	shiftloop:	  if (optimize)	    {	      if (flag_pic)		sprintf (buf, "lr %%4,[status]\n\tadd %%4,%%4,6\t%s single insn loop start",			 ASM_COMMENT_START);	      else		sprintf (buf, "mov %%4,%%%%st(1f)\t%s (single insn loop start) >> 2",			 ASM_COMMENT_START);	      output_asm_insn (buf, operands);	      output_asm_insn ("sr %4,[lp_start]", operands);	      output_asm_insn ("add %4,%4,1", operands);	      output_asm_insn ("sr %4,[lp_end]", operands);	      output_asm_insn ("nop\n\tnop", operands);	      if (flag_pic)		fprintf (asm_out_file, "\t%s single insn loop\n",			 ASM_COMMENT_START);	      else		fprintf (asm_out_file, "1:\t%s single insn loop\n",			 ASM_COMMENT_START);	      output_asm_insn (shift_one, operands);	    }	  else 	    {	      fprintf (asm_out_file, "1:\t%s begin shift loop\n",		       ASM_COMMENT_START);	      output_asm_insn ("sub.f %4,%4,1", operands);	      output_asm_insn ("nop", operands);	      output_asm_insn ("bn.nd 2f", operands);	      output_asm_insn (shift_one, operands);	      output_asm_insn ("b.nd 1b", operands);	      fprintf (asm_out_file, "2:\t%s end shift loop\n",		       ASM_COMMENT_START);	    }	}    }  return "";}/* Nested function support.  *//* Emit RTL insns to initialize the variable parts of a trampoline.   FNADDR is an RTX for the address of the function's pure code.   CXT is an RTX for the static chain value for the function.  */voidarc_initialize_trampoline (tramp, fnaddr, cxt)     rtx tramp ATTRIBUTE_UNUSED, fnaddr ATTRIBUTE_UNUSED, cxt ATTRIBUTE_UNUSED;{}/* Set the cpu type and print out other fancy things,   at the top of the file.  */voidarc_asm_file_start (file)     FILE *file;{  fprintf (file, "\t.cpu %s\n", arc_cpu_string);}/* Print operand X (an rtx) in assembler syntax to file FILE.   CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.   For `%' followed by punctuation, CODE is the punctuation and X is null.  */voidarc_print_operand (file, x, code)     FILE *file;     rtx x;     int code;{  switch (code)    {    case '#' :      /* Conditional branches.  For now these are equivalent.  */    case '*' :      /* Unconditional branches.  Output the appropriate delay slot suffix.  */      if (!final_sequence || XVECLEN (final_sequence, 0) == 1)	{	  /* There's nothing in the delay slot.  */	  fputs (".nd", file);	}      else	{	  rtx jump = XVECEXP (final_sequence, 0, 0);	  rtx delay = XVECEXP (final_sequence, 0, 1);	  if (INSN_ANNULLED_BRANCH_P (jump))	    fputs (INSN_FROM_TARGET_P (delay) ? ".jd" : ".nd", file);	  else	    fputs (".d", file);	}      return;    case '?' : /* with leading "." */    case '!' : /* without leading "." */      /* This insn can be conditionally executed.  See if the ccfsm machinery	 says it should be conditionalized.  */      if (arc_ccfsm_state == 3 || arc_ccfsm_state == 4)	{	  /* Is this insn in a delay slot?  */	  if (final_sequence && XVECLEN (final_sequence, 0) == 2)	    {	      rtx insn = XVECEXP (final_sequence, 0, 1);	      /* If the insn is annulled and is from the target path, we need		 to inverse the condition test.  */	      if (INSN_ANNULLED_BRANCH_P (insn))		{		  if (INSN_FROM_TARGET_P (insn))		    fprintf (file, "%s%s",			     code == '?' ? "." : "",			     arc_condition_codes[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current_cc)]);		  else		    fprintf (file, "%s%s",			     code == '?' ? "." : "",			     arc_condition_codes[arc_ccfsm_current_cc]);		}	      else	        {		  /* This insn is executed for either path, so don't		     conditionalize it at all.  */		  ; /* nothing to do */		}	    }	  else	    {	      /* This insn isn't in a delay slot.  */	      fprintf (file, "%s%s",		       code == '?' ? "." : "",		       arc_condition_codes[arc_ccfsm_current_cc]);	    }	}      return;    case '~' :      /* Output a nop if we're between a set of the condition codes,	 and a conditional branch.  */      if (last_insn_set_cc_p)	fputs ("nop\n\t", file);      return;    case 'd' :      fputs (arc_condition_codes[get_arc_condition_code (x)], file);      return;    case 'D' :      fputs (arc_condition_codes[ARC_INVERSE_CONDITION_CODE				 (get_arc_condition_code (x))],	     file);      return;    case 'R' :      /* Write second word of DImode or DFmode reference,	 register or memory.  */      if (GET_CODE (x) == REG)	fputs (reg_names[REGNO (x)+1], file);      else if (GET_CODE (x) == MEM)	{	  fputc ('[', file);	  /* Handle possible auto-increment.  Since it is pre-increment and	     we have already done it, we can just use an offset of four.  */	  /* ??? This is taken from rs6000.c I think.  I don't think it is	     currently necessary, but keep it around.  */	  if (GET_CODE (XEXP (x, 0)) == PRE_INC	      || GET_CODE (XEXP (x, 0)) == PRE_DEC)	    output_address (plus_constant (XEXP (XEXP (x, 0), 0), 4));	  else	    output_address (plus_constant (XEXP (x, 0), 4));	  fputc (']', file);	}      else	output_operand_lossage ("invalid operand to %%R code");      return;    case 'S' :      if ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FLAG (x))	  || GET_CODE (x) == LABEL_REF)	{	  fprintf (file, "%%st(");	  output_addr_const (file, x);	  fprintf (file, ")");	  return;	}      break;    case 'H' :    case 'L' :      if (GET_CODE (x) == REG)	{	  /* L = least significant word, H = most significant word */	  if ((TARGET_BIG_ENDIAN != 0) ^ (code == 'L'))	    fputs (reg_names[REGNO (x)], file);	  else	    fputs (reg_names[REGNO (x)+1], file);	}      else if (GET_CODE (x) == CONST_INT	       || GET_CODE (x) == CONST_DOUBLE)	{	  rtx first, second;	  split_double (x, &first, &second);	  fprintf (file, "0x%08lx",		   (long)(code == 'L' ? INTVAL (first) : INTVAL (second)));	}      else	output_operand_lossage ("invalid operand to %%H/%%L code");      return;    case 'A' :      {	char str[30];	if (GET_CODE (x) != CONST_DOUBLE	    || GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT)	  abort ();	real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x), sizeof (str), 0, 1);	fprintf (file, "%s", str);	return;      }    case 'U' :      /* Output a load/store with update indicator if appropriate.  */      if (GET_CODE (x) == MEM)	{	  if (GET_CODE (XEXP (x, 0)) == PRE_INC	      || GET_CODE (XEXP (x, 0)) == PRE_DEC)	    fputs (".a", file);	}      else	output_operand_lossage ("invalid operand to %%U code");      return;

⌨️ 快捷键说明

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