1*e4b17023SJohn Marino /* Support routines for the various generation passes.
2*e4b17023SJohn Marino Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
3*e4b17023SJohn Marino 2010, Free Software Foundation, Inc.
4*e4b17023SJohn Marino
5*e4b17023SJohn Marino This file is part of GCC.
6*e4b17023SJohn Marino
7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it
8*e4b17023SJohn Marino under the terms of the GNU General Public License as published by
9*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
10*e4b17023SJohn Marino any later version.
11*e4b17023SJohn Marino
12*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT
13*e4b17023SJohn Marino ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14*e4b17023SJohn Marino or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15*e4b17023SJohn Marino License for more details.
16*e4b17023SJohn Marino
17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
19*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
20*e4b17023SJohn Marino
21*e4b17023SJohn Marino #include "bconfig.h"
22*e4b17023SJohn Marino #include "system.h"
23*e4b17023SJohn Marino #include "coretypes.h"
24*e4b17023SJohn Marino #include "tm.h"
25*e4b17023SJohn Marino #include "rtl.h"
26*e4b17023SJohn Marino #include "obstack.h"
27*e4b17023SJohn Marino #include "errors.h"
28*e4b17023SJohn Marino #include "hashtab.h"
29*e4b17023SJohn Marino #include "read-md.h"
30*e4b17023SJohn Marino #include "gensupport.h"
31*e4b17023SJohn Marino
32*e4b17023SJohn Marino
33*e4b17023SJohn Marino /* In case some macros used by files we include need it, define this here. */
34*e4b17023SJohn Marino int target_flags;
35*e4b17023SJohn Marino
36*e4b17023SJohn Marino int insn_elision = 1;
37*e4b17023SJohn Marino
38*e4b17023SJohn Marino static struct obstack obstack;
39*e4b17023SJohn Marino struct obstack *rtl_obstack = &obstack;
40*e4b17023SJohn Marino
41*e4b17023SJohn Marino static int sequence_num;
42*e4b17023SJohn Marino
43*e4b17023SJohn Marino static int predicable_default;
44*e4b17023SJohn Marino static const char *predicable_true;
45*e4b17023SJohn Marino static const char *predicable_false;
46*e4b17023SJohn Marino
47*e4b17023SJohn Marino static htab_t condition_table;
48*e4b17023SJohn Marino
49*e4b17023SJohn Marino /* We initially queue all patterns, process the define_insn and
50*e4b17023SJohn Marino define_cond_exec patterns, then return them one at a time. */
51*e4b17023SJohn Marino
52*e4b17023SJohn Marino struct queue_elem
53*e4b17023SJohn Marino {
54*e4b17023SJohn Marino rtx data;
55*e4b17023SJohn Marino const char *filename;
56*e4b17023SJohn Marino int lineno;
57*e4b17023SJohn Marino struct queue_elem *next;
58*e4b17023SJohn Marino /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT, SPLIT
59*e4b17023SJohn Marino points to the generated DEFINE_SPLIT. */
60*e4b17023SJohn Marino struct queue_elem *split;
61*e4b17023SJohn Marino };
62*e4b17023SJohn Marino
63*e4b17023SJohn Marino #define MNEMONIC_ATTR_NAME "mnemonic"
64*e4b17023SJohn Marino #define MNEMONIC_HTAB_SIZE 1024
65*e4b17023SJohn Marino
66*e4b17023SJohn Marino static struct queue_elem *define_attr_queue;
67*e4b17023SJohn Marino static struct queue_elem **define_attr_tail = &define_attr_queue;
68*e4b17023SJohn Marino static struct queue_elem *define_pred_queue;
69*e4b17023SJohn Marino static struct queue_elem **define_pred_tail = &define_pred_queue;
70*e4b17023SJohn Marino static struct queue_elem *define_insn_queue;
71*e4b17023SJohn Marino static struct queue_elem **define_insn_tail = &define_insn_queue;
72*e4b17023SJohn Marino static struct queue_elem *define_cond_exec_queue;
73*e4b17023SJohn Marino static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
74*e4b17023SJohn Marino static struct queue_elem *other_queue;
75*e4b17023SJohn Marino static struct queue_elem **other_tail = &other_queue;
76*e4b17023SJohn Marino
77*e4b17023SJohn Marino static struct queue_elem *queue_pattern (rtx, struct queue_elem ***,
78*e4b17023SJohn Marino const char *, int);
79*e4b17023SJohn Marino
80*e4b17023SJohn Marino static void remove_constraints (rtx);
81*e4b17023SJohn Marino static void process_rtx (rtx, int);
82*e4b17023SJohn Marino
83*e4b17023SJohn Marino static int is_predicable (struct queue_elem *);
84*e4b17023SJohn Marino static void identify_predicable_attribute (void);
85*e4b17023SJohn Marino static int n_alternatives (const char *);
86*e4b17023SJohn Marino static void collect_insn_data (rtx, int *, int *);
87*e4b17023SJohn Marino static rtx alter_predicate_for_insn (rtx, int, int, int);
88*e4b17023SJohn Marino static const char *alter_test_for_insn (struct queue_elem *,
89*e4b17023SJohn Marino struct queue_elem *);
90*e4b17023SJohn Marino static char *shift_output_template (char *, const char *, int);
91*e4b17023SJohn Marino static const char *alter_output_for_insn (struct queue_elem *,
92*e4b17023SJohn Marino struct queue_elem *,
93*e4b17023SJohn Marino int, int);
94*e4b17023SJohn Marino static void process_one_cond_exec (struct queue_elem *);
95*e4b17023SJohn Marino static void process_define_cond_exec (void);
96*e4b17023SJohn Marino static void init_predicate_table (void);
97*e4b17023SJohn Marino static void record_insn_name (int, const char *);
98*e4b17023SJohn Marino
99*e4b17023SJohn Marino /* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
100*e4b17023SJohn Marino the gensupport programs. */
101*e4b17023SJohn Marino
102*e4b17023SJohn Marino rtx
gen_rtx_CONST_INT(enum machine_mode ARG_UNUSED (mode),HOST_WIDE_INT arg)103*e4b17023SJohn Marino gen_rtx_CONST_INT (enum machine_mode ARG_UNUSED (mode),
104*e4b17023SJohn Marino HOST_WIDE_INT arg)
105*e4b17023SJohn Marino {
106*e4b17023SJohn Marino rtx rt = rtx_alloc (CONST_INT);
107*e4b17023SJohn Marino
108*e4b17023SJohn Marino XWINT (rt, 0) = arg;
109*e4b17023SJohn Marino return rt;
110*e4b17023SJohn Marino }
111*e4b17023SJohn Marino
112*e4b17023SJohn Marino /* Predicate handling.
113*e4b17023SJohn Marino
114*e4b17023SJohn Marino We construct from the machine description a table mapping each
115*e4b17023SJohn Marino predicate to a list of the rtl codes it can possibly match. The
116*e4b17023SJohn Marino function 'maybe_both_true' uses it to deduce that there are no
117*e4b17023SJohn Marino expressions that can be matches by certain pairs of tree nodes.
118*e4b17023SJohn Marino Also, if a predicate can match only one code, we can hardwire that
119*e4b17023SJohn Marino code into the node testing the predicate.
120*e4b17023SJohn Marino
121*e4b17023SJohn Marino Some predicates are flagged as special. validate_pattern will not
122*e4b17023SJohn Marino warn about modeless match_operand expressions if they have a
123*e4b17023SJohn Marino special predicate. Predicates that allow only constants are also
124*e4b17023SJohn Marino treated as special, for this purpose.
125*e4b17023SJohn Marino
126*e4b17023SJohn Marino validate_pattern will warn about predicates that allow non-lvalues
127*e4b17023SJohn Marino when they appear in destination operands.
128*e4b17023SJohn Marino
129*e4b17023SJohn Marino Calculating the set of rtx codes that can possibly be accepted by a
130*e4b17023SJohn Marino predicate expression EXP requires a three-state logic: any given
131*e4b17023SJohn Marino subexpression may definitively accept a code C (Y), definitively
132*e4b17023SJohn Marino reject a code C (N), or may have an indeterminate effect (I). N
133*e4b17023SJohn Marino and I is N; Y or I is Y; Y and I, N or I are both I. Here are full
134*e4b17023SJohn Marino truth tables.
135*e4b17023SJohn Marino
136*e4b17023SJohn Marino a b a&b a|b
137*e4b17023SJohn Marino Y Y Y Y
138*e4b17023SJohn Marino N Y N Y
139*e4b17023SJohn Marino N N N N
140*e4b17023SJohn Marino I Y I Y
141*e4b17023SJohn Marino I N N I
142*e4b17023SJohn Marino I I I I
143*e4b17023SJohn Marino
144*e4b17023SJohn Marino We represent Y with 1, N with 0, I with 2. If any code is left in
145*e4b17023SJohn Marino an I state by the complete expression, we must assume that that
146*e4b17023SJohn Marino code can be accepted. */
147*e4b17023SJohn Marino
148*e4b17023SJohn Marino #define N 0
149*e4b17023SJohn Marino #define Y 1
150*e4b17023SJohn Marino #define I 2
151*e4b17023SJohn Marino
152*e4b17023SJohn Marino #define TRISTATE_AND(a,b) \
153*e4b17023SJohn Marino ((a) == I ? ((b) == N ? N : I) : \
154*e4b17023SJohn Marino (b) == I ? ((a) == N ? N : I) : \
155*e4b17023SJohn Marino (a) && (b))
156*e4b17023SJohn Marino
157*e4b17023SJohn Marino #define TRISTATE_OR(a,b) \
158*e4b17023SJohn Marino ((a) == I ? ((b) == Y ? Y : I) : \
159*e4b17023SJohn Marino (b) == I ? ((a) == Y ? Y : I) : \
160*e4b17023SJohn Marino (a) || (b))
161*e4b17023SJohn Marino
162*e4b17023SJohn Marino #define TRISTATE_NOT(a) \
163*e4b17023SJohn Marino ((a) == I ? I : !(a))
164*e4b17023SJohn Marino
165*e4b17023SJohn Marino /* 0 means no warning about that code yet, 1 means warned. */
166*e4b17023SJohn Marino static char did_you_mean_codes[NUM_RTX_CODE];
167*e4b17023SJohn Marino
168*e4b17023SJohn Marino /* Recursively calculate the set of rtx codes accepted by the
169*e4b17023SJohn Marino predicate expression EXP, writing the result to CODES. LINENO is
170*e4b17023SJohn Marino the line number on which the directive containing EXP appeared. */
171*e4b17023SJohn Marino
172*e4b17023SJohn Marino static void
compute_predicate_codes(rtx exp,int lineno,char codes[NUM_RTX_CODE])173*e4b17023SJohn Marino compute_predicate_codes (rtx exp, int lineno, char codes[NUM_RTX_CODE])
174*e4b17023SJohn Marino {
175*e4b17023SJohn Marino char op0_codes[NUM_RTX_CODE];
176*e4b17023SJohn Marino char op1_codes[NUM_RTX_CODE];
177*e4b17023SJohn Marino char op2_codes[NUM_RTX_CODE];
178*e4b17023SJohn Marino int i;
179*e4b17023SJohn Marino
180*e4b17023SJohn Marino switch (GET_CODE (exp))
181*e4b17023SJohn Marino {
182*e4b17023SJohn Marino case AND:
183*e4b17023SJohn Marino compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
184*e4b17023SJohn Marino compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
185*e4b17023SJohn Marino for (i = 0; i < NUM_RTX_CODE; i++)
186*e4b17023SJohn Marino codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
187*e4b17023SJohn Marino break;
188*e4b17023SJohn Marino
189*e4b17023SJohn Marino case IOR:
190*e4b17023SJohn Marino compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
191*e4b17023SJohn Marino compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
192*e4b17023SJohn Marino for (i = 0; i < NUM_RTX_CODE; i++)
193*e4b17023SJohn Marino codes[i] = TRISTATE_OR (op0_codes[i], op1_codes[i]);
194*e4b17023SJohn Marino break;
195*e4b17023SJohn Marino case NOT:
196*e4b17023SJohn Marino compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
197*e4b17023SJohn Marino for (i = 0; i < NUM_RTX_CODE; i++)
198*e4b17023SJohn Marino codes[i] = TRISTATE_NOT (op0_codes[i]);
199*e4b17023SJohn Marino break;
200*e4b17023SJohn Marino
201*e4b17023SJohn Marino case IF_THEN_ELSE:
202*e4b17023SJohn Marino /* a ? b : c accepts the same codes as (a & b) | (!a & c). */
203*e4b17023SJohn Marino compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
204*e4b17023SJohn Marino compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
205*e4b17023SJohn Marino compute_predicate_codes (XEXP (exp, 2), lineno, op2_codes);
206*e4b17023SJohn Marino for (i = 0; i < NUM_RTX_CODE; i++)
207*e4b17023SJohn Marino codes[i] = TRISTATE_OR (TRISTATE_AND (op0_codes[i], op1_codes[i]),
208*e4b17023SJohn Marino TRISTATE_AND (TRISTATE_NOT (op0_codes[i]),
209*e4b17023SJohn Marino op2_codes[i]));
210*e4b17023SJohn Marino break;
211*e4b17023SJohn Marino
212*e4b17023SJohn Marino case MATCH_CODE:
213*e4b17023SJohn Marino /* MATCH_CODE allows a specified list of codes. However, if it
214*e4b17023SJohn Marino does not apply to the top level of the expression, it does not
215*e4b17023SJohn Marino constrain the set of codes for the top level. */
216*e4b17023SJohn Marino if (XSTR (exp, 1)[0] != '\0')
217*e4b17023SJohn Marino {
218*e4b17023SJohn Marino memset (codes, Y, NUM_RTX_CODE);
219*e4b17023SJohn Marino break;
220*e4b17023SJohn Marino }
221*e4b17023SJohn Marino
222*e4b17023SJohn Marino memset (codes, N, NUM_RTX_CODE);
223*e4b17023SJohn Marino {
224*e4b17023SJohn Marino const char *next_code = XSTR (exp, 0);
225*e4b17023SJohn Marino const char *code;
226*e4b17023SJohn Marino
227*e4b17023SJohn Marino if (*next_code == '\0')
228*e4b17023SJohn Marino {
229*e4b17023SJohn Marino error_with_line (lineno, "empty match_code expression");
230*e4b17023SJohn Marino break;
231*e4b17023SJohn Marino }
232*e4b17023SJohn Marino
233*e4b17023SJohn Marino while ((code = scan_comma_elt (&next_code)) != 0)
234*e4b17023SJohn Marino {
235*e4b17023SJohn Marino size_t n = next_code - code;
236*e4b17023SJohn Marino int found_it = 0;
237*e4b17023SJohn Marino
238*e4b17023SJohn Marino for (i = 0; i < NUM_RTX_CODE; i++)
239*e4b17023SJohn Marino if (!strncmp (code, GET_RTX_NAME (i), n)
240*e4b17023SJohn Marino && GET_RTX_NAME (i)[n] == '\0')
241*e4b17023SJohn Marino {
242*e4b17023SJohn Marino codes[i] = Y;
243*e4b17023SJohn Marino found_it = 1;
244*e4b17023SJohn Marino break;
245*e4b17023SJohn Marino }
246*e4b17023SJohn Marino if (!found_it)
247*e4b17023SJohn Marino {
248*e4b17023SJohn Marino error_with_line (lineno,
249*e4b17023SJohn Marino "match_code \"%.*s\" matches nothing",
250*e4b17023SJohn Marino (int) n, code);
251*e4b17023SJohn Marino for (i = 0; i < NUM_RTX_CODE; i++)
252*e4b17023SJohn Marino if (!strncasecmp (code, GET_RTX_NAME (i), n)
253*e4b17023SJohn Marino && GET_RTX_NAME (i)[n] == '\0'
254*e4b17023SJohn Marino && !did_you_mean_codes[i])
255*e4b17023SJohn Marino {
256*e4b17023SJohn Marino did_you_mean_codes[i] = 1;
257*e4b17023SJohn Marino message_with_line (lineno, "(did you mean \"%s\"?)",
258*e4b17023SJohn Marino GET_RTX_NAME (i));
259*e4b17023SJohn Marino }
260*e4b17023SJohn Marino }
261*e4b17023SJohn Marino }
262*e4b17023SJohn Marino }
263*e4b17023SJohn Marino break;
264*e4b17023SJohn Marino
265*e4b17023SJohn Marino case MATCH_OPERAND:
266*e4b17023SJohn Marino /* MATCH_OPERAND disallows the set of codes that the named predicate
267*e4b17023SJohn Marino disallows, and is indeterminate for the codes that it does allow. */
268*e4b17023SJohn Marino {
269*e4b17023SJohn Marino struct pred_data *p = lookup_predicate (XSTR (exp, 1));
270*e4b17023SJohn Marino if (!p)
271*e4b17023SJohn Marino {
272*e4b17023SJohn Marino error_with_line (lineno, "reference to unknown predicate '%s'",
273*e4b17023SJohn Marino XSTR (exp, 1));
274*e4b17023SJohn Marino break;
275*e4b17023SJohn Marino }
276*e4b17023SJohn Marino for (i = 0; i < NUM_RTX_CODE; i++)
277*e4b17023SJohn Marino codes[i] = p->codes[i] ? I : N;
278*e4b17023SJohn Marino }
279*e4b17023SJohn Marino break;
280*e4b17023SJohn Marino
281*e4b17023SJohn Marino
282*e4b17023SJohn Marino case MATCH_TEST:
283*e4b17023SJohn Marino /* (match_test WHATEVER) is completely indeterminate. */
284*e4b17023SJohn Marino memset (codes, I, NUM_RTX_CODE);
285*e4b17023SJohn Marino break;
286*e4b17023SJohn Marino
287*e4b17023SJohn Marino default:
288*e4b17023SJohn Marino error_with_line (lineno,
289*e4b17023SJohn Marino "'%s' cannot be used in a define_predicate expression",
290*e4b17023SJohn Marino GET_RTX_NAME (GET_CODE (exp)));
291*e4b17023SJohn Marino memset (codes, I, NUM_RTX_CODE);
292*e4b17023SJohn Marino break;
293*e4b17023SJohn Marino }
294*e4b17023SJohn Marino }
295*e4b17023SJohn Marino
296*e4b17023SJohn Marino #undef TRISTATE_OR
297*e4b17023SJohn Marino #undef TRISTATE_AND
298*e4b17023SJohn Marino #undef TRISTATE_NOT
299*e4b17023SJohn Marino
300*e4b17023SJohn Marino /* Return true if NAME is a valid predicate name. */
301*e4b17023SJohn Marino
302*e4b17023SJohn Marino static bool
valid_predicate_name_p(const char * name)303*e4b17023SJohn Marino valid_predicate_name_p (const char *name)
304*e4b17023SJohn Marino {
305*e4b17023SJohn Marino const char *p;
306*e4b17023SJohn Marino
307*e4b17023SJohn Marino if (!ISALPHA (name[0]) && name[0] != '_')
308*e4b17023SJohn Marino return false;
309*e4b17023SJohn Marino for (p = name + 1; *p; p++)
310*e4b17023SJohn Marino if (!ISALNUM (*p) && *p != '_')
311*e4b17023SJohn Marino return false;
312*e4b17023SJohn Marino return true;
313*e4b17023SJohn Marino }
314*e4b17023SJohn Marino
315*e4b17023SJohn Marino /* Process define_predicate directive DESC, which appears on line number
316*e4b17023SJohn Marino LINENO. Compute the set of codes that can be matched, and record this
317*e4b17023SJohn Marino as a known predicate. */
318*e4b17023SJohn Marino
319*e4b17023SJohn Marino static void
process_define_predicate(rtx desc,int lineno)320*e4b17023SJohn Marino process_define_predicate (rtx desc, int lineno)
321*e4b17023SJohn Marino {
322*e4b17023SJohn Marino struct pred_data *pred;
323*e4b17023SJohn Marino char codes[NUM_RTX_CODE];
324*e4b17023SJohn Marino int i;
325*e4b17023SJohn Marino
326*e4b17023SJohn Marino if (!valid_predicate_name_p (XSTR (desc, 0)))
327*e4b17023SJohn Marino {
328*e4b17023SJohn Marino error_with_line (lineno,
329*e4b17023SJohn Marino "%s: predicate name must be a valid C function name",
330*e4b17023SJohn Marino XSTR (desc, 0));
331*e4b17023SJohn Marino return;
332*e4b17023SJohn Marino }
333*e4b17023SJohn Marino
334*e4b17023SJohn Marino pred = XCNEW (struct pred_data);
335*e4b17023SJohn Marino pred->name = XSTR (desc, 0);
336*e4b17023SJohn Marino pred->exp = XEXP (desc, 1);
337*e4b17023SJohn Marino pred->c_block = XSTR (desc, 2);
338*e4b17023SJohn Marino if (GET_CODE (desc) == DEFINE_SPECIAL_PREDICATE)
339*e4b17023SJohn Marino pred->special = true;
340*e4b17023SJohn Marino
341*e4b17023SJohn Marino compute_predicate_codes (XEXP (desc, 1), lineno, codes);
342*e4b17023SJohn Marino
343*e4b17023SJohn Marino for (i = 0; i < NUM_RTX_CODE; i++)
344*e4b17023SJohn Marino if (codes[i] != N)
345*e4b17023SJohn Marino add_predicate_code (pred, (enum rtx_code) i);
346*e4b17023SJohn Marino
347*e4b17023SJohn Marino add_predicate (pred);
348*e4b17023SJohn Marino }
349*e4b17023SJohn Marino #undef I
350*e4b17023SJohn Marino #undef N
351*e4b17023SJohn Marino #undef Y
352*e4b17023SJohn Marino
353*e4b17023SJohn Marino /* Queue PATTERN on LIST_TAIL. Return the address of the new queue
354*e4b17023SJohn Marino element. */
355*e4b17023SJohn Marino
356*e4b17023SJohn Marino static struct queue_elem *
queue_pattern(rtx pattern,struct queue_elem *** list_tail,const char * filename,int lineno)357*e4b17023SJohn Marino queue_pattern (rtx pattern, struct queue_elem ***list_tail,
358*e4b17023SJohn Marino const char *filename, int lineno)
359*e4b17023SJohn Marino {
360*e4b17023SJohn Marino struct queue_elem *e = XNEW(struct queue_elem);
361*e4b17023SJohn Marino e->data = pattern;
362*e4b17023SJohn Marino e->filename = filename;
363*e4b17023SJohn Marino e->lineno = lineno;
364*e4b17023SJohn Marino e->next = NULL;
365*e4b17023SJohn Marino e->split = NULL;
366*e4b17023SJohn Marino **list_tail = e;
367*e4b17023SJohn Marino *list_tail = &e->next;
368*e4b17023SJohn Marino return e;
369*e4b17023SJohn Marino }
370*e4b17023SJohn Marino
371*e4b17023SJohn Marino /* Build a define_attr for an binary attribute with name NAME and
372*e4b17023SJohn Marino possible values "yes" and "no", and queue it. */
373*e4b17023SJohn Marino static void
add_define_attr(const char * name)374*e4b17023SJohn Marino add_define_attr (const char *name)
375*e4b17023SJohn Marino {
376*e4b17023SJohn Marino struct queue_elem *e = XNEW(struct queue_elem);
377*e4b17023SJohn Marino rtx t1 = rtx_alloc (DEFINE_ATTR);
378*e4b17023SJohn Marino XSTR (t1, 0) = name;
379*e4b17023SJohn Marino XSTR (t1, 1) = "no,yes";
380*e4b17023SJohn Marino XEXP (t1, 2) = rtx_alloc (CONST_STRING);
381*e4b17023SJohn Marino XSTR (XEXP (t1, 2), 0) = "yes";
382*e4b17023SJohn Marino e->data = t1;
383*e4b17023SJohn Marino e->filename = "built-in";
384*e4b17023SJohn Marino e->lineno = -1;
385*e4b17023SJohn Marino e->next = define_attr_queue;
386*e4b17023SJohn Marino define_attr_queue = e;
387*e4b17023SJohn Marino
388*e4b17023SJohn Marino }
389*e4b17023SJohn Marino
390*e4b17023SJohn Marino /* Recursively remove constraints from an rtx. */
391*e4b17023SJohn Marino
392*e4b17023SJohn Marino static void
remove_constraints(rtx part)393*e4b17023SJohn Marino remove_constraints (rtx part)
394*e4b17023SJohn Marino {
395*e4b17023SJohn Marino int i, j;
396*e4b17023SJohn Marino const char *format_ptr;
397*e4b17023SJohn Marino
398*e4b17023SJohn Marino if (part == 0)
399*e4b17023SJohn Marino return;
400*e4b17023SJohn Marino
401*e4b17023SJohn Marino if (GET_CODE (part) == MATCH_OPERAND)
402*e4b17023SJohn Marino XSTR (part, 2) = "";
403*e4b17023SJohn Marino else if (GET_CODE (part) == MATCH_SCRATCH)
404*e4b17023SJohn Marino XSTR (part, 1) = "";
405*e4b17023SJohn Marino
406*e4b17023SJohn Marino format_ptr = GET_RTX_FORMAT (GET_CODE (part));
407*e4b17023SJohn Marino
408*e4b17023SJohn Marino for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
409*e4b17023SJohn Marino switch (*format_ptr++)
410*e4b17023SJohn Marino {
411*e4b17023SJohn Marino case 'e':
412*e4b17023SJohn Marino case 'u':
413*e4b17023SJohn Marino remove_constraints (XEXP (part, i));
414*e4b17023SJohn Marino break;
415*e4b17023SJohn Marino case 'E':
416*e4b17023SJohn Marino if (XVEC (part, i) != NULL)
417*e4b17023SJohn Marino for (j = 0; j < XVECLEN (part, i); j++)
418*e4b17023SJohn Marino remove_constraints (XVECEXP (part, i, j));
419*e4b17023SJohn Marino break;
420*e4b17023SJohn Marino }
421*e4b17023SJohn Marino }
422*e4b17023SJohn Marino
423*e4b17023SJohn Marino /* Process a top level rtx in some way, queuing as appropriate. */
424*e4b17023SJohn Marino
425*e4b17023SJohn Marino static void
process_rtx(rtx desc,int lineno)426*e4b17023SJohn Marino process_rtx (rtx desc, int lineno)
427*e4b17023SJohn Marino {
428*e4b17023SJohn Marino switch (GET_CODE (desc))
429*e4b17023SJohn Marino {
430*e4b17023SJohn Marino case DEFINE_INSN:
431*e4b17023SJohn Marino queue_pattern (desc, &define_insn_tail, read_md_filename, lineno);
432*e4b17023SJohn Marino break;
433*e4b17023SJohn Marino
434*e4b17023SJohn Marino case DEFINE_COND_EXEC:
435*e4b17023SJohn Marino queue_pattern (desc, &define_cond_exec_tail, read_md_filename, lineno);
436*e4b17023SJohn Marino break;
437*e4b17023SJohn Marino
438*e4b17023SJohn Marino case DEFINE_ATTR:
439*e4b17023SJohn Marino case DEFINE_ENUM_ATTR:
440*e4b17023SJohn Marino queue_pattern (desc, &define_attr_tail, read_md_filename, lineno);
441*e4b17023SJohn Marino break;
442*e4b17023SJohn Marino
443*e4b17023SJohn Marino case DEFINE_PREDICATE:
444*e4b17023SJohn Marino case DEFINE_SPECIAL_PREDICATE:
445*e4b17023SJohn Marino process_define_predicate (desc, lineno);
446*e4b17023SJohn Marino /* Fall through. */
447*e4b17023SJohn Marino
448*e4b17023SJohn Marino case DEFINE_CONSTRAINT:
449*e4b17023SJohn Marino case DEFINE_REGISTER_CONSTRAINT:
450*e4b17023SJohn Marino case DEFINE_MEMORY_CONSTRAINT:
451*e4b17023SJohn Marino case DEFINE_ADDRESS_CONSTRAINT:
452*e4b17023SJohn Marino queue_pattern (desc, &define_pred_tail, read_md_filename, lineno);
453*e4b17023SJohn Marino break;
454*e4b17023SJohn Marino
455*e4b17023SJohn Marino case DEFINE_INSN_AND_SPLIT:
456*e4b17023SJohn Marino {
457*e4b17023SJohn Marino const char *split_cond;
458*e4b17023SJohn Marino rtx split;
459*e4b17023SJohn Marino rtvec attr;
460*e4b17023SJohn Marino int i;
461*e4b17023SJohn Marino struct queue_elem *insn_elem;
462*e4b17023SJohn Marino struct queue_elem *split_elem;
463*e4b17023SJohn Marino
464*e4b17023SJohn Marino /* Create a split with values from the insn_and_split. */
465*e4b17023SJohn Marino split = rtx_alloc (DEFINE_SPLIT);
466*e4b17023SJohn Marino
467*e4b17023SJohn Marino i = XVECLEN (desc, 1);
468*e4b17023SJohn Marino XVEC (split, 0) = rtvec_alloc (i);
469*e4b17023SJohn Marino while (--i >= 0)
470*e4b17023SJohn Marino {
471*e4b17023SJohn Marino XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
472*e4b17023SJohn Marino remove_constraints (XVECEXP (split, 0, i));
473*e4b17023SJohn Marino }
474*e4b17023SJohn Marino
475*e4b17023SJohn Marino /* If the split condition starts with "&&", append it to the
476*e4b17023SJohn Marino insn condition to create the new split condition. */
477*e4b17023SJohn Marino split_cond = XSTR (desc, 4);
478*e4b17023SJohn Marino if (split_cond[0] == '&' && split_cond[1] == '&')
479*e4b17023SJohn Marino {
480*e4b17023SJohn Marino copy_md_ptr_loc (split_cond + 2, split_cond);
481*e4b17023SJohn Marino split_cond = join_c_conditions (XSTR (desc, 2), split_cond + 2);
482*e4b17023SJohn Marino }
483*e4b17023SJohn Marino XSTR (split, 1) = split_cond;
484*e4b17023SJohn Marino XVEC (split, 2) = XVEC (desc, 5);
485*e4b17023SJohn Marino XSTR (split, 3) = XSTR (desc, 6);
486*e4b17023SJohn Marino
487*e4b17023SJohn Marino /* Fix up the DEFINE_INSN. */
488*e4b17023SJohn Marino attr = XVEC (desc, 7);
489*e4b17023SJohn Marino PUT_CODE (desc, DEFINE_INSN);
490*e4b17023SJohn Marino XVEC (desc, 4) = attr;
491*e4b17023SJohn Marino
492*e4b17023SJohn Marino /* Queue them. */
493*e4b17023SJohn Marino insn_elem
494*e4b17023SJohn Marino = queue_pattern (desc, &define_insn_tail, read_md_filename,
495*e4b17023SJohn Marino lineno);
496*e4b17023SJohn Marino split_elem
497*e4b17023SJohn Marino = queue_pattern (split, &other_tail, read_md_filename, lineno);
498*e4b17023SJohn Marino insn_elem->split = split_elem;
499*e4b17023SJohn Marino break;
500*e4b17023SJohn Marino }
501*e4b17023SJohn Marino
502*e4b17023SJohn Marino default:
503*e4b17023SJohn Marino queue_pattern (desc, &other_tail, read_md_filename, lineno);
504*e4b17023SJohn Marino break;
505*e4b17023SJohn Marino }
506*e4b17023SJohn Marino }
507*e4b17023SJohn Marino
508*e4b17023SJohn Marino /* Return true if attribute PREDICABLE is true for ELEM, which holds
509*e4b17023SJohn Marino a DEFINE_INSN. */
510*e4b17023SJohn Marino
511*e4b17023SJohn Marino static int
is_predicable(struct queue_elem * elem)512*e4b17023SJohn Marino is_predicable (struct queue_elem *elem)
513*e4b17023SJohn Marino {
514*e4b17023SJohn Marino rtvec vec = XVEC (elem->data, 4);
515*e4b17023SJohn Marino const char *value;
516*e4b17023SJohn Marino int i;
517*e4b17023SJohn Marino
518*e4b17023SJohn Marino if (! vec)
519*e4b17023SJohn Marino return predicable_default;
520*e4b17023SJohn Marino
521*e4b17023SJohn Marino for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
522*e4b17023SJohn Marino {
523*e4b17023SJohn Marino rtx sub = RTVEC_ELT (vec, i);
524*e4b17023SJohn Marino switch (GET_CODE (sub))
525*e4b17023SJohn Marino {
526*e4b17023SJohn Marino case SET_ATTR:
527*e4b17023SJohn Marino if (strcmp (XSTR (sub, 0), "predicable") == 0)
528*e4b17023SJohn Marino {
529*e4b17023SJohn Marino value = XSTR (sub, 1);
530*e4b17023SJohn Marino goto found;
531*e4b17023SJohn Marino }
532*e4b17023SJohn Marino break;
533*e4b17023SJohn Marino
534*e4b17023SJohn Marino case SET_ATTR_ALTERNATIVE:
535*e4b17023SJohn Marino if (strcmp (XSTR (sub, 0), "predicable") == 0)
536*e4b17023SJohn Marino {
537*e4b17023SJohn Marino error_with_line (elem->lineno,
538*e4b17023SJohn Marino "multiple alternatives for `predicable'");
539*e4b17023SJohn Marino return 0;
540*e4b17023SJohn Marino }
541*e4b17023SJohn Marino break;
542*e4b17023SJohn Marino
543*e4b17023SJohn Marino case SET:
544*e4b17023SJohn Marino if (GET_CODE (SET_DEST (sub)) != ATTR
545*e4b17023SJohn Marino || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
546*e4b17023SJohn Marino break;
547*e4b17023SJohn Marino sub = SET_SRC (sub);
548*e4b17023SJohn Marino if (GET_CODE (sub) == CONST_STRING)
549*e4b17023SJohn Marino {
550*e4b17023SJohn Marino value = XSTR (sub, 0);
551*e4b17023SJohn Marino goto found;
552*e4b17023SJohn Marino }
553*e4b17023SJohn Marino
554*e4b17023SJohn Marino /* ??? It would be possible to handle this if we really tried.
555*e4b17023SJohn Marino It's not easy though, and I'm not going to bother until it
556*e4b17023SJohn Marino really proves necessary. */
557*e4b17023SJohn Marino error_with_line (elem->lineno,
558*e4b17023SJohn Marino "non-constant value for `predicable'");
559*e4b17023SJohn Marino return 0;
560*e4b17023SJohn Marino
561*e4b17023SJohn Marino default:
562*e4b17023SJohn Marino gcc_unreachable ();
563*e4b17023SJohn Marino }
564*e4b17023SJohn Marino }
565*e4b17023SJohn Marino
566*e4b17023SJohn Marino return predicable_default;
567*e4b17023SJohn Marino
568*e4b17023SJohn Marino found:
569*e4b17023SJohn Marino /* Find out which value we're looking at. Multiple alternatives means at
570*e4b17023SJohn Marino least one is predicable. */
571*e4b17023SJohn Marino if (strchr (value, ',') != NULL)
572*e4b17023SJohn Marino return 1;
573*e4b17023SJohn Marino if (strcmp (value, predicable_true) == 0)
574*e4b17023SJohn Marino return 1;
575*e4b17023SJohn Marino if (strcmp (value, predicable_false) == 0)
576*e4b17023SJohn Marino return 0;
577*e4b17023SJohn Marino
578*e4b17023SJohn Marino error_with_line (elem->lineno,
579*e4b17023SJohn Marino "unknown value `%s' for `predicable' attribute", value);
580*e4b17023SJohn Marino return 0;
581*e4b17023SJohn Marino }
582*e4b17023SJohn Marino
583*e4b17023SJohn Marino /* Examine the attribute "predicable"; discover its boolean values
584*e4b17023SJohn Marino and its default. */
585*e4b17023SJohn Marino
586*e4b17023SJohn Marino static void
identify_predicable_attribute(void)587*e4b17023SJohn Marino identify_predicable_attribute (void)
588*e4b17023SJohn Marino {
589*e4b17023SJohn Marino struct queue_elem *elem;
590*e4b17023SJohn Marino char *p_true, *p_false;
591*e4b17023SJohn Marino const char *value;
592*e4b17023SJohn Marino
593*e4b17023SJohn Marino /* Look for the DEFINE_ATTR for `predicable', which must exist. */
594*e4b17023SJohn Marino for (elem = define_attr_queue; elem ; elem = elem->next)
595*e4b17023SJohn Marino if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
596*e4b17023SJohn Marino goto found;
597*e4b17023SJohn Marino
598*e4b17023SJohn Marino error_with_line (define_cond_exec_queue->lineno,
599*e4b17023SJohn Marino "attribute `predicable' not defined");
600*e4b17023SJohn Marino return;
601*e4b17023SJohn Marino
602*e4b17023SJohn Marino found:
603*e4b17023SJohn Marino value = XSTR (elem->data, 1);
604*e4b17023SJohn Marino p_false = xstrdup (value);
605*e4b17023SJohn Marino p_true = strchr (p_false, ',');
606*e4b17023SJohn Marino if (p_true == NULL || strchr (++p_true, ',') != NULL)
607*e4b17023SJohn Marino {
608*e4b17023SJohn Marino error_with_line (elem->lineno, "attribute `predicable' is not a boolean");
609*e4b17023SJohn Marino free (p_false);
610*e4b17023SJohn Marino return;
611*e4b17023SJohn Marino }
612*e4b17023SJohn Marino p_true[-1] = '\0';
613*e4b17023SJohn Marino
614*e4b17023SJohn Marino predicable_true = p_true;
615*e4b17023SJohn Marino predicable_false = p_false;
616*e4b17023SJohn Marino
617*e4b17023SJohn Marino switch (GET_CODE (XEXP (elem->data, 2)))
618*e4b17023SJohn Marino {
619*e4b17023SJohn Marino case CONST_STRING:
620*e4b17023SJohn Marino value = XSTR (XEXP (elem->data, 2), 0);
621*e4b17023SJohn Marino break;
622*e4b17023SJohn Marino
623*e4b17023SJohn Marino case CONST:
624*e4b17023SJohn Marino error_with_line (elem->lineno, "attribute `predicable' cannot be const");
625*e4b17023SJohn Marino free (p_false);
626*e4b17023SJohn Marino return;
627*e4b17023SJohn Marino
628*e4b17023SJohn Marino default:
629*e4b17023SJohn Marino error_with_line (elem->lineno,
630*e4b17023SJohn Marino "attribute `predicable' must have a constant default");
631*e4b17023SJohn Marino free (p_false);
632*e4b17023SJohn Marino return;
633*e4b17023SJohn Marino }
634*e4b17023SJohn Marino
635*e4b17023SJohn Marino if (strcmp (value, p_true) == 0)
636*e4b17023SJohn Marino predicable_default = 1;
637*e4b17023SJohn Marino else if (strcmp (value, p_false) == 0)
638*e4b17023SJohn Marino predicable_default = 0;
639*e4b17023SJohn Marino else
640*e4b17023SJohn Marino {
641*e4b17023SJohn Marino error_with_line (elem->lineno,
642*e4b17023SJohn Marino "unknown value `%s' for `predicable' attribute", value);
643*e4b17023SJohn Marino free (p_false);
644*e4b17023SJohn Marino }
645*e4b17023SJohn Marino }
646*e4b17023SJohn Marino
647*e4b17023SJohn Marino /* Return the number of alternatives in constraint S. */
648*e4b17023SJohn Marino
649*e4b17023SJohn Marino static int
n_alternatives(const char * s)650*e4b17023SJohn Marino n_alternatives (const char *s)
651*e4b17023SJohn Marino {
652*e4b17023SJohn Marino int n = 1;
653*e4b17023SJohn Marino
654*e4b17023SJohn Marino if (s)
655*e4b17023SJohn Marino while (*s)
656*e4b17023SJohn Marino n += (*s++ == ',');
657*e4b17023SJohn Marino
658*e4b17023SJohn Marino return n;
659*e4b17023SJohn Marino }
660*e4b17023SJohn Marino
661*e4b17023SJohn Marino /* Determine how many alternatives there are in INSN, and how many
662*e4b17023SJohn Marino operands. */
663*e4b17023SJohn Marino
664*e4b17023SJohn Marino static void
collect_insn_data(rtx pattern,int * palt,int * pmax)665*e4b17023SJohn Marino collect_insn_data (rtx pattern, int *palt, int *pmax)
666*e4b17023SJohn Marino {
667*e4b17023SJohn Marino const char *fmt;
668*e4b17023SJohn Marino enum rtx_code code;
669*e4b17023SJohn Marino int i, j, len;
670*e4b17023SJohn Marino
671*e4b17023SJohn Marino code = GET_CODE (pattern);
672*e4b17023SJohn Marino switch (code)
673*e4b17023SJohn Marino {
674*e4b17023SJohn Marino case MATCH_OPERAND:
675*e4b17023SJohn Marino i = n_alternatives (XSTR (pattern, 2));
676*e4b17023SJohn Marino *palt = (i > *palt ? i : *palt);
677*e4b17023SJohn Marino /* Fall through. */
678*e4b17023SJohn Marino
679*e4b17023SJohn Marino case MATCH_OPERATOR:
680*e4b17023SJohn Marino case MATCH_SCRATCH:
681*e4b17023SJohn Marino case MATCH_PARALLEL:
682*e4b17023SJohn Marino i = XINT (pattern, 0);
683*e4b17023SJohn Marino if (i > *pmax)
684*e4b17023SJohn Marino *pmax = i;
685*e4b17023SJohn Marino break;
686*e4b17023SJohn Marino
687*e4b17023SJohn Marino default:
688*e4b17023SJohn Marino break;
689*e4b17023SJohn Marino }
690*e4b17023SJohn Marino
691*e4b17023SJohn Marino fmt = GET_RTX_FORMAT (code);
692*e4b17023SJohn Marino len = GET_RTX_LENGTH (code);
693*e4b17023SJohn Marino for (i = 0; i < len; i++)
694*e4b17023SJohn Marino {
695*e4b17023SJohn Marino switch (fmt[i])
696*e4b17023SJohn Marino {
697*e4b17023SJohn Marino case 'e': case 'u':
698*e4b17023SJohn Marino collect_insn_data (XEXP (pattern, i), palt, pmax);
699*e4b17023SJohn Marino break;
700*e4b17023SJohn Marino
701*e4b17023SJohn Marino case 'V':
702*e4b17023SJohn Marino if (XVEC (pattern, i) == NULL)
703*e4b17023SJohn Marino break;
704*e4b17023SJohn Marino /* Fall through. */
705*e4b17023SJohn Marino case 'E':
706*e4b17023SJohn Marino for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
707*e4b17023SJohn Marino collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
708*e4b17023SJohn Marino break;
709*e4b17023SJohn Marino
710*e4b17023SJohn Marino case 'i': case 'w': case '0': case 's': case 'S': case 'T':
711*e4b17023SJohn Marino break;
712*e4b17023SJohn Marino
713*e4b17023SJohn Marino default:
714*e4b17023SJohn Marino gcc_unreachable ();
715*e4b17023SJohn Marino }
716*e4b17023SJohn Marino }
717*e4b17023SJohn Marino }
718*e4b17023SJohn Marino
719*e4b17023SJohn Marino static rtx
alter_predicate_for_insn(rtx pattern,int alt,int max_op,int lineno)720*e4b17023SJohn Marino alter_predicate_for_insn (rtx pattern, int alt, int max_op, int lineno)
721*e4b17023SJohn Marino {
722*e4b17023SJohn Marino const char *fmt;
723*e4b17023SJohn Marino enum rtx_code code;
724*e4b17023SJohn Marino int i, j, len;
725*e4b17023SJohn Marino
726*e4b17023SJohn Marino code = GET_CODE (pattern);
727*e4b17023SJohn Marino switch (code)
728*e4b17023SJohn Marino {
729*e4b17023SJohn Marino case MATCH_OPERAND:
730*e4b17023SJohn Marino {
731*e4b17023SJohn Marino const char *c = XSTR (pattern, 2);
732*e4b17023SJohn Marino
733*e4b17023SJohn Marino if (n_alternatives (c) != 1)
734*e4b17023SJohn Marino {
735*e4b17023SJohn Marino error_with_line (lineno, "too many alternatives for operand %d",
736*e4b17023SJohn Marino XINT (pattern, 0));
737*e4b17023SJohn Marino return NULL;
738*e4b17023SJohn Marino }
739*e4b17023SJohn Marino
740*e4b17023SJohn Marino /* Replicate C as needed to fill out ALT alternatives. */
741*e4b17023SJohn Marino if (c && *c && alt > 1)
742*e4b17023SJohn Marino {
743*e4b17023SJohn Marino size_t c_len = strlen (c);
744*e4b17023SJohn Marino size_t len = alt * (c_len + 1);
745*e4b17023SJohn Marino char *new_c = XNEWVEC(char, len);
746*e4b17023SJohn Marino
747*e4b17023SJohn Marino memcpy (new_c, c, c_len);
748*e4b17023SJohn Marino for (i = 1; i < alt; ++i)
749*e4b17023SJohn Marino {
750*e4b17023SJohn Marino new_c[i * (c_len + 1) - 1] = ',';
751*e4b17023SJohn Marino memcpy (&new_c[i * (c_len + 1)], c, c_len);
752*e4b17023SJohn Marino }
753*e4b17023SJohn Marino new_c[len - 1] = '\0';
754*e4b17023SJohn Marino XSTR (pattern, 2) = new_c;
755*e4b17023SJohn Marino }
756*e4b17023SJohn Marino }
757*e4b17023SJohn Marino /* Fall through. */
758*e4b17023SJohn Marino
759*e4b17023SJohn Marino case MATCH_OPERATOR:
760*e4b17023SJohn Marino case MATCH_SCRATCH:
761*e4b17023SJohn Marino case MATCH_PARALLEL:
762*e4b17023SJohn Marino XINT (pattern, 0) += max_op;
763*e4b17023SJohn Marino break;
764*e4b17023SJohn Marino
765*e4b17023SJohn Marino default:
766*e4b17023SJohn Marino break;
767*e4b17023SJohn Marino }
768*e4b17023SJohn Marino
769*e4b17023SJohn Marino fmt = GET_RTX_FORMAT (code);
770*e4b17023SJohn Marino len = GET_RTX_LENGTH (code);
771*e4b17023SJohn Marino for (i = 0; i < len; i++)
772*e4b17023SJohn Marino {
773*e4b17023SJohn Marino rtx r;
774*e4b17023SJohn Marino
775*e4b17023SJohn Marino switch (fmt[i])
776*e4b17023SJohn Marino {
777*e4b17023SJohn Marino case 'e': case 'u':
778*e4b17023SJohn Marino r = alter_predicate_for_insn (XEXP (pattern, i), alt,
779*e4b17023SJohn Marino max_op, lineno);
780*e4b17023SJohn Marino if (r == NULL)
781*e4b17023SJohn Marino return r;
782*e4b17023SJohn Marino break;
783*e4b17023SJohn Marino
784*e4b17023SJohn Marino case 'E':
785*e4b17023SJohn Marino for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
786*e4b17023SJohn Marino {
787*e4b17023SJohn Marino r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
788*e4b17023SJohn Marino alt, max_op, lineno);
789*e4b17023SJohn Marino if (r == NULL)
790*e4b17023SJohn Marino return r;
791*e4b17023SJohn Marino }
792*e4b17023SJohn Marino break;
793*e4b17023SJohn Marino
794*e4b17023SJohn Marino case 'i': case 'w': case '0': case 's':
795*e4b17023SJohn Marino break;
796*e4b17023SJohn Marino
797*e4b17023SJohn Marino default:
798*e4b17023SJohn Marino gcc_unreachable ();
799*e4b17023SJohn Marino }
800*e4b17023SJohn Marino }
801*e4b17023SJohn Marino
802*e4b17023SJohn Marino return pattern;
803*e4b17023SJohn Marino }
804*e4b17023SJohn Marino
805*e4b17023SJohn Marino static const char *
alter_test_for_insn(struct queue_elem * ce_elem,struct queue_elem * insn_elem)806*e4b17023SJohn Marino alter_test_for_insn (struct queue_elem *ce_elem,
807*e4b17023SJohn Marino struct queue_elem *insn_elem)
808*e4b17023SJohn Marino {
809*e4b17023SJohn Marino return join_c_conditions (XSTR (ce_elem->data, 1),
810*e4b17023SJohn Marino XSTR (insn_elem->data, 2));
811*e4b17023SJohn Marino }
812*e4b17023SJohn Marino
813*e4b17023SJohn Marino /* Modify VAL, which is an attribute expression for the "enabled" attribute,
814*e4b17023SJohn Marino to take "ce_enabled" into account. Return the new expression. */
815*e4b17023SJohn Marino static rtx
modify_attr_enabled_ce(rtx val)816*e4b17023SJohn Marino modify_attr_enabled_ce (rtx val)
817*e4b17023SJohn Marino {
818*e4b17023SJohn Marino rtx eq_attr, str;
819*e4b17023SJohn Marino rtx ite;
820*e4b17023SJohn Marino eq_attr = rtx_alloc (EQ_ATTR);
821*e4b17023SJohn Marino ite = rtx_alloc (IF_THEN_ELSE);
822*e4b17023SJohn Marino str = rtx_alloc (CONST_STRING);
823*e4b17023SJohn Marino
824*e4b17023SJohn Marino XSTR (eq_attr, 0) = "ce_enabled";
825*e4b17023SJohn Marino XSTR (eq_attr, 1) = "yes";
826*e4b17023SJohn Marino XSTR (str, 0) = "no";
827*e4b17023SJohn Marino XEXP (ite, 0) = eq_attr;
828*e4b17023SJohn Marino XEXP (ite, 1) = val;
829*e4b17023SJohn Marino XEXP (ite, 2) = str;
830*e4b17023SJohn Marino
831*e4b17023SJohn Marino return ite;
832*e4b17023SJohn Marino }
833*e4b17023SJohn Marino
834*e4b17023SJohn Marino /* Alter the attribute vector of INSN, which is a COND_EXEC variant created
835*e4b17023SJohn Marino from a define_insn pattern. We must modify the "predicable" attribute
836*e4b17023SJohn Marino to be named "ce_enabled", and also change any "enabled" attribute that's
837*e4b17023SJohn Marino present so that it takes ce_enabled into account.
838*e4b17023SJohn Marino We rely on the fact that INSN was created with copy_rtx, and modify data
839*e4b17023SJohn Marino in-place. */
840*e4b17023SJohn Marino
841*e4b17023SJohn Marino static void
alter_attrs_for_insn(rtx insn)842*e4b17023SJohn Marino alter_attrs_for_insn (rtx insn)
843*e4b17023SJohn Marino {
844*e4b17023SJohn Marino static bool global_changes_made = false;
845*e4b17023SJohn Marino rtvec vec = XVEC (insn, 4);
846*e4b17023SJohn Marino rtvec new_vec;
847*e4b17023SJohn Marino rtx val, set;
848*e4b17023SJohn Marino int num_elem;
849*e4b17023SJohn Marino int predicable_idx = -1;
850*e4b17023SJohn Marino int enabled_idx = -1;
851*e4b17023SJohn Marino int i;
852*e4b17023SJohn Marino
853*e4b17023SJohn Marino if (! vec)
854*e4b17023SJohn Marino return;
855*e4b17023SJohn Marino
856*e4b17023SJohn Marino num_elem = GET_NUM_ELEM (vec);
857*e4b17023SJohn Marino for (i = num_elem - 1; i >= 0; --i)
858*e4b17023SJohn Marino {
859*e4b17023SJohn Marino rtx sub = RTVEC_ELT (vec, i);
860*e4b17023SJohn Marino switch (GET_CODE (sub))
861*e4b17023SJohn Marino {
862*e4b17023SJohn Marino case SET_ATTR:
863*e4b17023SJohn Marino if (strcmp (XSTR (sub, 0), "predicable") == 0)
864*e4b17023SJohn Marino {
865*e4b17023SJohn Marino predicable_idx = i;
866*e4b17023SJohn Marino XSTR (sub, 0) = "ce_enabled";
867*e4b17023SJohn Marino }
868*e4b17023SJohn Marino else if (strcmp (XSTR (sub, 0), "enabled") == 0)
869*e4b17023SJohn Marino {
870*e4b17023SJohn Marino enabled_idx = i;
871*e4b17023SJohn Marino XSTR (sub, 0) = "nonce_enabled";
872*e4b17023SJohn Marino }
873*e4b17023SJohn Marino break;
874*e4b17023SJohn Marino
875*e4b17023SJohn Marino case SET_ATTR_ALTERNATIVE:
876*e4b17023SJohn Marino if (strcmp (XSTR (sub, 0), "predicable") == 0)
877*e4b17023SJohn Marino /* We already give an error elsewhere. */
878*e4b17023SJohn Marino return;
879*e4b17023SJohn Marino else if (strcmp (XSTR (sub, 0), "enabled") == 0)
880*e4b17023SJohn Marino {
881*e4b17023SJohn Marino enabled_idx = i;
882*e4b17023SJohn Marino XSTR (sub, 0) = "nonce_enabled";
883*e4b17023SJohn Marino }
884*e4b17023SJohn Marino break;
885*e4b17023SJohn Marino
886*e4b17023SJohn Marino case SET:
887*e4b17023SJohn Marino if (GET_CODE (SET_DEST (sub)) != ATTR)
888*e4b17023SJohn Marino break;
889*e4b17023SJohn Marino if (strcmp (XSTR (SET_DEST (sub), 0), "predicable") == 0)
890*e4b17023SJohn Marino {
891*e4b17023SJohn Marino sub = SET_SRC (sub);
892*e4b17023SJohn Marino if (GET_CODE (sub) == CONST_STRING)
893*e4b17023SJohn Marino {
894*e4b17023SJohn Marino predicable_idx = i;
895*e4b17023SJohn Marino XSTR (sub, 0) = "ce_enabled";
896*e4b17023SJohn Marino }
897*e4b17023SJohn Marino else
898*e4b17023SJohn Marino /* We already give an error elsewhere. */
899*e4b17023SJohn Marino return;
900*e4b17023SJohn Marino break;
901*e4b17023SJohn Marino }
902*e4b17023SJohn Marino if (strcmp (XSTR (SET_DEST (sub), 0), "enabled") == 0)
903*e4b17023SJohn Marino {
904*e4b17023SJohn Marino enabled_idx = i;
905*e4b17023SJohn Marino XSTR (SET_DEST (sub), 0) = "nonce_enabled";
906*e4b17023SJohn Marino }
907*e4b17023SJohn Marino break;
908*e4b17023SJohn Marino
909*e4b17023SJohn Marino default:
910*e4b17023SJohn Marino gcc_unreachable ();
911*e4b17023SJohn Marino }
912*e4b17023SJohn Marino }
913*e4b17023SJohn Marino if (predicable_idx == -1)
914*e4b17023SJohn Marino return;
915*e4b17023SJohn Marino
916*e4b17023SJohn Marino if (!global_changes_made)
917*e4b17023SJohn Marino {
918*e4b17023SJohn Marino struct queue_elem *elem;
919*e4b17023SJohn Marino
920*e4b17023SJohn Marino global_changes_made = true;
921*e4b17023SJohn Marino add_define_attr ("ce_enabled");
922*e4b17023SJohn Marino add_define_attr ("nonce_enabled");
923*e4b17023SJohn Marino
924*e4b17023SJohn Marino for (elem = define_attr_queue; elem ; elem = elem->next)
925*e4b17023SJohn Marino if (strcmp (XSTR (elem->data, 0), "enabled") == 0)
926*e4b17023SJohn Marino {
927*e4b17023SJohn Marino XEXP (elem->data, 2)
928*e4b17023SJohn Marino = modify_attr_enabled_ce (XEXP (elem->data, 2));
929*e4b17023SJohn Marino }
930*e4b17023SJohn Marino }
931*e4b17023SJohn Marino if (enabled_idx == -1)
932*e4b17023SJohn Marino return;
933*e4b17023SJohn Marino
934*e4b17023SJohn Marino new_vec = rtvec_alloc (num_elem + 1);
935*e4b17023SJohn Marino for (i = 0; i < num_elem; i++)
936*e4b17023SJohn Marino RTVEC_ELT (new_vec, i) = RTVEC_ELT (vec, i);
937*e4b17023SJohn Marino val = rtx_alloc (IF_THEN_ELSE);
938*e4b17023SJohn Marino XEXP (val, 0) = rtx_alloc (EQ_ATTR);
939*e4b17023SJohn Marino XEXP (val, 1) = rtx_alloc (CONST_STRING);
940*e4b17023SJohn Marino XEXP (val, 2) = rtx_alloc (CONST_STRING);
941*e4b17023SJohn Marino XSTR (XEXP (val, 0), 0) = "nonce_enabled";
942*e4b17023SJohn Marino XSTR (XEXP (val, 0), 1) = "yes";
943*e4b17023SJohn Marino XSTR (XEXP (val, 1), 0) = "yes";
944*e4b17023SJohn Marino XSTR (XEXP (val, 2), 0) = "no";
945*e4b17023SJohn Marino set = rtx_alloc (SET);
946*e4b17023SJohn Marino SET_DEST (set) = rtx_alloc (ATTR);
947*e4b17023SJohn Marino XSTR (SET_DEST (set), 0) = "enabled";
948*e4b17023SJohn Marino SET_SRC (set) = modify_attr_enabled_ce (val);
949*e4b17023SJohn Marino RTVEC_ELT (new_vec, i) = set;
950*e4b17023SJohn Marino XVEC (insn, 4) = new_vec;
951*e4b17023SJohn Marino }
952*e4b17023SJohn Marino
953*e4b17023SJohn Marino /* Adjust all of the operand numbers in SRC to match the shift they'll
954*e4b17023SJohn Marino get from an operand displacement of DISP. Return a pointer after the
955*e4b17023SJohn Marino adjusted string. */
956*e4b17023SJohn Marino
957*e4b17023SJohn Marino static char *
shift_output_template(char * dest,const char * src,int disp)958*e4b17023SJohn Marino shift_output_template (char *dest, const char *src, int disp)
959*e4b17023SJohn Marino {
960*e4b17023SJohn Marino while (*src)
961*e4b17023SJohn Marino {
962*e4b17023SJohn Marino char c = *src++;
963*e4b17023SJohn Marino *dest++ = c;
964*e4b17023SJohn Marino if (c == '%')
965*e4b17023SJohn Marino {
966*e4b17023SJohn Marino c = *src++;
967*e4b17023SJohn Marino if (ISDIGIT ((unsigned char) c))
968*e4b17023SJohn Marino c += disp;
969*e4b17023SJohn Marino else if (ISALPHA (c))
970*e4b17023SJohn Marino {
971*e4b17023SJohn Marino *dest++ = c;
972*e4b17023SJohn Marino c = *src++ + disp;
973*e4b17023SJohn Marino }
974*e4b17023SJohn Marino *dest++ = c;
975*e4b17023SJohn Marino }
976*e4b17023SJohn Marino }
977*e4b17023SJohn Marino
978*e4b17023SJohn Marino return dest;
979*e4b17023SJohn Marino }
980*e4b17023SJohn Marino
981*e4b17023SJohn Marino static const char *
alter_output_for_insn(struct queue_elem * ce_elem,struct queue_elem * insn_elem,int alt,int max_op)982*e4b17023SJohn Marino alter_output_for_insn (struct queue_elem *ce_elem,
983*e4b17023SJohn Marino struct queue_elem *insn_elem,
984*e4b17023SJohn Marino int alt, int max_op)
985*e4b17023SJohn Marino {
986*e4b17023SJohn Marino const char *ce_out, *insn_out;
987*e4b17023SJohn Marino char *result, *p;
988*e4b17023SJohn Marino size_t len, ce_len, insn_len;
989*e4b17023SJohn Marino
990*e4b17023SJohn Marino /* ??? Could coordinate with genoutput to not duplicate code here. */
991*e4b17023SJohn Marino
992*e4b17023SJohn Marino ce_out = XSTR (ce_elem->data, 2);
993*e4b17023SJohn Marino insn_out = XTMPL (insn_elem->data, 3);
994*e4b17023SJohn Marino if (!ce_out || *ce_out == '\0')
995*e4b17023SJohn Marino return insn_out;
996*e4b17023SJohn Marino
997*e4b17023SJohn Marino ce_len = strlen (ce_out);
998*e4b17023SJohn Marino insn_len = strlen (insn_out);
999*e4b17023SJohn Marino
1000*e4b17023SJohn Marino if (*insn_out == '*')
1001*e4b17023SJohn Marino /* You must take care of the predicate yourself. */
1002*e4b17023SJohn Marino return insn_out;
1003*e4b17023SJohn Marino
1004*e4b17023SJohn Marino if (*insn_out == '@')
1005*e4b17023SJohn Marino {
1006*e4b17023SJohn Marino len = (ce_len + 1) * alt + insn_len + 1;
1007*e4b17023SJohn Marino p = result = XNEWVEC(char, len);
1008*e4b17023SJohn Marino
1009*e4b17023SJohn Marino do
1010*e4b17023SJohn Marino {
1011*e4b17023SJohn Marino do
1012*e4b17023SJohn Marino *p++ = *insn_out++;
1013*e4b17023SJohn Marino while (ISSPACE ((unsigned char) *insn_out));
1014*e4b17023SJohn Marino
1015*e4b17023SJohn Marino if (*insn_out != '#')
1016*e4b17023SJohn Marino {
1017*e4b17023SJohn Marino p = shift_output_template (p, ce_out, max_op);
1018*e4b17023SJohn Marino *p++ = ' ';
1019*e4b17023SJohn Marino }
1020*e4b17023SJohn Marino
1021*e4b17023SJohn Marino do
1022*e4b17023SJohn Marino *p++ = *insn_out++;
1023*e4b17023SJohn Marino while (*insn_out && *insn_out != '\n');
1024*e4b17023SJohn Marino }
1025*e4b17023SJohn Marino while (*insn_out);
1026*e4b17023SJohn Marino *p = '\0';
1027*e4b17023SJohn Marino }
1028*e4b17023SJohn Marino else
1029*e4b17023SJohn Marino {
1030*e4b17023SJohn Marino len = ce_len + 1 + insn_len + 1;
1031*e4b17023SJohn Marino result = XNEWVEC (char, len);
1032*e4b17023SJohn Marino
1033*e4b17023SJohn Marino p = shift_output_template (result, ce_out, max_op);
1034*e4b17023SJohn Marino *p++ = ' ';
1035*e4b17023SJohn Marino memcpy (p, insn_out, insn_len + 1);
1036*e4b17023SJohn Marino }
1037*e4b17023SJohn Marino
1038*e4b17023SJohn Marino return result;
1039*e4b17023SJohn Marino }
1040*e4b17023SJohn Marino
1041*e4b17023SJohn Marino /* Replicate insns as appropriate for the given DEFINE_COND_EXEC. */
1042*e4b17023SJohn Marino
1043*e4b17023SJohn Marino static void
process_one_cond_exec(struct queue_elem * ce_elem)1044*e4b17023SJohn Marino process_one_cond_exec (struct queue_elem *ce_elem)
1045*e4b17023SJohn Marino {
1046*e4b17023SJohn Marino struct queue_elem *insn_elem;
1047*e4b17023SJohn Marino for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
1048*e4b17023SJohn Marino {
1049*e4b17023SJohn Marino int alternatives, max_operand;
1050*e4b17023SJohn Marino rtx pred, insn, pattern, split;
1051*e4b17023SJohn Marino char *new_name;
1052*e4b17023SJohn Marino int i;
1053*e4b17023SJohn Marino
1054*e4b17023SJohn Marino if (! is_predicable (insn_elem))
1055*e4b17023SJohn Marino continue;
1056*e4b17023SJohn Marino
1057*e4b17023SJohn Marino alternatives = 1;
1058*e4b17023SJohn Marino max_operand = -1;
1059*e4b17023SJohn Marino collect_insn_data (insn_elem->data, &alternatives, &max_operand);
1060*e4b17023SJohn Marino max_operand += 1;
1061*e4b17023SJohn Marino
1062*e4b17023SJohn Marino if (XVECLEN (ce_elem->data, 0) != 1)
1063*e4b17023SJohn Marino {
1064*e4b17023SJohn Marino error_with_line (ce_elem->lineno, "too many patterns in predicate");
1065*e4b17023SJohn Marino return;
1066*e4b17023SJohn Marino }
1067*e4b17023SJohn Marino
1068*e4b17023SJohn Marino pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
1069*e4b17023SJohn Marino pred = alter_predicate_for_insn (pred, alternatives, max_operand,
1070*e4b17023SJohn Marino ce_elem->lineno);
1071*e4b17023SJohn Marino if (pred == NULL)
1072*e4b17023SJohn Marino return;
1073*e4b17023SJohn Marino
1074*e4b17023SJohn Marino /* Construct a new pattern for the new insn. */
1075*e4b17023SJohn Marino insn = copy_rtx (insn_elem->data);
1076*e4b17023SJohn Marino new_name = XNEWVAR (char, strlen XSTR (insn_elem->data, 0) + 4);
1077*e4b17023SJohn Marino sprintf (new_name, "*p %s", XSTR (insn_elem->data, 0));
1078*e4b17023SJohn Marino XSTR (insn, 0) = new_name;
1079*e4b17023SJohn Marino pattern = rtx_alloc (COND_EXEC);
1080*e4b17023SJohn Marino XEXP (pattern, 0) = pred;
1081*e4b17023SJohn Marino if (XVECLEN (insn, 1) == 1)
1082*e4b17023SJohn Marino {
1083*e4b17023SJohn Marino XEXP (pattern, 1) = XVECEXP (insn, 1, 0);
1084*e4b17023SJohn Marino XVECEXP (insn, 1, 0) = pattern;
1085*e4b17023SJohn Marino PUT_NUM_ELEM (XVEC (insn, 1), 1);
1086*e4b17023SJohn Marino }
1087*e4b17023SJohn Marino else
1088*e4b17023SJohn Marino {
1089*e4b17023SJohn Marino XEXP (pattern, 1) = rtx_alloc (PARALLEL);
1090*e4b17023SJohn Marino XVEC (XEXP (pattern, 1), 0) = XVEC (insn, 1);
1091*e4b17023SJohn Marino XVEC (insn, 1) = rtvec_alloc (1);
1092*e4b17023SJohn Marino XVECEXP (insn, 1, 0) = pattern;
1093*e4b17023SJohn Marino }
1094*e4b17023SJohn Marino
1095*e4b17023SJohn Marino XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
1096*e4b17023SJohn Marino XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
1097*e4b17023SJohn Marino alternatives, max_operand);
1098*e4b17023SJohn Marino alter_attrs_for_insn (insn);
1099*e4b17023SJohn Marino
1100*e4b17023SJohn Marino /* Put the new pattern on the `other' list so that it
1101*e4b17023SJohn Marino (a) is not reprocessed by other define_cond_exec patterns
1102*e4b17023SJohn Marino (b) appears after all normal define_insn patterns.
1103*e4b17023SJohn Marino
1104*e4b17023SJohn Marino ??? B is debatable. If one has normal insns that match
1105*e4b17023SJohn Marino cond_exec patterns, they will be preferred over these
1106*e4b17023SJohn Marino generated patterns. Whether this matters in practice, or if
1107*e4b17023SJohn Marino it's a good thing, or whether we should thread these new
1108*e4b17023SJohn Marino patterns into the define_insn chain just after their generator
1109*e4b17023SJohn Marino is something we'll have to experiment with. */
1110*e4b17023SJohn Marino
1111*e4b17023SJohn Marino queue_pattern (insn, &other_tail, insn_elem->filename,
1112*e4b17023SJohn Marino insn_elem->lineno);
1113*e4b17023SJohn Marino
1114*e4b17023SJohn Marino if (!insn_elem->split)
1115*e4b17023SJohn Marino continue;
1116*e4b17023SJohn Marino
1117*e4b17023SJohn Marino /* If the original insn came from a define_insn_and_split,
1118*e4b17023SJohn Marino generate a new split to handle the predicated insn. */
1119*e4b17023SJohn Marino split = copy_rtx (insn_elem->split->data);
1120*e4b17023SJohn Marino /* Predicate the pattern matched by the split. */
1121*e4b17023SJohn Marino pattern = rtx_alloc (COND_EXEC);
1122*e4b17023SJohn Marino XEXP (pattern, 0) = pred;
1123*e4b17023SJohn Marino if (XVECLEN (split, 0) == 1)
1124*e4b17023SJohn Marino {
1125*e4b17023SJohn Marino XEXP (pattern, 1) = XVECEXP (split, 0, 0);
1126*e4b17023SJohn Marino XVECEXP (split, 0, 0) = pattern;
1127*e4b17023SJohn Marino PUT_NUM_ELEM (XVEC (split, 0), 1);
1128*e4b17023SJohn Marino }
1129*e4b17023SJohn Marino else
1130*e4b17023SJohn Marino {
1131*e4b17023SJohn Marino XEXP (pattern, 1) = rtx_alloc (PARALLEL);
1132*e4b17023SJohn Marino XVEC (XEXP (pattern, 1), 0) = XVEC (split, 0);
1133*e4b17023SJohn Marino XVEC (split, 0) = rtvec_alloc (1);
1134*e4b17023SJohn Marino XVECEXP (split, 0, 0) = pattern;
1135*e4b17023SJohn Marino }
1136*e4b17023SJohn Marino /* Predicate all of the insns generated by the split. */
1137*e4b17023SJohn Marino for (i = 0; i < XVECLEN (split, 2); i++)
1138*e4b17023SJohn Marino {
1139*e4b17023SJohn Marino pattern = rtx_alloc (COND_EXEC);
1140*e4b17023SJohn Marino XEXP (pattern, 0) = pred;
1141*e4b17023SJohn Marino XEXP (pattern, 1) = XVECEXP (split, 2, i);
1142*e4b17023SJohn Marino XVECEXP (split, 2, i) = pattern;
1143*e4b17023SJohn Marino }
1144*e4b17023SJohn Marino /* Add the new split to the queue. */
1145*e4b17023SJohn Marino queue_pattern (split, &other_tail, read_md_filename,
1146*e4b17023SJohn Marino insn_elem->split->lineno);
1147*e4b17023SJohn Marino }
1148*e4b17023SJohn Marino }
1149*e4b17023SJohn Marino
1150*e4b17023SJohn Marino /* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
1151*e4b17023SJohn Marino patterns appropriately. */
1152*e4b17023SJohn Marino
1153*e4b17023SJohn Marino static void
process_define_cond_exec(void)1154*e4b17023SJohn Marino process_define_cond_exec (void)
1155*e4b17023SJohn Marino {
1156*e4b17023SJohn Marino struct queue_elem *elem;
1157*e4b17023SJohn Marino
1158*e4b17023SJohn Marino identify_predicable_attribute ();
1159*e4b17023SJohn Marino if (have_error)
1160*e4b17023SJohn Marino return;
1161*e4b17023SJohn Marino
1162*e4b17023SJohn Marino for (elem = define_cond_exec_queue; elem ; elem = elem->next)
1163*e4b17023SJohn Marino process_one_cond_exec (elem);
1164*e4b17023SJohn Marino }
1165*e4b17023SJohn Marino
1166*e4b17023SJohn Marino /* A read_md_files callback for reading an rtx. */
1167*e4b17023SJohn Marino
1168*e4b17023SJohn Marino static void
rtx_handle_directive(int lineno,const char * rtx_name)1169*e4b17023SJohn Marino rtx_handle_directive (int lineno, const char *rtx_name)
1170*e4b17023SJohn Marino {
1171*e4b17023SJohn Marino rtx queue, x;
1172*e4b17023SJohn Marino
1173*e4b17023SJohn Marino if (read_rtx (rtx_name, &queue))
1174*e4b17023SJohn Marino for (x = queue; x; x = XEXP (x, 1))
1175*e4b17023SJohn Marino process_rtx (XEXP (x, 0), lineno);
1176*e4b17023SJohn Marino }
1177*e4b17023SJohn Marino
1178*e4b17023SJohn Marino /* Comparison function for the mnemonic hash table. */
1179*e4b17023SJohn Marino
1180*e4b17023SJohn Marino static int
htab_eq_string(const void * s1,const void * s2)1181*e4b17023SJohn Marino htab_eq_string (const void *s1, const void *s2)
1182*e4b17023SJohn Marino {
1183*e4b17023SJohn Marino return strcmp ((const char*)s1, (const char*)s2) == 0;
1184*e4b17023SJohn Marino }
1185*e4b17023SJohn Marino
1186*e4b17023SJohn Marino /* Add mnemonic STR with length LEN to the mnemonic hash table
1187*e4b17023SJohn Marino MNEMONIC_HTAB. A trailing zero end character is appendend to STR
1188*e4b17023SJohn Marino and a permanent heap copy of STR is created. */
1189*e4b17023SJohn Marino
1190*e4b17023SJohn Marino static void
add_mnemonic_string(htab_t mnemonic_htab,const char * str,int len)1191*e4b17023SJohn Marino add_mnemonic_string (htab_t mnemonic_htab, const char *str, int len)
1192*e4b17023SJohn Marino {
1193*e4b17023SJohn Marino char *new_str;
1194*e4b17023SJohn Marino void **slot;
1195*e4b17023SJohn Marino char *str_zero = (char*)alloca (len + 1);
1196*e4b17023SJohn Marino
1197*e4b17023SJohn Marino memcpy (str_zero, str, len);
1198*e4b17023SJohn Marino str_zero[len] = '\0';
1199*e4b17023SJohn Marino
1200*e4b17023SJohn Marino slot = htab_find_slot (mnemonic_htab, str_zero, INSERT);
1201*e4b17023SJohn Marino
1202*e4b17023SJohn Marino if (*slot)
1203*e4b17023SJohn Marino return;
1204*e4b17023SJohn Marino
1205*e4b17023SJohn Marino /* Not found; create a permanent copy and add it to the hash table. */
1206*e4b17023SJohn Marino new_str = XNEWVAR (char, len + 1);
1207*e4b17023SJohn Marino memcpy (new_str, str_zero, len + 1);
1208*e4b17023SJohn Marino *slot = new_str;
1209*e4b17023SJohn Marino }
1210*e4b17023SJohn Marino
1211*e4b17023SJohn Marino /* Scan INSN for mnemonic strings and add them to the mnemonic hash
1212*e4b17023SJohn Marino table in MNEMONIC_HTAB.
1213*e4b17023SJohn Marino
1214*e4b17023SJohn Marino The mnemonics cannot be found if they are emitted using C code.
1215*e4b17023SJohn Marino
1216*e4b17023SJohn Marino If a mnemonic string contains ';' or a newline the string assumed
1217*e4b17023SJohn Marino to consist of more than a single instruction. The attribute value
1218*e4b17023SJohn Marino will then be set to the user defined default value. */
1219*e4b17023SJohn Marino
1220*e4b17023SJohn Marino static void
gen_mnemonic_setattr(htab_t mnemonic_htab,rtx insn)1221*e4b17023SJohn Marino gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn)
1222*e4b17023SJohn Marino {
1223*e4b17023SJohn Marino const char *template_code, *cp;
1224*e4b17023SJohn Marino int i;
1225*e4b17023SJohn Marino int vec_len;
1226*e4b17023SJohn Marino rtx set_attr;
1227*e4b17023SJohn Marino char *attr_name;
1228*e4b17023SJohn Marino rtvec new_vec;
1229*e4b17023SJohn Marino
1230*e4b17023SJohn Marino template_code = XTMPL (insn, 3);
1231*e4b17023SJohn Marino
1232*e4b17023SJohn Marino /* Skip patterns which use C code to emit the template. */
1233*e4b17023SJohn Marino if (template_code[0] == '*')
1234*e4b17023SJohn Marino return;
1235*e4b17023SJohn Marino
1236*e4b17023SJohn Marino if (template_code[0] == '@')
1237*e4b17023SJohn Marino cp = &template_code[1];
1238*e4b17023SJohn Marino else
1239*e4b17023SJohn Marino cp = &template_code[0];
1240*e4b17023SJohn Marino
1241*e4b17023SJohn Marino for (i = 0; *cp; )
1242*e4b17023SJohn Marino {
1243*e4b17023SJohn Marino const char *ep, *sp;
1244*e4b17023SJohn Marino int size = 0;
1245*e4b17023SJohn Marino
1246*e4b17023SJohn Marino while (ISSPACE (*cp))
1247*e4b17023SJohn Marino cp++;
1248*e4b17023SJohn Marino
1249*e4b17023SJohn Marino for (ep = sp = cp; !IS_VSPACE (*ep) && *ep != '\0'; ++ep)
1250*e4b17023SJohn Marino if (!ISSPACE (*ep))
1251*e4b17023SJohn Marino sp = ep + 1;
1252*e4b17023SJohn Marino
1253*e4b17023SJohn Marino if (i > 0)
1254*e4b17023SJohn Marino obstack_1grow (&string_obstack, ',');
1255*e4b17023SJohn Marino
1256*e4b17023SJohn Marino while (cp < sp && ((*cp >= '0' && *cp <= '9')
1257*e4b17023SJohn Marino || (*cp >= 'a' && *cp <= 'z')))
1258*e4b17023SJohn Marino
1259*e4b17023SJohn Marino {
1260*e4b17023SJohn Marino obstack_1grow (&string_obstack, *cp);
1261*e4b17023SJohn Marino cp++;
1262*e4b17023SJohn Marino size++;
1263*e4b17023SJohn Marino }
1264*e4b17023SJohn Marino
1265*e4b17023SJohn Marino while (cp < sp)
1266*e4b17023SJohn Marino {
1267*e4b17023SJohn Marino if (*cp == ';' || (*cp == '\\' && cp[1] == 'n'))
1268*e4b17023SJohn Marino {
1269*e4b17023SJohn Marino /* Don't set a value if there are more than one
1270*e4b17023SJohn Marino instruction in the string. */
1271*e4b17023SJohn Marino obstack_next_free (&string_obstack) =
1272*e4b17023SJohn Marino obstack_next_free (&string_obstack) - size;
1273*e4b17023SJohn Marino size = 0;
1274*e4b17023SJohn Marino
1275*e4b17023SJohn Marino cp = sp;
1276*e4b17023SJohn Marino break;
1277*e4b17023SJohn Marino }
1278*e4b17023SJohn Marino cp++;
1279*e4b17023SJohn Marino }
1280*e4b17023SJohn Marino if (size == 0)
1281*e4b17023SJohn Marino obstack_1grow (&string_obstack, '*');
1282*e4b17023SJohn Marino else
1283*e4b17023SJohn Marino add_mnemonic_string (mnemonic_htab,
1284*e4b17023SJohn Marino obstack_next_free (&string_obstack) - size,
1285*e4b17023SJohn Marino size);
1286*e4b17023SJohn Marino i++;
1287*e4b17023SJohn Marino }
1288*e4b17023SJohn Marino
1289*e4b17023SJohn Marino /* An insn definition might emit an empty string. */
1290*e4b17023SJohn Marino if (obstack_object_size (&string_obstack) == 0)
1291*e4b17023SJohn Marino return;
1292*e4b17023SJohn Marino
1293*e4b17023SJohn Marino obstack_1grow (&string_obstack, '\0');
1294*e4b17023SJohn Marino
1295*e4b17023SJohn Marino set_attr = rtx_alloc (SET_ATTR);
1296*e4b17023SJohn Marino XSTR (set_attr, 1) = XOBFINISH (&string_obstack, char *);
1297*e4b17023SJohn Marino attr_name = XNEWVAR (char, strlen (MNEMONIC_ATTR_NAME) + 1);
1298*e4b17023SJohn Marino strcpy (attr_name, MNEMONIC_ATTR_NAME);
1299*e4b17023SJohn Marino XSTR (set_attr, 0) = attr_name;
1300*e4b17023SJohn Marino
1301*e4b17023SJohn Marino if (!XVEC (insn, 4))
1302*e4b17023SJohn Marino vec_len = 0;
1303*e4b17023SJohn Marino else
1304*e4b17023SJohn Marino vec_len = XVECLEN (insn, 4);
1305*e4b17023SJohn Marino
1306*e4b17023SJohn Marino new_vec = rtvec_alloc (vec_len + 1);
1307*e4b17023SJohn Marino for (i = 0; i < vec_len; i++)
1308*e4b17023SJohn Marino RTVEC_ELT (new_vec, i) = XVECEXP (insn, 4, i);
1309*e4b17023SJohn Marino RTVEC_ELT (new_vec, vec_len) = set_attr;
1310*e4b17023SJohn Marino XVEC (insn, 4) = new_vec;
1311*e4b17023SJohn Marino }
1312*e4b17023SJohn Marino
1313*e4b17023SJohn Marino /* This function is called for the elements in the mnemonic hashtable
1314*e4b17023SJohn Marino and generates a comma separated list of the mnemonics. */
1315*e4b17023SJohn Marino
1316*e4b17023SJohn Marino static int
mnemonic_htab_callback(void ** slot,void * info ATTRIBUTE_UNUSED)1317*e4b17023SJohn Marino mnemonic_htab_callback (void **slot, void *info ATTRIBUTE_UNUSED)
1318*e4b17023SJohn Marino {
1319*e4b17023SJohn Marino obstack_grow (&string_obstack, (char*)*slot, strlen ((char*)*slot));
1320*e4b17023SJohn Marino obstack_1grow (&string_obstack, ',');
1321*e4b17023SJohn Marino return 1;
1322*e4b17023SJohn Marino }
1323*e4b17023SJohn Marino
1324*e4b17023SJohn Marino /* Generate (set_attr "mnemonic" "..") RTXs and append them to every
1325*e4b17023SJohn Marino insn definition in case the back end requests it by defining the
1326*e4b17023SJohn Marino mnemonic attribute. The values for the attribute will be extracted
1327*e4b17023SJohn Marino from the output patterns of the insn definitions as far as
1328*e4b17023SJohn Marino possible. */
1329*e4b17023SJohn Marino
1330*e4b17023SJohn Marino static void
gen_mnemonic_attr(void)1331*e4b17023SJohn Marino gen_mnemonic_attr (void)
1332*e4b17023SJohn Marino {
1333*e4b17023SJohn Marino struct queue_elem *elem;
1334*e4b17023SJohn Marino rtx mnemonic_attr = NULL;
1335*e4b17023SJohn Marino htab_t mnemonic_htab;
1336*e4b17023SJohn Marino const char *str, *p;
1337*e4b17023SJohn Marino int i;
1338*e4b17023SJohn Marino
1339*e4b17023SJohn Marino if (have_error)
1340*e4b17023SJohn Marino return;
1341*e4b17023SJohn Marino
1342*e4b17023SJohn Marino /* Look for the DEFINE_ATTR for `mnemonic'. */
1343*e4b17023SJohn Marino for (elem = define_attr_queue; elem != *define_attr_tail; elem = elem->next)
1344*e4b17023SJohn Marino if (GET_CODE (elem->data) == DEFINE_ATTR
1345*e4b17023SJohn Marino && strcmp (XSTR (elem->data, 0), MNEMONIC_ATTR_NAME) == 0)
1346*e4b17023SJohn Marino {
1347*e4b17023SJohn Marino mnemonic_attr = elem->data;
1348*e4b17023SJohn Marino break;
1349*e4b17023SJohn Marino }
1350*e4b17023SJohn Marino
1351*e4b17023SJohn Marino /* A (define_attr "mnemonic" "...") indicates that the back-end
1352*e4b17023SJohn Marino wants a mnemonic attribute to be generated. */
1353*e4b17023SJohn Marino if (!mnemonic_attr)
1354*e4b17023SJohn Marino return;
1355*e4b17023SJohn Marino
1356*e4b17023SJohn Marino mnemonic_htab = htab_create_alloc (MNEMONIC_HTAB_SIZE, htab_hash_string,
1357*e4b17023SJohn Marino htab_eq_string, 0, xcalloc, free);
1358*e4b17023SJohn Marino
1359*e4b17023SJohn Marino for (elem = define_insn_queue; elem; elem = elem->next)
1360*e4b17023SJohn Marino {
1361*e4b17023SJohn Marino rtx insn = elem->data;
1362*e4b17023SJohn Marino bool found = false;
1363*e4b17023SJohn Marino
1364*e4b17023SJohn Marino /* Check if the insn definition already has
1365*e4b17023SJohn Marino (set_attr "mnemonic" ...). */
1366*e4b17023SJohn Marino if (XVEC (insn, 4))
1367*e4b17023SJohn Marino for (i = 0; i < XVECLEN (insn, 4); i++)
1368*e4b17023SJohn Marino if (strcmp (XSTR (XVECEXP (insn, 4, i), 0), MNEMONIC_ATTR_NAME) == 0)
1369*e4b17023SJohn Marino {
1370*e4b17023SJohn Marino found = true;
1371*e4b17023SJohn Marino break;
1372*e4b17023SJohn Marino }
1373*e4b17023SJohn Marino
1374*e4b17023SJohn Marino if (!found)
1375*e4b17023SJohn Marino gen_mnemonic_setattr (mnemonic_htab, insn);
1376*e4b17023SJohn Marino }
1377*e4b17023SJohn Marino
1378*e4b17023SJohn Marino /* Add the user defined values to the hash table. */
1379*e4b17023SJohn Marino str = XSTR (mnemonic_attr, 1);
1380*e4b17023SJohn Marino while ((p = scan_comma_elt (&str)) != NULL)
1381*e4b17023SJohn Marino add_mnemonic_string (mnemonic_htab, p, str - p);
1382*e4b17023SJohn Marino
1383*e4b17023SJohn Marino htab_traverse (mnemonic_htab, mnemonic_htab_callback, NULL);
1384*e4b17023SJohn Marino
1385*e4b17023SJohn Marino /* Replace the last ',' with the zero end character. */
1386*e4b17023SJohn Marino *((char *)obstack_next_free (&string_obstack) - 1) = '\0';
1387*e4b17023SJohn Marino XSTR (mnemonic_attr, 1) = XOBFINISH (&string_obstack, char *);
1388*e4b17023SJohn Marino }
1389*e4b17023SJohn Marino
1390*e4b17023SJohn Marino /* The entry point for initializing the reader. */
1391*e4b17023SJohn Marino
1392*e4b17023SJohn Marino bool
init_rtx_reader_args_cb(int argc,char ** argv,bool (* parse_opt)(const char *))1393*e4b17023SJohn Marino init_rtx_reader_args_cb (int argc, char **argv,
1394*e4b17023SJohn Marino bool (*parse_opt) (const char *))
1395*e4b17023SJohn Marino {
1396*e4b17023SJohn Marino /* Prepare to read input. */
1397*e4b17023SJohn Marino condition_table = htab_create (500, hash_c_test, cmp_c_test, NULL);
1398*e4b17023SJohn Marino init_predicate_table ();
1399*e4b17023SJohn Marino obstack_init (rtl_obstack);
1400*e4b17023SJohn Marino sequence_num = 0;
1401*e4b17023SJohn Marino
1402*e4b17023SJohn Marino read_md_files (argc, argv, parse_opt, rtx_handle_directive);
1403*e4b17023SJohn Marino
1404*e4b17023SJohn Marino /* Process define_cond_exec patterns. */
1405*e4b17023SJohn Marino if (define_cond_exec_queue != NULL)
1406*e4b17023SJohn Marino process_define_cond_exec ();
1407*e4b17023SJohn Marino
1408*e4b17023SJohn Marino if (define_attr_queue != NULL)
1409*e4b17023SJohn Marino gen_mnemonic_attr ();
1410*e4b17023SJohn Marino
1411*e4b17023SJohn Marino return !have_error;
1412*e4b17023SJohn Marino }
1413*e4b17023SJohn Marino
1414*e4b17023SJohn Marino /* Programs that don't have their own options can use this entry point
1415*e4b17023SJohn Marino instead. */
1416*e4b17023SJohn Marino bool
init_rtx_reader_args(int argc,char ** argv)1417*e4b17023SJohn Marino init_rtx_reader_args (int argc, char **argv)
1418*e4b17023SJohn Marino {
1419*e4b17023SJohn Marino return init_rtx_reader_args_cb (argc, argv, 0);
1420*e4b17023SJohn Marino }
1421*e4b17023SJohn Marino
1422*e4b17023SJohn Marino /* The entry point for reading a single rtx from an md file. */
1423*e4b17023SJohn Marino
1424*e4b17023SJohn Marino rtx
read_md_rtx(int * lineno,int * seqnr)1425*e4b17023SJohn Marino read_md_rtx (int *lineno, int *seqnr)
1426*e4b17023SJohn Marino {
1427*e4b17023SJohn Marino struct queue_elem **queue, *elem;
1428*e4b17023SJohn Marino rtx desc;
1429*e4b17023SJohn Marino
1430*e4b17023SJohn Marino discard:
1431*e4b17023SJohn Marino
1432*e4b17023SJohn Marino /* Read all patterns from a given queue before moving on to the next. */
1433*e4b17023SJohn Marino if (define_attr_queue != NULL)
1434*e4b17023SJohn Marino queue = &define_attr_queue;
1435*e4b17023SJohn Marino else if (define_pred_queue != NULL)
1436*e4b17023SJohn Marino queue = &define_pred_queue;
1437*e4b17023SJohn Marino else if (define_insn_queue != NULL)
1438*e4b17023SJohn Marino queue = &define_insn_queue;
1439*e4b17023SJohn Marino else if (other_queue != NULL)
1440*e4b17023SJohn Marino queue = &other_queue;
1441*e4b17023SJohn Marino else
1442*e4b17023SJohn Marino return NULL_RTX;
1443*e4b17023SJohn Marino
1444*e4b17023SJohn Marino elem = *queue;
1445*e4b17023SJohn Marino *queue = elem->next;
1446*e4b17023SJohn Marino desc = elem->data;
1447*e4b17023SJohn Marino read_md_filename = elem->filename;
1448*e4b17023SJohn Marino *lineno = elem->lineno;
1449*e4b17023SJohn Marino *seqnr = sequence_num;
1450*e4b17023SJohn Marino
1451*e4b17023SJohn Marino free (elem);
1452*e4b17023SJohn Marino
1453*e4b17023SJohn Marino /* Discard insn patterns which we know can never match (because
1454*e4b17023SJohn Marino their C test is provably always false). If insn_elision is
1455*e4b17023SJohn Marino false, our caller needs to see all the patterns. Note that the
1456*e4b17023SJohn Marino elided patterns are never counted by the sequence numbering; it
1457*e4b17023SJohn Marino is the caller's responsibility, when insn_elision is false, not
1458*e4b17023SJohn Marino to use elided pattern numbers for anything. */
1459*e4b17023SJohn Marino switch (GET_CODE (desc))
1460*e4b17023SJohn Marino {
1461*e4b17023SJohn Marino case DEFINE_INSN:
1462*e4b17023SJohn Marino case DEFINE_EXPAND:
1463*e4b17023SJohn Marino if (maybe_eval_c_test (XSTR (desc, 2)) != 0)
1464*e4b17023SJohn Marino sequence_num++;
1465*e4b17023SJohn Marino else if (insn_elision)
1466*e4b17023SJohn Marino goto discard;
1467*e4b17023SJohn Marino
1468*e4b17023SJohn Marino /* *seqnr is used here so the name table will match caller's
1469*e4b17023SJohn Marino idea of insn numbering, whether or not elision is active. */
1470*e4b17023SJohn Marino record_insn_name (*seqnr, XSTR (desc, 0));
1471*e4b17023SJohn Marino break;
1472*e4b17023SJohn Marino
1473*e4b17023SJohn Marino case DEFINE_SPLIT:
1474*e4b17023SJohn Marino case DEFINE_PEEPHOLE:
1475*e4b17023SJohn Marino case DEFINE_PEEPHOLE2:
1476*e4b17023SJohn Marino if (maybe_eval_c_test (XSTR (desc, 1)) != 0)
1477*e4b17023SJohn Marino sequence_num++;
1478*e4b17023SJohn Marino else if (insn_elision)
1479*e4b17023SJohn Marino goto discard;
1480*e4b17023SJohn Marino break;
1481*e4b17023SJohn Marino
1482*e4b17023SJohn Marino default:
1483*e4b17023SJohn Marino break;
1484*e4b17023SJohn Marino }
1485*e4b17023SJohn Marino
1486*e4b17023SJohn Marino return desc;
1487*e4b17023SJohn Marino }
1488*e4b17023SJohn Marino
1489*e4b17023SJohn Marino /* Helper functions for insn elision. */
1490*e4b17023SJohn Marino
1491*e4b17023SJohn Marino /* Compute a hash function of a c_test structure, which is keyed
1492*e4b17023SJohn Marino by its ->expr field. */
1493*e4b17023SJohn Marino hashval_t
hash_c_test(const void * x)1494*e4b17023SJohn Marino hash_c_test (const void *x)
1495*e4b17023SJohn Marino {
1496*e4b17023SJohn Marino const struct c_test *a = (const struct c_test *) x;
1497*e4b17023SJohn Marino const unsigned char *base, *s = (const unsigned char *) a->expr;
1498*e4b17023SJohn Marino hashval_t hash;
1499*e4b17023SJohn Marino unsigned char c;
1500*e4b17023SJohn Marino unsigned int len;
1501*e4b17023SJohn Marino
1502*e4b17023SJohn Marino base = s;
1503*e4b17023SJohn Marino hash = 0;
1504*e4b17023SJohn Marino
1505*e4b17023SJohn Marino while ((c = *s++) != '\0')
1506*e4b17023SJohn Marino {
1507*e4b17023SJohn Marino hash += c + (c << 17);
1508*e4b17023SJohn Marino hash ^= hash >> 2;
1509*e4b17023SJohn Marino }
1510*e4b17023SJohn Marino
1511*e4b17023SJohn Marino len = s - base;
1512*e4b17023SJohn Marino hash += len + (len << 17);
1513*e4b17023SJohn Marino hash ^= hash >> 2;
1514*e4b17023SJohn Marino
1515*e4b17023SJohn Marino return hash;
1516*e4b17023SJohn Marino }
1517*e4b17023SJohn Marino
1518*e4b17023SJohn Marino /* Compare two c_test expression structures. */
1519*e4b17023SJohn Marino int
cmp_c_test(const void * x,const void * y)1520*e4b17023SJohn Marino cmp_c_test (const void *x, const void *y)
1521*e4b17023SJohn Marino {
1522*e4b17023SJohn Marino const struct c_test *a = (const struct c_test *) x;
1523*e4b17023SJohn Marino const struct c_test *b = (const struct c_test *) y;
1524*e4b17023SJohn Marino
1525*e4b17023SJohn Marino return !strcmp (a->expr, b->expr);
1526*e4b17023SJohn Marino }
1527*e4b17023SJohn Marino
1528*e4b17023SJohn Marino /* Given a string representing a C test expression, look it up in the
1529*e4b17023SJohn Marino condition_table and report whether or not its value is known
1530*e4b17023SJohn Marino at compile time. Returns a tristate: 1 for known true, 0 for
1531*e4b17023SJohn Marino known false, -1 for unknown. */
1532*e4b17023SJohn Marino int
maybe_eval_c_test(const char * expr)1533*e4b17023SJohn Marino maybe_eval_c_test (const char *expr)
1534*e4b17023SJohn Marino {
1535*e4b17023SJohn Marino const struct c_test *test;
1536*e4b17023SJohn Marino struct c_test dummy;
1537*e4b17023SJohn Marino
1538*e4b17023SJohn Marino if (expr[0] == 0)
1539*e4b17023SJohn Marino return 1;
1540*e4b17023SJohn Marino
1541*e4b17023SJohn Marino dummy.expr = expr;
1542*e4b17023SJohn Marino test = (const struct c_test *)htab_find (condition_table, &dummy);
1543*e4b17023SJohn Marino if (!test)
1544*e4b17023SJohn Marino return -1;
1545*e4b17023SJohn Marino return test->value;
1546*e4b17023SJohn Marino }
1547*e4b17023SJohn Marino
1548*e4b17023SJohn Marino /* Record the C test expression EXPR in the condition_table, with
1549*e4b17023SJohn Marino value VAL. Duplicates clobber previous entries. */
1550*e4b17023SJohn Marino
1551*e4b17023SJohn Marino void
add_c_test(const char * expr,int value)1552*e4b17023SJohn Marino add_c_test (const char *expr, int value)
1553*e4b17023SJohn Marino {
1554*e4b17023SJohn Marino struct c_test *test;
1555*e4b17023SJohn Marino
1556*e4b17023SJohn Marino if (expr[0] == 0)
1557*e4b17023SJohn Marino return;
1558*e4b17023SJohn Marino
1559*e4b17023SJohn Marino test = XNEW (struct c_test);
1560*e4b17023SJohn Marino test->expr = expr;
1561*e4b17023SJohn Marino test->value = value;
1562*e4b17023SJohn Marino
1563*e4b17023SJohn Marino *(htab_find_slot (condition_table, test, INSERT)) = test;
1564*e4b17023SJohn Marino }
1565*e4b17023SJohn Marino
1566*e4b17023SJohn Marino /* For every C test, call CALLBACK with two arguments: a pointer to
1567*e4b17023SJohn Marino the condition structure and INFO. Stops when CALLBACK returns zero. */
1568*e4b17023SJohn Marino void
traverse_c_tests(htab_trav callback,void * info)1569*e4b17023SJohn Marino traverse_c_tests (htab_trav callback, void *info)
1570*e4b17023SJohn Marino {
1571*e4b17023SJohn Marino if (condition_table)
1572*e4b17023SJohn Marino htab_traverse (condition_table, callback, info);
1573*e4b17023SJohn Marino }
1574*e4b17023SJohn Marino
1575*e4b17023SJohn Marino /* Helper functions for define_predicate and define_special_predicate
1576*e4b17023SJohn Marino processing. Shared between genrecog.c and genpreds.c. */
1577*e4b17023SJohn Marino
1578*e4b17023SJohn Marino static htab_t predicate_table;
1579*e4b17023SJohn Marino struct pred_data *first_predicate;
1580*e4b17023SJohn Marino static struct pred_data **last_predicate = &first_predicate;
1581*e4b17023SJohn Marino
1582*e4b17023SJohn Marino static hashval_t
hash_struct_pred_data(const void * ptr)1583*e4b17023SJohn Marino hash_struct_pred_data (const void *ptr)
1584*e4b17023SJohn Marino {
1585*e4b17023SJohn Marino return htab_hash_string (((const struct pred_data *)ptr)->name);
1586*e4b17023SJohn Marino }
1587*e4b17023SJohn Marino
1588*e4b17023SJohn Marino static int
eq_struct_pred_data(const void * a,const void * b)1589*e4b17023SJohn Marino eq_struct_pred_data (const void *a, const void *b)
1590*e4b17023SJohn Marino {
1591*e4b17023SJohn Marino return !strcmp (((const struct pred_data *)a)->name,
1592*e4b17023SJohn Marino ((const struct pred_data *)b)->name);
1593*e4b17023SJohn Marino }
1594*e4b17023SJohn Marino
1595*e4b17023SJohn Marino struct pred_data *
lookup_predicate(const char * name)1596*e4b17023SJohn Marino lookup_predicate (const char *name)
1597*e4b17023SJohn Marino {
1598*e4b17023SJohn Marino struct pred_data key;
1599*e4b17023SJohn Marino key.name = name;
1600*e4b17023SJohn Marino return (struct pred_data *) htab_find (predicate_table, &key);
1601*e4b17023SJohn Marino }
1602*e4b17023SJohn Marino
1603*e4b17023SJohn Marino /* Record that predicate PRED can accept CODE. */
1604*e4b17023SJohn Marino
1605*e4b17023SJohn Marino void
add_predicate_code(struct pred_data * pred,enum rtx_code code)1606*e4b17023SJohn Marino add_predicate_code (struct pred_data *pred, enum rtx_code code)
1607*e4b17023SJohn Marino {
1608*e4b17023SJohn Marino if (!pred->codes[code])
1609*e4b17023SJohn Marino {
1610*e4b17023SJohn Marino pred->num_codes++;
1611*e4b17023SJohn Marino pred->codes[code] = true;
1612*e4b17023SJohn Marino
1613*e4b17023SJohn Marino if (GET_RTX_CLASS (code) != RTX_CONST_OBJ)
1614*e4b17023SJohn Marino pred->allows_non_const = true;
1615*e4b17023SJohn Marino
1616*e4b17023SJohn Marino if (code != REG
1617*e4b17023SJohn Marino && code != SUBREG
1618*e4b17023SJohn Marino && code != MEM
1619*e4b17023SJohn Marino && code != CONCAT
1620*e4b17023SJohn Marino && code != PARALLEL
1621*e4b17023SJohn Marino && code != STRICT_LOW_PART)
1622*e4b17023SJohn Marino pred->allows_non_lvalue = true;
1623*e4b17023SJohn Marino
1624*e4b17023SJohn Marino if (pred->num_codes == 1)
1625*e4b17023SJohn Marino pred->singleton = code;
1626*e4b17023SJohn Marino else if (pred->num_codes == 2)
1627*e4b17023SJohn Marino pred->singleton = UNKNOWN;
1628*e4b17023SJohn Marino }
1629*e4b17023SJohn Marino }
1630*e4b17023SJohn Marino
1631*e4b17023SJohn Marino void
add_predicate(struct pred_data * pred)1632*e4b17023SJohn Marino add_predicate (struct pred_data *pred)
1633*e4b17023SJohn Marino {
1634*e4b17023SJohn Marino void **slot = htab_find_slot (predicate_table, pred, INSERT);
1635*e4b17023SJohn Marino if (*slot)
1636*e4b17023SJohn Marino {
1637*e4b17023SJohn Marino error ("duplicate predicate definition for '%s'", pred->name);
1638*e4b17023SJohn Marino return;
1639*e4b17023SJohn Marino }
1640*e4b17023SJohn Marino *slot = pred;
1641*e4b17023SJohn Marino *last_predicate = pred;
1642*e4b17023SJohn Marino last_predicate = &pred->next;
1643*e4b17023SJohn Marino }
1644*e4b17023SJohn Marino
1645*e4b17023SJohn Marino /* This array gives the initial content of the predicate table. It
1646*e4b17023SJohn Marino has entries for all predicates defined in recog.c. */
1647*e4b17023SJohn Marino
1648*e4b17023SJohn Marino struct std_pred_table
1649*e4b17023SJohn Marino {
1650*e4b17023SJohn Marino const char *name;
1651*e4b17023SJohn Marino bool special;
1652*e4b17023SJohn Marino bool allows_const_p;
1653*e4b17023SJohn Marino RTX_CODE codes[NUM_RTX_CODE];
1654*e4b17023SJohn Marino };
1655*e4b17023SJohn Marino
1656*e4b17023SJohn Marino static const struct std_pred_table std_preds[] = {
1657*e4b17023SJohn Marino {"general_operand", false, true, {SUBREG, REG, MEM}},
1658*e4b17023SJohn Marino {"address_operand", true, true, {SUBREG, REG, MEM, PLUS, MINUS, MULT}},
1659*e4b17023SJohn Marino {"register_operand", false, false, {SUBREG, REG}},
1660*e4b17023SJohn Marino {"pmode_register_operand", true, false, {SUBREG, REG}},
1661*e4b17023SJohn Marino {"scratch_operand", false, false, {SCRATCH, REG}},
1662*e4b17023SJohn Marino {"immediate_operand", false, true, {UNKNOWN}},
1663*e4b17023SJohn Marino {"const_int_operand", false, false, {CONST_INT}},
1664*e4b17023SJohn Marino {"const_double_operand", false, false, {CONST_INT, CONST_DOUBLE}},
1665*e4b17023SJohn Marino {"nonimmediate_operand", false, false, {SUBREG, REG, MEM}},
1666*e4b17023SJohn Marino {"nonmemory_operand", false, true, {SUBREG, REG}},
1667*e4b17023SJohn Marino {"push_operand", false, false, {MEM}},
1668*e4b17023SJohn Marino {"pop_operand", false, false, {MEM}},
1669*e4b17023SJohn Marino {"memory_operand", false, false, {SUBREG, MEM}},
1670*e4b17023SJohn Marino {"indirect_operand", false, false, {SUBREG, MEM}},
1671*e4b17023SJohn Marino {"ordered_comparison_operator", false, false, {EQ, NE,
1672*e4b17023SJohn Marino LE, LT, GE, GT,
1673*e4b17023SJohn Marino LEU, LTU, GEU, GTU}},
1674*e4b17023SJohn Marino {"comparison_operator", false, false, {EQ, NE,
1675*e4b17023SJohn Marino LE, LT, GE, GT,
1676*e4b17023SJohn Marino LEU, LTU, GEU, GTU,
1677*e4b17023SJohn Marino UNORDERED, ORDERED,
1678*e4b17023SJohn Marino UNEQ, UNGE, UNGT,
1679*e4b17023SJohn Marino UNLE, UNLT, LTGT}}
1680*e4b17023SJohn Marino };
1681*e4b17023SJohn Marino #define NUM_KNOWN_STD_PREDS ARRAY_SIZE (std_preds)
1682*e4b17023SJohn Marino
1683*e4b17023SJohn Marino /* Initialize the table of predicate definitions, starting with
1684*e4b17023SJohn Marino the information we have on generic predicates. */
1685*e4b17023SJohn Marino
1686*e4b17023SJohn Marino static void
init_predicate_table(void)1687*e4b17023SJohn Marino init_predicate_table (void)
1688*e4b17023SJohn Marino {
1689*e4b17023SJohn Marino size_t i, j;
1690*e4b17023SJohn Marino struct pred_data *pred;
1691*e4b17023SJohn Marino
1692*e4b17023SJohn Marino predicate_table = htab_create_alloc (37, hash_struct_pred_data,
1693*e4b17023SJohn Marino eq_struct_pred_data, 0,
1694*e4b17023SJohn Marino xcalloc, free);
1695*e4b17023SJohn Marino
1696*e4b17023SJohn Marino for (i = 0; i < NUM_KNOWN_STD_PREDS; i++)
1697*e4b17023SJohn Marino {
1698*e4b17023SJohn Marino pred = XCNEW (struct pred_data);
1699*e4b17023SJohn Marino pred->name = std_preds[i].name;
1700*e4b17023SJohn Marino pred->special = std_preds[i].special;
1701*e4b17023SJohn Marino
1702*e4b17023SJohn Marino for (j = 0; std_preds[i].codes[j] != 0; j++)
1703*e4b17023SJohn Marino add_predicate_code (pred, std_preds[i].codes[j]);
1704*e4b17023SJohn Marino
1705*e4b17023SJohn Marino if (std_preds[i].allows_const_p)
1706*e4b17023SJohn Marino for (j = 0; j < NUM_RTX_CODE; j++)
1707*e4b17023SJohn Marino if (GET_RTX_CLASS (j) == RTX_CONST_OBJ)
1708*e4b17023SJohn Marino add_predicate_code (pred, (enum rtx_code) j);
1709*e4b17023SJohn Marino
1710*e4b17023SJohn Marino add_predicate (pred);
1711*e4b17023SJohn Marino }
1712*e4b17023SJohn Marino }
1713*e4b17023SJohn Marino
1714*e4b17023SJohn Marino /* These functions allow linkage with print-rtl.c. Also, some generators
1715*e4b17023SJohn Marino like to annotate their output with insn names. */
1716*e4b17023SJohn Marino
1717*e4b17023SJohn Marino /* Holds an array of names indexed by insn_code_number. */
1718*e4b17023SJohn Marino static char **insn_name_ptr = 0;
1719*e4b17023SJohn Marino static int insn_name_ptr_size = 0;
1720*e4b17023SJohn Marino
1721*e4b17023SJohn Marino const char *
get_insn_name(int code)1722*e4b17023SJohn Marino get_insn_name (int code)
1723*e4b17023SJohn Marino {
1724*e4b17023SJohn Marino if (code < insn_name_ptr_size)
1725*e4b17023SJohn Marino return insn_name_ptr[code];
1726*e4b17023SJohn Marino else
1727*e4b17023SJohn Marino return NULL;
1728*e4b17023SJohn Marino }
1729*e4b17023SJohn Marino
1730*e4b17023SJohn Marino static void
record_insn_name(int code,const char * name)1731*e4b17023SJohn Marino record_insn_name (int code, const char *name)
1732*e4b17023SJohn Marino {
1733*e4b17023SJohn Marino static const char *last_real_name = "insn";
1734*e4b17023SJohn Marino static int last_real_code = 0;
1735*e4b17023SJohn Marino char *new_name;
1736*e4b17023SJohn Marino
1737*e4b17023SJohn Marino if (insn_name_ptr_size <= code)
1738*e4b17023SJohn Marino {
1739*e4b17023SJohn Marino int new_size;
1740*e4b17023SJohn Marino new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
1741*e4b17023SJohn Marino insn_name_ptr = XRESIZEVEC (char *, insn_name_ptr, new_size);
1742*e4b17023SJohn Marino memset (insn_name_ptr + insn_name_ptr_size, 0,
1743*e4b17023SJohn Marino sizeof(char *) * (new_size - insn_name_ptr_size));
1744*e4b17023SJohn Marino insn_name_ptr_size = new_size;
1745*e4b17023SJohn Marino }
1746*e4b17023SJohn Marino
1747*e4b17023SJohn Marino if (!name || name[0] == '\0')
1748*e4b17023SJohn Marino {
1749*e4b17023SJohn Marino new_name = XNEWVAR (char, strlen (last_real_name) + 10);
1750*e4b17023SJohn Marino sprintf (new_name, "%s+%d", last_real_name, code - last_real_code);
1751*e4b17023SJohn Marino }
1752*e4b17023SJohn Marino else
1753*e4b17023SJohn Marino {
1754*e4b17023SJohn Marino last_real_name = new_name = xstrdup (name);
1755*e4b17023SJohn Marino last_real_code = code;
1756*e4b17023SJohn Marino }
1757*e4b17023SJohn Marino
1758*e4b17023SJohn Marino insn_name_ptr[code] = new_name;
1759*e4b17023SJohn Marino }
1760*e4b17023SJohn Marino
1761*e4b17023SJohn Marino /* Make STATS describe the operands that appear in rtx X. */
1762*e4b17023SJohn Marino
1763*e4b17023SJohn Marino static void
get_pattern_stats_1(struct pattern_stats * stats,rtx x)1764*e4b17023SJohn Marino get_pattern_stats_1 (struct pattern_stats *stats, rtx x)
1765*e4b17023SJohn Marino {
1766*e4b17023SJohn Marino RTX_CODE code;
1767*e4b17023SJohn Marino int i;
1768*e4b17023SJohn Marino int len;
1769*e4b17023SJohn Marino const char *fmt;
1770*e4b17023SJohn Marino
1771*e4b17023SJohn Marino if (x == NULL_RTX)
1772*e4b17023SJohn Marino return;
1773*e4b17023SJohn Marino
1774*e4b17023SJohn Marino code = GET_CODE (x);
1775*e4b17023SJohn Marino switch (code)
1776*e4b17023SJohn Marino {
1777*e4b17023SJohn Marino case MATCH_OPERAND:
1778*e4b17023SJohn Marino case MATCH_OPERATOR:
1779*e4b17023SJohn Marino case MATCH_PARALLEL:
1780*e4b17023SJohn Marino stats->max_opno = MAX (stats->max_opno, XINT (x, 0));
1781*e4b17023SJohn Marino break;
1782*e4b17023SJohn Marino
1783*e4b17023SJohn Marino case MATCH_DUP:
1784*e4b17023SJohn Marino case MATCH_OP_DUP:
1785*e4b17023SJohn Marino case MATCH_PAR_DUP:
1786*e4b17023SJohn Marino stats->num_dups++;
1787*e4b17023SJohn Marino stats->max_dup_opno = MAX (stats->max_dup_opno, XINT (x, 0));
1788*e4b17023SJohn Marino break;
1789*e4b17023SJohn Marino
1790*e4b17023SJohn Marino case MATCH_SCRATCH:
1791*e4b17023SJohn Marino stats->max_scratch_opno = MAX (stats->max_scratch_opno, XINT (x, 0));
1792*e4b17023SJohn Marino break;
1793*e4b17023SJohn Marino
1794*e4b17023SJohn Marino default:
1795*e4b17023SJohn Marino break;
1796*e4b17023SJohn Marino }
1797*e4b17023SJohn Marino
1798*e4b17023SJohn Marino fmt = GET_RTX_FORMAT (code);
1799*e4b17023SJohn Marino len = GET_RTX_LENGTH (code);
1800*e4b17023SJohn Marino for (i = 0; i < len; i++)
1801*e4b17023SJohn Marino {
1802*e4b17023SJohn Marino if (fmt[i] == 'e' || fmt[i] == 'u')
1803*e4b17023SJohn Marino get_pattern_stats_1 (stats, XEXP (x, i));
1804*e4b17023SJohn Marino else if (fmt[i] == 'E')
1805*e4b17023SJohn Marino {
1806*e4b17023SJohn Marino int j;
1807*e4b17023SJohn Marino for (j = 0; j < XVECLEN (x, i); j++)
1808*e4b17023SJohn Marino get_pattern_stats_1 (stats, XVECEXP (x, i, j));
1809*e4b17023SJohn Marino }
1810*e4b17023SJohn Marino }
1811*e4b17023SJohn Marino }
1812*e4b17023SJohn Marino
1813*e4b17023SJohn Marino /* Make STATS describe the operands that appear in instruction pattern
1814*e4b17023SJohn Marino PATTERN. */
1815*e4b17023SJohn Marino
1816*e4b17023SJohn Marino void
get_pattern_stats(struct pattern_stats * stats,rtvec pattern)1817*e4b17023SJohn Marino get_pattern_stats (struct pattern_stats *stats, rtvec pattern)
1818*e4b17023SJohn Marino {
1819*e4b17023SJohn Marino int i, len;
1820*e4b17023SJohn Marino
1821*e4b17023SJohn Marino stats->max_opno = -1;
1822*e4b17023SJohn Marino stats->max_dup_opno = -1;
1823*e4b17023SJohn Marino stats->max_scratch_opno = -1;
1824*e4b17023SJohn Marino stats->num_dups = 0;
1825*e4b17023SJohn Marino
1826*e4b17023SJohn Marino len = GET_NUM_ELEM (pattern);
1827*e4b17023SJohn Marino for (i = 0; i < len; i++)
1828*e4b17023SJohn Marino get_pattern_stats_1 (stats, RTVEC_ELT (pattern, i));
1829*e4b17023SJohn Marino
1830*e4b17023SJohn Marino stats->num_generator_args = stats->max_opno + 1;
1831*e4b17023SJohn Marino stats->num_insn_operands = MAX (stats->max_opno,
1832*e4b17023SJohn Marino stats->max_scratch_opno) + 1;
1833*e4b17023SJohn Marino stats->num_operand_vars = MAX (stats->max_opno,
1834*e4b17023SJohn Marino MAX (stats->max_dup_opno,
1835*e4b17023SJohn Marino stats->max_scratch_opno)) + 1;
1836*e4b17023SJohn Marino }
1837