📄 rs6000.c
字号:
#endif return 0;}/* Return 1 if OP is a constant that can fit in a D field. */intshort_cint_operand (op, mode) register rtx op; enum machine_mode mode;{ return (GET_CODE (op) == CONST_INT && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) < 0x10000);}/* Similar for a unsigned D field. */intu_short_cint_operand (op, mode) register rtx op; enum machine_mode mode;{ return (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff0000) == 0);}/* Return 1 if OP is a CONST_INT that cannot fit in a signed D field. */intnon_short_cint_operand (op, mode) register rtx op; enum machine_mode mode;{ return (GET_CODE (op) == CONST_INT && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) >= 0x10000);}/* Returns 1 if OP is a register that is not special (i.e., not MQ, ctr, or lr). */intgpc_reg_operand (op, mode) register rtx op; enum machine_mode mode;{ return (register_operand (op, mode) && (GET_CODE (op) != REG || (REGNO (op) >= 67 && !FPMEM_REGNO_P (REGNO (op))) || REGNO (op) < 64));}/* Returns 1 if OP is either a pseudo-register or a register denoting a CR field. */intcc_reg_operand (op, mode) register rtx op; enum machine_mode mode;{ return (register_operand (op, mode) && (GET_CODE (op) != REG || REGNO (op) >= FIRST_PSEUDO_REGISTER || CR_REGNO_P (REGNO (op))));}/* Returns 1 if OP is either a constant integer valid for a D-field or a non-special register. If a register, it must be in the proper mode unless MODE is VOIDmode. */intreg_or_short_operand (op, mode) register rtx op; enum machine_mode mode;{ return short_cint_operand (op, mode) || gpc_reg_operand (op, mode);}/* Similar, except check if the negation of the constant would be valid for a D-field. */intreg_or_neg_short_operand (op, mode) register rtx op; enum machine_mode mode;{ if (GET_CODE (op) == CONST_INT) return CONST_OK_FOR_LETTER_P (INTVAL (op), 'P'); return gpc_reg_operand (op, mode);}/* Return 1 if the operand is either a register or an integer whose high-order 16 bits are zero. */intreg_or_u_short_operand (op, mode) register rtx op; enum machine_mode mode;{ if (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff0000) == 0) return 1; return gpc_reg_operand (op, mode);}/* Return 1 is the operand is either a non-special register or ANY constant integer. */intreg_or_cint_operand (op, mode) register rtx op; enum machine_mode mode;{ return GET_CODE (op) == CONST_INT || gpc_reg_operand (op, mode);}/* Return 1 if the operand is an operand that can be loaded via the GOT */intgot_operand (op, mode) register rtx op; enum machine_mode mode;{ 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) register rtx op; enum machine_mode mode;{ 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 (((unsigned HOST_WIDE_INT)value + 0x8000) < 0x10000) return 1;#if HOST_BITS_PER_WIDE_INT == 32 /* constant loadable with {cau|addis} */ else if ((value & 0xffff) == 0) return 1;#else /* constant loadable with {cau|addis} */ else if ((value & 0xffff) == 0 && (value & ~0xffffffff) == 0) return 1; else if (TARGET_64BIT) { HOST_WIDE_INT low = value & 0xffffffff; HOST_WIDE_INT high = value >> 32; if (high == 0 && (low & 0x80000000) == 0) return 2; else if (high == 0xffffffff && (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) 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 & 0x80000000) == 0) return num_insns_constant_wide (low); else if (((high & 0xffffffff) == 0xffffffff) && ((low & 0x80000000) != 0)) return num_insns_constant_wide (low); 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) register rtx op; register 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 || DEFAULT_ABI == ABI_SOLARIS)) 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 && TARGET_32BIT) return num_insns_constant (op, DImode) == 2; else abort ();}/* 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) register 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 address. */intoffsettable_addr_operand (op, mode) register rtx op; enum machine_mode mode;{ return offsettable_address_p (reload_completed | reload_in_progress, mode, op);}/* Return 1 if the operand is either an easy FP constant (see above) or memory. */intmem_or_easy_const_operand (op, mode) register 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 an SI add insn. */intadd_operand (op, mode) register rtx op; enum machine_mode mode;{ return (reg_or_short_operand (op, mode) || (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff) == 0));}/* Return 1 if OP is a constant but not a valid add_operand. */intnon_add_cint_operand (op, mode) register rtx op; enum machine_mode mode;{ return (GET_CODE (op) == CONST_INT && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) >= 0x10000 && (INTVAL (op) & 0xffff) != 0);}/* 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) register rtx op; enum machine_mode mode;{ return (gpc_reg_operand (op, mode) || (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0xffff0000) == 0 || (INTVAL (op) & 0xffff) == 0)));}/* Return 1 if C is a constant that is not a logical operand (as above). */intnon_logical_cint_operand (op, mode) register rtx op; enum machine_mode mode;{ return (GET_CODE (op) == CONST_INT && (INTVAL (op) & 0xffff0000) != 0 && (INTVAL (op) & 0xffff) != 0);}/* Return 1 if C is a constant that can be encoded in a mask on the RS/6000. It is if there are no more than two 1->0 or 0->1 transitions. Reject all ones and all zeros, since these should have been optimized away and confuse the making of MB and ME. */intmask_constant (c) register int c;{ int i; int last_bit_value; int transitions = 0; if (c == 0 || c == ~0) return 0; last_bit_value = c & 1; for (i = 1; i < 32; i++) if (((c >>= 1) & 1) != last_bit_value) last_bit_value ^= 1, transitions++; return transitions <= 2;}/* Return 1 if the operand is a constant that is a mask on the RS/6000. */intmask_operand (op, mode) register rtx op; enum machine_mode mode;{ return GET_CODE (op) == CONST_INT && mask_constant (INTVAL (op));}/* 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) register rtx op; enum machine_mode mode;{ return (logical_operand (op, mode) || mask_operand (op, mode));}/* Return 1 if the operand is a constant but not a valid operand for an AND insn. */intnon_and_cint_operand (op, mode) register rtx op; enum machine_mode mode;{ return GET_CODE (op) == CONST_INT && ! and_operand (op, mode);}/* Return 1 if the operand is a general register or memory operand. */intreg_or_mem_operand (op, mode) register rtx op;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -