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