📄 sparc.c
字号:
return (code == EQ || code == NE || code == GE || code == LT); return 1;}/* Return 1 if this is a 64-bit comparison operator. This allows the use of MATCH_OPERATOR to recognize all the branch insns. */intnoov_compare64_op (op, mode) register rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ enum rtx_code code = GET_CODE (op); if (! TARGET_V9) return 0; if (GET_RTX_CLASS (code) != '<') return 0; if (GET_MODE (XEXP (op, 0)) == CCX_NOOVmode) /* These are the only branches which work with CCX_NOOVmode. */ return (code == EQ || code == NE || code == GE || code == LT); return (GET_MODE (XEXP (op, 0)) == CCXmode);}/* Nonzero if OP is a comparison operator suitable for use in v9 conditional move or branch on register contents instructions. */intv9_regcmp_op (op, mode) register rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ enum rtx_code code = GET_CODE (op); if (GET_RTX_CLASS (code) != '<') return 0; return v9_regcmp_p (code);}/* Return 1 if this is a SIGN_EXTEND or ZERO_EXTEND operation. */intextend_op (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ return GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND;}/* Return nonzero if OP is an operator of mode MODE which can set the condition codes explicitly. We do not include PLUS and MINUS because these require CC_NOOVmode, which we handle explicitly. */intcc_arithop (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ if (GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR) return 1; return 0;}/* Return nonzero if OP is an operator of mode MODE which can bitwise complement its second operand and set the condition codes explicitly. */intcc_arithopn (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ /* XOR is not here because combine canonicalizes (xor (not ...) ...) and (xor ... (not ...)) to (not (xor ...)). */ return (GET_CODE (op) == AND || GET_CODE (op) == IOR);}/* Return true if OP is a register, or is a CONST_INT that can fit in a signed 13 bit immediate field. This is an acceptable SImode operand for most 3 address instructions. */intarith_operand (op, mode) rtx op; enum machine_mode mode;{ if (register_operand (op, mode)) return 1; if (GET_CODE (op) != CONST_INT) return 0; return SMALL_INT32 (op);}/* Return true if OP is a constant 4096 */intarith_4096_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ if (GET_CODE (op) != CONST_INT) return 0; else return INTVAL (op) == 4096;}/* Return true if OP is suitable as second operand for add/sub */intarith_add_operand (op, mode) rtx op; enum machine_mode mode;{ return arith_operand (op, mode) || arith_4096_operand (op, mode);}/* Return true if OP is a CONST_INT or a CONST_DOUBLE which can fit in the immediate field of OR and XOR instructions. Used for 64-bit constant formation patterns. */intconst64_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ return ((GET_CODE (op) == CONST_INT && SPARC_SIMM13_P (INTVAL (op)))#if HOST_BITS_PER_WIDE_INT != 64 || (GET_CODE (op) == CONST_DOUBLE && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op)) && (CONST_DOUBLE_HIGH (op) == ((CONST_DOUBLE_LOW (op) & 0x80000000) != 0 ? (HOST_WIDE_INT)-1 : 0)))#endif );}/* The same, but only for sethi instructions. */intconst64_high_operand (op, mode) rtx op; enum machine_mode mode;{ return ((GET_CODE (op) == CONST_INT && (INTVAL (op) & ~(HOST_WIDE_INT)0x3ff) != 0 && SPARC_SETHI_P (INTVAL (op) & GET_MODE_MASK (mode)) ) || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0 && (CONST_DOUBLE_LOW (op) & ~(HOST_WIDE_INT)0x3ff) != 0 && SPARC_SETHI_P (CONST_DOUBLE_LOW (op))));}/* Return true if OP is a register, or is a CONST_INT that can fit in a signed 11 bit immediate field. This is an acceptable SImode operand for the movcc instructions. */intarith11_operand (op, mode) rtx op; enum machine_mode mode;{ return (register_operand (op, mode) || (GET_CODE (op) == CONST_INT && SPARC_SIMM11_P (INTVAL (op))));}/* Return true if OP is a register, or is a CONST_INT that can fit in a signed 10 bit immediate field. This is an acceptable SImode operand for the movrcc instructions. */intarith10_operand (op, mode) rtx op; enum machine_mode mode;{ return (register_operand (op, mode) || (GET_CODE (op) == CONST_INT && SPARC_SIMM10_P (INTVAL (op))));}/* Return true if OP is a register, is a CONST_INT that fits in a 13 bit immediate field, or is a CONST_DOUBLE whose both parts fit in a 13 bit immediate field. v9: Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that can fit in a 13 bit immediate field. This is an acceptable DImode operand for most 3 address instructions. */intarith_double_operand (op, mode) rtx op; enum machine_mode mode;{ return (register_operand (op, mode) || (GET_CODE (op) == CONST_INT && SMALL_INT (op)) || (! TARGET_ARCH64 && GET_CODE (op) == CONST_DOUBLE && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000 && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_HIGH (op) + 0x1000) < 0x2000) || (TARGET_ARCH64 && GET_CODE (op) == CONST_DOUBLE && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000 && ((CONST_DOUBLE_HIGH (op) == -1 && (CONST_DOUBLE_LOW (op) & 0x1000) == 0x1000) || (CONST_DOUBLE_HIGH (op) == 0 && (CONST_DOUBLE_LOW (op) & 0x1000) == 0))));}/* Return true if OP is a constant 4096 for DImode on ARCH64 */intarith_double_4096_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ return (TARGET_ARCH64 && ((GET_CODE (op) == CONST_INT && INTVAL (op) == 4096) || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_LOW (op) == 4096 && CONST_DOUBLE_HIGH (op) == 0)));}/* Return true if OP is suitable as second operand for add/sub in DImode */intarith_double_add_operand (op, mode) rtx op; enum machine_mode mode;{ return arith_double_operand (op, mode) || arith_double_4096_operand (op, mode);}/* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that can fit in an 11 bit immediate field. This is an acceptable DImode operand for the movcc instructions. *//* ??? Replace with arith11_operand? */intarith11_double_operand (op, mode) rtx op; enum machine_mode mode;{ return (register_operand (op, mode) || (GET_CODE (op) == CONST_DOUBLE && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode) && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x400) < 0x800 && ((CONST_DOUBLE_HIGH (op) == -1 && (CONST_DOUBLE_LOW (op) & 0x400) == 0x400) || (CONST_DOUBLE_HIGH (op) == 0 && (CONST_DOUBLE_LOW (op) & 0x400) == 0))) || (GET_CODE (op) == CONST_INT && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode) && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x400) < 0x800));}/* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that can fit in an 10 bit immediate field. This is an acceptable DImode operand for the movrcc instructions. *//* ??? Replace with arith10_operand? */intarith10_double_operand (op, mode) rtx op; enum machine_mode mode;{ return (register_operand (op, mode) || (GET_CODE (op) == CONST_DOUBLE && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode) && (unsigned) (CONST_DOUBLE_LOW (op) + 0x200) < 0x400 && ((CONST_DOUBLE_HIGH (op) == -1 && (CONST_DOUBLE_LOW (op) & 0x200) == 0x200) || (CONST_DOUBLE_HIGH (op) == 0 && (CONST_DOUBLE_LOW (op) & 0x200) == 0))) || (GET_CODE (op) == CONST_INT && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode) && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x200) < 0x400));}/* Return truth value of whether OP is an integer which fits the range constraining immediate operands in most three-address insns, which have a 13 bit immediate field. */intsmall_int (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ return (GET_CODE (op) == CONST_INT && SMALL_INT (op));}intsmall_int_or_double (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ return ((GET_CODE (op) == CONST_INT && SMALL_INT (op)) || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0 && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))));}/* Recognize operand values for the umul instruction. That instruction sign extends immediate values just like all other sparc instructions, but interprets the extended result as an unsigned number. */intuns_small_int (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{#if HOST_BITS_PER_WIDE_INT > 32 /* All allowed constants will fit a CONST_INT. */ return (GET_CODE (op) == CONST_INT && ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000) || (INTVAL (op) >= 0xFFFFF000 && INTVAL (op) <= 0xFFFFFFFF)));#else return ((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000) || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0 && (unsigned) CONST_DOUBLE_LOW (op) - 0xFFFFF000 < 0x1000));#endif}intuns_arith_operand (op, mode) rtx op; enum machine_mode mode;{ return register_operand (op, mode) || uns_small_int (op, mode);}/* Return truth value of statement that OP is a call-clobbered register. */intclobbered_register (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);}/* Return 1 if OP is a valid operand for the source of a move insn. */intinput_operand (op, mode) rtx op; enum machine_mode mode;{ /* If both modes are non-void they must be the same. */ if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) return 0; /* Only a tiny bit of handling for CONSTANT_P_RTX is necessary. */ if (GET_CODE (op) == CONST && GET_CODE (XEXP (op, 0)) == CONSTANT_P_RTX) return 1; /* Allow any one instruction integer constant, and all CONST_INT variants when we are working in DImode and !arch64. */ if (GET_MODE_CLASS (mode) == MODE_INT && ((GET_CODE (op) == CONST_INT && (SPARC_SETHI_P (INTVAL (op) & GET_MODE_MASK (mode)) || SPARC_SIMM13_P (INTVAL (op)) || (mode == DImode && ! TARGET_ARCH64))) || (TARGET_ARCH64 && GET_CODE (op) == CONST_DOUBLE && ((CONST_DOUBLE_HIGH (op) == 0 && SPARC_SETHI_P (CONST_DOUBLE_LOW (op))) ||#if HOST_BITS_PER_WIDE_INT == 64 (CONST_DOUBLE_HIGH (op) == 0 && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op)))#else (SPARC_SIMM13_P (CONST_DOUBLE_LOW (op)) && (((CONST_DOUBLE_LOW (op) & 0x80000000) == 0 && CONST_DOUBLE_HIGH (op) == 0) || (CONST_DOUBLE_HIGH (op) == -1 && CONST_DOUBLE_LOW (op) & 0x80000000) != 0))#endif )))) return 1; /* If !arch64 and this is a DImode const, allow it so that the splits can be generated. */ if (! TARGET_ARCH64 && mode == DImode && GET_CODE (op) == CONST_DOUBLE) return 1; if (register_operand (op, mode)) return 1; if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_CODE (op) == CONST_DOUBLE) return 1; /* If this is a SUBREG, look inside so that we handle paradoxical ones. */ if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); /* Check for valid MEM forms. */ if (GET_CODE (op) == MEM) { rtx inside = XEXP (op, 0); if (GET_CODE (inside) == LO_SUM) { /* We can't allow these because all of the splits (eventually as they trickle down into DFmode splits) require offsettable memory references. */ if (! TARGET_V9 && GET_MODE (op) == TFmode) return 0; return (register_operand (XEXP (inside, 0), Pmode) && CONSTANT_P (XEXP (inside, 1))); } return memory_address_p (mode, inside); } return 0;}/* Return 1 if OP is valid for the lhs of a compare insn. */intcompare_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == ZERO_EXTRACT) return (register_operand (XEXP (op, 0), mode) && small_int_or_double (XEXP (op, 1), mode) && small_int_or_double (XEXP (op, 2), mode) /* This matches cmp_zero_extract. */ && ((mode == SImode && ((GET_CODE (XEXP (op, 2)) == CONST_INT && INTVAL (XEXP (op, 2)) > 19) || (GET_CODE (XEXP (op, 2)) == CONST_DOUBLE && CONST_DOUBLE_LOW (XEXP (op, 2)) > 19))) /* This matches cmp_zero_extract_sp64. */ || (mode == DImode && TARGET_ARCH64 && ((GET_CODE (XEXP (op, 2)) == CONST_INT && INTVAL (XEXP (op, 2)) > 51) || (GET_CODE (XEXP (op, 2)) == CONST_DOUBLE && CONST_DOUBLE_LOW (XEXP (op, 2)) > 51))))); else return register_operand (op, mode);}/* We know it can't be done in one insn when we get here, the movsi expander guarentees this. */voidsparc_emit_set_const32 (op0, op1) rtx op0; rtx op1;{ enum machine_mode mode = GET_MODE (op0); rtx temp; if (GET_CODE (op1) == CONST_INT)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -