📄 m32r.c
字号:
const char *str = XSTR (XEXP (rtl, 0), 0); int len = strlen (str); char *newstr = ggc_alloc (len + 2); strcpy (newstr + 1, str); *newstr = prefix; /* Note - we cannot leave the string in the ggc_alloc'ed space. It must reside in the stringtable's domain. */ newstr = (char *) ggc_alloc_string (newstr, len + 2); XSTR (XEXP (rtl, 0), 0) = newstr; }}/* Undo the effects of the above. */static const char *m32r_strip_name_encoding (str) const char *str;{ str += ENCODED_NAME_P (str); str += *str == '*'; return str;}/* Do anything needed before RTL is emitted for each function. */voidm32r_init_expanders (){ /* ??? At one point there was code here. The function is left in to make it easy to experiment. */}/* Acceptable arguments to the call insn. */intcall_address_operand (op, mode) rtx op; enum machine_mode mode;{ return symbolic_operand (op, mode);/* Constants and values in registers are not OK, because the m32r BL instruction can only support PC relative branching. */ }intcall_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) != MEM) return 0; op = XEXP (op, 0); return call_address_operand (op, mode);}/* Returns 1 if OP is a symbol reference. */intsymbolic_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ switch (GET_CODE (op)) { case SYMBOL_REF: case LABEL_REF: case CONST : return 1; default: return 0; }}/* Return 1 if OP is a reference to an object in .sdata/.sbss. */intsmall_data_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ if (! TARGET_SDATA_USE) return 0; if (GET_CODE (op) == SYMBOL_REF) return SDATA_NAME_P (XSTR (op, 0)); 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 && INT16_P (INTVAL (XEXP (XEXP (op, 0), 1)))) return SDATA_NAME_P (XSTR (XEXP (XEXP (op, 0), 0), 0)); return 0;}/* Return 1 if OP is a symbol that can use 24 bit addressing. */intaddr24_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ if (GET_CODE (op) == LABEL_REF) return TARGET_ADDR24; if (GET_CODE (op) == SYMBOL_REF) return (SMALL_NAME_P (XSTR (op, 0)) || (TARGET_ADDR24 && (CONSTANT_POOL_ADDRESS_P (op) || LIT_NAME_P (XSTR (op, 0))))); 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 && UINT24_P (INTVAL (XEXP (XEXP (op, 0), 1)))) { rtx sym = XEXP (XEXP (op, 0), 0); return (SMALL_NAME_P (XSTR (sym, 0)) || (TARGET_ADDR24 && (CONSTANT_POOL_ADDRESS_P (op) || LIT_NAME_P (XSTR (op, 0))))); } return 0;}/* Return 1 if OP is a symbol that needs 32 bit addressing. */intaddr32_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == LABEL_REF) return TARGET_ADDR32; if (GET_CODE (op) == SYMBOL_REF) return (! addr24_operand (op, mode) && ! small_data_operand (op, mode)); 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 (! addr24_operand (op, mode) && ! small_data_operand (op, mode)); } return 0;}/* Return 1 if OP is a function that can be called with the `bl' insn. */intcall26_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ if (GET_CODE (op) == SYMBOL_REF) return ! LARGE_NAME_P (XSTR (op, 0)); return TARGET_CALL26;}/* Returns 1 if OP is an acceptable operand for seth/add3. */intseth_add3_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF) return 1; 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 && INT16_P (INTVAL (XEXP (XEXP (op, 0), 1)))) return 1; return 0;}/* Return true if OP is a signed 8 bit immediate value. */intint8_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ if (GET_CODE (op) != CONST_INT) return 0; return INT8_P (INTVAL (op));}/* Return true if OP is a signed 16 bit immediate value useful in comparisons. */intcmp_int16_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ if (GET_CODE (op) != CONST_INT) return 0; return CMP_INT16_P (INTVAL (op));}/* Return true if OP is an unsigned 16 bit immediate value. */intuint16_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ if (GET_CODE (op) != CONST_INT) return 0; return UINT16_P (INTVAL (op));}/* Return true if OP is a register or signed 16 bit value. */intreg_or_int16_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) return register_operand (op, mode); if (GET_CODE (op) != CONST_INT) return 0; return INT16_P (INTVAL (op));}/* Return true if OP is a register or an unsigned 16 bit value. */intreg_or_uint16_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) return register_operand (op, mode); if (GET_CODE (op) != CONST_INT) return 0; return UINT16_P (INTVAL (op));}/* Return true if OP is a register or an integer value that can be used is SEQ/SNE. We can use either XOR of the value or ADD of the negative of the value for the constant. Don't allow 0, because that is special cased. */intreg_or_eq_int16_operand (op, mode) rtx op; enum machine_mode mode;{ HOST_WIDE_INT value; if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) return register_operand (op, mode); if (GET_CODE (op) != CONST_INT) return 0; value = INTVAL (op); return (value != 0) && (UINT16_P (value) || CMP_INT16_P (-value));}/* Return true if OP is a register or signed 16 bit value for compares. */intreg_or_cmp_int16_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) return register_operand (op, mode); if (GET_CODE (op) != CONST_INT) return 0; return CMP_INT16_P (INTVAL (op));}/* Return true if OP is a register or the constant 0. */intreg_or_zero_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG) return register_operand (op, mode); if (GET_CODE (op) != CONST_INT) return 0; return INTVAL (op) == 0;}/* Return true if OP is a const_int requiring two instructions to load. */inttwo_insn_const_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ if (GET_CODE (op) != CONST_INT) return 0; if (INT16_P (INTVAL (op)) || UINT24_P (INTVAL (op)) || UPPER16_P (INTVAL (op))) return 0; return 1;}/* Return true if OP is an acceptable argument for a single word move source. */intmove_src_operand (op, mode) rtx op; enum machine_mode mode;{ switch (GET_CODE (op)) { case SYMBOL_REF : case CONST : return addr24_operand (op, mode); case CONST_INT : /* ??? We allow more cse opportunities if we only allow constants loadable with one insn, and split the rest into two. The instances where this would help should be rare and the current way is simpler. */ if (HOST_BITS_PER_WIDE_INT > 32) { HOST_WIDE_INT rest = INTVAL (op) >> 31; return (rest == 0 || rest == -1); } else return 1; case LABEL_REF : return TARGET_ADDR24; case CONST_DOUBLE : if (mode == SFmode) return 1; else if (mode == SImode) { /* Large unsigned constants are represented as const_double's. */ unsigned HOST_WIDE_INT low, high; low = CONST_DOUBLE_LOW (op); high = CONST_DOUBLE_HIGH (op); return high == 0 && low <= 0xffffffff; } else return 0; case REG : return register_operand (op, mode); case SUBREG : /* (subreg (mem ...) ...) can occur here if the inner part was once a pseudo-reg and is now a stack slot. */ if (GET_CODE (SUBREG_REG (op)) == MEM) return address_operand (XEXP (SUBREG_REG (op), 0), mode); else return register_operand (op, mode); case MEM : if (GET_CODE (XEXP (op, 0)) == PRE_INC || GET_CODE (XEXP (op, 0)) == PRE_DEC) return 0; /* loads can't do pre-{inc,dec} */ return address_operand (XEXP (op, 0), mode); default : return 0; }}/* Return true if OP is an acceptable argument for a double word move source. */intmove_double_src_operand (op, mode) rtx op; enum machine_mode mode;{ switch (GET_CODE (op)) { case CONST_INT : case CONST_DOUBLE : return 1; case REG : return register_operand (op, mode); case SUBREG : /* (subreg (mem ...) ...) can occur here if the inner part was once a pseudo-reg and is now a stack slot. */ if (GET_CODE (SUBREG_REG (op)) == MEM) return move_double_src_operand (SUBREG_REG (op), mode); else return register_operand (op, mode); case MEM : /* Disallow auto inc/dec for now. */ if (GET_CODE (XEXP (op, 0)) == PRE_DEC || GET_CODE (XEXP (op, 0)) == PRE_INC) return 0; return address_operand (XEXP (op, 0), mode); default : return 0; }}/* Return true if OP is an acceptable argument for a move destination. */intmove_dest_operand (op, mode) rtx op; enum machine_mode mode;{ switch (GET_CODE (op)) { case REG : return register_operand (op, mode); case SUBREG : /* (subreg (mem ...) ...) can occur here if the inner part was once a pseudo-reg and is now a stack slot. */ if (GET_CODE (SUBREG_REG (op)) == MEM) return address_operand (XEXP (SUBREG_REG (op), 0), mode); else return register_operand (op, mode); case MEM : if (GET_CODE (XEXP (op, 0)) == POST_INC) return 0; /* stores can't do post inc */ return address_operand (XEXP (op, 0), mode); default : return 0; }}/* Return 1 if OP is a DImode const we want to handle inline. This must match the code in the movdi pattern. It is used by the 'G' CONST_DOUBLE_OK_FOR_LETTER. */inteasy_di_const (op) rtx op;{ rtx high_rtx, low_rtx; HOST_WIDE_INT high, low; split_double (op, &high_rtx, &low_rtx); high = INTVAL (high_rtx); low = INTVAL (low_rtx); /* Pick constants loadable with 2 16 bit `ldi' insns. */ if (high >= -128 && high <= 127 && low >= -128 && low <= 127) return 1; return 0;}/* Return 1 if OP is a DFmode const we want to handle inline. This must match the code in the movdf pattern. It is used by the 'H' CONST_DOUBLE_OK_FOR_LETTER. */inteasy_df_const (op) rtx op;{ REAL_VALUE_TYPE r; long l[2];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -