1;; Predicate definitions for Renesas RX. 2;; Copyright (C) 2008, 2009, 2011 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;; Return true if OP is a store multiple operation. This looks like: 76;; 77;; [(set (SP) (MINUS (SP) (INT))) 78;; (set (MEM (SP)) (REG)) 79;; (set (MEM (MINUS (SP) (INT))) (REG)) {optionally repeated} 80;; ] 81 82(define_special_predicate "rx_store_multiple_vector" 83 (match_code "parallel") 84{ 85 int count = XVECLEN (op, 0); 86 unsigned int src_regno; 87 rtx element; 88 int i; 89 90 /* Perform a quick check so we don't blow up below. */ 91 if (count <= 2) 92 return false; 93 94 /* Check that the first element of the vector is the stack adjust. */ 95 element = XVECEXP (op, 0, 0); 96 if ( ! SET_P (element) 97 || ! REG_P (SET_DEST (element)) 98 || REGNO (SET_DEST (element)) != SP_REG 99 || GET_CODE (SET_SRC (element)) != MINUS 100 || ! REG_P (XEXP (SET_SRC (element), 0)) 101 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG 102 || ! CONST_INT_P (XEXP (SET_SRC (element), 1))) 103 return false; 104 105 /* Check that the next element is the first push. */ 106 element = XVECEXP (op, 0, 1); 107 if ( ! SET_P (element) 108 || ! REG_P (SET_SRC (element)) 109 || GET_MODE (SET_SRC (element)) != SImode 110 || ! MEM_P (SET_DEST (element)) 111 || GET_MODE (SET_DEST (element)) != SImode 112 || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS 113 || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0)) 114 || REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG 115 || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1)) 116 || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1)) 117 != GET_MODE_SIZE (SImode)) 118 return false; 119 120 src_regno = REGNO (SET_SRC (element)); 121 122 /* Check that the remaining elements use SP-<disp> 123 addressing and decreasing register numbers. */ 124 for (i = 2; i < count; i++) 125 { 126 element = XVECEXP (op, 0, i); 127 128 if ( ! SET_P (element) 129 || ! REG_P (SET_SRC (element)) 130 || GET_MODE (SET_SRC (element)) != SImode 131 || REGNO (SET_SRC (element)) != src_regno - (i - 1) 132 || ! MEM_P (SET_DEST (element)) 133 || GET_MODE (SET_DEST (element)) != SImode 134 || GET_CODE (XEXP (SET_DEST (element), 0)) != MINUS 135 || ! REG_P (XEXP (XEXP (SET_DEST (element), 0), 0)) 136 || REGNO (XEXP (XEXP (SET_DEST (element), 0), 0)) != SP_REG 137 || ! CONST_INT_P (XEXP (XEXP (SET_DEST (element), 0), 1)) 138 || INTVAL (XEXP (XEXP (SET_DEST (element), 0), 1)) 139 != i * GET_MODE_SIZE (SImode)) 140 return false; 141 } 142 return true; 143}) 144 145;; Return true if OP is a load multiple operation. 146;; This looks like: 147;; [(set (SP) (PLUS (SP) (INT))) 148;; (set (REG) (MEM (SP))) 149;; (set (REG) (MEM (PLUS (SP) (INT)))) {optionally repeated} 150;; ] 151 152(define_special_predicate "rx_load_multiple_vector" 153 (match_code "parallel") 154{ 155 int count = XVECLEN (op, 0); 156 unsigned int dest_regno; 157 rtx element; 158 int i; 159 160 /* Perform a quick check so we don't blow up below. */ 161 if (count <= 2) 162 return false; 163 164 /* Check that the first element of the vector is the stack adjust. */ 165 element = XVECEXP (op, 0, 0); 166 if ( ! SET_P (element) 167 || ! REG_P (SET_DEST (element)) 168 || REGNO (SET_DEST (element)) != SP_REG 169 || GET_CODE (SET_SRC (element)) != PLUS 170 || ! REG_P (XEXP (SET_SRC (element), 0)) 171 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG 172 || ! CONST_INT_P (XEXP (SET_SRC (element), 1))) 173 return false; 174 175 /* Check that the next element is the first push. */ 176 element = XVECEXP (op, 0, 1); 177 if ( ! SET_P (element) 178 || ! REG_P (SET_DEST (element)) 179 || ! MEM_P (SET_SRC (element)) 180 || ! REG_P (XEXP (SET_SRC (element), 0)) 181 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG) 182 return false; 183 184 dest_regno = REGNO (SET_DEST (element)); 185 186 /* Check that the remaining elements use SP+<disp> 187 addressing and incremental register numbers. */ 188 for (i = 2; i < count; i++) 189 { 190 element = XVECEXP (op, 0, i); 191 192 if ( ! SET_P (element) 193 || ! REG_P (SET_DEST (element)) 194 || GET_MODE (SET_DEST (element)) != SImode 195 || REGNO (SET_DEST (element)) != dest_regno + (i - 1) 196 || ! MEM_P (SET_SRC (element)) 197 || GET_MODE (SET_SRC (element)) != SImode 198 || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS 199 || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0)) 200 || REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG 201 || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1)) 202 || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1)) 203 != (i - 1) * GET_MODE_SIZE (SImode)) 204 return false; 205 } 206 return true; 207}) 208 209;; Return true if OP is a pop-and-return load multiple operation. 210;; This looks like: 211;; [(set (SP) (PLUS (SP) (INT))) 212;; (set (REG) (MEM (SP))) 213;; (set (REG) (MEM (PLUS (SP) (INT)))) {optional and possibly repeated} 214;; (return) 215;; ] 216 217(define_special_predicate "rx_rtsd_vector" 218 (match_code "parallel") 219{ 220 int count = XVECLEN (op, 0); 221 unsigned int dest_regno; 222 rtx element; 223 int i; 224 225 /* Perform a quick check so we don't blow up below. */ 226 if (count <= 2) 227 return false; 228 229 /* Check that the first element of the vector is the stack adjust. */ 230 element = XVECEXP (op, 0, 0); 231 if ( ! SET_P (element) 232 || ! REG_P (SET_DEST (element)) 233 || REGNO (SET_DEST (element)) != SP_REG 234 || GET_CODE (SET_SRC (element)) != PLUS 235 || ! REG_P (XEXP (SET_SRC (element), 0)) 236 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG 237 || ! CONST_INT_P (XEXP (SET_SRC (element), 1))) 238 return false; 239 240 /* Check that the next element is the first push. */ 241 element = XVECEXP (op, 0, 1); 242 if ( ! SET_P (element) 243 || ! REG_P (SET_DEST (element)) 244 || ! MEM_P (SET_SRC (element)) 245 || ! REG_P (XEXP (SET_SRC (element), 0)) 246 || REGNO (XEXP (SET_SRC (element), 0)) != SP_REG) 247 return false; 248 249 dest_regno = REGNO (SET_DEST (element)); 250 251 /* Check that the remaining elements, if any, and except 252 for the last one, use SP+<disp> addressing and incremental 253 register numbers. */ 254 for (i = 2; i < count - 1; i++) 255 { 256 element = XVECEXP (op, 0, i); 257 258 if ( ! SET_P (element) 259 || ! REG_P (SET_DEST (element)) 260 || GET_MODE (SET_DEST (element)) != SImode 261 || REGNO (SET_DEST (element)) != dest_regno + (i - 1) 262 || ! MEM_P (SET_SRC (element)) 263 || GET_MODE (SET_SRC (element)) != SImode 264 || GET_CODE (XEXP (SET_SRC (element), 0)) != PLUS 265 || ! REG_P (XEXP (XEXP (SET_SRC (element), 0), 0)) 266 || REGNO (XEXP (XEXP (SET_SRC (element), 0), 0)) != SP_REG 267 || ! CONST_INT_P (XEXP (XEXP (SET_SRC (element), 0), 1)) 268 || INTVAL (XEXP (XEXP (SET_SRC (element), 0), 1)) 269 != (i - 1) * GET_MODE_SIZE (SImode)) 270 return false; 271 } 272 273 /* The last element must be a RETURN. */ 274 element = XVECEXP (op, 0, count - 1); 275 return GET_CODE (element) == RETURN; 276}) 277 278(define_predicate "label_ref_operand" 279 (match_code "label_ref") 280) 281 282(define_predicate "rx_z_comparison_operator" 283 (match_code "eq,ne") 284) 285 286(define_predicate "rx_zs_comparison_operator" 287 (match_code "eq,ne") 288) 289 290;; GT and LE omitted due to operand swap required. 291(define_predicate "rx_fp_comparison_operator" 292 (match_code "eq,ne,lt,ge,ordered,unordered") 293) 294 295(define_predicate "rshift_operator" 296 (match_code "ashiftrt,lshiftrt") 297) 298