1;; Predicates for C-SKY. 2;; Copyright (C) 2018-2021 Free Software Foundation, Inc. 3;; Contributed by C-SKY Microsystems and Mentor Graphics. 4;; 5;; This file is part of GCC. 6;; 7;; GCC is free software; you can redistribute it and/or modify it 8;; 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, but 13;; WITHOUT ANY WARRANTY; without even the implied warranty of 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15;; 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;; Return 1 if OP is a load multiple operation. 22 23(define_predicate "csky_load_multiple_operation" 24 (match_code "parallel") 25{ 26 int count = XVECLEN (op, 0); 27 int dest_regno; 28 rtx src_addr; 29 int i; 30 31 /* Perform a quick check so we don't blow up below. */ 32 if (count <= 1 33 || GET_CODE (XVECEXP (op, 0, 0)) != SET 34 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG 35 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM 36 || GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0)) != REG 37 || XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0) != stack_pointer_rtx) 38 return 0; 39 40 dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0))); 41 src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0); 42 43 for (i = 1; i < count; i++) 44 { 45 rtx elt = XVECEXP (op, 0, i); 46 47 if (GET_CODE (elt) != SET 48 || GET_CODE (SET_DEST (elt)) != REG 49 || GET_MODE (SET_DEST (elt)) != SImode 50 || REGNO (SET_DEST (elt)) != (unsigned) (dest_regno + i) 51 || GET_CODE (SET_SRC (elt)) != MEM 52 || GET_MODE (SET_SRC (elt)) != SImode 53 || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS 54 || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr) 55 || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT 56 || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4) 57 return 0; 58 } 59 return 1; 60}) 61 62;; Similar, for store multiple. 63 64(define_predicate "csky_store_multiple_operation" 65 (match_code "parallel") 66{ 67 int count = XVECLEN (op, 0); 68 int src_regno; 69 rtx dest_addr; 70 int i; 71 72 /* Perform a quick check so we don't blow up below. */ 73 if (count <= 1 74 || GET_CODE (XVECEXP (op, 0, 0)) != SET 75 || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM 76 || GET_CODE (XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0)) != REG 77 || XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0) != stack_pointer_rtx 78 || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG) 79 return 0; 80 81 src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0))); 82 dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0); 83 84 for (i = 1; i < count; i++) 85 { 86 rtx elt = XVECEXP (op, 0, i); 87 88 if (GET_CODE (elt) != SET 89 || GET_CODE (SET_SRC (elt)) != REG 90 || GET_MODE (SET_SRC (elt)) != SImode 91 || REGNO (SET_SRC (elt)) != (unsigned) (src_regno + i) 92 || GET_CODE (SET_DEST (elt)) != MEM 93 || GET_MODE (SET_DEST (elt)) != SImode 94 || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS 95 || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr) 96 || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT 97 || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4) 98 return 0; 99 } 100 return 1; 101}) 102 103 104(define_predicate "csky_arith_K_operand" 105 (match_code "reg,subreg,const_int") 106 { 107 if (register_operand (op, mode)) 108 return 1; 109 if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_K (INTVAL (op))) 110 return 1; 111 return 0; 112 }) 113 114(define_predicate "csky_literal_K_operand" 115 (match_code "const_int") 116 { 117 if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_K (INTVAL (op))) 118 return 1; 119 return 0; 120 }) 121 122(define_predicate "csky_literal_I_operand" 123 (match_code "const_int") 124 { 125 if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_I (INTVAL (op))) 126 return 1; 127 return 0; 128 }) 129 130(define_predicate "csky_literal_J_operand" 131 (match_code "const_int") 132 { 133 if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_J (INTVAL (op))) 134 return 1; 135 return 0; 136 }) 137 138(define_predicate "csky_literal_Uk_operand" 139 (match_code "const_int") 140 { 141 if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_Uk (INTVAL (op))) 142 return 1; 143 return 0; 144 }) 145 146;; Nonzero if OP is a register or constant value of 1 147 148(define_predicate "csky_arith_int1_operand" 149 (match_code "reg,subreg,const_int") 150 { 151 if (register_operand (op, mode)) 152 return 1; 153 if (op == const1_rtx) 154 return 1; 155 return 0; 156 }) 157 158 159;; Nonzero if OP is legal address for function call 160 161(define_predicate "csky_call_address_operand" 162 (match_code "reg,subreg,symbol_ref") 163 { 164 if (!flag_pic && (GET_CODE (op) == SYMBOL_REF)) 165 return 1; 166 if (register_operand (op, mode)) 167 return 1; 168 return 0; 169 }) 170 171;; Nonzero if OP is a valid source operand for a compare operation. 172 173(define_predicate "csky_compare_operand" 174 (match_code "const_int,reg,subreg") 175 { 176 if (register_operand (op, mode)) 177 return 1; 178 if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0) 179 return 1; 180 return 0; 181 }) 182 183(define_predicate "csky_literal_K_Uh_operand" 184 (match_code "const_int") 185 { 186 if (CONST_INT_P (op) 187 && (CSKY_CONST_OK_FOR_K (INTVAL (op)) 188 || CSKY_CONST_OK_FOR_Uh (INTVAL (op)))) 189 return 1; 190 return 0; 191 }) 192 193;; True if OP is a mem with an reg + optional displacement address. 194 195(define_predicate "csky_simple_mem_operand" 196 (and (match_operand 0 "memory_operand") 197 (match_test "csky_simple_addr_operand_p (XEXP (op, 0))"))) 198 199(define_predicate "csky_arith_any_imm_operand" 200 (match_code "const_int,reg,subreg") 201 { 202 if (register_operand (op, mode)) 203 return 1; 204 if (CONST_INT_P (op)) 205 return 1; 206 return 0; 207 }) 208 209(define_predicate "csky_arith_O_operand" 210 (match_code "reg,subreg,const_int") 211 { 212 if (register_operand (op, mode)) 213 return 1; 214 if (CONST_INT_P (op) && CSKY_CONST_OK_FOR_O (INTVAL (op))) 215 return 1; 216 return 0; 217 }) 218 219(define_predicate "csky_unspec_operand" 220 (match_code "unspec") 221 { 222 if (op == NULL || GET_CODE(op) != UNSPEC) 223 return 0; 224 return 1; 225 } 226) 227 228(define_predicate "csky_const_float1_operand" 229 (and (match_code "const_double") 230 (match_test "(op == CONST1_RTX (mode))"))) 231 232(define_predicate "csky_arith_float1_operand" 233 (ior (match_operand 0 "register_operand") 234 (match_operand 0 "csky_const_float1_operand"))) 235 236(define_predicate "csky_const_float0_operand" 237 (and (match_code "const_double") 238 (match_test "(op == CONST0_RTX (mode))"))) 239 240(define_predicate "csky_compare_operand_float" 241 (ior (match_operand 0 "register_operand") 242 (match_operand 0 "csky_const_float0_operand"))) 243 244(define_special_predicate "registers_push" 245 (match_code "parallel") 246{ 247 if ((GET_CODE (XVECEXP (op, 0, 0)) != SET) 248 || (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC) 249 || (XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != UNSPEC_PUSHPOP_MULT)) 250 return false; 251 return true; 252}) 253 254(define_special_predicate "registers_pop" 255 (match_code "parallel") 256{ 257 if ((GET_CODE (XVECEXP (op, 0, 1)) != SET) 258 || (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) != UNSPEC) 259 || (XINT (SET_SRC (XVECEXP (op, 0, 1)), 1) != UNSPEC_PUSHPOP_MULT)) 260 return false; 261 return true; 262}) 263 264(define_predicate "push_memory_operand" 265 (match_code "mem") 266{ 267 rtx x = XEXP (op, 0); 268 if (GET_CODE (x) != PRE_MODIFY) 269 return false; 270 if (XEXP (x, 0) != stack_pointer_rtx) 271 return false; 272 x = XEXP (x, 1); 273 if (GET_CODE (x) != PLUS) 274 return false; 275 if (XEXP (x, 0) != stack_pointer_rtx) 276 return false; 277 return CONST_INT_P (XEXP (x, 1)); 278}) 279 280(define_predicate "pop_memory_operand" 281 (match_code "mem") 282{ 283 rtx x = XEXP (op, 0); 284 if (GET_CODE (x) != POST_MODIFY) 285 return false; 286 if (XEXP (x, 0) != stack_pointer_rtx) 287 return false; 288 x = XEXP (x, 1); 289 if (GET_CODE (x) != PLUS) 290 return false; 291 if (XEXP (x, 0) != stack_pointer_rtx) 292 return false; 293 return CONST_INT_P (XEXP (x, 1)); 294}) 295 296(define_special_predicate "csky_float_comparison_operator" 297 (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu, 298 unordered,ordered")) 299