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

📄 optabs.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	    {	      x = convert_to_mode (wider_mode, x, unsignedp);	      y = convert_to_mode (wider_mode, y, unsignedp);	      emit_cmp_insn (x, y, 0, unsignedp, align);	    }	}      return;    }  abort ();}/* These three functions generate an insn body and return it   rather than emitting the insn.   They do not protect from queued increments,   because they may be used 1) in protect_from_queue itself   and 2) in other passes where there is no queue.  *//* Generate and return an insn body to add Y to X.  */rtxgen_add2_insn (x, y)     rtx x, y;{  return (GEN_FCN (add_optab->handlers[(int) GET_MODE (x)].insn_code)	  (x, x, y));}inthave_add2_insn (mode)     enum machine_mode mode;{  return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;}/* Generate and return an insn body to subtract Y from X.  */rtxgen_sub2_insn (x, y)     rtx x, y;{  return (GEN_FCN (sub_optab->handlers[(int) GET_MODE (x)].insn_code)	  (x, x, y));}inthave_sub2_insn (mode)     enum machine_mode mode;{  return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;}/* Generate the body of an instruction to copy Y into X.  */rtxgen_move_insn (x, y)     rtx x, y;{  register enum machine_mode mode = GET_MODE (x);  if (mode == VOIDmode)    mode = GET_MODE (y);  return (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));}#if 0/* Tables of patterns for extending one integer mode to another.  */enum insn_code zero_extend_optab[MAX_MACHINE_MODE][MAX_MACHINE_MODE];enum insn_code sign_extend_optab[MAX_MACHINE_MODE][MAX_MACHINE_MODE];/* Generate the body of an insn to extend Y (with mode MFROM)   into X (with mode MTO).  Do zero-extension if UNSIGNEDP is nonzero.  */rtxgen_extend_insn (x, y, mto, mfrom, unsignedp)     rtx x, y;     enum machine_mode mto, mfrom;     int unsignedp;{  return (GEN_FCN ((unsignedp ? zero_extend_optab : sign_extend_optab)		   [(int)mto][(int)mfrom])	  (x, y));}static voidinit_extends (){  bzero (sign_extend_optab, sizeof sign_extend_optab);  bzero (zero_extend_optab, sizeof zero_extend_optab);  sign_extend_optab[(int) SImode][(int) HImode] = CODE_FOR_extendhisi2;  sign_extend_optab[(int) SImode][(int) QImode] = CODE_FOR_extendqisi2;  sign_extend_optab[(int) HImode][(int) QImode] = CODE_FOR_extendqihi2;  zero_extend_optab[(int) SImode][(int) HImode] = CODE_FOR_zero_extendhisi2;  zero_extend_optab[(int) SImode][(int) QImode] = CODE_FOR_zero_extendqisi2;  zero_extend_optab[(int) HImode][(int) QImode] = CODE_FOR_zero_extendqihi2;}#endif/* can_fix_p and can_float_p say whether the target machine   can directly convert a given fixed point type to   a given floating point type, or vice versa.   The returned value is the CODE_FOR_... value to use,   or CODE_FOR_nothing if these modes cannot be directly converted.  */static enum insn_code fixtab[2][2][2];static enum insn_code fixtrunctab[2][2][2];static enum insn_code floattab[2][2];/* *TRUNCP_PTR is set to 1 if it is necessary to output   an explicit FTRUNC insn before the fix insn; otherwise 0.  */static enum insn_codecan_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)     enum machine_mode fltmode, fixmode;     int unsignedp;     int *truncp_ptr;{  *truncp_ptr = 0;  if (fixtrunctab[fltmode != SFmode][fixmode == DImode][unsignedp]      != CODE_FOR_nothing)    return fixtrunctab[fltmode != SFmode][fixmode == DImode][unsignedp];  if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)    {      *truncp_ptr = 1;      return fixtab[fltmode != SFmode][fixmode == DImode][unsignedp];    }  return CODE_FOR_nothing;}static enum insn_codecan_float_p (fltmode, fixmode)     enum machine_mode fixmode, fltmode;{  return floattab[fltmode != SFmode][fixmode == DImode];}voidinit_fixtab (){  enum insn_code *p;  for (p = fixtab[0][0];       p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]);        p++)    *p = CODE_FOR_nothing;  for (p = fixtrunctab[0][0];       p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]);        p++)    *p = CODE_FOR_nothing;#ifdef HAVE_fixsfsi2  if (HAVE_fixsfsi2)    fixtab[0][0][0] = CODE_FOR_fixsfsi2;#endif#ifdef HAVE_fixsfdi2  if (HAVE_fixsfdi2)    fixtab[0][1][0] = CODE_FOR_fixsfdi2;#endif#ifdef HAVE_fixdfsi2  if (HAVE_fixdfsi2)    fixtab[1][0][0] = CODE_FOR_fixdfsi2;#endif#ifdef HAVE_fixdfdi2  if (HAVE_fixdfdi2)    fixtab[1][1][0] = CODE_FOR_fixdfdi2;#endif#ifdef HAVE_fixunssfsi2  if (HAVE_fixunssfsi2)    fixtab[0][0][1] = CODE_FOR_fixunssfsi2;#endif#ifdef HAVE_fixunssfdi2  if (HAVE_fixunssfdi2)    fixtab[0][1][1] = CODE_FOR_fixunssfdi2;#endif#ifdef HAVE_fixunsdfsi2  if (HAVE_fixunsdfsi2)    fixtab[1][0][1] = CODE_FOR_fixunsdfsi2;#endif#ifdef HAVE_fixunsdfdi2  if (HAVE_fixunsdfdi2)    fixtab[1][1][1] = CODE_FOR_fixunsdfdi2;#endif#ifdef HAVE_fix_truncsfsi2  if (HAVE_fix_truncsfsi2)    fixtrunctab[0][0][0] = CODE_FOR_fix_truncsfsi2;#endif#ifdef HAVE_fix_truncsfdi2  if (HAVE_fix_truncsfdi2)    fixtrunctab[0][1][0] = CODE_FOR_fix_truncsfdi2;#endif#ifdef HAVE_fix_truncdfsi2  if (HAVE_fix_truncdfsi2)    fixtrunctab[1][0][0] = CODE_FOR_fix_truncdfsi2;#endif#ifdef HAVE_fix_truncdfdi2  if (HAVE_fix_truncdfdi2)    fixtrunctab[1][1][0] = CODE_FOR_fix_truncdfdi2;#endif#ifdef HAVE_fixuns_truncsfsi2  if (HAVE_fixuns_truncsfsi2)    fixtrunctab[0][0][1] = CODE_FOR_fixuns_truncsfsi2;#endif#ifdef HAVE_fixuns_truncsfdi2  if (HAVE_fixuns_truncsfdi2)    fixtrunctab[0][1][1] = CODE_FOR_fixuns_truncsfdi2;#endif#ifdef HAVE_fixuns_truncdfsi2  if (HAVE_fixuns_truncdfsi2)    fixtrunctab[1][0][1] = CODE_FOR_fixuns_truncdfsi2;#endif#ifdef HAVE_fixuns_truncdfdi2  if (HAVE_fixuns_truncdfdi2)    fixtrunctab[1][1][1] = CODE_FOR_fixuns_truncdfdi2;#endif#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC  /* This flag says the same insns that convert to a signed fixnum     also convert validly to an unsigned one.  */  {    int i;    int j;    for (i = 0; i < 2; i++)      for (j = 0; j < 2; j++)	fixtrunctab[i][j][1] = fixtrunctab[i][j][0];  }#endif}voidinit_floattab (){  enum insn_code *p;  for (p = floattab[0];       p < floattab[0] + sizeof floattab / sizeof (floattab[0][0]);        p++)    *p = CODE_FOR_nothing;#ifdef HAVE_floatsisf2  if (HAVE_floatsisf2)    floattab[0][0] = CODE_FOR_floatsisf2;#endif#ifdef HAVE_floatdisf2  if (HAVE_floatdisf2)    floattab[0][1] = CODE_FOR_floatdisf2;#endif#ifdef HAVE_floatsidf2  if (HAVE_floatsidf2)    floattab[1][0] = CODE_FOR_floatsidf2;#endif#ifdef HAVE_floatdidf2  if (HAVE_floatdidf2)    floattab[1][1] = CODE_FOR_floatdidf2;#endif}/* Generate code to convert FROM to floating point   and store in TO.  FROM must be fixed point.   UNSIGNEDP nonzero means regard FROM as unsigned.   Normally this is done by correcting the final value   if it is negative.  */voidexpand_float (real_to, from, unsignedp)     rtx real_to, from;     int unsignedp;{  enum insn_code icode;  register rtx to;  /* Constants should get converted in `fold'.     We lose here since we don't know the mode.  */  if (GET_MODE (from) == VOIDmode)    abort ();  to = real_to = protect_from_queue (real_to, 1);  from = protect_from_queue (from, 0);  if (flag_force_mem)    {      from = force_not_mem (from);    }  /* If we are about to do some arithmetic to correct for an     unsigned operand, do it in a pseudo-register.  */  if (unsignedp      && ! (GET_CODE (to) == REG && REGNO (to) >= FIRST_PSEUDO_REGISTER))    to = gen_reg_rtx (GET_MODE (to));  /* Now do the basic conversion.  Do it in the specified modes if possible;     otherwise convert either input, output or both with wider mode;     otherwise use a library call.  */  if ((icode = can_float_p (GET_MODE (to), GET_MODE (from)))      != CODE_FOR_nothing)    {      emit_unop_insn (icode, to, from, FLOAT);    }  else if (GET_MODE (to) == SFmode	   && ((icode = can_float_p (DFmode, GET_MODE (from)))	       != CODE_FOR_nothing))    {      to = gen_reg_rtx (DFmode);      emit_unop_insn (icode, to, from, FLOAT);    }  /* If we can't float a SI, maybe we can float a DI.     If so, convert to DI and then float.  */  else if (GET_MODE (from) != DImode	   && (can_float_p (GET_MODE (to), DImode) != CODE_FOR_nothing	       || can_float_p (DFmode, DImode) != CODE_FOR_nothing))    {      register rtx tem = gen_reg_rtx (DImode);      convert_move (tem, from, unsignedp);      from = tem;      /* If we extend FROM then we don't need to correct	 the final value for unsignedness.  */      unsignedp = 0;      if ((icode = can_float_p (GET_MODE (to), GET_MODE (from)))	  != CODE_FOR_nothing)	{	  emit_unop_insn (icode, to, from, FLOAT);	}      else if ((icode = can_float_p (DFmode, DImode))	        != CODE_FOR_nothing)	{	  to = gen_reg_rtx (DFmode);	  emit_unop_insn (icode, to, from, FLOAT);	}    }  /* No hardware instruction available; call a library     to convert from SImode or DImode into DFmode.  */  else    {      if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))	{	  from = convert_to_mode (SImode, from, unsignedp);	  unsignedp = 0;	}      emit_library_call (gen_rtx (SYMBOL_REF, Pmode,				  (GET_MODE (from) == SImode ? "__floatsidf"				   : "__floatdidf")),			 0, DFmode, 1, from, GET_MODE (from));      to = copy_to_reg (hard_libcall_value (DFmode));    }  /* If FROM was unsigned but we treated it as signed,     then in the case where it is negative (and therefore TO is negative),     correct its value by 2**bitwidth.  */  if (unsignedp)    {      rtx label = gen_label_rtx ();      rtx temp;      REAL_VALUE_TYPE offset;      do_pending_stack_adjust ();      emit_cmp_insn (to, GET_MODE (to) == DFmode ? dconst0_rtx : fconst0_rtx,		     0, 0, 0);      emit_jump_insn (gen_bge (label));      /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).  */      offset = REAL_VALUE_LDEXP (0.5, GET_MODE_BITSIZE (GET_MODE (from)) + 1);      temp = expand_binop (GET_MODE (to), add_optab, to,			   immed_real_const_1 (offset, GET_MODE (to)),			   to, 0, OPTAB_LIB_WIDEN);      if (temp != to)	emit_move_insn (to, temp);      do_pending_stack_adjust ();      emit_label (label);    }  /* Copy result to requested destination     if we have been computing in a temp location.  */  if (to != real_to)    {      if (GET_MODE (real_to) == GET_MODE (to))	emit_move_insn (real_to, to);      else	convert_move (real_to, to, 0);    }}/* expand_fix: generate code to convert FROM to fixed point   and store in TO.  FROM must be floating point.  */static rtxftruncify (x)     rtx x;{  rtx temp = gen_reg_rtx (GET_MODE (x));  return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);}voidexpand_fix (to, from, unsignedp)     register rtx to, from;     int unsignedp;{  enum insn_code icode;  register rtx target;  int must_trunc = 0;  while (1)    {      icode = can_fix_p (GET_MODE (to), GET_MODE (from), unsignedp, &must_trunc);      if (icode != CODE_FOR_nothing)	{	  if (must_trunc)	    from = ftruncify (from);	  emit_unop_insn (icode, to, from, FIX);	  return;	}#if 0  /* Turned off.  It fails because the positive numbers	  that become temporarily negative are rounded up instead of down.  */      /* If no insns for unsigned conversion,	 we can go via a signed number.	 But make sure we won't overflow in the compiler.  */      if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_INT	  /* Make sure we won't lose significant bits doing this.  */	  && GET_MODE_BITSIZE (GET_MODE (from)) > GET_MODE_BITSIZE (GET_MODE (to)))	{	  icode = can_fix_p (GET_MODE (to), GET_MODE (from),			     0, &must_trunc);	  if (icode != CODE_FOR_nothing)	    {	      REAL_VALUE_TYPE offset;	      rtx temp, temp1;	      int bitsize = GET_MODE_BITSIZE (GET_MODE (to));	      if (must_trunc)		from = ftruncify (from);	      /* Subtract 2**(N-1), convert to signed number,		 then add 2**(N-1).  */	      /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).  */	      offset = REAL_VALUE_LDEXP (0.5, bitsize);	      temp = expand_binop (GET_MODE (from), sub_optab, from,				   immed_real_const_1 (offset, GET_MODE (from)),				   0, 0, OPTAB_LIB_WIDEN);

⌨️ 快捷键说明

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