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

📄 rs6000.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
  if (fixed_regs[CR0_REGNO])	/* CR0 not available, don't do andi./andis.  */    return (gpc_reg_operand (op, mode) || mask64_operand (op, mode));  return (logical_operand (op, mode) || mask64_operand (op, mode));}/* Like the above, but also match constants that can be implemented   with two rldicl or rldicr insns.  */intand64_2_operand (op, mode)    rtx op;    enum machine_mode mode;{  if (fixed_regs[CR0_REGNO])	/* CR0 not available, don't do andi./andis. */    return gpc_reg_operand (op, mode) || mask64_2_operand (op, mode);  return logical_operand (op, mode) || mask64_2_operand (op, mode);}/* Return 1 if the operand is either a non-special register or a   constant that can be used as the operand of an RS/6000 logical AND insn.  */intand_operand (op, mode)    rtx op;    enum machine_mode mode;{  if (fixed_regs[CR0_REGNO])	/* CR0 not available, don't do andi./andis.  */    return (gpc_reg_operand (op, mode) || mask_operand (op, mode));  return (logical_operand (op, mode) || mask_operand (op, mode));}/* Return 1 if the operand is a general register or memory operand.  */intreg_or_mem_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (gpc_reg_operand (op, mode)	  || memory_operand (op, mode)	  || volatile_mem_operand (op, mode));}/* Return 1 if the operand is a general register or memory operand without   pre_inc or pre_dec which produces invalid form of PowerPC lwa   instruction.  */intlwa_operand (op, mode)     rtx op;     enum machine_mode mode;{  rtx inner = op;  if (reload_completed && GET_CODE (inner) == SUBREG)    inner = SUBREG_REG (inner);      return gpc_reg_operand (inner, mode)    || (memory_operand (inner, mode)	&& GET_CODE (XEXP (inner, 0)) != PRE_INC	&& GET_CODE (XEXP (inner, 0)) != PRE_DEC	&& (GET_CODE (XEXP (inner, 0)) != PLUS	    || GET_CODE (XEXP (XEXP (inner, 0), 1)) != CONST_INT	    || INTVAL (XEXP (XEXP (inner, 0), 1)) % 4 == 0));}/* Return 1 if the operand, used inside a MEM, is a SYMBOL_REF.  */intsymbol_ref_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (mode != VOIDmode && GET_MODE (op) != mode)    return 0;  return (GET_CODE (op) == SYMBOL_REF);}/* Return 1 if the operand, used inside a MEM, is a valid first argument   to CALL.  This is a SYMBOL_REF, a pseudo-register, LR or CTR.  */intcall_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (mode != VOIDmode && GET_MODE (op) != mode)    return 0;  return (GET_CODE (op) == SYMBOL_REF	  || (GET_CODE (op) == REG	      && (REGNO (op) == LINK_REGISTER_REGNUM		  || REGNO (op) == COUNT_REGISTER_REGNUM		  || REGNO (op) >= FIRST_PSEUDO_REGISTER)));}/* Return 1 if the operand is a SYMBOL_REF for a function known to be in   this file and the function is not weakly defined.  */intcurrent_file_function_operand (op, mode)     rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  return (GET_CODE (op) == SYMBOL_REF	  && (SYMBOL_REF_FLAG (op)	      || (op == XEXP (DECL_RTL (current_function_decl), 0)	          && ! DECL_WEAK (current_function_decl))));}/* Return 1 if this operand is a valid input for a move insn.  */intinput_operand (op, mode)     rtx op;     enum machine_mode mode;{  /* Memory is always valid.  */  if (memory_operand (op, mode))    return 1;  /* Only a tiny bit of handling for CONSTANT_P_RTX is necessary.  */  if (GET_CODE (op) == CONSTANT_P_RTX)    return 1;  /* For floating-point, easy constants are valid.  */  if (GET_MODE_CLASS (mode) == MODE_FLOAT      && CONSTANT_P (op)      && easy_fp_constant (op, mode))    return 1;  /* Allow any integer constant.  */  if (GET_MODE_CLASS (mode) == MODE_INT      && (GET_CODE (op) == CONST_INT	  || GET_CODE (op) == CONST_DOUBLE))    return 1;  /* For floating-point or multi-word mode, the only remaining valid type     is a register.  */  if (GET_MODE_CLASS (mode) == MODE_FLOAT      || GET_MODE_SIZE (mode) > UNITS_PER_WORD)    return register_operand (op, mode);  /* The only cases left are integral modes one word or smaller (we     do not get called for MODE_CC values).  These can be in any     register.  */  if (register_operand (op, mode))    return 1;  /* A SYMBOL_REF referring to the TOC is valid.  */  if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (op))    return 1;  /* A constant pool expression (relative to the TOC) is valid */  if (TOC_RELATIVE_EXPR_P (op))    return 1;  /* V.4 allows SYMBOL_REFs and CONSTs that are in the small data region     to be valid.  */  if (DEFAULT_ABI == ABI_V4      && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST)      && small_data_operand (op, Pmode))    return 1;  return 0;}/* Return 1 for an operand in small memory on V.4/eabi.  */intsmall_data_operand (op, mode)     rtx op ATTRIBUTE_UNUSED;     enum machine_mode mode ATTRIBUTE_UNUSED;{#if TARGET_ELF  rtx sym_ref;  if (rs6000_sdata == SDATA_NONE || rs6000_sdata == SDATA_DATA)    return 0;  if (DEFAULT_ABI != ABI_V4)    return 0;  if (GET_CODE (op) == SYMBOL_REF)    sym_ref = op;  else if (GET_CODE (op) != CONST	   || GET_CODE (XEXP (op, 0)) != PLUS	   || GET_CODE (XEXP (XEXP (op, 0), 0)) != SYMBOL_REF	   || GET_CODE (XEXP (XEXP (op, 0), 1)) != CONST_INT)    return 0;  else    {      rtx sum = XEXP (op, 0);      HOST_WIDE_INT summand;      /* We have to be careful here, because it is the referenced address        that must be 32k from _SDA_BASE_, not just the symbol.  */      summand = INTVAL (XEXP (sum, 1));      if (summand < 0 || summand > g_switch_value)       return 0;      sym_ref = XEXP (sum, 0);    }  if (*XSTR (sym_ref, 0) != '@')    return 0;  return 1;#else  return 0;#endif}static int constant_pool_expr_1 (op, have_sym, have_toc)     rtx op;    int *have_sym;    int *have_toc;{  switch (GET_CODE(op))     {    case SYMBOL_REF:      if (CONSTANT_POOL_ADDRESS_P (op))	{	  if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (op), Pmode))	    {	      *have_sym = 1;	      return 1;	    }	  else	    return 0;	}      else if (! strcmp (XSTR (op, 0), toc_label_name))	{	  *have_toc = 1;	  return 1;	}      else	return 0;    case PLUS:    case MINUS:      return (constant_pool_expr_1 (XEXP (op, 0), have_sym, have_toc)	      && constant_pool_expr_1 (XEXP (op, 1), have_sym, have_toc));    case CONST:      return constant_pool_expr_1 (XEXP (op, 0), have_sym, have_toc);    case CONST_INT:      return 1;    default:      return 0;    }}intconstant_pool_expr_p (op)    rtx op;{  int have_sym = 0;  int have_toc = 0;  return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_sym;}inttoc_relative_expr_p (op)    rtx op;{    int have_sym = 0;    int have_toc = 0;    return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_toc;}/* Try machine-dependent ways of modifying an illegitimate address   to be legitimate.  If we find one, return the new, valid address.   This is used from only one place: `memory_address' in explow.c.   OLDX is the address as it was before break_out_memory_refs was   called.  In some cases it is useful to look at this to decide what   needs to be done.   MODE is passed so that this function can use GO_IF_LEGITIMATE_ADDRESS.   It is always safe for this function to do nothing.  It exists to   recognize opportunities to optimize the output.   On RS/6000, first check for the sum of a register with a constant   integer that is out of range.  If so, generate code to add the   constant with the low-order 16 bits masked to the register and force   this result into another register (this can be done with `cau').   Then generate an address of REG+(CONST&0xffff), allowing for the   possibility of bit 16 being a one.   Then check for the sum of a register and something not constant, try to   load the other things into a register and return the sum.  */rtxrs6000_legitimize_address (x, oldx, mode)     rtx x;     rtx oldx ATTRIBUTE_UNUSED;     enum machine_mode mode;{  if (GET_CODE (x) == PLUS       && GET_CODE (XEXP (x, 0)) == REG      && GET_CODE (XEXP (x, 1)) == CONST_INT      && (unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000) >= 0x10000)    {       HOST_WIDE_INT high_int, low_int;      rtx sum;      low_int = ((INTVAL (XEXP (x, 1)) & 0xffff) ^ 0x8000) - 0x8000;      high_int = INTVAL (XEXP (x, 1)) - low_int;      sum = force_operand (gen_rtx_PLUS (Pmode, XEXP (x, 0),					 GEN_INT (high_int)), 0);      return gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));    }  else if (GET_CODE (x) == PLUS 	   && GET_CODE (XEXP (x, 0)) == REG	   && GET_CODE (XEXP (x, 1)) != CONST_INT	   && GET_MODE_NUNITS (mode) == 1	   && ((TARGET_HARD_FLOAT && TARGET_FPRS)	       || TARGET_POWERPC64	       || (mode != DFmode && mode != TFmode))	   && (TARGET_POWERPC64 || mode != DImode)	   && mode != TImode)    {      return gen_rtx_PLUS (Pmode, XEXP (x, 0),			   force_reg (Pmode, force_operand (XEXP (x, 1), 0)));    }  else if (ALTIVEC_VECTOR_MODE (mode))    {      rtx reg;      /* Make sure both operands are registers.  */      if (GET_CODE (x) == PLUS)	return gen_rtx_PLUS (Pmode, force_reg (Pmode, XEXP (x, 0)),			     force_reg (Pmode, XEXP (x, 1)));      reg = force_reg (Pmode, x);      return reg;    }  else if (SPE_VECTOR_MODE (mode))    {      /* We accept [reg + reg] and [reg + OFFSET].  */      if (GET_CODE (x) == PLUS)      {        rtx op1 = XEXP (x, 0);        rtx op2 = XEXP (x, 1);        op1 = force_reg (Pmode, op1);        if (GET_CODE (op2) != REG            && (GET_CODE (op2) != CONST_INT                || !SPE_CONST_OFFSET_OK (INTVAL (op2))))          op2 = force_reg (Pmode, op2);        return gen_rtx_PLUS (Pmode, op1, op2);      }      return force_reg (Pmode, x);    }  else if (TARGET_ELF && TARGET_32BIT && TARGET_NO_TOC && ! flag_pic	   && GET_CODE (x) != CONST_INT	   && GET_CODE (x) != CONST_DOUBLE 	   && CONSTANT_P (x)	   && GET_MODE_NUNITS (mode) == 1	   && (GET_MODE_BITSIZE (mode) <= 32	       || ((TARGET_HARD_FLOAT && TARGET_FPRS) && mode == DFmode)))    {      rtx reg = gen_reg_rtx (Pmode);      emit_insn (gen_elf_high (reg, (x)));      return gen_rtx_LO_SUM (Pmode, reg, (x));    }  else if (TARGET_MACHO && TARGET_32BIT && TARGET_NO_TOC	   && ! flag_pic	   && GET_CODE (x) != CONST_INT	   && GET_CODE (x) != CONST_DOUBLE 	   && CONSTANT_P (x)	   && ((TARGET_HARD_FLOAT && TARGET_FPRS) || mode != DFmode)	   && mode != DImode 	   && mode != TImode)    {      rtx reg = gen_reg_rtx (Pmode);      emit_insn (gen_macho_high (reg, (x)));      return gen_rtx_LO_SUM (Pmode, reg, (x));    }  else if (TARGET_TOC 	   && CONSTANT_POOL_EXPR_P (x)	   && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))    {      return create_TOC_reference (x);    }  else    return NULL_RTX;}/* The convention appears to be to define this wherever it is used.   With legitimize_reload_address now defined here, REG_MODE_OK_FOR_BASE_P   is now used here.  */#ifndef REG_MODE_OK_FOR_BASE_P#define REG_MODE_OK_FOR_BASE_P(REGNO, MODE) REG_OK_FOR_BASE_P (REGNO)#endif/* Our implementation of LEGITIMIZE_RELOAD_ADDRESS.  Returns a value to   replace the input X, or the original X if no replacement is called for.   The output parameter *WIN is 1 if the calling macro should goto WIN,   0 if it should not.   For RS/6000, we wish to handle large displacements off a base   register by splitting the addend across an addiu/addis and the mem insn.   This cuts number of extra insns needed from 3 to 1.   On Darwin, we use this to generate code for floating point constants.   A movsf_low is generated so we wind up with 2 instructions rather than 3.   The Darwin code is inside #if TARGET_MACHO because only then is   machopic_function_base_name() defined.  */rtxrs6000_legitimize_reload_address (x, mode, opnum, type, ind_levels, win)    rtx x;    enum machine_mode mode;    int opnum;    int type;    int ind_levels ATTRIBUTE_UNUSED;    int *win;{  /* We must recognize output that we have already generated ourselves.  */   if (GET_CODE (x) == PLUS      && GET_CODE (XEXP (x, 0)) == PLUS      && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT      && GET_CODE (XEXP (x, 1)) == CONST_INT)    {      push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,                   BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,                   opnum, (enum reload_type)type);      *win = 1;      return x;    }#if TARGET_MACHO  if (DEFAULT_ABI == ABI_DARWIN && flag_pic      && GET_CODE (x) == LO_SUM      && GET_CODE (XEXP (x, 0)) == PLUS      && XEXP (XEXP (x, 0), 0) == pic_offset_table_rtx      && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH      && GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 0)) == CONST      && XEXP (XEXP (

⌨️ 快捷键说明

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