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

📄 c4x.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 5 页
字号:
      cum->ints = cum->floats = 0;      cum->init = 1;    }  if (! TARGET_MEMPARM       && named       && type      && ! MUST_PASS_IN_STACK (mode, type))    {      /* Look for float, double, or long double argument.  */      if (mode == QFmode || mode == HFmode)	{	  if (cum->floats < cum->maxfloats)	    reg = c4x_fp_reglist[cum->floats];	}      /* Look for integer, enumeral, boolean, char, or pointer argument.  */      else if (mode == QImode || mode == Pmode)	{	  if (cum->ints < cum->maxints)	    reg = c4x_int_reglist[cum->maxfloats][cum->ints];	}    }  else if (! TARGET_MEMPARM && ! type)    {      /* We could use a different argument calling model for libcalls,         since we're only calling functions in libgcc.  Thus we could         pass arguments for long longs in registers rather than on the         stack.  In the meantime, use the odd TI format.  We make the         assumption that we won't have more than two floating point         args, six integer args, and that all the arguments are of the         same mode.  */      if (mode == QFmode || mode == HFmode)	reg = c4x_fp_reglist[cum->floats];      else if (mode == QImode || mode == Pmode)	reg = c4x_int_reglist[0][cum->ints];    }  if (TARGET_DEBUG)    {      fprintf (stderr, "c4x_function_arg(mode=%s, named=%d",	       GET_MODE_NAME (mode), named);      if (reg)	fprintf (stderr, ", reg=%s", reg_names[reg]);      else	fprintf (stderr, ", stack");      fprintf (stderr, ")\n");    }  if (reg)    return gen_rtx_REG (mode, reg);  else    return NULL_RTX;}static intc4x_isr_reg_used_p (regno)     int regno;{  /* Don't save/restore FP or ST, we handle them separately.  */  if (regno == FRAME_POINTER_REGNUM      || IS_ST_REG (regno))    return 0;  /* We could be a little smarter abut saving/restoring DP.     We'll only save if for the big memory model or if     we're paranoid. ;-)  */  if (IS_DP_REG (regno))    return ! TARGET_SMALL || TARGET_PARANOID;  /* Only save/restore regs in leaf function that are used.  */  if (c4x_leaf_function)    return regs_ever_live[regno] && fixed_regs[regno] == 0;  /* Only save/restore regs that are used by the ISR and regs     that are likely to be used by functions the ISR calls     if they are not fixed.  */  return IS_EXT_REG (regno)    || ((regs_ever_live[regno] || call_used_regs[regno]) 	&& fixed_regs[regno] == 0);}static intc4x_leaf_function_p (){  /* A leaf function makes no calls, so we only need     to save/restore the registers we actually use.     For the global variable leaf_function to be set, we need     to define LEAF_REGISTERS and all that it entails.     Let's check ourselves...   */  if (lookup_attribute ("leaf_pretend",			TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))    return 1;  /* Use the leaf_pretend attribute at your own risk.  This is a hack     to speed up ISRs that call a function infrequently where the     overhead of saving and restoring the additional registers is not     warranted.  You must save and restore the additional registers     required by the called function.  Caveat emptor.  Here's enough     rope...  */  if (leaf_function_p ())    return 1;  return 0;}static intc4x_assembler_function_p (){  tree type;  type = TREE_TYPE (current_function_decl);  return lookup_attribute ("assembler", TYPE_ATTRIBUTES (type)) != NULL;}static intc4x_interrupt_function_p (){  if (lookup_attribute ("interrupt",			TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))    return 1;  /* Look for TI style c_intnn  */  return current_function_name[0] == 'c'    && current_function_name[1] == '_'    && current_function_name[2] == 'i'    && current_function_name[3] == 'n'     && current_function_name[4] == 't'    && isdigit (current_function_name[5])    && isdigit (current_function_name[6]);}/* Write function prologue.  */voidc4x_function_prologue (file, size)     FILE *file;     int size;{  int regno;/* In functions where ar3 is not used but frame pointers are still   specified, frame pointers are not adjusted (if >= -O2) and this is   used so it won't be needlessly push the frame pointer.  */  int dont_push_ar3;  /* For __assembler__ function don't build a prologue.  */  if (c4x_assembler_function_p ())    {      fprintf (file, "; *** Assembler Function ***\n");      return;    }  /* For __interrupt__ function build specific prologue.  */  if (c4x_interrupt_function_p ())    {      c4x_leaf_function = c4x_leaf_function_p ();      fprintf (file, "; *** Interrupt Entry %s ***\n",	       c4x_leaf_function ? "(leaf)" : "");      fprintf (file, "\tpush\tst\n");      if (size)	{	  fprintf (file, "\tpush\tar3\n\tldi\tsp,ar3\n");	  /* FIXME: Assume ISR doesn't require more than 32767 words	     of local variables.  */	  if (size > 32767)	    error ("ISR %s requires %d words of local variables, "		   "maximum is 32767.", current_function_name, size);	  fprintf (file, "\taddi\t%d,sp\n", size);	}      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)	{	  if (c4x_isr_reg_used_p (regno))	    {	      fprintf (file, "\tpush\t%s\n", reg_names[regno]);	      if (IS_EXT_REG (regno))	/* save 32MSB of R0--R11 */		fprintf (file, "\tpushf\t%s\n", float_reg_names[regno]);	    }	}      /* We need to clear the repeat mode flag if the ISR is         going to use a RPTB instruction or uses the RC, RS, or RE         registers.  */      if (regs_ever_live[RC_REGNO] 	  || regs_ever_live[RS_REGNO] 	  || regs_ever_live[RE_REGNO])	fprintf (file, "\tandn\t0100h,st\n");      /* Reload DP reg if we are paranoid about some turkey         violating small memory model rules.  */      if (TARGET_SMALL && TARGET_PARANOID)	fprintf (file, TARGET_C3X ?		 "\tldp\t@data_sec\n" :		 "\tldpk\t@data_sec\n");    }  else    {      if (frame_pointer_needed)	{	  if ((size != 0)	      || (current_function_args_size != 0)	      || (optimize < 2))	    {	      fprintf (file, "\tpush\tar3\n");	      fprintf (file, "\tldi\tsp,ar3\n");	      dont_push_ar3 = 1;	    }	  else	    {	      /* Since ar3 is not used, we don't need to push it.  */	      dont_push_ar3 = 1;	    }	}      else	{	  /* If we use ar3, we need to push it.   */	  dont_push_ar3 = 0;	  if ((size != 0) || (current_function_args_size != 0))	    {	      /* If we are omitting the frame pointer, we still have	         to make space for it so the offsets are correct	         unless we don't use anything on the stack at all.  */	      size += 1;	    }	}      if (size > 32767)	{	  /* Local vars are too big, it will take multiple operations	     to increment SP.  */	  if (TARGET_C3X)	    {	      fprintf (file, "\tldi\t%d,r1\n", size >> 16);	      fprintf (file, "\tlsh\t16,r1\n");	    }	  else	    fprintf (file, "\tldhi\t%d,r1\n", size >> 16);	  fprintf (file, "\tor\t%d,r1\n", size & 0xffff);	  fprintf (file, "\taddi\tr1,sp\n");	}      else if (size != 0)	{	  /* Local vars take up less than 32767 words, so we can directly	     add the number.  */	  fprintf (file, "\taddi\t%d,sp\n", size);	}      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)	{	  if (regs_ever_live[regno] && ! call_used_regs[regno])	    {	      if ((regno == R6_REGNO) || (regno == R7_REGNO))		{		  /* R6 and R7 are saved as floating point */		  if (TARGET_PRESERVE_FLOAT)		    fprintf (file, "\tpush\t%s\n", reg_names[regno]);		  fprintf (file, "\tpushf\t%s\n", float_reg_names[regno]);		}	      else if ((! dont_push_ar3) || (regno != AR3_REGNO))		{		  fprintf (file, "\tpush\t%s\n", reg_names[regno]);		}	    }	}    }}/* Write function epilogue.  */voidc4x_function_epilogue (file, size)     FILE *file;     int size;{  int regno;  int restore_count = 0;  int delayed_jump = 0;  int dont_pop_ar3;  rtx insn;  insn = get_last_insn ();  if (insn && GET_CODE (insn) == NOTE)    insn = prev_nonnote_insn (insn);  if (insn && GET_CODE (insn) == BARRIER)    return;  /* For __assembler__ function build no epilogue.  */  if (c4x_assembler_function_p ())    {      fprintf (file, "\trets\n");	/* Play it safe */      return;    }#ifdef FUNCTION_BLOCK_PROFILER_EXIT  if (profile_block_flag == 2)    {      FUNCTION_BLOCK_PROFILER_EXIT (file);    }#endif  /* For __interrupt__ function build specific epilogue.  */  if (c4x_interrupt_function_p ())    {      for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)	{	  if (! c4x_isr_reg_used_p (regno))	    continue;	  if (IS_EXT_REG (regno))	    fprintf (file, "\tpopf\t%s\n", float_reg_names[regno]);	  fprintf (file, "\tpop\t%s\n", reg_names[regno]);	}      if (size)	{	  fprintf (file, "\tsubi\t%d,sp\n", size);	  fprintf (file, "\tpop\tar3\n");	}      fprintf (file, "\tpop\tst\n");      fprintf (file, "\treti\n");    }  else    {      if (frame_pointer_needed)	{	  if ((size != 0) 	      || (current_function_args_size != 0) 	      || (optimize < 2))	    {	      /* R2 holds the return value.  */	      fprintf (file, "\tldi\t*-ar3(1),r2\n");	      /* We already have the return value and the fp,	         so we need to add those to the stack.  */	      size += 2;	      delayed_jump = 1;	      restore_count = 1;	      dont_pop_ar3 = 1;	    }	  else	    {	      /* Since ar3 is not used for anything, we don't need to	         pop it.  */	      dont_pop_ar3 = 1;	    }	}      else	{	  dont_pop_ar3 = 0;	/* If we use ar3, we need to pop it */	  if (size || current_function_args_size)	    {	      /* If we are ommitting the frame pointer, we still have	         to make space for it so the offsets are correct	         unless we don't use anything on the stack at all.  */	      size += 1;	    }	}      /* Now get the number of instructions required to restore the         registers.  */      for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)	{	  if ((regs_ever_live[regno] && ! call_used_regs[regno])	      && ((! dont_pop_ar3) || (regno != AR3_REGNO)))	    {	      restore_count++;	      if (TARGET_PRESERVE_FLOAT		  && ((regno == R6_REGNO) || (regno == R7_REGNO)))	        restore_count++;	    }	}      /* Get the number of instructions required to restore the stack.  */      if (size > 32767)	restore_count += (TARGET_C3X ? 4 : 3);      else if (size != 0)	restore_count += 1;      if (delayed_jump && (restore_count < 3))	{	  /* We don't have enough instructions to account for the delayed	     branch, so put some nops in.  */	  fprintf (file, "\tbud\tr2\n");	  while (restore_count < 3)	    {	      fprintf (file, "\tnop\n");	      restore_count++;	    }	  restore_count = 0;	}      /* Now restore the saved registers, putting in the delayed branch         where required.  */      for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)	{	  if (regs_ever_live[regno] && ! call_used_regs[regno])	    {	      if (regno == AR3_REGNO && dont_pop_ar3)		continue;	      if (delayed_jump && (restore_count == 3))		fprintf (file, "\tbud\tr2\n");	      /* R6 and R7 are saved as floating point.  */	      if ((regno == R6_REGNO) || (regno == R7_REGNO))		{		  fprintf (file, "\tpopf\t%s\n", float_reg_names[regno]);		  if (TARGET_PRESERVE_FLOAT)		    {	              restore_count--;	              if (delayed_jump && (restore_count == 3))		        fprintf (file, "\tbud\tr2\n");		      fprintf (file, "\tpop\t%s\n", reg_names[regno]);		    }		}	      else		fprintf (file, "\tpop\t%s\n", reg_names[regno]);	      restore_count--;	    }	}      if (delayed_jump && (restore_count == 3))	fprintf (file, "\tbud\tr2\n");      if (frame_pointer_needed)	{	  if ((size != 0)	      || (current_function_args_size != 0)	      || (optimize < 2))	    {	      /* Restore the old FP.  */	      fprintf (file, "\tldi\t*ar3,ar3\n");	      restore_count--;	      if (delayed_jump && (restore_count == 3))		fprintf (file, "\tbud\tr2\n");	    }	}      if (size > 32767)	{	  /* Local vars are too big, it will take multiple operations	     to decrement SP.  */	  if (TARGET_C3X)	    {	      fprintf (file, "\tldi\t%d,r3\n", size >> 16);	      if (delayed_jump)		fprintf (file, "\tbud\tr2\n");	      fprintf (file, "\tlsh\t16,r3\n");	    }	  else	    fprintf (file, "\tldhi\t%d,r3\n", size >> 16);	  fprintf (file, "\tor\t%d,r3\n", size & 0xffff);	  fprintf (file, "\tsubi\tr3,sp\n");	}      else if (size != 0)	{	  /* Local vars take up less than 32768 words, so we can directly	     subtract the number.  */	  fprintf (file, "\tsubi\t%d,sp\n", size);	}      if (! delayed_jump)	fprintf (file, "\trets\n");    }}intc4x_null_epilogue_p (){  int regno;  if (reload_completed      && ! c4x_assembler_function_p ()      && ! c4x_interrupt_function_p ()      && ! current_function_calls_alloca      && ! current_function_args_size      && ! (profile_block_flag == 2)      && ! (optimize < 2)      && ! get_frame_size ())    {      for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)	if (regs_ever_live[regno] && ! call_used_regs[regno]	    && (regno != AR3_REGNO))	  return 0;      return 1;    }  return 0;}intc4x_emit_move_sequence (operands, mode)     rtx *operands;     enum machine_mode mode;     {  rtx op0 = operands[0];  rtx op1 = operands[1];  if (! reload_in_progress      && ! REG_P (op0)       && ! REG_P (op1)      && ! (stik_const_operand (op1, mode) && ! push_operand (op0, mode)))    op1 = force_reg (mode, op1);  if (GET_CODE (op1) == LO_SUM      && GET_MODE (op1) == Pmode      && dp_reg_operand (XEXP (op1, 0), mode))    {      /* expand_increment will sometimes create a LO_SUM immediate	 address.  */      op1 = XEXP (op1, 1);    }  else if (symbolic_address_operand (op1, mode))

⌨️ 快捷键说明

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