]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/genautomata.c
config.sub: Add support for avr target.
[thirdparty/gcc.git] / gcc / genautomata.c
CommitLineData
fae15c93 1/* Pipeline hazard description translator.
0b2fb0d7 2 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
fae15c93
VM
3
4 Written by Vladimir Makarov <vmakarov@redhat.com>
5
6This file is part of GNU CC.
7
8GNU CC is free software; you can redistribute it and/or modify it
9under the terms of the GNU General Public License as published by the
10Free Software Foundation; either version 2, or (at your option) any
11later version.
12
13GNU CC is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU CC; see the file COPYING. If not, write to the Free
20Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2102111-1307, USA. */
22
23/* References:
24
25 1. Detecting pipeline structural hazards quickly. T. Proebsting,
26 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
27 Principles of Programming Languages, pages 280--286, 1994.
28
29 This article is a good start point to understand usage of finite
30 state automata for pipeline hazard recognizers. But I'd
31 recommend the 2nd article for more deep understanding.
32
33 2. Efficient Instruction Scheduling Using Finite State Automata:
34 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
35 article about usage of finite state automata for pipeline hazard
36 recognizers.
37
38 The current implementation is different from the 2nd article in the
39 following:
40
41 1. New operator `|' (alternative) is permitted in functional unit
42 reservation which can be treated deterministicly and
43 non-deterministicly.
44
45 2. Possibility of usage of nondeterministic automata too.
46
47 3. Possibility to query functional unit reservations for given
48 automaton state.
49
50 4. Several constructions to describe impossible reservations
51 (`exclusion_set', `presence_set', and `absence_set').
52
53 5. No reverse automata are generated. Trace instruction scheduling
54 requires this. It can be easily added in the future if we
55 really need this.
56
57 6. Union of automaton states are not generated yet. It is planned
58 to be implemented. Such feature is needed to make more accurate
59 interlock insn scheduling to get state describing functional
60 unit reservation in a joint CFG point.
61*/
62
63/* This file code processes constructions of machine description file
64 which describes automaton used for recognition of processor pipeline
65 hazards by insn scheduler and can be used for other tasks (such as
66 VLIW insn packing.
67
68 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
69 `gen_bypass', `gen_excl_set', `gen_presence_set',
70 `gen_absence_set', `gen_automaton', `gen_automata_option',
71 `gen_reserv', `gen_insn_reserv' are called from file
72 `genattrtab.c'. They transform RTL constructions describing
73 automata in .md file into internal representation convenient for
74 further processing.
75
76 The translator major function `expand_automata' processes the
77 description internal representation into finite state automaton.
78 It can be divided on:
79
80 o checking correctness of the automaton pipeline description
81 (major function is `check_all_description').
82
83 o generating automaton (automata) from the description (major
84 function is `make_automaton').
85
86 o optional transformation of nondeterministic finite state
87 automata into deterministic ones if the alternative operator
88 `|' is treated nondeterministicly in the description (major
89 function is NDFA_to_DFA).
90
91 o optional minimization of the finite state automata by merging
92 equivalent automaton states (major function is `minimize_DFA').
93
94 o forming tables (some as comb vectors) and attributes
95 representing the automata (functions output_..._table).
96
97 Function `write_automata' outputs the created finite state
98 automaton as different tables and functions which works with the
99 automata to inquire automaton state and to change its state. These
100 function are used by gcc instruction scheduler and may be some
101 other gcc code. */
102
103#include "hconfig.h"
104#include "system.h"
105#include "rtl.h"
106#include "obstack.h"
107#include "errors.h"
108
fae15c93
VM
109#include <math.h>
110#include "hashtab.h"
111#include "varray.h"
112
fae15c93
VM
113#ifndef CHAR_BIT
114#define CHAR_BIT 8
115#endif
fae15c93
VM
116
117#include "genattrtab.h"
118
119#define obstack_chunk_alloc xmalloc
120#define obstack_chunk_free free
121
122/* Positions in machine description file. Now they are not used. But
123 they could be used in the future for better diagnostic messages. */
124typedef int pos_t;
125
126/* The following is element of vector of current (and planned in the
127 future) functional unit reservations. */
128typedef unsigned HOST_WIDE_INT set_el_t;
129
130/* Reservations of function units are represented by value of the following
131 type. */
132typedef set_el_t *reserv_sets_t;
133
134/* The following structure represents variable length array (vla) of
135 pointers and HOST WIDE INTs. We could be use only varray. But we
136 add new lay because we add elements very frequently and this could
137 stress OS allocator when varray is used only. */
138typedef struct {
139 size_t length; /* current size of vla. */
140 varray_type varray; /* container for vla. */
141} vla_ptr_t;
142
143typedef vla_ptr_t vla_hwint_t;
144
145/* The following structure describes a ticker. */
146struct ticker
147{
148 /* The following member value is time of the ticker creation with
149 taking into account time when the ticker is off. Active time of
150 the ticker is current time minus the value. */
151 int modified_creation_time;
152 /* The following member value is time (incremented by one) when the
153 ticker was off. Zero value means that now the ticker is on. */
154 int incremented_off_time;
155};
156
157/* The ticker is represented by the following type. */
158typedef struct ticker ticker_t;
159
160/* The following type describes elements of output vectors. */
161typedef HOST_WIDE_INT vect_el_t;
162
163/* Forward declaration of structures of internal representation of
164 pipeline description based on NDFA. */
165
166struct unit_decl;
167struct bypass_decl;
168struct result_decl;
169struct automaton_decl;
170struct unit_rel_decl;
171struct reserv_decl;
172struct insn_reserv_decl;
173struct decl;
174struct unit_regexp;
175struct result_regexp;
176struct reserv_regexp;
177struct nothing_regexp;
178struct sequence_regexp;
179struct repeat_regexp;
180struct allof_regexp;
181struct oneof_regexp;
182struct regexp;
183struct description;
184struct unit_set_el;
185struct state;
186struct alt_state;
187struct arc;
188struct ainsn;
189struct automaton;
190struct state_ainsn_table;
191
192/* The following typedefs are for brevity. */
deb09eff 193typedef struct unit_decl *unit_decl_t;
fae15c93
VM
194typedef struct decl *decl_t;
195typedef struct regexp *regexp_t;
196typedef struct unit_set_el *unit_set_el_t;
197typedef struct alt_state *alt_state_t;
198typedef struct state *state_t;
199typedef struct arc *arc_t;
200typedef struct ainsn *ainsn_t;
201typedef struct automaton *automaton_t;
202typedef struct automata_list_el *automata_list_el_t;
203typedef struct state_ainsn_table *state_ainsn_table_t;
204
205
206/* Prototypes of functions gen_cpu_unit, gen_query_cpu_unit,
207 gen_bypass, gen_excl_set, gen_presence_set, gen_absence_set,
208 gen_automaton, gen_automata_option, gen_reserv, gen_insn_reserv,
209 initiate_automaton_gen, expand_automata, write_automata are
210 described on the file top because the functions are called from
211 function `main'. */
212
213static void *create_node PARAMS ((size_t));
214static void *copy_node PARAMS ((void *, size_t));
215static char *check_name PARAMS ((char *, pos_t));
216static char *next_sep_el PARAMS ((char **, int, int));
217static int n_sep_els PARAMS ((char *, int, int));
218static char **get_str_vect PARAMS ((char *, int *, int, int));
219static regexp_t gen_regexp_el PARAMS ((char *));
220static regexp_t gen_regexp_repeat PARAMS ((char *));
221static regexp_t gen_regexp_allof PARAMS ((char *));
222static regexp_t gen_regexp_oneof PARAMS ((char *));
223static regexp_t gen_regexp_sequence PARAMS ((char *));
224static regexp_t gen_regexp PARAMS ((char *));
225
226static unsigned string_hash PARAMS ((const char *));
227static unsigned automaton_decl_hash PARAMS ((const void *));
228static int automaton_decl_eq_p PARAMS ((const void *,
229 const void *));
230static decl_t insert_automaton_decl PARAMS ((decl_t));
231static decl_t find_automaton_decl PARAMS ((char *));
232static void initiate_automaton_decl_table PARAMS ((void));
233static void finish_automaton_decl_table PARAMS ((void));
234
235static unsigned insn_decl_hash PARAMS ((const void *));
236static int insn_decl_eq_p PARAMS ((const void *,
237 const void *));
238static decl_t insert_insn_decl PARAMS ((decl_t));
239static decl_t find_insn_decl PARAMS ((char *));
240static void initiate_insn_decl_table PARAMS ((void));
241static void finish_insn_decl_table PARAMS ((void));
242
243static unsigned decl_hash PARAMS ((const void *));
244static int decl_eq_p PARAMS ((const void *,
245 const void *));
246static decl_t insert_decl PARAMS ((decl_t));
247static decl_t find_decl PARAMS ((char *));
248static void initiate_decl_table PARAMS ((void));
249static void finish_decl_table PARAMS ((void));
250
251static unit_set_el_t process_excls PARAMS ((char **, int, pos_t));
252static void add_excls PARAMS ((unit_set_el_t, unit_set_el_t,
253 pos_t));
254static unit_set_el_t process_presence_absence
255 PARAMS ((char **, int, pos_t, int));
256static void add_presence_absence PARAMS ((unit_set_el_t, unit_set_el_t,
257 pos_t, int));
258static void process_decls PARAMS ((void));
259static struct bypass_decl *find_bypass PARAMS ((struct bypass_decl *,
260 struct insn_reserv_decl *));
261static void check_automaton_usage PARAMS ((void));
262static regexp_t process_regexp PARAMS ((regexp_t));
263static void process_regexp_decls PARAMS ((void));
264static void check_usage PARAMS ((void));
265static int loop_in_regexp PARAMS ((regexp_t, decl_t));
266static void check_loops_in_regexps PARAMS ((void));
267static int process_regexp_cycles PARAMS ((regexp_t, int));
268static void evaluate_max_reserv_cycles PARAMS ((void));
269static void check_all_description PARAMS ((void));
270
271static ticker_t create_ticker PARAMS ((void));
272static void ticker_off PARAMS ((ticker_t *));
273static void ticker_on PARAMS ((ticker_t *));
274static int active_time PARAMS ((ticker_t));
275static void print_active_time PARAMS ((FILE *, ticker_t));
276
277static void add_advance_cycle_insn_decl PARAMS ((void));
278
279static alt_state_t get_free_alt_state PARAMS ((void));
280static void free_alt_state PARAMS ((alt_state_t));
281static void free_alt_states PARAMS ((alt_state_t));
282static int alt_state_cmp PARAMS ((const void *alt_state_ptr_1,
283 const void *alt_state_ptr_2));
284static alt_state_t uniq_sort_alt_states PARAMS ((alt_state_t));
285static int alt_states_eq PARAMS ((alt_state_t, alt_state_t));
286static void initiate_alt_states PARAMS ((void));
287static void finish_alt_states PARAMS ((void));
288
289static reserv_sets_t alloc_empty_reserv_sets PARAMS ((void));
290static unsigned reserv_sets_hash_value PARAMS ((reserv_sets_t));
291static int reserv_sets_cmp PARAMS ((reserv_sets_t, reserv_sets_t));
292static int reserv_sets_eq PARAMS ((reserv_sets_t, reserv_sets_t));
293static void set_unit_reserv PARAMS ((reserv_sets_t, int, int));
294static int test_unit_reserv PARAMS ((reserv_sets_t, int, int));
295static int it_is_empty_reserv_sets PARAMS ((reserv_sets_t))
296 ATTRIBUTE_UNUSED;
297static int reserv_sets_are_intersected PARAMS ((reserv_sets_t, reserv_sets_t));
298static void reserv_sets_shift PARAMS ((reserv_sets_t, reserv_sets_t));
299static void reserv_sets_or PARAMS ((reserv_sets_t, reserv_sets_t,
300 reserv_sets_t));
301static void reserv_sets_and PARAMS ((reserv_sets_t, reserv_sets_t,
302 reserv_sets_t))
303 ATTRIBUTE_UNUSED;
304static void output_cycle_reservs PARAMS ((FILE *, reserv_sets_t,
305 int, int));
306static void output_reserv_sets PARAMS ((FILE *, reserv_sets_t));
307static state_t get_free_state PARAMS ((int, automaton_t));
308static void free_state PARAMS ((state_t));
309static unsigned state_hash PARAMS ((const void *));
310static int state_eq_p PARAMS ((const void *, const void *));
311static state_t insert_state PARAMS ((state_t));
312static void set_state_reserv PARAMS ((state_t, int, int));
313static int intersected_state_reservs_p PARAMS ((state_t, state_t));
314static state_t states_union PARAMS ((state_t, state_t));
315static state_t state_shift PARAMS ((state_t));
316static void initiate_states PARAMS ((void));
317static void finish_states PARAMS ((void));
318
319static void free_arc PARAMS ((arc_t));
320static void remove_arc PARAMS ((state_t, arc_t));
321static arc_t find_arc PARAMS ((state_t, state_t, ainsn_t));
322static arc_t add_arc PARAMS ((state_t, state_t, ainsn_t, int));
323static arc_t first_out_arc PARAMS ((state_t));
324static arc_t next_out_arc PARAMS ((arc_t));
325static void initiate_arcs PARAMS ((void));
326static void finish_arcs PARAMS ((void));
327
328static automata_list_el_t get_free_automata_list_el PARAMS ((void));
329static void free_automata_list_el PARAMS ((automata_list_el_t));
330static void free_automata_list PARAMS ((automata_list_el_t));
331static unsigned automata_list_hash PARAMS ((const void *));
332static int automata_list_eq_p PARAMS ((const void *, const void *));
333static void initiate_automata_lists PARAMS ((void));
334static void automata_list_start PARAMS ((void));
335static void automata_list_add PARAMS ((automaton_t));
336static automata_list_el_t automata_list_finish PARAMS ((void));
337static void finish_automata_lists PARAMS ((void));
338
339static void initiate_excl_sets PARAMS ((void));
340static reserv_sets_t get_excl_set PARAMS ((reserv_sets_t));
341
342static void initiate_presence_absence_sets PARAMS ((void));
343static reserv_sets_t get_presence_absence_set PARAMS ((reserv_sets_t, int));
344
345static regexp_t copy_insn_regexp PARAMS ((regexp_t));
346static regexp_t transform_1 PARAMS ((regexp_t));
347static regexp_t transform_2 PARAMS ((regexp_t));
348static regexp_t transform_3 PARAMS ((regexp_t));
349static regexp_t regexp_transform_func
350 PARAMS ((regexp_t, regexp_t (*) (regexp_t)));
351static regexp_t transform_regexp PARAMS ((regexp_t));
352static void transform_insn_regexps PARAMS ((void));
353
deb09eff
VM
354static void process_unit_to_form_the_same_automaton_unit_lists
355 PARAMS ((regexp_t, regexp_t, int));
356static void form_the_same_automaton_unit_lists_from_regexp PARAMS ((regexp_t));
357static void form_the_same_automaton_unit_lists PARAMS ((void));
358static void check_unit_distributions_to_automata PARAMS ((void));
359
fae15c93
VM
360static int process_seq_for_forming_states PARAMS ((regexp_t, automaton_t,
361 int));
362static void finish_forming_alt_state PARAMS ((alt_state_t,
363 automaton_t));
364static void process_alts_for_forming_states PARAMS ((regexp_t,
365 automaton_t, int));
366static void create_alt_states PARAMS ((automaton_t));
367
368static void form_ainsn_with_same_reservs PARAMS ((automaton_t));
369
370static void make_automaton PARAMS ((automaton_t));
371static void form_arcs_marked_by_insn PARAMS ((state_t));
372static void create_composed_state PARAMS ((state_t, arc_t, vla_ptr_t *));
373static void NDFA_to_DFA PARAMS ((automaton_t));
374static void pass_state_graph PARAMS ((state_t, void (*) (state_t)));
375static void pass_states PARAMS ((automaton_t,
376 void (*) (state_t)));
377static void initiate_pass_states PARAMS ((void));
378static void add_achieved_state PARAMS ((state_t));
379static int set_out_arc_insns_equiv_num PARAMS ((state_t, int));
380static void clear_arc_insns_equiv_num PARAMS ((state_t));
381static void copy_equiv_class PARAMS ((vla_ptr_t *to,
382 const vla_ptr_t *from));
383static int state_is_differed PARAMS ((state_t, int, int));
384static state_t init_equiv_class PARAMS ((state_t *states, int));
385static int partition_equiv_class PARAMS ((state_t *, int,
386 vla_ptr_t *, int *));
387static void evaluate_equiv_classes PARAMS ((automaton_t, vla_ptr_t *));
388static void merge_states PARAMS ((automaton_t, vla_ptr_t *));
389static void set_new_cycle_flags PARAMS ((state_t));
390static void minimize_DFA PARAMS ((automaton_t));
391static void incr_states_and_arcs_nums PARAMS ((state_t));
392static void count_states_and_arcs PARAMS ((automaton_t, int *, int *));
393static void build_automaton PARAMS ((automaton_t));
394
395static void set_order_state_num PARAMS ((state_t));
396static void enumerate_states PARAMS ((automaton_t));
397
398static ainsn_t insert_ainsn_into_equiv_class PARAMS ((ainsn_t, ainsn_t));
399static void delete_ainsn_from_equiv_class PARAMS ((ainsn_t));
400static void process_insn_equiv_class PARAMS ((ainsn_t, arc_t *));
401static void process_state_for_insn_equiv_partition PARAMS ((state_t));
402static void set_insn_equiv_classes PARAMS ((automaton_t));
403
404static double estimate_one_automaton_bound PARAMS ((void));
405static int compare_max_occ_cycle_nums PARAMS ((const void *,
406 const void *));
407static void units_to_automata_heuristic_distr PARAMS ((void));
408static ainsn_t create_ainsns PARAMS ((void));
409static void units_to_automata_distr PARAMS ((void));
410static void create_automata PARAMS ((void));
411
412static void form_regexp PARAMS ((regexp_t));
413static const char *regexp_representation PARAMS ((regexp_t));
414static void finish_regexp_representation PARAMS ((void));
415
416static void output_range_type PARAMS ((FILE *, long int, long int));
417static int longest_path_length PARAMS ((state_t));
418static void process_state_longest_path_length PARAMS ((state_t));
419static void output_dfa_max_issue_rate PARAMS ((void));
420static void output_vect PARAMS ((vect_el_t *, int));
421static void output_chip_member_name PARAMS ((FILE *, automaton_t));
422static void output_temp_chip_member_name PARAMS ((FILE *, automaton_t));
423static void output_translate_vect_name PARAMS ((FILE *, automaton_t));
424static void output_trans_full_vect_name PARAMS ((FILE *, automaton_t));
425static void output_trans_comb_vect_name PARAMS ((FILE *, automaton_t));
426static void output_trans_check_vect_name PARAMS ((FILE *, automaton_t));
427static void output_trans_base_vect_name PARAMS ((FILE *, automaton_t));
428static void output_state_alts_full_vect_name PARAMS ((FILE *, automaton_t));
429static void output_state_alts_comb_vect_name PARAMS ((FILE *, automaton_t));
430static void output_state_alts_check_vect_name PARAMS ((FILE *, automaton_t));
431static void output_state_alts_base_vect_name PARAMS ((FILE *, automaton_t));
432static void output_min_issue_delay_vect_name PARAMS ((FILE *, automaton_t));
433static void output_dead_lock_vect_name PARAMS ((FILE *, automaton_t));
434static void output_reserved_units_table_name PARAMS ((FILE *, automaton_t));
435static void output_state_member_type PARAMS ((FILE *, automaton_t));
436static void output_chip_definitions PARAMS ((void));
437static void output_translate_vect PARAMS ((automaton_t));
438static int comb_vect_p PARAMS ((state_ainsn_table_t));
439static state_ainsn_table_t create_state_ainsn_table PARAMS ((automaton_t));
440static void output_state_ainsn_table
441 PARAMS ((state_ainsn_table_t, char *, void (*) (FILE *, automaton_t),
442 void (*) (FILE *, automaton_t), void (*) (FILE *, automaton_t),
443 void (*) (FILE *, automaton_t)));
444static void add_vect PARAMS ((state_ainsn_table_t,
445 int, vect_el_t *, int));
446static int out_state_arcs_num PARAMS ((state_t));
447static int compare_transition_els_num PARAMS ((const void *, const void *));
448static void add_vect_el PARAMS ((vla_hwint_t *,
449 ainsn_t, int));
450static void add_states_vect_el PARAMS ((state_t));
451static void output_trans_table PARAMS ((automaton_t));
452static void output_state_alts_table PARAMS ((automaton_t));
0b2fb0d7 453static int min_issue_delay_pass_states PARAMS ((state_t, ainsn_t));
fae15c93
VM
454static int min_issue_delay PARAMS ((state_t, ainsn_t));
455static void initiate_min_issue_delay_pass_states PARAMS ((void));
456static void output_min_issue_delay_table PARAMS ((automaton_t));
457static void output_dead_lock_vect PARAMS ((automaton_t));
458static void output_reserved_units_table PARAMS ((automaton_t));
459static void output_tables PARAMS ((void));
460static void output_max_insn_queue_index_def PARAMS ((void));
461static void output_insn_code_cases PARAMS ((void (*) (automata_list_el_t)));
462static void output_automata_list_min_issue_delay_code PARAMS ((automata_list_el_t));
463static void output_internal_min_issue_delay_func PARAMS ((void));
464static void output_automata_list_transition_code PARAMS ((automata_list_el_t));
465static void output_internal_trans_func PARAMS ((void));
466static void output_internal_insn_code_evaluation PARAMS ((const char *,
467 const char *, int));
468static void output_dfa_insn_code_func PARAMS ((void));
469static void output_trans_func PARAMS ((void));
470static void output_automata_list_state_alts_code PARAMS ((automata_list_el_t));
471static void output_internal_state_alts_func PARAMS ((void));
472static void output_state_alts_func PARAMS ((void));
473static void output_min_issue_delay_func PARAMS ((void));
474static void output_internal_dead_lock_func PARAMS ((void));
475static void output_dead_lock_func PARAMS ((void));
476static void output_internal_reset_func PARAMS ((void));
477static void output_size_func PARAMS ((void));
478static void output_reset_func PARAMS ((void));
479static void output_min_insn_conflict_delay_func PARAMS ((void));
480static void output_internal_insn_latency_func PARAMS ((void));
481static void output_insn_latency_func PARAMS ((void));
482static void output_print_reservation_func PARAMS ((void));
483static int units_cmp PARAMS ((const void *,
484 const void *));
485static void output_get_cpu_unit_code_func PARAMS ((void));
486static void output_cpu_unit_reservation_p PARAMS ((void));
487static void output_dfa_start_func PARAMS ((void));
488static void output_dfa_finish_func PARAMS ((void));
489
490static void output_regexp PARAMS ((regexp_t ));
491static void output_unit_set_el_list PARAMS ((unit_set_el_t));
492static void output_description PARAMS ((void));
493static void output_automaton_name PARAMS ((FILE *, automaton_t));
494static void output_automaton_units PARAMS ((automaton_t));
495static void add_state_reservs PARAMS ((state_t));
496static void output_state_arcs PARAMS ((state_t));
497static int state_reservs_cmp PARAMS ((const void *,
498 const void *));
499static void remove_state_duplicate_reservs PARAMS ((void));
500static void output_state PARAMS ((state_t));
501static void output_automaton_descriptions PARAMS ((void));
502static void output_statistics PARAMS ((FILE *));
503static void output_time_statistics PARAMS ((FILE *));
504static void generate PARAMS ((void));
505
506static void make_insn_alts_attr PARAMS ((void));
507static void make_internal_dfa_insn_code_attr PARAMS ((void));
508static void make_default_insn_latency_attr PARAMS ((void));
509static void make_bypass_attr PARAMS ((void));
510static const char *file_name_suffix PARAMS ((const char *));
511static const char *base_file_name PARAMS ((const char *));
deb09eff 512static void check_automata_insn_issues PARAMS ((void));
fae15c93
VM
513static void add_automaton_state PARAMS ((state_t));
514static void form_important_insn_automata_lists PARAMS ((void));
515
516/* Undefined position. */
517static pos_t no_pos = 0;
518
519/* All IR is stored in the following obstack. */
520static struct obstack irp;
521
522\f
523
524/* This page contains code for work with variable length array (vla)
525 of pointers. We could be use only varray. But we add new lay
526 because we add elements very frequently and this could stress OS
527 allocator when varray is used only. */
528
529/* Start work with vla. */
530#define VLA_PTR_CREATE(vla, allocated_length, name) \
531 do \
532 { \
533 vla_ptr_t *vla_ptr = &(vla); \
534 \
535 VARRAY_GENERIC_PTR_INIT (vla_ptr->varray, allocated_length, name);\
536 vla_ptr->length = 0; \
537 } \
538 while (0)
539
540/* Finish work with the vla. */
541#define VLA_PTR_DELETE(vla) VARRAY_FREE ((vla).varray)
542
543/* Return start address of the vla. */
544#define VLA_PTR_BEGIN(vla) ((void *) &VARRAY_GENERIC_PTR ((vla).varray, 0))
545
546/* Address of the last element of the vla. Do not use side effects in
547 the macro argument. */
548#define VLA_PTR_LAST(vla) (&VARRAY_GENERIC_PTR ((vla).varray, \
549 (vla).length - 1))
550/* Nullify the vla. */
551#define VLA_PTR_NULLIFY(vla) ((vla).length = 0)
552
553/* Shorten the vla on given number bytes. */
554#define VLA_PTR_SHORTEN(vla, n) ((vla).length -= (n))
555
556/* Expand the vla on N elements. The values of new elements are
557 undefined. */
558#define VLA_PTR_EXPAND(vla, n) \
559 do { \
560 vla_ptr_t *expand_vla_ptr = &(vla); \
561 size_t new_length = (n) + expand_vla_ptr->length; \
562 \
563 if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
564 VARRAY_GROW (expand_vla_ptr->varray, \
565 (new_length - expand_vla_ptr->length < 128 \
566 ? expand_vla_ptr->length + 128 : new_length)); \
567 expand_vla_ptr->length = new_length; \
568 } while (0)
569
570/* Add element to the end of the vla. */
571#define VLA_PTR_ADD(vla, ptr) \
572 do { \
573 vla_ptr_t *vla_ptr = &(vla); \
574 \
575 VLA_PTR_EXPAND (*vla_ptr, 1); \
576 VARRAY_GENERIC_PTR (vla_ptr->varray, vla_ptr->length - 1) = (ptr);\
577 } while (0)
578
579/* Length of the vla in elements. */
580#define VLA_PTR_LENGTH(vla) ((vla).length)
581
582/* N-th element of the vla. */
583#define VLA_PTR(vla, n) VARRAY_GENERIC_PTR ((vla).varray, n)
584
585
586/* The following macros are analogous to the previous ones but for
587 VLAs of HOST WIDE INTs. */
588
589#define VLA_HWINT_CREATE(vla, allocated_length, name) \
590 do { \
591 vla_hwint_t *vla_ptr = &(vla); \
592 \
593 VARRAY_WIDE_INT_INIT (vla_ptr->varray, allocated_length, name); \
594 vla_ptr->length = 0; \
595 } while (0)
596
597#define VLA_HWINT_DELETE(vla) VARRAY_FREE ((vla).varray)
598
599#define VLA_HWINT_BEGIN(vla) (&VARRAY_WIDE_INT ((vla).varray, 0))
600
601/* Do not use side effects in the macro argument. */
602#define VLA_HWINT_LAST(vla) (&VARRAY_WIDE_INT ((vla).varray, \
603 (vla).length - 1))
604
605#define VLA_HWINT_NULLIFY(vla) ((vla).length = 0)
606
607#define VLA_HWINT_SHORTEN(vla, n) ((vla).length -= (n))
608
609#define VLA_HWINT_EXPAND(vla, n) \
610 do { \
611 vla_hwint_t *expand_vla_ptr = &(vla); \
612 size_t new_length = (n) + expand_vla_ptr->length; \
613 \
614 if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \
615 VARRAY_GROW (expand_vla_ptr->varray, \
616 (new_length - expand_vla_ptr->length < 128 \
617 ? expand_vla_ptr->length + 128 : new_length)); \
618 expand_vla_ptr->length = new_length; \
619 } while (0)
620
621#define VLA_HWINT_ADD(vla, ptr) \
622 do { \
623 vla_hwint_t *vla_ptr = &(vla); \
624 \
625 VLA_HWINT_EXPAND (*vla_ptr, 1); \
626 VARRAY_WIDE_INT (vla_ptr->varray, vla_ptr->length - 1) = (ptr); \
627 } while (0)
628
629#define VLA_HWINT_LENGTH(vla) ((vla).length)
630
631#define VLA_HWINT(vla, n) VARRAY_WIDE_INT ((vla).varray, n)
632
633\f
634
635/* Options with the following names can be set up in automata_option
636 construction. Because the strings occur more one time we use the
637 macros. */
638
639#define NO_MINIMIZATION_OPTION "-no-minimization"
640
e3c8eb86
VM
641#define TIME_OPTION "-time"
642
643#define V_OPTION "-v"
644
fae15c93
VM
645#define W_OPTION "-w"
646
647#define NDFA_OPTION "-ndfa"
648
649/* The following flags are set up by function `initiate_automaton_gen'. */
650
651/* Make automata with nondeterministic reservation by insns (`-ndfa'). */
652static int ndfa_flag;
653
654/* Do not make minimization of DFA (`-no-minimization'). */
655static int no_minimization_flag;
656
657/* Value of this variable is number of automata being generated. The
658 actual number of automata may be less this value if there is not
659 sufficient number of units. This value is defined by argument of
660 option `-split' or by constructions automaton if the value is zero
661 (it is default value of the argument). */
662static int split_argument;
663
664/* Flag of output time statistics (`-time'). */
665static int time_flag;
666
667/* Flag of creation of description file which contains description of
668 result automaton and statistics information (`-v'). */
669static int v_flag;
670
671/* Flag of generating warning instead of error for non-critical errors
672 (`-w'). */
673static int w_flag;
674
675
676/* Output file for pipeline hazard recognizer (PHR) being generated.
677 The value is NULL if the file is not defined. */
678static FILE *output_file;
679
680/* Description file of PHR. The value is NULL if the file is not
681 created. */
682static FILE *output_description_file;
683
684/* PHR description file name. */
685static char *output_description_file_name;
686
687/* Value of the following variable is node representing description
688 being processed. This is start point of IR. */
689static struct description *description;
690
691\f
692
693/* This page contains description of IR structure (nodes). */
694
695enum decl_mode
696{
697 dm_unit,
698 dm_bypass,
699 dm_automaton,
700 dm_excl,
701 dm_presence,
702 dm_absence,
703 dm_reserv,
704 dm_insn_reserv
705};
706
707/* This describes define_cpu_unit and define_query_cpu_unit (see file
708 rtl.def). */
709struct unit_decl
710{
711 char *name;
712 /* NULL if the automaton name is absent. */
713 char *automaton_name;
714 /* If the following value is not zero, the cpu unit reservation is
715 described in define_query_cpu_unit. */
716 char query_p;
717
718 /* The following fields are defined by checker. */
719
720 /* The following field value is nonzero if the unit is used in an
721 regexp. */
722 char unit_is_used;
deb09eff
VM
723
724 /* The following field value is used to form cyclic lists of units
725 which should be in the same automaton because the unit is
726 reserved not on all alternatives of a regexp on a cycle. */
727 unit_decl_t the_same_automaton_unit;
728 /* The following field is TRUE if we already reported that the unit
729 is not in the same automaton. */
730 int the_same_automaton_message_reported_p;
731
fae15c93
VM
732 /* The following field value is order number (0, 1, ...) of given
733 unit. */
734 int unit_num;
735 /* The following field value is corresponding declaration of
736 automaton which was given in description. If the field value is
737 NULL then automaton in the unit declaration was absent. */
738 struct automaton_decl *automaton_decl;
739 /* The following field value is maximal cycle number (1, ...) on
740 which given unit occurs in insns. Zero value means that given
741 unit is not used in insns. */
742 int max_occ_cycle_num;
743 /* The following list contains units which conflict with given
744 unit. */
745 unit_set_el_t excl_list;
746 /* The following list contains units which are required to
747 reservation of given unit. */
748 unit_set_el_t presence_list;
749 /* The following list contains units which should be not present in
750 reservation for given unit. */
751 unit_set_el_t absence_list;
752 /* The following is used only when `query_p' has nonzero value.
753 This is query number for the unit. */
754 int query_num;
755
756 /* The following fields are defined by automaton generator. */
757
758 /* The following field value is number of the automaton to which
759 given unit belongs. */
760 int corresponding_automaton_num;
761};
762
763/* This describes define_bypass (see file rtl.def). */
764struct bypass_decl
765{
766 int latency;
767 char *out_insn_name;
768 char *in_insn_name;
769 char *bypass_guard_name;
770
771 /* The following fields are defined by checker. */
772
773 /* output and input insns of given bypass. */
774 struct insn_reserv_decl *out_insn_reserv;
775 struct insn_reserv_decl *in_insn_reserv;
776 /* The next bypass for given output insn. */
777 struct bypass_decl *next;
778};
779
780/* This describes define_automaton (see file rtl.def). */
781struct automaton_decl
782{
783 char *name;
784
785 /* The following fields are defined by automaton generator. */
786
787 /* The following field value is nonzero if the automaton is used in
788 an regexp definition. */
789 char automaton_is_used;
790
791 /* The following fields are defined by checker. */
792
793 /* The following field value is the corresponding automaton. This
794 field is not NULL only if the automaton is present in unit
795 declarations and the automatic partition on automata is not
796 used. */
797 automaton_t corresponding_automaton;
798};
799
800/* This describes unit relations: exclusion_set, presence_set, or
801 absence_set (see file rtl.def). */
802struct unit_rel_decl
803{
804 int names_num;
805 int first_list_length;
806 char *names [1];
807};
808
809/* This describes define_reservation (see file rtl.def). */
810struct reserv_decl
811{
812 char *name;
813 regexp_t regexp;
814
815 /* The following fields are defined by checker. */
816
817 /* The following field value is nonzero if the unit is used in an
818 regexp. */
819 char reserv_is_used;
820 /* The following field is used to check up cycle in expression
821 definition. */
822 int loop_pass_num;
823};
824
825/* This describes define_insn_reservartion (see file rtl.def). */
826struct insn_reserv_decl
827{
828 rtx condexp;
829 int default_latency;
830 regexp_t regexp;
831 char *name;
832
833 /* The following fields are defined by checker. */
834
835 /* The following field value is order number (0, 1, ...) of given
836 insn. */
837 int insn_num;
838 /* The following field value is list of bypasses in which given insn
839 is output insn. */
840 struct bypass_decl *bypass_list;
841
842 /* The following fields are defined by automaton generator. */
843
844 /* The following field is the insn regexp transformed that
845 the regexp has not optional regexp, repetition regexp, and an
846 reservation name (i.e. reservation identifiers are changed by the
847 corresponding regexp) and all alternations are the topest level
848 of the regexp. The value can be NULL only if it is special
849 insn `cycle advancing'. */
850 regexp_t transformed_regexp;
851 /* The following field value is list of arcs marked given
852 insn. The field is used in transfromation NDFA -> DFA. */
853 arc_t arcs_marked_by_insn;
854 /* The two following fields are used during minimization of a finite state
855 automaton. */
856 /* The field value is number of equivalence class of state into
857 which arc marked by given insn enters from a state (fixed during
858 an automaton minimization). */
859 int equiv_class_num;
860 /* The field value is state_alts of arc leaving a state (fixed
861 during an automaton minimization) and marked by given insn
862 enters. */
863 int state_alts;
864 /* The following member value is the list to automata which can be
deb09eff 865 changed by the insn issue. */
fae15c93
VM
866 automata_list_el_t important_automata_list;
867 /* The following member is used to process insn once for output. */
868 int processed_p;
869};
870
871/* This contains a declaration mentioned above. */
872struct decl
873{
874 /* What node in the union? */
875 enum decl_mode mode;
876 pos_t pos;
877 union
878 {
879 struct unit_decl unit;
880 struct bypass_decl bypass;
881 struct automaton_decl automaton;
882 struct unit_rel_decl excl;
883 struct unit_rel_decl presence;
884 struct unit_rel_decl absence;
885 struct reserv_decl reserv;
886 struct insn_reserv_decl insn_reserv;
887 } decl;
888};
889
890/* The following structures represent parsed reservation strings. */
891enum regexp_mode
892{
893 rm_unit,
894 rm_reserv,
895 rm_nothing,
896 rm_sequence,
897 rm_repeat,
898 rm_allof,
899 rm_oneof
900};
901
902/* Cpu unit in reservation. */
903struct unit_regexp
904{
905 char *name;
deb09eff 906 unit_decl_t unit_decl;
fae15c93
VM
907};
908
909/* Define_reservation in a reservation. */
910struct reserv_regexp
911{
912 char *name;
913 struct reserv_decl *reserv_decl;
914};
915
916/* Absence of reservation (represented by string `nothing'). */
917struct nothing_regexp
918{
919 /* This used to be empty but ISO C doesn't allow that. */
920 char unused;
921};
922
923/* Representation of reservations separated by ',' (see file
924 rtl.def). */
925struct sequence_regexp
926{
927 int regexps_num;
928 regexp_t regexps [1];
929};
930
931/* Representation of construction `repeat' (see file rtl.def). */
932struct repeat_regexp
933{
934 int repeat_num;
935 regexp_t regexp;
936};
937
938/* Representation of reservations separated by '+' (see file
939 rtl.def). */
940struct allof_regexp
941{
942 int regexps_num;
943 regexp_t regexps [1];
944};
945
946/* Representation of reservations separated by '|' (see file
947 rtl.def). */
948struct oneof_regexp
949{
950 int regexps_num;
951 regexp_t regexps [1];
952};
953
954/* Representation of a reservation string. */
955struct regexp
956{
957 /* What node in the union? */
958 enum regexp_mode mode;
959 pos_t pos;
960 union
961 {
962 struct unit_regexp unit;
963 struct reserv_regexp reserv;
964 struct nothing_regexp nothing;
965 struct sequence_regexp sequence;
966 struct repeat_regexp repeat;
967 struct allof_regexp allof;
968 struct oneof_regexp oneof;
969 } regexp;
970};
971
972/* Reperesents description of pipeline hazard description based on
973 NDFA. */
974struct description
975{
976 int decls_num;
977
978 /* The following fields are defined by checker. */
979
980 /* The following fields values are correspondingly number of all
981 units, query units, and insns in the description. */
982 int units_num;
983 int query_units_num;
984 int insns_num;
985 /* The following field value is max length (in cycles) of
986 reservations of insns. The field value is defined only for
987 correct programs. */
988 int max_insn_reserv_cycles;
989
990 /* The following fields are defined by automaton generator. */
991
992 /* The following field value is the first automaton. */
993 automaton_t first_automaton;
994
995 /* The following field is created by pipeline hazard parser and
996 contains all declarations. We allocate additional entry for
997 special insn "cycle advancing" which is added by the automaton
998 generator. */
999 decl_t decls [1];
1000};
1001
1002
1003
1004/* The following nodes are created in automaton checker. */
1005
1006/* The following nodes represent exclusion, presence, absence set for
1007 cpu units. Each element are accessed through only one excl_list,
1008 presence_list, absence_list. */
1009struct unit_set_el
1010{
deb09eff 1011 unit_decl_t unit_decl;
fae15c93
VM
1012 unit_set_el_t next_unit_set_el;
1013};
1014
1015
1016
1017/* The following nodes are created in automaton generator. */
1018
1019/* The following node type describes state automaton. The state may
1020 be deterministic or non-deterministic. Non-deterministic state has
1021 several component states which represent alternative cpu units
1022 reservations. The state also is used for describing a
1023 deterministic reservation of automaton insn. */
1024struct state
1025{
1026 /* The following member value is nonzero if there is a transition by
1027 cycle advancing. */
1028 int new_cycle_p;
1029 /* The following field is list of processor unit reservations on
1030 each cycle. */
1031 reserv_sets_t reservs;
1032 /* The following field is unique number of given state between other
1033 states. */
1034 int unique_num;
1035 /* The following field value is automaton to which given state
1036 belongs. */
1037 automaton_t automaton;
1038 /* The following field value is the first arc output from given
1039 state. */
1040 arc_t first_out_arc;
1041 /* The following field is used to form NDFA. */
1042 char it_was_placed_in_stack_for_NDFA_forming;
1043 /* The following field is used to form DFA. */
1044 char it_was_placed_in_stack_for_DFA_forming;
1045 /* The following field is used to transform NDFA to DFA. The field
1046 value is not NULL if the state is a compound state. In this case
1047 the value of field `unit_sets_list' is NULL. All states in the
1048 list are in the hash table. The list is formed through field
1049 `next_sorted_alt_state'. */
1050 alt_state_t component_states;
1051 /* The following field is used for passing graph of states. */
1052 int pass_num;
1053 /* The list of states belonging to one equivalence class is formed
1054 with the aid of the following field. */
1055 state_t next_equiv_class_state;
1056 /* The two following fields are used during minimization of a finite
1057 state automaton. */
1058 int equiv_class_num_1, equiv_class_num_2;
1059 /* The following field is used during minimization of a finite state
1060 automaton. The field value is state corresponding to equivalence
1061 class to which given state belongs. */
1062 state_t equiv_class_state;
1063 /* The following field value is the order number of given state.
1064 The states in final DFA is enumerated with the aid of the
1065 following field. */
1066 int order_state_num;
1067 /* This member is used for passing states for searching minimal
1068 delay time. */
1069 int state_pass_num;
1070 /* The following member is used to evaluate min issue delay of insn
1071 for a state. */
1072 int min_insn_issue_delay;
1073 /* The following member is used to evaluate max issue rate of the
1074 processor. The value of the member is maximal length of the path
1075 from given state no containing arcs marked by special insn `cycle
1076 advancing'. */
1077 int longest_path_length;
1078};
1079
1080/* The following macro is an initial value of member
deb09eff 1081 `longest_path_length' of a state. */
fae15c93
VM
1082#define UNDEFINED_LONGEST_PATH_LENGTH -1
1083
1084/* Automaton arc. */
1085struct arc
1086{
1087 /* The following field refers for the state into which given arc
1088 enters. */
1089 state_t to_state;
1090 /* The following field describes that the insn issue (with cycle
1091 advancing for special insn `cycle advancing' and without cycle
1092 advancing for others) makes transition from given state to
1093 another given state. */
1094 ainsn_t insn;
1095 /* The following field value is the next arc output from the same
1096 state. */
1097 arc_t next_out_arc;
1098 /* List of arcs marked given insn is formed with the following
1099 field. The field is used in transfromation NDFA -> DFA. */
1100 arc_t next_arc_marked_by_insn;
1101 /* The following field is defined if NDFA_FLAG is zero. The member
1102 value is number of alternative reservations which can be used for
1103 transition for given state by given insn. */
1104 int state_alts;
1105};
1106
1107/* The following node type describes a deterministic alternative in
1108 non-deterministic state which characterizes cpu unit reservations
1109 of automaton insn or which is part of NDFA. */
1110struct alt_state
1111{
1112 /* The following field is a determinist state which characterizes
1113 unit reservations of the instruction. */
1114 state_t state;
1115 /* The following field refers to the next state which characterizes
1116 unit reservations of the instruction. */
1117 alt_state_t next_alt_state;
1118 /* The following field refers to the next state in sorted list. */
1119 alt_state_t next_sorted_alt_state;
1120};
1121
1122/* The following node type describes insn of automaton. They are
1123 labels of FA arcs. */
1124struct ainsn
1125{
1126 /* The following field value is the corresponding insn declaration
1127 of description. */
1128 struct insn_reserv_decl *insn_reserv_decl;
1129 /* The following field value is the next insn declaration for an
1130 automaton. */
1131 ainsn_t next_ainsn;
1132 /* The following field is states which characterize automaton unit
1133 reservations of the instruction. The value can be NULL only if it
1134 is special insn `cycle advancing'. */
1135 alt_state_t alt_states;
1136 /* The following field is sorted list of states which characterize
1137 automaton unit reservations of the instruction. The value can be
1138 NULL only if it is special insn `cycle advancing'. */
1139 alt_state_t sorted_alt_states;
1140 /* The following field refers the next automaton insn with
1141 the same reservations. */
1142 ainsn_t next_same_reservs_insn;
1143 /* The following field is flag of the first automaton insn with the
1144 same reservations in the declaration list. Only arcs marked such
1145 insn is present in the automaton. This significantly decreases
1146 memory requirements especially when several automata are
1147 formed. */
1148 char first_insn_with_same_reservs;
1149 /* The following member has nonzero value if there is arc from state of
1150 the automaton marked by the ainsn. */
1151 char arc_exists_p;
e0a2f705 1152 /* Cyclic list of insns of an equivalence class is formed with the
fae15c93
VM
1153 aid of the following field. */
1154 ainsn_t next_equiv_class_insn;
1155 /* The following field value is nonzero if the insn declaration is
1156 the first insn declaration with given equivalence number. */
1157 char first_ainsn_with_given_equialence_num;
1158 /* The following field is number of class of equivalence of insns.
1159 It is necessary because many insns may be equivalent with the
1160 point of view of pipeline hazards. */
1161 int insn_equiv_class_num;
1162 /* The following member value is TRUE if there is an arc in the
1163 automaton marked by the insn into another state. In other
1164 words, the insn can change the state of the automaton. */
1165 int important_p;
1166};
1167
1168/* The folowing describes an automaton for PHR. */
1169struct automaton
1170{
1171 /* The following field value is the list of insn declarations for
1172 given automaton. */
1173 ainsn_t ainsn_list;
1174 /* The following field value is the corresponding automaton
1175 declaration. This field is not NULL only if the automatic
1176 partition on automata is not used. */
1177 struct automaton_decl *corresponding_automaton_decl;
1178 /* The following field value is the next automaton. */
1179 automaton_t next_automaton;
1180 /* The following field is start state of FA. There are not unit
1181 reservations in the state. */
1182 state_t start_state;
1183 /* The following field value is number of equivalence classes of
1184 insns (see field `insn_equiv_class_num' in
1185 `insn_reserv_decl'). */
1186 int insn_equiv_classes_num;
1187 /* The following field value is number of states of final DFA. */
1188 int achieved_states_num;
1189 /* The following field value is the order number (0, 1, ...) of
1190 given automaton. */
1191 int automaton_order_num;
1192 /* The following fields contain statistics information about
1193 building automaton. */
1194 int NDFA_states_num, DFA_states_num;
1195 /* The following field value is defined only if minimization of DFA
1196 is used. */
1197 int minimal_DFA_states_num;
1198 int NDFA_arcs_num, DFA_arcs_num;
1199 /* The following field value is defined only if minimization of DFA
1200 is used. */
1201 int minimal_DFA_arcs_num;
1202 /* The following two members refer for two table state x ainsn ->
1203 int. */
1204 state_ainsn_table_t trans_table;
1205 state_ainsn_table_t state_alts_table;
1206 /* The following member value is maximal value of min issue delay
1207 for insns of the automaton. */
1208 int max_min_delay;
1209 /* Usually min issue delay is small and we can place several (2, 4,
1210 8) elements in one vector element. So the compression factor can
1211 be 1 (no compression), 2, 4, 8. */
1212 int min_issue_delay_table_compression_factor;
1213};
1214
1215/* The following is the element of the list of automata. */
1216struct automata_list_el
1217{
1218 /* The automaton itself. */
1219 automaton_t automaton;
1220 /* The next automata set element. */
1221 automata_list_el_t next_automata_list_el;
1222};
1223
1224/* The following structure describes a table state X ainsn -> int(>= 0). */
1225struct state_ainsn_table
1226{
1227 /* Automaton to which given table belongs. */
1228 automaton_t automaton;
1229 /* The following tree vectors for comb vector implementation of the
1230 table. */
1231 vla_hwint_t comb_vect;
1232 vla_hwint_t check_vect;
1233 vla_hwint_t base_vect;
1234 /* This is simple implementation of the table. */
1235 vla_hwint_t full_vect;
1236 /* Minimal and maximal values of the previous vectors. */
1237 int min_comb_vect_el_value, max_comb_vect_el_value;
1238 int min_base_vect_el_value, max_base_vect_el_value;
1239};
1240
1241/* Create IR structure (node). */
1242static void *
1243create_node (size)
1244 size_t size;
1245{
1246 void *result;
1247
1248 obstack_blank (&irp, size);
1249 result = obstack_base (&irp);
1250 obstack_finish (&irp);
1251 /* Default values of members are NULL and zero. */
1252 memset (result, 0, size);
1253 return result;
1254}
1255
1256/* Copy IR structure (node). */
1257static void *
1258copy_node (from, size)
1259 void *from;
1260 size_t size;
1261{
1262 void *result;
1263 result = create_node (size);
1264 memcpy (result, from, size);
1265 return result;
1266}
1267
1268/* The function checks that NAME does not contain quotes (`"'). */
1269static char *
1270check_name (name, pos)
1271 char * name;
1272 pos_t pos ATTRIBUTE_UNUSED;
1273{
1274 char *str;
1275
1276 for (str = name; *str != '\0'; str++)
1277 if (*str == '\"')
1278 error ("Name `%s' contains quotes", name);
1279 return name;
1280}
1281
1282/* Pointers top all declartions during IR generation are stored in the
1283 following. */
1284static vla_ptr_t decls;
1285
e0a2f705 1286/* Given a pointer to a (char *) and a separator, return an alloc'ed
fae15c93
VM
1287 string containing the next separated element, taking parentheses
1288 into account if PAR_FLAG has nonzero value. Advance the pointer to
1289 after the string scanned, or the end-of-string. Return NULL if at
1290 end of string. */
1291static char *
1292next_sep_el (pstr, sep, par_flag)
1293 char **pstr;
1294 int sep;
1295 int par_flag;
1296{
1297 char *out_str;
1298 char *p;
1299 int pars_num;
1300 int n_spaces;
1301
1302 /* Remove leading whitespaces. */
1f8e4682 1303 while (ISSPACE ((int) **pstr))
fae15c93
VM
1304 (*pstr)++;
1305
1306 if (**pstr == '\0')
1307 return NULL;
1308
1309 n_spaces = 0;
1310 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1311 {
1312 if (par_flag && *p == '(')
1313 pars_num++;
1314 else if (par_flag && *p == ')')
1315 pars_num--;
1316 else if (pars_num == 0 && *p == sep)
1317 break;
1f8e4682 1318 if (pars_num == 0 && ISSPACE ((int) *p))
fae15c93
VM
1319 n_spaces++;
1320 else
1321 {
1322 for (; n_spaces != 0; n_spaces--)
1323 obstack_1grow (&irp, p [-n_spaces]);
1324 obstack_1grow (&irp, *p);
1325 }
1326 }
1327 obstack_1grow (&irp, '\0');
1328 out_str = obstack_base (&irp);
1329 obstack_finish (&irp);
1330
1331 *pstr = p;
1332 if (**pstr == sep)
1333 (*pstr)++;
1334
1335 return out_str;
1336}
1337
1338/* Given a string and a separator, return the number of separated
1339 elements in it, taking parentheses into account if PAR_FLAG has
1340 nonzero value. Return 0 for the null string, -1 if parantheses is
1341 not balanced. */
1342static int
1343n_sep_els (s, sep, par_flag)
1344 char *s;
1345 int sep;
1346 int par_flag;
1347{
1348 int n;
1349 int pars_num;
1350
1351 if (*s == '\0')
1352 return 0;
1353
1354 for (pars_num = 0, n = 1; *s; s++)
1355 if (par_flag && *s == '(')
1356 pars_num++;
1357 else if (par_flag && *s == ')')
1358 pars_num--;
1359 else if (pars_num == 0 && *s == sep)
1360 n++;
1361
1362 return (pars_num != 0 ? -1 : n);
1363}
1364
1365/* Given a string and a separator, return vector of strings which are
1366 elements in the string and number of elements through els_num.
1367 Take parentheses into account if PAR_FLAG has nonzero value.
1368 Return 0 for the null string, -1 if parantheses are not balanced. */
1369static char **
1370get_str_vect (str, els_num, sep, par_flag)
1371 char *str;
1372 int *els_num;
1373 int sep;
1374 int par_flag;
1375{
1376 int i;
1377 char **vect;
1378 char **pstr;
1379
1380 *els_num = n_sep_els (str, sep, par_flag);
1381 if (*els_num <= 0)
1382 return NULL;
1383 obstack_blank (&irp, sizeof (char *) * (*els_num));
1384 vect = (char **) obstack_base (&irp);
1385 obstack_finish (&irp);
1386 pstr = &str;
1387 for (i = 0; i < *els_num; i++)
1388 vect [i] = next_sep_el (pstr, sep, par_flag);
1389 if (next_sep_el (pstr, sep, par_flag) != NULL)
1390 abort ();
1391 return vect;
1392}
1393
1394/* Process a DEFINE_CPU_UNIT.
1395
1396 This gives information about a unit contained in CPU. We fill a
1397 struct unit_decl with information used later by `expand_automata'. */
1398void
1399gen_cpu_unit (def)
1400 rtx def;
1401{
1402 decl_t decl;
1403 char **str_cpu_units;
1404 int vect_length;
1405 int i;
1406
1407 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1408 if (str_cpu_units == NULL)
1409 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1410 for (i = 0; i < vect_length; i++)
1411 {
1412 decl = create_node (sizeof (struct decl));
1413 decl->mode = dm_unit;
1414 decl->pos = 0;
1415 decl->decl.unit.name = check_name (str_cpu_units [i], decl->pos);
1416 decl->decl.unit.automaton_name = (char *) XSTR (def, 1);
1417 decl->decl.unit.query_p = 0;
1418 VLA_PTR_ADD (decls, decl);
1419 num_dfa_decls++;
1420 }
1421}
1422
1423/* Process a DEFINE_QUERY_CPU_UNIT.
1424
1425 This gives information about a unit contained in CPU. We fill a
1426 struct unit_decl with information used later by `expand_automata'. */
1427void
1428gen_query_cpu_unit (def)
1429 rtx def;
1430{
1431 decl_t decl;
1432 char **str_cpu_units;
1433 int vect_length;
1434 int i;
1435
1436 str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1437 if (str_cpu_units == NULL)
1438 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1439 for (i = 0; i < vect_length; i++)
1440 {
1441 decl = create_node (sizeof (struct decl));
1442 decl->mode = dm_unit;
1443 decl->pos = 0;
1444 decl->decl.unit.name = check_name (str_cpu_units [i], decl->pos);
1445 decl->decl.unit.automaton_name = (char *) XSTR (def, 1);
1446 decl->decl.unit.query_p = 1;
1447 VLA_PTR_ADD (decls, decl);
1448 num_dfa_decls++;
1449 }
1450}
1451
1452/* Process a DEFINE_BYPASS.
1453
1454 This gives information about a unit contained in the CPU. We fill
1455 in a struct bypass_decl with information used later by
1456 `expand_automata'. */
1457void
1458gen_bypass (def)
1459 rtx def;
1460{
1461 decl_t decl;
1462 char **out_insns;
1463 int out_length;
1464 char **in_insns;
1465 int in_length;
1466 int i, j;
1467
1468 out_insns = get_str_vect ((char *) XSTR (def, 1), &out_length, ',', 0);
1469 if (out_insns == NULL)
1470 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1471 in_insns = get_str_vect ((char *) XSTR (def, 2), &in_length, ',', 0);
1472 if (in_insns == NULL)
1473 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1474 for (i = 0; i < out_length; i++)
1475 for (j = 0; j < in_length; j++)
1476 {
1477 decl = create_node (sizeof (struct decl));
1478 decl->mode = dm_bypass;
1479 decl->pos = 0;
1480 decl->decl.bypass.latency = XINT (def, 0);
1481 decl->decl.bypass.out_insn_name = out_insns [i];
1482 decl->decl.bypass.in_insn_name = in_insns [j];
1483 decl->decl.bypass.bypass_guard_name = (char *) XSTR (def, 3);
1484 VLA_PTR_ADD (decls, decl);
1485 num_dfa_decls++;
1486 }
1487}
1488
e0a2f705 1489/* Process an EXCLUSION_SET.
fae15c93
VM
1490
1491 This gives information about a cpu unit conflicts. We fill a
1492 struct unit_rel_decl (excl) with information used later by
1493 `expand_automata'. */
1494void
1495gen_excl_set (def)
1496 rtx def;
1497{
1498 decl_t decl;
1499 char **first_str_cpu_units;
1500 char **second_str_cpu_units;
1501 int first_vect_length;
1502 int length;
1503 int i;
1504
1505 first_str_cpu_units
1506 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1507 if (first_str_cpu_units == NULL)
1508 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1509 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1510 0);
1511 if (second_str_cpu_units == NULL)
1512 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1513 length += first_vect_length;
1514 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1515 decl->mode = dm_excl;
1516 decl->pos = 0;
1517 decl->decl.excl.names_num = length;
1518 decl->decl.excl.first_list_length = first_vect_length;
1519 for (i = 0; i < length; i++)
1520 if (i < first_vect_length)
1521 decl->decl.excl.names [i] = first_str_cpu_units [i];
1522 else
1523 decl->decl.excl.names [i] = second_str_cpu_units [i - first_vect_length];
1524 VLA_PTR_ADD (decls, decl);
1525 num_dfa_decls++;
1526}
1527
1528/* Process a PRESENCE_SET.
1529
1530 This gives information about a cpu unit reservation requirements.
1531 We fill a struct unit_rel_decl (presence) with information used
1532 later by `expand_automata'. */
1533void
1534gen_presence_set (def)
1535 rtx def;
1536{
1537 decl_t decl;
1538 char **first_str_cpu_units;
1539 char **second_str_cpu_units;
1540 int first_vect_length;
1541 int length;
1542 int i;
1543
1544 first_str_cpu_units
1545 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1546 if (first_str_cpu_units == NULL)
1547 fatal ("invalid first string `%s' in presence_set", XSTR (def, 0));
1548 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1549 0);
1550 if (second_str_cpu_units == NULL)
1551 fatal ("invalid second string `%s' in presence_set", XSTR (def, 1));
1552 length += first_vect_length;
1553 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1554 decl->mode = dm_presence;
1555 decl->pos = 0;
1556 decl->decl.presence.names_num = length;
1557 decl->decl.presence.first_list_length = first_vect_length;
1558 for (i = 0; i < length; i++)
1559 if (i < first_vect_length)
1560 decl->decl.presence.names [i] = first_str_cpu_units [i];
1561 else
1562 decl->decl.presence.names [i]
1563 = second_str_cpu_units [i - first_vect_length];
1564 VLA_PTR_ADD (decls, decl);
1565 num_dfa_decls++;
1566}
1567
e0a2f705 1568/* Process an ABSENCE_SET.
fae15c93
VM
1569
1570 This gives information about a cpu unit reservation requirements.
1571 We fill a struct unit_rel_decl (absence) with information used
1572 later by `expand_automata'. */
1573void
1574gen_absence_set (def)
1575 rtx def;
1576{
1577 decl_t decl;
1578 char **first_str_cpu_units;
1579 char **second_str_cpu_units;
1580 int first_vect_length;
1581 int length;
1582 int i;
1583
1584 first_str_cpu_units
1585 = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0);
1586 if (first_str_cpu_units == NULL)
1587 fatal ("invalid first string `%s' in absence_set", XSTR (def, 0));
1588 second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',',
1589 0);
1590 if (second_str_cpu_units == NULL)
1591 fatal ("invalid second string `%s' in absence_set", XSTR (def, 1));
1592 length += first_vect_length;
1593 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1594 decl->mode = dm_absence;
1595 decl->pos = 0;
1596 decl->decl.absence.names_num = length;
1597 decl->decl.absence.first_list_length = first_vect_length;
1598 for (i = 0; i < length; i++)
1599 if (i < first_vect_length)
1600 decl->decl.absence.names [i] = first_str_cpu_units [i];
1601 else
1602 decl->decl.absence.names [i]
1603 = second_str_cpu_units [i - first_vect_length];
1604 VLA_PTR_ADD (decls, decl);
1605 num_dfa_decls++;
1606}
1607
1608/* Process a DEFINE_AUTOMATON.
1609
1610 This gives information about a finite state automaton used for
1611 recognizing pipeline hazards. We fill a struct automaton_decl
1612 with information used later by `expand_automata'. */
1613void
1614gen_automaton (def)
1615 rtx def;
1616{
1617 decl_t decl;
1618 char **str_automata;
1619 int vect_length;
1620 int i;
1621
1622 str_automata = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0);
1623 if (str_automata == NULL)
1624 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1625 for (i = 0; i < vect_length; i++)
1626 {
1627 decl = create_node (sizeof (struct decl));
1628 decl->mode = dm_automaton;
1629 decl->pos = 0;
1630 decl->decl.automaton.name = check_name (str_automata [i], decl->pos);
1631 VLA_PTR_ADD (decls, decl);
1632 num_dfa_decls++;
1633 }
1634}
1635
e0a2f705 1636/* Process an AUTOMATA_OPTION.
fae15c93
VM
1637
1638 This gives information how to generate finite state automaton used
1639 for recognizing pipeline hazards. */
1640void
1641gen_automata_option (def)
1642 rtx def;
1643{
1644 if (strcmp ((char *) XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1645 no_minimization_flag = 1;
e3c8eb86
VM
1646 else if (strcmp ((char *) XSTR (def, 0), TIME_OPTION + 1) == 0)
1647 time_flag = 1;
1648 else if (strcmp ((char *) XSTR (def, 0), V_OPTION + 1) == 0)
1649 v_flag = 1;
fae15c93
VM
1650 else if (strcmp ((char *) XSTR (def, 0), W_OPTION + 1) == 0)
1651 w_flag = 1;
1652 else if (strcmp ((char *) XSTR (def, 0), NDFA_OPTION + 1) == 0)
1653 ndfa_flag = 1;
1654 else
1655 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1656}
1657
1658/* Name in reservation to denote absence reservation. */
1659#define NOTHING_NAME "nothing"
1660
1661/* The following string contains original reservation string being
1662 parsed. */
1663static char *reserv_str;
1664
1665/* Parse an element in STR. */
1666static regexp_t
1667gen_regexp_el (str)
1668 char *str;
1669{
1670 regexp_t regexp;
1671 int len;
1672
1673 if (*str == '(')
1674 {
1675 len = strlen (str);
1676 if (str [len - 1] != ')')
1677 fatal ("garbage after ) in reservation `%s'", reserv_str);
1678 str [len - 1] = '\0';
1679 regexp = gen_regexp_sequence (str + 1);
1680 }
1681 else if (strcmp (str, NOTHING_NAME) == 0)
1682 {
1683 regexp = create_node (sizeof (struct decl));
1684 regexp->mode = rm_nothing;
1685 }
1686 else
1687 {
1688 regexp = create_node (sizeof (struct decl));
1689 regexp->mode = rm_unit;
1690 regexp->regexp.unit.name = str;
1691 }
1692 return regexp;
1693}
1694
1695/* Parse construction `repeat' in STR. */
1696static regexp_t
1697gen_regexp_repeat (str)
1698 char *str;
1699{
1700 regexp_t regexp;
1701 regexp_t repeat;
1702 char **repeat_vect;
1703 int els_num;
1704 int i;
1705
1706 repeat_vect = get_str_vect (str, &els_num, '*', 1);
1707 if (repeat_vect == NULL)
1708 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1709 if (els_num > 1)
1710 {
1711 regexp = gen_regexp_el (repeat_vect [0]);
1712 for (i = 1; i < els_num; i++)
1713 {
1714 repeat = create_node (sizeof (struct regexp));
1715 repeat->mode = rm_repeat;
1716 repeat->regexp.repeat.regexp = regexp;
1717 repeat->regexp.repeat.repeat_num = atoi (repeat_vect [i]);
1718 if (repeat->regexp.repeat.repeat_num <= 1)
1719 fatal ("repetition `%s' <= 1 in reservation `%s'",
1720 str, reserv_str);
1721 regexp = repeat;
1722 }
1723 return regexp;
1724 }
1725 else
1726 return gen_regexp_el (str);
1727}
1728
1729/* Parse reservation STR which possibly contains separator '+'. */
1730static regexp_t
1731gen_regexp_allof (str)
1732 char *str;
1733{
1734 regexp_t allof;
1735 char **allof_vect;
1736 int els_num;
1737 int i;
1738
1739 allof_vect = get_str_vect (str, &els_num, '+', 1);
1740 if (allof_vect == NULL)
1741 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1742 if (els_num > 1)
1743 {
1744 allof = create_node (sizeof (struct regexp)
1745 + sizeof (regexp_t) * (els_num - 1));
1746 allof->mode = rm_allof;
1747 allof->regexp.allof.regexps_num = els_num;
1748 for (i = 0; i < els_num; i++)
1749 allof->regexp.allof.regexps [i] = gen_regexp_repeat (allof_vect [i]);
1750 return allof;
1751 }
1752 else
1753 return gen_regexp_repeat (str);
1754}
1755
1756/* Parse reservation STR which possibly contains separator '|'. */
1757static regexp_t
1758gen_regexp_oneof (str)
1759 char *str;
1760{
1761 regexp_t oneof;
1762 char **oneof_vect;
1763 int els_num;
1764 int i;
1765
1766 oneof_vect = get_str_vect (str, &els_num, '|', 1);
1767 if (oneof_vect == NULL)
1768 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1769 if (els_num > 1)
1770 {
1771 oneof = create_node (sizeof (struct regexp)
1772 + sizeof (regexp_t) * (els_num - 1));
1773 oneof->mode = rm_oneof;
1774 oneof->regexp.oneof.regexps_num = els_num;
1775 for (i = 0; i < els_num; i++)
1776 oneof->regexp.oneof.regexps [i] = gen_regexp_allof (oneof_vect [i]);
1777 return oneof;
1778 }
1779 else
1780 return gen_regexp_allof (str);
1781}
1782
1783/* Parse reservation STR which possibly contains separator ','. */
1784static regexp_t
1785gen_regexp_sequence (str)
1786 char *str;
1787{
1788 regexp_t sequence;
1789 char **sequence_vect;
1790 int els_num;
1791 int i;
1792
1793 sequence_vect = get_str_vect (str, &els_num, ',', 1);
1794 if (els_num > 1)
1795 {
1796 sequence = create_node (sizeof (struct regexp)
1797 + sizeof (regexp_t) * (els_num - 1));
1798 sequence->mode = rm_sequence;
1799 sequence->regexp.sequence.regexps_num = els_num;
1800 for (i = 0; i < els_num; i++)
1801 sequence->regexp.sequence.regexps [i]
1802 = gen_regexp_oneof (sequence_vect [i]);
1803 return sequence;
1804 }
1805 else
1806 return gen_regexp_oneof (str);
1807}
1808
1809/* Parse construction reservation STR. */
1810static regexp_t
1811gen_regexp (str)
1812 char *str;
1813{
1814 reserv_str = str;
1815 return gen_regexp_sequence (str);;
1816}
1817
1818/* Process a DEFINE_RESERVATION.
1819
1820 This gives information about a reservation of cpu units. We fill
1821 in a struct reserv_decl with information used later by
1822 `expand_automata'. */
1823void
1824gen_reserv (def)
1825 rtx def;
1826{
1827 decl_t decl;
1828
1829 decl = create_node (sizeof (struct decl));
1830 decl->mode = dm_reserv;
1831 decl->pos = 0;
1832 decl->decl.reserv.name = check_name ((char *) XSTR (def, 0), decl->pos);
1833 decl->decl.reserv.regexp = gen_regexp ((char *) XSTR (def, 1));
1834 VLA_PTR_ADD (decls, decl);
1835 num_dfa_decls++;
1836}
1837
1838/* Process a DEFINE_INSN_RESERVATION.
1839
1840 This gives information about the reservation of cpu units by an
1841 insn. We fill a struct insn_reserv_decl with information used
1842 later by `expand_automata'. */
1843void
1844gen_insn_reserv (def)
1845 rtx def;
1846{
1847 decl_t decl;
1848
1849 decl = create_node (sizeof (struct decl));
1850 decl->mode = dm_insn_reserv;
1851 decl->pos = 0;
1852 decl->decl.insn_reserv.name = check_name ((char *) XSTR (def, 0), decl->pos);
1853 decl->decl.insn_reserv.default_latency = XINT (def, 1);
1854 decl->decl.insn_reserv.condexp = XEXP (def, 2);
1855 decl->decl.insn_reserv.regexp = gen_regexp ((char *) XSTR (def, 3));
1856 VLA_PTR_ADD (decls, decl);
1857 num_dfa_decls++;
1858}
1859
1860\f
1861
1862/* The function evaluates hash value (0..UINT_MAX) of string. */
1863static unsigned
1864string_hash (string)
1865 const char *string;
1866{
1867 unsigned result, i;
1868
1869 for (result = i = 0;*string++ != '\0'; i++)
1870 result += ((unsigned char) *string << (i % CHAR_BIT));
1871 return result;
1872}
1873
1874\f
1875
1876/* This page contains abstract data `table of automaton declarations'.
1877 Elements of the table is nodes representing automaton declarations.
1878 Key of the table elements is name of given automaton. Rememeber
1879 that automaton names have own space. */
1880
e0a2f705 1881/* The function evaluates hash value of an automaton declaration. The
fae15c93
VM
1882 function is used by abstract data `hashtab'. The function returns
1883 hash value (0..UINT_MAX) of given automaton declaration. */
1884static unsigned
1885automaton_decl_hash (automaton_decl)
1886 const void *automaton_decl;
1887{
1888 const decl_t decl = (decl_t) automaton_decl;
1889
1890 if (decl->mode == dm_automaton && decl->decl.automaton.name == NULL)
1891 abort ();
1892 return string_hash (decl->decl.automaton.name);
1893}
1894
1895/* The function tests automaton declarations on equality of their
1896 keys. The function is used by abstract data `hashtab'. The
1897 function returns 1 if the declarations have the same key, 0
1898 otherwise. */
1899static int
1900automaton_decl_eq_p (automaton_decl_1, automaton_decl_2)
1901 const void* automaton_decl_1;
1902 const void* automaton_decl_2;
1903{
1904 const decl_t decl1 = (decl_t) automaton_decl_1;
1905 const decl_t decl2 = (decl_t) automaton_decl_2;
1906
1907 if (decl1->mode != dm_automaton || decl1->decl.automaton.name == NULL
1908 || decl2->mode != dm_automaton || decl2->decl.automaton.name == NULL)
1909 abort ();
1910 return strcmp (decl1->decl.automaton.name, decl2->decl.automaton.name) == 0;
1911}
1912
1913/* The automaton declaration table itself is represented by the
1914 following variable. */
1915static htab_t automaton_decl_table;
1916
1917/* The function inserts automaton declaration into the table. The
1918 function does nothing if an automaton declaration with the same key
1919 exists already in the table. The function returns automaton
1920 declaration node in the table with the same key as given automaton
1921 declaration node. */
1922static decl_t
1923insert_automaton_decl (automaton_decl)
1924 decl_t automaton_decl;
1925{
1926 void **entry_ptr;
1927
1928 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
1929 if (*entry_ptr == NULL)
1930 *entry_ptr = (void *) automaton_decl;
1931 return (decl_t) *entry_ptr;
1932}
1933
1934/* The following variable value is node representing automaton
1935 declaration. The node used for searching automaton declaration
1936 with given name. */
1937static struct decl work_automaton_decl;
1938
1939/* The function searches for automaton declaration in the table with
1940 the same key as node representing name of the automaton
1941 declaration. The function returns node found in the table, NULL if
1942 such node does not exist in the table. */
1943static decl_t
1944find_automaton_decl (name)
1945 char *name;
1946{
1947 void *entry;
1948
1949 work_automaton_decl.decl.automaton.name = name;
1950 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1951 return (decl_t) entry;
1952}
1953
1954/* The function creates empty automaton declaration table and node
1955 representing automaton declaration and used for searching automaton
1956 declaration with given name. The function must be called only once
1957 before any work with the automaton declaration table. */
1958static void
1959initiate_automaton_decl_table ()
1960{
1961 work_automaton_decl.mode = dm_automaton;
1962 automaton_decl_table = htab_create (10, automaton_decl_hash,
1963 automaton_decl_eq_p, (htab_del) 0);
1964}
1965
1966/* The function deletes the automaton declaration table. Only call of
1967 function `initiate_automaton_decl_table' is possible immediately
1968 after this function call. */
1969static void
1970finish_automaton_decl_table ()
1971{
1972 htab_delete (automaton_decl_table);
1973}
1974
1975\f
1976
1977/* This page contains abstract data `table of insn declarations'.
1978 Elements of the table is nodes representing insn declarations. Key
1979 of the table elements is name of given insn (in corresponding
1980 define_insn_reservation). Rememeber that insn names have own
1981 space. */
1982
e0a2f705 1983/* The function evaluates hash value of an insn declaration. The
fae15c93
VM
1984 function is used by abstract data `hashtab'. The function returns
1985 hash value (0..UINT_MAX) of given insn declaration. */
1986static unsigned
1987insn_decl_hash (insn_decl)
1988 const void *insn_decl;
1989{
1990 const decl_t decl = (decl_t) insn_decl;
1991
1992 if (decl->mode != dm_insn_reserv || decl->decl.insn_reserv.name == NULL)
1993 abort ();
1994 return string_hash (decl->decl.insn_reserv.name);
1995}
1996
1997/* The function tests insn declarations on equality of their keys.
1998 The function is used by abstract data `hashtab'. The function
1999 returns 1 if declarations have the same key, 0 otherwise. */
2000static int
2001insn_decl_eq_p (insn_decl_1, insn_decl_2)
2002 const void *insn_decl_1;
2003 const void *insn_decl_2;
2004{
2005 const decl_t decl1 = (decl_t) insn_decl_1;
2006 const decl_t decl2 = (decl_t) insn_decl_2;
2007
2008 if (decl1->mode != dm_insn_reserv || decl1->decl.insn_reserv.name == NULL
2009 || decl2->mode != dm_insn_reserv || decl2->decl.insn_reserv.name == NULL)
2010 abort ();
2011 return strcmp (decl1->decl.insn_reserv.name,
2012 decl2->decl.insn_reserv.name) == 0;
2013}
2014
2015/* The insn declaration table itself is represented by the following
2016 variable. The table does not contain insn reservation
2017 declarations. */
2018static htab_t insn_decl_table;
2019
2020/* The function inserts insn declaration into the table. The function
2021 does nothing if an insn declaration with the same key exists
2022 already in the table. The function returns insn declaration node
2023 in the table with the same key as given insn declaration node. */
2024static decl_t
2025insert_insn_decl (insn_decl)
2026 decl_t insn_decl;
2027{
2028 void **entry_ptr;
2029
2030 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
2031 if (*entry_ptr == NULL)
2032 *entry_ptr = (void *) insn_decl;
2033 return (decl_t) *entry_ptr;
2034}
2035
2036/* The following variable value is node representing insn reservation
2037 declaration. The node used for searching insn reservation
2038 declaration with given name. */
2039static struct decl work_insn_decl;
2040
2041/* The function searches for insn reservation declaration in the table
2042 with the same key as node representing name of the insn reservation
2043 declaration. The function returns node found in the table, NULL if
2044 such node does not exist in the table. */
2045static decl_t
2046find_insn_decl (name)
2047 char *name;
2048{
2049 void *entry;
2050
2051 work_insn_decl.decl.insn_reserv.name = name;
2052 entry = htab_find (insn_decl_table, &work_insn_decl);
2053 return (decl_t) entry;
2054}
2055
2056/* The function creates empty insn declaration table and node
2057 representing insn declaration and used for searching insn
2058 declaration with given name. The function must be called only once
2059 before any work with the insn declaration table. */
2060static void
2061initiate_insn_decl_table ()
2062{
2063 work_insn_decl.mode = dm_insn_reserv;
2064 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
2065 (htab_del) 0);
2066}
2067
2068/* The function deletes the insn declaration table. Only call of
2069 function `initiate_insn_decl_table' is possible immediately after
2070 this function call. */
2071static void
2072finish_insn_decl_table ()
2073{
2074 htab_delete (insn_decl_table);
2075}
2076
2077\f
2078
2079/* This page contains abstract data `table of declarations'. Elements
2080 of the table is nodes representing declarations (of units and
2081 reservations). Key of the table elements is names of given
2082 declarations. */
2083
2084/* The function evaluates hash value of a declaration. The function
2085 is used by abstract data `hashtab'. The function returns hash
2086 value (0..UINT_MAX) of given declaration. */
2087static unsigned
2088decl_hash (decl)
2089 const void *decl;
2090{
2091 const decl_t d = (const decl_t) decl;
2092
2093 if ((d->mode != dm_unit || d->decl.unit.name == NULL)
2094 && (d->mode != dm_reserv || d->decl.reserv.name == NULL))
2095 abort ();
2096 return string_hash (d->mode == dm_unit
2097 ? d->decl.unit.name : d->decl.reserv.name);
2098}
2099
2100/* The function tests declarations on equality of their keys. The
2101 function is used by abstract data `hashtab'. The function
2102 returns 1 if the declarations have the same key, 0 otherwise. */
2103static int
2104decl_eq_p (decl_1, decl_2)
2105 const void *decl_1;
2106 const void *decl_2;
2107{
2108 const decl_t d1 = (const decl_t) decl_1;
2109 const decl_t d2 = (const decl_t) decl_2;
2110
2111 if (((d1->mode != dm_unit || d1->decl.unit.name == NULL)
2112 && (d1->mode != dm_reserv || d1->decl.reserv.name == NULL))
2113 || ((d2->mode != dm_unit || d2->decl.unit.name == NULL)
2114 && (d2->mode != dm_reserv || d2->decl.reserv.name == NULL)))
2115 abort ();
2116 return strcmp ((d1->mode == dm_unit
2117 ? d1->decl.unit.name : d1->decl.reserv.name),
2118 (d2->mode == dm_unit
2119 ? d2->decl.unit.name : d2->decl.reserv.name)) == 0;
2120}
2121
2122/* The declaration table itself is represented by the following
2123 variable. */
2124static htab_t decl_table;
2125
2126/* The function inserts declaration into the table. The function does
2127 nothing if a declaration with the same key exists already in the
2128 table. The function returns declaration node in the table with the
2129 same key as given declaration node. */
2130
2131static decl_t
2132insert_decl (decl)
2133 decl_t decl;
2134{
2135 void **entry_ptr;
2136
2137 entry_ptr = htab_find_slot (decl_table, decl, 1);
2138 if (*entry_ptr == NULL)
2139 *entry_ptr = (void *) decl;
2140 return (decl_t) *entry_ptr;
2141}
2142
2143/* The following variable value is node representing declaration. The
2144 node used for searching declaration with given name. */
2145static struct decl work_decl;
2146
2147/* The function searches for declaration in the table with the same
2148 key as node representing name of the declaration. The function
2149 returns node found in the table, NULL if such node does not exist
2150 in the table. */
2151static decl_t
2152find_decl (name)
2153 char *name;
2154{
2155 void *entry;
2156
2157 work_decl.decl.unit.name = name;
2158 entry = htab_find (decl_table, &work_decl);
2159 return (decl_t) entry;
2160}
2161
2162/* The function creates empty declaration table and node representing
2163 declaration and used for searching declaration with given name.
2164 The function must be called only once before any work with the
2165 declaration table. */
2166static void
2167initiate_decl_table ()
2168{
2169 work_decl.mode = dm_unit;
2170 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2171}
2172
2173/* The function deletes the declaration table. Only call of function
2174 `initiate_declaration_table' is possible immediately after this
2175 function call. */
2176static void
2177finish_decl_table ()
2178{
2179 htab_delete (decl_table);
2180}
2181
2182\f
2183
2184/* This page contains checker of pipeline hazard description. */
2185
2186/* Checking NAMES in an exclusion clause vector and returning formed
2187 unit_set_el_list. */
2188static unit_set_el_t
2189process_excls (names, num, excl_pos)
2190 char **names;
2191 int num;
2192 pos_t excl_pos ATTRIBUTE_UNUSED;
2193{
2194 unit_set_el_t el_list;
2195 unit_set_el_t last_el;
2196 unit_set_el_t new_el;
2197 decl_t decl_in_table;
2198 int i;
2199
2200 el_list = NULL;
2201 last_el = NULL;
2202 for (i = 0; i < num; i++)
2203 {
2204 decl_in_table = find_decl (names [i]);
2205 if (decl_in_table == NULL)
2206 error ("unit `%s' in exclusion is not declared", names [i]);
2207 else if (decl_in_table->mode != dm_unit)
2208 error ("`%s' in exclusion is not unit", names [i]);
2209 else
2210 {
2211 new_el = create_node (sizeof (struct unit_set_el));
2212 new_el->unit_decl = &decl_in_table->decl.unit;
2213 new_el->next_unit_set_el = NULL;
2214 if (last_el == NULL)
2215 el_list = last_el = new_el;
2216 else
2217 {
2218 last_el->next_unit_set_el = new_el;
2219 last_el = last_el->next_unit_set_el;
2220 }
2221 }
2222 }
2223 return el_list;
2224}
2225
2226/* The function adds each element from SOURCE_LIST to the exclusion
2227 list of the each element from DEST_LIST. Checking situation "unit
2228 excludes itself". */
2229static void
2230add_excls (dest_list, source_list, excl_pos)
2231 unit_set_el_t dest_list;
2232 unit_set_el_t source_list;
2233 pos_t excl_pos ATTRIBUTE_UNUSED;
2234{
2235 unit_set_el_t dst;
2236 unit_set_el_t src;
2237 unit_set_el_t curr_el;
2238 unit_set_el_t prev_el;
2239 unit_set_el_t copy;
2240
2241 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2242 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2243 {
2244 if (dst->unit_decl == src->unit_decl)
2245 {
2246 error ("unit `%s' excludes itself", src->unit_decl->name);
2247 continue;
2248 }
2249 if (dst->unit_decl->automaton_name != NULL
2250 && src->unit_decl->automaton_name != NULL
2251 && strcmp (dst->unit_decl->automaton_name,
2252 src->unit_decl->automaton_name) != 0)
2253 {
2254 error ("units `%s' and `%s' in exclusion set belong to different automata",
2255 src->unit_decl->name, dst->unit_decl->name);
2256 continue;
2257 }
2258 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2259 curr_el != NULL;
2260 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2261 if (curr_el->unit_decl == src->unit_decl)
2262 break;
2263 if (curr_el == NULL)
2264 {
2265 /* Element not found - insert. */
2266 copy = copy_node (src, sizeof (*src));
2267 copy->next_unit_set_el = NULL;
2268 if (prev_el == NULL)
2269 dst->unit_decl->excl_list = copy;
2270 else
2271 prev_el->next_unit_set_el = copy;
2272 }
2273 }
2274}
2275
2276/* Checking NAMES in an presence clause vector and returning formed
2277 unit_set_el_list. The function is called only after processing all
2278 exclusion sets. */
2279static unit_set_el_t
2280process_presence_absence (names, num, req_pos, presence_p)
2281 char **names;
2282 int num;
2283 pos_t req_pos ATTRIBUTE_UNUSED;
2284 int presence_p;
2285{
2286 unit_set_el_t el_list;
2287 unit_set_el_t last_el;
2288 unit_set_el_t new_el;
2289 decl_t decl_in_table;
2290 int i;
2291
2292 el_list = NULL;
2293 last_el = NULL;
2294 for (i = 0; i < num; i++)
2295 {
2296 decl_in_table = find_decl (names [i]);
2297 if (decl_in_table == NULL)
2298 error ((presence_p
2299 ? "unit `%s' in presence set is not declared"
2300 : "unit `%s' in absence set is not declared"), names [i]);
2301 else if (decl_in_table->mode != dm_unit)
2302 error ((presence_p
2303 ? "`%s' in presence set is not unit"
2304 : "`%s' in absence set is not unit"), names [i]);
2305 else
2306 {
2307 new_el = create_node (sizeof (struct unit_set_el));
2308 new_el->unit_decl = &decl_in_table->decl.unit;
2309 new_el->next_unit_set_el = NULL;
2310 if (last_el == NULL)
2311 el_list = last_el = new_el;
2312 else
2313 {
2314 last_el->next_unit_set_el = new_el;
2315 last_el = last_el->next_unit_set_el;
2316 }
2317 }
2318 }
2319 return el_list;
2320}
2321
2322/* The function adds each element from SOURCE_LIST to presence (if
2323 PRESENCE_P) or absence list of the each element from DEST_LIST.
2324 Checking situations "unit requires own presence", "unit requires
2325 own absence", and "unit excludes and requires presence of ...".
2326 Remember that we process absence sets only after all presence
2327 sets. */
2328static void
2329add_presence_absence (dest_list, source_list, req_pos, presence_p)
2330 unit_set_el_t dest_list;
2331 unit_set_el_t source_list;
2332 pos_t req_pos ATTRIBUTE_UNUSED;
2333 int presence_p;
2334{
2335 unit_set_el_t dst;
2336 unit_set_el_t src;
2337 unit_set_el_t curr_el;
2338 unit_set_el_t prev_el;
2339 unit_set_el_t copy;
2340
2341 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2342 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2343 {
2344 if (dst->unit_decl == src->unit_decl)
2345 {
2346 error ((presence_p
2347 ? "unit `%s' requires own presence"
2348 : "unit `%s' requires own absence"), src->unit_decl->name);
2349 continue;
2350 }
2351 if (dst->unit_decl->automaton_name != NULL
2352 && src->unit_decl->automaton_name != NULL
2353 && strcmp (dst->unit_decl->automaton_name,
2354 src->unit_decl->automaton_name) != 0)
2355 {
2356 error ((presence_p
2357 ? "units `%s' and `%s' in presence set belong to different automata"
2358 : "units `%s' and `%s' in absence set belong to different automata"),
2359 src->unit_decl->name, dst->unit_decl->name);
2360 continue;
2361 }
2362 for (curr_el = (presence_p
2363 ? dst->unit_decl->presence_list
2364 : dst->unit_decl->absence_list), prev_el = NULL;
2365 curr_el != NULL;
2366 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2367 if (curr_el->unit_decl == src->unit_decl)
2368 break;
2369 if (curr_el == NULL)
2370 {
2371 /* Element not found - insert if there is no error. */
2372 int no_error_flag = 1;
2373
2374 if (presence_p)
2375 for (curr_el = dst->unit_decl->excl_list;
2376 curr_el != NULL;
2377 curr_el = curr_el->next_unit_set_el)
2378 {
2379 if (src->unit_decl == curr_el->unit_decl)
2380 {
2381 if (!w_flag)
2382 {
2383 error
2384 ("unit `%s' excludes and requires presence of `%s'",
2385 dst->unit_decl->name, src->unit_decl->name);
2386 no_error_flag = 0;
2387 }
2388 else
2389 warning
2390 ("unit `%s' excludes and requires presence of `%s'",
2391 dst->unit_decl->name, src->unit_decl->name);
2392 }
2393 }
2394 else
2395 for (curr_el = dst->unit_decl->presence_list;
2396 curr_el != NULL;
2397 curr_el = curr_el->next_unit_set_el)
2398 {
2399 if (src->unit_decl == curr_el->unit_decl)
2400 {
2401 if (!w_flag)
2402 {
2403 error
2404 ("unit `%s' requires absence and presence of `%s'",
2405 dst->unit_decl->name, src->unit_decl->name);
2406 no_error_flag = 0;
2407 }
2408 else
2409 warning
2410 ("unit `%s' requires absence and presence of `%s'",
2411 dst->unit_decl->name, src->unit_decl->name);
2412 }
2413 }
2414 if (no_error_flag)
2415 {
2416 copy = copy_node (src, sizeof (*src));
2417 copy->next_unit_set_el = NULL;
2418 if (prev_el == NULL)
2419 {
2420 if (presence_p)
2421 dst->unit_decl->presence_list = copy;
2422 else
2423 dst->unit_decl->absence_list = copy;
2424 }
2425 else
2426 prev_el->next_unit_set_el = copy;
2427 }
2428 }
2429 }
2430}
2431
2432/* The function searches for bypass with given IN_INSN_RESERV in given
2433 BYPASS_LIST. */
2434static struct bypass_decl *
2435find_bypass (bypass_list, in_insn_reserv)
2436 struct bypass_decl *bypass_list;
2437 struct insn_reserv_decl *in_insn_reserv;
2438{
2439 struct bypass_decl *bypass;
2440
2441 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2442 if (bypass->in_insn_reserv == in_insn_reserv)
2443 break;
2444 return bypass;
2445}
2446
2447/* The function processes pipeline description declarations, checks
2448 their correctness, and forms exclusion/presence/absence sets. */
2449static void
2450process_decls ()
2451{
2452 decl_t decl;
2453 decl_t automaton_decl;
2454 decl_t decl_in_table;
2455 decl_t out_insn_reserv;
2456 decl_t in_insn_reserv;
2457 struct bypass_decl *bypass;
2458 int automaton_presence;
2459 int i;
2460
2461 /* Checking repeated automata declarations. */
2462 automaton_presence = 0;
2463 for (i = 0; i < description->decls_num; i++)
2464 {
2465 decl = description->decls [i];
2466 if (decl->mode == dm_automaton)
2467 {
2468 automaton_presence = 1;
2469 decl_in_table = insert_automaton_decl (decl);
2470 if (decl_in_table != decl)
2471 {
2472 if (!w_flag)
2473 error ("repeated declaration of automaton `%s'",
2474 decl->decl.automaton.name);
2475 else
2476 warning ("repeated declaration of automaton `%s'",
2477 decl->decl.automaton.name);
2478 }
2479 }
2480 }
2481 /* Checking undeclared automata, repeated declarations (except for
2482 automata) and correctness of their attributes (insn latency times
2483 etc.). */
2484 for (i = 0; i < description->decls_num; i++)
2485 {
2486 decl = description->decls [i];
2487 if (decl->mode == dm_insn_reserv)
2488 {
2489 decl->decl.insn_reserv.condexp
2490 = check_attr_test (decl->decl.insn_reserv.condexp, 0, 0);
2491 if (decl->decl.insn_reserv.default_latency < 0)
2492 error ("define_insn_reservation `%s' has negative latency time",
2493 decl->decl.insn_reserv.name);
2494 decl->decl.insn_reserv.insn_num = description->insns_num;
2495 description->insns_num++;
2496 decl_in_table = insert_insn_decl (decl);
2497 if (decl_in_table != decl)
2498 error ("`%s' is already used as insn reservation name",
2499 decl->decl.insn_reserv.name);
2500 }
2501 else if (decl->mode == dm_bypass)
2502 {
2503 if (decl->decl.bypass.latency < 0)
2504 error ("define_bypass `%s - %s' has negative latency time",
2505 decl->decl.bypass.out_insn_name,
2506 decl->decl.bypass.in_insn_name);
2507 }
2508 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2509 {
2510 if (decl->mode == dm_unit)
2511 {
2512 decl->decl.unit.automaton_decl = NULL;
2513 if (decl->decl.unit.automaton_name != NULL)
2514 {
2515 automaton_decl
2516 = find_automaton_decl (decl->decl.unit.automaton_name);
2517 if (automaton_decl == NULL)
2518 error ("automaton `%s' is not declared",
2519 decl->decl.unit.automaton_name);
2520 else
2521 {
2522 automaton_decl->decl.automaton.automaton_is_used = 1;
2523 decl->decl.unit.automaton_decl
2524 = &automaton_decl->decl.automaton;
2525 }
2526 }
2527 else if (automaton_presence)
2528 error ("define_unit `%s' without automaton when one defined",
2529 decl->decl.unit.name);
2530 decl->decl.unit.unit_num = description->units_num;
2531 description->units_num++;
2532 if (strcmp (decl->decl.unit.name, NOTHING_NAME) == 0)
2533 {
2534 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2535 continue;
2536 }
2537 decl_in_table = find_decl (decl->decl.unit.name);
2538 }
2539 else
2540 {
2541 if (strcmp (decl->decl.reserv.name, NOTHING_NAME) == 0)
2542 {
2543 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2544 continue;
2545 }
2546 decl_in_table = find_decl (decl->decl.reserv.name);
2547 }
2548 if (decl_in_table == NULL)
2549 decl_in_table = insert_decl (decl);
2550 else
2551 {
2552 if (decl->mode == dm_unit)
2553 error ("repeated declaration of unit `%s'",
2554 decl->decl.unit.name);
2555 else
2556 error ("repeated declaration of reservation `%s'",
2557 decl->decl.reserv.name);
2558 }
2559 }
2560 }
2561 /* Check bypasses and form list of bypasses for each (output)
2562 insn. */
2563 for (i = 0; i < description->decls_num; i++)
2564 {
2565 decl = description->decls [i];
2566 if (decl->mode == dm_bypass)
2567 {
2568 out_insn_reserv = find_insn_decl (decl->decl.bypass.out_insn_name);
2569 in_insn_reserv = find_insn_decl (decl->decl.bypass.in_insn_name);
2570 if (out_insn_reserv == NULL)
2571 error ("there is no insn reservation `%s'",
2572 decl->decl.bypass.out_insn_name);
2573 else if (in_insn_reserv == NULL)
2574 error ("there is no insn reservation `%s'",
2575 decl->decl.bypass.in_insn_name);
2576 else
2577 {
2578 decl->decl.bypass.out_insn_reserv
2579 = &out_insn_reserv->decl.insn_reserv;
2580 decl->decl.bypass.in_insn_reserv
2581 = &in_insn_reserv->decl.insn_reserv;
2582 bypass
2583 = find_bypass (out_insn_reserv->decl.insn_reserv.bypass_list,
2584 decl->decl.bypass.in_insn_reserv);
2585 if (bypass != NULL)
2586 {
2587 if (decl->decl.bypass.latency == bypass->latency)
2588 {
2589 if (!w_flag)
2590 error
2591 ("the same bypass `%s - %s' is already defined",
2592 decl->decl.bypass.out_insn_name,
2593 decl->decl.bypass.in_insn_name);
2594 else
2595 warning
2596 ("the same bypass `%s - %s' is already defined",
2597 decl->decl.bypass.out_insn_name,
2598 decl->decl.bypass.in_insn_name);
2599 }
2600 else
2601 error ("bypass `%s - %s' is already defined",
2602 decl->decl.bypass.out_insn_name,
2603 decl->decl.bypass.in_insn_name);
2604 }
2605 else
2606 {
2607 decl->decl.bypass.next
2608 = out_insn_reserv->decl.insn_reserv.bypass_list;
2609 out_insn_reserv->decl.insn_reserv.bypass_list
2610 = &decl->decl.bypass;
2611 }
2612 }
2613 }
2614 }
2615
2616 /* Check exclusion set declarations and form exclussion sets. */
2617 for (i = 0; i < description->decls_num; i++)
2618 {
2619 decl = description->decls [i];
2620 if (decl->mode == dm_excl)
2621 {
2622 unit_set_el_t unit_set_el_list;
2623 unit_set_el_t unit_set_el_list_2;
2624
2625 unit_set_el_list
2626 = process_excls (decl->decl.excl.names,
2627 decl->decl.excl.first_list_length, decl->pos);
2628 unit_set_el_list_2
2629 = process_excls (&decl->decl.excl.names
2630 [decl->decl.excl.first_list_length],
2631 decl->decl.excl.names_num
2632 - decl->decl.excl.first_list_length,
2633 decl->pos);
2634 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2635 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2636 }
2637 }
2638
2639 /* Check presence set declarations and form presence sets. */
2640 for (i = 0; i < description->decls_num; i++)
2641 {
2642 decl = description->decls [i];
2643 if (decl->mode == dm_presence)
2644 {
2645 unit_set_el_t unit_set_el_list;
2646 unit_set_el_t unit_set_el_list_2;
2647
2648 unit_set_el_list
2649 = process_presence_absence
2650 (decl->decl.presence.names,
2651 decl->decl.presence.first_list_length, decl->pos, 1);
2652 unit_set_el_list_2
2653 = process_presence_absence
2654 (&decl->decl.presence.names
2655 [decl->decl.presence.first_list_length],
2656 decl->decl.presence.names_num
2657 - decl->decl.presence.first_list_length,
2658 decl->pos, 1);
2659 add_presence_absence (unit_set_el_list, unit_set_el_list_2,
2660 decl->pos, 1);
2661 }
2662 }
2663
2664 /* Check absence set declarations and form absence sets. */
2665 for (i = 0; i < description->decls_num; i++)
2666 {
2667 decl = description->decls [i];
2668 if (decl->mode == dm_absence)
2669 {
2670 unit_set_el_t unit_set_el_list;
2671 unit_set_el_t unit_set_el_list_2;
2672
2673 unit_set_el_list
2674 = process_presence_absence
2675 (decl->decl.presence.names,
2676 decl->decl.presence.first_list_length, decl->pos, 0);
2677 unit_set_el_list_2
2678 = process_presence_absence
2679 (&decl->decl.presence.names
2680 [decl->decl.presence.first_list_length],
2681 decl->decl.presence.names_num
2682 - decl->decl.presence.first_list_length,
2683 decl->pos, 0);
2684 add_presence_absence (unit_set_el_list, unit_set_el_list_2,
2685 decl->pos, 0);
2686 }
2687 }
2688}
2689
2690/* The following function checks that declared automaton is used. If
2691 the automaton is not used, the function fixes error/warning. The
2692 following function must be called only after `process_decls'. */
2693static void
2694check_automaton_usage ()
2695{
2696 decl_t decl;
2697 int i;
2698
2699 for (i = 0; i < description->decls_num; i++)
2700 {
2701 decl = description->decls [i];
2702 if (decl->mode == dm_automaton
2703 && !decl->decl.automaton.automaton_is_used)
2704 {
2705 if (!w_flag)
2706 error ("automaton `%s' is not used", decl->decl.automaton.name);
2707 else
2708 warning ("automaton `%s' is not used", decl->decl.automaton.name);
2709 }
2710 }
2711}
2712
2713/* The following recursive function processes all regexp in order to
2714 fix usage of units or reservations and to fix errors of undeclared
2715 name. The function may change unit_regexp onto reserv_regexp.
2716 Remember that reserv_regexp does not exist before the function
2717 call. */
2718static regexp_t
2719process_regexp (regexp)
2720 regexp_t regexp;
2721{
2722 decl_t decl_in_table;
2723 regexp_t new_regexp;
2724 int i;
2725
2726 if (regexp->mode == rm_unit)
2727 {
2728 decl_in_table = find_decl (regexp->regexp.unit.name);
2729 if (decl_in_table == NULL)
2730 error ("undeclared unit or reservation `%s'",
2731 regexp->regexp.unit.name);
2732 else if (decl_in_table->mode == dm_unit)
2733 {
2734 decl_in_table->decl.unit.unit_is_used = 1;
2735 regexp->regexp.unit.unit_decl = &decl_in_table->decl.unit;
2736 }
2737 else if (decl_in_table->mode == dm_reserv)
2738 {
2739 decl_in_table->decl.reserv.reserv_is_used = 1;
2740 new_regexp = create_node (sizeof (struct regexp));
2741 new_regexp->mode = rm_reserv;
2742 new_regexp->pos = regexp->pos;
2743 new_regexp->regexp.reserv.name = regexp->regexp.unit.name;
2744 new_regexp->regexp.reserv.reserv_decl = &decl_in_table->decl.reserv;
2745 regexp = new_regexp;
2746 }
2747 else
2748 abort ();
2749 }
2750 else if (regexp->mode == rm_sequence)
2751 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
2752 regexp->regexp.sequence.regexps [i]
2753 = process_regexp (regexp->regexp.sequence.regexps [i]);
2754 else if (regexp->mode == rm_allof)
2755 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
2756 regexp->regexp.allof.regexps [i]
2757 = process_regexp (regexp->regexp.allof.regexps [i]);
2758 else if (regexp->mode == rm_oneof)
2759 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
2760 regexp->regexp.oneof.regexps [i]
2761 = process_regexp (regexp->regexp.oneof.regexps [i]);
2762 else if (regexp->mode == rm_repeat)
2763 regexp->regexp.repeat.regexp
2764 = process_regexp (regexp->regexp.repeat.regexp);
2765 else if (regexp->mode != rm_nothing)
2766 abort ();
2767 return regexp;
2768}
2769
2770/* The following function processes regexp of define_reservation and
2771 define_insn_reservation with the aid of function
2772 `process_regexp'. */
2773static void
2774process_regexp_decls ()
2775{
2776 decl_t decl;
2777 int i;
2778
2779 for (i = 0; i < description->decls_num; i++)
2780 {
2781 decl = description->decls [i];
2782 if (decl->mode == dm_reserv)
2783 decl->decl.reserv.regexp = process_regexp (decl->decl.reserv.regexp);
2784 else if (decl->mode == dm_insn_reserv)
2785 decl->decl.insn_reserv.regexp
2786 = process_regexp (decl->decl.insn_reserv.regexp);
2787 }
2788}
2789
2790/* The following function checks that declared unit is used. If the
2791 unit is not used, the function fixes errors/warnings. The
2792 following function must be called only after `process_decls',
2793 `process_regexp_decls'. */
2794static void
2795check_usage ()
2796{
2797 decl_t decl;
2798 int i;
2799
2800 for (i = 0; i < description->decls_num; i++)
2801 {
2802 decl = description->decls [i];
2803 if (decl->mode == dm_unit && !decl->decl.unit.unit_is_used)
2804 {
2805 if (!w_flag)
2806 error ("unit `%s' is not used", decl->decl.unit.name);
2807 else
2808 warning ("unit `%s' is not used", decl->decl.unit.name);
2809 }
2810 else if (decl->mode == dm_reserv && !decl->decl.reserv.reserv_is_used)
2811 {
2812 if (!w_flag)
2813 error ("reservation `%s' is not used", decl->decl.reserv.name);
2814 else
2815 warning ("reservation `%s' is not used", decl->decl.reserv.name);
2816 }
2817 }
2818}
2819
2820/* The following variable value is number of reservation being
2821 processed on loop recognition. */
2822static int curr_loop_pass_num;
2823
2824/* The following recursive function returns nonzero value if REGEXP
2825 contains given decl or reservations in given regexp refers for
2826 given decl. */
2827static int
2828loop_in_regexp (regexp, start_decl)
2829 regexp_t regexp;
2830 decl_t start_decl;
2831{
2832 int i;
2833
2834 if (regexp == NULL)
2835 return 0;
2836 if (regexp->mode == rm_unit)
2837 return 0;
2838 else if (regexp->mode == rm_reserv)
2839 {
2840 if (start_decl->mode == dm_reserv
2841 && regexp->regexp.reserv.reserv_decl == &start_decl->decl.reserv)
2842 return 1;
2843 else if (regexp->regexp.reserv.reserv_decl->loop_pass_num
2844 == curr_loop_pass_num)
2845 /* declaration has been processed. */
2846 return 0;
2847 else
2848 {
2849 regexp->regexp.reserv.reserv_decl->loop_pass_num
2850 = curr_loop_pass_num;
2851 return loop_in_regexp (regexp->regexp.reserv.reserv_decl->regexp,
2852 start_decl);
2853 }
2854 }
2855 else if (regexp->mode == rm_sequence)
2856 {
2857 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
2858 if (loop_in_regexp (regexp->regexp.sequence.regexps [i], start_decl))
2859 return 1;
2860 return 0;
2861 }
2862 else if (regexp->mode == rm_allof)
2863 {
2864 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
2865 if (loop_in_regexp (regexp->regexp.allof.regexps [i], start_decl))
2866 return 1;
2867 return 0;
2868 }
2869 else if (regexp->mode == rm_oneof)
2870 {
2871 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
2872 if (loop_in_regexp (regexp->regexp.oneof.regexps [i], start_decl))
2873 return 1;
2874 return 0;
2875 }
2876 else if (regexp->mode == rm_repeat)
2877 return loop_in_regexp (regexp->regexp.repeat.regexp, start_decl);
2878 else
2879 {
2880 if (regexp->mode != rm_nothing)
2881 abort ();
2882 return 0;
2883 }
2884}
2885
2886/* The following function fixes errors "cycle in definition ...". The
2887 function uses function `loop_in_regexp' for that. */
2888static void
2889check_loops_in_regexps ()
2890{
2891 decl_t decl;
2892 int i;
2893
2894 for (i = 0; i < description->decls_num; i++)
2895 {
2896 decl = description->decls [i];
2897 if (decl->mode == dm_reserv)
2898 decl->decl.reserv.loop_pass_num = 0;
2899 }
2900 for (i = 0; i < description->decls_num; i++)
2901 {
2902 decl = description->decls [i];
2903 curr_loop_pass_num = i;
2904
2905 if (decl->mode == dm_reserv)
2906 {
2907 decl->decl.reserv.loop_pass_num = curr_loop_pass_num;
2908 if (loop_in_regexp (decl->decl.reserv.regexp, decl))
2909 {
2910 if (decl->decl.reserv.regexp == NULL)
2911 abort ();
2912 error ("cycle in definition of reservation `%s'",
2913 decl->decl.reserv.name);
2914 }
2915 }
2916 }
2917}
2918
2919/* The function recursively processes IR of reservation and defines
2920 max and min cycle for reservation of unit and for result in the
2921 reservation. */
2922static int
2923process_regexp_cycles (regexp, start_cycle)
2924 regexp_t regexp;
2925 int start_cycle;
2926{
2927 int i;
2928
2929 if (regexp->mode == rm_unit)
2930 {
2931 if (regexp->regexp.unit.unit_decl->max_occ_cycle_num < start_cycle)
2932 regexp->regexp.unit.unit_decl->max_occ_cycle_num = start_cycle;
2933 return start_cycle;
2934 }
2935 else if (regexp->mode == rm_reserv)
2936 return process_regexp_cycles (regexp->regexp.reserv.reserv_decl->regexp,
2937 start_cycle);
2938 else if (regexp->mode == rm_repeat)
2939 {
2940 for (i = 0; i < regexp->regexp.repeat.repeat_num; i++)
2941 start_cycle = process_regexp_cycles (regexp->regexp.repeat.regexp,
2942 start_cycle) + 1;
2943 return start_cycle;
2944 }
2945 else if (regexp->mode == rm_sequence)
2946 {
2947 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
2948 start_cycle
2949 = process_regexp_cycles (regexp->regexp.sequence.regexps [i],
2950 start_cycle) + 1;
2951 return start_cycle;
2952 }
2953 else if (regexp->mode == rm_allof)
2954 {
2955 int finish_cycle = 0;
2956 int cycle;
2957
2958 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
2959 {
2960 cycle = process_regexp_cycles (regexp->regexp.allof.regexps [i],
2961 start_cycle);
2962 if (finish_cycle < cycle)
2963 finish_cycle = cycle;
2964 }
2965 return finish_cycle;
2966 }
2967 else if (regexp->mode == rm_oneof)
2968 {
2969 int finish_cycle = 0;
2970 int cycle;
2971
2972 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
2973 {
2974 cycle = process_regexp_cycles (regexp->regexp.oneof.regexps [i],
2975 start_cycle);
2976 if (finish_cycle < cycle)
2977 finish_cycle = cycle;
2978 }
2979 return finish_cycle;
2980 }
2981 else
2982 {
2983 if (regexp->mode != rm_nothing)
2984 abort ();
2985 return start_cycle;
2986 }
2987}
2988
2989/* The following function is called only for correct program. The
2990 function defines max reservation of insns in cycles. */
2991static void
2992evaluate_max_reserv_cycles ()
2993{
2994 int max_insn_cycles_num;
2995 decl_t decl;
2996 int i;
2997
2998 description->max_insn_reserv_cycles = 0;
2999 for (i = 0; i < description->decls_num; i++)
3000 {
3001 decl = description->decls [i];
3002 if (decl->mode == dm_insn_reserv)
3003 {
3004 max_insn_cycles_num
3005 = process_regexp_cycles (decl->decl.insn_reserv.regexp, 0);
3006 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3007 description->max_insn_reserv_cycles = max_insn_cycles_num;
3008 }
3009 }
deb09eff 3010 description->max_insn_reserv_cycles++;
fae15c93
VM
3011}
3012
3013/* The following function calls functions for checking all
3014 description. */
3015static void
3016check_all_description ()
3017{
3018 process_decls ();
3019 check_automaton_usage ();
3020 process_regexp_decls ();
3021 check_usage ();
3022 check_loops_in_regexps ();
3023 if (!have_error)
3024 evaluate_max_reserv_cycles ();
3025}
3026
3027\f
3028
3029/* The page contains abstract data `ticker'. This data is used to
3030 report time of different phases of building automata. It is
3031 possibly to write a description for which automata will be built
3032 during several minutes even on fast machine. */
3033
3034/* The following function creates ticker and makes it active. */
3035static ticker_t
3036create_ticker ()
3037{
3038 ticker_t ticker;
3039
3040 ticker.modified_creation_time = get_run_time ();
3041 ticker.incremented_off_time = 0;
3042 return ticker;
3043}
3044
3045/* The following function switches off given ticker. */
3046static void
3047ticker_off (ticker)
3048 ticker_t *ticker;
3049{
3050 if (ticker->incremented_off_time == 0)
3051 ticker->incremented_off_time = get_run_time () + 1;
3052}
3053
3054/* The following function switches on given ticker. */
3055static void
3056ticker_on (ticker)
3057 ticker_t *ticker;
3058{
3059 if (ticker->incremented_off_time != 0)
3060 {
3061 ticker->modified_creation_time
3062 += get_run_time () - ticker->incremented_off_time + 1;
3063 ticker->incremented_off_time = 0;
3064 }
3065}
3066
3067/* The following function returns current time in milliseconds since
3068 the moment when given ticker was created. */
3069static int
3070active_time (ticker)
3071 ticker_t ticker;
3072{
3073 if (ticker.incremented_off_time != 0)
3074 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3075 else
3076 return get_run_time () - ticker.modified_creation_time;
3077}
3078
3079/* The following function returns string representation of active time
3080 of given ticker. The result is string representation of seconds
3081 with accuracy of 1/100 second. Only result of the last call of the
3082 function exists. Therefore the following code is not correct
3083
3084 printf ("parser time: %s\ngeneration time: %s\n",
3085 active_time_string (parser_ticker),
3086 active_time_string (generation_ticker));
3087
3088 Correct code has to be the following
3089
3090 printf ("parser time: %s\n", active_time_string (parser_ticker));
3091 printf ("generation time: %s\n",
3092 active_time_string (generation_ticker));
3093
3094*/
3095static void
3096print_active_time (f, ticker)
3097 FILE *f;
3098 ticker_t ticker;
3099{
3100 int msecs;
3101
3102 msecs = active_time (ticker);
3103 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3104}
3105
3106\f
3107
3108/* The following variable value is number of automaton which are
3109 really being created. This value is defined on the base of
3110 argument of option `-split'. If the variable has zero value the
3111 number of automata is defined by the constructions `%automaton'.
3112 This case occures when option `-split' is absent or has zero
3113 argument. If constructions `define_automaton' is absent only one
3114 automaton is created. */
3115static int automata_num;
3116
3117/* The following variable values are times of
3118 o transformation of regular expressions
3119 o building NDFA (DFA if !ndfa_flag)
3120 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3121 o DFA minimization
3122 o building insn equivalence classes
3123 o all previous ones
3124 o code output */
3125static ticker_t transform_time;
3126static ticker_t NDFA_time;
3127static ticker_t NDFA_to_DFA_time;
3128static ticker_t minimize_time;
3129static ticker_t equiv_time;
3130static ticker_t automaton_generation_time;
3131static ticker_t output_time;
3132
3133/* The following variable values are times of
3134 all checking
3135 all generation
3136 all pipeline hazard translator work */
3137static ticker_t check_time;
3138static ticker_t generation_time;
3139static ticker_t all_time;
3140
3141\f
3142
3143/* Pseudo insn decl which denotes advancing cycle. */
3144static decl_t advance_cycle_insn_decl;
3145static void
3146add_advance_cycle_insn_decl ()
3147{
3148 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3149 advance_cycle_insn_decl->mode = dm_insn_reserv;
3150 advance_cycle_insn_decl->pos = no_pos;
3151 advance_cycle_insn_decl->decl.insn_reserv.regexp = NULL;
3152 advance_cycle_insn_decl->decl.insn_reserv.name = (char *) "$advance_cycle";
3153 advance_cycle_insn_decl->decl.insn_reserv.insn_num = description->insns_num;
3154 description->decls [description->decls_num] = advance_cycle_insn_decl;
3155 description->decls_num++;
3156 description->insns_num++;
3157 num_dfa_decls++;
3158}
3159
3160\f
3161/* Abstract data `alternative states' which reperesents
3162 nondeterministic nature of the description (see comments for
3163 structures alt_state and state). */
3164
3165/* List of free states. */
3166static alt_state_t first_free_alt_state;
3167
3168#ifndef NDEBUG
3169/* The following variables is maximal number of allocated nodes
3170 alt_state. */
3171static int allocated_alt_states_num = 0;
3172#endif
3173
3174/* The following function returns free node alt_state. It may be new
3175 allocated node or node freed eralier. */
3176static alt_state_t
3177get_free_alt_state ()
3178{
3179 alt_state_t result;
3180
3181 if (first_free_alt_state != NULL)
3182 {
3183 result = first_free_alt_state;
3184 first_free_alt_state = first_free_alt_state->next_alt_state;
3185 }
3186 else
3187 {
3188#ifndef NDEBUG
3189 allocated_alt_states_num++;
3190#endif
3191 result = create_node (sizeof (struct alt_state));
3192 }
3193 result->state = NULL;
3194 result->next_alt_state = NULL;
3195 result->next_sorted_alt_state = NULL;
3196 return result;
3197}
3198
3199/* The function frees node ALT_STATE. */
3200static void
3201free_alt_state (alt_state)
3202 alt_state_t alt_state;
3203{
3204 if (alt_state == NULL)
3205 return;
3206 alt_state->next_alt_state = first_free_alt_state;
3207 first_free_alt_state = alt_state;
3208}
3209
3210/* The function frees list started with node ALT_STATE_LIST. */
3211static void
3212free_alt_states (alt_states_list)
3213 alt_state_t alt_states_list;
3214{
3215 alt_state_t curr_alt_state;
3216 alt_state_t next_alt_state;
3217
3218 for (curr_alt_state = alt_states_list;
3219 curr_alt_state != NULL;
3220 curr_alt_state = next_alt_state)
3221 {
3222 next_alt_state = curr_alt_state->next_alt_state;
3223 free_alt_state (curr_alt_state);
3224 }
3225}
3226
3227/* The function compares unique numbers of alt states. */
3228static int
3229alt_state_cmp (alt_state_ptr_1, alt_state_ptr_2)
3230 const void *alt_state_ptr_1;
3231 const void *alt_state_ptr_2;
3232{
3233 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3234 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3235 return 0;
3236 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3237 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3238 return -1;
3239 else
3240 return 1;
3241}
3242
3243/* The function sorts ALT_STATES_LIST and removes duplicated alt
3244 states from the list. The comparison key is alt state unique
3245 number. */
3246static alt_state_t
3247uniq_sort_alt_states (alt_states_list)
3248 alt_state_t alt_states_list;
3249{
3250 alt_state_t curr_alt_state;
3251 vla_ptr_t alt_states;
3252 size_t i;
3253 size_t prev_unique_state_ind;
3254 alt_state_t result;
3255 alt_state_t *result_ptr;
3256
3257 VLA_PTR_CREATE (alt_states, 150, "alt_states");
3258 for (curr_alt_state = alt_states_list;
3259 curr_alt_state != NULL;
3260 curr_alt_state = curr_alt_state->next_alt_state)
3261 VLA_PTR_ADD (alt_states, curr_alt_state);
3262 qsort (VLA_PTR_BEGIN (alt_states), VLA_PTR_LENGTH (alt_states),
3263 sizeof (alt_state_t), alt_state_cmp);
3264 if (VLA_PTR_LENGTH (alt_states) == 0)
3265 result = NULL;
3266 else
3267 {
3268 result_ptr = VLA_PTR_BEGIN (alt_states);
3269 prev_unique_state_ind = 0;
3270 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3271 if (result_ptr [prev_unique_state_ind]->state != result_ptr [i]->state)
3272 {
3273 prev_unique_state_ind++;
3274 result_ptr [prev_unique_state_ind] = result_ptr [i];
3275 }
3276#if 0
3277 for (i = prev_unique_state_ind + 1; i < VLA_PTR_LENGTH (alt_states); i++)
3278 free_alt_state (result_ptr [i]);
3279#endif
3280 VLA_PTR_SHORTEN (alt_states, i - prev_unique_state_ind - 1);
3281 result_ptr = VLA_PTR_BEGIN (alt_states);
3282 for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++)
3283 result_ptr [i - 1]->next_sorted_alt_state = result_ptr [i];
3284 result_ptr [i - 1]->next_sorted_alt_state = NULL;
3285 result = *result_ptr;
3286 }
3287 VLA_PTR_DELETE (alt_states);
3288 return result;
3289}
3290
3291/* The function checks equality of alt state lists. Remember that the
3292 lists must be already sorted by the previous function. */
3293static int
3294alt_states_eq (alt_states_1, alt_states_2)
3295 alt_state_t alt_states_1;
3296 alt_state_t alt_states_2;
3297{
3298 while (alt_states_1 != NULL && alt_states_2 != NULL
3299 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3300 {
3301 alt_states_1 = alt_states_1->next_sorted_alt_state;
3302 alt_states_2 = alt_states_2->next_sorted_alt_state;
3303 }
3304 return alt_states_1 == alt_states_2;
3305}
3306
3307/* Initialization of the abstract data. */
3308static void
3309initiate_alt_states ()
3310{
3311 first_free_alt_state = NULL;
3312}
3313
3314/* Finishing work with the abstract data. */
3315static void
3316finish_alt_states ()
3317{
3318}
3319
3320\f
3321
3322/* The page contains macros for work with bits strings. We could use
3323 standard gcc bitmap or sbitmap but it would result in difficulties
3324 of building canadian cross. */
3325
3326/* Set bit number bitno in the bit string. The macro is not side
3327 effect proof. */
3328#define SET_BIT(bitstring, bitno) \
3329 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3330
3331/* Test if bit number bitno in the bitstring is set. The macro is not
3332 side effect proof. */
3333#define TEST_BIT(bitstring, bitno) \
3334 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3335
3336\f
3337
3338/* This page contains abstract data `state'. */
3339
deb09eff 3340/* Maximal length of reservations in cycles (>= 1). */
fae15c93
VM
3341static int max_cycles_num;
3342
3343/* Number of set elements (see type set_el_t) needed for
3344 representation of one cycle reservation. It is depended on units
3345 number. */
3346static int els_in_cycle_reserv;
3347
3348/* Number of set elements (see type set_el_t) needed for
3349 representation of maximal length reservation. Deterministic
3350 reservation is stored as set (bit string) of length equal to the
3351 variable value * number of bits in set_el_t. */
3352static int els_in_reservs;
3353
3354/* VLA for representation of array of pointers to unit
3355 declarations. */
3356static vla_ptr_t units_container;
3357
3358/* The start address of the array. */
deb09eff 3359static unit_decl_t *units_array;
fae15c93
VM
3360
3361/* Empty reservation of maximal length. */
3362static reserv_sets_t empty_reserv;
3363
3364/* The state table itself is represented by the following variable. */
3365static htab_t state_table;
3366
3367/* VLA for representation of array of pointers to free nodes
3368 `state'. */
3369static vla_ptr_t free_states;
3370
3371static int curr_unique_state_num;
3372
3373#ifndef NDEBUG
3374/* The following variables is maximal number of allocated nodes
3375 `state'. */
3376static int allocated_states_num = 0;
3377#endif
3378
3379/* Allocate new reservation set. */
3380static reserv_sets_t
3381alloc_empty_reserv_sets ()
3382{
3383 reserv_sets_t result;
3384
3385 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3386 result = (reserv_sets_t) obstack_base (&irp);
3387 obstack_finish (&irp);
3388 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3389 return result;
3390}
3391
3392/* Hash value of reservation set. */
3393static unsigned
3394reserv_sets_hash_value (reservs)
3395 reserv_sets_t reservs;
3396{
dceb2b75
VM
3397 set_el_t hash_value;
3398 unsigned result;
3399 int reservs_num, i;
fae15c93
VM
3400 set_el_t *reserv_ptr;
3401
3402 hash_value = 0;
3403 reservs_num = els_in_reservs;
3404 reserv_ptr = reservs;
dceb2b75 3405 i = 0;
fae15c93
VM
3406 while (reservs_num != 0)
3407 {
3408 reservs_num--;
dceb2b75
VM
3409 hash_value += ((*reserv_ptr >> i)
3410 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3411 i++;
3412 if (i == sizeof (set_el_t) * CHAR_BIT)
3413 i = 0;
fae15c93
VM
3414 reserv_ptr++;
3415 }
96b1f73b 3416 if (sizeof (set_el_t) <= sizeof (unsigned))
dceb2b75
VM
3417 return hash_value;
3418 result = 0;
b326b2c1 3419 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
dceb2b75
VM
3420 {
3421 result += (unsigned) hash_value;
b326b2c1 3422 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
dceb2b75
VM
3423 }
3424 return result;
fae15c93
VM
3425}
3426
3427/* Comparison of given reservation sets. */
3428static int
3429reserv_sets_cmp (reservs_1, reservs_2)
3430 reserv_sets_t reservs_1;
3431 reserv_sets_t reservs_2;
3432{
3433 int reservs_num;
3434 set_el_t *reserv_ptr_1;
3435 set_el_t *reserv_ptr_2;
3436
3437 if (reservs_1 == NULL || reservs_2 == NULL)
3438 abort ();
3439 reservs_num = els_in_reservs;
3440 reserv_ptr_1 = reservs_1;
3441 reserv_ptr_2 = reservs_2;
3442 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3443 {
3444 reservs_num--;
3445 reserv_ptr_1++;
3446 reserv_ptr_2++;
3447 }
3448 if (reservs_num == 0)
3449 return 0;
3450 else if (*reserv_ptr_1 < *reserv_ptr_2)
3451 return -1;
3452 else
3453 return 1;
3454}
3455
3456/* The function checks equality of the reservation sets. */
3457static int
3458reserv_sets_eq (reservs_1, reservs_2)
3459 reserv_sets_t reservs_1;
3460 reserv_sets_t reservs_2;
3461{
3462 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3463}
3464
3465/* Set up in the reservation set that unit with UNIT_NUM is used on
3466 CYCLE_NUM. */
3467static void
3468set_unit_reserv (reservs, cycle_num, unit_num)
3469 reserv_sets_t reservs;
3470 int cycle_num;
3471 int unit_num;
3472{
3473 if (cycle_num >= max_cycles_num)
3474 abort ();
3475 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3476 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3477}
3478
3479/* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3480 used on CYCLE_NUM. */
3481static int
3482test_unit_reserv (reservs, cycle_num, unit_num)
3483 reserv_sets_t reservs;
3484 int cycle_num;
3485 int unit_num;
3486{
3487 if (cycle_num >= max_cycles_num)
3488 abort ();
3489 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3490 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3491}
3492
3493/* The function checks that the reservation set represents no one unit
3494 reservation. */
3495static int
3496it_is_empty_reserv_sets (operand)
3497 reserv_sets_t operand;
3498{
3499 set_el_t *reserv_ptr;
3500 int reservs_num;
3501
3502 if (operand == NULL)
3503 abort ();
3504 for (reservs_num = els_in_reservs, reserv_ptr = operand;
3505 reservs_num != 0;
3506 reserv_ptr++, reservs_num--)
3507 if (*reserv_ptr != 0)
3508 return 0;
3509 return 1;
3510}
3511
3512/* The function checks that the reservation sets are intersected,
3513 i.e. there is a unit reservation on a cycle in both reservation
3514 sets. */
3515static int
3516reserv_sets_are_intersected (operand_1, operand_2)
3517 reserv_sets_t operand_1;
3518 reserv_sets_t operand_2;
3519{
3520 set_el_t *el_ptr_1;
3521 set_el_t *el_ptr_2;
3522 set_el_t *cycle_ptr_1;
3523 set_el_t *cycle_ptr_2;
3524 int nonzero_p;
3525
3526 if (operand_1 == NULL || operand_2 == NULL)
3527 abort ();
3528 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3529 el_ptr_1 < operand_1 + els_in_reservs;
3530 el_ptr_1++, el_ptr_2++)
3531 if (*el_ptr_1 & *el_ptr_2)
3532 return 1;
3533 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3534 cycle_ptr_1 < operand_1 + els_in_reservs;
3535 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3536 {
3537 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3538 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3539 el_ptr_1++, el_ptr_2++)
3540 if (*el_ptr_1 & *el_ptr_2)
3541 return 1;
3542 nonzero_p = 0;
3543 for (el_ptr_1 = cycle_ptr_1,
3544 el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 1);
3545 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3546 el_ptr_1++, el_ptr_2++)
3547 if (*el_ptr_1 & *el_ptr_2)
3548 break;
3549 else if (*el_ptr_2 != 0)
3550 nonzero_p = 1;
3551 if (nonzero_p && el_ptr_1 >= cycle_ptr_1 + els_in_cycle_reserv)
3552 return 1;
3553 for (el_ptr_1 = cycle_ptr_1,
3554 el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 0);
3555 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3556 el_ptr_1++, el_ptr_2++)
3557 /* It looks like code for exclusion but exclusion set is
3558 made as symmetric relation preliminary. */
3559 if (*el_ptr_1 & *el_ptr_2)
3560 return 1;
3561 }
3562 return 0;
3563}
3564
3565/* The function sets up RESULT bits by bits of OPERAND shifted on one
3566 cpu cycle. The remaining bits of OPERAND (representing the last
3567 cycle unit reservations) are not chenged. */
3568static void
3569reserv_sets_shift (result, operand)
3570 reserv_sets_t result;
3571 reserv_sets_t operand;
3572{
3573 int i;
3574
3575 if (result == NULL || operand == NULL || result == operand)
3576 abort ();
3577 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3578 result [i - els_in_cycle_reserv] = operand [i];
3579}
3580
3581/* OR of the reservation sets. */
3582static void
3583reserv_sets_or (result, operand_1, operand_2)
3584 reserv_sets_t result;
3585 reserv_sets_t operand_1;
3586 reserv_sets_t operand_2;
3587{
3588 set_el_t *el_ptr_1;
3589 set_el_t *el_ptr_2;
3590 set_el_t *result_set_el_ptr;
3591
3592 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3593 abort ();
3594 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3595 el_ptr_1 < operand_1 + els_in_reservs;
3596 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3597 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3598}
3599
3600/* AND of the reservation sets. */
3601static void
3602reserv_sets_and (result, operand_1, operand_2)
3603 reserv_sets_t result;
3604 reserv_sets_t operand_1;
3605 reserv_sets_t operand_2;
3606{
3607 set_el_t *el_ptr_1;
3608 set_el_t *el_ptr_2;
3609 set_el_t *result_set_el_ptr;
3610
3611 if (result == NULL || operand_1 == NULL || operand_2 == NULL)
3612 abort ();
3613 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3614 el_ptr_1 < operand_1 + els_in_reservs;
3615 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3616 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3617}
3618
3619/* The function outputs string representation of units reservation on
3620 cycle START_CYCLE in the reservation set. The function uses repeat
3621 construction if REPETITION_NUM > 1. */
3622static void
3623output_cycle_reservs (f, reservs, start_cycle, repetition_num)
3624 FILE *f;
3625 reserv_sets_t reservs;
3626 int start_cycle;
3627 int repetition_num;
3628{
3629 int unit_num;
3630 int reserved_units_num;
3631
3632 reserved_units_num = 0;
3633 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3634 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3635 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3636 reserved_units_num++;
3637 if (repetition_num <= 0)
3638 abort ();
3639 if (repetition_num != 1 && reserved_units_num > 1)
3640 fprintf (f, "(");
3641 reserved_units_num = 0;
3642 for (unit_num = 0;
3643 unit_num < description->units_num;
3644 unit_num++)
3645 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3646 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3647 {
3648 if (reserved_units_num != 0)
3649 fprintf (f, "+");
3650 reserved_units_num++;
3651 fprintf (f, "%s", units_array [unit_num]->name);
3652 }
3653 if (reserved_units_num == 0)
3654 fprintf (f, NOTHING_NAME);
3655 if (repetition_num <= 0)
3656 abort ();
dceb2b75
VM
3657 if (reserved_units_num > 1)
3658 fprintf (f, ")");
3659 if (repetition_num != 1)
3660 fprintf (f, "*%d", repetition_num);
fae15c93
VM
3661}
3662
3663/* The function outputs string representation of units reservation in
3664 the reservation set. */
3665static void
3666output_reserv_sets (f, reservs)
3667 FILE *f;
3668 reserv_sets_t reservs;
3669{
3670 int start_cycle = 0;
3671 int cycle;
3672 int repetition_num;
3673
3674 repetition_num = 0;
3675 for (cycle = 0; cycle < max_cycles_num; cycle++)
3676 if (repetition_num == 0)
3677 {
3678 repetition_num++;
3679 start_cycle = cycle;
3680 }
3681 else if (memcmp
3682 ((char *) reservs + start_cycle * els_in_cycle_reserv
3683 * sizeof (set_el_t),
3684 (char *) reservs + cycle * els_in_cycle_reserv
3685 * sizeof (set_el_t),
3686 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3687 repetition_num++;
3688 else
3689 {
3690 if (start_cycle != 0)
3691 fprintf (f, ", ");
3692 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3693 repetition_num = 1;
3694 start_cycle = cycle;
3695 }
3696 if (start_cycle < max_cycles_num)
3697 {
3698 if (start_cycle != 0)
3699 fprintf (f, ", ");
3700 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3701 }
3702}
3703
3704/* The following function returns free node state for AUTOMATON. It
3705 may be new allocated node or node freed eralier. The function also
3706 allocates reservation set if WITH_RESERVS has nonzero value. */
3707static state_t
3708get_free_state (with_reservs, automaton)
3709 int with_reservs;
3710 automaton_t automaton;
3711{
3712 state_t result;
3713
3714 if (max_cycles_num <= 0 || automaton == NULL)
3715 abort ();
3716 if (VLA_PTR_LENGTH (free_states) != 0)
3717 {
3718 result = VLA_PTR (free_states, VLA_PTR_LENGTH (free_states) - 1);
3719 VLA_PTR_SHORTEN (free_states, 1);
3720 result->automaton = automaton;
3721 result->first_out_arc = NULL;
3722 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3723 result->it_was_placed_in_stack_for_DFA_forming = 0;
3724 result->component_states = NULL;
3725 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3726 }
3727 else
3728 {
3729#ifndef NDEBUG
3730 allocated_states_num++;
3731#endif
3732 result = create_node (sizeof (struct state));
3733 result->automaton = automaton;
3734 result->first_out_arc = NULL;
3735 result->unique_num = curr_unique_state_num;
3736 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3737 curr_unique_state_num++;
3738 }
3739 if (with_reservs)
3740 {
3741 if (result->reservs == NULL)
3742 result->reservs = alloc_empty_reserv_sets ();
3743 else
3744 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3745 }
3746 return result;
3747}
3748
3749/* The function frees node STATE. */
3750static void
3751free_state (state)
3752 state_t state;
3753{
3754 free_alt_states (state->component_states);
3755 VLA_PTR_ADD (free_states, state);
3756}
3757
3758/* Hash value of STATE. If STATE represents deterministic state it is
3759 simply hash value of the corresponding reservation set. Otherwise
3760 it is formed from hash values of the component deterministic
3761 states. One more key is order number of state automaton. */
3762static unsigned
3763state_hash (state)
3764 const void *state;
3765{
3766 unsigned int hash_value;
3767 alt_state_t alt_state;
3768
3769 if (((state_t) state)->component_states == NULL)
3770 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
3771 else
3772 {
3773 hash_value = 0;
3774 for (alt_state = ((state_t) state)->component_states;
3775 alt_state != NULL;
3776 alt_state = alt_state->next_sorted_alt_state)
3777 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3778 | (hash_value << CHAR_BIT))
3779 + alt_state->state->unique_num);
3780 }
3781 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3782 | (hash_value << CHAR_BIT))
3783 + ((state_t) state)->automaton->automaton_order_num);
3784 return hash_value;
3785}
3786
3787/* Return nonzero value if the states are the same. */
3788static int
3789state_eq_p (state_1, state_2)
3790 const void *state_1;
3791 const void *state_2;
3792{
3793 alt_state_t alt_state_1;
3794 alt_state_t alt_state_2;
3795
3796 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
3797 return 0;
3798 else if (((state_t) state_1)->component_states == NULL
3799 && ((state_t) state_2)->component_states == NULL)
3800 return reserv_sets_eq (((state_t) state_1)->reservs,
3801 ((state_t) state_2)->reservs);
3802 else if (((state_t) state_1)->component_states != NULL
3803 && ((state_t) state_2)->component_states != NULL)
3804 {
3805 for (alt_state_1 = ((state_t) state_1)->component_states,
3806 alt_state_2 = ((state_t) state_2)->component_states;
3807 alt_state_1 != NULL && alt_state_2 != NULL;
3808 alt_state_1 = alt_state_1->next_sorted_alt_state,
3809 alt_state_2 = alt_state_2->next_sorted_alt_state)
3810 /* All state in the list must be already in the hash table.
3811 Also the lists must be sorted. */
3812 if (alt_state_1->state != alt_state_2->state)
3813 return 0;
3814 return alt_state_1 == alt_state_2;
3815 }
3816 else
3817 return 0;
3818}
3819
3820/* Insert STATE into the state table. */
3821static state_t
3822insert_state (state)
3823 state_t state;
3824{
3825 void **entry_ptr;
3826
3827 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
3828 if (*entry_ptr == NULL)
3829 *entry_ptr = (void *) state;
3830 return (state_t) *entry_ptr;
3831}
3832
3833/* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3834 deterministic STATE. */
3835static void
3836set_state_reserv (state, cycle_num, unit_num)
3837 state_t state;
3838 int cycle_num;
3839 int unit_num;
3840{
3841 set_unit_reserv (state->reservs, cycle_num, unit_num);
3842}
3843
3844/* Return nonzero value if the deterministic states contains a
3845 reservation of the same cpu unit on the same cpu cycle. */
3846static int
3847intersected_state_reservs_p (state1, state2)
3848 state_t state1;
3849 state_t state2;
3850{
3851 if (state1->automaton != state2->automaton)
3852 abort ();
3853 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3854}
3855
3856/* Return deterministic state (inserted into the table) which
3857 representing the automaton state whic is union of reservations of
3858 deterministic states. */
3859static state_t
3860states_union (state1, state2)
3861 state_t state1;
3862 state_t state2;
3863{
3864 state_t result;
3865 state_t state_in_table;
3866
3867 if (state1->automaton != state2->automaton)
3868 abort ();
3869 result = get_free_state (1, state1->automaton);
3870 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3871 state_in_table = insert_state (result);
3872 if (result != state_in_table)
3873 {
3874 free_state (result);
3875 result = state_in_table;
3876 }
3877 return result;
3878}
3879
3880/* Return deterministic state (inserted into the table) which
3881 represent the automaton state is obtained from deterministic STATE
3882 by advancing cpu cycle. */
3883static state_t
3884state_shift (state)
3885 state_t state;
3886{
3887 state_t result;
3888 state_t state_in_table;
3889
3890 result = get_free_state (1, state->automaton);
3891 reserv_sets_shift (result->reservs, state->reservs);
3892 state_in_table = insert_state (result);
3893 if (result != state_in_table)
3894 {
3895 free_state (result);
3896 result = state_in_table;
3897 }
3898 return result;
3899}
3900
3901/* Initialization of the abstract data. */
3902static void
3903initiate_states ()
3904{
3905 decl_t decl;
3906 int i;
3907
3908 VLA_PTR_CREATE (units_container, description->units_num, "units_container");
3909 units_array
30cc9d00
VM
3910 = (description->decls_num && description->units_num
3911 ? VLA_PTR_BEGIN (units_container) : NULL);
fae15c93
VM
3912 for (i = 0; i < description->decls_num; i++)
3913 {
3914 decl = description->decls [i];
3915 if (decl->mode == dm_unit)
3916 units_array [decl->decl.unit.unit_num] = &decl->decl.unit;
3917 }
3918 max_cycles_num = description->max_insn_reserv_cycles;
fae15c93
VM
3919 els_in_cycle_reserv
3920 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3921 / (sizeof (set_el_t) * CHAR_BIT));
3922 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3923 curr_unique_state_num = 0;
3924 initiate_alt_states ();
3925 VLA_PTR_CREATE (free_states, 1500, "free states");
3926 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3927 empty_reserv = alloc_empty_reserv_sets ();
3928}
3929
3930/* Finisging work with the abstract data. */
3931static void
3932finish_states ()
3933{
3934 VLA_PTR_DELETE (units_container);
3935 htab_delete (state_table);
3936 VLA_PTR_DELETE (free_states);
3937 finish_alt_states ();
3938}
3939
3940\f
3941
3942/* Abstract data `arcs'. */
3943
3944/* List of free arcs. */
3945static arc_t first_free_arc;
3946
3947#ifndef NDEBUG
3948/* The following variables is maximal number of allocated nodes
3949 `arc'. */
3950static int allocated_arcs_num = 0;
3951#endif
3952
3953/* The function frees node ARC. */
3954static void
3955free_arc (arc)
3956 arc_t arc;
3957{
3958 arc->next_out_arc = first_free_arc;
3959 first_free_arc = arc;
3960}
3961
3962/* The function removes and frees ARC staring from FROM_STATE. */
3963static void
3964remove_arc (from_state, arc)
3965 state_t from_state;
3966 arc_t arc;
3967{
3968 arc_t prev_arc;
3969 arc_t curr_arc;
3970
3971 if (arc == NULL)
3972 abort ();
3973 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3974 curr_arc != NULL;
3975 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3976 if (curr_arc == arc)
3977 break;
3978 if (curr_arc == NULL)
3979 abort ();
3980 if (prev_arc == NULL)
3981 from_state->first_out_arc = arc->next_out_arc;
3982 else
3983 prev_arc->next_out_arc = arc->next_out_arc;
3984 free_arc (arc);
3985}
3986
3987/* The functions returns arc with given characteristics (or NULL if
3988 the arc does not exist). */
3989static arc_t
3990find_arc (from_state, to_state, insn)
3991 state_t from_state;
3992 state_t to_state;
3993 ainsn_t insn;
3994{
3995 arc_t arc;
3996
3997 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3998 if (arc->to_state == to_state && arc->insn == insn)
3999 return arc;
4000 return NULL;
4001}
4002
4003/* The function adds arc from FROM_STATE to TO_STATE marked by AINSN
4004 and with given STATE_ALTS. The function returns added arc (or
4005 already existing arc). */
4006static arc_t
4007add_arc (from_state, to_state, ainsn, state_alts)
4008 state_t from_state;
4009 state_t to_state;
4010 ainsn_t ainsn;
4011 int state_alts;
4012{
4013 arc_t new_arc;
4014
4015 new_arc = find_arc (from_state, to_state, ainsn);
4016 if (new_arc != NULL)
4017 return new_arc;
4018 if (first_free_arc == NULL)
4019 {
4020#ifndef NDEBUG
4021 allocated_arcs_num++;
4022#endif
4023 new_arc = create_node (sizeof (struct arc));
4024 new_arc->to_state = NULL;
4025 new_arc->insn = NULL;
4026 new_arc->next_out_arc = NULL;
4027 }
4028 else
4029 {
4030 new_arc = first_free_arc;
4031 first_free_arc = first_free_arc->next_out_arc;
4032 }
4033 new_arc->to_state = to_state;
4034 new_arc->insn = ainsn;
4035 ainsn->arc_exists_p = 1;
4036 new_arc->next_out_arc = from_state->first_out_arc;
4037 from_state->first_out_arc = new_arc;
4038 new_arc->next_arc_marked_by_insn = NULL;
4039 new_arc->state_alts = state_alts;
4040 return new_arc;
4041}
4042
4043/* The function returns the first arc starting from STATE. */
4044static arc_t
4045first_out_arc (state)
4046 state_t state;
4047{
4048 return state->first_out_arc;
4049}
4050
4051/* The function returns next out arc after ARC. */
4052static arc_t
4053next_out_arc (arc)
4054 arc_t arc;
4055{
4056 return arc->next_out_arc;
4057}
4058
4059/* Initialization of the abstract data. */
4060static void
4061initiate_arcs ()
4062{
4063 first_free_arc = NULL;
4064}
4065
4066/* Finishing work with the abstract data. */
4067static void
4068finish_arcs ()
4069{
4070}
4071
4072\f
4073
4074/* Abstract data `automata lists'. */
4075
4076/* List of free states. */
4077static automata_list_el_t first_free_automata_list_el;
4078
4079/* The list being formed. */
4080static automata_list_el_t current_automata_list;
4081
4082/* Hash table of automata lists. */
4083static htab_t automata_list_table;
4084
4085/* The following function returns free automata list el. It may be
4086 new allocated node or node freed earlier. */
4087static automata_list_el_t
4088get_free_automata_list_el ()
4089{
4090 automata_list_el_t result;
4091
4092 if (first_free_automata_list_el != NULL)
4093 {
4094 result = first_free_automata_list_el;
4095 first_free_automata_list_el
4096 = first_free_automata_list_el->next_automata_list_el;
4097 }
4098 else
4099 result = create_node (sizeof (struct automata_list_el));
4100 result->automaton = NULL;
4101 result->next_automata_list_el = NULL;
4102 return result;
4103}
4104
4105/* The function frees node AUTOMATA_LIST_EL. */
4106static void
4107free_automata_list_el (automata_list_el)
4108 automata_list_el_t automata_list_el;
4109{
4110 if (automata_list_el == NULL)
4111 return;
4112 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4113 first_free_automata_list_el = automata_list_el;
4114}
4115
4116/* The function frees list AUTOMATA_LIST. */
4117static void
4118free_automata_list (automata_list)
4119 automata_list_el_t automata_list;
4120{
4121 automata_list_el_t curr_automata_list_el;
4122 automata_list_el_t next_automata_list_el;
4123
4124 for (curr_automata_list_el = automata_list;
4125 curr_automata_list_el != NULL;
4126 curr_automata_list_el = next_automata_list_el)
4127 {
4128 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4129 free_automata_list_el (curr_automata_list_el);
4130 }
4131}
4132
4133/* Hash value of AUTOMATA_LIST. */
4134static unsigned
4135automata_list_hash (automata_list)
4136 const void *automata_list;
4137{
4138 unsigned int hash_value;
4139 automata_list_el_t curr_automata_list_el;
4140
4141 hash_value = 0;
4142 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4143 curr_automata_list_el != NULL;
4144 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4145 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4146 | (hash_value << CHAR_BIT))
4147 + curr_automata_list_el->automaton->automaton_order_num);
4148 return hash_value;
4149}
4150
4151/* Return nonzero value if the automata_lists are the same. */
4152static int
4153automata_list_eq_p (automata_list_1, automata_list_2)
4154 const void *automata_list_1;
4155 const void *automata_list_2;
4156{
4157 automata_list_el_t automata_list_el_1;
4158 automata_list_el_t automata_list_el_2;
4159
4160 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4161 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4162 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4163 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4164 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4165 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4166 return 0;
4167 return automata_list_el_1 == automata_list_el_2;
4168}
4169
4170/* Initialization of the abstract data. */
4171static void
4172initiate_automata_lists ()
4173{
4174 first_free_automata_list_el = NULL;
4175 automata_list_table = htab_create (1500, automata_list_hash,
4176 automata_list_eq_p, (htab_del) 0);
4177}
4178
4179/* The following function starts new automata list and makes it the
4180 current one. */
4181static void
4182automata_list_start ()
4183{
4184 current_automata_list = NULL;
4185}
4186
4187/* The following function adds AUTOMATON to the current list. */
4188static void
4189automata_list_add (automaton)
4190 automaton_t automaton;
4191{
4192 automata_list_el_t el;
4193
4194 el = get_free_automata_list_el ();
4195 el->automaton = automaton;
4196 el->next_automata_list_el = current_automata_list;
4197 current_automata_list = el;
4198}
4199
4200/* The following function finishes forming the current list, inserts
4201 it into the table and returns it. */
4202static automata_list_el_t
4203automata_list_finish ()
4204{
4205 void **entry_ptr;
4206
4207 if (current_automata_list == NULL)
4208 return NULL;
4209 entry_ptr = htab_find_slot (automata_list_table,
4210 (void *) current_automata_list, 1);
4211 if (*entry_ptr == NULL)
4212 *entry_ptr = (void *) current_automata_list;
4213 else
4214 free_automata_list (current_automata_list);
4215 current_automata_list = NULL;
4216 return (automata_list_el_t) *entry_ptr;
4217}
4218
4219/* Finishing work with the abstract data. */
4220static void
4221finish_automata_lists ()
4222{
4223 htab_delete (automata_list_table);
4224}
4225
4226\f
4227
4228/* The page contains abstract data for work with exclusion sets (see
4229 exclusion_set in file rtl.def). */
4230
4231/* The following variable refers to an exclusion set returned by
4232 get_excl_set. This is bit string of length equal to cpu units
4233 number. If exclusion set for given unit contains 1 for a unit,
4234 then simultaneous reservation of the units is prohibited. */
4235static reserv_sets_t excl_set;
4236
4237/* The array contains exclusion sets for each unit. */
4238static reserv_sets_t *unit_excl_set_table;
4239
4240/* The following function forms the array containing exclusion sets
4241 for each unit. */
4242static void
4243initiate_excl_sets ()
4244{
4245 decl_t decl;
4246 reserv_sets_t unit_excl_set;
4247 unit_set_el_t el;
4248 int i;
4249
4250 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4251 excl_set = (reserv_sets_t) obstack_base (&irp);
4252 obstack_finish (&irp);
4253 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4254 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4255 obstack_finish (&irp);
4256 /* Evaluate unit exclusion sets. */
4257 for (i = 0; i < description->decls_num; i++)
4258 {
4259 decl = description->decls [i];
4260 if (decl->mode == dm_unit)
4261 {
4262 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4263 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4264 obstack_finish (&irp);
4265 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4266 for (el = decl->decl.unit.excl_list;
4267 el != NULL;
4268 el = el->next_unit_set_el)
4269 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4270 unit_excl_set_table [decl->decl.unit.unit_num] = unit_excl_set;
4271 }
4272 }
4273}
4274
4275/* The function sets up and return EXCL_SET which is union of
4276 exclusion sets for each unit in IN_SET. */
4277static reserv_sets_t
4278get_excl_set (in_set)
4279 reserv_sets_t in_set;
4280{
4281 int excl_char_num;
4282 int chars_num;
4283 int i;
4284 int start_unit_num;
4285 int unit_num;
4286
4287 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4288 memset (excl_set, 0, chars_num);
4289 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4290 if (((unsigned char *) in_set) [excl_char_num])
4291 for (i = CHAR_BIT - 1; i >= 0; i--)
4292 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4293 {
4294 start_unit_num = excl_char_num * CHAR_BIT + i;
4295 if (start_unit_num >= description->units_num)
4296 return excl_set;
4297 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4298 {
4299 excl_set [unit_num]
4300 |= unit_excl_set_table [start_unit_num] [unit_num];
4301 }
4302 }
4303 return excl_set;
4304}
4305
4306\f
4307
4308/* The page contains abstract data for work with presence/absence sets
4309 (see presence_set/absence_set in file rtl.def). */
4310
4311/* The following variables refer to correspondingly an presence and an
4312 absence set returned by get_presence_absence_set. This is bit
4313 string of length equal to cpu units number. */
4314static reserv_sets_t presence_set, absence_set;
4315
4316/* The following arrays contain correspondingly presence and absence
4317 sets for each unit. */
4318static reserv_sets_t *unit_presence_set_table, *unit_absence_set_table;
4319
4320/* The following function forms the array containing presence and
4321 absence sets for each unit */
4322static void
4323initiate_presence_absence_sets ()
4324{
4325 decl_t decl;
4326 reserv_sets_t unit_set;
4327 unit_set_el_t el;
4328 int i;
4329
4330 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4331 presence_set = (reserv_sets_t) obstack_base (&irp);
4332 obstack_finish (&irp);
4333 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4334 unit_presence_set_table = (reserv_sets_t *) obstack_base (&irp);
4335 obstack_finish (&irp);
4336 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4337 absence_set = (reserv_sets_t) obstack_base (&irp);
4338 obstack_finish (&irp);
4339 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4340 unit_absence_set_table = (reserv_sets_t *) obstack_base (&irp);
4341 obstack_finish (&irp);
4342 /* Evaluate unit presence/absence sets. */
4343 for (i = 0; i < description->decls_num; i++)
4344 {
4345 decl = description->decls [i];
4346 if (decl->mode == dm_unit)
4347 {
4348 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4349 unit_set = (reserv_sets_t) obstack_base (&irp);
4350 obstack_finish (&irp);
4351 memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4352 for (el = decl->decl.unit.presence_list;
4353 el != NULL;
4354 el = el->next_unit_set_el)
4355 SET_BIT (unit_set, el->unit_decl->unit_num);
4356 unit_presence_set_table [decl->decl.unit.unit_num] = unit_set;
4357
4358 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4359 unit_set = (reserv_sets_t) obstack_base (&irp);
4360 obstack_finish (&irp);
4361 memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4362 for (el = decl->decl.unit.absence_list;
4363 el != NULL;
4364 el = el->next_unit_set_el)
4365 SET_BIT (unit_set, el->unit_decl->unit_num);
4366 unit_absence_set_table [decl->decl.unit.unit_num] = unit_set;
4367 }
4368 }
4369}
4370
4371/* The function sets up and return PRESENCE_SET (if PRESENCE_P) or
4372 ABSENCE_SET which is union of corresponding sets for each unit in
4373 IN_SET. */
4374static reserv_sets_t
4375get_presence_absence_set (in_set, presence_p)
4376 reserv_sets_t in_set;
4377 int presence_p;
4378{
4379 int char_num;
4380 int chars_num;
4381 int i;
4382 int start_unit_num;
4383 int unit_num;
4384
4385 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4386 if (presence_p)
4387 memset (presence_set, 0, chars_num);
4388 else
4389 memset (absence_set, 0, chars_num);
4390 for (char_num = 0; char_num < chars_num; char_num++)
4391 if (((unsigned char *) in_set) [char_num])
4392 for (i = CHAR_BIT - 1; i >= 0; i--)
4393 if ((((unsigned char *) in_set) [char_num] >> i) & 1)
4394 {
4395 start_unit_num = char_num * CHAR_BIT + i;
4396 if (start_unit_num >= description->units_num)
4397 return (presence_p ? presence_set : absence_set);
4398 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4399 if (presence_p)
4400 presence_set [unit_num]
4401 |= unit_presence_set_table [start_unit_num] [unit_num];
4402 else
4403 absence_set [unit_num]
4404 |= unit_absence_set_table [start_unit_num] [unit_num];
4405 }
4406 return (presence_p ? presence_set : absence_set);
4407}
4408
4409\f
4410
4411/* This page contains code for transformation of original reservations
4412 described in .md file. The main goal of transformations is
4413 simplifying reservation and lifting up all `|' on the top of IR
4414 reservation representation. */
4415
4416
4417/* The following function makes copy of IR representation of
4418 reservation. The function also substitutes all reservations
4419 defined by define_reservation by corresponding value during making
4420 the copy. */
4421static regexp_t
4422copy_insn_regexp (regexp)
4423 regexp_t regexp;
4424{
4425 regexp_t result;
4426 int i;
4427
4428 if (regexp->mode == rm_reserv)
4429 result = copy_insn_regexp (regexp->regexp.reserv.reserv_decl->regexp);
4430 else if (regexp->mode == rm_unit)
4431 result = copy_node (regexp, sizeof (struct regexp));
4432 else if (regexp->mode == rm_repeat)
4433 {
4434 result = copy_node (regexp, sizeof (struct regexp));
4435 result->regexp.repeat.regexp
4436 = copy_insn_regexp (regexp->regexp.repeat.regexp);
4437 }
4438 else if (regexp->mode == rm_sequence)
4439 {
4440 result = copy_node (regexp,
4441 sizeof (struct regexp) + sizeof (regexp_t)
4442 * (regexp->regexp.sequence.regexps_num - 1));
4443 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
4444 result->regexp.sequence.regexps [i]
4445 = copy_insn_regexp (regexp->regexp.sequence.regexps [i]);
4446 }
4447 else if (regexp->mode == rm_allof)
4448 {
4449 result = copy_node (regexp,
4450 sizeof (struct regexp) + sizeof (regexp_t)
4451 * (regexp->regexp.allof.regexps_num - 1));
4452 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
4453 result->regexp.allof.regexps [i]
4454 = copy_insn_regexp (regexp->regexp.allof.regexps [i]);
4455 }
4456 else if (regexp->mode == rm_oneof)
4457 {
4458 result = copy_node (regexp,
4459 sizeof (struct regexp) + sizeof (regexp_t)
4460 * (regexp->regexp.oneof.regexps_num - 1));
4461 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
4462 result->regexp.oneof.regexps [i]
4463 = copy_insn_regexp (regexp->regexp.oneof.regexps [i]);
4464 }
4465 else
4466 {
4467 if (regexp->mode != rm_nothing)
4468 abort ();
4469 result = copy_node (regexp, sizeof (struct regexp));
4470 }
4471 return result;
4472}
4473
4474/* The following variable is set up 1 if a transformation has been
4475 applied. */
4476static int regexp_transformed_p;
4477
4478/* The function makes transformation
4479 A*N -> A, A, ... */
4480static regexp_t
4481transform_1 (regexp)
4482 regexp_t regexp;
4483{
4484 int i;
4485 int repeat_num;
4486 regexp_t operand;
4487 pos_t pos;
4488
4489 if (regexp->mode == rm_repeat)
4490 {
4491 repeat_num = regexp->regexp.repeat.repeat_num;
4492 if (repeat_num <= 1)
4493 abort ();
4494 operand = regexp->regexp.repeat.regexp;
4495 pos = regexp->mode;
4496 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4497 * (repeat_num - 1));
4498 regexp->mode = rm_sequence;
4499 regexp->pos = pos;
4500 regexp->regexp.sequence.regexps_num = repeat_num;
4501 for (i = 0; i < repeat_num; i++)
4502 regexp->regexp.sequence.regexps [i] = copy_insn_regexp (operand);
4503 regexp_transformed_p = 1;
4504 }
4505 return regexp;
4506}
4507
4508/* The function makes transformations
4509 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4510 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4511 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4512static regexp_t
4513transform_2 (regexp)
4514 regexp_t regexp;
4515{
4516 if (regexp->mode == rm_sequence)
4517 {
e3c8eb86 4518 regexp_t sequence = NULL;
fae15c93 4519 regexp_t result;
e3c8eb86 4520 int sequence_index = 0;
fae15c93
VM
4521 int i, j;
4522
4523 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
4524 if (regexp->regexp.sequence.regexps [i]->mode == rm_sequence)
4525 {
4526 sequence_index = i;
4527 sequence = regexp->regexp.sequence.regexps [i];
4528 break;
4529 }
4530 if (i < regexp->regexp.sequence.regexps_num)
4531 {
4532 if (sequence->regexp.sequence.regexps_num <= 1
4533 || regexp->regexp.sequence.regexps_num <= 1)
4534 abort ();
4535 result = create_node (sizeof (struct regexp)
4536 + sizeof (regexp_t)
4537 * (regexp->regexp.sequence.regexps_num
4538 + sequence->regexp.sequence.regexps_num
4539 - 2));
4540 result->mode = rm_sequence;
4541 result->pos = regexp->pos;
4542 result->regexp.sequence.regexps_num
4543 = (regexp->regexp.sequence.regexps_num
4544 + sequence->regexp.sequence.regexps_num - 1);
4545 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
4546 if (i < sequence_index)
4547 result->regexp.sequence.regexps [i]
4548 = copy_insn_regexp (regexp->regexp.sequence.regexps [i]);
4549 else if (i > sequence_index)
4550 result->regexp.sequence.regexps
4551 [i + sequence->regexp.sequence.regexps_num - 1]
4552 = copy_insn_regexp (regexp->regexp.sequence.regexps [i]);
4553 else
4554 for (j = 0; j < sequence->regexp.sequence.regexps_num; j++)
4555 result->regexp.sequence.regexps [i + j]
4556 = copy_insn_regexp (sequence->regexp.sequence.regexps [j]);
4557 regexp_transformed_p = 1;
4558 regexp = result;
4559 }
4560 }
4561 else if (regexp->mode == rm_allof)
4562 {
e3c8eb86 4563 regexp_t allof = NULL;
fae15c93 4564 regexp_t result;
e3c8eb86 4565 int allof_index = 0;
fae15c93
VM
4566 int i, j;
4567
4568 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
4569 if (regexp->regexp.allof.regexps [i]->mode == rm_allof)
4570 {
4571 allof_index = i;
4572 allof = regexp->regexp.allof.regexps [i];
4573 break;
4574 }
4575 if (i < regexp->regexp.allof.regexps_num)
4576 {
4577 if (allof->regexp.allof.regexps_num <= 1
4578 || regexp->regexp.allof.regexps_num <= 1)
4579 abort ();
4580 result = create_node (sizeof (struct regexp)
4581 + sizeof (regexp_t)
4582 * (regexp->regexp.allof.regexps_num
4583 + allof->regexp.allof.regexps_num - 2));
4584 result->mode = rm_allof;
4585 result->pos = regexp->pos;
4586 result->regexp.allof.regexps_num
4587 = (regexp->regexp.allof.regexps_num
4588 + allof->regexp.allof.regexps_num - 1);
4589 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
4590 if (i < allof_index)
4591 result->regexp.allof.regexps [i]
4592 = copy_insn_regexp (regexp->regexp.allof.regexps [i]);
4593 else if (i > allof_index)
4594 result->regexp.allof.regexps
4595 [i + allof->regexp.allof.regexps_num - 1]
4596 = copy_insn_regexp (regexp->regexp.allof.regexps [i]);
4597 else
4598 for (j = 0; j < allof->regexp.allof.regexps_num; j++)
4599 result->regexp.allof.regexps [i + j]
4600 = copy_insn_regexp (allof->regexp.allof.regexps [j]);
4601 regexp_transformed_p = 1;
4602 regexp = result;
4603 }
4604 }
4605 else if (regexp->mode == rm_oneof)
4606 {
e3c8eb86 4607 regexp_t oneof = NULL;
fae15c93 4608 regexp_t result;
e3c8eb86 4609 int oneof_index = 0;
fae15c93
VM
4610 int i, j;
4611
4612 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
4613 if (regexp->regexp.oneof.regexps [i]->mode == rm_oneof)
4614 {
4615 oneof_index = i;
4616 oneof = regexp->regexp.oneof.regexps [i];
4617 break;
4618 }
4619 if (i < regexp->regexp.oneof.regexps_num)
4620 {
4621 if (oneof->regexp.oneof.regexps_num <= 1
4622 || regexp->regexp.oneof.regexps_num <= 1)
4623 abort ();
4624 result = create_node (sizeof (struct regexp)
4625 + sizeof (regexp_t)
4626 * (regexp->regexp.oneof.regexps_num
4627 + oneof->regexp.oneof.regexps_num - 2));
4628 result->mode = rm_oneof;
4629 result->pos = regexp->pos;
4630 result->regexp.oneof.regexps_num
4631 = (regexp->regexp.oneof.regexps_num
4632 + oneof->regexp.oneof.regexps_num - 1);
4633 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
4634 if (i < oneof_index)
4635 result->regexp.oneof.regexps [i]
4636 = copy_insn_regexp (regexp->regexp.oneof.regexps [i]);
4637 else if (i > oneof_index)
4638 result->regexp.oneof.regexps
4639 [i + oneof->regexp.oneof.regexps_num - 1]
4640 = copy_insn_regexp (regexp->regexp.oneof.regexps [i]);
4641 else
4642 for (j = 0; j < oneof->regexp.oneof.regexps_num; j++)
4643 result->regexp.oneof.regexps [i + j]
4644 = copy_insn_regexp (oneof->regexp.oneof.regexps [j]);
4645 regexp_transformed_p = 1;
4646 regexp = result;
4647 }
4648 }
4649 return regexp;
4650}
4651
4652/* The function makes transformations
4653 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
317638a8 4654 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
dceb2b75
VM
4655 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4656 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
fae15c93
VM
4657static regexp_t
4658transform_3 (regexp)
4659 regexp_t regexp;
4660{
4661 if (regexp->mode == rm_sequence)
4662 {
e3c8eb86
VM
4663 regexp_t oneof = NULL;
4664 int oneof_index = 0;
fae15c93
VM
4665 regexp_t result;
4666 regexp_t sequence;
4667 int i, j;
4668
4669 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
4670 if (regexp->regexp.sequence.regexps [i]->mode == rm_oneof)
4671 {
4672 oneof_index = i;
4673 oneof = regexp->regexp.sequence.regexps [i];
4674 break;
4675 }
4676 if (i < regexp->regexp.sequence.regexps_num)
4677 {
4678 if (oneof->regexp.oneof.regexps_num <= 1
4679 || regexp->regexp.sequence.regexps_num <= 1)
4680 abort ();
4681 result = create_node (sizeof (struct regexp)
4682 + sizeof (regexp_t)
4683 * (oneof->regexp.oneof.regexps_num - 1));
4684 result->mode = rm_oneof;
4685 result->pos = regexp->pos;
4686 result->regexp.oneof.regexps_num = oneof->regexp.oneof.regexps_num;
4687 for (i = 0; i < result->regexp.oneof.regexps_num; i++)
4688 {
4689 sequence
4690 = create_node (sizeof (struct regexp)
4691 + sizeof (regexp_t)
4692 * (regexp->regexp.sequence.regexps_num - 1));
4693 sequence->mode = rm_sequence;
4694 sequence->pos = regexp->pos;
4695 sequence->regexp.sequence.regexps_num
4696 = regexp->regexp.sequence.regexps_num;
4697 result->regexp.oneof.regexps [i] = sequence;
4698 for (j = 0; j < sequence->regexp.sequence.regexps_num; j++)
4699 if (j != oneof_index)
4700 sequence->regexp.sequence.regexps [j]
4701 = copy_insn_regexp (regexp->regexp.sequence.regexps [j]);
4702 else
4703 sequence->regexp.sequence.regexps [j]
4704 = copy_insn_regexp (oneof->regexp.oneof.regexps [i]);
4705 }
4706 regexp_transformed_p = 1;
4707 regexp = result;
4708 }
4709 }
4710 else if (regexp->mode == rm_allof)
4711 {
e3c8eb86
VM
4712 regexp_t oneof = NULL, seq;
4713 int oneof_index = 0, max_seq_length, allof_length;
fae15c93 4714 regexp_t result;
e3c8eb86 4715 regexp_t allof = NULL, allof_op;
fae15c93
VM
4716 int i, j;
4717
4718 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
4719 if (regexp->regexp.allof.regexps [i]->mode == rm_oneof)
4720 {
4721 oneof_index = i;
4722 oneof = regexp->regexp.allof.regexps [i];
4723 break;
4724 }
4725 if (i < regexp->regexp.allof.regexps_num)
4726 {
4727 if (oneof->regexp.oneof.regexps_num <= 1
4728 || regexp->regexp.allof.regexps_num <= 1)
4729 abort ();
4730 result = create_node (sizeof (struct regexp)
4731 + sizeof (regexp_t)
4732 * (oneof->regexp.oneof.regexps_num - 1));
4733 result->mode = rm_oneof;
4734 result->pos = regexp->pos;
4735 result->regexp.oneof.regexps_num = oneof->regexp.oneof.regexps_num;
4736 for (i = 0; i < result->regexp.oneof.regexps_num; i++)
4737 {
4738 allof
4739 = create_node (sizeof (struct regexp)
4740 + sizeof (regexp_t)
4741 * (regexp->regexp.allof.regexps_num - 1));
4742 allof->mode = rm_allof;
4743 allof->pos = regexp->pos;
4744 allof->regexp.allof.regexps_num
4745 = regexp->regexp.allof.regexps_num;
4746 result->regexp.oneof.regexps [i] = allof;
4747 for (j = 0; j < allof->regexp.allof.regexps_num; j++)
4748 if (j != oneof_index)
4749 allof->regexp.allof.regexps [j]
4750 = copy_insn_regexp (regexp->regexp.allof.regexps [j]);
4751 else
4752 allof->regexp.allof.regexps [j]
4753 = copy_insn_regexp (oneof->regexp.oneof.regexps [i]);
4754 }
4755 regexp_transformed_p = 1;
4756 regexp = result;
4757 }
dceb2b75 4758 max_seq_length = 0;
317638a8
VM
4759 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
4760 if (regexp->regexp.allof.regexps [i]->mode == rm_sequence)
4761 {
317638a8 4762 seq = regexp->regexp.allof.regexps [i];
dceb2b75
VM
4763 if (max_seq_length < seq->regexp.sequence.regexps_num)
4764 max_seq_length = seq->regexp.sequence.regexps_num;
4765 }
4766 else if (regexp->regexp.allof.regexps [i]->mode != rm_unit)
4767 {
4768 max_seq_length = 0;
317638a8
VM
4769 break;
4770 }
dceb2b75 4771 if (max_seq_length != 0)
317638a8 4772 {
dceb2b75 4773 if (max_seq_length == 1 || regexp->regexp.allof.regexps_num <= 1)
317638a8
VM
4774 abort ();
4775 result = create_node (sizeof (struct regexp)
dceb2b75 4776 + sizeof (regexp_t) * (max_seq_length - 1));
317638a8
VM
4777 result->mode = rm_sequence;
4778 result->pos = regexp->pos;
dceb2b75
VM
4779 result->regexp.sequence.regexps_num = max_seq_length;
4780 for (i = 0; i < max_seq_length; i++)
4781 {
4782 allof_length = 0;
4783 for (j = 0; j < regexp->regexp.allof.regexps_num; j++)
4784 if (regexp->regexp.allof.regexps [j]->mode == rm_sequence
4785 && (i < (regexp->regexp.allof.regexps [j]
4786 ->regexp.sequence.regexps_num)))
4787 {
4788 allof_op = (regexp->regexp.allof.regexps [j]
4789 ->regexp.sequence.regexps [i]);
4790 allof_length++;
4791 }
4792 else if (i == 0
4793 && regexp->regexp.allof.regexps [j]->mode == rm_unit)
4794 {
4795 allof_op = regexp->regexp.allof.regexps [j];
4796 allof_length++;
4797 }
4798 if (allof_length == 1)
4799 result->regexp.sequence.regexps [i] = allof_op;
4800 else
4801 {
4802 allof = create_node (sizeof (struct regexp)
4803 + sizeof (regexp_t)
4804 * (allof_length - 1));
4805 allof->mode = rm_allof;
4806 allof->pos = regexp->pos;
4807 allof->regexp.allof.regexps_num = allof_length;
4808 result->regexp.sequence.regexps [i] = allof;
4809 allof_length = 0;
4810 for (j = 0; j < regexp->regexp.allof.regexps_num; j++)
4811 if (regexp->regexp.allof.regexps [j]->mode == rm_sequence
4812 && (i < (regexp->regexp.allof.regexps [j]
4813 ->regexp.sequence.regexps_num)))
4814 {
4815 allof_op = (regexp->regexp.allof.regexps [j]
4816 ->regexp.sequence.regexps [i]);
4817 allof->regexp.allof.regexps [allof_length] = allof_op;
4818
4819 allof_length++;
4820 }
4821 else if (i == 0
4822 && (regexp->regexp.allof.regexps [j]->mode
4823 == rm_unit))
4824 {
4825 allof_op = regexp->regexp.allof.regexps [j];
4826 allof->regexp.allof.regexps [allof_length] = allof_op;
4827 allof_length++;
4828 }
4829 }
4830 }
317638a8
VM
4831 regexp_transformed_p = 1;
4832 regexp = result;
4833 }
fae15c93
VM
4834 }
4835 return regexp;
4836}
4837
4838/* The function traverses IR of reservation and applies transformations
4839 implemented by FUNC. */
4840static regexp_t
4841regexp_transform_func (regexp, func)
4842 regexp_t regexp;
4843 regexp_t (*func) PARAMS ((regexp_t regexp));
4844{
4845 int i;
4846
4847 if (regexp->mode == rm_sequence)
4848 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
4849 regexp->regexp.sequence.regexps [i]
4850 = regexp_transform_func (regexp->regexp.sequence.regexps [i], func);
4851 else if (regexp->mode == rm_allof)
4852 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
4853 regexp->regexp.allof.regexps [i]
4854 = regexp_transform_func (regexp->regexp.allof.regexps [i], func);
4855 else if (regexp->mode == rm_oneof)
4856 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
4857 regexp->regexp.oneof.regexps [i]
4858 = regexp_transform_func (regexp->regexp.oneof.regexps [i], func);
4859 else if (regexp->mode == rm_repeat)
4860 regexp->regexp.repeat.regexp
4861 = regexp_transform_func (regexp->regexp.repeat.regexp, func);
4862 else if (regexp->mode != rm_nothing && regexp->mode != rm_unit)
4863 abort ();
4864 return (*func) (regexp);
4865}
4866
4867/* The function applies all transformations for IR representation of
4868 reservation REGEXP. */
4869static regexp_t
4870transform_regexp (regexp)
4871 regexp_t regexp;
4872{
4873 regexp = regexp_transform_func (regexp, transform_1);
4874 do
4875 {
4876 regexp_transformed_p = 0;
4877 regexp = regexp_transform_func (regexp, transform_2);
4878 regexp = regexp_transform_func (regexp, transform_3);
4879 }
4880 while (regexp_transformed_p);
4881 return regexp;
4882}
4883
4884/* The function applys all transformations for reservations of all
4885 insn declarations. */
4886static void
4887transform_insn_regexps ()
4888{
4889 decl_t decl;
4890 int i;
4891
deb09eff
VM
4892 transform_time = create_ticker ();
4893 add_advance_cycle_insn_decl ();
4894 fprintf (stderr, "Reservation transformation...");
4895 fflush (stderr);
fae15c93
VM
4896 for (i = 0; i < description->decls_num; i++)
4897 {
4898 decl = description->decls [i];
4899 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4900 decl->decl.insn_reserv.transformed_regexp
4901 = transform_regexp (copy_insn_regexp
4902 (decl->decl.insn_reserv.regexp));
4903 }
deb09eff
VM
4904 fprintf (stderr, "done\n");
4905 ticker_off (&transform_time);
4906 fflush (stderr);
4907}
4908
4909\f
4910
4911/* The following variable is an array indexed by cycle. Each element
4912 contains cyclic list of units which should be in the same cycle. */
4913static unit_decl_t *the_same_automaton_lists;
4914
4915/* The function processes all alternative reservations on CYCLE in
4916 given REGEXP to check the UNIT is not reserved on the all
4917 alternatives. If it is true, the unit should be in the same
4918 automaton with other analogous units reserved on CYCLE in given
4919 REGEXP. */
4920static void
4921process_unit_to_form_the_same_automaton_unit_lists (unit, regexp, cycle)
4922 regexp_t unit;
4923 regexp_t regexp;
4924 int cycle;
4925{
4926 int i, k;
4927 regexp_t seq, allof;
4928 unit_decl_t unit_decl, last;
4929
4930 if (regexp == NULL || regexp->mode != rm_oneof)
4931 abort ();
4932 unit_decl = unit->regexp.unit.unit_decl;
4933 for (i = regexp->regexp.oneof.regexps_num - 1; i >= 0; i--)
4934 {
4935 seq = regexp->regexp.oneof.regexps [i];
4936 if (seq->mode == rm_sequence)
4937 {
4938 if (cycle >= seq->regexp.sequence.regexps_num)
4939 break;
4940 allof = seq->regexp.sequence.regexps [cycle];
4941 if (allof->mode == rm_allof)
4942 {
4943 for (k = 0; k < allof->regexp.allof.regexps_num; k++)
4944 if (allof->regexp.allof.regexps [k]->mode == rm_unit
4945 && (allof->regexp.allof.regexps [k]->regexp.unit.unit_decl
4946 == unit_decl))
4947 break;
4948 if (k >= allof->regexp.allof.regexps_num)
4949 break;
4950 }
4951 else if (allof->mode == rm_unit
4952 && allof->regexp.unit.unit_decl != unit_decl)
4953 break;
4954 }
4955 else if (cycle != 0)
4956 break;
4957 else if (seq->mode == rm_allof)
4958 {
4959 for (k = 0; k < seq->regexp.allof.regexps_num; k++)
4960 if (seq->regexp.allof.regexps [k]->mode == rm_unit
4961 && (seq->regexp.allof.regexps [k]->regexp.unit.unit_decl
4962 == unit_decl))
4963 break;
4964 if (k >= seq->regexp.allof.regexps_num)
4965 break;
4966 }
4967 else if (seq->mode == rm_unit && seq->regexp.unit.unit_decl != unit_decl)
4968 break;
4969 }
4970 if (i >= 0)
4971 {
4972 if (the_same_automaton_lists [cycle] == NULL)
4973 the_same_automaton_lists [cycle] = unit_decl;
4974 else
4975 {
4976 for (last = the_same_automaton_lists [cycle];;)
4977 {
4978 if (last == unit_decl)
4979 return;
4980 if (last->the_same_automaton_unit
4981 == the_same_automaton_lists [cycle])
4982 break;
4983 last = last->the_same_automaton_unit;
4984 }
4985 last->the_same_automaton_unit = unit_decl->the_same_automaton_unit;
4986 unit_decl->the_same_automaton_unit
4987 = the_same_automaton_lists [cycle];
4988 }
4989 }
4990}
4991
4992/* The function processes given REGEXP to find units which should be
4993 in the same automaton. */
4994static void
4995form_the_same_automaton_unit_lists_from_regexp (regexp)
4996 regexp_t regexp;
4997{
4998 int i, j, k;
4999 regexp_t seq, allof, unit;
5000
5001 if (regexp == NULL || regexp->mode != rm_oneof)
5002 return;
5003 for (i = 0; i < description->max_insn_reserv_cycles; i++)
5004 the_same_automaton_lists [i] = NULL;
5005 for (i = regexp->regexp.oneof.regexps_num - 1; i >= 0; i--)
5006 {
5007 seq = regexp->regexp.oneof.regexps [i];
5008 if (seq->mode == rm_sequence)
5009 for (j = 0; j < seq->regexp.sequence.regexps_num; j++)
5010 {
5011 allof = seq->regexp.sequence.regexps [j];
5012 if (allof->mode == rm_allof)
5013 for (k = 0; k < allof->regexp.allof.regexps_num; k++)
5014 {
5015 unit = allof->regexp.allof.regexps [k];
5016 if (unit->mode == rm_unit)
5017 process_unit_to_form_the_same_automaton_unit_lists
5018 (unit, regexp, j);
83e0be55 5019 else if (unit->mode != rm_nothing)
deb09eff
VM
5020 abort ();
5021 }
5022 else if (allof->mode == rm_unit)
5023 process_unit_to_form_the_same_automaton_unit_lists
5024 (allof, regexp, j);
5025 else if (allof->mode != rm_nothing)
5026 abort ();
5027 }
5028 else if (seq->mode == rm_allof)
5029 for (k = 0; k < seq->regexp.allof.regexps_num; k++)
5030 {
5031 unit = seq->regexp.allof.regexps [k];
5032 if (unit->mode == rm_unit)
5033 process_unit_to_form_the_same_automaton_unit_lists
5034 (unit, regexp, 0);
5035 else if (unit->mode != rm_nothing)
5036 abort ();
5037 }
5038 else if (seq->mode == rm_unit)
5039 process_unit_to_form_the_same_automaton_unit_lists (seq, regexp, 0);
5040 else if (seq->mode != rm_nothing)
5041 abort ();
5042 }
5043}
5044
5045/* The function initializes data to search for units which should be
5046 in the same automaton and call function
5047 `form_the_same_automaton_unit_lists_from_regexp' for each insn
5048 reservation regexp. */
5049static void
5050form_the_same_automaton_unit_lists ()
5051{
5052 decl_t decl;
5053 int i;
5054
5055 the_same_automaton_lists
5056 = (unit_decl_t *) xmalloc (description->max_insn_reserv_cycles
5057 * sizeof (unit_decl_t));
5058 for (i = 0; i < description->decls_num; i++)
5059 {
5060 decl = description->decls [i];
5061 if (decl->mode == dm_unit)
5062 {
5063 decl->decl.unit.the_same_automaton_message_reported_p = FALSE;
5064 decl->decl.unit.the_same_automaton_unit = &decl->decl.unit;
5065 }
5066 }
5067 for (i = 0; i < description->decls_num; i++)
5068 {
5069 decl = description->decls [i];
5070 if (decl->mode == dm_insn_reserv)
5071 form_the_same_automaton_unit_lists_from_regexp
5072 (decl->decl.insn_reserv.transformed_regexp);
5073 }
5074 free (the_same_automaton_lists);
5075}
5076
5077/* The function finds units which should be in the same automaton and,
5078 if they are not, reports about it. */
5079static void
5080check_unit_distributions_to_automata ()
5081{
5082 decl_t decl;
5083 unit_decl_t start_unit_decl, unit_decl;
5084 int i;
5085
5086 form_the_same_automaton_unit_lists ();
5087 for (i = 0; i < description->decls_num; i++)
5088 {
5089 decl = description->decls [i];
5090 if (decl->mode == dm_unit)
5091 {
5092 start_unit_decl = &decl->decl.unit;
5093 if (!start_unit_decl->the_same_automaton_message_reported_p)
5094 for (unit_decl = start_unit_decl->the_same_automaton_unit;
5095 unit_decl != start_unit_decl;
5096 unit_decl = unit_decl->the_same_automaton_unit)
5097 if (start_unit_decl->automaton_decl != unit_decl->automaton_decl)
5098 {
5099 error ("Units `%s' and `%s' should be in the same automaton",
5100 start_unit_decl->name, unit_decl->name);
5101 unit_decl->the_same_automaton_message_reported_p = TRUE;
5102 }
5103 }
5104 }
fae15c93
VM
5105}
5106
5107\f
5108
5109/* The page contains code for building alt_states (see comments for
5110 IR) describing all possible insns reservations of an automaton. */
5111
5112/* Current state being formed for which the current alt_state
5113 refers. */
5114static state_t state_being_formed;
5115
5116/* Current alt_state being formed. */
5117static alt_state_t alt_state_being_formed;
5118
5119/* This recursive function processes `,' and units in reservation
5120 REGEXP for forming alt_states of AUTOMATON. It is believed that
5121 CURR_CYCLE is start cycle of all reservation REGEXP. */
5122static int
5123process_seq_for_forming_states (regexp, automaton, curr_cycle)
5124 regexp_t regexp;
5125 automaton_t automaton;
5126 int curr_cycle;
5127{
5128 int i;
5129
5130 if (regexp == NULL)
5131 return curr_cycle;
5132 else if (regexp->mode == rm_unit)
5133 {
5134 if (regexp->regexp.unit.unit_decl->corresponding_automaton_num
5135 == automaton->automaton_order_num)
5136 set_state_reserv (state_being_formed, curr_cycle,
5137 regexp->regexp.unit.unit_decl->unit_num);
5138 return curr_cycle;
5139 }
5140 else if (regexp->mode == rm_sequence)
5141 {
5142 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
5143 curr_cycle
5144 = process_seq_for_forming_states
5145 (regexp->regexp.sequence.regexps [i], automaton, curr_cycle) + 1;
5146 return curr_cycle;
5147 }
5148 else if (regexp->mode == rm_allof)
5149 {
5150 int finish_cycle = 0;
5151 int cycle;
5152
5153 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
5154 {
5155 cycle
5156 = process_seq_for_forming_states (regexp->regexp.allof.regexps [i],
5157 automaton, curr_cycle);
5158 if (finish_cycle < cycle)
5159 finish_cycle = cycle;
5160 }
5161 return finish_cycle;
5162 }
5163 else
5164 {
5165 if (regexp->mode != rm_nothing)
5166 abort ();
5167 return curr_cycle;
5168 }
5169}
5170
5171/* This recursive function finishes forming ALT_STATE of AUTOMATON and
5172 inserts alt_state into the table. */
5173static void
5174finish_forming_alt_state (alt_state, automaton)
5175 alt_state_t alt_state;
5176 automaton_t automaton ATTRIBUTE_UNUSED;
5177{
5178 state_t state_in_table;
5179 state_t corresponding_state;
5180
5181 corresponding_state = alt_state->state;
5182 state_in_table = insert_state (corresponding_state);
5183 if (state_in_table != corresponding_state)
5184 {
5185 free_state (corresponding_state);
5186 alt_state->state = state_in_table;
5187 }
5188}
5189
5190/* The following variable value is current automaton insn for whose
5191 reservation the alt states are created. */
5192static ainsn_t curr_ainsn;
5193
5194/* This recursive function processes `|' in reservation REGEXP for
5195 forming alt_states of AUTOMATON. List of the alt states should
5196 have the same order as in the description. */
5197static void
5198process_alts_for_forming_states (regexp, automaton, inside_oneof_p)
5199 regexp_t regexp;
5200 automaton_t automaton;
5201 int inside_oneof_p;
5202{
5203 int i;
5204
5205 if (regexp->mode != rm_oneof)
5206 {
5207 alt_state_being_formed = get_free_alt_state ();
5208 state_being_formed = get_free_state (1, automaton);
5209 alt_state_being_formed->state = state_being_formed;
5210 /* We inserts in reverse order but we process alternatives also
5211 in reverse order. So we have the same order of alternative
5212 as in the description. */
5213 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5214 curr_ainsn->alt_states = alt_state_being_formed;
5215 (void) process_seq_for_forming_states (regexp, automaton, 0);
5216 finish_forming_alt_state (alt_state_being_formed, automaton);
5217 }
5218 else
5219 {
5220 if (inside_oneof_p)
5221 abort ();
5222 /* We processes it in reverse order to get list with the same
5223 order as in the description. See also the previous
5224 commentary. */
5225 for (i = regexp->regexp.oneof.regexps_num - 1; i >= 0; i--)
5226 process_alts_for_forming_states (regexp->regexp.oneof.regexps [i],
5227 automaton, 1);
5228 }
5229}
5230
5231/* Create nodes alt_state for all AUTOMATON insns. */
5232static void
5233create_alt_states (automaton)
5234 automaton_t automaton;
5235{
5236 struct insn_reserv_decl *reserv_decl;
5237
5238 for (curr_ainsn = automaton->ainsn_list;
5239 curr_ainsn != NULL;
5240 curr_ainsn = curr_ainsn->next_ainsn)
5241 {
5242 reserv_decl = curr_ainsn->insn_reserv_decl;
5243 if (reserv_decl != &advance_cycle_insn_decl->decl.insn_reserv)
5244 {
5245 curr_ainsn->alt_states = NULL;
5246 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5247 automaton, 0);
5248 curr_ainsn->sorted_alt_states
5249 = uniq_sort_alt_states (curr_ainsn->alt_states);
5250 }
5251 }
5252}
5253
5254\f
5255
5256/* The page contains major code for building DFA(s) for fast pipeline
5257 hazards recognition. */
5258
5259/* The function forms list of ainsns of AUTOMATON with the same
5260 reservation. */
5261static void
5262form_ainsn_with_same_reservs (automaton)
5263 automaton_t automaton;
5264{
5265 ainsn_t curr_ainsn;
5266 size_t i;
5267 vla_ptr_t first_insns;
5268 vla_ptr_t last_insns;
5269
5270 VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs");
5271 VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs");
5272 for (curr_ainsn = automaton->ainsn_list;
5273 curr_ainsn != NULL;
5274 curr_ainsn = curr_ainsn->next_ainsn)
5275 if (curr_ainsn->insn_reserv_decl
5276 == &advance_cycle_insn_decl->decl.insn_reserv)
5277 {
5278 curr_ainsn->next_same_reservs_insn = NULL;
5279 curr_ainsn->first_insn_with_same_reservs = 1;
5280 }
5281 else
5282 {
5283 for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++)
5284 if (alt_states_eq
5285 (curr_ainsn->sorted_alt_states,
5286 ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states))
5287 break;
5288 curr_ainsn->next_same_reservs_insn = NULL;
5289 if (i < VLA_PTR_LENGTH (first_insns))
5290 {
5291 curr_ainsn->first_insn_with_same_reservs = 0;
5292 ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn
5293 = curr_ainsn;
5294 VLA_PTR (last_insns, i) = curr_ainsn;
5295 }
5296 else
5297 {
5298 VLA_PTR_ADD (first_insns, curr_ainsn);
5299 VLA_PTR_ADD (last_insns, curr_ainsn);
5300 curr_ainsn->first_insn_with_same_reservs = 1;
5301 }
5302 }
5303 VLA_PTR_DELETE (first_insns);
5304 VLA_PTR_DELETE (last_insns);
5305}
5306
5307/* The following function creates all states of nondeterministic (if
5308 NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */
5309static void
5310make_automaton (automaton)
5311 automaton_t automaton;
5312{
5313 ainsn_t ainsn;
5314 struct insn_reserv_decl *insn_reserv_decl;
5315 alt_state_t alt_state;
5316 state_t state;
5317 state_t start_state;
5318 state_t state2;
5319 ainsn_t advance_cycle_ainsn;
5320 arc_t added_arc;
5321 vla_ptr_t state_stack;
5322
5323 VLA_PTR_CREATE (state_stack, 150, "state stack");
5324 /* Create the start state (empty state). */
5325 start_state = insert_state (get_free_state (1, automaton));
5326 automaton->start_state = start_state;
5327 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5328 VLA_PTR_ADD (state_stack, start_state);
5329 while (VLA_PTR_LENGTH (state_stack) != 0)
5330 {
5331 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5332 VLA_PTR_SHORTEN (state_stack, 1);
5333 advance_cycle_ainsn = NULL;
5334 for (ainsn = automaton->ainsn_list;
5335 ainsn != NULL;
5336 ainsn = ainsn->next_ainsn)
5337 if (ainsn->first_insn_with_same_reservs)
5338 {
5339 insn_reserv_decl = ainsn->insn_reserv_decl;
5340 if (insn_reserv_decl != &advance_cycle_insn_decl->decl.insn_reserv)
5341 {
5342 /* We process alt_states in the same order as they are
5343 present in the description. */
5344 added_arc = NULL;
5345 for (alt_state = ainsn->alt_states;
5346 alt_state != NULL;
5347 alt_state = alt_state->next_alt_state)
5348 {
5349 state2 = alt_state->state;
5350 if (!intersected_state_reservs_p (state, state2))
5351 {
5352 state2 = states_union (state, state2);
5353 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5354 {
5355 state2->it_was_placed_in_stack_for_NDFA_forming
5356 = 1;
5357 VLA_PTR_ADD (state_stack, state2);
5358 }
5359 added_arc = add_arc (state, state2, ainsn, 1);
5360 if (!ndfa_flag)
5361 break;
5362 }
5363 }
5364 if (!ndfa_flag && added_arc != NULL)
5365 {
5366 added_arc->state_alts = 0;
5367 for (alt_state = ainsn->alt_states;
5368 alt_state != NULL;
5369 alt_state = alt_state->next_alt_state)
5370 {
5371 state2 = alt_state->state;
5372 if (!intersected_state_reservs_p (state, state2))
5373 added_arc->state_alts++;
5374 }
5375 }
5376 }
5377 else
5378 advance_cycle_ainsn = ainsn;
5379 }
5380 /* Add transition to advance cycle. */
5381 state2 = state_shift (state);
5382 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5383 {
5384 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5385 VLA_PTR_ADD (state_stack, state2);
5386 }
5387 if (advance_cycle_ainsn == NULL)
5388 abort ();
5389 add_arc (state, state2, advance_cycle_ainsn, 1);
5390 }
5391 VLA_PTR_DELETE (state_stack);
5392}
5393
5394/* Foms lists of all arcs of STATE marked by the same ainsn. */
5395static void
5396form_arcs_marked_by_insn (state)
5397 state_t state;
5398{
5399 decl_t decl;
5400 arc_t arc;
5401 int i;
5402
5403 for (i = 0; i < description->decls_num; i++)
5404 {
5405 decl = description->decls [i];
5406 if (decl->mode == dm_insn_reserv)
5407 decl->decl.insn_reserv.arcs_marked_by_insn = NULL;
5408 }
5409 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5410 {
5411 if (arc->insn == NULL)
5412 abort ();
5413 arc->next_arc_marked_by_insn
5414 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5415 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5416 }
5417}
5418
5419/* The function creates composed state (see comments for IR) from
5420 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5421 same insn. If the composed state is not in STATE_STACK yet, it is
5422 popped to STATE_STACK. */
5423static void
5424create_composed_state (original_state, arcs_marked_by_insn, state_stack)
5425 state_t original_state;
5426 arc_t arcs_marked_by_insn;
5427 vla_ptr_t *state_stack;
5428{
5429 state_t state;
5430 alt_state_t curr_alt_state;
5431 alt_state_t new_alt_state;
5432 arc_t curr_arc;
5433 arc_t next_arc;
5434 state_t state_in_table;
5435 state_t temp_state;
5436 alt_state_t canonical_alt_states_list;
5437 int alts_number;
5438
5439 if (arcs_marked_by_insn == NULL)
5440 return;
5441 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5442 state = arcs_marked_by_insn->to_state;
5443 else
5444 {
5445 if (!ndfa_flag)
5446 abort ();
5447 /* Create composed state. */
5448 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5449 curr_alt_state = NULL;
5450 for (curr_arc = arcs_marked_by_insn;
5451 curr_arc != NULL;
5452 curr_arc = curr_arc->next_arc_marked_by_insn)
5453 {
5454 new_alt_state = get_free_alt_state ();
5455 new_alt_state->next_alt_state = curr_alt_state;
5456 new_alt_state->state = curr_arc->to_state;
5457 if (curr_arc->to_state->component_states != NULL)
5458 abort ();
5459 curr_alt_state = new_alt_state;
5460 }
5461 /* There are not identical sets in the alt state list. */
5462 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5463 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5464 {
5465 temp_state = state;
5466 state = canonical_alt_states_list->state;
5467 free_state (temp_state);
5468 }
5469 else
5470 {
5471 state->component_states = canonical_alt_states_list;
5472 state_in_table = insert_state (state);
5473 if (state_in_table != state)
5474 {
5475 if (!state_in_table->it_was_placed_in_stack_for_DFA_forming)
5476 abort ();
5477 free_state (state);
5478 state = state_in_table;
5479 }
5480 else
5481 {
5482 if (state->it_was_placed_in_stack_for_DFA_forming)
5483 abort ();
5484 for (curr_alt_state = state->component_states;
5485 curr_alt_state != NULL;
5486 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5487 for (curr_arc = first_out_arc (curr_alt_state->state);
5488 curr_arc != NULL;
5489 curr_arc = next_out_arc (curr_arc))
5490 add_arc (state, curr_arc->to_state, curr_arc->insn, 1);
5491 }
5492 arcs_marked_by_insn->to_state = state;
5493 for (alts_number = 0,
5494 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5495 curr_arc != NULL;
5496 curr_arc = next_arc)
5497 {
5498 next_arc = curr_arc->next_arc_marked_by_insn;
5499 remove_arc (original_state, curr_arc);
5500 alts_number++;
5501 }
5502 arcs_marked_by_insn->state_alts = alts_number;
5503 }
5504 }
5505 if (!state->it_was_placed_in_stack_for_DFA_forming)
5506 {
5507 state->it_was_placed_in_stack_for_DFA_forming = 1;
5508 VLA_PTR_ADD (*state_stack, state);
5509 }
5510}
5511
5512/* The function transformes nondeterminstic AUTOMATON into
5513 deterministic. */
5514static void
5515NDFA_to_DFA (automaton)
5516 automaton_t automaton;
5517{
5518 state_t start_state;
5519 state_t state;
5520 decl_t decl;
5521 vla_ptr_t state_stack;
5522 int i;
5523
5524 VLA_PTR_CREATE (state_stack, 150, "state stack");
5525 /* Create the start state (empty state). */
5526 start_state = automaton->start_state;
5527 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5528 VLA_PTR_ADD (state_stack, start_state);
5529 while (VLA_PTR_LENGTH (state_stack) != 0)
5530 {
5531 state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1);
5532 VLA_PTR_SHORTEN (state_stack, 1);
5533 form_arcs_marked_by_insn (state);
5534 for (i = 0; i < description->decls_num; i++)
5535 {
5536 decl = description->decls [i];
5537 if (decl->mode == dm_insn_reserv)
5538 create_composed_state
5539 (state, decl->decl.insn_reserv.arcs_marked_by_insn,
5540 &state_stack);
5541 }
5542 }
5543 VLA_PTR_DELETE (state_stack);
5544}
5545
5546/* The following variable value is current number (1, 2, ...) of passing
5547 graph of states. */
5548static int curr_state_graph_pass_num;
5549
5550/* This recursive function passes all states achieved from START_STATE
5551 and applies APPLIED_FUNC to them. */
5552static void
5553pass_state_graph (start_state, applied_func)
5554 state_t start_state;
5555 void (*applied_func) PARAMS ((state_t state));
5556{
5557 arc_t arc;
5558
5559 if (start_state->pass_num == curr_state_graph_pass_num)
5560 return;
5561 start_state->pass_num = curr_state_graph_pass_num;
5562 (*applied_func) (start_state);
5563 for (arc = first_out_arc (start_state);
5564 arc != NULL;
5565 arc = next_out_arc (arc))
5566 pass_state_graph (arc->to_state, applied_func);
5567}
5568
5569/* This recursive function passes all states of AUTOMATON and applies
5570 APPLIED_FUNC to them. */
5571static void
5572pass_states (automaton, applied_func)
5573 automaton_t automaton;
5574 void (*applied_func) PARAMS ((state_t state));
5575{
5576 curr_state_graph_pass_num++;
5577 pass_state_graph (automaton->start_state, applied_func);
5578}
5579
5580/* The function initializes code for passing of all states. */
5581static void
5582initiate_pass_states ()
5583{
5584 curr_state_graph_pass_num = 0;
5585}
5586
5587/* The following vla is used for storing pointers to all achieved
5588 states. */
5589static vla_ptr_t all_achieved_states;
5590
5591/* This function is called by function pass_states to add an achieved
5592 STATE. */
5593static void
5594add_achieved_state (state)
5595 state_t state;
5596{
5597 VLA_PTR_ADD (all_achieved_states, state);
5598}
5599
5600/* The function sets up equivalence numbers of insns which mark all
5601 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5602 nonzero value) or by equiv_class_num_2 of the destination state.
5603 The function returns number of out arcs of STATE. */
5604static int
5605set_out_arc_insns_equiv_num (state, odd_iteration_flag)
5606 state_t state;
5607 int odd_iteration_flag;
5608{
5609 int state_out_arcs_num;
5610 arc_t arc;
5611
5612 state_out_arcs_num = 0;
5613 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5614 {
5615 if (arc->insn->insn_reserv_decl->equiv_class_num != 0
5616 || arc->insn->insn_reserv_decl->state_alts != 0)
5617 abort ();
5618 state_out_arcs_num++;
5619 arc->insn->insn_reserv_decl->equiv_class_num
5620 = (odd_iteration_flag
5621 ? arc->to_state->equiv_class_num_1
5622 : arc->to_state->equiv_class_num_2);
5623 arc->insn->insn_reserv_decl->state_alts = arc->state_alts;
5624 if (arc->insn->insn_reserv_decl->equiv_class_num == 0
5625 || arc->insn->insn_reserv_decl->state_alts <= 0)
5626 abort ();
5627 }
5628 return state_out_arcs_num;
5629}
5630
5631/* The function clears equivalence numbers and alt_states in all insns
5632 which mark all out arcs of STATE. */
5633static void
5634clear_arc_insns_equiv_num (state)
5635 state_t state;
5636{
5637 arc_t arc;
5638
5639 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5640 {
5641 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5642 arc->insn->insn_reserv_decl->state_alts = 0;
5643 }
5644}
5645
5646/* The function copies pointers to equivalent states from vla FROM
5647 into vla TO. */
5648static void
5649copy_equiv_class (to, from)
5650 vla_ptr_t *to;
5651 const vla_ptr_t *from;
5652{
5653 state_t *class_ptr;
5654
5655 VLA_PTR_NULLIFY (*to);
5656 for (class_ptr = VLA_PTR_BEGIN (*from);
5657 class_ptr <= (state_t *) VLA_PTR_LAST (*from);
5658 class_ptr++)
5659 VLA_PTR_ADD (*to, *class_ptr);
5660}
5661
5662/* The function returns nonzero value if STATE is not equivalent to
5663 another state from the same current partition on equivalence
5664 classes Another state has ORIGINAL_STATE_OUT_ARCS_NUM number of
5665 output arcs. Iteration of making equivalence partition is defined
5666 by ODD_ITERATION_FLAG. */
5667static int
5668state_is_differed (state, original_state_out_arcs_num, odd_iteration_flag)
5669 state_t state;
5670 int original_state_out_arcs_num;
5671 int odd_iteration_flag;
5672{
5673 arc_t arc;
5674 int state_out_arcs_num;
5675
5676 state_out_arcs_num = 0;
5677 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5678 {
5679 state_out_arcs_num++;
5680 if ((odd_iteration_flag
5681 ? arc->to_state->equiv_class_num_1
5682 : arc->to_state->equiv_class_num_2)
5683 != arc->insn->insn_reserv_decl->equiv_class_num
5684 || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts))
5685 return 1;
5686 }
5687 return state_out_arcs_num != original_state_out_arcs_num;
5688}
5689
5690/* The function makes initial partition of STATES on equivalent
5691 classes. */
5692static state_t
5693init_equiv_class (states, states_num)
5694 state_t *states;
5695 int states_num;
5696{
5697 state_t *state_ptr;
5698 state_t result_equiv_class;
5699
5700 result_equiv_class = NULL;
5701 for (state_ptr = states; state_ptr < states + states_num; state_ptr++)
5702 {
5703 (*state_ptr)->equiv_class_num_1 = 1;
5704 (*state_ptr)->next_equiv_class_state = result_equiv_class;
5705 result_equiv_class = *state_ptr;
5706 }
5707 return result_equiv_class;
5708}
5709
5710/* The function processes equivalence class given by its pointer
5711 EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there
5712 are not equvalent states, the function partitions the class
5713 removing nonequivalent states and placing them in
5714 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5715 assigns it to the state equivalence number. If the class has been
deb09eff 5716 partitioned, the function returns nonzero value. */
fae15c93
VM
5717static int
5718partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
5719 next_iteration_classes, new_equiv_class_num_ptr)
5720 state_t *equiv_class_ptr;
5721 int odd_iteration_flag;
5722 vla_ptr_t *next_iteration_classes;
5723 int *new_equiv_class_num_ptr;
5724{
5725 state_t new_equiv_class;
5726 int partition_p;
5727 state_t first_state;
5728 state_t curr_state;
5729 state_t prev_state;
5730 state_t next_state;
5731 int out_arcs_num;
5732
5733 partition_p = 0;
5734 if (*equiv_class_ptr == NULL)
5735 abort ();
5736 for (first_state = *equiv_class_ptr;
5737 first_state != NULL;
5738 first_state = new_equiv_class)
5739 {
5740 new_equiv_class = NULL;
5741 if (first_state->next_equiv_class_state != NULL)
5742 {
5743 /* There are more one states in the class equivalence. */
5744 out_arcs_num = set_out_arc_insns_equiv_num (first_state,
5745 odd_iteration_flag);
5746 for (prev_state = first_state,
5747 curr_state = first_state->next_equiv_class_state;
5748 curr_state != NULL;
5749 curr_state = next_state)
5750 {
5751 next_state = curr_state->next_equiv_class_state;
5752 if (state_is_differed (curr_state, out_arcs_num,
5753 odd_iteration_flag))
5754 {
5755 /* Remove curr state from the class equivalence. */
5756 prev_state->next_equiv_class_state = next_state;
5757 /* Add curr state to the new class equivalence. */
5758 curr_state->next_equiv_class_state = new_equiv_class;
5759 if (new_equiv_class == NULL)
5760 (*new_equiv_class_num_ptr)++;
5761 if (odd_iteration_flag)
5762 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5763 else
5764 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5765 new_equiv_class = curr_state;
5766 partition_p = 1;
5767 }
5768 else
5769 prev_state = curr_state;
5770 }
5771 clear_arc_insns_equiv_num (first_state);
5772 }
5773 if (new_equiv_class != NULL)
5774 VLA_PTR_ADD (*next_iteration_classes, new_equiv_class);
5775 }
5776 return partition_p;
5777}
5778
5779/* The function finds equivalent states of AUTOMATON. */
5780static void
5781evaluate_equiv_classes (automaton, equiv_classes)
5782 automaton_t automaton;
5783 vla_ptr_t *equiv_classes;
5784{
5785 state_t new_equiv_class;
5786 int new_equiv_class_num;
5787 int odd_iteration_flag;
5788 int finish_flag;
5789 vla_ptr_t next_iteration_classes;
5790 state_t *equiv_class_ptr;
5791 state_t *state_ptr;
5792
5793 VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states");
5794 pass_states (automaton, add_achieved_state);
5795 new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states),
5796 VLA_PTR_LENGTH (all_achieved_states));
5797 odd_iteration_flag = 0;
5798 new_equiv_class_num = 1;
5799 VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes");
5800 VLA_PTR_ADD (next_iteration_classes, new_equiv_class);
5801 do
5802 {
5803 odd_iteration_flag = !odd_iteration_flag;
5804 finish_flag = 1;
5805 copy_equiv_class (equiv_classes, &next_iteration_classes);
5806 /* Transfer equiv numbers for the next iteration. */
5807 for (state_ptr = VLA_PTR_BEGIN (all_achieved_states);
5808 state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states);
5809 state_ptr++)
5810 if (odd_iteration_flag)
5811 (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1;
5812 else
5813 (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2;
5814 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
5815 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
5816 equiv_class_ptr++)
5817 if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag,
5818 &next_iteration_classes,
5819 &new_equiv_class_num))
5820 finish_flag = 0;
5821 }
5822 while (!finish_flag);
5823 VLA_PTR_DELETE (next_iteration_classes);
5824 VLA_PTR_DELETE (all_achieved_states);
5825}
5826
5827/* The function merges equivalent states of AUTOMATON. */
5828static void
5829merge_states (automaton, equiv_classes)
5830 automaton_t automaton;
5831 vla_ptr_t *equiv_classes;
5832{
5833 state_t *equiv_class_ptr;
5834 state_t curr_state;
5835 state_t new_state;
5836 state_t first_class_state;
5837 alt_state_t alt_states;
5838 alt_state_t new_alt_state;
5839 arc_t curr_arc;
5840 arc_t next_arc;
5841
5842 /* Create states corresponding to equivalence classes containing two
5843 or more states. */
5844 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
5845 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
5846 equiv_class_ptr++)
5847 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
5848 {
5849 /* There are more one states in the class equivalence. */
5850 /* Create new compound state. */
5851 new_state = get_free_state (0, automaton);
5852 alt_states = NULL;
5853 first_class_state = *equiv_class_ptr;
5854 for (curr_state = first_class_state;
5855 curr_state != NULL;
5856 curr_state = curr_state->next_equiv_class_state)
5857 {
5858 curr_state->equiv_class_state = new_state;
5859 new_alt_state = get_free_alt_state ();
5860 new_alt_state->state = curr_state;
5861 new_alt_state->next_sorted_alt_state = alt_states;
5862 alt_states = new_alt_state;
5863 }
5864 new_state->component_states = alt_states;
5865 }
5866 else
5867 (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr;
5868 for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes);
5869 equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes);
5870 equiv_class_ptr++)
5871 if ((*equiv_class_ptr)->next_equiv_class_state != NULL)
5872 {
5873 first_class_state = *equiv_class_ptr;
5874 /* Create new arcs output from the state corresponding to
5875 equiv class. */
5876 for (curr_arc = first_out_arc (first_class_state);
5877 curr_arc != NULL;
5878 curr_arc = next_out_arc (curr_arc))
5879 add_arc (first_class_state->equiv_class_state,
5880 curr_arc->to_state->equiv_class_state,
5881 curr_arc->insn, curr_arc->state_alts);
5882 /* Delete output arcs from states of given class equivalence. */
5883 for (curr_state = first_class_state;
5884 curr_state != NULL;
5885 curr_state = curr_state->next_equiv_class_state)
5886 {
5887 if (automaton->start_state == curr_state)
5888 automaton->start_state = curr_state->equiv_class_state;
5889 /* Delete the state and its output arcs. */
5890 for (curr_arc = first_out_arc (curr_state);
5891 curr_arc != NULL;
5892 curr_arc = next_arc)
5893 {
5894 next_arc = next_out_arc (curr_arc);
5895 free_arc (curr_arc);
5896 }
5897 }
5898 }
5899 else
5900 {
5901 /* Change `to_state' of arcs output from the state of given
5902 equivalence class. */
5903 for (curr_arc = first_out_arc (*equiv_class_ptr);
5904 curr_arc != NULL;
5905 curr_arc = next_out_arc (curr_arc))
5906 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
5907 }
5908}
5909
5910/* The function sets up new_cycle_p for states if there is arc to the
5911 state marked by advance_cycle_insn_decl. */
5912static void
5913set_new_cycle_flags (state)
5914 state_t state;
5915{
5916 arc_t arc;
5917
5918 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5919 if (arc->insn->insn_reserv_decl
5920 == &advance_cycle_insn_decl->decl.insn_reserv)
5921 arc->to_state->new_cycle_p = 1;
5922}
5923
5924/* The top level function for minimization of deterministic
5925 AUTOMATON. */
5926static void
5927minimize_DFA (automaton)
5928 automaton_t automaton;
5929{
5930 vla_ptr_t equiv_classes;
5931
5932 VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes");
5933 evaluate_equiv_classes (automaton, &equiv_classes);
5934 merge_states (automaton, &equiv_classes);
5935 pass_states (automaton, set_new_cycle_flags);
5936 VLA_PTR_DELETE (equiv_classes);
5937}
5938
5939/* Values of two variables are counted number of states and arcs in an
5940 automaton. */
5941static int curr_counted_states_num;
5942static int curr_counted_arcs_num;
5943
5944/* The function is called by function `pass_states' to count states
5945 and arcs of an automaton. */
5946static void
5947incr_states_and_arcs_nums (state)
5948 state_t state;
5949{
5950 arc_t arc;
5951
5952 curr_counted_states_num++;
5953 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5954 curr_counted_arcs_num++;
5955}
5956
5957/* The function counts states and arcs of AUTOMATON. */
5958static void
5959count_states_and_arcs (automaton, states_num, arcs_num)
5960 automaton_t automaton;
5961 int *states_num;
5962 int *arcs_num;
5963{
5964 curr_counted_states_num = 0;
5965 curr_counted_arcs_num = 0;
5966 pass_states (automaton, incr_states_and_arcs_nums);
5967 *states_num = curr_counted_states_num;
5968 *arcs_num = curr_counted_arcs_num;
5969}
5970
5971/* The function builds one DFA AUTOMATON for fast pipeline hazards
5972 recognition after checking and simplifying IR of the
5973 description. */
5974static void
5975build_automaton (automaton)
5976 automaton_t automaton;
5977{
5978 int states_num;
5979 int arcs_num;
5980
5981 ticker_on (&NDFA_time);
5982 make_automaton (automaton);
5983 ticker_off (&NDFA_time);
5984 count_states_and_arcs (automaton, &states_num, &arcs_num);
5985 automaton->NDFA_states_num = states_num;
5986 automaton->NDFA_arcs_num = arcs_num;
5987 ticker_on (&NDFA_to_DFA_time);
5988 NDFA_to_DFA (automaton);
5989 ticker_off (&NDFA_to_DFA_time);
5990 count_states_and_arcs (automaton, &states_num, &arcs_num);
5991 automaton->DFA_states_num = states_num;
5992 automaton->DFA_arcs_num = arcs_num;
5993 if (!no_minimization_flag)
5994 {
5995 ticker_on (&minimize_time);
5996 minimize_DFA (automaton);
5997 ticker_off (&minimize_time);
5998 count_states_and_arcs (automaton, &states_num, &arcs_num);
5999 automaton->minimal_DFA_states_num = states_num;
6000 automaton->minimal_DFA_arcs_num = arcs_num;
6001 }
6002}
6003
6004\f
6005
6006/* The page contains code for enumeration of all states of an automaton. */
6007
6008/* Variable used for enumeration of all states of an automaton. Its
6009 value is current number of automaton states. */
6010static int curr_state_order_num;
6011
6012/* The function is called by function `pass_states' for enumerating
6013 states. */
6014static void
6015set_order_state_num (state)
6016 state_t state;
6017{
6018 state->order_state_num = curr_state_order_num;
6019 curr_state_order_num++;
6020}
6021
6022/* The function enumerates all states of AUTOMATON. */
6023static void
6024enumerate_states (automaton)
6025 automaton_t automaton;
6026{
6027 curr_state_order_num = 0;
6028 pass_states (automaton, set_order_state_num);
6029 automaton->achieved_states_num = curr_state_order_num;
6030}
6031
6032\f
6033
6034/* The page contains code for finding equivalent automaton insns
6035 (ainsns). */
6036
6037/* The function inserts AINSN into cyclic list
6038 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6039static ainsn_t
6040insert_ainsn_into_equiv_class (ainsn, cyclic_equiv_class_insn_list)
6041 ainsn_t ainsn;
6042 ainsn_t cyclic_equiv_class_insn_list;
6043{
6044 if (cyclic_equiv_class_insn_list == NULL)
6045 ainsn->next_equiv_class_insn = ainsn;
6046 else
6047 {
6048 ainsn->next_equiv_class_insn
6049 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6050 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6051 }
6052 return ainsn;
6053}
6054
6055/* The function deletes equiv_class_insn into cyclic list of
6056 equivalent ainsns. */
6057static void
6058delete_ainsn_from_equiv_class (equiv_class_insn)
6059 ainsn_t equiv_class_insn;
6060{
6061 ainsn_t curr_equiv_class_insn;
6062 ainsn_t prev_equiv_class_insn;
6063
6064 prev_equiv_class_insn = equiv_class_insn;
6065 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6066 curr_equiv_class_insn != equiv_class_insn;
6067 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6068 prev_equiv_class_insn = curr_equiv_class_insn;
6069 if (prev_equiv_class_insn != equiv_class_insn)
6070 prev_equiv_class_insn->next_equiv_class_insn
6071 = equiv_class_insn->next_equiv_class_insn;
6072}
6073
6074/* The function processes AINSN of a state in order to find equivalent
6075 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6076 state. */
6077static void
6078process_insn_equiv_class (ainsn, insn_arcs_array)
6079 ainsn_t ainsn;
6080 arc_t *insn_arcs_array;
6081{
6082 ainsn_t next_insn;
6083 ainsn_t curr_insn;
6084 ainsn_t cyclic_insn_list;
6085 arc_t arc;
6086
6087 if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL)
6088 abort ();
6089 curr_insn = ainsn;
6090 /* New class of ainsns which are not equivalent to given ainsn. */
6091 cyclic_insn_list = NULL;
6092 do
6093 {
6094 next_insn = curr_insn->next_equiv_class_insn;
6095 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6096 if (arc == NULL
6097 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6098 != arc->to_state))
6099 {
6100 delete_ainsn_from_equiv_class (curr_insn);
6101 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6102 cyclic_insn_list);
6103 }
6104 curr_insn = next_insn;
6105 }
6106 while (curr_insn != ainsn);
6107}
6108
6109/* The function processes STATE in order to find equivalent ainsns. */
6110static void
6111process_state_for_insn_equiv_partition (state)
6112 state_t state;
6113{
6114 arc_t arc;
6115 arc_t *insn_arcs_array;
6116 int i;
6117 vla_ptr_t insn_arcs_vect;
6118
6119 VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector");
6120 VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num);
6121 insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect);
6122 /* Process insns of the arcs. */
6123 for (i = 0; i < description->insns_num; i++)
6124 insn_arcs_array [i] = NULL;
6125 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6126 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6127 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6128 process_insn_equiv_class (arc->insn, insn_arcs_array);
6129 VLA_PTR_DELETE (insn_arcs_vect);
6130}
6131
6132/* The function searches for equivalent ainsns of AUTOMATON. */
6133static void
6134set_insn_equiv_classes (automaton)
6135 automaton_t automaton;
6136{
6137 ainsn_t ainsn;
6138 ainsn_t first_insn;
6139 ainsn_t curr_insn;
6140 ainsn_t cyclic_insn_list;
6141 ainsn_t insn_with_same_reservs;
6142 int equiv_classes_num;
6143
6144 /* All insns are included in one equivalence class. */
6145 cyclic_insn_list = NULL;
6146 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6147 if (ainsn->first_insn_with_same_reservs)
6148 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6149 cyclic_insn_list);
6150 /* Process insns in order to make equivalence partition. */
6151 pass_states (automaton, process_state_for_insn_equiv_partition);
6152 /* Enumerate equiv classes. */
6153 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6154 /* Set undefined value. */
6155 ainsn->insn_equiv_class_num = -1;
6156 equiv_classes_num = 0;
6157 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6158 if (ainsn->insn_equiv_class_num < 0)
6159 {
6160 first_insn = ainsn;
6161 if (!first_insn->first_insn_with_same_reservs)
6162 abort ();
6163 first_insn->first_ainsn_with_given_equialence_num = 1;
6164 curr_insn = first_insn;
6165 do
6166 {
6167 for (insn_with_same_reservs = curr_insn;
6168 insn_with_same_reservs != NULL;
6169 insn_with_same_reservs
6170 = insn_with_same_reservs->next_same_reservs_insn)
6171 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6172 curr_insn = curr_insn->next_equiv_class_insn;
6173 }
6174 while (curr_insn != first_insn);
6175 equiv_classes_num++;
6176 }
6177 automaton->insn_equiv_classes_num = equiv_classes_num;
6178}
6179
6180\f
6181
6182/* This page contains code for creating DFA(s) and calls functions
6183 building them. */
6184
6185
6186/* The following value is used to prevent floating point overflow for
6187 estimating an automaton bound. The value should be less DBL_MAX on
6188 the host machine. We use here approximate minimum of maximal
6189 double floating point value required by ANSI C standard. It
6190 will work for non ANSI sun compiler too. */
6191
6192#define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6193
6194/* The function estimate size of the single DFA used by PHR (pipeline
6195 hazards recognizer). */
6196static double
6197estimate_one_automaton_bound ()
6198{
6199 decl_t decl;
6200 double one_automaton_estimation_bound;
6201 double root_value;
6202 int i;
6203
6204 one_automaton_estimation_bound = 1.0;
6205 for (i = 0; i < description->decls_num; i++)
6206 {
6207 decl = description->decls [i];
6208 if (decl->mode == dm_unit)
6209 {
6210 root_value = exp (log (decl->decl.unit.max_occ_cycle_num + 1.0)
6211 / automata_num);
6212 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6213 > one_automaton_estimation_bound)
6214 one_automaton_estimation_bound *= root_value;
6215 }
6216 }
6217 return one_automaton_estimation_bound;
6218}
6219
6220/* The function compares unit declarations acoording to their maximal
6221 cycle in reservations. */
6222static int
6223compare_max_occ_cycle_nums (unit_decl_1, unit_decl_2)
6224 const void *unit_decl_1;
6225 const void *unit_decl_2;
6226{
6227 if (((*(decl_t *) unit_decl_1)->decl.unit.max_occ_cycle_num)
6228 < ((*(decl_t *) unit_decl_2)->decl.unit.max_occ_cycle_num))
6229 return 1;
6230 else if (((*(decl_t *) unit_decl_1)->decl.unit.max_occ_cycle_num)
6231 == ((*(decl_t *) unit_decl_2)->decl.unit.max_occ_cycle_num))
6232 return 0;
6233 else
6234 return -1;
6235}
6236
6237/* The function makes heuristic assigning automata to units. Actually
6238 efficacy of the algorithm has been checked yet??? */
6239static void
6240units_to_automata_heuristic_distr ()
6241{
6242 double estimation_bound;
6243 decl_t decl;
6244 decl_t *unit_decl_ptr;
6245 int automaton_num;
6246 int rest_units_num;
6247 double bound_value;
6248 vla_ptr_t unit_decls;
6249 int i;
6250
6251 if (description->units_num == 0)
6252 return;
6253 estimation_bound = estimate_one_automaton_bound ();
6254 VLA_PTR_CREATE (unit_decls, 150, "unit decls");
6255 for (i = 0; i < description->decls_num; i++)
6256 {
6257 decl = description->decls [i];
6258 if (decl->mode == dm_unit)
6259 VLA_PTR_ADD (unit_decls, decl);
6260 }
6261 qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls),
6262 sizeof (decl_t), compare_max_occ_cycle_nums);
6263 automaton_num = 0;
6264 unit_decl_ptr = VLA_PTR_BEGIN (unit_decls);
6265 bound_value = (*unit_decl_ptr)->decl.unit.max_occ_cycle_num;
6266 (*unit_decl_ptr)->decl.unit.corresponding_automaton_num = automaton_num;
6267 for (unit_decl_ptr++;
6268 unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls);
6269 unit_decl_ptr++)
6270 {
6271 rest_units_num
6272 = ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1);
6273 if (automata_num - automaton_num - 1 > rest_units_num)
6274 abort ();
6275 if (automaton_num < automata_num - 1
6276 && ((automata_num - automaton_num - 1 == rest_units_num)
6277 || (bound_value
6278 > (estimation_bound
6279 / ((*unit_decl_ptr)->decl.unit.max_occ_cycle_num)))))
6280 {
6281 bound_value = (*unit_decl_ptr)->decl.unit.max_occ_cycle_num;
6282 automaton_num++;
6283 }
6284 else
6285 bound_value *= (*unit_decl_ptr)->decl.unit.max_occ_cycle_num;
6286 (*unit_decl_ptr)->decl.unit.corresponding_automaton_num = automaton_num;
6287 }
6288 if (automaton_num != automata_num - 1)
6289 abort ();
6290 VLA_PTR_DELETE (unit_decls);
6291}
6292
6293/* The functions creates automaton insns for each automata. Automaton
6294 insn is simply insn for given automaton which makes reservation
6295 only of units of the automaton. */
6296static ainsn_t
6297create_ainsns ()
6298{
6299 decl_t decl;
6300 ainsn_t first_ainsn;
6301 ainsn_t curr_ainsn;
6302 ainsn_t prev_ainsn;
6303 int i;
6304
6305 first_ainsn = NULL;
6306 prev_ainsn = NULL;
6307 for (i = 0; i < description->decls_num; i++)
6308 {
6309 decl = description->decls [i];
6310 if (decl->mode == dm_insn_reserv)
6311 {
6312 curr_ainsn = create_node (sizeof (struct ainsn));
6313 curr_ainsn->insn_reserv_decl = &decl->decl.insn_reserv;
6314 curr_ainsn->important_p = FALSE;
6315 curr_ainsn->next_ainsn = NULL;
6316 if (prev_ainsn == NULL)
6317 first_ainsn = curr_ainsn;
6318 else
6319 prev_ainsn->next_ainsn = curr_ainsn;
6320 prev_ainsn = curr_ainsn;
6321 }
6322 }
6323 return first_ainsn;
6324}
6325
6326/* The function assigns automata to units according to constructions
6327 `define_automaton' in the description. */
6328static void
6329units_to_automata_distr ()
6330{
6331 decl_t decl;
6332 int i;
6333
6334 for (i = 0; i < description->decls_num; i++)
6335 {
6336 decl = description->decls [i];
6337 if (decl->mode == dm_unit)
6338 {
6339 if (decl->decl.unit.automaton_decl == NULL
6340 || (decl->decl.unit.automaton_decl->corresponding_automaton
6341 == NULL))
6342 /* Distribute to the first automaton. */
6343 decl->decl.unit.corresponding_automaton_num = 0;
6344 else
6345 decl->decl.unit.corresponding_automaton_num
6346 = (decl->decl.unit.automaton_decl
6347 ->corresponding_automaton->automaton_order_num);
6348 }
6349 }
6350}
6351
6352/* The function creates DFA(s) for fast pipeline hazards recognition
6353 after checking and simplifying IR of the description. */
6354static void
6355create_automata ()
6356{
6357 automaton_t curr_automaton;
6358 automaton_t prev_automaton;
6359 decl_t decl;
6360 int curr_automaton_num;
6361 int i;
6362
6363 if (automata_num != 0)
6364 {
6365 units_to_automata_heuristic_distr ();
6366 for (prev_automaton = NULL, curr_automaton_num = 0;
6367 curr_automaton_num < automata_num;
6368 curr_automaton_num++, prev_automaton = curr_automaton)
6369 {
6370 curr_automaton = create_node (sizeof (struct automaton));
6371 curr_automaton->ainsn_list = create_ainsns ();
6372 curr_automaton->corresponding_automaton_decl = NULL;
6373 curr_automaton->next_automaton = NULL;
6374 curr_automaton->automaton_order_num = curr_automaton_num;
6375 if (prev_automaton == NULL)
6376 description->first_automaton = curr_automaton;
6377 else
6378 prev_automaton->next_automaton = curr_automaton;
6379 }
6380 }
6381 else
6382 {
6383 curr_automaton_num = 0;
6384 prev_automaton = NULL;
6385 for (i = 0; i < description->decls_num; i++)
6386 {
6387 decl = description->decls [i];
6388 if (decl->mode == dm_automaton
6389 && decl->decl.automaton.automaton_is_used)
6390 {
6391 curr_automaton = create_node (sizeof (struct automaton));
6392 curr_automaton->ainsn_list = create_ainsns ();
6393 curr_automaton->corresponding_automaton_decl
6394 = &decl->decl.automaton;
6395 curr_automaton->next_automaton = NULL;
6396 decl->decl.automaton.corresponding_automaton = curr_automaton;
6397 curr_automaton->automaton_order_num = curr_automaton_num;
6398 if (prev_automaton == NULL)
6399 description->first_automaton = curr_automaton;
6400 else
6401 prev_automaton->next_automaton = curr_automaton;
6402 curr_automaton_num++;
6403 prev_automaton = curr_automaton;
6404 }
6405 }
6406 if (curr_automaton_num == 0)
6407 {
6408 curr_automaton = create_node (sizeof (struct automaton));
6409 curr_automaton->ainsn_list = create_ainsns ();
6410 curr_automaton->corresponding_automaton_decl = NULL;
6411 curr_automaton->next_automaton = NULL;
6412 description->first_automaton = curr_automaton;
6413 }
6414 units_to_automata_distr ();
6415 }
6416 NDFA_time = create_ticker ();
6417 ticker_off (&NDFA_time);
6418 NDFA_to_DFA_time = create_ticker ();
6419 ticker_off (&NDFA_to_DFA_time);
6420 minimize_time = create_ticker ();
6421 ticker_off (&minimize_time);
6422 equiv_time = create_ticker ();
6423 ticker_off (&equiv_time);
6424 for (curr_automaton = description->first_automaton;
6425 curr_automaton != NULL;
6426 curr_automaton = curr_automaton->next_automaton)
6427 {
6428 if (curr_automaton->corresponding_automaton_decl == NULL)
6429 fprintf (stderr, "Create anonymous automaton ...");
6430 else
6431 fprintf (stderr, "Create automaton `%s'...",
6432 curr_automaton->corresponding_automaton_decl->name);
6433 create_alt_states (curr_automaton);
6434 form_ainsn_with_same_reservs (curr_automaton);
6435 build_automaton (curr_automaton);
6436 enumerate_states (curr_automaton);
6437 ticker_on (&equiv_time);
6438 set_insn_equiv_classes (curr_automaton);
6439 ticker_off (&equiv_time);
6440 fprintf (stderr, "done\n");
6441 }
6442}
6443
6444\f
6445
6446/* This page contains code for forming string representation of
6447 regexp. The representation is formed on IR obstack. So you should
6448 not work with IR obstack between regexp_representation and
6449 finish_regexp_representation calls. */
6450
6451/* This recursive function forms string representation of regexp
6452 (without tailing '\0'). */
6453static void
6454form_regexp (regexp)
6455 regexp_t regexp;
6456{
6457 int i;
6458
6459 if (regexp->mode == rm_unit || regexp->mode == rm_reserv)
6460 {
6461 const char *name = (regexp->mode == rm_unit
6462 ? regexp->regexp.unit.name
6463 : regexp->regexp.reserv.name);
6464
6465 obstack_grow (&irp, name, strlen (name));
6466 }
6467 else if (regexp->mode == rm_sequence)
6468 for (i = 0; i < regexp->regexp.sequence.regexps_num; i++)
6469 {
6470 if (i != 0)
6471 obstack_1grow (&irp, ',');
6472 form_regexp (regexp->regexp.sequence.regexps [i]);
6473 }
6474 else if (regexp->mode == rm_allof)
6475 {
6476 obstack_1grow (&irp, '(');
6477 for (i = 0; i < regexp->regexp.allof.regexps_num; i++)
6478 {
6479 if (i != 0)
6480 obstack_1grow (&irp, '+');
6481 if (regexp->regexp.allof.regexps[i]->mode == rm_sequence
6482 || regexp->regexp.oneof.regexps[i]->mode == rm_oneof)
6483 obstack_1grow (&irp, '(');
6484 form_regexp (regexp->regexp.allof.regexps [i]);
6485 if (regexp->regexp.allof.regexps[i]->mode == rm_sequence
6486 || regexp->regexp.oneof.regexps[i]->mode == rm_oneof)
6487 obstack_1grow (&irp, ')');
6488 }
6489 obstack_1grow (&irp, ')');
6490 }
6491 else if (regexp->mode == rm_oneof)
6492 for (i = 0; i < regexp->regexp.oneof.regexps_num; i++)
6493 {
6494 if (i != 0)
6495 obstack_1grow (&irp, '|');
6496 if (regexp->regexp.oneof.regexps[i]->mode == rm_sequence)
6497 obstack_1grow (&irp, '(');
6498 form_regexp (regexp->regexp.oneof.regexps [i]);
6499 if (regexp->regexp.oneof.regexps[i]->mode == rm_sequence)
6500 obstack_1grow (&irp, ')');
6501 }
6502 else if (regexp->mode == rm_repeat)
6503 {
6504 char digits [30];
6505
6506 if (regexp->regexp.repeat.regexp->mode == rm_sequence
6507 || regexp->regexp.repeat.regexp->mode == rm_allof
6508 || regexp->regexp.repeat.regexp->mode == rm_oneof)
6509 obstack_1grow (&irp, '(');
6510 form_regexp (regexp->regexp.repeat.regexp);
6511 if (regexp->regexp.repeat.regexp->mode == rm_sequence
6512 || regexp->regexp.repeat.regexp->mode == rm_allof
6513 || regexp->regexp.repeat.regexp->mode == rm_oneof)
6514 obstack_1grow (&irp, ')');
6515 sprintf (digits, "*%d", regexp->regexp.repeat.repeat_num);
6516 obstack_grow (&irp, digits, strlen (digits));
6517 }
6518 else if (regexp->mode == rm_nothing)
6519 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6520 else
6521 abort ();
6522}
6523
6524/* The function returns string representation of REGEXP on IR
6525 obstack. */
6526static const char *
6527regexp_representation (regexp)
6528 regexp_t regexp;
6529{
6530 form_regexp (regexp);
6531 obstack_1grow (&irp, '\0');
6532 return obstack_base (&irp);
6533}
6534
6535/* The function frees memory allocated for last formed string
6536 representation of regexp. */
6537static void
6538finish_regexp_representation ()
6539{
6540 int length = obstack_object_size (&irp);
6541
6542 obstack_blank_fast (&irp, -length);
6543}
6544
6545\f
6546
6547/* This page contains code for output PHR (pipeline hazards recognizer). */
6548
6549/* The function outputs minimal C type which is sufficient for
6550 representation numbers in range min_range_value and
6551 max_range_value. Because host machine and build machine may be
6552 different, we use here minimal values required by ANSI C standard
6553 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6554 approximation. */
6555
6556static void
6557output_range_type (f, min_range_value, max_range_value)
6558 FILE *f;
6559 long int min_range_value;
6560 long int max_range_value;
6561{
6562 if (min_range_value >= 0 && max_range_value <= 255)
6563 fprintf (f, "unsigned char");
6564 else if (min_range_value >= -127 && max_range_value <= 127)
6565 fprintf (f, "signed char");
6566 else if (min_range_value >= 0 && max_range_value <= 65535)
6567 fprintf (f, "unsigned short");
6568 else if (min_range_value >= -32767 && max_range_value <= 32767)
6569 fprintf (f, "short");
6570 else
6571 fprintf (f, "int");
6572}
6573
6574/* The following macro value is used as value of member
6575 `longest_path_length' of state when we are processing path and the
6576 state on the path. */
6577
6578#define ON_THE_PATH -2
6579
6580/* The following recursive function searches for the length of the
6581 longest path starting from STATE which does not contain cycles and
6582 `cycle advance' arcs. */
6583
6584static int
6585longest_path_length (state)
6586 state_t state;
6587{
6588 arc_t arc;
6589 int length, result;
6590
6591 if (state->longest_path_length == ON_THE_PATH)
6592 /* We don't expect the path cycle here. Our graph may contain
6593 only cycles with one state on the path not containing `cycle
6594 advance' arcs -- see comment below. */
6595 abort ();
6596 else if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
6597 /* We alreday visited the state. */
6598 return state->longest_path_length;
6599
6600 result = 0;
6601 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
deb09eff 6602 /* Ignore cycles containing one state and `cycle advance' arcs. */
fae15c93
VM
6603 if (arc->to_state != state
6604 && (arc->insn->insn_reserv_decl
6605 != &advance_cycle_insn_decl->decl.insn_reserv))
6606 {
6607 length = longest_path_length (arc->to_state);
6608 if (length > result)
6609 result = length;
6610 }
6611 state->longest_path_length = result + 1;
6612 return result;
6613}
6614
6615/* The following variable value is value of the corresponding global
6616 variable in the automaton based pipeline interface. */
6617
6618static int max_dfa_issue_rate;
6619
6620/* The following function processes the longest path length staring
deb09eff 6621 from STATE to find MAX_DFA_ISSUE_RATE. */
fae15c93
VM
6622
6623static void
6624process_state_longest_path_length (state)
6625 state_t state;
6626{
6627 int value;
6628
6629 value = longest_path_length (state);
6630 if (value > max_dfa_issue_rate)
6631 max_dfa_issue_rate = value;
6632}
6633
6634/* The following nacro value is name of the corresponding global
6635 variable in the automaton based pipeline interface. */
6636
6637#define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate"
6638
6639/* The following function calculates value of the the corresponding
6640 global variable and outputs its declaration. */
6641
6642static void
6643output_dfa_max_issue_rate ()
6644{
6645 automaton_t automaton;
6646
6647 if (UNDEFINED_LONGEST_PATH_LENGTH == ON_THE_PATH || ON_THE_PATH >= 0)
6648 abort ();
6649 max_dfa_issue_rate = 0;
6650 for (automaton = description->first_automaton;
6651 automaton != NULL;
6652 automaton = automaton->next_automaton)
6653 pass_states (automaton, process_state_longest_path_length);
6654 fprintf (output_file, "\nint %s = %d;\n",
6655 MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate);
6656}
6657
6658/* The function outputs all initialization values of VECT with length
6659 vect_length. */
6660static void
6661output_vect (vect, vect_length)
6662 vect_el_t *vect;
6663 int vect_length;
6664{
6665 int els_on_line;
6666
6667 els_on_line = 1;
6668 if (vect_length == 0)
6669 fprintf (output_file,
6670 "0 /* This is dummy el because the vect is empty */");
6671 else
6672 {
6673 do
6674 {
6675 fprintf (output_file, "%5ld", (long) *vect);
6676 vect_length--;
6677 if (els_on_line == 10)
6678 {
6679 els_on_line = 0;
6680 fprintf (output_file, ",\n");
6681 }
6682 else if (vect_length != 0)
6683 fprintf (output_file, ", ");
6684 els_on_line++;
6685 vect++;
6686 }
6687 while (vect_length != 0);
6688 }
6689}
6690
6691/* The following is name of the structure which represents DFA(s) for
6692 PHR. */
6693#define CHIP_NAME "DFA_chip"
6694
6695/* The following is name of member which represents state of a DFA for
6696 PHR. */
6697static void
6698output_chip_member_name (f, automaton)
6699 FILE *f;
6700 automaton_t automaton;
6701{
6702 if (automaton->corresponding_automaton_decl == NULL)
6703 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6704 else
6705 fprintf (f, "%s_automaton_state",
6706 automaton->corresponding_automaton_decl->name);
6707}
6708
6709/* The following is name of temporary variable which stores state of a
6710 DFA for PHR. */
6711static void
6712output_temp_chip_member_name (f, automaton)
6713 FILE *f;
6714 automaton_t automaton;
6715{
6716 fprintf (f, "_");
6717 output_chip_member_name (f, automaton);
6718}
6719
6720/* This is name of macro value which is code of pseudo_insn
6721 representing advancing cpu cycle. Its value is used as internal
6722 code unknown insn. */
6723#define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6724
6725/* Output name of translate vector for given automaton. */
6726static void
6727output_translate_vect_name (f, automaton)
6728 FILE *f;
6729 automaton_t automaton;
6730{
6731 if (automaton->corresponding_automaton_decl == NULL)
6732 fprintf (f, "translate_%d", automaton->automaton_order_num);
6733 else
6734 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6735}
6736
6737/* Output name for simple transition table representation. */
6738static void
6739output_trans_full_vect_name (f, automaton)
6740 FILE *f;
6741 automaton_t automaton;
6742{
6743 if (automaton->corresponding_automaton_decl == NULL)
6744 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6745 else
6746 fprintf (f, "%s_transitions",
6747 automaton->corresponding_automaton_decl->name);
6748}
6749
6750/* Output name of comb vector of the transition table for given
6751 automaton. */
6752static void
6753output_trans_comb_vect_name (f, automaton)
6754 FILE *f;
6755 automaton_t automaton;
6756{
6757 if (automaton->corresponding_automaton_decl == NULL)
6758 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6759 else
6760 fprintf (f, "%s_transitions",
6761 automaton->corresponding_automaton_decl->name);
6762}
6763
6764/* Output name of check vector of the transition table for given
6765 automaton. */
6766static void
6767output_trans_check_vect_name (f, automaton)
6768 FILE *f;
6769 automaton_t automaton;
6770{
6771 if (automaton->corresponding_automaton_decl == NULL)
6772 fprintf (f, "check_%d", automaton->automaton_order_num);
6773 else
6774 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6775}
6776
6777/* Output name of base vector of the transition table for given
6778 automaton. */
6779static void
6780output_trans_base_vect_name (f, automaton)
6781 FILE *f;
6782 automaton_t automaton;
6783{
6784 if (automaton->corresponding_automaton_decl == NULL)
6785 fprintf (f, "base_%d", automaton->automaton_order_num);
6786 else
6787 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6788}
6789
6790/* Output name for simple alternatives number representation. */
6791static void
6792output_state_alts_full_vect_name (f, automaton)
6793 FILE *f;
6794 automaton_t automaton;
6795{
6796 if (automaton->corresponding_automaton_decl == NULL)
6797 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
6798 else
6799 fprintf (f, "%s_state_alts",
6800 automaton->corresponding_automaton_decl->name);
6801}
6802
6803/* Output name of comb vector of the alternatives number table for given
6804 automaton. */
6805static void
6806output_state_alts_comb_vect_name (f, automaton)
6807 FILE *f;
6808 automaton_t automaton;
6809{
6810 if (automaton->corresponding_automaton_decl == NULL)
6811 fprintf (f, "state_alts_%d", automaton->automaton_order_num);
6812 else
6813 fprintf (f, "%s_state_alts",
6814 automaton->corresponding_automaton_decl->name);
6815}
6816
6817/* Output name of check vector of the alternatives number table for given
6818 automaton. */
6819static void
6820output_state_alts_check_vect_name (f, automaton)
6821 FILE *f;
6822 automaton_t automaton;
6823{
6824 if (automaton->corresponding_automaton_decl == NULL)
6825 fprintf (f, "check_state_alts_%d", automaton->automaton_order_num);
6826 else
6827 fprintf (f, "%s_check_state_alts",
6828 automaton->corresponding_automaton_decl->name);
6829}
6830
6831/* Output name of base vector of the alternatives number table for given
6832 automaton. */
6833static void
6834output_state_alts_base_vect_name (f, automaton)
6835 FILE *f;
6836 automaton_t automaton;
6837{
6838 if (automaton->corresponding_automaton_decl == NULL)
6839 fprintf (f, "base_state_alts_%d", automaton->automaton_order_num);
6840 else
6841 fprintf (f, "%s_base_state_alts",
6842 automaton->corresponding_automaton_decl->name);
6843}
6844
6845/* Output name of simple min issue delay table representation. */
6846static void
6847output_min_issue_delay_vect_name (f, automaton)
6848 FILE *f;
6849 automaton_t automaton;
6850{
6851 if (automaton->corresponding_automaton_decl == NULL)
6852 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6853 else
6854 fprintf (f, "%s_min_issue_delay",
6855 automaton->corresponding_automaton_decl->name);
6856}
6857
6858/* Output name of deadlock vector for given automaton. */
6859static void
6860output_dead_lock_vect_name (f, automaton)
6861 FILE *f;
6862 automaton_t automaton;
6863{
6864 if (automaton->corresponding_automaton_decl == NULL)
6865 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6866 else
6867 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6868}
6869
6870/* Output name of reserved units table for AUTOMATON into file F. */
6871static void
6872output_reserved_units_table_name (f, automaton)
6873 FILE *f;
6874 automaton_t automaton;
6875{
6876 if (automaton->corresponding_automaton_decl == NULL)
6877 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6878 else
6879 fprintf (f, "%s_reserved_units",
6880 automaton->corresponding_automaton_decl->name);
6881}
6882
6883/* Name of the PHR interface macro. */
6884#define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS"
6885
6886/* Name of the PHR interface macro. */
6887#define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6888
6889/* Names of an internal functions: */
6890#define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6891
6892/* This is external type of DFA(s) state. */
6893#define STATE_TYPE_NAME "state_t"
6894
6895#define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6896
6897#define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts"
6898
6899#define INTERNAL_RESET_FUNC_NAME "internal_reset"
6900
6901#define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6902
6903#define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6904
6905/* Name of cache of insn dfa codes. */
6906#define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6907
deb09eff 6908/* Name of length of cache of insn dfa codes. */
fae15c93
VM
6909#define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6910
6911/* Names of the PHR interface functions: */
6912#define SIZE_FUNC_NAME "state_size"
6913
6914#define TRANSITION_FUNC_NAME "state_transition"
6915
6916#define STATE_ALTS_FUNC_NAME "state_alts"
6917
6918#define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6919
6920#define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6921
6922#define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6923
6924#define RESET_FUNC_NAME "state_reset"
6925
6926#define INSN_LATENCY_FUNC_NAME "insn_latency"
6927
6928#define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6929
6930#define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6931
6932#define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6933
6934#define DFA_START_FUNC_NAME "dfa_start"
6935
6936#define DFA_FINISH_FUNC_NAME "dfa_finish"
6937
6938/* Names of parameters of the PHR interface functions. */
6939#define STATE_NAME "state"
6940
6941#define INSN_PARAMETER_NAME "insn"
6942
6943#define INSN2_PARAMETER_NAME "insn2"
6944
6945#define CHIP_PARAMETER_NAME "chip"
6946
6947#define FILE_PARAMETER_NAME "f"
6948
6949#define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6950
6951#define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6952
6953/* Names of the variables whose values are internal insn code of rtx
6954 insn. */
6955#define INTERNAL_INSN_CODE_NAME "insn_code"
6956
6957#define INTERNAL_INSN2_CODE_NAME "insn2_code"
6958
6959/* Names of temporary variables in some functions. */
6960#define TEMPORARY_VARIABLE_NAME "temp"
6961
6962#define I_VARIABLE_NAME "i"
6963
6964/* Name of result variable in some functions. */
6965#define RESULT_VARIABLE_NAME "res"
6966
6967/* Name of function (attribute) to translate insn into number of insn
6968 alternatives reservation. */
6969#define INSN_ALTS_FUNC_NAME "insn_alts"
6970
6971/* Name of function (attribute) to translate insn into internal insn
6972 code. */
6973#define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6974
6975/* Name of function (attribute) to translate insn into internal insn
6976 code with caching. */
6977#define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6978
6979/* Name of function (attribute) to translate insn into internal insn
6980 code. */
6981#define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency"
6982
6983/* Name of function (attribute) to translate insn into internal insn
6984 code. */
6985#define BYPASS_P_FUNC_NAME "bypass_p"
6986
6987/* Output C type which is used for representation of codes of states
6988 of AUTOMATON. */
6989static void
6990output_state_member_type (f, automaton)
6991 FILE *f;
6992 automaton_t automaton;
6993{
6994 output_range_type (f, 0, automaton->achieved_states_num);
6995}
6996
6997/* Output definition of the structure representing current DFA(s)
6998 state(s). */
6999static void
7000output_chip_definitions ()
7001{
7002 automaton_t automaton;
7003
7004 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7005 for (automaton = description->first_automaton;
7006 automaton != NULL;
7007 automaton = automaton->next_automaton)
7008 {
7009 fprintf (output_file, " ");
7010 output_state_member_type (output_file, automaton);
7011 fprintf (output_file, " ");
7012 output_chip_member_name (output_file, automaton);
7013 fprintf (output_file, ";\n");
7014 }
7015 fprintf (output_file, "};\n\n");
7016#if 0
7017 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7018#endif
7019}
7020
7021
7022/* The function outputs translate vector of internal insn code into
7023 insn equivalence class number. The equivalence class number is
7024 used to access to table and vectors reprewsenting DFA(s). */
7025static void
7026output_translate_vect (automaton)
7027 automaton_t automaton;
7028{
7029 ainsn_t ainsn;
7030 int insn_value;
7031 vla_hwint_t translate_vect;
7032
7033 VLA_HWINT_CREATE (translate_vect, 250, "translate vector");
7034 VLA_HWINT_EXPAND (translate_vect, description->insns_num);
7035 for (insn_value = 0; insn_value <= description->insns_num; insn_value++)
7036 /* Undefined value */
7037 VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num;
7038 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7039 VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num)
7040 = ainsn->insn_equiv_class_num;
7041 fprintf (output_file,
7042 "/* Vector translating external insn codes to internal ones.*/\n");
7043 fprintf (output_file, "static const ");
7044 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7045 fprintf (output_file, " ");
7046 output_translate_vect_name (output_file, automaton);
7047 fprintf (output_file, "[] = {\n");
7048 output_vect (VLA_HWINT_BEGIN (translate_vect),
7049 VLA_HWINT_LENGTH (translate_vect));
7050 fprintf (output_file, "};\n\n");
7051 VLA_HWINT_DELETE (translate_vect);
7052}
7053
7054/* The value in a table state x ainsn -> something which represents
7055 undefined value. */
7056static int undefined_vect_el_value;
7057
7058/* The following function returns nonzero value if the best
7059 representation of the table is comb vector. */
7060static int
7061comb_vect_p (tab)
7062 state_ainsn_table_t tab;
7063{
7064 return (2 * VLA_HWINT_LENGTH (tab->full_vect)
7065 > 5 * VLA_HWINT_LENGTH (tab->comb_vect));
7066}
7067
7068/* The following function creates new table for AUTOMATON. */
7069static state_ainsn_table_t
7070create_state_ainsn_table (automaton)
7071 automaton_t automaton;
7072{
7073 state_ainsn_table_t tab;
7074 int full_vect_length;
7075 int i;
7076
7077 tab = create_node (sizeof (struct state_ainsn_table));
7078 tab->automaton = automaton;
7079 VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector");
7080 VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector");
7081 VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector");
7082 VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num);
7083 VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector");
7084 full_vect_length = (automaton->insn_equiv_classes_num
7085 * automaton->achieved_states_num);
7086 VLA_HWINT_EXPAND (tab->full_vect, full_vect_length);
7087 for (i = 0; i < full_vect_length; i++)
7088 VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value;
7089 tab->min_base_vect_el_value = 0;
7090 tab->max_base_vect_el_value = 0;
7091 tab->min_comb_vect_el_value = 0;
7092 tab->max_comb_vect_el_value = 0;
7093 return tab;
7094}
7095
7096/* The following function outputs the best C representation of the
7097 table TAB of given TABLE_NAME. */
7098static void
7099output_state_ainsn_table (tab, table_name, output_full_vect_name_func,
7100 output_comb_vect_name_func,
7101 output_check_vect_name_func,
7102 output_base_vect_name_func)
7103 state_ainsn_table_t tab;
7104 char *table_name;
7105 void (*output_full_vect_name_func) PARAMS ((FILE *, automaton_t));
7106 void (*output_comb_vect_name_func) PARAMS ((FILE *, automaton_t));
7107 void (*output_check_vect_name_func) PARAMS ((FILE *, automaton_t));
7108 void (*output_base_vect_name_func) PARAMS ((FILE *, automaton_t));
7109{
7110 if (!comb_vect_p (tab))
7111 {
7112 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7113 fprintf (output_file, "static const ");
7114 output_range_type (output_file, tab->min_comb_vect_el_value,
7115 tab->max_comb_vect_el_value);
7116 fprintf (output_file, " ");
7117 (*output_full_vect_name_func) (output_file, tab->automaton);
7118 fprintf (output_file, "[] = {\n");
7119 output_vect (VLA_HWINT_BEGIN (tab->full_vect),
7120 VLA_HWINT_LENGTH (tab->full_vect));
7121 fprintf (output_file, "};\n\n");
7122 }
7123 else
7124 {
7125 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7126 fprintf (output_file, "static const ");
7127 output_range_type (output_file, tab->min_comb_vect_el_value,
7128 tab->max_comb_vect_el_value);
7129 fprintf (output_file, " ");
7130 (*output_comb_vect_name_func) (output_file, tab->automaton);
7131 fprintf (output_file, "[] = {\n");
7132 output_vect (VLA_HWINT_BEGIN (tab->comb_vect),
7133 VLA_HWINT_LENGTH (tab->comb_vect));
7134 fprintf (output_file, "};\n\n");
7135 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7136 fprintf (output_file, "static const ");
7137 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7138 fprintf (output_file, " ");
7139 (*output_check_vect_name_func) (output_file, tab->automaton);
7140 fprintf (output_file, "[] = {\n");
7141 output_vect (VLA_HWINT_BEGIN (tab->check_vect),
7142 VLA_HWINT_LENGTH (tab->check_vect));
7143 fprintf (output_file, "};\n\n");
7144 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7145 fprintf (output_file, "static const ");
7146 output_range_type (output_file, tab->min_base_vect_el_value,
7147 tab->max_base_vect_el_value);
7148 fprintf (output_file, " ");
7149 (*output_base_vect_name_func) (output_file, tab->automaton);
7150 fprintf (output_file, "[] = {\n");
7151 output_vect (VLA_HWINT_BEGIN (tab->base_vect),
7152 VLA_HWINT_LENGTH (tab->base_vect));
7153 fprintf (output_file, "};\n\n");
7154 }
7155}
7156
7157/* The following function adds vector with length VECT_LENGTH and
7158 elements pointed by VECT to table TAB as its line with number
7159 VECT_NUM. */
7160static void
7161add_vect (tab, vect_num, vect, vect_length)
7162 state_ainsn_table_t tab;
7163 int vect_num;
7164 vect_el_t *vect;
7165 int vect_length;
7166{
7167 int real_vect_length;
7168 vect_el_t *comb_vect_start;
7169 vect_el_t *check_vect_start;
7170 int comb_vect_index;
7171 int comb_vect_els_num;
7172 int vect_index;
7173 int first_unempty_vect_index;
7174 int additional_els_num;
7175 int no_state_value;
7176 vect_el_t vect_el;
7177 int i;
7178
7179 if (vect_length == 0)
7180 abort ();
7181 real_vect_length = tab->automaton->insn_equiv_classes_num;
7182 if (vect [vect_length - 1] == undefined_vect_el_value)
7183 abort ();
7184 /* Form full vector in the table: */
7185 for (i = 0; i < vect_length; i++)
7186 VLA_HWINT (tab->full_vect,
7187 i + tab->automaton->insn_equiv_classes_num * vect_num)
7188 = vect [i];
7189 /* Form comb vector in the table: */
7190 if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect))
7191 abort ();
7192 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7193 comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect);
7194 for (first_unempty_vect_index = 0;
7195 first_unempty_vect_index < vect_length;
7196 first_unempty_vect_index++)
7197 if (vect [first_unempty_vect_index] != undefined_vect_el_value)
7198 break;
7199 /* Search for the place in comb vect for the inserted vect. */
7200 for (comb_vect_index = 0;
7201 comb_vect_index < comb_vect_els_num;
7202 comb_vect_index++)
7203 {
7204 for (vect_index = first_unempty_vect_index;
7205 vect_index < vect_length
7206 && vect_index + comb_vect_index < comb_vect_els_num;
7207 vect_index++)
7208 if (vect [vect_index] != undefined_vect_el_value
7209 && (comb_vect_start [vect_index + comb_vect_index]
7210 != undefined_vect_el_value))
7211 break;
7212 if (vect_index >= vect_length
7213 || vect_index + comb_vect_index >= comb_vect_els_num)
7214 break;
7215 }
7216 /* Slot was found. */
7217 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7218 if (additional_els_num < 0)
7219 additional_els_num = 0;
7220 /* Expand comb and check vectors. */
7221 vect_el = undefined_vect_el_value;
7222 no_state_value = tab->automaton->achieved_states_num;
7223 while (additional_els_num > 0)
7224 {
7225 VLA_HWINT_ADD (tab->comb_vect, vect_el);
7226 VLA_HWINT_ADD (tab->check_vect, no_state_value);
7227 additional_els_num--;
7228 }
7229 comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect);
7230 check_vect_start = VLA_HWINT_BEGIN (tab->check_vect);
7231 if (VLA_HWINT_LENGTH (tab->comb_vect)
7232 < (size_t) (comb_vect_index + real_vect_length))
7233 abort ();
7234 /* Fill comb and check vectors. */
7235 for (vect_index = 0; vect_index < vect_length; vect_index++)
7236 if (vect [vect_index] != undefined_vect_el_value)
7237 {
7238 if (comb_vect_start [comb_vect_index + vect_index]
7239 != undefined_vect_el_value)
7240 abort ();
7241 comb_vect_start [comb_vect_index + vect_index] = vect [vect_index];
7242 if (vect [vect_index] < 0)
7243 abort ();
7244 if (tab->max_comb_vect_el_value < vect [vect_index])
7245 tab->max_comb_vect_el_value = vect [vect_index];
7246 if (tab->min_comb_vect_el_value > vect [vect_index])
7247 tab->min_comb_vect_el_value = vect [vect_index];
7248 check_vect_start [comb_vect_index + vect_index] = vect_num;
7249 }
7250 if (tab->max_base_vect_el_value < comb_vect_index)
7251 tab->max_base_vect_el_value = comb_vect_index;
7252 if (tab->min_base_vect_el_value > comb_vect_index)
7253 tab->min_base_vect_el_value = comb_vect_index;
7254 VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index;
7255}
7256
7257/* Return number of out arcs of STATE. */
7258static int
7259out_state_arcs_num (state)
7260 state_t state;
7261{
7262 int result;
7263 arc_t arc;
7264
7265 result = 0;
7266 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7267 {
7268 if (arc->insn == NULL)
7269 abort ();
7270 if (arc->insn->first_ainsn_with_given_equialence_num)
7271 result++;
7272 }
7273 return result;
7274}
7275
7276/* Compare number of possible transitions from the states. */
7277static int
7278compare_transition_els_num (state_ptr_1, state_ptr_2)
7279 const void *state_ptr_1;
7280 const void *state_ptr_2;
7281{
7282 int transition_els_num_1;
7283 int transition_els_num_2;
7284
7285 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7286 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7287 if (transition_els_num_1 < transition_els_num_2)
7288 return 1;
7289 else if (transition_els_num_1 == transition_els_num_2)
7290 return 0;
7291 else
7292 return -1;
7293}
7294
7295/* The function adds element EL_VALUE to vector VECT for a table state
7296 x AINSN. */
7297static void
7298add_vect_el (vect, ainsn, el_value)
7299 vla_hwint_t *vect;
7300 ainsn_t ainsn;
7301 int el_value;
7302{
7303 int equiv_class_num;
7304 int vect_index;
7305
7306 if (ainsn == NULL)
7307 abort ();
7308 equiv_class_num = ainsn->insn_equiv_class_num;
7309 for (vect_index = VLA_HWINT_LENGTH (*vect);
7310 vect_index <= equiv_class_num;
7311 vect_index++)
7312 VLA_HWINT_ADD (*vect, undefined_vect_el_value);
7313 VLA_HWINT (*vect, equiv_class_num) = el_value;
7314}
7315
7316/* This is for forming vector of states of an automaton. */
7317static vla_ptr_t output_states_vect;
7318
7319/* The function is called by function pass_states. The function adds
7320 STATE to `output_states_vect'. */
7321static void
7322add_states_vect_el (state)
7323 state_t state;
7324{
7325 VLA_PTR_ADD (output_states_vect, state);
7326}
7327
7328/* Form and output vectors (comb, check, base or full vector)
7329 representing transition table of AUTOMATON. */
7330static void
7331output_trans_table (automaton)
7332 automaton_t automaton;
7333{
7334 state_t *state_ptr;
7335 arc_t arc;
7336 vla_hwint_t transition_vect;
7337
7338 undefined_vect_el_value = automaton->achieved_states_num;
7339 automaton->trans_table = create_state_ainsn_table (automaton);
7340 /* Create vect of pointers to states ordered by num of transitions
7341 from the state (state with the maximum num is the first). */
7342 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7343 pass_states (automaton, add_states_vect_el);
7344 qsort (VLA_PTR_BEGIN (output_states_vect),
7345 VLA_PTR_LENGTH (output_states_vect),
7346 sizeof (state_t), compare_transition_els_num);
7347 VLA_HWINT_CREATE (transition_vect, 500, "transition vector");
7348 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7349 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7350 state_ptr++)
7351 {
7352 VLA_HWINT_NULLIFY (transition_vect);
7353 for (arc = first_out_arc (*state_ptr);
7354 arc != NULL;
7355 arc = next_out_arc (arc))
7356 {
7357 if (arc->insn == NULL)
7358 abort ();
7359 if (arc->insn->first_ainsn_with_given_equialence_num)
7360 add_vect_el (&transition_vect, arc->insn,
7361 arc->to_state->order_state_num);
7362 }
7363 add_vect (automaton->trans_table, (*state_ptr)->order_state_num,
7364 VLA_HWINT_BEGIN (transition_vect),
7365 VLA_HWINT_LENGTH (transition_vect));
7366 }
7367 output_state_ainsn_table
7368 (automaton->trans_table, (char *) "state transitions",
7369 output_trans_full_vect_name, output_trans_comb_vect_name,
7370 output_trans_check_vect_name, output_trans_base_vect_name);
7371 VLA_PTR_DELETE (output_states_vect);
7372 VLA_HWINT_DELETE (transition_vect);
7373}
7374
7375/* Form and output vectors (comb, check, base or simple vect)
7376 representing alts number table of AUTOMATON. The table is state x
7377 ainsn -> number of possible alternative reservations by the
7378 ainsn. */
7379static void
7380output_state_alts_table (automaton)
7381 automaton_t automaton;
7382{
7383 state_t *state_ptr;
7384 arc_t arc;
7385 vla_hwint_t state_alts_vect;
7386
7387 undefined_vect_el_value = 0; /* no alts when transition is not possible */
7388 automaton->state_alts_table = create_state_ainsn_table (automaton);
7389 /* Create vect of pointers to states ordered by num of transitions
7390 from the state (state with the maximum num is the first). */
7391 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7392 pass_states (automaton, add_states_vect_el);
7393 qsort (VLA_PTR_BEGIN (output_states_vect),
7394 VLA_PTR_LENGTH (output_states_vect),
7395 sizeof (state_t), compare_transition_els_num);
7396 /* Create base, comb, and check vectors. */
7397 VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector");
7398 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7399 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7400 state_ptr++)
7401 {
7402 VLA_HWINT_NULLIFY (state_alts_vect);
7403 for (arc = first_out_arc (*state_ptr);
7404 arc != NULL;
7405 arc = next_out_arc (arc))
7406 {
7407 if (arc->insn == NULL)
7408 abort ();
7409 if (arc->insn->first_ainsn_with_given_equialence_num)
7410 add_vect_el (&state_alts_vect, arc->insn, arc->state_alts);
7411 }
7412 add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num,
7413 VLA_HWINT_BEGIN (state_alts_vect),
7414 VLA_HWINT_LENGTH (state_alts_vect));
7415 }
7416 output_state_ainsn_table
7417 (automaton->state_alts_table, (char *) "state insn alternatives",
7418 output_state_alts_full_vect_name, output_state_alts_comb_vect_name,
7419 output_state_alts_check_vect_name, output_state_alts_base_vect_name);
7420 VLA_PTR_DELETE (output_states_vect);
7421 VLA_HWINT_DELETE (state_alts_vect);
7422}
7423
7424/* The current number of passing states to find minimal issue delay
7425 value for an ainsn and state. */
7426static int curr_state_pass_num;
7427
7428
7429/* This recursive function passes states to find minimal issue delay
0b2fb0d7
VM
7430 value for AINSN. The state being visited is STATE. The function
7431 returns minimal issue delay value for AINSN in STATE or -1 if we
7432 enter into a loop. */
7433static int
fae15c93
VM
7434min_issue_delay_pass_states (state, ainsn)
7435 state_t state;
7436 ainsn_t ainsn;
7437{
7438 arc_t arc;
7439 int min_insn_issue_delay, insn_issue_delay;
7440
0b2fb0d7
VM
7441 if (state->state_pass_num == curr_state_pass_num
7442 || state->min_insn_issue_delay != -1)
7443 /* We've entered into a loop or already have the correct value for
deb09eff 7444 given state and ainsn. */
0b2fb0d7 7445 return state->min_insn_issue_delay;
fae15c93 7446 state->state_pass_num = curr_state_pass_num;
0b2fb0d7 7447 min_insn_issue_delay = -1;
fae15c93
VM
7448 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7449 if (arc->insn == ainsn)
7450 {
7451 min_insn_issue_delay = 0;
7452 break;
7453 }
7454 else
7455 {
0b2fb0d7
VM
7456 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7457 if (insn_issue_delay != -1)
fae15c93 7458 {
0b2fb0d7
VM
7459 if (arc->insn->insn_reserv_decl
7460 == &advance_cycle_insn_decl->decl.insn_reserv)
7461 insn_issue_delay++;
fae15c93
VM
7462 if (min_insn_issue_delay == -1
7463 || min_insn_issue_delay > insn_issue_delay)
0b2fb0d7
VM
7464 {
7465 min_insn_issue_delay = insn_issue_delay;
7466 if (insn_issue_delay == 0)
7467 break;
7468 }
fae15c93
VM
7469 }
7470 }
0b2fb0d7 7471 return min_insn_issue_delay;
fae15c93
VM
7472}
7473
7474/* The function searches minimal issue delay value for AINSN in STATE.
0b2fb0d7
VM
7475 The function can return negative value if we can not issue AINSN. We
7476 will report about it later. */
fae15c93
VM
7477static int
7478min_issue_delay (state, ainsn)
7479 state_t state;
7480 ainsn_t ainsn;
7481{
7482 curr_state_pass_num++;
0b2fb0d7 7483 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
fae15c93
VM
7484 return state->min_insn_issue_delay;
7485}
7486
7487/* The function initiates code for finding minimal issue delay values.
7488 It should be called only once. */
7489static void
7490initiate_min_issue_delay_pass_states ()
7491{
7492 curr_state_pass_num = 0;
7493}
7494
7495/* Form and output vectors representing minimal issue delay table of
7496 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7497 the ainsn. */
7498static void
7499output_min_issue_delay_table (automaton)
7500 automaton_t automaton;
7501{
7502 vla_hwint_t min_issue_delay_vect;
7503 vla_hwint_t compressed_min_issue_delay_vect;
7504 vect_el_t min_delay;
7505 ainsn_t ainsn;
7506 state_t *state_ptr;
7507 int i;
7508
7509 /* Create vect of pointers to states ordered by num of transitions
7510 from the state (state with the maximum num is the first). */
7511 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7512 pass_states (automaton, add_states_vect_el);
7513 VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector");
7514 VLA_HWINT_EXPAND (min_issue_delay_vect,
7515 VLA_HWINT_LENGTH (output_states_vect)
7516 * automaton->insn_equiv_classes_num);
7517 for (i = 0;
7518 i < ((int) VLA_HWINT_LENGTH (output_states_vect)
7519 * automaton->insn_equiv_classes_num);
7520 i++)
7521 VLA_HWINT (min_issue_delay_vect, i) = 0;
7522 automaton->max_min_delay = 0;
0b2fb0d7
VM
7523 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7524 if (ainsn->first_ainsn_with_given_equialence_num)
7525 {
7526 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7527 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7528 state_ptr++)
7529 (*state_ptr)->min_insn_issue_delay = -1;
7530 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7531 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7532 state_ptr++)
7533 {
fae15c93
VM
7534 min_delay = min_issue_delay (*state_ptr, ainsn);
7535 if (automaton->max_min_delay < min_delay)
7536 automaton->max_min_delay = min_delay;
7537 VLA_HWINT (min_issue_delay_vect,
7538 (*state_ptr)->order_state_num
7539 * automaton->insn_equiv_classes_num
7540 + ainsn->insn_equiv_class_num) = min_delay;
7541 }
0b2fb0d7 7542 }
fae15c93
VM
7543 fprintf (output_file, "/* Vector of min issue delay of insns.*/\n");
7544 fprintf (output_file, "static const ");
7545 output_range_type (output_file, 0, automaton->max_min_delay);
7546 fprintf (output_file, " ");
7547 output_min_issue_delay_vect_name (output_file, automaton);
7548 fprintf (output_file, "[] = {\n");
7549 /* Compress the vector */
7550 if (automaton->max_min_delay < 2)
7551 automaton->min_issue_delay_table_compression_factor = 8;
7552 else if (automaton->max_min_delay < 4)
7553 automaton->min_issue_delay_table_compression_factor = 4;
7554 else if (automaton->max_min_delay < 16)
7555 automaton->min_issue_delay_table_compression_factor = 2;
7556 else
7557 automaton->min_issue_delay_table_compression_factor = 1;
7558 VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500,
7559 "compressed min issue delay vector");
7560 VLA_HWINT_EXPAND (compressed_min_issue_delay_vect,
7561 (VLA_HWINT_LENGTH (min_issue_delay_vect)
7562 + automaton->min_issue_delay_table_compression_factor
7563 - 1)
7564 / automaton->min_issue_delay_table_compression_factor);
7565 for (i = 0;
7566 i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect);
7567 i++)
7568 VLA_HWINT (compressed_min_issue_delay_vect, i) = 0;
7569 for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++)
7570 VLA_HWINT (compressed_min_issue_delay_vect,
7571 i / automaton->min_issue_delay_table_compression_factor)
7572 |= (VLA_HWINT (min_issue_delay_vect, i)
7573 << (8 - (i % automaton->min_issue_delay_table_compression_factor
7574 + 1)
7575 * (8 / automaton->min_issue_delay_table_compression_factor)));
7576 output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect),
7577 VLA_HWINT_LENGTH (compressed_min_issue_delay_vect));
7578 fprintf (output_file, "};\n\n");
7579 VLA_PTR_DELETE (output_states_vect);
7580 VLA_HWINT_DELETE (min_issue_delay_vect);
7581 VLA_HWINT_DELETE (compressed_min_issue_delay_vect);
7582}
7583
7584#ifndef NDEBUG
7585/* Number of states which contains transition only by advancing cpu
7586 cycle. */
7587static int locked_states_num;
7588#endif
7589
7590/* Form and output vector representing the locked states of
7591 AUTOMATON. */
7592static void
7593output_dead_lock_vect (automaton)
7594 automaton_t automaton;
7595{
7596 state_t *state_ptr;
7597 arc_t arc;
7598 vla_hwint_t dead_lock_vect;
7599
7600 /* Create vect of pointers to states ordered by num of
7601 transitions from the state (state with the maximum num is the
7602 first). */
7603 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7604 pass_states (automaton, add_states_vect_el);
7605 VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector");
7606 VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect));
7607 for (state_ptr = VLA_PTR_BEGIN (output_states_vect);
7608 state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7609 state_ptr++)
7610 {
7611 arc = first_out_arc (*state_ptr);
7612 if (arc == NULL)
7613 abort ();
7614 VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)
7615 = (next_out_arc (arc) == NULL
7616 && (arc->insn->insn_reserv_decl
7617 == &advance_cycle_insn_decl->decl.insn_reserv) ? 1 : 0);
7618#ifndef NDEBUG
7619 if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num))
7620 locked_states_num++;
7621#endif
7622 }
7623 fprintf (output_file, "/* Vector for locked state flags. */\n");
7624 fprintf (output_file, "static const ");
7625 output_range_type (output_file, 0, 1);
7626 fprintf (output_file, " ");
7627 output_dead_lock_vect_name (output_file, automaton);
7628 fprintf (output_file, "[] = {\n");
7629 output_vect (VLA_HWINT_BEGIN (dead_lock_vect),
7630 VLA_HWINT_LENGTH (dead_lock_vect));
7631 fprintf (output_file, "};\n\n");
7632 VLA_HWINT_DELETE (dead_lock_vect);
7633 VLA_PTR_DELETE (output_states_vect);
7634}
7635
7636/* Form and output vector representing reserved units of the states of
7637 AUTOMATON. */
7638static void
7639output_reserved_units_table (automaton)
7640 automaton_t automaton;
7641{
7642 state_t *curr_state_ptr;
7643 vla_hwint_t reserved_units_table;
7644 size_t state_byte_size;
7645 int i;
7646
7647 /* Create vect of pointers to states. */
7648 VLA_PTR_CREATE (output_states_vect, 1500, "output states vector");
7649 pass_states (automaton, add_states_vect_el);
7650 /* Create vector. */
7651 VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector");
7652 state_byte_size = (description->query_units_num + 7) / 8;
7653 VLA_HWINT_EXPAND (reserved_units_table,
7654 VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7655 for (i = 0;
7656 i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size);
7657 i++)
7658 VLA_HWINT (reserved_units_table, i) = 0;
7659 for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect);
7660 curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect);
7661 curr_state_ptr++)
7662 {
7663 for (i = 0; i < description->units_num; i++)
7664 if (units_array [i]->query_p)
7665 {
7666 if (test_unit_reserv ((*curr_state_ptr)->reservs, 0, i))
7667 VLA_HWINT (reserved_units_table,
7668 (*curr_state_ptr)->order_state_num * state_byte_size
7669 + units_array [i]->query_num / 8)
7670 += (1 << (units_array [i]->query_num % 8));
7671 }
7672 }
7673 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7674 fprintf (output_file, "static const ");
7675 output_range_type (output_file, 0, 255);
7676 fprintf (output_file, " ");
7677 output_reserved_units_table_name (output_file, automaton);
7678 fprintf (output_file, "[] = {\n");
7679 output_vect (VLA_HWINT_BEGIN (reserved_units_table),
7680 VLA_HWINT_LENGTH (reserved_units_table));
7681 fprintf (output_file, "};\n\n");
7682 VLA_HWINT_DELETE (reserved_units_table);
7683 VLA_PTR_DELETE (output_states_vect);
7684}
7685
7686/* The function outputs all tables representing DFA(s) used for fast
7687 pipeline hazards recognition. */
7688static void
7689output_tables ()
7690{
7691 automaton_t automaton;
7692
7693#ifndef NDEBUG
7694 locked_states_num = 0;
7695#endif
7696 initiate_min_issue_delay_pass_states ();
7697 for (automaton = description->first_automaton;
7698 automaton != NULL;
7699 automaton = automaton->next_automaton)
7700 {
7701 output_translate_vect (automaton);
7702 output_trans_table (automaton);
7703 fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
7704 output_state_alts_table (automaton);
7705 fprintf (output_file, "\n#endif /* #if %s */\n\n",
7706 AUTOMATON_STATE_ALTS_MACRO_NAME);
7707 output_min_issue_delay_table (automaton);
7708 output_dead_lock_vect (automaton);
7709 if (no_minimization_flag)
7710 {
7711 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
7712 output_reserved_units_table (automaton);
7713 fprintf (output_file, "\n#endif /* #if %s */\n\n",
7714 CPU_UNITS_QUERY_MACRO_NAME);
7715 }
7716 }
7717 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7718 advance_cycle_insn_decl->decl.insn_reserv.insn_num);
7719}
7720
7721/* The function outputs definition and value of PHR interface variable
7722 `max_insn_queue_index' */
7723static void
7724output_max_insn_queue_index_def ()
7725{
7726 int i;
7727
7728 for (i = 0; (1 << i) <= description->max_insn_reserv_cycles; i++)
7729 ;
7730 if (i < 0)
7731 abort ();
7732 fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1);
7733}
7734
7735
7736/* The function outputs switch cases for insn reseravtions using
7737 function *output_automata_list_code. */
7738static void
7739output_insn_code_cases (output_automata_list_code)
7740 void (*output_automata_list_code) (automata_list_el_t);
7741{
7742 decl_t decl, decl_2;
7743 int i, j;
7744
7745 for (i = 0; i < description->decls_num; i++)
7746 {
7747 decl = description->decls [i];
7748 if (decl->mode == dm_insn_reserv)
7749 decl->decl.insn_reserv.processed_p = FALSE;
7750 }
7751 for (i = 0; i < description->decls_num; i++)
7752 {
7753 decl = description->decls [i];
7754 if (decl->mode == dm_insn_reserv && !decl->decl.insn_reserv.processed_p)
7755 {
7756 for (j = i; j < description->decls_num; j++)
7757 {
7758 decl_2 = description->decls [j];
7759 if (decl_2->mode == dm_insn_reserv
7760 && (decl_2->decl.insn_reserv.important_automata_list
7761 == decl->decl.insn_reserv.important_automata_list))
7762 {
7763 decl_2->decl.insn_reserv.processed_p = TRUE;
7764 fprintf (output_file, " case %d: /* %s */\n",
7765 decl_2->decl.insn_reserv.insn_num,
7766 decl_2->decl.insn_reserv.name);
7767 }
7768 }
7769 (*output_automata_list_code)
7770 (decl->decl.insn_reserv.important_automata_list);
7771 }
7772 }
7773}
7774
7775
7776/* The function outputs a code for evaluation of a minimal delay of
7777 issue of insns which have reservations in given AUTOMATA_LIST. */
7778static void
7779output_automata_list_min_issue_delay_code (automata_list)
7780 automata_list_el_t automata_list;
7781{
7782 automata_list_el_t el;
7783 automaton_t automaton;
7784
7785 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7786 {
7787 automaton = el->automaton;
7788 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7789 output_min_issue_delay_vect_name (output_file, automaton);
7790 fprintf (output_file,
7791 (automaton->min_issue_delay_table_compression_factor != 1
7792 ? " [(" : " ["));
7793 output_translate_vect_name (output_file, automaton);
7794 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7795 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7796 output_chip_member_name (output_file, automaton);
7797 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7798 if (automaton->min_issue_delay_table_compression_factor == 1)
7799 fprintf (output_file, "];\n");
7800 else
7801 {
7802 fprintf (output_file, ") / %d];\n",
7803 automaton->min_issue_delay_table_compression_factor);
7804 fprintf (output_file, " %s = (%s >> (8 - (",
7805 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7806 output_translate_vect_name (output_file, automaton);
7807 fprintf
7808 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7809 INTERNAL_INSN_CODE_NAME,
7810 automaton->min_issue_delay_table_compression_factor,
7811 8 / automaton->min_issue_delay_table_compression_factor,
7812 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7813 - 1);
7814 }
7815 if (el == automata_list)
7816 fprintf (output_file, " %s = %s;\n",
7817 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7818 else
7819 {
7820 fprintf (output_file, " if (%s > %s)\n",
7821 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7822 fprintf (output_file, " %s = %s;\n",
7823 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7824 }
7825 }
7826 fprintf (output_file, " break;\n\n");
7827}
7828
7829/* Output function `internal_min_issue_delay'. */
7830static void
7831output_internal_min_issue_delay_func ()
7832{
7833 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
7834 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, CHIP_NAME);
7835 fprintf (output_file,
e2ff6cee 7836 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
fae15c93
VM
7837 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7838 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
7839 CHIP_PARAMETER_NAME);
e2ff6cee 7840 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s;\n",
fae15c93
VM
7841 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7842 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7843 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7844 fprintf (output_file,
7845 "\n default:\n %s = -1;\n break;\n }\n",
7846 RESULT_VARIABLE_NAME);
7847 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7848 fprintf (output_file, "}\n\n");
7849}
7850
7851/* The function outputs a code changing state after issue of insns
7852 which have reservations in given AUTOMATA_LIST. */
7853static void
7854output_automata_list_transition_code (automata_list)
7855 automata_list_el_t automata_list;
7856{
7857 automata_list_el_t el, next_el;
7858
7859 fprintf (output_file, " {\n");
7860 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7861 for (el = automata_list;; el = next_el)
7862 {
7863 next_el = el->next_automata_list_el;
7864 if (next_el == NULL)
7865 break;
7866 fprintf (output_file, " ");
7867 output_state_member_type (output_file, el->automaton);
7868 fprintf (output_file, " ");
7869 output_temp_chip_member_name (output_file, el->automaton);
7870 fprintf (output_file, ";\n");
7871 }
7872 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7873 if (comb_vect_p (el->automaton->trans_table))
7874 {
7875 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7876 output_trans_base_vect_name (output_file, el->automaton);
7877 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7878 output_chip_member_name (output_file, el->automaton);
7879 fprintf (output_file, "] + ");
7880 output_translate_vect_name (output_file, el->automaton);
7881 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7882 fprintf (output_file, " if (");
7883 output_trans_check_vect_name (output_file, el->automaton);
7884 fprintf (output_file, " [%s] != %s->",
7885 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7886 output_chip_member_name (output_file, el->automaton);
7887 fprintf (output_file, ")\n");
7888 fprintf (output_file, " return %s (%s, %s);\n",
7889 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7890 CHIP_PARAMETER_NAME);
7891 fprintf (output_file, " else\n");
7892 fprintf (output_file, " ");
7893 if (el->next_automata_list_el != NULL)
7894 output_temp_chip_member_name (output_file, el->automaton);
7895 else
7896 {
7897 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7898 output_chip_member_name (output_file, el->automaton);
7899 }
7900 fprintf (output_file, " = ");
7901 output_trans_comb_vect_name (output_file, el->automaton);
7902 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7903 }
7904 else
7905 {
7906 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7907 output_trans_full_vect_name (output_file, el->automaton);
7908 fprintf (output_file, " [");
7909 output_translate_vect_name (output_file, el->automaton);
7910 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7911 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7912 output_chip_member_name (output_file, el->automaton);
7913 fprintf (output_file, " * %d];\n",
7914 el->automaton->insn_equiv_classes_num);
7915 fprintf (output_file, " if (%s >= %d)\n",
7916 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7917 fprintf (output_file, " return %s (%s, %s);\n",
7918 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7919 CHIP_PARAMETER_NAME);
7920 fprintf (output_file, " else\n ");
7921 if (el->next_automata_list_el != NULL)
7922 output_temp_chip_member_name (output_file, el->automaton);
7923 else
7924 {
7925 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7926 output_chip_member_name (output_file, el->automaton);
7927 }
7928 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7929 }
7930 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7931 for (el = automata_list;; el = next_el)
7932 {
7933 next_el = el->next_automata_list_el;
7934 if (next_el == NULL)
7935 break;
7936 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7937 output_chip_member_name (output_file, el->automaton);
7938 fprintf (output_file, " = ");
7939 output_temp_chip_member_name (output_file, el->automaton);
7940 fprintf (output_file, ";\n");
7941 }
7942 fprintf (output_file, " return -1;\n");
7943 fprintf (output_file, " }\n");
7944}
7945
7946/* Output function `internal_state_transition'. */
7947static void
7948output_internal_trans_func ()
7949{
7950 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
7951 INTERNAL_TRANSITION_FUNC_NAME, CHIP_NAME);
7952 fprintf (output_file,
e2ff6cee 7953 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s ATTRIBUTE_UNUSED;\n",
fae15c93
VM
7954 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7955 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME,
7956 CHIP_NAME, CHIP_PARAMETER_NAME);
e2ff6cee 7957 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
fae15c93
VM
7958 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7959 output_insn_code_cases (output_automata_list_transition_code);
7960 fprintf (output_file, "\n default:\n return -1;\n }\n");
7961 fprintf (output_file, "}\n\n");
7962}
7963
7964/* Output code
7965
7966 if (insn != 0)
7967 {
7968 insn_code = dfa_insn_code (insn);
7969 if (insn_code > DFA__ADVANCE_CYCLE)
7970 return code;
7971 }
7972 else
7973 insn_code = DFA__ADVANCE_CYCLE;
7974
7975 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7976 code denotes CODE. */
7977static void
7978output_internal_insn_code_evaluation (insn_name, insn_code_name, code)
7979 const char *insn_name;
7980 const char *insn_code_name;
7981 int code;
7982{
7983 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
7984 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
7985 DFA_INSN_CODE_FUNC_NAME, insn_name);
7986 fprintf (output_file, " if (%s > %s)\n return %d;\n",
7987 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
7988 fprintf (output_file, " }\n else\n %s = %s;\n\n",
7989 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
7990}
7991
7992
7993/* The function outputs function `dfa_insn_code'. */
7994static void
7995output_dfa_insn_code_func ()
7996{
7997 fprintf (output_file, "#ifdef __GNUC__\n__inline__\n#endif\n");
7998 fprintf (output_file, "static int %s PARAMS ((rtx));\n",
7999 DFA_INSN_CODE_FUNC_NAME);
8000 fprintf (output_file, "static int\n%s (%s)\n\trtx %s;\n",
8001 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME, INSN_PARAMETER_NAME);
8002 fprintf (output_file, "{\n int %s;\n int %s;\n\n",
8003 INTERNAL_INSN_CODE_NAME, TEMPORARY_VARIABLE_NAME);
8004 fprintf (output_file, " if (INSN_UID (%s) >= %s)\n {\n",
8005 INSN_PARAMETER_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8006 fprintf (output_file, " %s = %s;\n %s = 2 * INSN_UID (%s);\n",
8007 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8008 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, INSN_PARAMETER_NAME);
8009 fprintf (output_file, " %s = xrealloc (%s, %s * sizeof (int));\n",
8010 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8011 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8012 fprintf (output_file,
8013 " for (; %s < %s; %s++)\n %s [%s] = -1;\n }\n",
8014 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8015 TEMPORARY_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8016 TEMPORARY_VARIABLE_NAME);
8017 fprintf (output_file, " if ((%s = %s [INSN_UID (%s)]) < 0)\n {\n",
8018 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8019 INSN_PARAMETER_NAME);
8020 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8021 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8022 fprintf (output_file, " %s [INSN_UID (%s)] = %s;\n",
8023 DFA_INSN_CODES_VARIABLE_NAME, INSN_PARAMETER_NAME,
8024 INTERNAL_INSN_CODE_NAME);
8025 fprintf (output_file, " }\n return %s;\n}\n\n",
8026 INTERNAL_INSN_CODE_NAME);
8027}
8028
8029/* The function outputs PHR interface function `state_transition'. */
8030static void
8031output_trans_func ()
8032{
8033 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8034 TRANSITION_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8035 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8036 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8037 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8038 INTERNAL_INSN_CODE_NAME, -1);
8039 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8040 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8041}
8042
8043/* The function outputs a code for evaluation of alternative states
8044 number for insns which have reservations in given AUTOMATA_LIST. */
8045static void
8046output_automata_list_state_alts_code (automata_list)
8047 automata_list_el_t automata_list;
8048{
8049 automata_list_el_t el;
8050 automaton_t automaton;
8051
8052 fprintf (output_file, " {\n");
8053 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8054 if (comb_vect_p (el->automaton->state_alts_table))
8055 {
8056 fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME);
8057 break;
8058 }
8059 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8060 {
8061 automaton = el->automaton;
8062 if (comb_vect_p (automaton->state_alts_table))
8063 {
8064 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8065 output_state_alts_base_vect_name (output_file, automaton);
8066 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8067 output_chip_member_name (output_file, automaton);
8068 fprintf (output_file, "] + ");
8069 output_translate_vect_name (output_file, automaton);
8070 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8071 fprintf (output_file, " if (");
8072 output_state_alts_check_vect_name (output_file, automaton);
8073 fprintf (output_file, " [%s] != %s->",
8074 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8075 output_chip_member_name (output_file, automaton);
8076 fprintf (output_file, ")\n");
8077 fprintf (output_file, " return 0;\n");
8078 fprintf (output_file, " else\n");
8079 fprintf (output_file,
8080 (el == automata_list
8081 ? " %s = " : " %s += "),
8082 RESULT_VARIABLE_NAME);
8083 output_state_alts_comb_vect_name (output_file, automaton);
8084 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8085 }
8086 else
8087 {
8088 fprintf (output_file,
8089 (el == automata_list
8090 ? "\n %s = " : " %s += "),
8091 RESULT_VARIABLE_NAME);
8092 output_state_alts_full_vect_name (output_file, automaton);
8093 fprintf (output_file, " [");
8094 output_translate_vect_name (output_file, automaton);
8095 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8096 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8097 output_chip_member_name (output_file, automaton);
8098 fprintf (output_file, " * %d];\n",
8099 automaton->insn_equiv_classes_num);
8100 }
8101 }
8102 fprintf (output_file, " break;\n }\n\n");
8103}
8104
8105/* Output function `internal_state_alts'. */
8106static void
8107output_internal_state_alts_func ()
8108{
8109 fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n",
8110 INTERNAL_STATE_ALTS_FUNC_NAME, CHIP_NAME);
8111 fprintf (output_file,
8112 "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n",
8113 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8114 CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME,
8115 CHIP_PARAMETER_NAME);
8116 fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME);
8117 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8118 output_insn_code_cases (output_automata_list_state_alts_code);
8119 fprintf (output_file,
8120 "\n default:\n %s = 0;\n break;\n }\n",
8121 RESULT_VARIABLE_NAME);
8122 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8123 fprintf (output_file, "}\n\n");
8124}
8125
8126/* The function outputs PHR interface function `state_alts'. */
8127static void
8128output_state_alts_func ()
8129{
8130 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8131 STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8132 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8133 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8134 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8135 INTERNAL_INSN_CODE_NAME, 0);
8136 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8137 INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8138}
8139
8140/* Output function `min_issue_delay'. */
8141static void
8142output_min_issue_delay_func ()
8143{
8144 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n",
8145 MIN_ISSUE_DELAY_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME,
8146 STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME);
8147 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8148 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8149 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8150 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8151 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8152 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8153 fprintf (output_file, " }\n else\n %s = %s;\n",
8154 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8155 fprintf (output_file, "\n return %s (%s, %s);\n",
8156 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8157 STATE_NAME);
8158 fprintf (output_file, "}\n\n");
8159}
8160
8161/* Output function `internal_dead_lock'. */
8162static void
8163output_internal_dead_lock_func ()
8164{
8165 automaton_t automaton;
8166
8167 fprintf (output_file, "static int %s PARAMS ((struct %s *));\n",
8168 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME);
8169 fprintf (output_file, "static int\n%s (%s)\n\tstruct %s *%s;\n",
8170 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_PARAMETER_NAME, CHIP_NAME,
8171 CHIP_PARAMETER_NAME);
8172 fprintf (output_file, "{\n");
8173 for (automaton = description->first_automaton;
8174 automaton != NULL;
8175 automaton = automaton->next_automaton)
8176 {
8177 fprintf (output_file, " if (");
8178 output_dead_lock_vect_name (output_file, automaton);
8179 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8180 output_chip_member_name (output_file, automaton);
8181 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8182 }
8183 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8184}
8185
8186/* The function outputs PHR interface function `state_dead_lock_p'. */
8187static void
8188output_dead_lock_func ()
8189{
8190 fprintf (output_file, "int\n%s (%s)\n\t%s %s;\n",
8191 DEAD_LOCK_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8192 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8193 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8194}
8195
8196/* Output function `internal_reset'. */
8197static void
8198output_internal_reset_func ()
8199{
8200 fprintf (output_file, "static void %s PARAMS ((struct %s *));\n",
8201 INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8202 fprintf (output_file, "static void\n%s (%s)\n\tstruct %s *%s;\n",
8203 INTERNAL_RESET_FUNC_NAME, CHIP_PARAMETER_NAME,
8204 CHIP_NAME, CHIP_PARAMETER_NAME);
8205 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8206 CHIP_PARAMETER_NAME, CHIP_NAME);
8207}
8208
8209/* The function outputs PHR interface function `state_size'. */
8210static void
8211output_size_func ()
8212{
8213 fprintf (output_file, "int\n%s ()\n", SIZE_FUNC_NAME);
8214 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8215}
8216
8217/* The function outputs PHR interface function `state_reset'. */
8218static void
8219output_reset_func ()
8220{
8221 fprintf (output_file, "void\n%s (%s)\n\t %s %s;\n",
8222 RESET_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME);
8223 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8224 STATE_NAME);
8225}
8226
8227/* Output function `min_insn_conflict_delay'. */
8228static void
8229output_min_insn_conflict_delay_func ()
8230{
8231 fprintf (output_file,
8232 "int\n%s (%s, %s, %s)\n\t%s %s;\n\trtx %s;\n\trtx %s;\n",
8233 MIN_INSN_CONFLICT_DELAY_FUNC_NAME,
8234 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8235 STATE_TYPE_NAME, STATE_NAME,
8236 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8237 fprintf (output_file, "{\n struct %s %s;\n int %s, %s;\n",
8238 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8239 INTERNAL_INSN2_CODE_NAME);
8240 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8241 INTERNAL_INSN_CODE_NAME, 0);
8242 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8243 INTERNAL_INSN2_CODE_NAME, 0);
8244 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8245 CHIP_NAME, STATE_NAME, CHIP_NAME);
8246 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8247 fprintf (output_file, " if (%s (%s, &%s) > 0)\n abort ();\n",
8248 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8249 fprintf (output_file, " return %s (%s, &%s);\n",
8250 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8251 CHIP_NAME);
8252 fprintf (output_file, "}\n\n");
8253}
8254
8255/* Output function `internal_insn_latency'. */
8256static void
8257output_internal_insn_latency_func ()
8258{
8259 decl_t decl;
8260 struct bypass_decl *bypass;
8261 int i;
8262
8263 fprintf (output_file, "static int %s PARAMS ((int, int, rtx, rtx));\n",
8264 INTERNAL_INSN_LATENCY_FUNC_NAME);
8265 fprintf (output_file, "static int\n%s (%s, %s, %s, %s)",
8266 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8267 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8268 INSN2_PARAMETER_NAME);
8269 fprintf (output_file, "\n\tint %s;\n\tint %s;\n",
8270 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8271 fprintf (output_file,
8272 "\trtx %s ATTRIBUTE_UNUSED;\n\trtx %s ATTRIBUTE_UNUSED;\n",
8273 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8274 fprintf (output_file, "{\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8275 for (i = 0; i < description->decls_num; i++)
8276 {
8277 decl = description->decls [i];
8278 if (decl->mode == dm_insn_reserv)
8279 {
8280 fprintf (output_file, " case %d:\n",
8281 decl->decl.insn_reserv.insn_num);
8282 if (decl->decl.insn_reserv.bypass_list == NULL)
8283 fprintf (output_file, " return (%s != %s ? %d : 0);\n",
8284 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8285 decl->decl.insn_reserv.default_latency);
8286 else
8287 {
8288 fprintf (output_file, " switch (%s)\n {\n",
8289 INTERNAL_INSN2_CODE_NAME);
8290 for (bypass = decl->decl.insn_reserv.bypass_list;
8291 bypass != NULL;
8292 bypass = bypass->next)
8293 {
8294 fprintf (output_file, " case %d:\n",
8295 bypass->in_insn_reserv->insn_num);
8296 if (bypass->bypass_guard_name == NULL)
8297 fprintf (output_file, " return %d;\n",
8298 bypass->latency);
8299 else
8300 fprintf (output_file,
8301 " return (%s (%s, %s) ? %d : %d);\n",
8302 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8303 INSN2_PARAMETER_NAME, bypass->latency,
8304 decl->decl.insn_reserv.default_latency);
8305 }
8306 fprintf (output_file, " default:\n");
8307 fprintf (output_file,
8308 " return (%s != %s ? %d : 0);\n }\n",
8309 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8310 decl->decl.insn_reserv.default_latency);
8311
8312 }
8313 }
8314 }
8315 fprintf (output_file, " default:\n return 0;\n }\n}\n\n");
8316}
8317
8318/* The function outputs PHR interface function `insn_latency'. */
8319static void
8320output_insn_latency_func ()
8321{
8322 fprintf (output_file, "int\n%s (%s, %s)\n\trtx %s;\n\trtx %s;\n",
8323 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME,
8324 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8325 fprintf (output_file, "{\n int %s, %s;\n",
8326 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8327 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8328 INTERNAL_INSN_CODE_NAME, 0);
8329 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8330 INTERNAL_INSN2_CODE_NAME, 0);
8331 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8332 INTERNAL_INSN_LATENCY_FUNC_NAME,
8333 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8334 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8335}
8336
8337/* The function outputs PHR interface function `print_reservation'. */
8338static void
8339output_print_reservation_func ()
8340{
8341 decl_t decl;
8342 int i;
8343
8344 fprintf (output_file, "void\n%s (%s, %s)\n\tFILE *%s;\n\trtx %s;\n",
8345 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8346 INSN_PARAMETER_NAME, FILE_PARAMETER_NAME,
8347 INSN_PARAMETER_NAME);
8348 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8349 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8350 fprintf (output_file, " %s = %s (%s);\n",
8351 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8352 INSN_PARAMETER_NAME);
8353 fprintf (output_file, " if (%s > %s)\n",
8354 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8355 fprintf (output_file, " {\n fprintf (%s, \"%s\");\n",
8356 FILE_PARAMETER_NAME, NOTHING_NAME);
8357 fprintf (output_file, " return;\n }\n");
8358 fprintf (output_file, " }\n else\n");
8359 fprintf (output_file,
8360 " {\n fprintf (%s, \"%s\");\n return;\n }\n",
8361 FILE_PARAMETER_NAME, NOTHING_NAME);
8362 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8363 for (i = 0; i < description->decls_num; i++)
8364 {
8365 decl = description->decls [i];
8366 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8367 {
8368 fprintf (output_file,
8369 " case %d:\n", decl->decl.insn_reserv.insn_num);
8370 fprintf (output_file,
8371 " fprintf (%s, \"%s\");\n break;\n",
8372 FILE_PARAMETER_NAME,
8373 regexp_representation (decl->decl.insn_reserv.regexp));
8374 finish_regexp_representation ();
8375 }
8376 }
8377 fprintf (output_file, " default:\n fprintf (%s, \"%s\");\n }\n",
8378 FILE_PARAMETER_NAME, NOTHING_NAME);
8379 fprintf (output_file, "}\n\n");
8380}
8381
8382/* The following function is used to sort unit declaration by their
8383 names. */
8384static int
8385units_cmp (unit1, unit2)
8386 const void *unit1, *unit2;
8387{
deb09eff
VM
8388 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8389 const unit_decl_t u2 = *(unit_decl_t *) unit2;
fae15c93
VM
8390
8391 return strcmp (u1->name, u2->name);
8392}
8393
8394/* The following macro value is name of struct containing unit name
8395 and unit code. */
8396#define NAME_CODE_STRUCT_NAME "name_code"
8397
8398/* The following macro value is name of table of struct name_code. */
8399#define NAME_CODE_TABLE_NAME "name_code_table"
8400
8401/* The following macro values are member names for struct name_code. */
8402#define NAME_MEMBER_NAME "name"
8403#define CODE_MEMBER_NAME "code"
8404
8405/* The following macro values are local variable names for function
8406 `get_cpu_unit_code'. */
8407#define CMP_VARIABLE_NAME "cmp"
8408#define LOW_VARIABLE_NAME "l"
8409#define MIDDLE_VARIABLE_NAME "m"
8410#define HIGH_VARIABLE_NAME "h"
8411
8412/* The following function outputs function to obtain internal cpu unit
8413 code by the cpu unit name. */
8414static void
8415output_get_cpu_unit_code_func ()
8416{
8417 int i;
deb09eff 8418 unit_decl_t *units;
fae15c93
VM
8419
8420 fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n",
8421 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8422 CPU_UNIT_NAME_PARAMETER_NAME);
8423 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8424 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8425 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8426 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8427 fprintf (output_file, " static struct %s %s [] =\n {\n",
8428 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
deb09eff
VM
8429 units = (unit_decl_t *) xmalloc (sizeof (unit_decl_t)
8430 * description->units_num);
8431 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8432 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
fae15c93
VM
8433 for (i = 0; i < description->units_num; i++)
8434 if (units [i]->query_p)
8435 fprintf (output_file, " {\"%s\", %d},\n",
8436 units[i]->name, units[i]->query_num);
8437 fprintf (output_file, " };\n\n");
8438 fprintf (output_file, " /* The following is binary search: */\n");
8439 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8440 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8441 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8442 fprintf (output_file, " while (%s <= %s)\n {\n",
8443 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8444 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8445 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8446 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8447 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8448 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8449 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8450 fprintf (output_file, " %s = %s - 1;\n",
8451 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8452 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8453 fprintf (output_file, " %s = %s + 1;\n",
8454 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8455 fprintf (output_file, " else\n");
8456 fprintf (output_file, " return %s [%s].%s;\n }\n",
8457 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8458 fprintf (output_file, " return -1;\n}\n\n");
8459 free (units);
8460}
8461
8462/* The following function outputs function to check reservation of cpu
8463 unit (its internal code will be passed as the function argument) in
8464 given cpu state. */
8465static void
8466output_cpu_unit_reservation_p ()
8467{
8468 automaton_t automaton;
8469
8470 fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n",
8471 CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME,
8472 CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME,
8473 CPU_CODE_PARAMETER_NAME);
8474 fprintf (output_file, "{\n if (%s < 0 || %s >= %d)\n abort ();\n",
8475 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8476 description->query_units_num);
8477 for (automaton = description->first_automaton;
8478 automaton != NULL;
8479 automaton = automaton->next_automaton)
8480 {
8481 fprintf (output_file, " if ((");
8482 output_reserved_units_table_name (output_file, automaton);
8483 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8484 output_chip_member_name (output_file, automaton);
8485 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8486 (description->query_units_num + 7) / 8,
8487 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8488 fprintf (output_file, " return 1;\n");
8489 }
8490 fprintf (output_file, " return 0;\n}\n\n");
8491}
8492
8493/* The function outputs PHR interface function `dfa_start'. */
8494static void
8495output_dfa_start_func ()
8496{
8497 fprintf (output_file,
8498 "void\n%s ()\n{\n int %s;\n\n %s = get_max_uid ();\n",
8499 DFA_START_FUNC_NAME, I_VARIABLE_NAME,
8500 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8501 fprintf (output_file, " %s = (int *) xmalloc (%s * sizeof (int));\n",
8502 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8503 fprintf (output_file,
8504 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8505 I_VARIABLE_NAME, I_VARIABLE_NAME,
8506 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8507 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8508}
8509
8510/* The function outputs PHR interface function `dfa_finish'. */
8511static void
8512output_dfa_finish_func ()
8513{
8514 fprintf (output_file, "void\n%s ()\n{\n free (%s);\n}\n\n",
8515 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8516}
8517
8518\f
8519
8520/* The page contains code for output description file (readable
8521 representation of original description and generated DFA(s). */
8522
8523/* The function outputs string representation of IR reservation. */
8524static void
8525output_regexp (regexp)
8526 regexp_t regexp;
8527{
8528 fprintf (output_description_file, "%s", regexp_representation (regexp));
8529 finish_regexp_representation ();
8530}
8531
8532/* Output names of units in LIST separated by comma. */
8533static void
8534output_unit_set_el_list (list)
8535 unit_set_el_t list;
8536{
8537 unit_set_el_t el;
8538
8539 for (el = list; el != NULL; el = el->next_unit_set_el)
8540 {
8541 if (el != list)
8542 fprintf (output_description_file, ",");
8543 fprintf (output_description_file, "%s", el->unit_decl->name);
8544 }
8545}
8546
8547/* The function outputs string representation of IR define_reservation
8548 and define_insn_reservation. */
8549static void
8550output_description ()
8551{
8552 decl_t decl;
8553 int i;
8554
8555 for (i = 0; i < description->decls_num; i++)
8556 {
8557 decl = description->decls [i];
8558 if (decl->mode == dm_unit)
8559 {
8560 if (decl->decl.unit.excl_list != NULL)
8561 {
8562 fprintf (output_description_file, "unit %s exlusion_set: ",
8563 decl->decl.unit.name);
8564 output_unit_set_el_list (decl->decl.unit.excl_list);
8565 fprintf (output_description_file, "\n");
8566 }
8567 if (decl->decl.unit.presence_list != NULL)
8568 {
8569 fprintf (output_description_file, "unit %s presence_set: ",
8570 decl->decl.unit.name);
8571 output_unit_set_el_list (decl->decl.unit.presence_list);
8572 fprintf (output_description_file, "\n");
8573 }
8574 if (decl->decl.unit.absence_list != NULL)
8575 {
8576 fprintf (output_description_file, "unit %s absence_set: ",
8577 decl->decl.unit.name);
8578 output_unit_set_el_list (decl->decl.unit.absence_list);
8579 fprintf (output_description_file, "\n");
8580 }
8581 }
8582 }
8583 fprintf (output_description_file, "\n");
8584 for (i = 0; i < description->decls_num; i++)
8585 {
8586 decl = description->decls [i];
8587 if (decl->mode == dm_reserv)
8588 {
8589 fprintf (output_description_file, "reservation ");
8590 fprintf (output_description_file, decl->decl.reserv.name);
8591 fprintf (output_description_file, ": ");
8592 output_regexp (decl->decl.reserv.regexp);
8593 fprintf (output_description_file, "\n");
8594 }
8595 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8596 {
8597 fprintf (output_description_file, "insn reservation %s ",
8598 decl->decl.insn_reserv.name);
8599 print_rtl (output_description_file, decl->decl.insn_reserv.condexp);
8600 fprintf (output_description_file, ": ");
8601 output_regexp (decl->decl.insn_reserv.regexp);
8602 fprintf (output_description_file, "\n");
8603 }
8604 else if (decl->mode == dm_bypass)
8605 fprintf (output_description_file, "bypass %d %s %s\n",
8606 decl->decl.bypass.latency, decl->decl.bypass.out_insn_name,
8607 decl->decl.bypass.in_insn_name);
8608 }
8609 fprintf (output_description_file, "\n\f\n");
8610}
8611
8612/* The function outputs name of AUTOMATON. */
8613static void
8614output_automaton_name (f, automaton)
8615 FILE *f;
8616 automaton_t automaton;
8617{
8618 if (automaton->corresponding_automaton_decl == NULL)
8619 fprintf (f, "#%d", automaton->automaton_order_num);
8620 else
8621 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8622}
8623
8624/* Maximal length of line for pretty printing into description
8625 file. */
8626#define MAX_LINE_LENGTH 70
8627
8628/* The function outputs units name belonging to AUTOMATON. */
8629static void
8630output_automaton_units (automaton)
8631 automaton_t automaton;
8632{
8633 decl_t decl;
8634 char *name;
8635 int curr_line_length;
8636 int there_is_an_automaton_unit;
8637 int i;
8638
8639 fprintf (output_description_file, "\n Coresponding units:\n");
8640 fprintf (output_description_file, " ");
8641 curr_line_length = 4;
8642 there_is_an_automaton_unit = 0;
8643 for (i = 0; i < description->decls_num; i++)
8644 {
8645 decl = description->decls [i];
8646 if (decl->mode == dm_unit
8647 && (decl->decl.unit.corresponding_automaton_num
8648 == automaton->automaton_order_num))
8649 {
8650 there_is_an_automaton_unit = 1;
8651 name = decl->decl.unit.name;
8652 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8653 {
8654 curr_line_length = strlen (name) + 4;
8655 fprintf (output_description_file, "\n ");
8656 }
8657 else
8658 {
8659 curr_line_length += strlen (name) + 1;
8660 fprintf (output_description_file, " ");
8661 }
8662 fprintf (output_description_file, name);
8663 }
8664 }
8665 if (!there_is_an_automaton_unit)
8666 fprintf (output_description_file, "<None>");
8667 fprintf (output_description_file, "\n\n");
8668}
8669
8670/* The following variable is used for forming array of all possible cpu unit
8671 reservations described by the current DFA state. */
8672static vla_ptr_t state_reservs;
8673
8674/* The function forms `state_reservs' for STATE. */
8675static void
8676add_state_reservs (state)
8677 state_t state;
8678{
8679 alt_state_t curr_alt_state;
8680 reserv_sets_t reservs;
8681
8682 if (state->component_states != NULL)
8683 for (curr_alt_state = state->component_states;
8684 curr_alt_state != NULL;
8685 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8686 add_state_reservs (curr_alt_state->state);
8687 else
8688 {
8689 reservs = state->reservs;
8690 VLA_PTR_ADD (state_reservs, reservs);
8691 }
8692}
8693
8694/* The function outputs readable represenatation of all out arcs of
8695 STATE. */
8696static void
8697output_state_arcs (state)
8698 state_t state;
8699{
8700 arc_t arc;
8701 ainsn_t ainsn;
8702 char *insn_name;
8703 int curr_line_length;
8704
8705 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8706 {
8707 ainsn = arc->insn;
8708 if (!ainsn->first_insn_with_same_reservs)
8709 abort ();
8710 fprintf (output_description_file, " ");
8711 curr_line_length = 7;
8712 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8713 do
8714 {
8715 insn_name = ainsn->insn_reserv_decl->name;
8716 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8717 {
8718 if (ainsn != arc->insn)
8719 {
8720 fprintf (output_description_file, ",\n ");
8721 curr_line_length = strlen (insn_name) + 6;
8722 }
8723 else
8724 curr_line_length += strlen (insn_name);
8725 }
8726 else
8727 {
8728 curr_line_length += strlen (insn_name);
8729 if (ainsn != arc->insn)
8730 {
8731 curr_line_length += 2;
8732 fprintf (output_description_file, ", ");
8733 }
8734 }
8735 fprintf (output_description_file, insn_name);
8736 ainsn = ainsn->next_same_reservs_insn;
8737 }
8738 while (ainsn != NULL);
8739 fprintf (output_description_file, " %d (%d)\n",
8740 arc->to_state->order_state_num, arc->state_alts);
8741 }
8742 fprintf (output_description_file, "\n");
8743}
8744
8745/* The following function is used for sorting possible cpu unit
8746 reservation of a DFA state. */
8747static int
8748state_reservs_cmp (reservs_ptr_1, reservs_ptr_2)
8749 const void *reservs_ptr_1;
8750 const void *reservs_ptr_2;
8751{
8752 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
8753 *(reserv_sets_t *) reservs_ptr_2);
8754}
8755
8756/* The following function is used for sorting possible cpu unit
8757 reservation of a DFA state. */
8758static void
8759remove_state_duplicate_reservs ()
8760{
8761 reserv_sets_t *reservs_ptr;
8762 reserv_sets_t *last_formed_reservs_ptr;
8763
8764 last_formed_reservs_ptr = NULL;
8765 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
8766 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
8767 reservs_ptr++)
8768 if (last_formed_reservs_ptr == NULL)
8769 last_formed_reservs_ptr = reservs_ptr;
8770 else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0)
8771 {
8772 ++last_formed_reservs_ptr;
8773 *last_formed_reservs_ptr = *reservs_ptr;
8774 }
8775 VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1);
8776}
8777
8778/* The following function output readable representation of DFA(s)
8779 state used for fast recognition of pipeline hazards. State is
8780 described by possible (current and scehduled) cpu unit
8781 reservations. */
8782static void
8783output_state (state)
8784 state_t state;
8785{
8786 reserv_sets_t *reservs_ptr;
8787
8788 VLA_PTR_CREATE (state_reservs, 150, "state reservations");
8789 fprintf (output_description_file, " State #%d", state->order_state_num);
8790 fprintf (output_description_file,
8791 state->new_cycle_p ? " (new cycle)\n" : "\n");
8792 add_state_reservs (state);
8793 qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs),
8794 sizeof (reserv_sets_t), state_reservs_cmp);
8795 remove_state_duplicate_reservs ();
8796 for (reservs_ptr = VLA_PTR_BEGIN (state_reservs);
8797 reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs);
8798 reservs_ptr++)
8799 {
8800 fprintf (output_description_file, " ");
8801 output_reserv_sets (output_description_file, *reservs_ptr);
8802 fprintf (output_description_file, "\n");
8803 }
8804 fprintf (output_description_file, "\n");
8805 output_state_arcs (state);
8806 VLA_PTR_DELETE (state_reservs);
8807}
8808
8809/* The following function output readable representation of
8810 DFAs used for fast recognition of pipeline hazards. */
8811static void
8812output_automaton_descriptions ()
8813{
8814 automaton_t automaton;
8815
8816 for (automaton = description->first_automaton;
8817 automaton != NULL;
8818 automaton = automaton->next_automaton)
8819 {
8820 fprintf (output_description_file, "\nAutomaton ");
8821 output_automaton_name (output_description_file, automaton);
8822 fprintf (output_description_file, "\n");
8823 output_automaton_units (automaton);
8824 pass_states (automaton, output_state);
8825 }
8826}
8827
8828\f
8829
8830/* The page contains top level function for generation DFA(s) used for
8831 PHR. */
8832
8833/* The function outputs statistics about work of different phases of
8834 DFA generator. */
8835static void
8836output_statistics (f)
8837 FILE *f;
8838{
8839 automaton_t automaton;
8840#ifndef NDEBUG
8841 int transition_comb_vect_els = 0;
8842 int transition_full_vect_els = 0;
8843 int state_alts_comb_vect_els = 0;
8844 int state_alts_full_vect_els = 0;
8845 int min_issue_delay_vect_els = 0;
8846#endif
8847
8848 for (automaton = description->first_automaton;
8849 automaton != NULL;
8850 automaton = automaton->next_automaton)
8851 {
8852 fprintf (f, "\nAutomaton ");
8853 output_automaton_name (f, automaton);
8854 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
8855 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8856 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
8857 automaton->DFA_states_num, automaton->DFA_arcs_num);
8858 if (!no_minimization_flag)
8859 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8860 automaton->minimal_DFA_states_num,
8861 automaton->minimal_DFA_arcs_num);
8862 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
8863 description->insns_num, automaton->insn_equiv_classes_num);
8864#ifndef NDEBUG
8865 fprintf
8866 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8867 (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect),
8868 (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect),
8869 (comb_vect_p (automaton->trans_table)
8870 ? "use comb vect" : "use simple vect"));
8871 fprintf
8872 (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n",
8873 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect),
8874 (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect),
8875 (comb_vect_p (automaton->state_alts_table)
8876 ? "use comb vect" : "use simple vect"));
8877 fprintf
8878 (f, "%5ld min delay table els, compression factor %d\n",
8879 (long) automaton->DFA_states_num * automaton->insn_equiv_classes_num,
8880 automaton->min_issue_delay_table_compression_factor);
8881 transition_comb_vect_els
8882 += VLA_HWINT_LENGTH (automaton->trans_table->comb_vect);
8883 transition_full_vect_els
8884 += VLA_HWINT_LENGTH (automaton->trans_table->full_vect);
8885 state_alts_comb_vect_els
8886 += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect);
8887 state_alts_full_vect_els
8888 += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect);
8889 min_issue_delay_vect_els
8890 += automaton->DFA_states_num * automaton->insn_equiv_classes_num;
8891#endif
8892 }
8893#ifndef NDEBUG
8894 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
8895 allocated_states_num, allocated_arcs_num);
8896 fprintf (f, "%5d all allocated alternative states\n",
8897 allocated_alt_states_num);
8898 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
8899 transition_comb_vect_els, transition_full_vect_els);
8900 fprintf
8901 (f, "%5d all state alts comb vector els, %5d all state alts table els\n",
8902 state_alts_comb_vect_els, state_alts_full_vect_els);
8903 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
8904 fprintf (f, "%5d locked states num\n", locked_states_num);
8905#endif
8906}
8907
8908/* The function output times of work of different phases of DFA
8909 generator. */
8910static void
8911output_time_statistics (f)
8912 FILE *f;
8913{
8914 fprintf (f, "\n transformation: ");
8915 print_active_time (f, transform_time);
8916 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
8917 print_active_time (f, NDFA_time);
8918 if (ndfa_flag)
8919 {
8920 fprintf (f, ", NDFA -> DFA: ");
8921 print_active_time (f, NDFA_to_DFA_time);
8922 }
8923 fprintf (f, "\n DFA minimization: ");
8924 print_active_time (f, minimize_time);
8925 fprintf (f, ", making insn equivalence: ");
8926 print_active_time (f, equiv_time);
8927 fprintf (f, "\n all automaton generation: ");
8928 print_active_time (f, automaton_generation_time);
8929 fprintf (f, ", output: ");
8930 print_active_time (f, output_time);
8931 fprintf (f, "\n");
8932}
8933
8934/* The function generates DFA (deterministic finate state automaton)
8935 for fast recognition of pipeline hazards. No errors during
8936 checking must be fixed before this function call. */
8937static void
8938generate ()
8939{
8940 automata_num = split_argument;
8941 if (description->units_num < automata_num)
8942 automata_num = description->units_num;
8943 initiate_states ();
8944 initiate_arcs ();
8945 initiate_automata_lists ();
8946 initiate_pass_states ();
8947 initiate_excl_sets ();
8948 initiate_presence_absence_sets ();
8949 automaton_generation_time = create_ticker ();
fae15c93
VM
8950 create_automata ();
8951 ticker_off (&automaton_generation_time);
8952}
8953
8954\f
8955
8956/* The following function creates attribute which order number of insn
8957 in pipeline hazard description translator. */
8958static void
8959make_insn_alts_attr ()
8960{
8961 int i, insn_num;
8962 decl_t decl;
8963 rtx condexp;
8964
8965 condexp = rtx_alloc (COND);
8966 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
8967 XEXP (condexp, 1) = make_numeric_value (0);
8968 for (i = insn_num = 0; i < description->decls_num; i++)
8969 {
8970 decl = description->decls [i];
8971 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8972 {
8973 XVECEXP (condexp, 0, 2 * insn_num) = decl->decl.insn_reserv.condexp;
8974 XVECEXP (condexp, 0, 2 * insn_num + 1)
8975 = make_numeric_value (decl->decl.insn_reserv.transformed_regexp
8976 ->regexp.oneof.regexps_num);
8977 insn_num++;
8978 }
8979 }
8980 if (description->insns_num != insn_num + 1)
8981 abort ();
8982 make_internal_attr (attr_printf (sizeof ("*")
8983 + strlen (INSN_ALTS_FUNC_NAME) + 1,
8984 "*%s", INSN_ALTS_FUNC_NAME),
8985 condexp, 0);
8986}
8987
8988\f
8989
8990/* The following function creates attribute which is order number of
8991 insn in pipeline hazard description translator. */
8992static void
8993make_internal_dfa_insn_code_attr ()
8994{
8995 int i, insn_num;
8996 decl_t decl;
8997 rtx condexp;
8998
8999 condexp = rtx_alloc (COND);
9000 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9001 XEXP (condexp, 1) = make_numeric_value (advance_cycle_insn_decl
9002 ->decl.insn_reserv.insn_num + 1);
9003 for (i = insn_num = 0; i < description->decls_num; i++)
9004 {
9005 decl = description->decls [i];
9006 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9007 {
9008 XVECEXP (condexp, 0, 2 * insn_num) = decl->decl.insn_reserv.condexp;
9009 XVECEXP (condexp, 0, 2 * insn_num + 1)
9010 = make_numeric_value (decl->decl.insn_reserv.insn_num);
9011 insn_num++;
9012 }
9013 }
9014 if (description->insns_num != insn_num + 1)
9015 abort ();
9016 make_internal_attr
9017 (attr_printf (sizeof ("*")
9018 + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1,
9019 "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME),
9020 condexp, 0);
9021}
9022
9023\f
9024
9025/* The following function creates attribute which order number of insn
9026 in pipeline hazard description translator. */
9027static void
9028make_default_insn_latency_attr ()
9029{
9030 int i, insn_num;
9031 decl_t decl;
9032 rtx condexp;
9033
9034 condexp = rtx_alloc (COND);
9035 XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2);
9036 XEXP (condexp, 1) = make_numeric_value (0);
9037 for (i = insn_num = 0; i < description->decls_num; i++)
9038 {
9039 decl = description->decls [i];
9040 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
9041 {
9042 XVECEXP (condexp, 0, 2 * insn_num) = decl->decl.insn_reserv.condexp;
9043 XVECEXP (condexp, 0, 2 * insn_num + 1)
9044 = make_numeric_value (decl->decl.insn_reserv.default_latency);
9045 insn_num++;
9046 }
9047 }
9048 if (description->insns_num != insn_num + 1)
9049 abort ();
9050 make_internal_attr (attr_printf (sizeof ("*")
9051 + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME)
9052 + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME),
9053 condexp, 0);
9054}
9055
9056\f
9057
9058/* The following function creates attribute which returns 1 if given
9059 output insn has bypassing and 0 otherwise. */
9060static void
9061make_bypass_attr ()
9062{
9063 int i, bypass_insn;
9064 int bypass_insns_num = 0;
9065 decl_t decl;
9066 rtx result_rtx;
9067
9068 for (i = 0; i < description->decls_num; i++)
9069 {
9070 decl = description->decls [i];
9071 if (decl->mode == dm_insn_reserv
9072 && decl->decl.insn_reserv.condexp != NULL
9073 && decl->decl.insn_reserv.bypass_list != NULL)
9074 bypass_insns_num++;
9075 }
9076 if (bypass_insns_num == 0)
9077 result_rtx = make_numeric_value (0);
9078 else
9079 {
9080 result_rtx = rtx_alloc (COND);
9081 XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2);
9082 XEXP (result_rtx, 1) = make_numeric_value (0);
9083
9084 for (i = bypass_insn = 0; i < description->decls_num; i++)
9085 {
9086 decl = description->decls [i];
9087 if (decl->mode == dm_insn_reserv
9088 && decl->decl.insn_reserv.condexp != NULL
9089 && decl->decl.insn_reserv.bypass_list != NULL)
9090 {
9091 XVECEXP (result_rtx, 0, 2 * bypass_insn)
9092 = decl->decl.insn_reserv.condexp;
9093 XVECEXP (result_rtx, 0, 2 * bypass_insn + 1)
9094 = make_numeric_value (1);
9095 bypass_insn++;
9096 }
9097 }
9098 }
9099 make_internal_attr (attr_printf (sizeof ("*")
9100 + strlen (BYPASS_P_FUNC_NAME) + 1,
9101 "*%s", BYPASS_P_FUNC_NAME),
9102 result_rtx, 0);
9103}
9104
9105\f
9106
9107/* This page mainly contains top level functions of pipeline hazards
9108 description translator. */
9109
9110/* The following macro value is suffix of name of description file of
9111 pipeline hazards description translator. */
9112#define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9113
9114/* The function returns suffix of given file name. The returned
9115 string can not be changed. */
9116static const char *
9117file_name_suffix (file_name)
9118 const char *file_name;
9119{
9120 const char *last_period;
9121
9122 for (last_period = NULL; *file_name != '\0'; file_name++)
9123 if (*file_name == '.')
9124 last_period = file_name;
9125 return (last_period == NULL ? file_name : last_period);
9126}
9127
9128/* The function returns base name of given file name, i.e. pointer to
9129 first char after last `/' (or `\' for WIN32) in given file name,
9130 given file name itself if the directory name is absent. The
9131 returned string can not be changed. */
9132static const char *
9133base_file_name (file_name)
9134 const char *file_name;
9135{
9136 int directory_name_length;
9137
9138 directory_name_length = strlen (file_name);
9139#ifdef WIN32
9140 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9141 && file_name[directory_name_length] != '\\')
9142#else
9143 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9144#endif
9145 directory_name_length--;
9146 return file_name + directory_name_length + 1;
9147}
9148
9149/* The following is top level function to initialize the work of
9150 pipeline hazards description translator. */
9151void
9152initiate_automaton_gen (argc, argv)
9153 int argc;
9154 char **argv;
9155{
9156 const char *base_name;
9157 int i;
9158
9159 ndfa_flag = 0;
9160 split_argument = 0; /* default value */
9161 no_minimization_flag = 0;
9162 time_flag = 0;
9163 v_flag = 0;
9164 w_flag = 0;
9165 for (i = 2; i < argc; i++)
9166 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9167 no_minimization_flag = 1;
e3c8eb86 9168 else if (strcmp (argv [i], TIME_OPTION) == 0)
fae15c93 9169 time_flag = 1;
e3c8eb86 9170 else if (strcmp (argv [i], V_OPTION) == 0)
fae15c93
VM
9171 v_flag = 1;
9172 else if (strcmp (argv [i], W_OPTION) == 0)
9173 w_flag = 1;
9174 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9175 ndfa_flag = 1;
9176 else if (strcmp (argv [i], "-split") == 0)
9177 {
9178 if (i + 1 >= argc)
9179 fatal ("-split has no argument.");
9180 fatal ("option `-split' has not been implemented yet\n");
9181 /* split_argument = atoi (argument_vect [i + 1]); */
9182 }
9183 VLA_PTR_CREATE (decls, 150, "decls");
9184 /* Initialize IR storage. */
9185 obstack_init (&irp);
9186 initiate_automaton_decl_table ();
9187 initiate_insn_decl_table ();
9188 initiate_decl_table ();
9189 output_file = stdout;
9190 output_description_file = NULL;
9191 base_name = base_file_name (argv[1]);
9192 obstack_grow (&irp, base_name,
9193 strlen (base_name) - strlen (file_name_suffix (base_name)));
9194 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9195 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9196 obstack_1grow (&irp, '\0');
9197 output_description_file_name = obstack_base (&irp);
9198 obstack_finish (&irp);
9199}
9200
9201/* The following function checks existence at least one arc marked by
9202 each insn. */
9203static void
deb09eff 9204check_automata_insn_issues ()
fae15c93
VM
9205{
9206 automaton_t automaton;
9207 ainsn_t ainsn, reserv_ainsn;
9208
9209 for (automaton = description->first_automaton;
9210 automaton != NULL;
9211 automaton = automaton->next_automaton)
9212 {
9213 for (ainsn = automaton->ainsn_list;
9214 ainsn != NULL;
9215 ainsn = ainsn->next_ainsn)
9216 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9217 {
9218 for (reserv_ainsn = ainsn;
9219 reserv_ainsn != NULL;
9220 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9221 if (automaton->corresponding_automaton_decl != NULL)
9222 {
9223 if (!w_flag)
9224 error ("Automaton `%s': Insn `%s' will never be issued",
9225 automaton->corresponding_automaton_decl->name,
9226 reserv_ainsn->insn_reserv_decl->name);
9227 else
9228 warning
9229 ("Automaton `%s': Insn `%s' will never be issued",
9230 automaton->corresponding_automaton_decl->name,
9231 reserv_ainsn->insn_reserv_decl->name);
9232 }
9233 else
9234 {
9235 if (!w_flag)
9236 error ("Insn `%s' will never be issued",
9237 reserv_ainsn->insn_reserv_decl->name);
9238 else
9239 warning ("Insn `%s' will never be issued",
9240 reserv_ainsn->insn_reserv_decl->name);
9241 }
9242 }
9243 }
9244}
9245
9246/* The following vla is used for storing pointers to all achieved
9247 states. */
9248static vla_ptr_t automaton_states;
9249
9250/* This function is called by function pass_states to add an achieved
9251 STATE. */
9252static void
9253add_automaton_state (state)
9254 state_t state;
9255{
9256 VLA_PTR_ADD (automaton_states, state);
9257}
9258
9259/* The following function forms list of important automata (whose
9260 states may be changed after the insn issue) for each insn. */
9261static void
9262form_important_insn_automata_lists ()
9263{
9264 automaton_t automaton;
9265 state_t *state_ptr;
9266 decl_t decl;
9267 ainsn_t ainsn;
9268 arc_t arc;
9269 int i;
9270
9271 VLA_PTR_CREATE (automaton_states, 1500,
9272 "automaton states for forming important insn automata sets");
deb09eff 9273 /* Mark important ainsns. */
fae15c93
VM
9274 for (automaton = description->first_automaton;
9275 automaton != NULL;
9276 automaton = automaton->next_automaton)
9277 {
9278 VLA_PTR_NULLIFY (automaton_states);
9279 pass_states (automaton, add_automaton_state);
9280 for (state_ptr = VLA_PTR_BEGIN (automaton_states);
9281 state_ptr <= (state_t *) VLA_PTR_LAST (automaton_states);
9282 state_ptr++)
9283 {
9284 for (arc = first_out_arc (*state_ptr);
9285 arc != NULL;
9286 arc = next_out_arc (arc))
9287 if (arc->to_state != *state_ptr)
9288 {
9289 if (!arc->insn->first_insn_with_same_reservs)
9290 abort ();
9291 for (ainsn = arc->insn;
9292 ainsn != NULL;
9293 ainsn = ainsn->next_same_reservs_insn)
9294 ainsn->important_p = TRUE;
9295 }
9296 }
9297 }
9298 VLA_PTR_DELETE (automaton_states);
deb09eff 9299 /* Create automata sets for the insns. */
fae15c93
VM
9300 for (i = 0; i < description->decls_num; i++)
9301 {
9302 decl = description->decls [i];
9303 if (decl->mode == dm_insn_reserv)
9304 {
9305 automata_list_start ();
9306 for (automaton = description->first_automaton;
9307 automaton != NULL;
9308 automaton = automaton->next_automaton)
9309 for (ainsn = automaton->ainsn_list;
9310 ainsn != NULL;
9311 ainsn = ainsn->next_ainsn)
9312 if (ainsn->important_p
9313 && ainsn->insn_reserv_decl == &decl->decl.insn_reserv)
9314 {
9315 automata_list_add (automaton);
9316 break;
9317 }
9318 decl->decl.insn_reserv.important_automata_list
9319 = automata_list_finish ();
9320 }
9321 }
9322}
9323
9324
9325/* The following is top level function to generate automat(a,on) for
9326 fast recognition of pipeline hazards. */
9327void
9328expand_automata ()
9329{
9330 int i;
9331
9332 description = create_node (sizeof (struct description)
9333 /* One entry for cycle advancing insn. */
9334 + sizeof (decl_t) * VLA_PTR_LENGTH (decls));
9335 description->decls_num = VLA_PTR_LENGTH (decls);
9336 description->query_units_num = 0;
9337 for (i = 0; i < description->decls_num; i++)
9338 {
9339 description->decls [i] = VLA_PTR (decls, i);
9340 if (description->decls [i]->mode == dm_unit
9341 && description->decls [i]->decl.unit.query_p)
9342 description->decls [i]->decl.unit.query_num
9343 = description->query_units_num++;
9344 }
9345 all_time = create_ticker ();
9346 check_time = create_ticker ();
9347 fprintf (stderr, "Check description...");
9348 fflush (stderr);
9349 check_all_description ();
9350 fprintf (stderr, "done\n");
9351 ticker_off (&check_time);
9352 generation_time = create_ticker ();
deb09eff
VM
9353 if (!have_error)
9354 {
9355 transform_insn_regexps ();
9356 check_unit_distributions_to_automata ();
9357 }
fae15c93
VM
9358 if (!have_error)
9359 {
9360 generate ();
deb09eff
VM
9361 check_automata_insn_issues ();
9362 }
9363 if (!have_error)
9364 {
9365 form_important_insn_automata_lists ();
9366 fprintf (stderr, "Generation of attributes...");
9367 fflush (stderr);
9368 make_internal_dfa_insn_code_attr ();
9369 make_insn_alts_attr ();
9370 make_default_insn_latency_attr ();
9371 make_bypass_attr ();
9372 fprintf (stderr, "done\n");
fae15c93
VM
9373 }
9374 ticker_off (&generation_time);
9375 ticker_off (&all_time);
9376 fprintf (stderr, "All other genattrtab stuff...");
9377 fflush (stderr);
9378}
9379
9380/* The following is top level function to output PHR and to finish
9381 work with pipeline description translator. */
9382void
9383write_automata ()
9384{
9385 fprintf (stderr, "done\n");
9386 if (have_error)
9387 fatal ("Errors in DFA description");
9388 ticker_on (&all_time);
9389 output_time = create_ticker ();
9390 fprintf (stderr, "Forming and outputing automata tables...");
9391 fflush (stderr);
9392 output_dfa_max_issue_rate ();
9393 output_tables ();
9394 fprintf (stderr, "done\n");
9395 fprintf (stderr, "Output functions to work with automata...");
9396 fflush (stderr);
9397 output_chip_definitions ();
9398 output_max_insn_queue_index_def ();
9399 output_internal_min_issue_delay_func ();
9400 output_internal_trans_func ();
9401 /* Cache of insn dfa codes: */
9402 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9403 fprintf (output_file, "\nstatic int %s;\n\n",
9404 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9405 output_dfa_insn_code_func ();
9406 output_trans_func ();
9407 fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME);
9408 output_internal_state_alts_func ();
9409 output_state_alts_func ();
9410 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9411 AUTOMATON_STATE_ALTS_MACRO_NAME);
9412 output_min_issue_delay_func ();
9413 output_internal_dead_lock_func ();
9414 output_dead_lock_func ();
9415 output_size_func ();
9416 output_internal_reset_func ();
9417 output_reset_func ();
9418 output_min_insn_conflict_delay_func ();
9419 output_internal_insn_latency_func ();
9420 output_insn_latency_func ();
9421 output_print_reservation_func ();
9422 if (no_minimization_flag)
9423 {
9424 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9425 output_get_cpu_unit_code_func ();
9426 output_cpu_unit_reservation_p ();
9427 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9428 CPU_UNITS_QUERY_MACRO_NAME);
9429 }
9430 output_dfa_start_func ();
9431 output_dfa_finish_func ();
9432 fprintf (stderr, "done\n");
9433 if (v_flag)
9434 {
9435 output_description_file = fopen (output_description_file_name, "w");
9436 if (output_description_file == NULL)
9437 {
9438 perror (output_description_file_name);
9439 exit (FATAL_EXIT_CODE);
9440 }
9441 fprintf (stderr, "Output automata description...");
9442 fflush (stderr);
9443 output_description ();
9444 output_automaton_descriptions ();
9445 fprintf (stderr, "done\n");
9446 output_statistics (output_description_file);
9447 }
9448 output_statistics (stderr);
9449 ticker_off (&output_time);
9450 output_time_statistics (stderr);
9451 finish_states ();
9452 finish_arcs ();
9453 finish_automata_lists ();
9454 if (time_flag)
9455 {
9456 fprintf (stderr, "Summary:\n");
9457 fprintf (stderr, " check time ");
9458 print_active_time (stderr, check_time);
9459 fprintf (stderr, ", generation time ");
9460 print_active_time (stderr, generation_time);
9461 fprintf (stderr, ", all time ");
9462 print_active_time (stderr, all_time);
9463 fprintf (stderr, "\n");
9464 }
9465 /* Finish all work. */
9466 if (output_description_file != NULL)
9467 {
9468 fflush (output_description_file);
9469 if (ferror (stdout) != 0)
9470 fatal ("Error in writing DFA description file %s",
9471 output_description_file_name);
9472 fclose (output_description_file);
9473 }
9474 finish_automaton_decl_table ();
9475 finish_insn_decl_table ();
9476 finish_decl_table ();
9477 obstack_free (&irp, NULL);
9478 if (have_error && output_description_file != NULL)
9479 remove (output_description_file_name);
9480}