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