1;; Predicate definitions for Renesas RX. 2;; Copyright (C) 2008-2021 Free Software Foundation, Inc. 3;; Contributed by Red Hat. 4;; 5;; This file is part of GCC. 6;; 7;; GCC is free software; you can redistribute it and/or modify 8;; it under the terms of the GNU General Public License as published by 9;; the Free Software Foundation; either version 3, or (at your option) 10;; any later version. 11;; 12;; GCC is distributed in the hope that it will be useful, 13;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15;; GNU General Public License for more details. 16;; 17;; You should have received a copy of the GNU General Public License 18;; along with GCC; see the file COPYING3. If not see 19;; <http://www.gnu.org/licenses/>. 20 21 22 23;; Check that the operand is suitable for a call insn. 24;; Only registers and symbol refs are allowed. 25 26(define_predicate "rx_call_operand" 27 (ior (match_code "reg") 28 (and (match_test "!TARGET_JSR") 29 (match_code "symbol_ref"))) 30) 31 32;; For sibcall operations we can only use a symbolic address. 33 34(define_predicate "rx_symbolic_call_operand" 35 (match_code "symbol_ref") 36) 37 38;; Check that the operand is suitable for a shift insn 39;; Only small integers or a value in a register are permitted. 40 41(define_predicate "rx_shift_operand" 42 (ior (match_operand 0 "register_operand") 43 (and (match_code "const_int") 44 (match_test "IN_RANGE (INTVAL (op), 0, 31)"))) 45) 46 47(define_predicate "rx_constshift_operand" 48 (and (match_code "const_int") 49 (match_test "IN_RANGE (INTVAL (op), 0, 31)")) 50) 51 52(define_predicate "rx_restricted_mem_operand" 53 (and (match_code "mem") 54 (match_test "rx_is_restricted_memory_address (XEXP (op, 0), mode)")) 55) 56 57;; Check that the operand is suitable as the source operand 58;; for a logic or arithmeitc instruction. Registers, integers 59;; and a restricted subset of memory addresses are allowed. 60 61(define_predicate "rx_source_operand" 62 (ior (match_operand 0 "register_operand") 63 (match_operand 0 "immediate_operand") 64 (match_operand 0 "rx_restricted_mem_operand")) 65) 66 67;; Check that the operand is suitable as the source operand 68;; for a comparison instruction. This is the same as 69;; rx_source_operand except that SUBREGs are allowed but 70;; CONST_INTs are not. 71 72(define_predicate "rx_compare_operand" 73 (ior (match_operand 0 "register_operand") 74 (match_operand 0 "rx_restricted_mem_operand")) 75) 76 77;; Check that the operand is suitable as the source operand 78;; for a min/max instruction. This is the same as 79;; rx_source_operand except that CONST_INTs are allowed but 80;; REGs and SUBREGs are not. 81 82(define_predicate "rx_minmaxex_operand" 83 (ior (match_operand 0 "immediate_operand") 84 (match_operand 0 "rx_restricted_mem_operand")) 85) 86 87;; Return true if OP is a store multiple operation. This looks like: 88;; 89;; [(set (SP) (MINUS (SP) (INT))) 90;; (set (MEM (SP)) (REG)) 91;; (set (MEM (MINUS (SP) (INT))) (REG)) {optionally repeated} 92;; ] 93 94(define_special_predicate "rx_store_multiple_vector" 95 (match_code "parallel") 96{ 97 int count = XVECLEN (op, 0); 98 unsigned int src_regno; 99 rtx element; 100 int i; 101 102 /* Perform a quick check so we don't blow up below. */ 103 if (count <= 2) 104 return false; 105 106 /* Check that the first element of the vector is the stack adjust. */ 107 element = XVECEXP (op, 0, 0); 108 if ( ! SET_P (element) 109 || ! REG_P (SET_DEST (element)) 110 || REGNO (SET_DEST (element)) != SP_REG 111 || GET_CODE (SET_SRC (element)) != MINUS 112 || ! REG_P (XEXP (SET_SRC (element), 0)) 113 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG 114 || ! CONST_INT_P (XEXP (SET_SRC (element), 1))) 115 return false; 116 117 /* Check that the next element is the first push. */ 118 element = XVECEXP (op, 0, 1); 119 if ( ! SET_P (element) 120 || ! REG_P (SET_SRC (element)) 121 || GET_MODE (SET_SRC (element)) != SImode 122 || ! MEM_P (SET_DEST (element)) 123 || GET_MODE (SET_DEST (element)) != SImode 124 || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS 125 || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0)) 126 || REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG 127 || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1)) 128 || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1)) 129 != GET_MODE_SIZE (SImode)) 130 return false; 131 132 src_regno = REGNO (SET_SRC (element)); 133 134 /* Check that the remaining elements use SP-<disp> 135 addressing and decreasing register numbers. */ 136 for (i = 2; i < count; i++) 137 { 138 element = XVECEXP (op, 0, i); 139 140 if ( ! SET_P (element) 141 || ! REG_P (SET_SRC (element)) 142 || GET_MODE (SET_SRC (element)) != SImode 143 || REGNO (SET_SRC (element)) != src_regno - (i - 1) 144 || ! MEM_P (SET_DEST (element)) 145 || GET_MODE (SET_DEST (element)) != SImode 146 || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS 147 || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0)) 148 || REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG 149 || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1)) 150 || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1)) 151 != i * GET_MODE_SIZE (SImode)) 152 return false; 153 } 154 return true; 155}) 156 157;; Return true if OP is a load multiple operation. 158;; This looks like: 159;; [(set (SP) (PLUS (SP) (INT))) 160;; (set (REG) (MEM (SP))) 161;; (set (REG) (MEM (PLUS (SP) (INT)))) {optionally repeated} 162;; ] 163 164(define_special_predicate "rx_load_multiple_vector" 165 (match_code "parallel") 166{ 167 int count = XVECLEN (op, 0); 168 unsigned int dest_regno; 169 rtx element; 170 int i; 171 172 /* Perform a quick check so we don't blow up below. */ 173 if (count <= 2) 174 return false; 175 176 /* Check that the first element of the vector is the stack adjust. */ 177 element = XVECEXP (op, 0, 0); 178 if ( ! SET_P (element) 179 || ! REG_P (SET_DEST (element)) 180 || REGNO (SET_DEST (element)) != SP_REG 181 || GET_CODE (SET_SRC (element)) != PLUS 182 || ! REG_P (XEXP (SET_SRC (element), 0)) 183 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG 184 || ! CONST_INT_P (XEXP (SET_SRC (element), 1))) 185 return false; 186 187 /* Check that the next element is the first push. */ 188 element = XVECEXP (op, 0, 1); 189 if ( ! SET_P (element) 190 || ! REG_P (SET_DEST (element)) 191 || ! MEM_P (SET_SRC (element)) 192 || ! REG_P (XEXP (SET_SRC (element), 0)) 193 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG) 194 return false; 195 196 dest_regno = REGNO (SET_DEST (element)); 197 198 /* Check that the remaining elements use SP+<disp> 199 addressing and incremental register numbers. */ 200 for (i = 2; i < count; i++) 201 { 202 element = XVECEXP (op, 0, i); 203 204 if ( ! SET_P (element) 205 || ! REG_P (SET_DEST (element)) 206 || GET_MODE (SET_DEST (element)) != SImode 207 || REGNO (SET_DEST (element)) != dest_regno + (i - 1) 208 || ! MEM_P (SET_SRC (element)) 209 || GET_MODE (SET_SRC (element)) != SImode 210 || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS 211 || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0)) 212 || REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG 213 || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1)) 214 || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1)) 215 != (i - 1) * GET_MODE_SIZE (SImode)) 216 return false; 217 } 218 return true; 219}) 220 221;; Return true if OP is a pop-and-return load multiple operation. 222;; This looks like: 223;; [(set (SP) (PLUS (SP) (INT))) 224;; (set (REG) (MEM (SP))) 225;; (set (REG) (MEM (PLUS (SP) (INT)))) {optional and possibly repeated} 226;; (return) 227;; ] 228 229(define_special_predicate "rx_rtsd_vector" 230 (match_code "parallel") 231{ 232 int count = XVECLEN (op, 0); 233 unsigned int dest_regno; 234 rtx element; 235 int i; 236 237 /* Perform a quick check so we don't blow up below. */ 238 if (count <= 2) 239 return false; 240 241 /* Check that the first element of the vector is the stack adjust. */ 242 element = XVECEXP (op, 0, 0); 243 if ( ! SET_P (element) 244 || ! REG_P (SET_DEST (element)) 245 || REGNO (SET_DEST (element)) != SP_REG 246 || GET_CODE (SET_SRC (element)) != PLUS 247 || ! REG_P (XEXP (SET_SRC (element), 0)) 248 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG 249 || ! CONST_INT_P (XEXP (SET_SRC (element), 1))) 250 return false; 251 252 /* Check that the next element is the first push. */ 253 element = XVECEXP (op, 0, 1); 254 if ( ! SET_P (element) 255 || ! REG_P (SET_DEST (element)) 256 || ! MEM_P (SET_SRC (element)) 257 || ! REG_P (XEXP (SET_SRC (element), 0)) 258 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG) 259 return false; 260 261 dest_regno = REGNO (SET_DEST (element)); 262 263 /* Check that the remaining elements, if any, and except 264 for the last one, use SP+<disp> addressing and incremental 265 register numbers. */ 266 for (i = 2; i < count - 1; i++) 267 { 268 element = XVECEXP (op, 0, i); 269 270 if ( ! SET_P (element) 271 || ! REG_P (SET_DEST (element)) 272 || GET_MODE (SET_DEST (element)) != SImode 273 || REGNO (SET_DEST (element)) != dest_regno + (i - 1) 274 || ! MEM_P (SET_SRC (element)) 275 || GET_MODE (SET_SRC (element)) != SImode 276 || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS 277 || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0)) 278 || REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG 279 || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1)) 280 || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1)) 281 != (i - 1) * GET_MODE_SIZE (SImode)) 282 return false; 283 } 284 285 /* The last element must be a RETURN. */ 286 element = XVECEXP (op, 0, count - 1); 287 return GET_CODE (element) == RETURN; 288}) 289 290(define_predicate "label_ref_operand" 291 (match_code "label_ref") 292) 293 294(define_predicate "rx_z_comparison_operator" 295 (match_code "eq,ne") 296) 297 298(define_predicate "rx_zs_comparison_operator" 299 (match_code "eq,ne,lt,ge") 300) 301 302;; GT and LE omitted due to operand swap required. 303(define_predicate "rx_fp_comparison_operator" 304 (match_code "eq,ne,lt,ge,ordered,unordered") 305) 306 307(define_predicate "rshift_operator" 308 (match_code "ashiftrt,lshiftrt") 309) 310