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

📄 sparc.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
  {    char pattern[200];    register char *ld_suffix = (align == 1) ? "ub" : (align == 2) ? "uh" : "";    register char *st_suffix = (align == 1) ? "b" : (align == 2) ? "h" : "";    sprintf (pattern, "ld%s [%%1+%%2],%%%%g1\n\tsubcc %%2,%%4,%%2\n\tbge %s\n\tst%s %%%%g1,[%%0+%%2]\n%s:", ld_suffix, &label3[1], st_suffix, &label5[1]);    output_asm_insn (pattern, xoperands);  }  return "";}/* Output reasonable peephole for set-on-condition-code insns.   Note that these insns assume a particular way of defining   labels.  Therefore, *both* sparc.h and this function must   be changed if a new syntax is needed.    */char *output_scc_insn (operands, insn)     rtx operands[];     rtx insn;{  static char string[100];  rtx label = 0, next = insn;  int need_label = 0;  /* Try doing a jump optimization which jump.c can't do for us     because we did not expose that setcc works by using branches.     If this scc insn is followed by an unconditional branch, then have     the jump insn emitted here jump to that location, instead of to     the end of the scc sequence as usual.  */  do    {      if (GET_CODE (next) == CODE_LABEL)	label = next;      next = NEXT_INSN (next);      if (next == 0)	break;    }  while (GET_CODE (next) == NOTE || GET_CODE (next) == CODE_LABEL);  /* If we are in a sequence, and the following insn is a sequence also,     then just following the current insn's next field will take us to the     first insn of the next sequence, which is the wrong place.  We don't     want to optimize with a branch that has had its delay slot filled.     Avoid this by verifying that NEXT_INSN (PREV_INSN (next)) == next     which fails only if NEXT is such a branch.  */  if (next && GET_CODE (next) == JUMP_INSN && simplejump_p (next)      && (! final_sequence || NEXT_INSN (PREV_INSN (next)) == next))    label = JUMP_LABEL (next);  /* If not optimizing, jump label fields are not set.  To be safe, always     check here to whether label is still zero.  */  if (label == 0)    {      label = gen_label_rtx ();      need_label = 1;    }  LABEL_NUSES (label) += 1;  operands[2] = label;  /* If we are in a delay slot, assume it is the delay slot of an fpcc     insn since our type isn't allowed anywhere else.  */  /* ??? Fpcc instructions no longer have delay slots, so this code is     probably obsolete.  */  /* The fastest way to emit code for this is an annulled branch followed     by two move insns.  This will take two cycles if the branch is taken,     and three cycles if the branch is not taken.     However, if we are in the delay slot of another branch, this won't work,     because we can't put a branch in the delay slot of another branch.     The above sequence would effectively take 3 or 4 cycles respectively     since a no op would have be inserted between the two branches.     In this case, we want to emit a move, annulled branch, and then the     second move.  This sequence always takes 3 cycles, and hence is faster     when we are in a branch delay slot.  */  if (final_sequence)    {      strcpy (string, "mov 0,%0\n\t");      strcat (string, output_cbranch (operands[1], 2, 0, 1, 0));      strcat (string, "\n\tmov 1,%0");    }  else    {      strcpy (string, output_cbranch (operands[1], 2, 0, 1, 0));      strcat (string, "\n\tmov 1,%0\n\tmov 0,%0");    }  if (need_label)    strcat (string, "\n%l2:");  return string;}/* Vectors to keep interesting information about registers where   it can easily be got.  *//* Modes for condition codes.  */#define C_MODES						\  ((1 << (int) CCmode) | (1 << (int) CC_NOOVmode)	\   | (1 << (int) CCFPmode) | (1 << (int) CCFPEmode))/* Modes for single-word (and smaller) quantities.  */#define S_MODES						\ (~C_MODES						\  & ~ ((1 << (int) DImode) | (1 << (int) TImode)	\      | (1 << (int) DFmode) | (1 << (int) TFmode)))/* Modes for double-word (and smaller) quantities.  */#define D_MODES					\  (~C_MODES					\   & ~ ((1 << (int) TImode) | (1 << (int) TFmode)))/* Modes for quad-word quantities.  */#define T_MODES (~C_MODES)/* Modes for single-float quantities.  We must allow any single word or   smaller quantity.  This is because the fix/float conversion instructions   take integer inputs/outputs from the float registers.  */#define SF_MODES (S_MODES)/* Modes for double-float quantities.  */#define DF_MODES (SF_MODES | (1 << (int) DFmode) | (1 << (int) SCmode))/* Modes for quad-float quantities.  */#define TF_MODES (DF_MODES | (1 << (int) TFmode) | (1 << (int) DCmode))/* Value is 1 if register/mode pair is acceptable on sparc.   The funny mixture of D and T modes is because integer operations   do not specially operate on tetra quantities, so non-quad-aligned   registers can hold quadword quantities (except %o4 and %i4 because   they cross fixed registers.  */int hard_regno_mode_ok[] = {  C_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,  T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,  T_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,  T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES, D_MODES, S_MODES,  TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,  TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,  TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES,  TF_MODES, SF_MODES, DF_MODES, SF_MODES, TF_MODES, SF_MODES, DF_MODES, SF_MODES};#ifdef __GNUC__inline#endifstatic intsave_regs (file, low, high, base, offset, n_fregs)     FILE *file;     int low, high;     char *base;     int offset;     int n_fregs;{  int i;  for (i = low; i < high; i += 2)    {      if (regs_ever_live[i] && ! call_used_regs[i])	if (regs_ever_live[i+1] && ! call_used_regs[i+1])	  fprintf (file, "\tstd %s,[%s+%d]\n",		   reg_names[i], base, offset + 4 * n_fregs),	  n_fregs += 2;	else	  fprintf (file, "\tst %s,[%s+%d]\n",		   reg_names[i], base, offset + 4 * n_fregs),	  n_fregs += 2;      else if (regs_ever_live[i+1] && ! call_used_regs[i+1])	fprintf (file, "\tst %s,[%s+%d]\n",		 reg_names[i+1], base, offset + 4 * n_fregs),	n_fregs += 2;    }  return n_fregs;}#ifdef __GNUC__inline#endifstatic intrestore_regs (file, low, high, base, offset, n_fregs)     FILE *file;     int low, high;     char *base;     int offset;{  int i;  for (i = low; i < high; i += 2)    {      if (regs_ever_live[i] && ! call_used_regs[i])	if (regs_ever_live[i+1] && ! call_used_regs[i+1])	  fprintf (file, "\tldd [%s+%d], %s\n",		   base, offset + 4 * n_fregs, reg_names[i]),	  n_fregs += 2;	else	  fprintf (file, "\tld [%s+%d],%s\n",		   base, offset + 4 * n_fregs, reg_names[i]),	  n_fregs += 2;      else if (regs_ever_live[i+1] && ! call_used_regs[i+1])	fprintf (file, "\tld [%s+%d],%s\n",		 base, offset + 4 * n_fregs, reg_names[i+1]),	n_fregs += 2;    }  return n_fregs;}/* Static variables we want to share between prologue and epilogue.  *//* Number of live floating point registers needed to be saved.  */static int num_fregs;/* Nonzero if any floating point register was ever used.  */static int fregs_ever_live;intcompute_frame_size (size, leaf_function)     int size;     int leaf_function;{  int fregs_ever_live = 0;  int n_fregs = 0, i;  int outgoing_args_size = (current_function_outgoing_args_size			    + REG_PARM_STACK_SPACE (current_function_decl));  apparent_fsize = ((size) + 7 - STARTING_FRAME_OFFSET) & -8;  for (i = 32; i < FIRST_PSEUDO_REGISTER; i += 2)    fregs_ever_live |= regs_ever_live[i]|regs_ever_live[i+1];  if (TARGET_EPILOGUE && fregs_ever_live)    {      for (i = 32; i < FIRST_PSEUDO_REGISTER; i += 2)	if ((regs_ever_live[i] && ! call_used_regs[i])	    || (regs_ever_live[i+1] && ! call_used_regs[i+1]))	  n_fregs += 2;    }  /* Set up values for use in `function_epilogue'.  */  num_fregs = n_fregs;  apparent_fsize += (outgoing_args_size+7) & -8;  if (leaf_function && n_fregs == 0      && apparent_fsize == (REG_PARM_STACK_SPACE (current_function_decl)			    - STARTING_FRAME_OFFSET))    apparent_fsize = 0;  actual_fsize = apparent_fsize + n_fregs*4;  /* Make sure nothing can clobber our register windows.     If a SAVE must be done, or there is a stack-local variable,     the register window area must be allocated.  */  if (leaf_function == 0 || size > 0)    actual_fsize += (16 * UNITS_PER_WORD)+8;  return actual_fsize;}/* Output code for the function prologue.  */voidoutput_function_prologue (file, size, leaf_function)     FILE *file;     int size;     int leaf_function;{  if (leaf_function)    frame_base_name = "%sp+80";  else    frame_base_name = "%fp";  /* Need to use actual_fsize, since we are also allocating     space for our callee (and our own register save area).  */  actual_fsize = compute_frame_size (size, leaf_function);  fprintf (file, "\t!#PROLOGUE# 0\n");  if (actual_fsize == 0)    /* do nothing.  */ ;  else if (actual_fsize <= 4096)    {      if (! leaf_function)	fprintf (file, "\tsave %%sp,-%d,%%sp\n", actual_fsize);      else	fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize);    }  else if (actual_fsize <= 8192)    {      /* For frames in the range 4097..8192, we can use just two insns.  */      if (! leaf_function)	{	  fprintf (file, "\tsave %%sp,-4096,%%sp\n");	  fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize - 4096);	}      else	{	  fprintf (file, "\tadd %%sp,-4096,%%sp\n");	  fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize - 4096);	}    }  else    {      if (! leaf_function)	{	  fprintf (file, "\tsethi %%hi(-%d),%%g1\n", actual_fsize);	  if ((actual_fsize & 0x3ff) != 0)	    fprintf (file, "\tor %%g1,%%lo(-%d),%%g1\n", actual_fsize);	  fprintf (file, "\tsave %%sp,%%g1,%%sp\n");	}      else	{	  fprintf (file, "\tsethi %%hi(-%d),%%g1\n", actual_fsize);	  if ((actual_fsize & 0x3ff) != 0)	    fprintf (file, "\tor %%g1,%%lo(-%d),%%g1\n", actual_fsize);	  fprintf (file, "\tadd %%sp,%%g1,%%sp\n");	}    }  /* If doing anything with PIC, do it now.  */  if (! flag_pic)    fprintf (file, "\t!#PROLOGUE# 1\n");  /* Figure out where to save any special registers.  */  if (num_fregs)    {      int offset, n_fregs = num_fregs;      if (! leaf_function)	offset = -apparent_fsize;      else	offset = 0;      if (TARGET_EPILOGUE && ! leaf_function)	n_fregs = save_regs (file, 0, 16, frame_base_name, offset, 0);      else if (leaf_function)	n_fregs = save_regs (file, 0, 32, frame_base_name, offset, 0);      if (TARGET_EPILOGUE)	save_regs (file, 32, FIRST_PSEUDO_REGISTER,		   frame_base_name, offset, n_fregs);    }  if (regs_ever_live[62])    fprintf (file, "\tst %s,[%s-16]\n\tst %s,[%s-12]\n",	     reg_names[0], frame_base_name,	     reg_names[0], frame_base_name);  leaf_label = 0;  if (leaf_function && actual_fsize != 0)    {      /* warning ("leaf procedure with frame size %d", actual_fsize); */      if (! TARGET_EPILOGUE)	leaf_label = gen_label_rtx ();    }}/* Output code for the function epilogue.  */voidoutput_function_epilogue (file, size, leaf_function)     FILE *file;     int size;     int leaf_function;{  int n_fregs, i;  char *ret;  if (leaf_label)    {      emit_label_after (leaf_label, get_last_insn ());      final_scan_insn (get_last_insn (), file, 0, 0, 1);    }  if (num_fregs)    {      int offset, n_fregs = num_fregs;      if (! leaf_function)	offset = -apparent_fsize;      else	offset = 0;      if (TARGET_EPILOGUE && ! leaf_function)	n_fregs = restore_regs (file, 0, 16, frame_base_name, offset, 0);      else if (leaf_function)	n_fregs = restore_regs (file, 0, 32, frame_base_name, offset, 0);      if (TARGET_EPILOGUE)	restore_regs (file, 32, FIRST_PSEUDO_REGISTER,		      frame_base_name, offset, n_fregs);    }  /* Work out how to skip the caller's unimp instruction if required.  */  if (leaf_function)    ret = (current_function_returns_struct ? "jmp %o7+12" : "retl");  else    ret = (current_function_returns_struct ? "jmp %i7+12" : "ret");  if (TARGET_EPILOGUE || leaf_label)    {      int old_target_epilogue = TARGET_EPILOGUE;      target_flags &= ~old_target_epilogue;      if (! leaf_function)	{	  /* If we wound up with things in our delay slot, flush them here.  */	  if (current_function_epilogue_delay_list)	    {	      rtx insn = emit_jump_insn_after (gen_rtx (RETURN, VOIDmode),					       get_last_insn ());	      PATTERN (insn) = gen_rtx (PARALLEL, VOIDmode,					gen_rtvec (2,						   PATTERN (XEXP (current_function_epilogue_delay_list, 0)),						   PATTERN (insn)));	      final_scan_insn (insn, file, 1, 0, 1);	    }	  else	    fprintf (file, "\t%s\n\trestore\n", ret);	}      /* All of the following cases are for leaf functions.  */      else if (current_function_epilogue_delay_list)	{	  /* eligible_for_epilogue_delay_slot ensures that if this is a	     leaf function, then we will only have insn in the delay slot	     if the frame size is zero, thus no adjust for the stack is	     needed here.  */	  if (actual_fsize != 0)	    abort ();	  fprintf (file, "\t%s\n", ret);	  final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),			   file, 1, 0, 1);	}      else if (actual_fsize <= 4096)	fprintf (file, "\t%s\n\tsub %%sp,-%d,%%sp\n", ret, actual_fsize);      else if (actual_fsize <= 8192)	fprintf (file, "\tsub %%sp,-4096,%%sp\n\t%s\n\tsub %%sp,-%d,%%sp\n",		 ret, actual_fsize - 4096);      else if ((actual_fsize & 0x3ff) == 0)	fprintf (file, "\tsethi %%hi(%d),%%g1\n\t%s\n\tadd %%sp,%%g1,%%sp\n",		 actual_fsize, ret);      else		 	fprintf (file, "\tsethi %%hi(%d),%%g1\n\tor %%g1,%%lo(%d),%%g1\n\t%s\n\tadd %%sp,%%g1,%%sp\n",		 actual_fsize, actual_fsize, ret);      target_flags |= old_target_epilogue;    }}/* Return the string to output a conditional branch to LABEL, which is   the operand number of the label.  OP is the conditional expression.  The   mode of register 0 says what kind of comparison we made.   REVERSED is non-zero if we should reverse the sense of the comparison.   ANNUL is non-zero if we should generate an annulling branch.   NOOP is non-zero if we have to follow this 

⌨️ 快捷键说明

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