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

📄 m32r.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 5 页
字号:
  int               must_swap = 0;  switch (code)    {    case EQ:  compare_code = EQ;  branch_code = NE; break;    case NE:  compare_code = EQ;  branch_code = EQ; break;    case LT:  compare_code = LT;  branch_code = NE; break;    case LE:  compare_code = LT;  branch_code = EQ; must_swap = 1; break;    case GT:  compare_code = LT;  branch_code = NE; must_swap = 1; break;    case GE:  compare_code = LT;  branch_code = EQ; break;    case LTU: compare_code = LTU; branch_code = NE; break;    case LEU: compare_code = LTU; branch_code = EQ; must_swap = 1; break;    case GTU: compare_code = LTU; branch_code = NE; must_swap = 1; break;    case GEU: compare_code = LTU; branch_code = EQ; break;    }  if (need_compare)    {      switch (compare_code)	{	case EQ:	  if (GET_CODE (y) == CONST_INT	      && CMP_INT16_P (INTVAL (y))		/* reg equal to small const.  */	      && y != const0_rtx)	    {	      rtx tmp = gen_reg_rtx (SImode);			      	      emit_insn (gen_cmp_ne_small_const_insn (tmp, x, y));	      x = tmp;	      y = const0_rtx;	    }	  else if (CONSTANT_P (y))			/* reg equal to const.  */	    {	      rtx tmp = force_reg (GET_MODE (x), y);	      y = tmp;	    }	  if (register_operand (y, SImode) 		/* reg equal to reg.  */	      || y == const0_rtx) 	   		/* req equal to zero. */	    {		emit_insn (gen_cmp_eqsi_insn (x, y));			      return gen_rtx (code, mode, cc_reg, const0_rtx);	    }	  break;      	case LT:	  if (register_operand (y, SImode)	      || (GET_CODE (y) == CONST_INT && CMP_INT16_P (INTVAL (y))))	    {	      rtx tmp = gen_reg_rtx (SImode);	      /* reg compared to reg. */	      	      switch (code)		{		case LT:		  emit_insn (gen_cmp_ltsi_insn (x, y));		  code = EQ;		  break;		case LE:		  if (y == const0_rtx)		    tmp = const1_rtx;		  else		    emit_insn (gen_cmp_ne_small_const_insn (tmp, y, const1_rtx));		  emit_insn (gen_cmp_ltsi_insn (x, tmp));		  code = EQ;		  break;		case GT:		  if (GET_CODE (y) == CONST_INT)		    tmp = gen_rtx (PLUS, SImode, y, const1_rtx);		  else		    emit_insn (gen_cmp_ne_small_const_insn (tmp, y, const1_rtx));		  emit_insn (gen_cmp_ltsi_insn (x, tmp));		  code = NE;		  break;		case GE:		  emit_insn (gen_cmp_ltsi_insn (x, y));		  code = NE;		  break;		default:		  abort();		}	      	      return gen_rtx (code, mode, cc_reg, const0_rtx);	    }	  break;	  	case LTU:	  if (register_operand (y, SImode)	      || (GET_CODE (y) == CONST_INT && CMP_INT16_P (INTVAL (y))))	    {	      rtx tmp = gen_reg_rtx (SImode);	      /* reg (unsigned) compared to reg. */	      	      switch (code)		{		case LTU:		  emit_insn (gen_cmp_ltusi_insn (x, y));		  code = EQ;		  break;		case LEU:		  if (y == const0_rtx)		    tmp = const1_rtx;		  else		    emit_insn (gen_cmp_ne_small_const_insn (tmp, y, const1_rtx));		  emit_insn (gen_cmp_ltusi_insn (x, tmp));		  code = EQ;		  break;		case GTU:		  if (GET_CODE (y) == CONST_INT)		    tmp = gen_rtx (PLUS, SImode, y, const1_rtx);		  else		    emit_insn (gen_cmp_ne_small_const_insn (tmp, y, const1_rtx));		  emit_insn (gen_cmp_ltusi_insn (x, tmp));		  code = NE;		  break;		case GEU:		  emit_insn (gen_cmp_ltusi_insn (x, y));		  code = NE;		  break;		default:		  abort();		}	      	      return gen_rtx (code, mode, cc_reg, const0_rtx);	    }	  break;	default:	  abort();	}    }  else    if (! TARGET_OLD_COMPARE)    {      /* reg/reg equal comparison */      if (compare_code == EQ	  && register_operand (y, SImode))	return gen_rtx (code, mode, x, y);            /* reg/zero signed comparison */      if ((compare_code == EQ || compare_code == LT)	  && y == const0_rtx)	return gen_rtx (code, mode, x, y);            /* reg/smallconst equal comparison */      if (compare_code == EQ	  && GET_CODE (y) == CONST_INT	  && CMP_INT16_P (INTVAL (y)))	{	  rtx tmp = gen_reg_rtx (SImode);	  emit_insn (gen_cmp_ne_small_const_insn (tmp, x, y));	  return gen_rtx (code, mode, tmp, const0_rtx);	}            /* reg/const equal comparison */      if (compare_code == EQ	  && CONSTANT_P (y))	{	  rtx tmp = force_reg (GET_MODE (x), y);	  return gen_rtx (code, mode, x, tmp);	}    }  if (CONSTANT_P (y))    {      if (must_swap)	y = force_reg (GET_MODE (x), y);      else	{	  int ok_const =	    (code == LTU || code == LEU || code == GTU || code == GEU)	    ? uint16_operand (y, GET_MODE (y))	    : reg_or_cmp_int16_operand (y, GET_MODE (y));	  	  if (! ok_const)	    y = force_reg (GET_MODE (x), y);	}    }  switch (compare_code)    {    case EQ :      emit_insn (gen_cmp_eqsi_insn (must_swap ? y : x, must_swap ? x : y));      break;    case LT :      emit_insn (gen_cmp_ltsi_insn (must_swap ? y : x, must_swap ? x : y));      break;    case LTU :      emit_insn (gen_cmp_ltusi_insn (must_swap ? y : x, must_swap ? x : y));      break;    }  return gen_rtx (branch_code, VOIDmode, cc_reg, CONST0_RTX (mode));}/* Split a 2 word move (DI or DF) into component parts.  */rtxgen_split_move_double (operands)     rtx operands[];{  enum machine_mode mode = GET_MODE (operands[0]);  rtx dest = operands[0];  rtx src  = operands[1];  rtx val;  /* We might have (SUBREG (MEM)) here, so just get rid of the     subregs to make this code simpler.  It is safe to call     alter_subreg any time after reload.  */  if (GET_CODE (dest) == SUBREG)    dest = alter_subreg (dest);  if (GET_CODE (src) == SUBREG)    src = alter_subreg (src);  start_sequence ();  if (GET_CODE (dest) == REG)    {      int dregno = REGNO (dest);      /* reg = reg */      if (GET_CODE (src) == REG)	{	  int sregno = REGNO (src);	  int reverse = (dregno == sregno + 1);	  /* We normally copy the low-numbered register first.  However, if	     the first register operand 0 is the same as the second register of	     operand 1, we must copy in the opposite order.  */	  emit_insn (gen_rtx_SET (VOIDmode,				  operand_subword (dest, reverse, TRUE, mode),				  operand_subword (src,  reverse, TRUE, mode)));	  emit_insn (gen_rtx_SET (VOIDmode,				  operand_subword (dest, !reverse, TRUE, mode),				  operand_subword (src,  !reverse, TRUE, mode)));	}      /* reg = constant */      else if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)	{	  rtx words[2];	  split_double (src, &words[0], &words[1]);	  emit_insn (gen_rtx_SET (VOIDmode,				  operand_subword (dest, 0, TRUE, mode),				  words[0]));	  emit_insn (gen_rtx_SET (VOIDmode,				  operand_subword (dest, 1, TRUE, mode),				  words[1]));	}      /* reg = mem */      else if (GET_CODE (src) == MEM)	{	  /* If the high-address word is used in the address, we must load it	     last.  Otherwise, load it first.  */	  rtx addr = XEXP (src, 0);	  int reverse = (refers_to_regno_p (dregno, dregno+1, addr, 0) != 0);	  /* We used to optimize loads from single registers as		ld r1,r3+; ld r2,r3	     if r3 were not used subsequently.  However, the REG_NOTES aren't	     propigated correctly by the reload phase, and it can cause bad	     code to be generated.  We could still try:		ld r1,r3+; ld r2,r3; addi r3,-4	     which saves 2 bytes and doesn't force longword alignment.  */	  emit_insn (gen_rtx_SET (VOIDmode,				  operand_subword (dest, reverse, TRUE, mode),				  change_address (src, SImode,						  plus_constant (addr,								 reverse * UNITS_PER_WORD))));	  emit_insn (gen_rtx_SET (VOIDmode,				  operand_subword (dest, !reverse, TRUE, mode),				  change_address (src, SImode,						  plus_constant (addr,								 (!reverse) * UNITS_PER_WORD))));	}      else	abort ();    }  /* mem = reg */  /* We used to optimize loads from single registers as	st r1,r3; st r2,+r3     if r3 were not used subsequently.  However, the REG_NOTES aren't     propigated correctly by the reload phase, and it can cause bad     code to be generated.  We could still try:	st r1,r3; st r2,+r3; addi r3,-4     which saves 2 bytes and doesn't force longword alignment.  */  else if (GET_CODE (dest) == MEM && GET_CODE (src) == REG)    {      rtx addr = XEXP (dest, 0);      emit_insn (gen_rtx_SET (VOIDmode,			      change_address (dest, SImode, addr),			      operand_subword (src, 0, TRUE, mode)));      emit_insn (gen_rtx_SET (VOIDmode,			      change_address (dest, SImode,					      plus_constant (addr, UNITS_PER_WORD)),			      operand_subword (src, 1, TRUE, mode)));    }  else    abort ();  val = gen_sequence ();  end_sequence ();  return val;}/* Implements the FUNCTION_ARG_PARTIAL_NREGS macro.  */intfunction_arg_partial_nregs (cum, int_mode, type, named)     CUMULATIVE_ARGS *cum;     int int_mode;     tree type;     int named;{  enum machine_mode mode = (enum machine_mode)int_mode;  int ret;  int size = (((mode == BLKmode && type)	       ? int_size_in_bytes (type)	       : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;  if (*cum >= M32R_MAX_PARM_REGS)    ret = 0;  else if (*cum + size > M32R_MAX_PARM_REGS)    ret = (*cum + size) - M32R_MAX_PARM_REGS;  else    ret = 0;  return ret;}/* Do any needed setup for a variadic function.  For the M32R, we must   create a register parameter block, and then copy any anonymous arguments   in registers to memory.   CUM has not been updated for the last named argument which has type TYPE   and mode MODE, and we rely on this fact.  */voidm32r_setup_incoming_varargs (cum, int_mode, type, pretend_size, no_rtl)     CUMULATIVE_ARGS *cum;     int int_mode;     tree type;     int *pretend_size;     int no_rtl;{  enum machine_mode mode = (enum machine_mode)int_mode;  int first_anon_arg;  if (no_rtl)    return;  /* All BLKmode values are passed by reference.  */  if (mode == BLKmode)    abort ();  /* We must treat `__builtin_va_alist' as an anonymous arg.  */  if (current_function_varargs)    first_anon_arg = *cum;  else    first_anon_arg = (ROUND_ADVANCE_CUM (*cum, mode, type)		      + ROUND_ADVANCE_ARG (mode, type));  if (first_anon_arg < M32R_MAX_PARM_REGS)    {      /* Note that first_reg_offset < M32R_MAX_PARM_REGS.  */      int first_reg_offset = first_anon_arg;      /* Size in words to "pretend" allocate.  */      int size = M32R_MAX_PARM_REGS - first_reg_offset;      rtx regblock;      regblock = gen_rtx (MEM, BLKmode,			  plus_constant (arg_pointer_rtx,					 FIRST_PARM_OFFSET (0)));      move_block_from_reg (first_reg_offset, regblock,			   size, size * UNITS_PER_WORD);      *pretend_size = (size * UNITS_PER_WORD);    }}/* Cost functions.  *//* Provide the costs of an addressing mode that contains ADDR.   If ADDR is not a valid address, its cost is irrelevant.   This function is trivial at the moment.  This code doesn't live   in m32r.h so it's easy to experiment.  */intm32r_address_cost (addr)     rtx addr;{  return 1;}/* Type of function DECL.   The result is cached.  To reset the cache at the end of a function,   call with DECL = NULL_TREE.  */enum m32r_function_typem32r_compute_function_type (decl)     tree decl;{  /* Cached value.  */  static enum m32r_function_type fn_type = M32R_FUNCTION_UNKNOWN;  /* Last function we were called for.  */  static tree last_fn = NULL_TREE;  /* Resetting the cached value?  */  if (decl == NULL_TREE)    {      fn_type = M32R_FUNCTION_UNKNOWN;      last_fn = NULL_TREE;      return fn_type;    }  if (decl == last_fn && fn_type != M32R_FUNCTION_UNKNOWN)    return fn_type;  /* Compute function type.  */  fn_type = (lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (current_function_decl)) != NULL_TREE	     ? M32R_FUNCTION_INTERRUPT	     : M32R_FUNCTION_NORMAL);  last_fn = decl;  return fn_type;}/* Function prologue/epilogue handlers.  *//* M32R stack frames look like:             Before call                       After call        +-----------------------+       +-----------------------+        |                       |       |                       |   high |  local variables,     |       |  local variables,     |   mem  |  reg save area, etc.  |       |  reg save area, etc.  |        |                       |       |                       |        +-----------------------+       +-----------------------+        |                       |       |                       |        |  arguments on stack.  |       |  arguments on stack.  |        |                       |       |                       |  SP+0->+-----------------------+       +-----------------------+                                        |  reg parm save area,  |                                        |  only created for     |                                            |  variable argument    |                                            |  functions            |    					+-----------------------+                                        |   previous frame ptr  |                                        +-----------------------+                                            |                       |                                            |  register save area   |                                            |                       |    					+-----------------------+                                        |    return address     |                                            +-----------------------+                                            |                       |                                            |  local variables      |    

⌨️ 快捷键说明

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