]>
Commit | Line | Data |
---|---|---|
bcead286 | 1 | /* Predicates for TI C6X |
7adcbafe | 2 | Copyright (C) 2010-2022 Free Software Foundation, Inc. |
bcead286 BS |
3 | Contributed by Andrew Jenner <andrew@codesourcery.com> |
4 | Contributed by Bernd Schmidt <bernds@codesourcery.com> | |
5 | ||
6 | This file is part of GCC. | |
7 | ||
8 | GCC is free software; you can redistribute it and/or modify it | |
9 | under the terms of the GNU General Public License as published | |
10 | by the Free Software Foundation; either version 3, or (at your | |
11 | option) any later version. | |
12 | ||
13 | GCC is distributed in the hope that it will be useful, but WITHOUT | |
14 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
15 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
16 | License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with GCC; see the file COPYING3. If not see | |
20 | <http://www.gnu.org/licenses/>. */ | |
21 | ||
22 | (define_predicate "reg_or_const_int_operand" | |
23 | (ior (match_operand 0 "register_operand") | |
24 | (match_operand 0 "const_int_operand"))) | |
25 | ||
26 | (define_predicate "const_vector_operand" | |
27 | (match_code "const_vector")) | |
28 | ||
29 | (define_predicate "scst5_operand" | |
30 | (and (match_operand 0 "const_int_operand") | |
31 | (match_test "satisfies_constraint_Is5 (op)"))) | |
32 | ||
33 | (define_predicate "reg_or_ucst4_operand" | |
34 | (ior (match_operand 0 "register_operand") | |
35 | (and (match_operand 0 "const_int_operand") | |
36 | (match_test "satisfies_constraint_Iu4 (op)")))) | |
37 | ||
38 | (define_predicate "reg_or_scst5_operand" | |
39 | (ior (match_operand 0 "register_operand") | |
40 | (match_operand 0 "scst5_operand"))) | |
41 | ||
42 | (define_predicate "reg_or_ucst5_operand" | |
43 | (ior (match_operand 0 "register_operand") | |
44 | (and (match_operand 0 "const_int_operand") | |
45 | (match_test "satisfies_constraint_Iu5 (op)")))) | |
46 | ||
47 | (define_predicate "addsi_operand" | |
48 | (ior (match_operand 0 "register_operand") | |
49 | (and (match_operand 0 "const_int_operand") | |
50 | (match_test "satisfies_constraint_IsB (op)")))) | |
51 | ||
52 | (define_predicate "andsi_operand" | |
53 | (ior (match_operand 0 "reg_or_scst5_operand") | |
54 | (and (match_operand 0 "const_int_operand") | |
55 | (match_test "satisfies_constraint_Jc (op)")))) | |
56 | ||
57 | (define_predicate "iorsi_operand" | |
58 | (ior (match_operand 0 "reg_or_scst5_operand") | |
59 | (and (match_operand 0 "const_int_operand") | |
60 | (match_test "satisfies_constraint_Js (op)")))) | |
61 | ||
62 | (define_predicate "insv_operand" | |
63 | (and (match_operand 0 "const_int_operand") | |
64 | (match_test "INTVAL (op) == 0 || INTVAL (op) == -1"))) | |
65 | ||
66 | (define_predicate "c6x_jump_operand" | |
67 | (match_code "label_ref,symbol_ref,reg")) | |
68 | ||
69 | (define_predicate "c6x_call_operand" | |
70 | (ior (match_code "symbol_ref,reg") | |
71 | (and (match_code "subreg") | |
72 | (match_test "GET_CODE (XEXP (op, 0)) == REG"))) | |
73 | { | |
74 | /* The linker transforms jumps to undefined weak symbols in a way that | |
75 | is incompatible with our code generation. */ | |
76 | return (GET_CODE (op) != SYMBOL_REF | |
77 | || (!SYMBOL_REF_WEAK (op) | |
78 | && !c6x_long_call_p (op))); | |
79 | }) | |
80 | ||
81 | ;; Returns 1 if OP is a symbolic operand, i.e. a symbol_ref or a label_ref, | |
82 | ;; possibly with an offset. | |
83 | (define_predicate "symbolic_operand" | |
84 | (ior (match_code "symbol_ref,label_ref") | |
85 | (and (match_code "const") | |
86 | (match_test "GET_CODE (XEXP (op,0)) == PLUS | |
87 | && (GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF | |
88 | || GET_CODE (XEXP (XEXP (op, 0), 0)) == LABEL_REF) | |
89 | && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT")))) | |
90 | ||
91 | (define_predicate "const_int_or_symbolic_operand" | |
92 | (ior (match_operand 0 "symbolic_operand") | |
93 | (match_operand 0 "const_int_operand"))) | |
94 | ||
95 | ;; Return nonzero iff OP is one of the integer constants 2, 4 or 8. | |
96 | (define_predicate "adda_scale_operand" | |
97 | (and (match_code "const_int") | |
98 | (match_test "INTVAL (op) == 2 || INTVAL (op) == 4 | |
99 | || ((TARGET_INSNS_64 || TARGET_INSNS_67) | |
100 | && INTVAL (op) == 8)"))) | |
101 | ||
102 | ;; Return nonzero iff OP is one of the integer constants 2 or 4. | |
103 | (define_predicate "suba_scale_operand" | |
104 | (and (match_code "const_int") | |
105 | (match_test "INTVAL (op) == 2 || INTVAL (op) == 4"))) | |
106 | ||
107 | ;; True if this operator is valid for predication. | |
108 | (define_predicate "predicate_operator" | |
109 | (match_code "eq,ne")) | |
110 | ||
111 | (define_predicate "c6x_comparison_operator" | |
112 | (match_code "eq,ltu,gtu,lt,gt")) | |
113 | ||
114 | (define_predicate "non_c6x_comparison_operator" | |
115 | (match_code "ne,leu,geu,le,ge")) | |
116 | ||
117 | ;; FP Comparisons handled by c6x_expand_compare. | |
118 | (define_predicate "c6x_fp_comparison_operator" | |
119 | (ior (match_code "eq,lt,gt,le,ge") | |
120 | (and (match_test "TARGET_FP") | |
121 | (match_code "ltgt,uneq,unlt,ungt,unle,unge,ordered,unordered")))) | |
122 | ||
123 | (define_predicate "c6x_any_comparison_operand" | |
124 | (match_code "eq,lt,gt,le,ge,ltu,gtu") | |
125 | { | |
126 | rtx op0 = XEXP (op, 0); | |
127 | rtx op1 = XEXP (op, 1); | |
128 | if (ltugtu_operator (op, SImode) | |
129 | && register_operand (op0, SImode) | |
130 | && ((TARGET_INSNS_64 && reg_or_ucst5_operand (op1, SImode)) | |
131 | || (!TARGET_INSNS_64 && reg_or_ucst4_operand (op1, SImode)))) | |
132 | return true; | |
133 | if (eqltgt_operator (op, SImode) | |
134 | && register_operand (op0, SImode) | |
135 | && reg_or_scst5_operand (op1, SImode)) | |
136 | return true; | |
137 | if (!TARGET_FP) | |
138 | return false; | |
139 | if (!eqltgt_operator (op, SFmode) && !eqltgt_operator (op, DFmode)) | |
140 | return false; | |
141 | if (register_operand (op0, GET_MODE (op)) | |
142 | && register_operand (op1, GET_MODE (op))) | |
143 | return true; | |
144 | return false; | |
145 | }) | |
146 | ||
147 | (define_predicate "ltugtu_operator" | |
148 | (match_code "ltu,gtu")) | |
149 | ||
150 | (define_predicate "eqltgt_operator" | |
151 | (match_code "eq,lt,gt")) | |
152 | ||
153 | (define_predicate "eqne_operator" | |
154 | (match_code "eq,ne")) | |
155 | ||
156 | (define_predicate "predicate_register" | |
157 | (and (match_code "reg") | |
158 | (ior (match_test "REGNO_REG_CLASS (REGNO (op)) == PREDICATE_A_REGS") | |
159 | (match_test "REGNO_REG_CLASS (REGNO (op)) == PREDICATE_B_REGS")))) | |
160 | ||
161 | ;; Allow const_ints for things like the real_mult patterns. | |
162 | (define_predicate "a_register" | |
163 | (ior (and (match_code "reg") | |
164 | (match_test "A_REGNO_P (REGNO (op))")) | |
165 | (and (match_code "const_int") | |
166 | (match_test "A_REGNO_P (INTVAL (op))")))) | |
167 | ||
168 | (define_predicate "b_register" | |
169 | (ior (and (match_code "reg") | |
170 | (match_test "B_REGNO_P (REGNO (op))")) | |
171 | (and (match_code "const_int") | |
172 | (match_test "B_REGNO_P (INTVAL (op))")))) | |
173 | ||
174 | (define_predicate "pic_register_operand" | |
175 | (and (match_code "reg") | |
176 | (match_test "op == pic_offset_table_rtx"))) | |
177 | ||
178 | ;; True if OP refers to a symbol in the sdata section. | |
179 | (define_predicate "sdata_symbolic_operand" | |
180 | (match_code "symbol_ref,const") | |
181 | { | |
182 | HOST_WIDE_INT offset = 0, size = 0; | |
183 | tree t; | |
184 | ||
185 | switch (GET_CODE (op)) | |
186 | { | |
187 | case CONST: | |
188 | op = XEXP (op, 0); | |
189 | if (GET_CODE (op) != PLUS | |
190 | || GET_CODE (XEXP (op, 0)) != SYMBOL_REF | |
191 | || GET_CODE (XEXP (op, 1)) != CONST_INT) | |
192 | return false; | |
193 | offset = INTVAL (XEXP (op, 1)); | |
194 | op = XEXP (op, 0); | |
195 | /* FALLTHRU */ | |
196 | ||
197 | case SYMBOL_REF: | |
198 | /* For shared libraries, only allow symbols we know are local. | |
199 | For executables, the linker knows to create copy relocs if | |
200 | necessary so we can use DP-relative addressing for all small | |
201 | objects. */ | |
202 | if ((c6x_initial_flag_pic && !SYMBOL_REF_LOCAL_P (op)) | |
203 | || !SYMBOL_REF_SMALL_P (op)) | |
204 | return false; | |
205 | ||
206 | /* Note that in addition to DECLs, we can get various forms | |
207 | of constants here. */ | |
208 | t = SYMBOL_REF_DECL (op); | |
209 | if (DECL_P (t)) | |
210 | t = DECL_SIZE_UNIT (t); | |
211 | else | |
212 | t = TYPE_SIZE_UNIT (TREE_TYPE (t)); | |
9541ffee | 213 | if (t && tree_fits_shwi_p (t)) |
bcead286 | 214 | { |
9439e9a1 | 215 | size = tree_to_shwi (t); |
bcead286 BS |
216 | if (size < 0) |
217 | size = 0; | |
218 | } | |
219 | ||
220 | /* Don't allow addressing outside the object. */ | |
221 | return (offset >= 0 && offset <= size); | |
222 | ||
223 | default: | |
224 | gcc_unreachable (); | |
225 | } | |
226 | }) |