163d1a8abSmrg;; Predicate definitions for Renesas RX.
2*ec02198aSmrg;; Copyright (C) 2008-2020 Free Software Foundation, Inc.
363d1a8abSmrg;; Contributed by Red Hat.
463d1a8abSmrg;;
563d1a8abSmrg;; This file is part of GCC.
663d1a8abSmrg;;
763d1a8abSmrg;; GCC is free software; you can redistribute it and/or modify
863d1a8abSmrg;; it under the terms of the GNU General Public License as published by
963d1a8abSmrg;; the Free Software Foundation; either version 3, or (at your option)
1063d1a8abSmrg;; any later version.
1163d1a8abSmrg;;
1263d1a8abSmrg;; GCC is distributed in the hope that it will be useful,
1363d1a8abSmrg;; but WITHOUT ANY WARRANTY; without even the implied warranty of
1463d1a8abSmrg;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1563d1a8abSmrg;; GNU General Public License for more details.
1663d1a8abSmrg;;
1763d1a8abSmrg;; You should have received a copy of the GNU General Public License
1863d1a8abSmrg;; along with GCC; see the file COPYING3.  If not see
1963d1a8abSmrg;; <http://www.gnu.org/licenses/>.
2063d1a8abSmrg
2163d1a8abSmrg
2263d1a8abSmrg
2363d1a8abSmrg;; Check that the operand is suitable for a call insn.
2463d1a8abSmrg;; Only registers and symbol refs are allowed.
2563d1a8abSmrg
2663d1a8abSmrg(define_predicate "rx_call_operand"
2763d1a8abSmrg  (ior (match_code "reg")
2863d1a8abSmrg       (and (match_test "!TARGET_JSR")
2963d1a8abSmrg	    (match_code "symbol_ref")))
3063d1a8abSmrg)
3163d1a8abSmrg
3263d1a8abSmrg;; For sibcall operations we can only use a symbolic address.
3363d1a8abSmrg
3463d1a8abSmrg(define_predicate "rx_symbolic_call_operand"
3563d1a8abSmrg  (match_code "symbol_ref")
3663d1a8abSmrg)
3763d1a8abSmrg
3863d1a8abSmrg;; Check that the operand is suitable for a shift insn
3963d1a8abSmrg;; Only small integers or a value in a register are permitted.
4063d1a8abSmrg
4163d1a8abSmrg(define_predicate "rx_shift_operand"
4263d1a8abSmrg  (ior (match_operand 0 "register_operand")
4363d1a8abSmrg       (and (match_code "const_int")
4463d1a8abSmrg	    (match_test "IN_RANGE (INTVAL (op), 0, 31)")))
4563d1a8abSmrg)
4663d1a8abSmrg
4763d1a8abSmrg(define_predicate "rx_constshift_operand"
4863d1a8abSmrg  (and (match_code "const_int")
4963d1a8abSmrg       (match_test "IN_RANGE (INTVAL (op), 0, 31)"))
5063d1a8abSmrg)
5163d1a8abSmrg
5263d1a8abSmrg(define_predicate "rx_restricted_mem_operand"
5363d1a8abSmrg  (and (match_code "mem")
5463d1a8abSmrg       (match_test "rx_is_restricted_memory_address (XEXP (op, 0), mode)"))
5563d1a8abSmrg)
5663d1a8abSmrg
5763d1a8abSmrg;; Check that the operand is suitable as the source operand
5863d1a8abSmrg;; for a logic or arithmeitc instruction.  Registers, integers
5963d1a8abSmrg;; and a restricted subset of memory addresses are allowed.
6063d1a8abSmrg
6163d1a8abSmrg(define_predicate "rx_source_operand"
6263d1a8abSmrg  (ior (match_operand 0 "register_operand")
6363d1a8abSmrg       (match_operand 0 "immediate_operand")
6463d1a8abSmrg       (match_operand 0 "rx_restricted_mem_operand"))
6563d1a8abSmrg)
6663d1a8abSmrg
6763d1a8abSmrg;; Check that the operand is suitable as the source operand
6863d1a8abSmrg;; for a comparison instruction.  This is the same as
6963d1a8abSmrg;; rx_source_operand except that SUBREGs are allowed but
7063d1a8abSmrg;; CONST_INTs are not.
7163d1a8abSmrg
7263d1a8abSmrg(define_predicate "rx_compare_operand"
7363d1a8abSmrg  (ior (match_operand 0 "register_operand")
7463d1a8abSmrg       (match_operand 0 "rx_restricted_mem_operand"))
7563d1a8abSmrg)
7663d1a8abSmrg
7763d1a8abSmrg;; Check that the operand is suitable as the source operand
7863d1a8abSmrg;; for a min/max instruction.  This is the same as
7963d1a8abSmrg;; rx_source_operand except that CONST_INTs are allowed but
8063d1a8abSmrg;; REGs and SUBREGs are not.
8163d1a8abSmrg
8263d1a8abSmrg(define_predicate "rx_minmaxex_operand"
8363d1a8abSmrg  (ior (match_operand 0 "immediate_operand")
8463d1a8abSmrg       (match_operand 0 "rx_restricted_mem_operand"))
8563d1a8abSmrg)
8663d1a8abSmrg
8763d1a8abSmrg;; Return true if OP is a store multiple operation.  This looks like:
8863d1a8abSmrg;;
8963d1a8abSmrg;;   [(set (SP) (MINUS (SP) (INT)))
9063d1a8abSmrg;;    (set (MEM (SP)) (REG))
9163d1a8abSmrg;;    (set (MEM (MINUS (SP) (INT))) (REG)) {optionally repeated}
9263d1a8abSmrg;;   ]
9363d1a8abSmrg
9463d1a8abSmrg(define_special_predicate "rx_store_multiple_vector"
9563d1a8abSmrg  (match_code "parallel")
9663d1a8abSmrg{
9763d1a8abSmrg  int count = XVECLEN (op, 0);
9863d1a8abSmrg  unsigned int src_regno;
9963d1a8abSmrg  rtx element;
10063d1a8abSmrg  int i;
10163d1a8abSmrg
10263d1a8abSmrg  /* Perform a quick check so we don't blow up below.  */
10363d1a8abSmrg  if (count <= 2)
10463d1a8abSmrg    return false;
10563d1a8abSmrg
10663d1a8abSmrg  /* Check that the first element of the vector is the stack adjust.  */
10763d1a8abSmrg  element = XVECEXP (op, 0, 0);
10863d1a8abSmrg  if (   ! SET_P (element)
10963d1a8abSmrg      || ! REG_P (SET_DEST (element))
11063d1a8abSmrg      ||   REGNO (SET_DEST (element)) != SP_REG
11163d1a8abSmrg      ||   GET_CODE (SET_SRC (element)) != MINUS
11263d1a8abSmrg      || ! REG_P (XEXP (SET_SRC (element), 0))
11363d1a8abSmrg      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
11463d1a8abSmrg      || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
11563d1a8abSmrg    return false;
11663d1a8abSmrg
11763d1a8abSmrg  /* Check that the next element is the first push.  */
11863d1a8abSmrg  element = XVECEXP (op, 0, 1);
11963d1a8abSmrg  if (   ! SET_P (element)
12063d1a8abSmrg      || ! REG_P (SET_SRC (element))
12163d1a8abSmrg      || GET_MODE (SET_SRC (element)) != SImode
12263d1a8abSmrg      || ! MEM_P (SET_DEST (element))
12363d1a8abSmrg      || GET_MODE (SET_DEST (element)) != SImode
12463d1a8abSmrg      || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
12563d1a8abSmrg      || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
12663d1a8abSmrg      ||   REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
12763d1a8abSmrg      || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
12863d1a8abSmrg      || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
12963d1a8abSmrg        != GET_MODE_SIZE (SImode))
13063d1a8abSmrg    return false;
13163d1a8abSmrg
13263d1a8abSmrg  src_regno = REGNO (SET_SRC (element));
13363d1a8abSmrg
13463d1a8abSmrg  /* Check that the remaining elements use SP-<disp>
13563d1a8abSmrg     addressing and decreasing register numbers.  */
13663d1a8abSmrg  for (i = 2; i < count; i++)
13763d1a8abSmrg    {
13863d1a8abSmrg      element = XVECEXP (op, 0, i);
13963d1a8abSmrg
14063d1a8abSmrg      if (   ! SET_P (element)
14163d1a8abSmrg	  || ! REG_P (SET_SRC (element))
14263d1a8abSmrg	  || GET_MODE (SET_SRC (element)) != SImode
14363d1a8abSmrg	  || REGNO (SET_SRC (element)) != src_regno - (i - 1)
14463d1a8abSmrg	  || ! MEM_P (SET_DEST (element))
14563d1a8abSmrg	  || GET_MODE (SET_DEST (element)) != SImode
14663d1a8abSmrg	  || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS
14763d1a8abSmrg          || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0))
14863d1a8abSmrg          ||   REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG
14963d1a8abSmrg	  || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1))
15063d1a8abSmrg	  || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1))
15163d1a8abSmrg	     != i * GET_MODE_SIZE (SImode))
15263d1a8abSmrg	return false;
15363d1a8abSmrg    }
15463d1a8abSmrg  return true;
15563d1a8abSmrg})
15663d1a8abSmrg
15763d1a8abSmrg;; Return true if OP is a load multiple operation.
15863d1a8abSmrg;; This looks like:
15963d1a8abSmrg;;  [(set (SP) (PLUS (SP) (INT)))
16063d1a8abSmrg;;   (set (REG) (MEM (SP)))
16163d1a8abSmrg;;   (set (REG) (MEM (PLUS (SP) (INT)))) {optionally repeated}
16263d1a8abSmrg;;  ]
16363d1a8abSmrg
16463d1a8abSmrg(define_special_predicate "rx_load_multiple_vector"
16563d1a8abSmrg  (match_code "parallel")
16663d1a8abSmrg{
16763d1a8abSmrg  int count = XVECLEN (op, 0);
16863d1a8abSmrg  unsigned int dest_regno;
16963d1a8abSmrg  rtx element;
17063d1a8abSmrg  int i;
17163d1a8abSmrg
17263d1a8abSmrg  /* Perform a quick check so we don't blow up below.  */
17363d1a8abSmrg  if (count <= 2)
17463d1a8abSmrg    return false;
17563d1a8abSmrg
17663d1a8abSmrg  /* Check that the first element of the vector is the stack adjust.  */
17763d1a8abSmrg  element = XVECEXP (op, 0, 0);
17863d1a8abSmrg  if (   ! SET_P (element)
17963d1a8abSmrg      || ! REG_P (SET_DEST (element))
18063d1a8abSmrg      ||   REGNO (SET_DEST (element)) != SP_REG
18163d1a8abSmrg      ||   GET_CODE (SET_SRC (element)) != PLUS
18263d1a8abSmrg      || ! REG_P (XEXP (SET_SRC (element), 0))
18363d1a8abSmrg      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
18463d1a8abSmrg      || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
18563d1a8abSmrg    return false;
18663d1a8abSmrg
18763d1a8abSmrg  /* Check that the next element is the first push.  */
18863d1a8abSmrg  element = XVECEXP (op, 0, 1);
18963d1a8abSmrg  if (   ! SET_P (element)
19063d1a8abSmrg      || ! REG_P (SET_DEST (element))
19163d1a8abSmrg      || ! MEM_P (SET_SRC (element))
19263d1a8abSmrg      || ! REG_P (XEXP (SET_SRC (element), 0))
19363d1a8abSmrg      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
19463d1a8abSmrg    return false;
19563d1a8abSmrg
19663d1a8abSmrg  dest_regno = REGNO (SET_DEST (element));
19763d1a8abSmrg
19863d1a8abSmrg  /* Check that the remaining elements use SP+<disp>
19963d1a8abSmrg     addressing and incremental register numbers.  */
20063d1a8abSmrg  for (i = 2; i < count; i++)
20163d1a8abSmrg    {
20263d1a8abSmrg      element = XVECEXP (op, 0, i);
20363d1a8abSmrg
20463d1a8abSmrg      if (   ! SET_P (element)
20563d1a8abSmrg	  || ! REG_P (SET_DEST (element))
20663d1a8abSmrg	  || GET_MODE (SET_DEST (element)) != SImode
20763d1a8abSmrg	  || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
20863d1a8abSmrg	  || ! MEM_P (SET_SRC (element))
20963d1a8abSmrg	  || GET_MODE (SET_SRC (element)) != SImode
21063d1a8abSmrg	  || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
21163d1a8abSmrg          || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
21263d1a8abSmrg          ||   REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
21363d1a8abSmrg	  || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
21463d1a8abSmrg	  || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
21563d1a8abSmrg	     != (i - 1) * GET_MODE_SIZE (SImode))
21663d1a8abSmrg	return false;
21763d1a8abSmrg    }
21863d1a8abSmrg  return true;
21963d1a8abSmrg})
22063d1a8abSmrg
22163d1a8abSmrg;; Return true if OP is a pop-and-return load multiple operation.
22263d1a8abSmrg;; This looks like:
22363d1a8abSmrg;;  [(set (SP) (PLUS (SP) (INT)))
22463d1a8abSmrg;;   (set (REG) (MEM (SP)))
22563d1a8abSmrg;;   (set (REG) (MEM (PLUS (SP) (INT)))) {optional and possibly repeated}
22663d1a8abSmrg;;   (return)
22763d1a8abSmrg;;  ]
22863d1a8abSmrg
22963d1a8abSmrg(define_special_predicate "rx_rtsd_vector"
23063d1a8abSmrg  (match_code "parallel")
23163d1a8abSmrg{
23263d1a8abSmrg  int count = XVECLEN (op, 0);
23363d1a8abSmrg  unsigned int dest_regno;
23463d1a8abSmrg  rtx element;
23563d1a8abSmrg  int i;
23663d1a8abSmrg
23763d1a8abSmrg  /* Perform a quick check so we don't blow up below.  */
23863d1a8abSmrg  if (count <= 2)
23963d1a8abSmrg    return false;
24063d1a8abSmrg
24163d1a8abSmrg  /* Check that the first element of the vector is the stack adjust.  */
24263d1a8abSmrg  element = XVECEXP (op, 0, 0);
24363d1a8abSmrg  if (   ! SET_P (element)
24463d1a8abSmrg      || ! REG_P (SET_DEST (element))
24563d1a8abSmrg      ||   REGNO (SET_DEST (element)) != SP_REG
24663d1a8abSmrg      ||   GET_CODE (SET_SRC (element)) != PLUS
24763d1a8abSmrg      || ! REG_P (XEXP (SET_SRC (element), 0))
24863d1a8abSmrg      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG
24963d1a8abSmrg      || ! CONST_INT_P (XEXP (SET_SRC (element), 1)))
25063d1a8abSmrg    return false;
25163d1a8abSmrg
25263d1a8abSmrg  /* Check that the next element is the first push.  */
25363d1a8abSmrg  element = XVECEXP (op, 0, 1);
25463d1a8abSmrg  if (   ! SET_P (element)
25563d1a8abSmrg      || ! REG_P (SET_DEST (element))
25663d1a8abSmrg      || ! MEM_P (SET_SRC (element))
25763d1a8abSmrg      || ! REG_P (XEXP (SET_SRC (element), 0))
25863d1a8abSmrg      ||   REGNO (XEXP (SET_SRC (element), 0)) != SP_REG)
25963d1a8abSmrg    return false;
26063d1a8abSmrg
26163d1a8abSmrg  dest_regno = REGNO (SET_DEST (element));
26263d1a8abSmrg
26363d1a8abSmrg  /* Check that the remaining elements, if any, and except
26463d1a8abSmrg     for the last one, use SP+<disp> addressing and incremental
26563d1a8abSmrg     register numbers.  */
26663d1a8abSmrg  for (i = 2; i < count - 1; i++)
26763d1a8abSmrg    {
26863d1a8abSmrg      element = XVECEXP (op, 0, i);
26963d1a8abSmrg
27063d1a8abSmrg      if (   ! SET_P (element)
27163d1a8abSmrg	  || ! REG_P (SET_DEST (element))
27263d1a8abSmrg	  || GET_MODE (SET_DEST (element)) != SImode
27363d1a8abSmrg	  || REGNO (SET_DEST (element)) != dest_regno + (i - 1)
27463d1a8abSmrg	  || ! MEM_P (SET_SRC (element))
27563d1a8abSmrg	  || GET_MODE (SET_SRC (element)) != SImode
27663d1a8abSmrg	  || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS
27763d1a8abSmrg          || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0))
27863d1a8abSmrg          ||   REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG
27963d1a8abSmrg	  || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1))
28063d1a8abSmrg	  || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1))
28163d1a8abSmrg	     != (i - 1) * GET_MODE_SIZE (SImode))
28263d1a8abSmrg	return false;
28363d1a8abSmrg    }
28463d1a8abSmrg
28563d1a8abSmrg  /* The last element must be a RETURN.  */
28663d1a8abSmrg  element = XVECEXP (op, 0, count - 1);
28763d1a8abSmrg  return GET_CODE (element) == RETURN;
28863d1a8abSmrg})
28963d1a8abSmrg
29063d1a8abSmrg(define_predicate "label_ref_operand"
29163d1a8abSmrg  (match_code "label_ref")
29263d1a8abSmrg)
29363d1a8abSmrg
29463d1a8abSmrg(define_predicate "rx_z_comparison_operator"
29563d1a8abSmrg  (match_code "eq,ne")
29663d1a8abSmrg)
29763d1a8abSmrg
29863d1a8abSmrg(define_predicate "rx_zs_comparison_operator"
29963d1a8abSmrg  (match_code "eq,ne,lt,ge")
30063d1a8abSmrg)
30163d1a8abSmrg
30263d1a8abSmrg;; GT and LE omitted due to operand swap required.
30363d1a8abSmrg(define_predicate "rx_fp_comparison_operator"
30463d1a8abSmrg  (match_code "eq,ne,lt,ge,ordered,unordered")
30563d1a8abSmrg)
30663d1a8abSmrg
30763d1a8abSmrg(define_predicate "rshift_operator"
30863d1a8abSmrg  (match_code "ashiftrt,lshiftrt")
30963d1a8abSmrg)
310