diff options
Diffstat (limited to 'gcc/config/pa/predicates.md')
-rw-r--r-- | gcc/config/pa/predicates.md | 141 |
1 files changed, 127 insertions, 14 deletions
diff --git a/gcc/config/pa/predicates.md b/gcc/config/pa/predicates.md index d59530cbe3d..8823706026b 100644 --- a/gcc/config/pa/predicates.md +++ b/gcc/config/pa/predicates.md @@ -234,24 +234,134 @@ return IS_INDEX_ADDR_P (op) && memory_address_p (mode, op); }) +;; True iff OP is a register plus base memory operand. + +(define_predicate "reg_plus_base_memory_operand" + (match_code "subreg,mem") +{ + if (GET_MODE (op) != mode) + return false; + + /* Before reload, a (SUBREG (MEM...)) forces reloading into a register. */ + if (reload_completed && GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + if (! MEM_P (op)) + return false; + + op = XEXP (op, 0); + if (GET_CODE (op) != PLUS) + return false; + + if (REG_P (XEXP (op, 0)) && REG_OK_FOR_BASE_P (XEXP (op, 0))) + return GET_CODE (XEXP (op, 1)) == CONST_INT; + + return false; +}) + +;; True iff OP is a base14 operand. + +(define_predicate "base14_operand" + (match_code "const_int") +{ + if (!INT_14_BITS (op)) + return false; + + /* Although this may not be necessary, we require that the + base value is correctly aligned for its mode as this is + assumed in the instruction encoding. */ + switch (mode) + { + case QImode: + case HImode: + return true; + + case SImode: + case SFmode: + case SCmode: + return (INTVAL (op) % 4) == 0; + + case DImode: + case DFmode: + case DCmode: + return (INTVAL (op) % 8) == 0; + + default: + break; + } + + return false; +}) + ;; True iff the operand OP can be used as the destination operand of ;; an integer store. This also implies the operand could be used as -;; the source operand of an integer load. Symbolic, lo_sum and indexed +;; the source operand of an integer load. LO_SUM DLT and indexed ;; memory operands are not allowed. We accept reloading pseudos and ;; other memory operands. (define_predicate "integer_store_memory_operand" (match_code "reg,mem") { - return ((reload_in_progress - && REG_P (op) - && REGNO (op) >= FIRST_PSEUDO_REGISTER - && reg_renumber [REGNO (op)] < 0) - || (MEM_P (op) - && (reload_in_progress || memory_address_p (mode, XEXP (op, 0))) - && !symbolic_memory_operand (op, VOIDmode) - && !IS_LO_SUM_DLT_ADDR_P (XEXP (op, 0)) - && !IS_INDEX_ADDR_P (XEXP (op, 0)))); + if (reload_in_progress + && REG_P (op) + && REGNO (op) >= FIRST_PSEUDO_REGISTER + && reg_renumber [REGNO (op)] < 0) + return true; + + if (reg_plus_base_memory_operand (op, mode)) + { + /* Extract CONST_INT operand. */ + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + op = XEXP (op, 0); + op = REG_P (XEXP (op, 0)) ? XEXP (op, 1) : XEXP (op, 0); + return base14_operand (op, mode) || INT_5_BITS (op); + } + + if (!MEM_P (op)) + return false; + + return ((reload_in_progress || memory_address_p (mode, XEXP (op, 0))) + && !IS_LO_SUM_DLT_ADDR_P (XEXP (op, 0)) + && !IS_INDEX_ADDR_P (XEXP (op, 0))); +}) + +;; True iff the operand OP can be used as the destination operand of +;; a floating point store. This also implies the operand could be used as +;; the source operand of a floating point load. LO_SUM DLT and indexed +;; memory operands are not allowed. Symbolic operands are accepted if +;; INT14_OK_STRICT is true. We accept reloading pseudos and other memory +;; operands. + +(define_predicate "floating_point_store_memory_operand" + (match_code "reg,mem") +{ + if (reload_in_progress + && REG_P (op) + && REGNO (op) >= FIRST_PSEUDO_REGISTER + && reg_renumber [REGNO (op)] < 0) + return true; + + if (reg_plus_base_memory_operand (op, mode)) + { + /* Extract CONST_INT operand. */ + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + op = XEXP (op, 0); + op = REG_P (XEXP (op, 0)) ? XEXP (op, 1) : XEXP (op, 0); + return ((TARGET_PA_20 + && !TARGET_ELF32 + && base14_operand (op, mode)) + || INT_5_BITS (op)); + } + + if (!MEM_P (op)) + return false; + + return ((reload_in_progress || memory_address_p (mode, XEXP (op, 0))) + && (INT14_OK_STRICT || !symbolic_memory_operand (op, VOIDmode)) + && !IS_LO_SUM_DLT_ADDR_P (XEXP (op, 0)) + && !IS_INDEX_ADDR_P (XEXP (op, 0))); }) ;; Return true iff OP is an integer register. @@ -302,7 +412,7 @@ if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); - if (GET_CODE (op) != MEM || symbolic_memory_operand (op, mode)) + if (! MEM_P (op)) return false; op = XEXP (op, 0); @@ -484,7 +594,10 @@ op = SUBREG_REG (op); if (!MEM_P (op)) return false; - return pa_symbolic_expression_p (XEXP (op, 0)); + op = XEXP (op, 0); + if (GET_CODE (op) == LO_SUM) + op = XEXP (op, 1); + return pa_symbolic_expression_p (op); }) ;; True iff OP is a symbolic operand. @@ -507,9 +620,9 @@ || GET_CODE (XEXP (op, 0)) == LABEL_REF) && GET_CODE (XEXP (op, 1)) == CONST_INT); default: - gcc_unreachable (); + break; } - return true; + return false; }) ;; Return true if OP is a symbolic operand for the TLS Global Dynamic model. |