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

📄 xtensa.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    return nonimmed_operand (op, mode);  return mem_operand (op, mode);}intsext_fldsz_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  return ((GET_CODE (op) == CONST_INT) && xtensa_tp7 (INTVAL (op) - 1));}intlsbitnum_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  if (GET_CODE (op) == CONST_INT)    {      return (BITS_BIG_ENDIAN	      ? (INTVAL (op) == BITS_PER_WORD-1)	      : (INTVAL (op) == 0));    }  return FALSE;}static intb4const_or_zero (int v){  if (v == 0)    return TRUE;  return xtensa_b4const (v);}intbranch_operand (rtx op, enum machine_mode mode){  if (GET_CODE (op) == CONST_INT)    return b4const_or_zero (INTVAL (op));  return register_operand (op, mode);}intubranch_operand (rtx op, enum machine_mode mode){  if (GET_CODE (op) == CONST_INT)    return xtensa_b4constu (INTVAL (op));  return register_operand (op, mode);}intcall_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  if ((GET_CODE (op) == REG)      && (op != arg_pointer_rtx)      && ((REGNO (op) < FRAME_POINTER_REGNUM)	  || (REGNO (op) > LAST_VIRTUAL_REGISTER)))    return TRUE;  if (CONSTANT_ADDRESS_P (op))    {      /* Direct calls only allowed to static functions with PIC.  */      if (flag_pic)	{	  tree callee, callee_sec, caller_sec;	  if (GET_CODE (op) != SYMBOL_REF	      || !SYMBOL_REF_LOCAL_P (op) || SYMBOL_REF_EXTERNAL_P (op))	    return FALSE;	  /* Don't attempt a direct call if the callee is known to be in	     a different section, since there's a good chance it will be	     out of range.  */	  if (flag_function_sections	      || DECL_ONE_ONLY (current_function_decl))	    return FALSE;	  caller_sec = DECL_SECTION_NAME (current_function_decl);	  callee = SYMBOL_REF_DECL (op);	  if (callee)	    {	      if (DECL_ONE_ONLY (callee))		return FALSE;	      callee_sec = DECL_SECTION_NAME (callee);	      if (((caller_sec == NULL_TREE) ^ (callee_sec == NULL_TREE))		  || (caller_sec != NULL_TREE		      && strcmp (TREE_STRING_POINTER (caller_sec),				 TREE_STRING_POINTER (callee_sec)) != 0))		return FALSE;	    }	  else if (caller_sec != NULL_TREE)	    return FALSE;	}      return TRUE;    }  return FALSE;}intmove_operand (rtx op, enum machine_mode mode){  if (register_operand (op, mode)      || memory_operand (op, mode))    return TRUE;  switch (mode)    {    case DFmode:    case SFmode:      return TARGET_CONST16 && CONSTANT_P (op);    case DImode:    case SImode:      if (TARGET_CONST16)	return CONSTANT_P (op);      /* Fall through.  */    case HImode:    case QImode:      if (GET_CODE (op) == CONST_INT && xtensa_simm12b (INTVAL (op)))	return TRUE;      break;    default:      break;    }  return FALSE;}intsmalloffset_mem_p (rtx op){  if (GET_CODE (op) == MEM)    {      rtx addr = XEXP (op, 0);      if (GET_CODE (addr) == REG)	return REG_OK_FOR_BASE_P (addr);      if (GET_CODE (addr) == PLUS)	{	  rtx offset = XEXP (addr, 0);	  if (GET_CODE (offset) != CONST_INT)	    offset = XEXP (addr, 1);	  if (GET_CODE (offset) != CONST_INT)	    return FALSE;	  return xtensa_lsi4x4 (INTVAL (offset));	}    }  return FALSE;}intconstantpool_address_p (rtx addr){  rtx sym = addr;  if (GET_CODE (addr) == CONST)    {      rtx offset;      /* Only handle (PLUS (SYM, OFFSET)) form.  */      addr = XEXP (addr, 0);      if (GET_CODE (addr) != PLUS)	return FALSE;      /* Make sure the address is word aligned.  */      offset = XEXP (addr, 1);      if ((GET_CODE (offset) != CONST_INT)	  || ((INTVAL (offset) & 3) != 0))	return FALSE;      sym = XEXP (addr, 0);    }  if ((GET_CODE (sym) == SYMBOL_REF)      && CONSTANT_POOL_ADDRESS_P (sym))    return TRUE;  return FALSE;}intconstantpool_mem_p (rtx op){  if (GET_CODE (op) == MEM)    return constantpool_address_p (XEXP (op, 0));  return FALSE;}/* Accept the floating point constant 1 in the appropriate mode.  */intconst_float_1_operand (rtx op, enum machine_mode mode){  REAL_VALUE_TYPE d;  static REAL_VALUE_TYPE onedf;  static REAL_VALUE_TYPE onesf;  static int one_initialized;  if ((GET_CODE (op) != CONST_DOUBLE)      || (mode != GET_MODE (op))      || (mode != DFmode && mode != SFmode))    return FALSE;  REAL_VALUE_FROM_CONST_DOUBLE (d, op);  if (! one_initialized)    {      onedf = REAL_VALUE_ATOF ("1.0", DFmode);      onesf = REAL_VALUE_ATOF ("1.0", SFmode);      one_initialized = TRUE;    }  if (mode == DFmode)    return REAL_VALUES_EQUAL (d, onedf);  else    return REAL_VALUES_EQUAL (d, onesf);}intfpmem_offset_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED){  if (GET_CODE (op) == CONST_INT)    return xtensa_mem_offset (INTVAL (op), SFmode);  return 0;}voidxtensa_extend_reg (rtx dst, rtx src){  rtx temp = gen_reg_rtx (SImode);  rtx shift = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (GET_MODE (src)));  /* Generate paradoxical subregs as needed so that the modes match.  */  src = simplify_gen_subreg (SImode, src, GET_MODE (src), 0);  dst = simplify_gen_subreg (SImode, dst, GET_MODE (dst), 0);  emit_insn (gen_ashlsi3 (temp, src, shift));  emit_insn (gen_ashrsi3 (dst, temp, shift));}intbranch_operator (rtx x, enum machine_mode mode){  if (GET_MODE (x) != mode)    return FALSE;  switch (GET_CODE (x))    {    case EQ:    case NE:    case LT:    case GE:      return TRUE;    default:      break;    }  return FALSE;}intubranch_operator (rtx x, enum machine_mode mode){  if (GET_MODE (x) != mode)    return FALSE;  switch (GET_CODE (x))    {    case LTU:    case GEU:      return TRUE;    default:      break;    }  return FALSE;}intboolean_operator (rtx x, enum machine_mode mode){  if (GET_MODE (x) != mode)    return FALSE;  switch (GET_CODE (x))    {    case EQ:    case NE:      return TRUE;    default:      break;    }  return FALSE;}intxtensa_mask_immediate (int v){#define MAX_MASK_SIZE 16  int mask_size;  for (mask_size = 1; mask_size <= MAX_MASK_SIZE; mask_size++)    {      if ((v & 1) == 0)	return FALSE;      v = v >> 1;      if (v == 0)	return TRUE;    }  return FALSE;}intxtensa_mem_offset (unsigned v, enum machine_mode mode){  switch (mode)    {    case BLKmode:      /* Handle the worst case for block moves.  See xtensa_expand_block_move	 where we emit an optimized block move operation if the block can be	 moved in < "move_ratio" pieces.  The worst case is when the block is	 aligned but has a size of (3 mod 4) (does this happen?) so that the	 last piece requires a byte load/store.  */      return (xtensa_uimm8 (v)	      && xtensa_uimm8 (v + MOVE_MAX * LARGEST_MOVE_RATIO));    case QImode:      return xtensa_uimm8 (v);    case HImode:      return xtensa_uimm8x2 (v);    case DFmode:      return (xtensa_uimm8x4 (v) && xtensa_uimm8x4 (v + 4));    default:      break;    }  return xtensa_uimm8x4 (v);}/* Make normal rtx_code into something we can index from an array.  */static enum internal_testmap_test_to_internal_test (enum rtx_code test_code){  enum internal_test test = ITEST_MAX;  switch (test_code)    {    default:			break;    case EQ:  test = ITEST_EQ;  break;    case NE:  test = ITEST_NE;  break;    case GT:  test = ITEST_GT;  break;    case GE:  test = ITEST_GE;  break;    case LT:  test = ITEST_LT;  break;    case LE:  test = ITEST_LE;  break;    case GTU: test = ITEST_GTU; break;    case GEU: test = ITEST_GEU; break;    case LTU: test = ITEST_LTU; break;    case LEU: test = ITEST_LEU; break;    }  return test;}/* Generate the code to compare two integer values.  The return value is   the comparison expression.  */static rtxgen_int_relational (enum rtx_code test_code, /* relational test (EQ, etc) */		    rtx cmp0, /* first operand to compare */		    rtx cmp1, /* second operand to compare */		    int *p_invert /* whether branch needs to reverse test */){  struct cmp_info  {    enum rtx_code test_code;	/* test code to use in insn */    int (*const_range_p) (int);	/* predicate function to check range */    int const_add;		/* constant to add (convert LE -> LT) */    int reverse_regs;		/* reverse registers in test */    int invert_const;		/* != 0 if invert value if cmp1 is constant */    int invert_reg;		/* != 0 if invert value if cmp1 is register */    int unsignedp;		/* != 0 for unsigned comparisons.  */  };  static struct cmp_info info[ (int)ITEST_MAX ] = {    { EQ,	b4const_or_zero,	0, 0, 0, 0, 0 },	/* EQ  */    { NE,	b4const_or_zero,	0, 0, 0, 0, 0 },	/* NE  */    { LT,	b4const_or_zero,	1, 1, 1, 0, 0 },	/* GT  */    { GE,	b4const_or_zero,	0, 0, 0, 0, 0 },	/* GE  */    { LT,	b4const_or_zero,	0, 0, 0, 0, 0 },	/* LT  */    { GE,	b4const_or_zero,	1, 1, 1, 0, 0 },	/* LE  */    { LTU,	xtensa_b4constu,	1, 1, 1, 0, 1 },	/* GTU */    { GEU,	xtensa_b4constu,	0, 0, 0, 0, 1 },	/* GEU */    { LTU,	xtensa_b4constu,	0, 0, 0, 0, 1 },	/* LTU */    { GEU,	xtensa_b4constu,	1, 1, 1, 0, 1 },	/* LEU */  };  enum internal_test test;  enum machine_mode mode;  struct cmp_info *p_info;  test = map_test_to_internal_test (test_code);  if (test == ITEST_MAX)    abort ();  p_info = &info[ (int)test ];  mode = GET_MODE (cmp0);  if (mode == VOIDmode)    mode = GET_MODE (cmp1);  /* Make sure we can handle any constants given to us.  */  if (GET_CODE (cmp1) == CONST_INT)    {      HOST_WIDE_INT value = INTVAL (cmp1);      unsigned HOST_WIDE_INT uvalue = (unsigned HOST_WIDE_INT)value;      /* if the immediate overflows or does not fit in the immediate field,	 spill it to a register */      if ((p_info->unsignedp ?	   (uvalue + p_info->const_add > uvalue) :	   (value + p_info->const_add > value)) != (p_info->const_add > 0))	{	  cmp1 = force_reg (mode, cmp1);	}      else if (!(p_info->const_range_p) (value + p_info->const_add))	{	  cmp1 = force_reg (mode, cmp1);	}    }  else if ((GET_CODE (cmp1) != REG) && (GET_CODE (cmp1) != SUBREG))    {      cmp1 = force_reg (mode, cmp1);    }  /* See if we need to invert the result.  */  *p_invert = ((GET_CODE (cmp1) == CONST_INT)	       ? p_info->invert_const	       : p_info->invert_reg);  /* Comparison to constants, may involve adding 1 to change a LT into LE.     Comparison between two registers, may involve switching operands.  */  if (GET_CODE (cmp1) == CONST_INT)    {      if (p_info->const_add != 0)	cmp1 = GEN_INT (INTVAL (cmp1) + p_info->const_add);    }  else if (p_info->reverse_regs)    {      rtx temp = cmp0;      cmp0 = cmp1;      cmp1 = temp;    }  return gen_rtx_fmt_ee (p_info->test_code, VOIDmode, cmp0, cmp1);}/* Generate the code to compare two float values.  The return value is   the comparison expression.  */static rtxgen_float_relational (enum rtx_code test_code, /* relational test (EQ, etc) */		      rtx cmp0, /* first operand to compare */		      rtx cmp1 /* second operand to compare */){  rtx (*gen_fn) (rtx, rtx, rtx);  rtx brtmp;  int reverse_regs, invert;  switch (test_code)    {    case EQ: reverse_regs = 0; invert = 0; gen_fn = gen_seq_sf; break;    case NE: reverse_regs = 0; invert = 1; gen_fn = gen_seq_sf; break;    case LE: reverse_regs = 0; invert = 0; gen_fn = gen_sle_sf; break;    case GT: reverse_regs = 1; invert = 0; gen_fn = gen_slt_sf; break;    case LT: reverse_regs = 0; invert = 0; gen_fn = gen_slt_sf; break;    case GE: reverse_regs = 1; invert = 0; gen_fn = gen_sle_sf; break;    default:      fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1));      reverse_regs = 0; invert = 0; gen_fn = 0; /* avoid compiler warnings */    }

⌨️ 快捷键说明

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