📄 arm.c
字号:
{ return (s_register_operand (op, mode) || (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op))) || memory_operand (op, mode));}/* Return TRUE for valid operands for the rhs of an ARM instruction, or if a constant that is valid when negated. */intarm_add_operand (op, mode) rtx op; enum machine_mode mode;{ return (s_register_operand (op, mode) || (GET_CODE (op) == CONST_INT && (const_ok_for_arm (INTVAL (op)) || const_ok_for_arm (-INTVAL (op)))));}intarm_not_operand (op, mode) rtx op; enum machine_mode mode;{ return (s_register_operand (op, mode) || (GET_CODE (op) == CONST_INT && (const_ok_for_arm (INTVAL (op)) || const_ok_for_arm (~INTVAL (op)))));}/* Return TRUE for valid operands for the rhs of an FPU instruction. */intfpu_rhs_operand (op, mode) rtx op; enum machine_mode mode;{ if (s_register_operand (op, mode)) return TRUE; else if (GET_CODE (op) == CONST_DOUBLE) return (const_double_rtx_ok_for_fpu (op)); return FALSE;}intfpu_add_operand (op, mode) rtx op; enum machine_mode mode;{ if (s_register_operand (op, mode)) return TRUE; else if (GET_CODE (op) == CONST_DOUBLE) return (const_double_rtx_ok_for_fpu (op) || neg_const_double_rtx_ok_for_fpu (op)); return FALSE;}/* Return nonzero if OP is a constant power of two. */intpower_of_two_operand (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) == CONST_INT) { HOST_WIDE_INT value = INTVAL(op); return value != 0 && (value & (value - 1)) == 0; } return FALSE;}/* Return TRUE for a valid operand of a DImode operation. Either: REG, CONST_DOUBLE or MEM(DImode_address). Note that this disallows MEM(REG+REG), but allows MEM(PRE/POST_INC/DEC(REG)). */intdi_operand (op, mode) rtx op; enum machine_mode mode;{ if (s_register_operand (op, mode)) return TRUE; switch (GET_CODE (op)) { case CONST_DOUBLE: case CONST_INT: return TRUE; case MEM: return memory_address_p (DImode, XEXP (op, 0)); default: return FALSE; }}/* Return TRUE for a valid operand of a DFmode operation when -msoft-float. Either: REG, CONST_DOUBLE or MEM(DImode_address). Note that this disallows MEM(REG+REG), but allows MEM(PRE/POST_INC/DEC(REG)). */intsoft_df_operand (op, mode) rtx op; enum machine_mode mode;{ if (s_register_operand (op, mode)) return TRUE; switch (GET_CODE (op)) { case CONST_DOUBLE: return TRUE; case MEM: return memory_address_p (DFmode, XEXP (op, 0)); default: return FALSE; }}/* Return TRUE for valid index operands. */intindex_operand (op, mode) rtx op; enum machine_mode mode;{ return (s_register_operand(op, mode) || (immediate_operand (op, mode) && INTVAL (op) < 4096 && INTVAL (op) > -4096));}/* Return TRUE for valid shifts by a constant. This also accepts any power of two on the (somewhat overly relaxed) assumption that the shift operator in this case was a mult. */intconst_shift_operand (op, mode) rtx op; enum machine_mode mode;{ return (power_of_two_operand (op, mode) || (immediate_operand (op, mode) && (INTVAL (op) < 32 && INTVAL (op) > 0)));}/* Return TRUE for arithmetic operators which can be combined with a multiply (shift). */intshiftable_operator (x, mode) rtx x; enum machine_mode mode;{ if (GET_MODE (x) != mode) return FALSE; else { enum rtx_code code = GET_CODE (x); return (code == PLUS || code == MINUS || code == IOR || code == XOR || code == AND); }}/* Return TRUE for shift operators. */intshift_operator (x, mode) rtx x; enum machine_mode mode;{ if (GET_MODE (x) != mode) return FALSE; else { enum rtx_code code = GET_CODE (x); if (code == MULT) return power_of_two_operand (XEXP (x, 1)); return (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT || code == ROTATERT); }}int equality_operator (x, mode) rtx x; enum machine_mode mode;{ return GET_CODE (x) == EQ || GET_CODE (x) == NE;}/* Return TRUE for SMIN SMAX UMIN UMAX operators. */intminmax_operator (x, mode) rtx x; enum machine_mode mode;{ enum rtx_code code = GET_CODE (x); if (GET_MODE (x) != mode) return FALSE; return code == SMIN || code == SMAX || code == UMIN || code == UMAX;}/* return TRUE if x is EQ or NE *//* Return TRUE if this is the condition code register, if we aren't given a mode, accept any class CCmode register */intcc_register (x, mode) rtx x; enum machine_mode mode;{ if (mode == VOIDmode) { mode = GET_MODE (x); if (GET_MODE_CLASS (mode) != MODE_CC) return FALSE; } if (mode == GET_MODE (x) && GET_CODE (x) == REG && REGNO (x) == 24) return TRUE; return FALSE;}/* Return TRUE if this is the condition code register, if we aren't given a mode, accept any mode in class CC_MODE that is reversible */intreversible_cc_register (x, mode) rtx x; enum machine_mode mode;{ if (mode == VOIDmode) { mode = GET_MODE (x); if (GET_MODE_CLASS (mode) != MODE_CC && GET_CODE (x) == REG && REGNO (x) == 24) abort (); if (GET_MODE_CLASS (mode) != MODE_CC || (! flag_fast_math && ! REVERSIBLE_CC_MODE (mode))) return FALSE; } if (mode == GET_MODE (x) && GET_CODE (x) == REG && REGNO (x) == 24) return TRUE; return FALSE;}enum rtx_codeminmax_code (x) rtx x;{ enum rtx_code code = GET_CODE (x); if (code == SMAX) return GE; else if (code == SMIN) return LE; else if (code == UMIN) return LEU; else if (code == UMAX) return GEU; abort ();}/* Return 1 if memory locations are adjacent */intadjacent_mem_locations (a, b) rtx a, b;{ int val0 = 0, val1 = 0; int reg0, reg1; if ((GET_CODE (XEXP (a, 0)) == REG || (GET_CODE (XEXP (a, 0)) == PLUS && GET_CODE (XEXP (XEXP (a, 0), 1)) == CONST_INT)) && (GET_CODE (XEXP (b, 0)) == REG || (GET_CODE (XEXP (b, 0)) == PLUS && GET_CODE (XEXP (XEXP (b, 0), 1)) == CONST_INT))) { if (GET_CODE (XEXP (a, 0)) == PLUS) { reg0 = REGNO (XEXP (XEXP (a, 0), 0)); val0 = INTVAL (XEXP (XEXP (a, 0), 1)); } else reg0 = REGNO (XEXP (a, 0)); if (GET_CODE (XEXP (b, 0)) == PLUS) { reg1 = REGNO (XEXP (XEXP (b, 0), 0)); val1 = INTVAL (XEXP (XEXP (b, 0), 1)); } else reg1 = REGNO (XEXP (b, 0)); return (reg0 == reg1) && ((val1 - val0) == 4 || (val0 - val1) == 4); } return 0;}/* Return 1 if OP is a load multiple operation. It is known to be parallel and the first section will be tested. */intload_multiple_operation (op, mode) rtx op; enum machine_mode mode;{ HOST_WIDE_INT count = XVECLEN (op, 0); int dest_regno; rtx src_addr; HOST_WIDE_INT i = 1, base = 0; rtx elt; if (count <= 1 || GET_CODE (XVECEXP (op, 0, 0)) != SET) return 0; /* Check to see if this might be a write-back */ if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS) { i++; base = 1; /* Now check it more carefully */ if (GET_CODE (SET_DEST (elt)) != REG || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG || REGNO (XEXP (SET_SRC (elt), 0)) != REGNO (SET_DEST (elt)) || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 2) * 4 || GET_CODE (XVECEXP (op, 0, count - 1)) != CLOBBER || GET_CODE (XEXP (XVECEXP (op, 0, count - 1), 0)) != REG || REGNO (XEXP (XVECEXP (op, 0, count - 1), 0)) != REGNO (SET_DEST (elt))) return 0; count--; } /* Perform a quick check so we don't blow up below. */ if (count <= i || GET_CODE (XVECEXP (op, 0, i - 1)) != SET || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != REG || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != MEM) return 0; dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1))); src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0); for (; i < count; i++) { rtx elt = XVECEXP (op, 0, i); if (GET_CODE (elt) != SET || GET_CODE (SET_DEST (elt)) != REG || GET_MODE (SET_DEST (elt)) != SImode || REGNO (SET_DEST (elt)) != dest_regno + i - base || GET_CODE (SET_SRC (elt)) != MEM || GET_MODE (SET_SRC (elt)) != SImode || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr) || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != (i - base) * 4) return 0; } return 1;}/* Return 1 if OP is a store multiple operation. It is known to be parallel and the first section will be tested. */intstore_multiple_operation (op, mode) rtx op; enum machine_mode mode;{ HOST_WIDE_INT count = XVECLEN (op, 0); int src_regno; rtx dest_addr; HOST_WIDE_INT i = 1, base = 0; rtx elt; if (count <= 1 || GET_CODE (XVECEXP (op, 0, 0)) != SET) return 0; /* Check to see if this might be a write-back */ if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS) { i++; base = 1; /* Now check it more carefully */ if (GET_CODE (SET_DEST (elt)) != REG || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG || REGNO (XEXP (SET_SRC (elt), 0)) != REGNO (SET_DEST (elt)) || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 2) * 4 || GET_CODE (XVECEXP (op, 0, count - 1)) != CLOBBER || GET_CODE (XEXP (XVECEXP (op, 0, count - 1), 0)) != REG || REGNO (XEXP (XVECEXP (op, 0, count - 1), 0)) != REGNO (SET_DEST (elt))) return 0; count--; } /* Perform a quick check so we don't blow up below. */ if (count <= i || GET_CODE (XVECEXP (op, 0, i - 1)) != SET || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != MEM || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != REG) return 0; src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1))); dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0); for (; i < count; i++) { elt = XVECEXP (op, 0, i); if (GET_CODE (elt) != SET || GET_CODE (SET_SRC (elt)) != REG || GET_MODE (SET_SRC (elt)) != SImode || REGNO (SET_SRC (elt)) != src_regno + i - base || GET_CODE (SET_DEST (elt)) != MEM || GET_MODE (SET_DEST (elt)) != SImode || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr) || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != (i - base) * 4) return 0; } return 1;}intmulti_register_push (op, mode) rtx op; enum machine_mode mode;{ if (GET_CODE (op) != PARALLEL || (GET_CODE (XVECEXP (op, 0, 0)) != SET) || (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC) || (XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != 2)) return 0; return 1;}/* Routines for use with attributes */intconst_pool_offset (symbol) rtx symbol;{ return get_pool_offset (symbol) - get_pool_size () - get_prologue_size ();}/* Routines for use in generating RTL */rtxarm_gen_load_multiple (base_regno, count, from, up, write_back) int base_regno; int count; rtx from; int up; int write_back;{ int i = 0, j; rtx result; int sign = up ? 1 : -1; result = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (count + (write_back ? 2 : 0))); if (write_back) { XVECEXP (result, 0, 0) = gen_rtx (SET, GET_MODE (from), from, plus_constant (from, count * 4 * sign)); i = 1; count++; } for (j = 0; i < count; i++, j++) { XVECEXP (result, 0, i) = gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, base_regno + j), gen_rtx (MEM, SImode, plus_constant (from, j * 4 * sign))); } if (write_back) XVECEXP (result, 0, i) = gen_rtx (CLOBBER, SImode, from); return result;}rtxarm_gen_store_multiple (base_regno, count, to, up, write_back) int base_regno; int count;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -