📄 rs6000.c
字号:
{ return (GET_CODE (op) == CONST_INT || gpc_reg_operand (op, mode));}/* Return 1 is the operand is either a non-special register or ANY 32-bit signed constant integer. */intreg_or_arith_cint_operand (op, mode) rtx op; enum machine_mode mode;{ return (gpc_reg_operand (op, mode) || (GET_CODE (op) == CONST_INT#if HOST_BITS_PER_WIDE_INT != 32 && ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80000000) < (unsigned HOST_WIDE_INT) 0x100000000ll)#endif ));}/* Return 1 is the operand is either a non-special register or a 32-bit signed constant integer valid for 64-bit addition. */intreg_or_add_cint64_operand (op, mode) rtx op; enum machine_mode mode;{ return (gpc_reg_operand (op, mode) || (GET_CODE (op) == CONST_INT && INTVAL (op) < 0x7fff8000#if HOST_BITS_PER_WIDE_INT != 32 && ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80008000) < 0x100000000ll)#endif ));}/* Return 1 is the operand is either a non-special register or a 32-bit signed constant integer valid for 64-bit subtraction. */intreg_or_sub_cint64_operand (op, mode) rtx op; enum machine_mode mode;{ return (gpc_reg_operand (op, mode) || (GET_CODE (op) == CONST_INT && (- INTVAL (op)) < 0x7fff8000#if HOST_BITS_PER_WIDE_INT != 32 && ((unsigned HOST_WIDE_INT) ((- INTVAL (op)) + 0x80008000) < 0x100000000ll)#endif ));}/* Return 1 is the operand is either a non-special register or ANY 32-bit unsigned constant integer. */intreg_or_logical_cint_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == CONST_INT) { if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT) { if (GET_MODE_BITSIZE (mode) <= 32) abort (); if (INTVAL (op) < 0) return 0; } return ((INTVAL (op) & GET_MODE_MASK (mode) & (~ (unsigned HOST_WIDE_INT) 0xffffffff)) == 0); } else if (GET_CODE (op) == CONST_DOUBLE) { if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT || mode != DImode) abort (); return CONST_DOUBLE_HIGH (op) == 0; } else return gpc_reg_operand (op, mode);}/* Return 1 if the operand is an operand that can be loaded via the GOT. */intgot_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST || GET_CODE (op) == LABEL_REF);}/* Return 1 if the operand is a simple references that can be loaded via the GOT (labels involving addition aren't allowed). */intgot_no_const_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF);}/* Return the number of instructions it takes to form a constant in an integer register. */static intnum_insns_constant_wide (value) HOST_WIDE_INT value;{ /* signed constant loadable with {cal|addi} */ if (CONST_OK_FOR_LETTER_P (value, 'I')) return 1; /* constant loadable with {cau|addis} */ else if (CONST_OK_FOR_LETTER_P (value, 'L')) return 1;#if HOST_BITS_PER_WIDE_INT == 64 else if (TARGET_POWERPC64) { HOST_WIDE_INT low = value & 0xffffffff; HOST_WIDE_INT high = value >> 32; low = (low ^ 0x80000000) - 0x80000000; /* sign extend */ if (high == 0 && (low & 0x80000000) == 0) return 2; else if (high == -1 && (low & 0x80000000) != 0) return 2; else if (! low) return num_insns_constant_wide (high) + 1; else return (num_insns_constant_wide (high) + num_insns_constant_wide (low) + 1); }#endif else return 2;}intnum_insns_constant (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == CONST_INT) {#if HOST_BITS_PER_WIDE_INT == 64 if ((INTVAL (op) >> 31) != 0 && (INTVAL (op) >> 31) != -1 && mask64_operand (op, mode)) return 2; else#endif return num_insns_constant_wide (INTVAL (op)); } else if (GET_CODE (op) == CONST_DOUBLE && mode == SFmode) { long l; REAL_VALUE_TYPE rv; REAL_VALUE_FROM_CONST_DOUBLE (rv, op); REAL_VALUE_TO_TARGET_SINGLE (rv, l); return num_insns_constant_wide ((HOST_WIDE_INT) l); } else if (GET_CODE (op) == CONST_DOUBLE) { HOST_WIDE_INT low; HOST_WIDE_INT high; long l[2]; REAL_VALUE_TYPE rv; int endian = (WORDS_BIG_ENDIAN == 0); if (mode == VOIDmode || mode == DImode) { high = CONST_DOUBLE_HIGH (op); low = CONST_DOUBLE_LOW (op); } else { REAL_VALUE_FROM_CONST_DOUBLE (rv, op); REAL_VALUE_TO_TARGET_DOUBLE (rv, l); high = l[endian]; low = l[1 - endian]; } if (TARGET_32BIT) return (num_insns_constant_wide (low) + num_insns_constant_wide (high)); else { if (high == 0 && low >= 0) return num_insns_constant_wide (low); else if (high == -1 && low < 0) return num_insns_constant_wide (low); else if (mask64_operand (op, mode)) return 2; else if (low == 0) return num_insns_constant_wide (high) + 1; else return (num_insns_constant_wide (high) + num_insns_constant_wide (low) + 1); } } else abort ();}/* Return 1 if the operand is a CONST_DOUBLE and it can be put into a register with one instruction per word. We only do this if we can safely read CONST_DOUBLE_{LOW,HIGH}. */inteasy_fp_constant (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) != CONST_DOUBLE || GET_MODE (op) != mode || (GET_MODE_CLASS (mode) != MODE_FLOAT && mode != DImode)) return 0; /* Consider all constants with -msoft-float to be easy. */ if (TARGET_SOFT_FLOAT && mode != DImode) return 1; /* If we are using V.4 style PIC, consider all constants to be hard. */ if (flag_pic && DEFAULT_ABI == ABI_V4) return 0;#ifdef TARGET_RELOCATABLE /* Similarly if we are using -mrelocatable, consider all constants to be hard. */ if (TARGET_RELOCATABLE) return 0;#endif if (mode == DFmode) { long k[2]; REAL_VALUE_TYPE rv; REAL_VALUE_FROM_CONST_DOUBLE (rv, op); REAL_VALUE_TO_TARGET_DOUBLE (rv, k); return (num_insns_constant_wide ((HOST_WIDE_INT)k[0]) == 1 && num_insns_constant_wide ((HOST_WIDE_INT)k[1]) == 1); } else if (mode == SFmode) { long l; REAL_VALUE_TYPE rv; REAL_VALUE_FROM_CONST_DOUBLE (rv, op); REAL_VALUE_TO_TARGET_SINGLE (rv, l); return num_insns_constant_wide (l) == 1; } else if (mode == DImode) return ((TARGET_POWERPC64 && GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_LOW (op) == 0) || (num_insns_constant (op, DImode) <= 2)); else if (mode == SImode) return 1; else abort ();}/* Return 1 if the operand is a CONST_INT and can be put into a register with one instruction. */static inteasy_vector_constant (op) rtx op;{ rtx elt; int units, i; if (GET_CODE (op) != CONST_VECTOR) return 0; units = CONST_VECTOR_NUNITS (op); /* We can generate 0 easily. Look for that. */ for (i = 0; i < units; ++i) { elt = CONST_VECTOR_ELT (op, i); /* We could probably simplify this by just checking for equality with CONST0_RTX for the current mode, but let's be safe instead. */ switch (GET_CODE (elt)) { case CONST_INT: if (INTVAL (elt) != 0) return 0; break; case CONST_DOUBLE: if (CONST_DOUBLE_LOW (elt) != 0 || CONST_DOUBLE_HIGH (elt) != 0) return 0; break; default: return 0; } } /* We could probably generate a few other constants trivially, but gcc doesn't generate them yet. FIXME later. */ return 1;}/* Return 1 if the operand is the constant 0. This works for scalars as well as vectors. */intzero_constant (op, mode) rtx op; enum machine_mode mode;{ return op == CONST0_RTX (mode);}/* Return 1 if the operand is 0.0. */intzero_fp_constant (op, mode) rtx op; enum machine_mode mode;{ return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);}/* Return 1 if the operand is in volatile memory. Note that during the RTL generation phase, memory_operand does not return TRUE for volatile memory references. So this function allows us to recognize volatile references where its safe. */intvolatile_mem_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) != MEM) return 0; if (!MEM_VOLATILE_P (op)) return 0; if (mode != GET_MODE (op)) return 0; if (reload_completed) return memory_operand (op, mode); if (reload_in_progress) return strict_memory_address_p (mode, XEXP (op, 0)); return memory_address_p (mode, XEXP (op, 0));}/* Return 1 if the operand is an offsettable memory operand. */intoffsettable_mem_operand (op, mode) rtx op; enum machine_mode mode;{ return ((GET_CODE (op) == MEM) && offsettable_address_p (reload_completed || reload_in_progress, mode, XEXP (op, 0)));}/* Return 1 if the operand is either an easy FP constant (see above) or memory. */intmem_or_easy_const_operand (op, mode) rtx op; enum machine_mode mode;{ return memory_operand (op, mode) || easy_fp_constant (op, mode);}/* Return 1 if the operand is either a non-special register or an item that can be used as the operand of a `mode' add insn. */intadd_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == CONST_INT) return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'I') || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L')); return gpc_reg_operand (op, mode);}/* Return 1 if OP is a constant but not a valid add_operand. */intnon_add_cint_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ return (GET_CODE (op) == CONST_INT && !CONST_OK_FOR_LETTER_P (INTVAL (op), 'I') && !CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));}/* Return 1 if the operand is a non-special register or a constant that can be used as the operand of an OR or XOR insn on the RS/6000. */intlogical_operand (op, mode) rtx op; enum machine_mode mode;{ HOST_WIDE_INT opl, oph; if (gpc_reg_operand (op, mode)) return 1; if (GET_CODE (op) == CONST_INT) { opl = INTVAL (op) & GET_MODE_MASK (mode);#if HOST_BITS_PER_WIDE_INT <= 32
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -