]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/pa/predicates.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / pa / predicates.md
index 4a871194c29c2dd0e733973c51477c216a66b1cd..131ccbee2cd39b313ed9c9783c4e40dc7c665682 100644 (file)
@@ -1,5 +1,5 @@
 ;; Predicate definitions for HP PA-RISC.
-;; Copyright (C) 2005, 2007, 2010, 2011 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2020 Free Software Foundation, Inc.
 ;;
 ;; This file is part of GCC.
 ;;
   (and (match_code "const_int")
        (match_test "INT_U5_BITS (op)")))
 
+;; Return truth value of whether OP is an integer which fits the range
+;; constraining 6-bit unsigned immediate operands in three-address insns.
+
+(define_predicate "uint6_operand"
+  (and (match_code "const_int")
+       (match_test "INT_U6_BITS (op)")))
+
 ;; Return truth value of whether OP is an integer which fits the range
 ;; constraining 11-bit signed immediate operands in three-address insns.
 
   (ior (match_operand 0 "register_operand")
        (match_code "const_int")))
 
+;; Return truth value of whether OP can be used as a shift operand in
+;; a shift insn that accepts registers of mode MODE or 5-bit shift amounts.
+
+(define_predicate "shift5_operand"
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "uint5_operand")))
+
+;; Return truth value of whether OP can be used as a shift operand in
+;; a shift insn that accepts registers of mode MODE or 6-bit shift amounts.
+
+(define_predicate "shift6_operand"
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "uint6_operand")))
+
 ;; True iff OP can be used as an operand in an adddi3 insn.
 
 (define_predicate "adddi3_operand"
   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 E_BLKmode:
+    case E_QImode:
+    case E_HImode:
+      return true;
+
+    case E_VOIDmode:
+      return false;
+
+    default:
+      return (INTVAL (op) % GET_MODE_SIZE (mode)) == 0;
+    }
+
+  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))
+    {
+      if (reload_in_progress)
+       return true;
+
+      /* 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))
+    {
+      if (reload_in_progress)
+       return true;
+
+      /* 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.
   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);
 ;; This predicate is used for branch patterns that internally handle
 ;; register reloading.  We need to accept non-symbolic memory operands
 ;; after reload to ensure that the pattern is still valid if reload
-;; didn't find a hard register for the operand.
+;; didn't find a hard register for the operand.  We also reject index
+;; and lo_sum DLT address as these are invalid for move destinations.
 
 (define_predicate "reg_before_reload_operand"
   (match_code "reg,mem")
 {
+  rtx op0;
+
   if (register_operand (op, mode))
     return true;
 
-  if (reload_completed
-      && memory_operand (op, mode)
-      && !symbolic_memory_operand (op, mode))
-    return true;
+  if (!reload_in_progress && !reload_completed)
+    return false;
 
-  return false;
+  if (! MEM_P (op))
+    return false;
+
+  op0 = XEXP (op, 0);
+
+  return (memory_address_p (mode, op0)
+         && !IS_INDEX_ADDR_P (op0)
+         && !IS_LO_SUM_DLT_ADDR_P (op0)
+         && !symbolic_memory_operand (op, mode));
 })
 
 ;; True iff OP is a register or const_0 operand for MODE.
 ;; Return 1 if OP is a CONST_INT with the value 2, 4, or 8.  These are
 ;; the valid constants for shadd instructions.
 
+(define_predicate "mem_shadd_operand"
+  (and (match_code "const_int")
+       (match_test "pa_mem_shadd_constant_p (INTVAL (op))")))
+
 (define_predicate "shadd_operand"
   (and (match_code "const_int")
        (match_test "pa_shadd_constant_p (INTVAL (op))")))
     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.
                  || 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.