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

📄 optabs.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	      register rtx t0 = gen_reg_rtx (wider_mode);	      register rtx t1 = gen_reg_rtx (wider_mode);	      if (expand_twoval_binop (binoptab,				       convert_to_mode (wider_mode, op0,							unsignedp),				       convert_to_mode (wider_mode, op1,							unsignedp),				       t0, t1, unsignedp))		{		  convert_move (targ0, t0, unsignedp);		  convert_move (targ1, t1, unsignedp);		  return 1;		}	      else		delete_insns_since (last);	    }	}    }  delete_insns_since (entry_last);  return 0;}/* Generate code to perform an operation specified by UNOPTAB   on operand OP0, with result having machine-mode MODE.   UNSIGNEDP is for the case where we have to widen the operands   to perform the operation.  It says to use zero-extension.   If TARGET is nonzero, the value   is generated there, if it is convenient to do so.   In all cases an rtx is returned for the locus of the value;   this may or may not be TARGET.  */rtxexpand_unop (mode, unoptab, op0, target, unsignedp)     enum machine_mode mode;     optab unoptab;     rtx op0;     rtx target;     int unsignedp;{  enum mode_class class;  enum machine_mode wider_mode;  register rtx temp;  rtx last = get_last_insn ();  rtx pat;  class = GET_MODE_CLASS (mode);  op0 = protect_from_queue (op0, 0);  if (flag_force_mem)    {      op0 = force_not_mem (op0);    }  if (target)    target = protect_from_queue (target, 1);  if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)    {      int icode = (int) unoptab->handlers[(int) mode].insn_code;      enum machine_mode mode0 = insn_operand_mode[icode][1];      rtx xop0 = op0;      if (target)	temp = target;      else	temp = gen_reg_rtx (mode);      if (GET_MODE (xop0) != VOIDmode	  && GET_MODE (xop0) != mode0)	xop0 = convert_to_mode (mode0, xop0, unsignedp);      /* Now, if insn doesn't accept our operand, put it into a pseudo.  */      if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))	xop0 = copy_to_mode_reg (mode0, xop0);      if (! (*insn_operand_predicate[icode][0]) (temp, mode))	temp = gen_reg_rtx (mode);      pat = GEN_FCN (icode) (temp, xop0);      if (pat)	{	  if (GET_CODE (pat) == SEQUENCE	      && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))	    {	      delete_insns_since (last);	      return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);	    }	  emit_insn (pat);	  	  return temp;	}      else	delete_insns_since (last);    }  /* It can't be done in this mode.  Can we open-code it in a wider mode?  */  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)    for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;	 wider_mode = GET_MODE_WIDER_MODE (wider_mode))      {	if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)	  {	    rtx xop0 = op0;	    /* For certain operations, we need not actually extend	       the narrow operand, as long as we will truncate the	       results to the same narrowness.  But it is faster to	       convert a SUBREG due to mode promotion.  */	    if ((unoptab == neg_optab || unoptab == one_cmpl_optab)		&& GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD		&& class == MODE_INT		&& ! (GET_CODE (xop0) == SUBREG		      && SUBREG_PROMOTED_VAR_P (xop0)))	      xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0);	    else	      xop0 = convert_to_mode (wider_mode, xop0, unsignedp);	      	    temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,				unsignedp);	    if (temp)	      {		if (class != MODE_INT)		  {		    if (target == 0)		      target = gen_reg_rtx (mode);		    convert_move (target, temp, 0);		    return target;		  }		else		  return gen_lowpart (mode, temp);	      }	    else	      delete_insns_since (last);	  }      }  /* These can be done a word at a time.  */  if (unoptab == one_cmpl_optab      && class == MODE_INT      && GET_MODE_SIZE (mode) > UNITS_PER_WORD      && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)    {      int i;      rtx insns;      if (target == 0 || target == op0)	target = gen_reg_rtx (mode);      start_sequence ();      /* Do the actual arithmetic.  */      for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)	{	  rtx target_piece = operand_subword (target, i, 1, mode);	  rtx x = expand_unop (word_mode, unoptab,			       operand_subword_force (op0, i, mode),			       target_piece, unsignedp);	  if (target_piece != x)	    emit_move_insn (target_piece, x);	}      insns = get_insns ();      end_sequence ();      emit_no_conflict_block (insns, target, op0, NULL_RTX,			      gen_rtx (unoptab->code, mode, op0));      return target;    }  /* Open-code the complex negation operation.  */  else if (unoptab == neg_optab	   && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))    {      rtx target_piece;      rtx x;      rtx seq;      /* Find the correct mode for the real and imaginary parts */      enum machine_mode submode	= mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,			 class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,			 0);      if (submode == BLKmode)	abort ();      if (target == 0)	target = gen_reg_rtx (mode);            start_sequence ();      target_piece = gen_imagpart (submode, target);      x = expand_unop (submode, unoptab,		       gen_imagpart (submode, op0),		       target_piece, unsignedp);      if (target_piece != x)	emit_move_insn (target_piece, x);      target_piece = gen_realpart (submode, target);      x = expand_unop (submode, unoptab,		       gen_realpart (submode, op0),		       target_piece, unsignedp);      if (target_piece != x)	emit_move_insn (target_piece, x);      seq = get_insns ();      end_sequence ();      emit_no_conflict_block (seq, target, op0, 0,			      gen_rtx (unoptab->code, mode, op0));      return target;    }  /* Now try a library call in this mode.  */  if (unoptab->handlers[(int) mode].libfunc)    {      rtx insns;      rtx funexp = unoptab->handlers[(int) mode].libfunc;      start_sequence ();      /* Pass 1 for NO_QUEUE so we don't lose any increments	 if the libcall is cse'd or moved.  */      emit_library_call (unoptab->handlers[(int) mode].libfunc,			 1, mode, 1, op0, mode);      insns = get_insns ();      end_sequence ();      target = gen_reg_rtx (mode);      emit_libcall_block (insns, target, hard_libcall_value (mode),			  gen_rtx (unoptab->code, mode, op0));      return target;    }  /* It can't be done in this mode.  Can we do it in a wider mode?  */  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)    {      for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))	{	  if ((unoptab->handlers[(int) wider_mode].insn_code	       != CODE_FOR_nothing)	      || unoptab->handlers[(int) wider_mode].libfunc)	    {	      rtx xop0 = op0;	      /* For certain operations, we need not actually extend		 the narrow operand, as long as we will truncate the		 results to the same narrowness.  */	      if ((unoptab == neg_optab || unoptab == one_cmpl_optab)		  && GET_MODE_SIZE (wider_mode) <= UNITS_PER_WORD		  && class == MODE_INT		  && ! (GET_CODE (xop0) == SUBREG			&& SUBREG_PROMOTED_VAR_P (xop0)))		xop0 = gen_rtx (SUBREG, wider_mode, force_reg (mode, xop0), 0);	      else		xop0 = convert_to_mode (wider_mode, xop0, unsignedp);	      	      temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,				  unsignedp);	      if (temp)		{		  if (class != MODE_INT)		    {		      if (target == 0)			target = gen_reg_rtx (mode);		      convert_move (target, temp, 0);		      return target;		    }		  else		    return gen_lowpart (mode, temp);		}	      else		delete_insns_since (last);	    }	}    }  return 0;}/* Emit code to compute the absolute value of OP0, with result to   TARGET if convenient.  (TARGET may be 0.)  The return value says   where the result actually is to be found.   MODE is the mode of the operand; the mode of the result is   different but can be deduced from MODE.   UNSIGNEDP is relevant for complex integer modes.  */rtxexpand_complex_abs (mode, op0, target, unsignedp)     enum machine_mode mode;     rtx op0;     rtx target;     int unsignedp;{  enum mode_class class = GET_MODE_CLASS (mode);  enum machine_mode wider_mode;  register rtx temp;  rtx entry_last = get_last_insn ();  rtx last;  rtx pat;  /* Find the correct mode for the real and imaginary parts.  */  enum machine_mode submode    = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,		     class == MODE_COMPLEX_INT ? MODE_INT : MODE_FLOAT,		     0);  if (submode == BLKmode)    abort ();  op0 = protect_from_queue (op0, 0);  if (flag_force_mem)    {      op0 = force_not_mem (op0);    }  last = get_last_insn ();  if (target)    target = protect_from_queue (target, 1);  if (abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)    {      int icode = (int) abs_optab->handlers[(int) mode].insn_code;      enum machine_mode mode0 = insn_operand_mode[icode][1];      rtx xop0 = op0;      if (target)	temp = target;      else	temp = gen_reg_rtx (submode);      if (GET_MODE (xop0) != VOIDmode	  && GET_MODE (xop0) != mode0)	xop0 = convert_to_mode (mode0, xop0, unsignedp);      /* Now, if insn doesn't accept our operand, put it into a pseudo.  */      if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))	xop0 = copy_to_mode_reg (mode0, xop0);      if (! (*insn_operand_predicate[icode][0]) (temp, submode))	temp = gen_reg_rtx (submode);      pat = GEN_FCN (icode) (temp, xop0);      if (pat)	{	  if (GET_CODE (pat) == SEQUENCE	      && ! add_equal_note (pat, temp, abs_optab->code, xop0, NULL_RTX))	    {	      delete_insns_since (last);	      return expand_unop (mode, abs_optab, op0, NULL_RTX, unsignedp);	    }	  emit_insn (pat);	  	  return temp;	}      else	delete_insns_since (last);    }  /* It can't be done in this mode.  Can we open-code it in a wider mode?  */  for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;       wider_mode = GET_MODE_WIDER_MODE (wider_mode))    {      if (abs_optab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)	{	  rtx xop0 = op0;	  xop0 = convert_to_mode (wider_mode, xop0, unsignedp);	  temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);	  if (temp)	    {	      if (class != MODE_COMPLEX_INT)		{		  if (target == 0)		    target = gen_reg_rtx (submode);		  convert_move (target, temp, 0);		  return target;		}	      else		return gen_lowpart (submode, temp);	    }	  else	    delete_insns_since (last);	}    }  /* Open-code the complex absolute-value operation     if we can open-code sqrt.  Otherwise it's not worth while.  */  if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing)    {      rtx real, imag, total;      real = gen_realpart (submode, op0);      imag = gen_imagpart (submode, op0);      /* Square both parts.  */      real = expand_mult (mode, real, real, NULL_RTX, 0);      imag = expand_mult (mode, imag, imag, NULL_RTX, 0);      /* Sum the parts.  */      total = expand_binop (submode, add_optab, real, imag, 0,			    0, OPTAB_LIB_WIDEN);      /* Get sqrt in TARGET.  Set TARGET to where the result is.  */      target = expand_unop (submode, sqrt_optab, total, target, 0);      if (target == 0)	delete_insns_since (last);      else	return target;    }  /* Now try a library call in this mode.  */  if (abs_optab->handlers[(int) mode].libfunc)    {      rtx insns;      rtx funexp = abs_optab->handlers[(int) mode].libfunc;      start_sequence ();      /* Pass 1 for NO_QUEUE so we don't lose any increments	 if the libcall is cse'd or moved.  */      emit_library_call (abs_optab->handlers[(int) mode].libfunc,			 1, mode, 1, op0, mode);      insns = get_insns ();      end_sequence ();      target = gen_reg_rtx (submode);      emit_libcall_block (insns, target, hard_libcall_value (submode),			  gen_rtx (abs_optab->code, mode, op0));

⌨️ 快捷键说明

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