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