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

📄 rs6000.c

📁 gcc3.2.1源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      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 (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 && 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 || 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 (XEXP (x, 0), 1), 0) == XEXP (x, 1)      && GET_CODE (XEXP (XEXP (x, 1), 0)) == MINUS      && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 0)) == SYMBOL_REF      && GET_CODE (XEXP (XEXP (XEXP (x, 1), 0), 1)) == SYMBOL_REF)    {      /* Result of previous invocation of this function on Darwin	 floating point constant.  */      push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,		BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,		opnum, (enum reload_type)type);      *win = 1;      return x;    }#endif  if (GET_CODE (x) == PLUS      && GET_CODE (XEXP (x, 0)) == REG      && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER      && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)      && GET_CODE (XEXP (x, 1)) == CONST_INT      && !ALTIVEC_VECTOR_MODE (mode))    {      HOST_WIDE_INT val = INTVAL (XEXP (x, 1));      HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;      HOST_WIDE_INT high        = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000;      /* Check for 32-bit overflow.  */      if (high + low != val)        {	  *win = 0;	  return x;	}      /* Reload the high part into a base reg; leave the low part         in the mem directly.  */      x = gen_rtx_PLUS (GET_MODE (x),                        gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),                                      GEN_INT (high)),                        GEN_INT (low));      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 (GET_CODE (x) == SYMBOL_REF      && DEFAULT_ABI == ABI_DARWIN      && !ALTIVEC_VECTOR_MODE (mode)      && flag_pic)    {      /* Darwin load of floating point constant.  */      rtx offset = gen_rtx (CONST, Pmode,		    gen_rtx (MINUS, Pmode, x,		    gen_rtx (SYMBOL_REF, Pmode,			machopic_function_base_name ())));      x = gen_rtx (LO_SUM, GET_MODE (x),	    gen_rtx (PLUS, Pmode, pic_offset_table_rtx,		gen_rtx (HIGH, Pmode, offset)), offset);      push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,		BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,		opnum, (enum reload_type)type);      *win = 1;      return x;    }#endif  if (TARGET_TOC      && CONSTANT_POOL_EXPR_P (x)      && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))    {      (x) = create_TOC_reference (x);      *win = 1;      return x;    }  *win = 0;  return x;}    /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression   that is a valid memory address for an instruction.   The MODE argument is the machine mode for the MEM expression   that wants to use this address.   On the RS/6000, there are four valid address: a SYMBOL_REF that   refers to a constant pool entry of an address (or the sum of it   plus a constant), a short (16-bit signed) constant plus a register,   the sum of two registers, or a register indirect, possibly with an   auto-increment.  For DFmode and DImode with an constant plus register,   we must ensure that both words are addressable or PowerPC64 with offset   word aligned.   For modes spanning multiple registers (DFmode in 32-bit GPRs,   32-bit DImode, TImode), indexed addressing cannot be used because   adjacent memory cells are accessed by adding word-sized offsets   during assembly output.  */intrs6000_legitimate_address (mode, x, reg_ok_strict)    enum machine_mode mode;    rtx x;    int reg_ok_strict;{  if (LEGITIMATE_INDIRECT_ADDRESS_P (x, reg_ok_strict))    return 1;  if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)      && !ALTIVEC_VECTOR_MODE (mode)      && TARGET_UPDATE      && LEGITIMATE_INDIRECT_ADDRESS_P (XEXP (x, 0), reg_ok_strict))    return 1;  if (LEGITIMATE_SMALL_DATA_P (mode, x))    return 1;  if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (x))    return 1;  /* If not REG_OK_STRICT (before reload) let pass any stack offset.  */  if (! reg_ok_strict      && GET_CODE (x) == PLUS      && GET_CODE (XEXP (x, 0)) == REG      && XEXP (x, 0) == virtual_stack_vars_rtx      && GET_CODE (XEXP (x, 1)) == CONST_INT)    return 1;  if (LEGITIMATE_OFFSET_ADDRESS_P (mode, x, reg_ok_strict))    return 1;  if (mode != TImode      && (TARGET_HARD_FLOAT || TARGET_POWERPC64 || mode != DFmode)      && (TARGET_POWERPC64 || mode != DImode)      && LEGITIMATE_INDEXED_ADDRESS_P (x, reg_ok_strict))    return 1;  if (LEGITIMATE_LO_SUM_ADDRESS_P (mode, x, reg_ok_strict))    return 1;  return 0;}/* Try to output insns to set TARGET equal to the constant C if it can   be done in less than N insns.  Do all computations in MODE.   Returns the place where the output has been placed if it can be   done and the insns have been emitted.  If it would take more than N   insns, zero is returned and no insns and emitted.  */rtxrs6000_emit_set_const (dest, mode, source, n)     rtx dest, source;     enum machine_mode mode;     int n ATTRIBUTE_UNUSED;{  HOST_WIDE_INT c0, c1;  if (mode == QImode || mode == HImode || mode == SImode)    {      if (dest == NULL)        dest = gen_reg_rtx (mode);      emit_insn (gen_rtx_SET (VOIDmode, dest, source));      return dest;    }  if (GET_CODE (source) == CONST_INT)    {      c0 = INTVAL (source);      c1 = -(c0 < 0);    }  else if (GET_CODE (source) == CONST_DOUBLE)    {#if HOST_BITS_PER_WIDE_INT >= 64      c0 = CONST_DOUBLE_LOW (source);      c1 = -(c0 < 0);#else      c0 = CONST_DOUBLE_LOW (source);      c1 = CONST_DOUBLE_HIGH (source);#endif    }  else    abort ();  return rs6000_emit_set_long_const (dest, c0, c1);}/* Having failed to find a 3 insn sequence in rs6000_emit_set_const,   fall back to a straight forward decomposition.  We do this to avoid   exponential run times encountered when looking for longer sequences   with rs6000_emit_set_const.  */static rtxrs6000_emit_set_long_const (dest, c1, c2)     rtx dest;     HOST_WIDE_INT c1, c2;{  if (!TARGET_POWERPC64)    {      rtx operand1, operand2;      operand1 = operand_subword_force (dest, WORDS_BIG_ENDIAN == 0,					DImode);      operand2 = operand_subword_force (dest, WORDS_BIG_ENDIAN != 0,					DImode);      emit_move_insn (operand1, GEN_INT (c1));      emit_move_insn (operand2, GEN_INT (c2));    }  else    {      HOST_WIDE_INT ud1, ud2, ud3, ud4;      ud1 = c1 & 0xffff;      ud2 = (c1 & 0xffff0000) >> 16;#if HOST_BITS_PER_WIDE_INT >= 64      c2 = c1 >> 32;#endif      ud3 = c2 & 0xffff;      ud4 = (c2 & 0xffff0000) >> 16;      if ((ud4 == 0xffff && ud3 == 0xffff && ud2 == 0xffff && (ud1 & 0x8000)) 	  || (ud4 == 0 && ud3 == 0 && ud2 == 0 && ! (ud1 & 0x8000)))	{	  if (ud1 & 0x8000)	    emit_move_insn (dest, GEN_INT (((ud1  ^ 0x8000) -  0x8000)));	  else	    emit_move_insn (dest, GEN_INT (ud1));	}      else if ((ud4 == 0xffff && ud3 == 0xffff && (ud2 & 0x8000)) 	       || (ud4 == 0 && ud3 == 0 && ! (ud2 & 0x8000)))	{	  if (ud2 & 0x8000)	    emit_move_insn (dest, GEN_INT (((ud2 << 16) ^ 0x80000000) 					   - 0x80000000));	  else	    emit_move_insn (dest, GEN_INT (ud2 << 16));	  if (ud1 != 0)	    emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));	}      else if ((ud4 == 0xffff && (ud3 & 0x8000)) 	       || (ud4 == 0 && ! (ud3 & 0x8000)))	{	  if (ud3 & 0x8000)	    emit_move_insn (dest, GEN_INT (((ud3 << 16) ^ 0x80000000) 					   - 0x80000000));	  else	    emit_move_insn (dest, GEN_INT (ud3 << 16));	  if (ud2 != 0)	    emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud2)));	  emit_move_insn (dest, gen_rtx_ASHIFT (DImode, dest, GEN_INT (16)));	  if (ud1 != 0)	    emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));	}      else 	{	  if (ud4 & 0x8000)	    emit_move_insn (dest, GEN_INT (((ud4 << 16) ^ 0x80000000) 					   - 0x80000000));	  else	    emit_move_insn (dest, GEN_INT (ud4 << 16));	  if (ud3 != 0)	    emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud3)));	  emit_move_insn (dest, gen_rtx_ASHIFT (DImode, dest, GEN_INT (32)));	  if (ud2 != 0)	    emit_move_insn (dest, gen_rtx_IOR (DImode, dest, 					       GEN_INT (ud2 << 16)));		  if (ud1 != 0)	    emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));	}    }  return dest;}/* Emit a move from SOURCE to DEST in mode MODE.  */voidrs6000_emit_move (dest, source, mode)     rtx dest;     rtx source;     enum machine_mode mode;{  rtx operands[2];  operands[0] = dest;  operands[1] = source;    /* Sanity checks.  Check that we get CONST_DOUBLE only when we should.  */  if (GET_CODE (operands[1]) == CONST_DOUBLE      && ! FLOAT_MODE_P (mode)      && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)    {      /* FIXME.  This should never happen.  */      /* Since it seems that it does, do the safe thing and convert	 to a CONST_INT.  */      operands[1] = 	GEN_INT (trunc_int_for_mode (CONST_DOUBLE_LOW (operands[1]), mode));    }  if (GET_CODE (operands[1]) == CONST_DOUBLE      && ! FLOAT_MODE_P (mode)      && ((CONST_DOUBLE_HIGH (operands[1]) == 0	   && CONST_DOUBLE_LOW (operands[1]) >= 0)	  || (CONST_DOUBLE_HIGH (operands[1]) == -1	      && CONST_DOUBLE_LOW (operands[1]) < 0)))    abort ();  /* Check if GCC is setting up a block move that will end up using FP     registers as temporaries.  We must make sure this is acceptable.  */  if (GET_CODE (operands[0]) == MEM      && GET_CODE (operands[1]) == MEM      && mode == DImode      && (SLOW_UNALIGNED_ACCESS (DImode, MEM_ALIGN (operands[0]))	  || SLOW_UNALIGNED_ACCESS (DImode, MEM_ALIGN (operands[1])))      && ! (SLOW_UNALIGNED_ACCESS (SImode, (MEM_ALIGN (operands[0]) > 32					    ? 32 : MEM_ALIGN (operands[0])))	    || SLOW_UNALIGNED_ACCESS (SImode, (MEM_ALIGN (operands[1]) > 32					       ? 32 					       : MEM_ALIGN (operands[1]))))      && ! MEM_VOLATILE_P (operands [0])      && ! MEM_VOLATILE_P (operands [1]))    {      emit_move_insn (adjust_address (operands[0], SImode, 0),		      adjust_address (operands[1], SImode, 0));      emit_move_insn (adjust_address (operands[0], SImode, 4),		      adjust_address (operands[1], SImode, 4));      return;    }    if (! no_new_pseudos && GET_CODE (operands[0]) != REG)    operands[1] = force_reg (mode, operands[1]);  if (mode == SFmode && ! TARGET_POWERPC && TARGET_HARD_FLOAT      && GET_CODE (operands[0]) == MEM)    {      int regnum;      if (reload_in_progress || reload_completed)	regnum = true_regnum (operands[1]);      else if (GET_CODE (operands[1]) == REG)	regnum = REGNO (operands[1]);      else	regnum = -1;            /* If operands[1] is a register, on POWER it may have	 double-precision data in it, so truncate it to single	 precision.  */      if (FP_REGNO_P (regnum) || regnum >= FIRST_PSEUDO_REGISTER)	{	  rtx newreg;	  newreg = (no_new_pseudos ? operands[1] : gen_reg_rtx (mode));	  emit_insn (gen_aux_truncdfsf2 (newreg, operands[1]));	  operands[1] = newreg;	}    }  /* Handle the case where reload calls us with an invalid address;     and the case of CONSTANT_P_RTX.  */  if (!VECTOR_MODE_P (mode)      && (! general_operand (operands[1], mode)	  || ! nonimmediate_operand (operands[0], mode)	  || GET_CODE (operands[1]) == CONSTANT_P_RTX))    {      emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));      return;    }    /* FIXME:  In the long term, this switch state

⌨️ 快捷键说明

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