📄 arm.c
字号:
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 class CCmode register which indicates a dominance expression. */intdominant_cc_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 != CC_DNEmode && mode != CC_DEQmode && mode != CC_DLEmode && mode != CC_DLTmode && mode != CC_DGEmode && mode != CC_DGTmode && mode != CC_DLEUmode && mode != CC_DLTUmode && mode != CC_DGEUmode && mode != CC_DGTUmode) return FALSE; if (mode == GET_MODE (x) && GET_CODE (x) == REG && REGNO (x) == 24) return TRUE; return FALSE;}/* Return TRUE if X references a SYMBOL_REF. */intsymbol_mentioned_p (x) rtx x;{ register char *fmt; register int i; if (GET_CODE (x) == SYMBOL_REF) return 1; fmt = GET_RTX_FORMAT (GET_CODE (x)); for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) { if (fmt[i] == 'E') { register int j; for (j = XVECLEN (x, i) - 1; j >= 0; j--) if (symbol_mentioned_p (XVECEXP (x, i, j))) return 1; } else if (fmt[i] == 'e' && symbol_mentioned_p (XEXP (x, i))) return 1; } return 0;}/* Return TRUE if X references a LABEL_REF. */intlabel_mentioned_p (x) rtx x;{ register char *fmt; register int i; if (GET_CODE (x) == LABEL_REF) return 1; fmt = GET_RTX_FORMAT (GET_CODE (x)); for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) { if (fmt[i] == 'E') { register int j; for (j = XVECLEN (x, i) - 1; j >= 0; j--) if (label_mentioned_p (XVECEXP (x, i, j))) return 1; } else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i))) return 1; } return 0;}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;}intload_multiple_sequence (operands, nops, regs, base, load_offset) rtx *operands; int nops; int *regs; int *base; HOST_WIDE_INT *load_offset;{ int unsorted_regs[4]; HOST_WIDE_INT unsorted_offsets[4]; int order[4]; int base_reg; int i; /* Can only handle 2, 3, or 4 insns at present, though could be easily extended if required. */ if (nops < 2 || nops > 4) abort (); /* Loop over the operands and check that the memory references are suitable (ie immediate offsets from the same base register). At the same time, extract the target register, and the memory offsets. */ for (i = 0; i < nops; i++) { rtx reg; rtx offset; /* Convert a subreg of a mem into the mem itself. */ if (GET_CODE (operands[nops + i]) == SUBREG) operands[nops + i] = alter_subreg(operands[nops + i]); if (GET_CODE (operands[nops + i]) != MEM) abort (); /* Don't reorder volatile memory references; it doesn't seem worth looking for the case where the order is ok anyway. */ if (MEM_VOLATILE_P (operands[nops + i])) return 0; offset = const0_rtx; if ((GET_CODE (reg = XEXP (operands[nops + i], 0)) == REG || (GET_CODE (reg) == SUBREG && GET_CODE (reg = SUBREG_REG (reg)) == REG)) || (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS && ((GET_CODE (reg = XEXP (XEXP (operands[nops + i], 0), 0)) == REG) || (GET_CODE (reg) == SUBREG && GET_CODE (reg = SUBREG_REG (reg)) == REG)) && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1)) == CONST_INT))) { if (i == 0) { base_reg = REGNO(reg); unsorted_regs[0] = (GET_CODE (operands[i]) == REG ? REGNO (operands[i]) : REGNO (SUBREG_REG (operands[i]))); order[0] = 0; } else { if (base_reg != REGNO (reg)) /* Not addressed from the same base register. */ return 0; unsorted_regs[i] = (GET_CODE (operands[i]) == REG ? REGNO (operands[i]) : REGNO (SUBREG_REG (operands[i]))); if (unsorted_regs[i] < unsorted_regs[order[0]]) order[0] = i; } /* If it isn't an integer register, or if it overwrites the base register but isn't the last insn in the list, then we can't do this. */ if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14 || (i != nops - 1 && unsorted_regs[i] == base_reg)) return 0; unsorted_offsets[i] = INTVAL (offset); } else /* Not a suitable memory address. */ return 0; } /* All the useful information has now been extracted from the operands into unsorted_regs and unsorted_offsets; additionally, order[0] has been set to the lowest numbered register in the list. Sort the registers into order, and check that the memory offsets are ascending and adjacent. */ for (i = 1; i < nops; i++) { int j; order[i] = order[i - 1]; for (j = 0; j < nops; j++) if (unsorted_regs[j] > unsorted_regs[order[i - 1]] && (order[i] == order[i - 1] || unsorted_regs[j] < unsorted_regs[order[i]])) order[i] = j; /* Have we found a suitable register? if not
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -