Home | History | Annotate | Line # | Download | only in csky
      1 ;; Predicates for C-SKY.
      2 ;; Copyright (C) 2018-2024 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,unordered,ordered"))
    298