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

📄 out-sparc.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
      if (lucky2)	{	  if (REGNO (operands[1]) == REGNO (operands[2]))	    {	      if (REGNO (operands[1]) == 8)		output_asm_insn ("mov %%o0,%%o1");	      else		output_asm_insn ("mov %%o1,%%o0");	    }	  output_asm_insn ("call .mul,2\n\tnop", operands);	}      else	{	  rtx xoperands[2];	  xoperands[0] = gen_rtx (REG, SImode,				  8 ^ (REGNO (operands[1]) == 8));	  xoperands[1] = operands[2];	  output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);	}    }  else if (lucky2)    {      rtx xoperands[2];      xoperands[0] = gen_rtx (REG, SImode,			      8 ^ (REGNO (operands[2]) == 8));      xoperands[1] = operands[1];      output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);    }  else    {      output_asm_insn ("mov %1,%%o0\n\tcall .mul,2\n\tmov %2,%%o1",		       operands);    }  if (REGNO (operands[0]) == 8)    return "";  return "mov %%o0,%0";}/* Make floating point register f0 contain 0.   SIZE is the number of registers (including f0)   which should contain 0.  */voidmake_f0_contain_0 (size)     int size;{  if (size == 1)    {      if ((cc_status.flags & (CC_F0_IS_0)) == 0)	output_asm_insn ("ld [%%fp-16],%%f0", 0);      cc_status.flags |= CC_F0_IS_0;    }  else if (size == 2)    {      if ((cc_status.flags & CC_F0_IS_0) == 0)	output_asm_insn ("ld [%%fp-16],%%f0", 0);      if ((cc_status.flags & (CC_F1_IS_0)) == 0)	output_asm_insn ("ld [%%fp-12],%%f1", 0);      cc_status.flags |= CC_F0_IS_0 | CC_F1_IS_0;    }}/* Since condition codes don't have logical links, we need to keep   their setting and use together for set-cc insns.  */voidgen_scc_insn (code, mode, operands)     enum rtx_code code;     enum machine_mode mode;     rtx *operands;{  extern rtx sequence_stack;  rtx last_insn = XEXP (XEXP (sequence_stack, 1), 0);  rtx last_pat;  /* Skip back over the CLOBBERs that may precede this insn.  */  while (last_insn && GET_CODE (last_insn) == INSN	 && GET_CODE (PATTERN (last_insn)) == CLOBBER)    last_insn = PREV_INSN (last_insn);  /* We should have found the preceding compare.  */  if (last_insn == 0 || GET_CODE (last_insn) != INSN)    abort ();  last_pat = PATTERN (last_insn);  if (GET_CODE (last_pat) != SET      || GET_CODE (SET_DEST (last_pat)) != CC0)    abort ();  /* Turn off that previous insn, now that we have got the data out of it.  */  PUT_CODE (last_insn, NOTE);  NOTE_LINE_NUMBER (last_insn) = NOTE_INSN_DELETED;  /* Emit one replacement insn to compare operands and store result.  */  emit_insn (gen_rtx (SET, VOIDmode, operands[0],		      gen_rtx (code, mode, SET_SRC (last_pat), const0_rtx)));}/* Output reasonable peephole for set-on-condition-code insns.   Note that these insns assume a particular way of defining   labels.  Therefore, *both* tm-sparc.h and this function must   be changed if a new syntax is needed.  */char *output_scc_insn (code, operand)     enum rtx_code code;     rtx operand;{  rtx xoperands[2];  rtx label = gen_label_rtx ();  int cc_in_fccr = cc_status.flags & CC_IN_FCCR;  int antisymmetric = 0;  xoperands[0] = operand;  xoperands[1] = label;  switch (code)    {    case NE:      if (cc_in_fccr)	output_asm_insn ("fbne,a %l0", &label);      else	output_asm_insn ("bne,a %l0", &label);      break;    case EQ:      if (cc_in_fccr)	output_asm_insn ("fbe,a %l0", &label);      else	output_asm_insn ("be,a %l0", &label);      break;    case GE:      if (cc_in_fccr)	output_asm_insn ("fbge,a %l0", &label);      else	output_asm_insn ("bge,a %l0", &label);      antisymmetric = 1;      break;    case GT:      if (cc_in_fccr)	output_asm_insn ("fbg,a %l0", &label);      else	output_asm_insn ("bg,a %l0", &label);      antisymmetric = 1;      break;    case LE:      if (cc_in_fccr)	output_asm_insn ("fble,a %l0", &label);      else	output_asm_insn ("ble,a %l0", &label);      antisymmetric = 1;      break;    case LT:      if (cc_in_fccr)	output_asm_insn ("fbl,a %l0", &label);      else	output_asm_insn ("bl,a %l0", &label);      antisymmetric = 1;      break;    case GEU:      if (cc_in_fccr)	abort ();      else	output_asm_insn ("bgeu,a %l0", &label);      antisymmetric = 1;      break;    case GTU:      if (cc_in_fccr)	abort ();      else	output_asm_insn ("bgu,a %l0", &label);      antisymmetric = 1;      break;    case LEU:      if (cc_in_fccr)	abort ();      else	output_asm_insn ("bleu,a %l0", &label);      antisymmetric = 1;      break;    case LTU:      if (cc_in_fccr)	abort ();      else	output_asm_insn ("blu,a %l0", &label);      antisymmetric = 1;      break;    default:      abort ();    }  if (antisymmetric      && (cc_status.flags & CC_REVERSED))    output_asm_insn ("orcc %%g0,0,%0\n\torcc %%g0,1,%0\n%l1:", xoperands);  else    output_asm_insn ("orcc %%g0,1,%0\n\torcc %%g0,0,%0\n%l1:", xoperands);  cc_status.flags &= ~CC_IN_FCCR;  return "";}/* Output a delayed branch insn with the delay insn in its   branch slot.  The delayed branch insn template is in TEMPLATE,   with operands OPERANDS.  The insn in its delay slot is INSN.   As a special case, since we know that all memory transfers are via   ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory   reference around the branch as	sethi %hi(x),%%g1	b ...	ld/st [%g1+%lo(x)],...   As another special case, we handle loading (SYMBOL_REF ...) and   other large constants around branches as well:	sethi %hi(x),%0	b ...	or %0,%lo(x),%1   */char *output_delayed_branch (template, operands, insn)     char *template;     rtx *operands;     rtx insn;{  extern rtx recog_operand[];  rtx src = XVECEXP (PATTERN (insn), 0, 1);  rtx dest = XVECEXP (PATTERN (insn), 0, 0);  if (GET_CODE (src) == SYMBOL_REF      || (GET_CODE (src) == CONST_INT	  && !(SMALL_INT (src) || (INTVAL (src) & 0x3ff) == 0)))    {      rtx xoperands[2];      xoperands[0] = dest;      xoperands[1] = src;      /* Output the `sethi' insn.  */      output_asm_insn ("sethi %%hi(%1),%0", xoperands);      /* Output the branch instruction next.  */      output_asm_insn (template, operands);      /* Now output the `or' insn.  */      output_asm_insn ("or %0,%%lo(%1),%0", xoperands);    }  else if ((GET_CODE (src) == MEM	    && CONSTANT_ADDRESS_P (XEXP (src, 0)))	   || (GET_CODE (dest) == MEM	       && CONSTANT_ADDRESS_P (XEXP (dest, 0))))    {      rtx xoperands[2];      char *split_template;      xoperands[0] = dest;      xoperands[1] = src;      /* Output the `sethi' insn.  */      if (GET_CODE (src) == MEM)	{	  if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)		 && cc_prev_status.mdep == XEXP (operands[1], 0)))	    output_asm_insn ("sethi %%hi(%m1),%%g1", xoperands);	  split_template = "ld [%%g1+%%lo(%m1)],%0";	}      else	{	  if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)		 && cc_prev_status.mdep == XEXP (operands[0], 0)))	    output_asm_insn ("sethi %%hi(%m0),%%g1", xoperands);	  split_template = "st %r1,[%%g1+%%lo(%m0)]";	}      /* Output the branch instruction next.  */      output_asm_insn (template, operands);      /* Now output the load or store.	 No need to do a CC_STATUS_INIT, because we are branching anyway.  */      output_asm_insn (split_template, xoperands);    }  else    {      extern char *insn_template[];      extern char *(*insn_outfun[])();      int insn_code_number;      rtx pat = gen_rtx (SET, VOIDmode, dest, src);      rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);      int i;      extern rtx alter_subreg();      extern int insn_n_operands[];      /* Output the branch instruction first.  */      output_asm_insn (template, operands);      /* Now recognize the insn which we put in its delay slot.	 We must do this after outputing the branch insn,	 since operands may just be a pointer to `recog_operand'.  */      insn_code_number = recog (pat, delay_insn);      if (insn_code_number == -1)	abort ();      for (i = 0; i < insn_n_operands[insn_code_number]; i++)	{	  if (GET_CODE (recog_operand[i]) == SUBREG)	    recog_operand[i] = alter_subreg (recog_operand[i]);	}      /* Now get the template for what this insn would	 have been, without the branch.  Its operands are	 exactly the same as they would be, so we don't	 need to do an insn_extract.  */      template = insn_template[insn_code_number];      if (template == 0)	template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);      output_asm_insn (template, recog_operand);    }  CC_STATUS_INIT;  return "";}/* Output a newly constructed insn DELAY_INSN.  */char *output_delay_insn (delay_insn)     rtx delay_insn;{  char *template;  extern rtx recog_operand[];  extern char call_used_regs[];  extern char *insn_template[];  extern int insn_n_operands[];  extern char *(*insn_outfun[])();  extern rtx alter_subreg();  int insn_code_number;  extern int insn_n_operands[];  int i;  /* Now recognize the insn which we put in its delay slot.     We must do this after outputing the branch insn,     since operands may just be a pointer to `recog_operand'.  */  insn_code_number = recog_memoized (delay_insn);  if (insn_code_number == -1)    abort ();  /* Extract the operands of this delay insn.  */  INSN_CODE (delay_insn) = insn_code_number;  insn_extract (delay_insn);  /* It is possible that this insn has not been properly scaned by final     yet.  If this insn's operands don't appear in the peephole's     actual operands, then they won't be fixed up by final, so we     make sure they get fixed up here.  -- This is a kludge.  */  for (i = 0; i < insn_n_operands[insn_code_number]; i++)    {      if (GET_CODE (recog_operand[i]) == SUBREG)	recog_operand[i] = alter_subreg (recog_operand[i]);    }#ifdef REGISTER_CONSTRAINTS  if (! constrain_operands (insn_code_number))    abort ();#endif  cc_prev_status = cc_status;  /* Update `cc_status' for this instruction.     The instruction's output routine may change it further.     If the output routine for a jump insn needs to depend     on the cc status, it should look at cc_prev_status.  */  NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);  /* Now get the template for what this insn would     have been, without the branch.  */  template = insn_template[insn_code_number];  if (template == 0)    template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);  output_asm_insn (template, recog_operand);  return "";}/* Output the insn HEAD, keeping OPERANDS protected (wherever they are).   HEAD comes from the target of some branch, so before we output it,   we delete it from the target, lest we execute it twice.  The caller   of this function promises that such code motion is permissable.  */char *output_eager_then_insn (head, operands)     rtx head;     rtx *operands;{  extern rtx alter_subreg ();  extern int insn_n_operands[];  extern rtx recog_operand[];  rtx xoperands[MAX_RECOG_OPERANDS];  int insn_code_number, i, nbytes;  rtx nhead;  /* Micro-hack: run peephole on head if it looks like a good idea.     Right now there's only one such case worth doing...     This could be made smarter if the peephole for ``2-insn combine''     were also made smarter.  */  if (GET_CODE (PATTERN (head)) == SET      && REG_P (SET_SRC (PATTERN (head)))      && REG_P (SET_DEST (PATTERN (head)))      && (nhead = next_real_insn_no_labels (head))      && GET_CODE (nhead) == INSN      && GET_CODE (PATTERN (nhead)) == SET      && GET_CODE (SET_DEST (PATTERN (nhead))) == CC0      && (SET_SRC (PATTERN (nhead)) == SET_SRC (PATTERN (head))	  || SET_SRC (PATTERN (nhead)) == SET_DEST (PATTERN (head))))    /* Something's wrong if this does not fly.  */    if (! peephole (head))      abort ();  /* Save our contents of `operands', since output_delay_insn sets them.  */  insn_code_number = recog_memoized (head);  nbytes = insn_n_operands[insn_code_number] * sizeof (rtx);  bcopy (operands, xoperands, nbytes);  /* Output the delay insn, and prevent duplication later.  */  delete_insn (head);  output_delay_insn (head);  /* Restore this insn's operands.  */  bcopy (xoperands, operands, nbytes);}/* Return the next INSN, CALL_INSN or JUMP_INSN after LABEL;   or 0, if there is none.  Also return 0 if we cross a label.  */rtxnext_real_insn_no_labels (label)     rtx label;{  register rtx insn = NEXT_INSN (label);  register RTX_CODE code;  while (insn)    {      code = GET_CODE (insn);      if (code == INSN)	{	  if (GET_CODE (PATTERN (insn)) != CLOBBER	      && GET_CODE (PATTERN (insn)) != USE)	    return insn;	}      if (code == CALL_INSN || code == JUMP_INSN)	return insn;      if (code == CODE_LABEL)	return 0;      insn = NEXT_INSN (insn);    }  return 0;}intoperands_satisfy_eager_branch_peephole (operands, conditional)     rtx *operands;     int conditional;{  rtx label;  if (conditional)    {      if (GET_CODE (operands[0]) != IF_THEN_ELSE)	return 0;      if (GET_CODE (XEXP (operands[0], 1)) == LABEL_REF)	label = XEXP (XEXP (operands[0], 1), 0);      else if (GET_CODE (XEXP (operands[0], 2)) == LABEL_REF)	label = XEXP (XEXP (operands[0], 2), 0);      else return 0;    }  else    {      label = operands[0];    }  if (LABEL_NUSES (label) == 1)    {      rtx prev = PREV_INSN (label);      while (prev && GET_CODE (prev) == NOTE)	prev = PREV_INSN (prev);      if (prev == 0	  || GET_CODE (prev) == BARRIER)	{	  rtx head = next_real_insn_no_labels (label);	  if (head	      && ! INSN_DELETED_P (head)	      && GET_CODE (head) == INSN	      && GET_CODE (PATTERN (head)) == SET	      && strict_single_insn_op_p (SET_SRC (PATTERN (head)),					  GET_MODE (SET_DEST (PATTERN (head))))	      && strict_single_insn_op_p (SET_DEST (PATTERN (head)),					  GET_MODE (SET_DEST (PATTERN (head))))	      /* Moves between FP regs and CPU regs are two insns.  */	      && !(GET_CODE (SET_SRC (PATTERN (head))) == REG		   && GET_CODE (SET_DEST (PATTERN (head))) == REG		   && (FP_REG_P (SET_SRC (PATTERN (head)))		       != FP_REG_P (SET_DEST (PATTERN (head))))))	    {	      if (conditional == 2)		return (GET_CODE (operands[1]) != PC			&& safe_insn_src_p (operands[2], VOIDmode)			&& strict_single_insn_op_p (operands[2], VOIDmode)			&& operand_clobbered_before_used_after (operands[1], label));	      return 1;	    }	}    }  if (conditional == 1      && GET_CODE (operands[1]) != PC      && safe_insn_src_p (operands[2], VOIDmode)      && strict_single_insn_op_p (operands[2], VOIDmode)      && operand_clobbered_before_used_after (operands[1], label))    return 1;  return 0;}

⌨️ 快捷键说明

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