diff options
author | vmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-08-30 20:44:51 +0000 |
---|---|---|
committer | vmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-08-30 20:44:51 +0000 |
commit | 17c7a04d1c73b837492a822490fa59ee17db094f (patch) | |
tree | 9cc1dc4a63e4c3af0ab3e68c017e773ea05dec6f /gcc/genautomata.c | |
parent | e025bbe7bf73c4adaa7edeec9158db8f8438295f (diff) | |
download | gcc-17c7a04d1c73b837492a822490fa59ee17db094f.tar.gz |
2001-08-30 Vladimir Makarov <vmakarov@redhat.com>
* rtl.def: Undo my patch commited 2001-08-27.
* genattrtab.c: Ditto.
* rtl.h: Ditto.
* sched-int.h: Ditto.
* target-def.h: Ditto.
* target.h: Ditto.
* haifa-sched.c: Ditto.
* sched-rgn.c: Ditto.
* sched-vis.c: Ditto.
* Makefile.in: Ditto.
* doc/md.texi: Ditto.
* doc/tm.texi: Ditto.
* doc/contrib.texi: Ditto.
* doc/gcc.texi: Ditto.
* genattrtab.h: Remove it.
* genautomata.c: Remove it.
* genattr.c: Undo my patch and Richard Henderson's patch commited
2001-08-27.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@45297 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/genautomata.c')
-rw-r--r-- | gcc/genautomata.c | 8767 |
1 files changed, 0 insertions, 8767 deletions
diff --git a/gcc/genautomata.c b/gcc/genautomata.c deleted file mode 100644 index 6da05ba5876..00000000000 --- a/gcc/genautomata.c +++ /dev/null @@ -1,8767 +0,0 @@ -/* Pipeline hazard description translator. - Copyright (C) 2000, 2001 Free Software Foundation, Inc. - - Written by Vladimir Makarov <vmakarov@redhat.com> - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. - -GNU CC is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ - -/* References: - - 1. Detecting pipeline structural hazards quickly. T. Proebsting, - C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on - Principles of Programming Languages, pages 280--286, 1994. - - This article is a good start point to understand usage of finite - state automata for pipeline hazard recognizers. But I'd - recommend the 2nd article for more deep understanding. - - 2. Efficient Instruction Scheduling Using Finite State Automata: - V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best - article about usage of finite state automata for pipeline hazard - recognizers. - - The current implementation is different from the 2nd article in the - following: - - 1. New operator `|' (alternative) is permitted in functional unit - reservation which can be treated deterministicly and - non-deterministicly. - - 2. Possibility of usage of nondeterministic automata too. - - 3. Possibility to query functional unit reservations for given - automaton state. - - 4. Several constructions to describe impossible reservations - (`exclusion_set', `presence_set', and `absence_set'). - - 5. No reverse automata are generated. Trace instruction scheduling - requires this. It can be easily added in the future if we - really need this. - - 6. Union of automaton states are not generated yet. It is planned - to be implemented. Such feature is needed to make more accurate - interlock insn scheduling to get state describing functional - unit reservation in a joint CFG point. -*/ - -/* This file code processes constructions of machine description file - which describes automaton used for recognition of processor pipeline - hazards by insn scheduler and can be used for other tasks (such as - VLIW insn packing. - - The translator functions `gen_cpu_unit', `gen_query_cpu_unit', - `gen_bypass', `gen_excl_set', `gen_presence_set', - `gen_absence_set', `gen_automaton', `gen_automata_option', - `gen_reserv', `gen_insn_reserv' are called from file - `genattrtab.c'. They transform RTL constructions describing - automata in .md file into internal representation convenient for - further processing. - - The translator major function `expand_automata' processes the - description internal representation into finite state automaton. - It can be divided on: - - o checking correctness of the automaton pipeline description - (major function is `check_all_description'). - - o generating automaton (automata) from the description (major - function is `make_automaton'). - - o optional transformation of nondeterministic finite state - automata into deterministic ones if the alternative operator - `|' is treated nondeterministicly in the description (major - function is NDFA_to_DFA). - - o optional minimization of the finite state automata by merging - equivalent automaton states (major function is `minimize_DFA'). - - o forming tables (some as comb vectors) and attributes - representing the automata (functions output_..._table). - - Function `write_automata' outputs the created finite state - automaton as different tables and functions which works with the - automata to inquire automaton state and to change its state. These - function are used by gcc instruction scheduler and may be some - other gcc code. */ - -#include "hconfig.h" -#include "system.h" -#include "rtl.h" -#include "obstack.h" -#include "errors.h" - -#include <ctype.h> -#include <math.h> -#include "hashtab.h" -#include "varray.h" - -#ifdef HAVE_LIMITS_H -#include <limits.h> -#else -#ifndef CHAR_BIT -#define CHAR_BIT 8 -#endif -#endif - -#include "genattrtab.h" - -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free - -/* Positions in machine description file. Now they are not used. But - they could be used in the future for better diagnostic messages. */ -typedef int pos_t; - -/* The following is element of vector of current (and planned in the - future) functional unit reservations. */ -typedef unsigned HOST_WIDE_INT set_el_t; - -/* Reservations of function units are represented by value of the following - type. */ -typedef set_el_t *reserv_sets_t; - -/* The following structure represents variable length array (vla) of - pointers and HOST WIDE INTs. We could be use only varray. But we - add new lay because we add elements very frequently and this could - stress OS allocator when varray is used only. */ -typedef struct { - size_t length; /* current size of vla. */ - varray_type varray; /* container for vla. */ -} vla_ptr_t; - -typedef vla_ptr_t vla_hwint_t; - -/* The following structure describes a ticker. */ -struct ticker -{ - /* The following member value is time of the ticker creation with - taking into account time when the ticker is off. Active time of - the ticker is current time minus the value. */ - int modified_creation_time; - /* The following member value is time (incremented by one) when the - ticker was off. Zero value means that now the ticker is on. */ - int incremented_off_time; -}; - -/* The ticker is represented by the following type. */ -typedef struct ticker ticker_t; - -/* The following type describes elements of output vectors. */ -typedef HOST_WIDE_INT vect_el_t; - -/* Forward declaration of structures of internal representation of - pipeline description based on NDFA. */ - -struct unit_decl; -struct bypass_decl; -struct result_decl; -struct automaton_decl; -struct unit_rel_decl; -struct reserv_decl; -struct insn_reserv_decl; -struct decl; -struct unit_regexp; -struct result_regexp; -struct reserv_regexp; -struct nothing_regexp; -struct sequence_regexp; -struct repeat_regexp; -struct allof_regexp; -struct oneof_regexp; -struct regexp; -struct description; -struct unit_set_el; -struct state; -struct alt_state; -struct arc; -struct ainsn; -struct automaton; -struct state_ainsn_table; - -/* The following typedefs are for brevity. */ -typedef struct decl *decl_t; -typedef struct regexp *regexp_t; -typedef struct unit_set_el *unit_set_el_t; -typedef struct alt_state *alt_state_t; -typedef struct state *state_t; -typedef struct arc *arc_t; -typedef struct ainsn *ainsn_t; -typedef struct automaton *automaton_t; -typedef struct state_ainsn_table *state_ainsn_table_t; - - -/* Prototypes of functions gen_cpu_unit, gen_query_cpu_unit, - gen_bypass, gen_excl_set, gen_presence_set, gen_absence_set, - gen_automaton, gen_automata_option, gen_reserv, gen_insn_reserv, - initiate_automaton_gen, expand_automata, write_automata are - described on the file top because the functions are called from - function `main'. */ - -static void *create_node PARAMS ((size_t)); -static void *copy_node PARAMS ((void *, size_t)); -static char *check_name PARAMS ((char *, pos_t)); -static char *next_sep_el PARAMS ((char **, int, int)); -static int n_sep_els PARAMS ((char *, int, int)); -static char **get_str_vect PARAMS ((char *, int *, int, int)); -static regexp_t gen_regexp_el PARAMS ((char *)); -static regexp_t gen_regexp_repeat PARAMS ((char *)); -static regexp_t gen_regexp_allof PARAMS ((char *)); -static regexp_t gen_regexp_oneof PARAMS ((char *)); -static regexp_t gen_regexp_sequence PARAMS ((char *)); -static regexp_t gen_regexp PARAMS ((char *)); - -static unsigned string_hash PARAMS ((const char *)); -static unsigned automaton_decl_hash PARAMS ((const void *)); -static int automaton_decl_eq_p PARAMS ((const void *, - const void *)); -static decl_t insert_automaton_decl PARAMS ((decl_t)); -static decl_t find_automaton_decl PARAMS ((char *)); -static void initiate_automaton_decl_table PARAMS ((void)); -static void finish_automaton_decl_table PARAMS ((void)); - -static unsigned insn_decl_hash PARAMS ((const void *)); -static int insn_decl_eq_p PARAMS ((const void *, - const void *)); -static decl_t insert_insn_decl PARAMS ((decl_t)); -static decl_t find_insn_decl PARAMS ((char *)); -static void initiate_insn_decl_table PARAMS ((void)); -static void finish_insn_decl_table PARAMS ((void)); - -static unsigned decl_hash PARAMS ((const void *)); -static int decl_eq_p PARAMS ((const void *, - const void *)); -static decl_t insert_decl PARAMS ((decl_t)); -static decl_t find_decl PARAMS ((char *)); -static void initiate_decl_table PARAMS ((void)); -static void finish_decl_table PARAMS ((void)); - -static unit_set_el_t process_excls PARAMS ((char **, int, pos_t)); -static void add_excls PARAMS ((unit_set_el_t, unit_set_el_t, - pos_t)); -static unit_set_el_t process_presence_absence - PARAMS ((char **, int, pos_t, int)); -static void add_presence_absence PARAMS ((unit_set_el_t, unit_set_el_t, - pos_t, int)); -static void process_decls PARAMS ((void)); -static struct bypass_decl *find_bypass PARAMS ((struct bypass_decl *, - struct insn_reserv_decl *)); -static void check_automaton_usage PARAMS ((void)); -static regexp_t process_regexp PARAMS ((regexp_t)); -static void process_regexp_decls PARAMS ((void)); -static void check_usage PARAMS ((void)); -static int loop_in_regexp PARAMS ((regexp_t, decl_t)); -static void check_loops_in_regexps PARAMS ((void)); -static int process_regexp_cycles PARAMS ((regexp_t, int)); -static void evaluate_max_reserv_cycles PARAMS ((void)); -static void check_all_description PARAMS ((void)); - -static ticker_t create_ticker PARAMS ((void)); -static void ticker_off PARAMS ((ticker_t *)); -static void ticker_on PARAMS ((ticker_t *)); -static int active_time PARAMS ((ticker_t)); -static void print_active_time PARAMS ((FILE *, ticker_t)); - -static void add_advance_cycle_insn_decl PARAMS ((void)); - -static alt_state_t get_free_alt_state PARAMS ((void)); -static void free_alt_state PARAMS ((alt_state_t)); -static void free_alt_states PARAMS ((alt_state_t)); -static int alt_state_cmp PARAMS ((const void *alt_state_ptr_1, - const void *alt_state_ptr_2)); -static alt_state_t uniq_sort_alt_states PARAMS ((alt_state_t)); -static int alt_states_eq PARAMS ((alt_state_t, alt_state_t)); -static void initiate_alt_states PARAMS ((void)); -static void finish_alt_states PARAMS ((void)); - -static reserv_sets_t alloc_empty_reserv_sets PARAMS ((void)); -static unsigned reserv_sets_hash_value PARAMS ((reserv_sets_t)); -static int reserv_sets_cmp PARAMS ((reserv_sets_t, reserv_sets_t)); -static int reserv_sets_eq PARAMS ((reserv_sets_t, reserv_sets_t)); -static void set_unit_reserv PARAMS ((reserv_sets_t, int, int)); -static int test_unit_reserv PARAMS ((reserv_sets_t, int, int)); -static int it_is_empty_reserv_sets PARAMS ((reserv_sets_t)) - ATTRIBUTE_UNUSED; -static int reserv_sets_are_intersected PARAMS ((reserv_sets_t, reserv_sets_t)); -static void reserv_sets_shift PARAMS ((reserv_sets_t, reserv_sets_t)); -static void reserv_sets_or PARAMS ((reserv_sets_t, reserv_sets_t, - reserv_sets_t)); -static void reserv_sets_and PARAMS ((reserv_sets_t, reserv_sets_t, - reserv_sets_t)) - ATTRIBUTE_UNUSED; -static void output_cycle_reservs PARAMS ((FILE *, reserv_sets_t, - int, int)); -static void output_reserv_sets PARAMS ((FILE *, reserv_sets_t)); -static state_t get_free_state PARAMS ((int, automaton_t)); -static void free_state PARAMS ((state_t)); -static unsigned state_hash PARAMS ((const void *)); -static int state_eq_p PARAMS ((const void *, const void *)); -static state_t insert_state PARAMS ((state_t)); -static void set_state_reserv PARAMS ((state_t, int, int)); -static int intersected_state_reservs_p PARAMS ((state_t, state_t)); -static state_t states_union PARAMS ((state_t, state_t)); -static state_t state_shift PARAMS ((state_t)); -static void initiate_states PARAMS ((void)); -static void finish_states PARAMS ((void)); - -static void free_arc PARAMS ((arc_t)); -static void remove_arc PARAMS ((state_t, arc_t)); -static arc_t find_arc PARAMS ((state_t, state_t, ainsn_t)); -static arc_t add_arc PARAMS ((state_t, state_t, ainsn_t, int)); -static arc_t first_out_arc PARAMS ((state_t)); -static arc_t next_out_arc PARAMS ((arc_t)); -static void initiate_arcs PARAMS ((void)); -static void finish_arcs PARAMS ((void)); - -static void initiate_excl_sets PARAMS ((void)); -static reserv_sets_t get_excl_set PARAMS ((reserv_sets_t)); - -static void initiate_presence_absence_sets PARAMS ((void)); -static reserv_sets_t get_presence_absence_set PARAMS ((reserv_sets_t, int)); - -static regexp_t copy_insn_regexp PARAMS ((regexp_t)); -static regexp_t transform_1 PARAMS ((regexp_t)); -static regexp_t transform_2 PARAMS ((regexp_t)); -static regexp_t transform_3 PARAMS ((regexp_t)); -static regexp_t regexp_transform_func - PARAMS ((regexp_t, regexp_t (*) (regexp_t))); -static regexp_t transform_regexp PARAMS ((regexp_t)); -static void transform_insn_regexps PARAMS ((void)); - -static int process_seq_for_forming_states PARAMS ((regexp_t, automaton_t, - int)); -static void finish_forming_alt_state PARAMS ((alt_state_t, - automaton_t)); -static void process_alts_for_forming_states PARAMS ((regexp_t, - automaton_t, int)); -static void create_alt_states PARAMS ((automaton_t)); - -static void form_ainsn_with_same_reservs PARAMS ((automaton_t)); - -static void make_automaton PARAMS ((automaton_t)); -static void form_arcs_marked_by_insn PARAMS ((state_t)); -static void create_composed_state PARAMS ((state_t, arc_t, vla_ptr_t *)); -static void NDFA_to_DFA PARAMS ((automaton_t)); -static void pass_state_graph PARAMS ((state_t, void (*) (state_t))); -static void pass_states PARAMS ((automaton_t, - void (*) (state_t))); -static void initiate_pass_states PARAMS ((void)); -static void add_achieved_state PARAMS ((state_t)); -static int set_out_arc_insns_equiv_num PARAMS ((state_t, int)); -static void clear_arc_insns_equiv_num PARAMS ((state_t)); -static void copy_equiv_class PARAMS ((vla_ptr_t *to, - const vla_ptr_t *from)); -static int state_is_differed PARAMS ((state_t, int, int)); -static state_t init_equiv_class PARAMS ((state_t *states, int)); -static int partition_equiv_class PARAMS ((state_t *, int, - vla_ptr_t *, int *)); -static void evaluate_equiv_classes PARAMS ((automaton_t, vla_ptr_t *)); -static void merge_states PARAMS ((automaton_t, vla_ptr_t *)); -static void set_new_cycle_flags PARAMS ((state_t)); -static void minimize_DFA PARAMS ((automaton_t)); -static void incr_states_and_arcs_nums PARAMS ((state_t)); -static void count_states_and_arcs PARAMS ((automaton_t, int *, int *)); -static void build_automaton PARAMS ((automaton_t)); - -static void set_order_state_num PARAMS ((state_t)); -static void enumerate_states PARAMS ((automaton_t)); - -static ainsn_t insert_ainsn_into_equiv_class PARAMS ((ainsn_t, ainsn_t)); -static void delete_ainsn_from_equiv_class PARAMS ((ainsn_t)); -static void process_insn_equiv_class PARAMS ((ainsn_t, arc_t *)); -static void process_state_for_insn_equiv_partition PARAMS ((state_t)); -static void set_insn_equiv_classes PARAMS ((automaton_t)); - -static double estimate_one_automaton_bound PARAMS ((void)); -static int compare_max_occ_cycle_nums PARAMS ((const void *, - const void *)); -static void units_to_automata_heuristic_distr PARAMS ((void)); -static ainsn_t create_ainsns PARAMS ((void)); -static void units_to_automata_distr PARAMS ((void)); -static void create_automata PARAMS ((void)); - -static void form_regexp PARAMS ((regexp_t)); -static const char *regexp_representation PARAMS ((regexp_t)); -static void finish_regexp_representation PARAMS ((void)); - -static void output_range_type PARAMS ((FILE *, long int, long int)); -static int longest_path_length PARAMS ((state_t)); -static void process_state_longest_path_length PARAMS ((state_t)); -static void output_dfa_max_issue_rate PARAMS ((void)); -static void output_vect PARAMS ((vect_el_t *, int)); -static void output_chip_member_name PARAMS ((FILE *, automaton_t)); -static void output_temp_chip_member_name PARAMS ((FILE *, automaton_t)); -static void output_translate_vect_name PARAMS ((FILE *, automaton_t)); -static void output_trans_full_vect_name PARAMS ((FILE *, automaton_t)); -static void output_trans_comb_vect_name PARAMS ((FILE *, automaton_t)); -static void output_trans_check_vect_name PARAMS ((FILE *, automaton_t)); -static void output_trans_base_vect_name PARAMS ((FILE *, automaton_t)); -static void output_state_alts_full_vect_name PARAMS ((FILE *, automaton_t)); -static void output_state_alts_comb_vect_name PARAMS ((FILE *, automaton_t)); -static void output_state_alts_check_vect_name PARAMS ((FILE *, automaton_t)); -static void output_state_alts_base_vect_name PARAMS ((FILE *, automaton_t)); -static void output_min_issue_delay_vect_name PARAMS ((FILE *, automaton_t)); -static void output_dead_lock_vect_name PARAMS ((FILE *, automaton_t)); -static void output_reserved_units_table_name PARAMS ((FILE *, automaton_t)); -static void output_state_member_type PARAMS ((FILE *, automaton_t)); -static void output_chip_definitions PARAMS ((void)); -static void output_translate_vect PARAMS ((automaton_t)); -static int comb_vect_p PARAMS ((state_ainsn_table_t)); -static state_ainsn_table_t create_state_ainsn_table PARAMS ((automaton_t)); -static void output_state_ainsn_table - PARAMS ((state_ainsn_table_t, char *, void (*) (FILE *, automaton_t), - void (*) (FILE *, automaton_t), void (*) (FILE *, automaton_t), - void (*) (FILE *, automaton_t))); -static void add_vect PARAMS ((state_ainsn_table_t, - int, vect_el_t *, int)); -static int out_state_arcs_num PARAMS ((state_t)); -static int compare_transition_els_num PARAMS ((const void *, const void *)); -static void add_vect_el PARAMS ((vla_hwint_t *, - ainsn_t, int)); -static void add_states_vect_el PARAMS ((state_t)); -static void output_trans_table PARAMS ((automaton_t)); -static void output_state_alts_table PARAMS ((automaton_t)); -static void min_issue_delay_pass_states PARAMS ((state_t, ainsn_t)); -static int min_issue_delay PARAMS ((state_t, ainsn_t)); -static void initiate_min_issue_delay_pass_states PARAMS ((void)); -static void output_min_issue_delay_table PARAMS ((automaton_t)); -static void output_dead_lock_vect PARAMS ((automaton_t)); -static void output_reserved_units_table PARAMS ((automaton_t)); -static void output_tables PARAMS ((void)); -static void output_max_insn_queue_index_def PARAMS ((void)); -static void output_internal_min_issue_delay_func PARAMS ((void)); -static void output_internal_trans_func PARAMS ((void)); -static void output_internal_insn_code_evaluation PARAMS ((const char *, - const char *, int)); -static void output_dfa_insn_code_func PARAMS ((void)); -static void output_trans_func PARAMS ((void)); -static void output_internal_state_alts_func PARAMS ((void)); -static void output_state_alts_func PARAMS ((void)); -static void output_min_issue_delay_func PARAMS ((void)); -static void output_internal_dead_lock_func PARAMS ((void)); -static void output_dead_lock_func PARAMS ((void)); -static void output_internal_reset_func PARAMS ((void)); -static void output_size_func PARAMS ((void)); -static void output_reset_func PARAMS ((void)); -static void output_min_insn_conflict_delay_func PARAMS ((void)); -static void output_internal_insn_latency_func PARAMS ((void)); -static void output_insn_latency_func PARAMS ((void)); -static void output_print_reservation_func PARAMS ((void)); -static int units_cmp PARAMS ((const void *, - const void *)); -static void output_get_cpu_unit_code_func PARAMS ((void)); -static void output_cpu_unit_reservation_p PARAMS ((void)); -static void output_dfa_start_func PARAMS ((void)); -static void output_dfa_finish_func PARAMS ((void)); - -static void output_regexp PARAMS ((regexp_t )); -static void output_unit_set_el_list PARAMS ((unit_set_el_t)); -static void output_description PARAMS ((void)); -static void output_automaton_name PARAMS ((FILE *, automaton_t)); -static void output_automaton_units PARAMS ((automaton_t)); -static void add_state_reservs PARAMS ((state_t)); -static void output_state_arcs PARAMS ((state_t)); -static int state_reservs_cmp PARAMS ((const void *, - const void *)); -static void remove_state_duplicate_reservs PARAMS ((void)); -static void output_state PARAMS ((state_t)); -static void output_automaton_descriptions PARAMS ((void)); -static void output_statistics PARAMS ((FILE *)); -static void output_time_statistics PARAMS ((FILE *)); -static void generate PARAMS ((void)); - -static void make_insn_alts_attr PARAMS ((void)); -static void make_internal_dfa_insn_code_attr PARAMS ((void)); -static void make_default_insn_latency_attr PARAMS ((void)); -static void make_bypass_attr PARAMS ((void)); -static const char *file_name_suffix PARAMS ((const char *)); -static const char *base_file_name PARAMS ((const char *)); -static void check_automata PARAMS ((void)); - -/* Undefined position. */ -static pos_t no_pos = 0; - -/* All IR is stored in the following obstack. */ -static struct obstack irp; - - - -/* This page contains code for work with variable length array (vla) - of pointers. We could be use only varray. But we add new lay - because we add elements very frequently and this could stress OS - allocator when varray is used only. */ - -/* Start work with vla. */ -#define VLA_PTR_CREATE(vla, allocated_length, name) \ - do \ - { \ - vla_ptr_t *vla_ptr = &(vla); \ - \ - VARRAY_GENERIC_PTR_INIT (vla_ptr->varray, allocated_length, name);\ - vla_ptr->length = 0; \ - } \ - while (0) - -/* Finish work with the vla. */ -#define VLA_PTR_DELETE(vla) VARRAY_FREE ((vla).varray) - -/* Return start address of the vla. */ -#define VLA_PTR_BEGIN(vla) ((void *) &VARRAY_GENERIC_PTR ((vla).varray, 0)) - -/* Address of the last element of the vla. Do not use side effects in - the macro argument. */ -#define VLA_PTR_LAST(vla) (&VARRAY_GENERIC_PTR ((vla).varray, \ - (vla).length - 1)) -/* Nullify the vla. */ -#define VLA_PTR_NULLIFY(vla) ((vla).length = 0) - -/* Shorten the vla on given number bytes. */ -#define VLA_PTR_SHORTEN(vla, n) ((vla).length -= (n)) - -/* Expand the vla on N elements. The values of new elements are - undefined. */ -#define VLA_PTR_EXPAND(vla, n) \ - do { \ - vla_ptr_t *expand_vla_ptr = &(vla); \ - size_t new_length = (n) + expand_vla_ptr->length; \ - \ - if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \ - VARRAY_GROW (expand_vla_ptr->varray, \ - (new_length - expand_vla_ptr->length < 128 \ - ? expand_vla_ptr->length + 128 : new_length)); \ - expand_vla_ptr->length = new_length; \ - } while (0) - -/* Add element to the end of the vla. */ -#define VLA_PTR_ADD(vla, ptr) \ - do { \ - vla_ptr_t *vla_ptr = &(vla); \ - \ - VLA_PTR_EXPAND (*vla_ptr, 1); \ - VARRAY_GENERIC_PTR (vla_ptr->varray, vla_ptr->length - 1) = (ptr);\ - } while (0) - -/* Length of the vla in elements. */ -#define VLA_PTR_LENGTH(vla) ((vla).length) - -/* N-th element of the vla. */ -#define VLA_PTR(vla, n) VARRAY_GENERIC_PTR ((vla).varray, n) - - -/* The following macros are analogous to the previous ones but for - VLAs of HOST WIDE INTs. */ - -#define VLA_HWINT_CREATE(vla, allocated_length, name) \ - do { \ - vla_hwint_t *vla_ptr = &(vla); \ - \ - VARRAY_WIDE_INT_INIT (vla_ptr->varray, allocated_length, name); \ - vla_ptr->length = 0; \ - } while (0) - -#define VLA_HWINT_DELETE(vla) VARRAY_FREE ((vla).varray) - -#define VLA_HWINT_BEGIN(vla) (&VARRAY_WIDE_INT ((vla).varray, 0)) - -/* Do not use side effects in the macro argument. */ -#define VLA_HWINT_LAST(vla) (&VARRAY_WIDE_INT ((vla).varray, \ - (vla).length - 1)) - -#define VLA_HWINT_NULLIFY(vla) ((vla).length = 0) - -#define VLA_HWINT_SHORTEN(vla, n) ((vla).length -= (n)) - -#define VLA_HWINT_EXPAND(vla, n) \ - do { \ - vla_hwint_t *expand_vla_ptr = &(vla); \ - size_t new_length = (n) + expand_vla_ptr->length; \ - \ - if (VARRAY_SIZE (expand_vla_ptr->varray) < new_length) \ - VARRAY_GROW (expand_vla_ptr->varray, \ - (new_length - expand_vla_ptr->length < 128 \ - ? expand_vla_ptr->length + 128 : new_length)); \ - expand_vla_ptr->length = new_length; \ - } while (0) - -#define VLA_HWINT_ADD(vla, ptr) \ - do { \ - vla_hwint_t *vla_ptr = &(vla); \ - \ - VLA_HWINT_EXPAND (*vla_ptr, 1); \ - VARRAY_WIDE_INT (vla_ptr->varray, vla_ptr->length - 1) = (ptr); \ - } while (0) - -#define VLA_HWINT_LENGTH(vla) ((vla).length) - -#define VLA_HWINT(vla, n) VARRAY_WIDE_INT ((vla).varray, n) - - - -/* Options with the following names can be set up in automata_option - construction. Because the strings occur more one time we use the - macros. */ - -#define NO_MINIMIZATION_OPTION "-no-minimization" - -#define W_OPTION "-w" - -#define NDFA_OPTION "-ndfa" - -/* The following flags are set up by function `initiate_automaton_gen'. */ - -/* Make automata with nondeterministic reservation by insns (`-ndfa'). */ -static int ndfa_flag; - -/* Do not make minimization of DFA (`-no-minimization'). */ -static int no_minimization_flag; - -/* Value of this variable is number of automata being generated. The - actual number of automata may be less this value if there is not - sufficient number of units. This value is defined by argument of - option `-split' or by constructions automaton if the value is zero - (it is default value of the argument). */ -static int split_argument; - -/* Flag of output time statistics (`-time'). */ -static int time_flag; - -/* Flag of creation of description file which contains description of - result automaton and statistics information (`-v'). */ -static int v_flag; - -/* Flag of generating warning instead of error for non-critical errors - (`-w'). */ -static int w_flag; - - -/* Output file for pipeline hazard recognizer (PHR) being generated. - The value is NULL if the file is not defined. */ -static FILE *output_file; - -/* Description file of PHR. The value is NULL if the file is not - created. */ -static FILE *output_description_file; - -/* PHR description file name. */ -static char *output_description_file_name; - -/* Value of the following variable is node representing description - being processed. This is start point of IR. */ -static struct description *description; - - - -/* This page contains description of IR structure (nodes). */ - -enum decl_mode -{ - dm_unit, - dm_bypass, - dm_automaton, - dm_excl, - dm_presence, - dm_absence, - dm_reserv, - dm_insn_reserv -}; - -/* This describes define_cpu_unit and define_query_cpu_unit (see file - rtl.def). */ -struct unit_decl -{ - char *name; - /* NULL if the automaton name is absent. */ - char *automaton_name; - /* If the following value is not zero, the cpu unit reservation is - described in define_query_cpu_unit. */ - char query_p; - - /* The following fields are defined by checker. */ - - /* The following field value is nonzero if the unit is used in an - regexp. */ - char unit_is_used; - /* The following field value is order number (0, 1, ...) of given - unit. */ - int unit_num; - /* The following field value is corresponding declaration of - automaton which was given in description. If the field value is - NULL then automaton in the unit declaration was absent. */ - struct automaton_decl *automaton_decl; - /* The following field value is maximal cycle number (1, ...) on - which given unit occurs in insns. Zero value means that given - unit is not used in insns. */ - int max_occ_cycle_num; - /* The following list contains units which conflict with given - unit. */ - unit_set_el_t excl_list; - /* The following list contains units which are required to - reservation of given unit. */ - unit_set_el_t presence_list; - /* The following list contains units which should be not present in - reservation for given unit. */ - unit_set_el_t absence_list; - /* The following is used only when `query_p' has nonzero value. - This is query number for the unit. */ - int query_num; - - /* The following fields are defined by automaton generator. */ - - /* The following field value is number of the automaton to which - given unit belongs. */ - int corresponding_automaton_num; -}; - -/* This describes define_bypass (see file rtl.def). */ -struct bypass_decl -{ - int latency; - char *out_insn_name; - char *in_insn_name; - char *bypass_guard_name; - - /* The following fields are defined by checker. */ - - /* output and input insns of given bypass. */ - struct insn_reserv_decl *out_insn_reserv; - struct insn_reserv_decl *in_insn_reserv; - /* The next bypass for given output insn. */ - struct bypass_decl *next; -}; - -/* This describes define_automaton (see file rtl.def). */ -struct automaton_decl -{ - char *name; - - /* The following fields are defined by automaton generator. */ - - /* The following field value is nonzero if the automaton is used in - an regexp definition. */ - char automaton_is_used; - - /* The following fields are defined by checker. */ - - /* The following field value is the corresponding automaton. This - field is not NULL only if the automaton is present in unit - declarations and the automatic partition on automata is not - used. */ - automaton_t corresponding_automaton; -}; - -/* This describes unit relations: exclusion_set, presence_set, or - absence_set (see file rtl.def). */ -struct unit_rel_decl -{ - int names_num; - int first_list_length; - char *names [1]; -}; - -/* This describes define_reservation (see file rtl.def). */ -struct reserv_decl -{ - char *name; - regexp_t regexp; - - /* The following fields are defined by checker. */ - - /* The following field value is nonzero if the unit is used in an - regexp. */ - char reserv_is_used; - /* The following field is used to check up cycle in expression - definition. */ - int loop_pass_num; -}; - -/* This describes define_insn_reservartion (see file rtl.def). */ -struct insn_reserv_decl -{ - rtx condexp; - int default_latency; - regexp_t regexp; - char *name; - - /* The following fields are defined by checker. */ - - /* The following field value is order number (0, 1, ...) of given - insn. */ - int insn_num; - /* The following field value is list of bypasses in which given insn - is output insn. */ - struct bypass_decl *bypass_list; - - /* The following fields are defined by automaton generator. */ - - /* The following field is the insn regexp transformed that - the regexp has not optional regexp, repetition regexp, and an - reservation name (i.e. reservation identifiers are changed by the - corresponding regexp) and all alternations are the topest level - of the regexp. The value can be NULL only if it is special - insn `cycle advancing'. */ - regexp_t transformed_regexp; - /* The following field value is list of arcs marked given - insn. The field is used in transfromation NDFA -> DFA. */ - arc_t arcs_marked_by_insn; - /* The two following fields are used during minimization of a finite state - automaton. */ - /* The field value is number of equivalence class of state into - which arc marked by given insn enters from a state (fixed during - an automaton minimization). */ - int equiv_class_num; - /* The field value is state_alts of arc leaving a state (fixed - during an automaton minimization) and marked by given insn - enters. */ - int state_alts; -}; - -/* This contains a declaration mentioned above. */ -struct decl -{ - /* What node in the union? */ - enum decl_mode mode; - pos_t pos; - union - { - struct unit_decl unit; - struct bypass_decl bypass; - struct automaton_decl automaton; - struct unit_rel_decl excl; - struct unit_rel_decl presence; - struct unit_rel_decl absence; - struct reserv_decl reserv; - struct insn_reserv_decl insn_reserv; - } decl; -}; - -/* The following structures represent parsed reservation strings. */ -enum regexp_mode -{ - rm_unit, - rm_reserv, - rm_nothing, - rm_sequence, - rm_repeat, - rm_allof, - rm_oneof -}; - -/* Cpu unit in reservation. */ -struct unit_regexp -{ - char *name; - struct unit_decl *unit_decl; -}; - -/* Define_reservation in a reservation. */ -struct reserv_regexp -{ - char *name; - struct reserv_decl *reserv_decl; -}; - -/* Absence of reservation (represented by string `nothing'). */ -struct nothing_regexp -{ - /* This used to be empty but ISO C doesn't allow that. */ - char unused; -}; - -/* Representation of reservations separated by ',' (see file - rtl.def). */ -struct sequence_regexp -{ - int regexps_num; - regexp_t regexps [1]; -}; - -/* Representation of construction `repeat' (see file rtl.def). */ -struct repeat_regexp -{ - int repeat_num; - regexp_t regexp; -}; - -/* Representation of reservations separated by '+' (see file - rtl.def). */ -struct allof_regexp -{ - int regexps_num; - regexp_t regexps [1]; -}; - -/* Representation of reservations separated by '|' (see file - rtl.def). */ -struct oneof_regexp -{ - int regexps_num; - regexp_t regexps [1]; -}; - -/* Representation of a reservation string. */ -struct regexp -{ - /* What node in the union? */ - enum regexp_mode mode; - pos_t pos; - union - { - struct unit_regexp unit; - struct reserv_regexp reserv; - struct nothing_regexp nothing; - struct sequence_regexp sequence; - struct repeat_regexp repeat; - struct allof_regexp allof; - struct oneof_regexp oneof; - } regexp; -}; - -/* Reperesents description of pipeline hazard description based on - NDFA. */ -struct description -{ - int decls_num; - - /* The following fields are defined by checker. */ - - /* The following fields values are correspondingly number of all - units, query units, and insns in the description. */ - int units_num; - int query_units_num; - int insns_num; - /* The following field value is max length (in cycles) of - reservations of insns. The field value is defined only for - correct programs. */ - int max_insn_reserv_cycles; - - /* The following fields are defined by automaton generator. */ - - /* The following field value is the first automaton. */ - automaton_t first_automaton; - - /* The following field is created by pipeline hazard parser and - contains all declarations. We allocate additional entry for - special insn "cycle advancing" which is added by the automaton - generator. */ - decl_t decls [1]; -}; - - - -/* The following nodes are created in automaton checker. */ - -/* The following nodes represent exclusion, presence, absence set for - cpu units. Each element are accessed through only one excl_list, - presence_list, absence_list. */ -struct unit_set_el -{ - struct unit_decl *unit_decl; - unit_set_el_t next_unit_set_el; -}; - - - -/* The following nodes are created in automaton generator. */ - -/* The following node type describes state automaton. The state may - be deterministic or non-deterministic. Non-deterministic state has - several component states which represent alternative cpu units - reservations. The state also is used for describing a - deterministic reservation of automaton insn. */ -struct state -{ - /* The following member value is nonzero if there is a transition by - cycle advancing. */ - int new_cycle_p; - /* The following field is list of processor unit reservations on - each cycle. */ - reserv_sets_t reservs; - /* The following field is unique number of given state between other - states. */ - int unique_num; - /* The following field value is automaton to which given state - belongs. */ - automaton_t automaton; - /* The following field value is the first arc output from given - state. */ - arc_t first_out_arc; - /* The following field is used to form NDFA. */ - char it_was_placed_in_stack_for_NDFA_forming; - /* The following field is used to form DFA. */ - char it_was_placed_in_stack_for_DFA_forming; - /* The following field is used to transform NDFA to DFA. The field - value is not NULL if the state is a compound state. In this case - the value of field `unit_sets_list' is NULL. All states in the - list are in the hash table. The list is formed through field - `next_sorted_alt_state'. */ - alt_state_t component_states; - /* The following field is used for passing graph of states. */ - int pass_num; - /* The list of states belonging to one equivalence class is formed - with the aid of the following field. */ - state_t next_equiv_class_state; - /* The two following fields are used during minimization of a finite - state automaton. */ - int equiv_class_num_1, equiv_class_num_2; - /* The following field is used during minimization of a finite state - automaton. The field value is state corresponding to equivalence - class to which given state belongs. */ - state_t equiv_class_state; - /* The following field value is the order number of given state. - The states in final DFA is enumerated with the aid of the - following field. */ - int order_state_num; - /* This member is used for passing states for searching minimal - delay time. */ - int state_pass_num; - /* The following member is used to evaluate min issue delay of insn - for a state. */ - int min_insn_issue_delay; - /* The following member is used to evaluate max issue rate of the - processor. The value of the member is maximal length of the path - from given state no containing arcs marked by special insn `cycle - advancing'. */ - int longest_path_length; -}; - -/* The following macro is an initial value of member - `longest_path_length' of a state. */ -#define UNDEFINED_LONGEST_PATH_LENGTH -1 - -/* Automaton arc. */ -struct arc -{ - /* The following field refers for the state into which given arc - enters. */ - state_t to_state; - /* The following field describes that the insn issue (with cycle - advancing for special insn `cycle advancing' and without cycle - advancing for others) makes transition from given state to - another given state. */ - ainsn_t insn; - /* The following field value is the next arc output from the same - state. */ - arc_t next_out_arc; - /* List of arcs marked given insn is formed with the following - field. The field is used in transfromation NDFA -> DFA. */ - arc_t next_arc_marked_by_insn; - /* The following field is defined if NDFA_FLAG is zero. The member - value is number of alternative reservations which can be used for - transition for given state by given insn. */ - int state_alts; -}; - -/* The following node type describes a deterministic alternative in - non-deterministic state which characterizes cpu unit reservations - of automaton insn or which is part of NDFA. */ -struct alt_state -{ - /* The following field is a determinist state which characterizes - unit reservations of the instruction. */ - state_t state; - /* The following field refers to the next state which characterizes - unit reservations of the instruction. */ - alt_state_t next_alt_state; - /* The following field refers to the next state in sorted list. */ - alt_state_t next_sorted_alt_state; -}; - -/* The following node type describes insn of automaton. They are - labels of FA arcs. */ -struct ainsn -{ - /* The following field value is the corresponding insn declaration - of description. */ - struct insn_reserv_decl *insn_reserv_decl; - /* The following field value is the next insn declaration for an - automaton. */ - ainsn_t next_ainsn; - /* The following field is states which characterize automaton unit - reservations of the instruction. The value can be NULL only if it - is special insn `cycle advancing'. */ - alt_state_t alt_states; - /* The following field is sorted list of states which characterize - automaton unit reservations of the instruction. The value can be - NULL only if it is special insn `cycle advancing'. */ - alt_state_t sorted_alt_states; - /* The following field refers the next automaton insn with - the same reservations. */ - ainsn_t next_same_reservs_insn; - /* The following field is flag of the first automaton insn with the - same reservations in the declaration list. Only arcs marked such - insn is present in the automaton. This significantly decreases - memory requirements especially when several automata are - formed. */ - char first_insn_with_same_reservs; - /* The following member has nonzero value if there is arc from state of - the automaton marked by the ainsn. */ - char arc_exists_p; - /* Cyclic list of insns of a equivalence class is formed with the - aid of the following field. */ - ainsn_t next_equiv_class_insn; - /* The following field value is nonzero if the insn declaration is - the first insn declaration with given equivalence number. */ - char first_ainsn_with_given_equialence_num; - /* The following field is number of class of equivalence of insns. - It is necessary because many insns may be equivalent with the - point of view of pipeline hazards. */ - int insn_equiv_class_num; -}; - -/* The folowing describes an automaton for PHR. */ -struct automaton -{ - /* The following field value is the list of insn declarations for - given automaton. */ - ainsn_t ainsn_list; - /* The following field value is the corresponding automaton - declaration. This field is not NULL only if the automatic - partition on automata is not used. */ - struct automaton_decl *corresponding_automaton_decl; - /* The following field value is the next automaton. */ - automaton_t next_automaton; - /* The following field is start state of FA. There are not unit - reservations in the state. */ - state_t start_state; - /* The following field value is number of equivalence classes of - insns (see field `insn_equiv_class_num' in - `insn_reserv_decl'). */ - int insn_equiv_classes_num; - /* The following field value is number of states of final DFA. */ - int achieved_states_num; - /* The following field value is the order number (0, 1, ...) of - given automaton. */ - int automaton_order_num; - /* The following fields contain statistics information about - building automaton. */ - int NDFA_states_num, DFA_states_num; - /* The following field value is defined only if minimization of DFA - is used. */ - int minimal_DFA_states_num; - int NDFA_arcs_num, DFA_arcs_num; - /* The following field value is defined only if minimization of DFA - is used. */ - int minimal_DFA_arcs_num; - /* The following two members refer for two table state x ainsn -> - int. */ - state_ainsn_table_t trans_table; - state_ainsn_table_t state_alts_table; - /* The following member value is maximal value of min issue delay - for insns of the automaton. */ - int max_min_delay; - /* Usually min issue delay is small and we can place several (2, 4, - 8) elements in one vector element. So the compression factor can - be 1 (no compression), 2, 4, 8. */ - int min_issue_delay_table_compression_factor; -}; - -/* The following structure describes a table state X ainsn -> int(>= 0). */ -struct state_ainsn_table -{ - /* Automaton to which given table belongs. */ - automaton_t automaton; - /* The following tree vectors for comb vector implementation of the - table. */ - vla_hwint_t comb_vect; - vla_hwint_t check_vect; - vla_hwint_t base_vect; - /* This is simple implementation of the table. */ - vla_hwint_t full_vect; - /* Minimal and maximal values of the previous vectors. */ - int min_comb_vect_el_value, max_comb_vect_el_value; - int min_base_vect_el_value, max_base_vect_el_value; -}; - -/* Create IR structure (node). */ -static void * -create_node (size) - size_t size; -{ - void *result; - - obstack_blank (&irp, size); - result = obstack_base (&irp); - obstack_finish (&irp); - /* Default values of members are NULL and zero. */ - memset (result, 0, size); - return result; -} - -/* Copy IR structure (node). */ -static void * -copy_node (from, size) - void *from; - size_t size; -{ - void *result; - result = create_node (size); - memcpy (result, from, size); - return result; -} - -/* The function checks that NAME does not contain quotes (`"'). */ -static char * -check_name (name, pos) - char * name; - pos_t pos ATTRIBUTE_UNUSED; -{ - char *str; - - for (str = name; *str != '\0'; str++) - if (*str == '\"') - error ("Name `%s' contains quotes", name); - return name; -} - -/* Pointers top all declartions during IR generation are stored in the - following. */ -static vla_ptr_t decls; - -/* Given a pointer to a (char *) and a separator, return a alloc'ed - string containing the next separated element, taking parentheses - into account if PAR_FLAG has nonzero value. Advance the pointer to - after the string scanned, or the end-of-string. Return NULL if at - end of string. */ -static char * -next_sep_el (pstr, sep, par_flag) - char **pstr; - int sep; - int par_flag; -{ - char *out_str; - char *p; - int pars_num; - int n_spaces; - - /* Remove leading whitespaces. */ - while (isspace ((int) **pstr)) - (*pstr)++; - - if (**pstr == '\0') - return NULL; - - n_spaces = 0; - for (pars_num = 0, p = *pstr; *p != '\0'; p++) - { - if (par_flag && *p == '(') - pars_num++; - else if (par_flag && *p == ')') - pars_num--; - else if (pars_num == 0 && *p == sep) - break; - if (pars_num == 0 && isspace ((int) *p)) - n_spaces++; - else - { - for (; n_spaces != 0; n_spaces--) - obstack_1grow (&irp, p [-n_spaces]); - obstack_1grow (&irp, *p); - } - } - obstack_1grow (&irp, '\0'); - out_str = obstack_base (&irp); - obstack_finish (&irp); - - *pstr = p; - if (**pstr == sep) - (*pstr)++; - - return out_str; -} - -/* Given a string and a separator, return the number of separated - elements in it, taking parentheses into account if PAR_FLAG has - nonzero value. Return 0 for the null string, -1 if parantheses is - not balanced. */ -static int -n_sep_els (s, sep, par_flag) - char *s; - int sep; - int par_flag; -{ - int n; - int pars_num; - - if (*s == '\0') - return 0; - - for (pars_num = 0, n = 1; *s; s++) - if (par_flag && *s == '(') - pars_num++; - else if (par_flag && *s == ')') - pars_num--; - else if (pars_num == 0 && *s == sep) - n++; - - return (pars_num != 0 ? -1 : n); -} - -/* Given a string and a separator, return vector of strings which are - elements in the string and number of elements through els_num. - Take parentheses into account if PAR_FLAG has nonzero value. - Return 0 for the null string, -1 if parantheses are not balanced. */ -static char ** -get_str_vect (str, els_num, sep, par_flag) - char *str; - int *els_num; - int sep; - int par_flag; -{ - int i; - char **vect; - char **pstr; - - *els_num = n_sep_els (str, sep, par_flag); - if (*els_num <= 0) - return NULL; - obstack_blank (&irp, sizeof (char *) * (*els_num)); - vect = (char **) obstack_base (&irp); - obstack_finish (&irp); - pstr = &str; - for (i = 0; i < *els_num; i++) - vect [i] = next_sep_el (pstr, sep, par_flag); - if (next_sep_el (pstr, sep, par_flag) != NULL) - abort (); - return vect; -} - -/* Process a DEFINE_CPU_UNIT. - - This gives information about a unit contained in CPU. We fill a - struct unit_decl with information used later by `expand_automata'. */ -void -gen_cpu_unit (def) - rtx def; -{ - decl_t decl; - char **str_cpu_units; - int vect_length; - int i; - - str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0); - if (str_cpu_units == NULL) - fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0)); - for (i = 0; i < vect_length; i++) - { - decl = create_node (sizeof (struct decl)); - decl->mode = dm_unit; - decl->pos = 0; - decl->decl.unit.name = check_name (str_cpu_units [i], decl->pos); - decl->decl.unit.automaton_name = (char *) XSTR (def, 1); - decl->decl.unit.query_p = 0; - VLA_PTR_ADD (decls, decl); - num_dfa_decls++; - } -} - -/* Process a DEFINE_QUERY_CPU_UNIT. - - This gives information about a unit contained in CPU. We fill a - struct unit_decl with information used later by `expand_automata'. */ -void -gen_query_cpu_unit (def) - rtx def; -{ - decl_t decl; - char **str_cpu_units; - int vect_length; - int i; - - str_cpu_units = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0); - if (str_cpu_units == NULL) - fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0)); - for (i = 0; i < vect_length; i++) - { - decl = create_node (sizeof (struct decl)); - decl->mode = dm_unit; - decl->pos = 0; - decl->decl.unit.name = check_name (str_cpu_units [i], decl->pos); - decl->decl.unit.automaton_name = (char *) XSTR (def, 1); - decl->decl.unit.query_p = 1; - VLA_PTR_ADD (decls, decl); - num_dfa_decls++; - } -} - -/* Process a DEFINE_BYPASS. - - This gives information about a unit contained in the CPU. We fill - in a struct bypass_decl with information used later by - `expand_automata'. */ -void -gen_bypass (def) - rtx def; -{ - decl_t decl; - char **out_insns; - int out_length; - char **in_insns; - int in_length; - int i, j; - - out_insns = get_str_vect ((char *) XSTR (def, 1), &out_length, ',', 0); - if (out_insns == NULL) - fatal ("invalid string `%s' in define_bypass", XSTR (def, 1)); - in_insns = get_str_vect ((char *) XSTR (def, 2), &in_length, ',', 0); - if (in_insns == NULL) - fatal ("invalid string `%s' in define_bypass", XSTR (def, 2)); - for (i = 0; i < out_length; i++) - for (j = 0; j < in_length; j++) - { - decl = create_node (sizeof (struct decl)); - decl->mode = dm_bypass; - decl->pos = 0; - decl->decl.bypass.latency = XINT (def, 0); - decl->decl.bypass.out_insn_name = out_insns [i]; - decl->decl.bypass.in_insn_name = in_insns [j]; - decl->decl.bypass.bypass_guard_name = (char *) XSTR (def, 3); - VLA_PTR_ADD (decls, decl); - num_dfa_decls++; - } -} - -/* Process a EXCLUSION_SET. - - This gives information about a cpu unit conflicts. We fill a - struct unit_rel_decl (excl) with information used later by - `expand_automata'. */ -void -gen_excl_set (def) - rtx def; -{ - decl_t decl; - char **first_str_cpu_units; - char **second_str_cpu_units; - int first_vect_length; - int length; - int i; - - first_str_cpu_units - = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0); - if (first_str_cpu_units == NULL) - fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0)); - second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',', - 0); - if (second_str_cpu_units == NULL) - fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1)); - length += first_vect_length; - decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *)); - decl->mode = dm_excl; - decl->pos = 0; - decl->decl.excl.names_num = length; - decl->decl.excl.first_list_length = first_vect_length; - for (i = 0; i < length; i++) - if (i < first_vect_length) - decl->decl.excl.names [i] = first_str_cpu_units [i]; - else - decl->decl.excl.names [i] = second_str_cpu_units [i - first_vect_length]; - VLA_PTR_ADD (decls, decl); - num_dfa_decls++; -} - -/* Process a PRESENCE_SET. - - This gives information about a cpu unit reservation requirements. - We fill a struct unit_rel_decl (presence) with information used - later by `expand_automata'. */ -void -gen_presence_set (def) - rtx def; -{ - decl_t decl; - char **first_str_cpu_units; - char **second_str_cpu_units; - int first_vect_length; - int length; - int i; - - first_str_cpu_units - = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0); - if (first_str_cpu_units == NULL) - fatal ("invalid first string `%s' in presence_set", XSTR (def, 0)); - second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',', - 0); - if (second_str_cpu_units == NULL) - fatal ("invalid second string `%s' in presence_set", XSTR (def, 1)); - length += first_vect_length; - decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *)); - decl->mode = dm_presence; - decl->pos = 0; - decl->decl.presence.names_num = length; - decl->decl.presence.first_list_length = first_vect_length; - for (i = 0; i < length; i++) - if (i < first_vect_length) - decl->decl.presence.names [i] = first_str_cpu_units [i]; - else - decl->decl.presence.names [i] - = second_str_cpu_units [i - first_vect_length]; - VLA_PTR_ADD (decls, decl); - num_dfa_decls++; -} - -/* Process a ABSENCE_SET. - - This gives information about a cpu unit reservation requirements. - We fill a struct unit_rel_decl (absence) with information used - later by `expand_automata'. */ -void -gen_absence_set (def) - rtx def; -{ - decl_t decl; - char **first_str_cpu_units; - char **second_str_cpu_units; - int first_vect_length; - int length; - int i; - - first_str_cpu_units - = get_str_vect ((char *) XSTR (def, 0), &first_vect_length, ',', 0); - if (first_str_cpu_units == NULL) - fatal ("invalid first string `%s' in absence_set", XSTR (def, 0)); - second_str_cpu_units = get_str_vect ((char *) XSTR (def, 1), &length, ',', - 0); - if (second_str_cpu_units == NULL) - fatal ("invalid second string `%s' in absence_set", XSTR (def, 1)); - length += first_vect_length; - decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *)); - decl->mode = dm_absence; - decl->pos = 0; - decl->decl.absence.names_num = length; - decl->decl.absence.first_list_length = first_vect_length; - for (i = 0; i < length; i++) - if (i < first_vect_length) - decl->decl.absence.names [i] = first_str_cpu_units [i]; - else - decl->decl.absence.names [i] - = second_str_cpu_units [i - first_vect_length]; - VLA_PTR_ADD (decls, decl); - num_dfa_decls++; -} - -/* Process a DEFINE_AUTOMATON. - - This gives information about a finite state automaton used for - recognizing pipeline hazards. We fill a struct automaton_decl - with information used later by `expand_automata'. */ -void -gen_automaton (def) - rtx def; -{ - decl_t decl; - char **str_automata; - int vect_length; - int i; - - str_automata = get_str_vect ((char *) XSTR (def, 0), &vect_length, ',', 0); - if (str_automata == NULL) - fatal ("invalid string `%s' in define_automaton", XSTR (def, 0)); - for (i = 0; i < vect_length; i++) - { - decl = create_node (sizeof (struct decl)); - decl->mode = dm_automaton; - decl->pos = 0; - decl->decl.automaton.name = check_name (str_automata [i], decl->pos); - VLA_PTR_ADD (decls, decl); - num_dfa_decls++; - } -} - -/* Process a AUTOMATA_OPTION. - - This gives information how to generate finite state automaton used - for recognizing pipeline hazards. */ -void -gen_automata_option (def) - rtx def; -{ - if (strcmp ((char *) XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0) - no_minimization_flag = 1; - else if (strcmp ((char *) XSTR (def, 0), W_OPTION + 1) == 0) - w_flag = 1; - else if (strcmp ((char *) XSTR (def, 0), NDFA_OPTION + 1) == 0) - ndfa_flag = 1; - else - fatal ("invalid option `%s' in automata_option", XSTR (def, 0)); -} - -/* Name in reservation to denote absence reservation. */ -#define NOTHING_NAME "nothing" - -/* The following string contains original reservation string being - parsed. */ -static char *reserv_str; - -/* Parse an element in STR. */ -static regexp_t -gen_regexp_el (str) - char *str; -{ - regexp_t regexp; - int len; - - if (*str == '(') - { - len = strlen (str); - if (str [len - 1] != ')') - fatal ("garbage after ) in reservation `%s'", reserv_str); - str [len - 1] = '\0'; - regexp = gen_regexp_sequence (str + 1); - } - else if (strcmp (str, NOTHING_NAME) == 0) - { - regexp = create_node (sizeof (struct decl)); - regexp->mode = rm_nothing; - } - else - { - regexp = create_node (sizeof (struct decl)); - regexp->mode = rm_unit; - regexp->regexp.unit.name = str; - } - return regexp; -} - -/* Parse construction `repeat' in STR. */ -static regexp_t -gen_regexp_repeat (str) - char *str; -{ - regexp_t regexp; - regexp_t repeat; - char **repeat_vect; - int els_num; - int i; - - repeat_vect = get_str_vect (str, &els_num, '*', 1); - if (repeat_vect == NULL) - fatal ("invalid `%s' in reservation `%s'", str, reserv_str); - if (els_num > 1) - { - regexp = gen_regexp_el (repeat_vect [0]); - for (i = 1; i < els_num; i++) - { - repeat = create_node (sizeof (struct regexp)); - repeat->mode = rm_repeat; - repeat->regexp.repeat.regexp = regexp; - repeat->regexp.repeat.repeat_num = atoi (repeat_vect [i]); - if (repeat->regexp.repeat.repeat_num <= 1) - fatal ("repetition `%s' <= 1 in reservation `%s'", - str, reserv_str); - regexp = repeat; - } - return regexp; - } - else - return gen_regexp_el (str); -} - -/* Parse reservation STR which possibly contains separator '+'. */ -static regexp_t -gen_regexp_allof (str) - char *str; -{ - regexp_t allof; - char **allof_vect; - int els_num; - int i; - - allof_vect = get_str_vect (str, &els_num, '+', 1); - if (allof_vect == NULL) - fatal ("invalid `%s' in reservation `%s'", str, reserv_str); - if (els_num > 1) - { - allof = create_node (sizeof (struct regexp) - + sizeof (regexp_t) * (els_num - 1)); - allof->mode = rm_allof; - allof->regexp.allof.regexps_num = els_num; - for (i = 0; i < els_num; i++) - allof->regexp.allof.regexps [i] = gen_regexp_repeat (allof_vect [i]); - return allof; - } - else - return gen_regexp_repeat (str); -} - -/* Parse reservation STR which possibly contains separator '|'. */ -static regexp_t -gen_regexp_oneof (str) - char *str; -{ - regexp_t oneof; - char **oneof_vect; - int els_num; - int i; - - oneof_vect = get_str_vect (str, &els_num, '|', 1); - if (oneof_vect == NULL) - fatal ("invalid `%s' in reservation `%s'", str, reserv_str); - if (els_num > 1) - { - oneof = create_node (sizeof (struct regexp) - + sizeof (regexp_t) * (els_num - 1)); - oneof->mode = rm_oneof; - oneof->regexp.oneof.regexps_num = els_num; - for (i = 0; i < els_num; i++) - oneof->regexp.oneof.regexps [i] = gen_regexp_allof (oneof_vect [i]); - return oneof; - } - else - return gen_regexp_allof (str); -} - -/* Parse reservation STR which possibly contains separator ','. */ -static regexp_t -gen_regexp_sequence (str) - char *str; -{ - regexp_t sequence; - char **sequence_vect; - int els_num; - int i; - - sequence_vect = get_str_vect (str, &els_num, ',', 1); - if (els_num > 1) - { - sequence = create_node (sizeof (struct regexp) - + sizeof (regexp_t) * (els_num - 1)); - sequence->mode = rm_sequence; - sequence->regexp.sequence.regexps_num = els_num; - for (i = 0; i < els_num; i++) - sequence->regexp.sequence.regexps [i] - = gen_regexp_oneof (sequence_vect [i]); - return sequence; - } - else - return gen_regexp_oneof (str); -} - -/* Parse construction reservation STR. */ -static regexp_t -gen_regexp (str) - char *str; -{ - reserv_str = str; - return gen_regexp_sequence (str);; -} - -/* Process a DEFINE_RESERVATION. - - This gives information about a reservation of cpu units. We fill - in a struct reserv_decl with information used later by - `expand_automata'. */ -void -gen_reserv (def) - rtx def; -{ - decl_t decl; - - decl = create_node (sizeof (struct decl)); - decl->mode = dm_reserv; - decl->pos = 0; - decl->decl.reserv.name = check_name ((char *) XSTR (def, 0), decl->pos); - decl->decl.reserv.regexp = gen_regexp ((char *) XSTR (def, 1)); - VLA_PTR_ADD (decls, decl); - num_dfa_decls++; -} - -/* Process a DEFINE_INSN_RESERVATION. - - This gives information about the reservation of cpu units by an - insn. We fill a struct insn_reserv_decl with information used - later by `expand_automata'. */ -void -gen_insn_reserv (def) - rtx def; -{ - decl_t decl; - - decl = create_node (sizeof (struct decl)); - decl->mode = dm_insn_reserv; - decl->pos = 0; - decl->decl.insn_reserv.name = check_name ((char *) XSTR (def, 0), decl->pos); - decl->decl.insn_reserv.default_latency = XINT (def, 1); - decl->decl.insn_reserv.condexp = XEXP (def, 2); - decl->decl.insn_reserv.regexp = gen_regexp ((char *) XSTR (def, 3)); - VLA_PTR_ADD (decls, decl); - num_dfa_decls++; -} - - - -/* The function evaluates hash value (0..UINT_MAX) of string. */ -static unsigned -string_hash (string) - const char *string; -{ - unsigned result, i; - - for (result = i = 0;*string++ != '\0'; i++) - result += ((unsigned char) *string << (i % CHAR_BIT)); - return result; -} - - - -/* This page contains abstract data `table of automaton declarations'. - Elements of the table is nodes representing automaton declarations. - Key of the table elements is name of given automaton. Rememeber - that automaton names have own space. */ - -/* The function evaluates hash value of a automaton declaration. The - function is used by abstract data `hashtab'. The function returns - hash value (0..UINT_MAX) of given automaton declaration. */ -static unsigned -automaton_decl_hash (automaton_decl) - const void *automaton_decl; -{ - const decl_t decl = (decl_t) automaton_decl; - - if (decl->mode == dm_automaton && decl->decl.automaton.name == NULL) - abort (); - return string_hash (decl->decl.automaton.name); -} - -/* The function tests automaton declarations on equality of their - keys. The function is used by abstract data `hashtab'. The - function returns 1 if the declarations have the same key, 0 - otherwise. */ -static int -automaton_decl_eq_p (automaton_decl_1, automaton_decl_2) - const void* automaton_decl_1; - const void* automaton_decl_2; -{ - const decl_t decl1 = (decl_t) automaton_decl_1; - const decl_t decl2 = (decl_t) automaton_decl_2; - - if (decl1->mode != dm_automaton || decl1->decl.automaton.name == NULL - || decl2->mode != dm_automaton || decl2->decl.automaton.name == NULL) - abort (); - return strcmp (decl1->decl.automaton.name, decl2->decl.automaton.name) == 0; -} - -/* The automaton declaration table itself is represented by the - following variable. */ -static htab_t automaton_decl_table; - -/* The function inserts automaton declaration into the table. The - function does nothing if an automaton declaration with the same key - exists already in the table. The function returns automaton - declaration node in the table with the same key as given automaton - declaration node. */ -static decl_t -insert_automaton_decl (automaton_decl) - decl_t automaton_decl; -{ - void **entry_ptr; - - entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1); - if (*entry_ptr == NULL) - *entry_ptr = (void *) automaton_decl; - return (decl_t) *entry_ptr; -} - -/* The following variable value is node representing automaton - declaration. The node used for searching automaton declaration - with given name. */ -static struct decl work_automaton_decl; - -/* The function searches for automaton declaration in the table with - the same key as node representing name of the automaton - declaration. The function returns node found in the table, NULL if - such node does not exist in the table. */ -static decl_t -find_automaton_decl (name) - char *name; -{ - void *entry; - - work_automaton_decl.decl.automaton.name = name; - entry = htab_find (automaton_decl_table, &work_automaton_decl); - return (decl_t) entry; -} - -/* The function creates empty automaton declaration table and node - representing automaton declaration and used for searching automaton - declaration with given name. The function must be called only once - before any work with the automaton declaration table. */ -static void -initiate_automaton_decl_table () -{ - work_automaton_decl.mode = dm_automaton; - automaton_decl_table = htab_create (10, automaton_decl_hash, - automaton_decl_eq_p, (htab_del) 0); -} - -/* The function deletes the automaton declaration table. Only call of - function `initiate_automaton_decl_table' is possible immediately - after this function call. */ -static void -finish_automaton_decl_table () -{ - htab_delete (automaton_decl_table); -} - - - -/* This page contains abstract data `table of insn declarations'. - Elements of the table is nodes representing insn declarations. Key - of the table elements is name of given insn (in corresponding - define_insn_reservation). Rememeber that insn names have own - space. */ - -/* The function evaluates hash value of a insn declaration. The - function is used by abstract data `hashtab'. The function returns - hash value (0..UINT_MAX) of given insn declaration. */ -static unsigned -insn_decl_hash (insn_decl) - const void *insn_decl; -{ - const decl_t decl = (decl_t) insn_decl; - - if (decl->mode != dm_insn_reserv || decl->decl.insn_reserv.name == NULL) - abort (); - return string_hash (decl->decl.insn_reserv.name); -} - -/* The function tests insn declarations on equality of their keys. - The function is used by abstract data `hashtab'. The function - returns 1 if declarations have the same key, 0 otherwise. */ -static int -insn_decl_eq_p (insn_decl_1, insn_decl_2) - const void *insn_decl_1; - const void *insn_decl_2; -{ - const decl_t decl1 = (decl_t) insn_decl_1; - const decl_t decl2 = (decl_t) insn_decl_2; - - if (decl1->mode != dm_insn_reserv || decl1->decl.insn_reserv.name == NULL - || decl2->mode != dm_insn_reserv || decl2->decl.insn_reserv.name == NULL) - abort (); - return strcmp (decl1->decl.insn_reserv.name, - decl2->decl.insn_reserv.name) == 0; -} - -/* The insn declaration table itself is represented by the following - variable. The table does not contain insn reservation - declarations. */ -static htab_t insn_decl_table; - -/* The function inserts insn declaration into the table. The function - does nothing if an insn declaration with the same key exists - already in the table. The function returns insn declaration node - in the table with the same key as given insn declaration node. */ -static decl_t -insert_insn_decl (insn_decl) - decl_t insn_decl; -{ - void **entry_ptr; - - entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1); - if (*entry_ptr == NULL) - *entry_ptr = (void *) insn_decl; - return (decl_t) *entry_ptr; -} - -/* The following variable value is node representing insn reservation - declaration. The node used for searching insn reservation - declaration with given name. */ -static struct decl work_insn_decl; - -/* The function searches for insn reservation declaration in the table - with the same key as node representing name of the insn reservation - declaration. The function returns node found in the table, NULL if - such node does not exist in the table. */ -static decl_t -find_insn_decl (name) - char *name; -{ - void *entry; - - work_insn_decl.decl.insn_reserv.name = name; - entry = htab_find (insn_decl_table, &work_insn_decl); - return (decl_t) entry; -} - -/* The function creates empty insn declaration table and node - representing insn declaration and used for searching insn - declaration with given name. The function must be called only once - before any work with the insn declaration table. */ -static void -initiate_insn_decl_table () -{ - work_insn_decl.mode = dm_insn_reserv; - insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p, - (htab_del) 0); -} - -/* The function deletes the insn declaration table. Only call of - function `initiate_insn_decl_table' is possible immediately after - this function call. */ -static void -finish_insn_decl_table () -{ - htab_delete (insn_decl_table); -} - - - -/* This page contains abstract data `table of declarations'. Elements - of the table is nodes representing declarations (of units and - reservations). Key of the table elements is names of given - declarations. */ - -/* The function evaluates hash value of a declaration. The function - is used by abstract data `hashtab'. The function returns hash - value (0..UINT_MAX) of given declaration. */ -static unsigned -decl_hash (decl) - const void *decl; -{ - const decl_t d = (const decl_t) decl; - - if ((d->mode != dm_unit || d->decl.unit.name == NULL) - && (d->mode != dm_reserv || d->decl.reserv.name == NULL)) - abort (); - return string_hash (d->mode == dm_unit - ? d->decl.unit.name : d->decl.reserv.name); -} - -/* The function tests declarations on equality of their keys. The - function is used by abstract data `hashtab'. The function - returns 1 if the declarations have the same key, 0 otherwise. */ -static int -decl_eq_p (decl_1, decl_2) - const void *decl_1; - const void *decl_2; -{ - const decl_t d1 = (const decl_t) decl_1; - const decl_t d2 = (const decl_t) decl_2; - - if (((d1->mode != dm_unit || d1->decl.unit.name == NULL) - && (d1->mode != dm_reserv || d1->decl.reserv.name == NULL)) - || ((d2->mode != dm_unit || d2->decl.unit.name == NULL) - && (d2->mode != dm_reserv || d2->decl.reserv.name == NULL))) - abort (); - return strcmp ((d1->mode == dm_unit - ? d1->decl.unit.name : d1->decl.reserv.name), - (d2->mode == dm_unit - ? d2->decl.unit.name : d2->decl.reserv.name)) == 0; -} - -/* The declaration table itself is represented by the following - variable. */ -static htab_t decl_table; - -/* The function inserts declaration into the table. The function does - nothing if a declaration with the same key exists already in the - table. The function returns declaration node in the table with the - same key as given declaration node. */ - -static decl_t -insert_decl (decl) - decl_t decl; -{ - void **entry_ptr; - - entry_ptr = htab_find_slot (decl_table, decl, 1); - if (*entry_ptr == NULL) - *entry_ptr = (void *) decl; - return (decl_t) *entry_ptr; -} - -/* The following variable value is node representing declaration. The - node used for searching declaration with given name. */ -static struct decl work_decl; - -/* The function searches for declaration in the table with the same - key as node representing name of the declaration. The function - returns node found in the table, NULL if such node does not exist - in the table. */ -static decl_t -find_decl (name) - char *name; -{ - void *entry; - - work_decl.decl.unit.name = name; - entry = htab_find (decl_table, &work_decl); - return (decl_t) entry; -} - -/* The function creates empty declaration table and node representing - declaration and used for searching declaration with given name. - The function must be called only once before any work with the - declaration table. */ -static void -initiate_decl_table () -{ - work_decl.mode = dm_unit; - decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0); -} - -/* The function deletes the declaration table. Only call of function - `initiate_declaration_table' is possible immediately after this - function call. */ -static void -finish_decl_table () -{ - htab_delete (decl_table); -} - - - -/* This page contains checker of pipeline hazard description. */ - -/* Checking NAMES in an exclusion clause vector and returning formed - unit_set_el_list. */ -static unit_set_el_t -process_excls (names, num, excl_pos) - char **names; - int num; - pos_t excl_pos ATTRIBUTE_UNUSED; -{ - unit_set_el_t el_list; - unit_set_el_t last_el; - unit_set_el_t new_el; - decl_t decl_in_table; - int i; - - el_list = NULL; - last_el = NULL; - for (i = 0; i < num; i++) - { - decl_in_table = find_decl (names [i]); - if (decl_in_table == NULL) - error ("unit `%s' in exclusion is not declared", names [i]); - else if (decl_in_table->mode != dm_unit) - error ("`%s' in exclusion is not unit", names [i]); - else - { - new_el = create_node (sizeof (struct unit_set_el)); - new_el->unit_decl = &decl_in_table->decl.unit; - new_el->next_unit_set_el = NULL; - if (last_el == NULL) - el_list = last_el = new_el; - else - { - last_el->next_unit_set_el = new_el; - last_el = last_el->next_unit_set_el; - } - } - } - return el_list; -} - -/* The function adds each element from SOURCE_LIST to the exclusion - list of the each element from DEST_LIST. Checking situation "unit - excludes itself". */ -static void -add_excls (dest_list, source_list, excl_pos) - unit_set_el_t dest_list; - unit_set_el_t source_list; - pos_t excl_pos ATTRIBUTE_UNUSED; -{ - unit_set_el_t dst; - unit_set_el_t src; - unit_set_el_t curr_el; - unit_set_el_t prev_el; - unit_set_el_t copy; - - for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el) - for (src = source_list; src != NULL; src = src->next_unit_set_el) - { - if (dst->unit_decl == src->unit_decl) - { - error ("unit `%s' excludes itself", src->unit_decl->name); - continue; - } - for (curr_el = dst->unit_decl->excl_list, prev_el = NULL; - curr_el != NULL; - prev_el = curr_el, curr_el = curr_el->next_unit_set_el) - if (curr_el->unit_decl == src->unit_decl) - break; - if (curr_el == NULL) - { - /* Element not found - insert. */ - copy = copy_node (src, sizeof (*src)); - copy->next_unit_set_el = NULL; - if (prev_el == NULL) - dst->unit_decl->excl_list = copy; - else - prev_el->next_unit_set_el = copy; - } - } -} - -/* Checking NAMES in an presence clause vector and returning formed - unit_set_el_list. The function is called only after processing all - exclusion sets. */ -static unit_set_el_t -process_presence_absence (names, num, req_pos, presence_p) - char **names; - int num; - pos_t req_pos ATTRIBUTE_UNUSED; - int presence_p; -{ - unit_set_el_t el_list; - unit_set_el_t last_el; - unit_set_el_t new_el; - decl_t decl_in_table; - int i; - - el_list = NULL; - last_el = NULL; - for (i = 0; i < num; i++) - { - decl_in_table = find_decl (names [i]); - if (decl_in_table == NULL) - error ((presence_p - ? "unit `%s' in presence set is not declared" - : "unit `%s' in absence set is not declared"), names [i]); - else if (decl_in_table->mode != dm_unit) - error ((presence_p - ? "`%s' in presence set is not unit" - : "`%s' in absence set is not unit"), names [i]); - else - { - new_el = create_node (sizeof (struct unit_set_el)); - new_el->unit_decl = &decl_in_table->decl.unit; - new_el->next_unit_set_el = NULL; - if (last_el == NULL) - el_list = last_el = new_el; - else - { - last_el->next_unit_set_el = new_el; - last_el = last_el->next_unit_set_el; - } - } - } - return el_list; -} - -/* The function adds each element from SOURCE_LIST to presence (if - PRESENCE_P) or absence list of the each element from DEST_LIST. - Checking situations "unit requires own presence", "unit requires - own absence", and "unit excludes and requires presence of ...". - Remember that we process absence sets only after all presence - sets. */ -static void -add_presence_absence (dest_list, source_list, req_pos, presence_p) - unit_set_el_t dest_list; - unit_set_el_t source_list; - pos_t req_pos ATTRIBUTE_UNUSED; - int presence_p; -{ - unit_set_el_t dst; - unit_set_el_t src; - unit_set_el_t curr_el; - unit_set_el_t prev_el; - unit_set_el_t copy; - - for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el) - for (src = source_list; src != NULL; src = src->next_unit_set_el) - { - if (dst->unit_decl == src->unit_decl) - { - error ((presence_p - ? "unit `%s' requires own presence" - : "unit `%s' requires own absence"), src->unit_decl->name); - continue; - } - for (curr_el = (presence_p - ? dst->unit_decl->presence_list - : dst->unit_decl->absence_list), prev_el = NULL; - curr_el != NULL; - prev_el = curr_el, curr_el = curr_el->next_unit_set_el) - if (curr_el->unit_decl == src->unit_decl) - break; - if (curr_el == NULL) - { - /* Element not found - insert if there is no error. */ - int no_error_flag = 1; - - if (presence_p) - for (curr_el = dst->unit_decl->excl_list; - curr_el != NULL; - curr_el = curr_el->next_unit_set_el) - { - if (src->unit_decl == curr_el->unit_decl) - { - if (!w_flag) - { - error - ("unit `%s' excludes and requires presence of `%s'", - dst->unit_decl->name, src->unit_decl->name); - no_error_flag = 0; - } - else - warning - ("unit `%s' excludes and requires presence of `%s'", - dst->unit_decl->name, src->unit_decl->name); - } - } - else - for (curr_el = dst->unit_decl->presence_list; - curr_el != NULL; - curr_el = curr_el->next_unit_set_el) - { - if (src->unit_decl == curr_el->unit_decl) - { - if (!w_flag) - { - error - ("unit `%s' requires absence and presence of `%s'", - dst->unit_decl->name, src->unit_decl->name); - no_error_flag = 0; - } - else - warning - ("unit `%s' requires absence and presence of `%s'", - dst->unit_decl->name, src->unit_decl->name); - } - } - if (no_error_flag) - { - copy = copy_node (src, sizeof (*src)); - copy->next_unit_set_el = NULL; - if (prev_el == NULL) - { - if (presence_p) - dst->unit_decl->presence_list = copy; - else - dst->unit_decl->absence_list = copy; - } - else - prev_el->next_unit_set_el = copy; - } - } - } -} - -/* The function searches for bypass with given IN_INSN_RESERV in given - BYPASS_LIST. */ -static struct bypass_decl * -find_bypass (bypass_list, in_insn_reserv) - struct bypass_decl *bypass_list; - struct insn_reserv_decl *in_insn_reserv; -{ - struct bypass_decl *bypass; - - for (bypass = bypass_list; bypass != NULL; bypass = bypass->next) - if (bypass->in_insn_reserv == in_insn_reserv) - break; - return bypass; -} - -/* The function processes pipeline description declarations, checks - their correctness, and forms exclusion/presence/absence sets. */ -static void -process_decls () -{ - decl_t decl; - decl_t automaton_decl; - decl_t decl_in_table; - decl_t out_insn_reserv; - decl_t in_insn_reserv; - struct bypass_decl *bypass; - int automaton_presence; - int i; - - /* Checking repeated automata declarations. */ - automaton_presence = 0; - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_automaton) - { - automaton_presence = 1; - decl_in_table = insert_automaton_decl (decl); - if (decl_in_table != decl) - { - if (!w_flag) - error ("repeated declaration of automaton `%s'", - decl->decl.automaton.name); - else - warning ("repeated declaration of automaton `%s'", - decl->decl.automaton.name); - } - } - } - /* Checking undeclared automata, repeated declarations (except for - automata) and correctness of their attributes (insn latency times - etc.). */ - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_insn_reserv) - { - decl->decl.insn_reserv.condexp - = check_attr_test (decl->decl.insn_reserv.condexp, 0, 0); - if (decl->decl.insn_reserv.default_latency < 0) - error ("define_insn_reservation `%s' has negative latency time", - decl->decl.insn_reserv.name); - decl->decl.insn_reserv.insn_num = description->insns_num; - description->insns_num++; - decl_in_table = insert_insn_decl (decl); - if (decl_in_table != decl) - error ("`%s' is already used as insn reservation name", - decl->decl.insn_reserv.name); - } - else if (decl->mode == dm_bypass) - { - if (decl->decl.bypass.latency < 0) - error ("define_bypass `%s - %s' has negative latency time", - decl->decl.bypass.out_insn_name, - decl->decl.bypass.in_insn_name); - } - else if (decl->mode == dm_unit || decl->mode == dm_reserv) - { - if (decl->mode == dm_unit) - { - decl->decl.unit.automaton_decl = NULL; - if (decl->decl.unit.automaton_name != NULL) - { - automaton_decl - = find_automaton_decl (decl->decl.unit.automaton_name); - if (automaton_decl == NULL) - error ("automaton `%s' is not declared", - decl->decl.unit.automaton_name); - else - { - automaton_decl->decl.automaton.automaton_is_used = 1; - decl->decl.unit.automaton_decl - = &automaton_decl->decl.automaton; - } - } - else if (automaton_presence) - error ("define_unit `%s' without automaton when one defined", - decl->decl.unit.name); - decl->decl.unit.unit_num = description->units_num; - description->units_num++; - if (strcmp (decl->decl.unit.name, NOTHING_NAME) == 0) - { - error ("`%s' is declared as cpu unit", NOTHING_NAME); - continue; - } - decl_in_table = find_decl (decl->decl.unit.name); - } - else - { - if (strcmp (decl->decl.reserv.name, NOTHING_NAME) == 0) - { - error ("`%s' is declared as cpu reservation", NOTHING_NAME); - continue; - } - decl_in_table = find_decl (decl->decl.reserv.name); - } - if (decl_in_table == NULL) - decl_in_table = insert_decl (decl); - else - { - if (decl->mode == dm_unit) - error ("repeated declaration of unit `%s'", - decl->decl.unit.name); - else - error ("repeated declaration of reservation `%s'", - decl->decl.reserv.name); - } - } - } - /* Check bypasses and form list of bypasses for each (output) - insn. */ - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_bypass) - { - out_insn_reserv = find_insn_decl (decl->decl.bypass.out_insn_name); - in_insn_reserv = find_insn_decl (decl->decl.bypass.in_insn_name); - if (out_insn_reserv == NULL) - error ("there is no insn reservation `%s'", - decl->decl.bypass.out_insn_name); - else if (in_insn_reserv == NULL) - error ("there is no insn reservation `%s'", - decl->decl.bypass.in_insn_name); - else - { - decl->decl.bypass.out_insn_reserv - = &out_insn_reserv->decl.insn_reserv; - decl->decl.bypass.in_insn_reserv - = &in_insn_reserv->decl.insn_reserv; - bypass - = find_bypass (out_insn_reserv->decl.insn_reserv.bypass_list, - decl->decl.bypass.in_insn_reserv); - if (bypass != NULL) - { - if (decl->decl.bypass.latency == bypass->latency) - { - if (!w_flag) - error - ("the same bypass `%s - %s' is already defined", - decl->decl.bypass.out_insn_name, - decl->decl.bypass.in_insn_name); - else - warning - ("the same bypass `%s - %s' is already defined", - decl->decl.bypass.out_insn_name, - decl->decl.bypass.in_insn_name); - } - else - error ("bypass `%s - %s' is already defined", - decl->decl.bypass.out_insn_name, - decl->decl.bypass.in_insn_name); - } - else - { - decl->decl.bypass.next - = out_insn_reserv->decl.insn_reserv.bypass_list; - out_insn_reserv->decl.insn_reserv.bypass_list - = &decl->decl.bypass; - } - } - } - } - - /* Check exclusion set declarations and form exclussion sets. */ - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_excl) - { - unit_set_el_t unit_set_el_list; - unit_set_el_t unit_set_el_list_2; - - unit_set_el_list - = process_excls (decl->decl.excl.names, - decl->decl.excl.first_list_length, decl->pos); - unit_set_el_list_2 - = process_excls (&decl->decl.excl.names - [decl->decl.excl.first_list_length], - decl->decl.excl.names_num - - decl->decl.excl.first_list_length, - decl->pos); - add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos); - add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos); - } - } - - /* Check presence set declarations and form presence sets. */ - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_presence) - { - unit_set_el_t unit_set_el_list; - unit_set_el_t unit_set_el_list_2; - - unit_set_el_list - = process_presence_absence - (decl->decl.presence.names, - decl->decl.presence.first_list_length, decl->pos, 1); - unit_set_el_list_2 - = process_presence_absence - (&decl->decl.presence.names - [decl->decl.presence.first_list_length], - decl->decl.presence.names_num - - decl->decl.presence.first_list_length, - decl->pos, 1); - add_presence_absence (unit_set_el_list, unit_set_el_list_2, - decl->pos, 1); - } - } - - /* Check absence set declarations and form absence sets. */ - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_absence) - { - unit_set_el_t unit_set_el_list; - unit_set_el_t unit_set_el_list_2; - - unit_set_el_list - = process_presence_absence - (decl->decl.presence.names, - decl->decl.presence.first_list_length, decl->pos, 0); - unit_set_el_list_2 - = process_presence_absence - (&decl->decl.presence.names - [decl->decl.presence.first_list_length], - decl->decl.presence.names_num - - decl->decl.presence.first_list_length, - decl->pos, 0); - add_presence_absence (unit_set_el_list, unit_set_el_list_2, - decl->pos, 0); - } - } -} - -/* The following function checks that declared automaton is used. If - the automaton is not used, the function fixes error/warning. The - following function must be called only after `process_decls'. */ -static void -check_automaton_usage () -{ - decl_t decl; - int i; - - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_automaton - && !decl->decl.automaton.automaton_is_used) - { - if (!w_flag) - error ("automaton `%s' is not used", decl->decl.automaton.name); - else - warning ("automaton `%s' is not used", decl->decl.automaton.name); - } - } -} - -/* The following recursive function processes all regexp in order to - fix usage of units or reservations and to fix errors of undeclared - name. The function may change unit_regexp onto reserv_regexp. - Remember that reserv_regexp does not exist before the function - call. */ -static regexp_t -process_regexp (regexp) - regexp_t regexp; -{ - decl_t decl_in_table; - regexp_t new_regexp; - int i; - - if (regexp->mode == rm_unit) - { - decl_in_table = find_decl (regexp->regexp.unit.name); - if (decl_in_table == NULL) - error ("undeclared unit or reservation `%s'", - regexp->regexp.unit.name); - else if (decl_in_table->mode == dm_unit) - { - decl_in_table->decl.unit.unit_is_used = 1; - regexp->regexp.unit.unit_decl = &decl_in_table->decl.unit; - } - else if (decl_in_table->mode == dm_reserv) - { - decl_in_table->decl.reserv.reserv_is_used = 1; - new_regexp = create_node (sizeof (struct regexp)); - new_regexp->mode = rm_reserv; - new_regexp->pos = regexp->pos; - new_regexp->regexp.reserv.name = regexp->regexp.unit.name; - new_regexp->regexp.reserv.reserv_decl = &decl_in_table->decl.reserv; - regexp = new_regexp; - } - else - abort (); - } - else if (regexp->mode == rm_sequence) - for (i = 0; i < regexp->regexp.sequence.regexps_num; i++) - regexp->regexp.sequence.regexps [i] - = process_regexp (regexp->regexp.sequence.regexps [i]); - else if (regexp->mode == rm_allof) - for (i = 0; i < regexp->regexp.allof.regexps_num; i++) - regexp->regexp.allof.regexps [i] - = process_regexp (regexp->regexp.allof.regexps [i]); - else if (regexp->mode == rm_oneof) - for (i = 0; i < regexp->regexp.oneof.regexps_num; i++) - regexp->regexp.oneof.regexps [i] - = process_regexp (regexp->regexp.oneof.regexps [i]); - else if (regexp->mode == rm_repeat) - regexp->regexp.repeat.regexp - = process_regexp (regexp->regexp.repeat.regexp); - else if (regexp->mode != rm_nothing) - abort (); - return regexp; -} - -/* The following function processes regexp of define_reservation and - define_insn_reservation with the aid of function - `process_regexp'. */ -static void -process_regexp_decls () -{ - decl_t decl; - int i; - - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_reserv) - decl->decl.reserv.regexp = process_regexp (decl->decl.reserv.regexp); - else if (decl->mode == dm_insn_reserv) - decl->decl.insn_reserv.regexp - = process_regexp (decl->decl.insn_reserv.regexp); - } -} - -/* The following function checks that declared unit is used. If the - unit is not used, the function fixes errors/warnings. The - following function must be called only after `process_decls', - `process_regexp_decls'. */ -static void -check_usage () -{ - decl_t decl; - int i; - - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_unit && !decl->decl.unit.unit_is_used) - { - if (!w_flag) - error ("unit `%s' is not used", decl->decl.unit.name); - else - warning ("unit `%s' is not used", decl->decl.unit.name); - } - else if (decl->mode == dm_reserv && !decl->decl.reserv.reserv_is_used) - { - if (!w_flag) - error ("reservation `%s' is not used", decl->decl.reserv.name); - else - warning ("reservation `%s' is not used", decl->decl.reserv.name); - } - } -} - -/* The following variable value is number of reservation being - processed on loop recognition. */ -static int curr_loop_pass_num; - -/* The following recursive function returns nonzero value if REGEXP - contains given decl or reservations in given regexp refers for - given decl. */ -static int -loop_in_regexp (regexp, start_decl) - regexp_t regexp; - decl_t start_decl; -{ - int i; - - if (regexp == NULL) - return 0; - if (regexp->mode == rm_unit) - return 0; - else if (regexp->mode == rm_reserv) - { - if (start_decl->mode == dm_reserv - && regexp->regexp.reserv.reserv_decl == &start_decl->decl.reserv) - return 1; - else if (regexp->regexp.reserv.reserv_decl->loop_pass_num - == curr_loop_pass_num) - /* declaration has been processed. */ - return 0; - else - { - regexp->regexp.reserv.reserv_decl->loop_pass_num - = curr_loop_pass_num; - return loop_in_regexp (regexp->regexp.reserv.reserv_decl->regexp, - start_decl); - } - } - else if (regexp->mode == rm_sequence) - { - for (i = 0; i < regexp->regexp.sequence.regexps_num; i++) - if (loop_in_regexp (regexp->regexp.sequence.regexps [i], start_decl)) - return 1; - return 0; - } - else if (regexp->mode == rm_allof) - { - for (i = 0; i < regexp->regexp.allof.regexps_num; i++) - if (loop_in_regexp (regexp->regexp.allof.regexps [i], start_decl)) - return 1; - return 0; - } - else if (regexp->mode == rm_oneof) - { - for (i = 0; i < regexp->regexp.oneof.regexps_num; i++) - if (loop_in_regexp (regexp->regexp.oneof.regexps [i], start_decl)) - return 1; - return 0; - } - else if (regexp->mode == rm_repeat) - return loop_in_regexp (regexp->regexp.repeat.regexp, start_decl); - else - { - if (regexp->mode != rm_nothing) - abort (); - return 0; - } -} - -/* The following function fixes errors "cycle in definition ...". The - function uses function `loop_in_regexp' for that. */ -static void -check_loops_in_regexps () -{ - decl_t decl; - int i; - - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_reserv) - decl->decl.reserv.loop_pass_num = 0; - } - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - curr_loop_pass_num = i; - - if (decl->mode == dm_reserv) - { - decl->decl.reserv.loop_pass_num = curr_loop_pass_num; - if (loop_in_regexp (decl->decl.reserv.regexp, decl)) - { - if (decl->decl.reserv.regexp == NULL) - abort (); - error ("cycle in definition of reservation `%s'", - decl->decl.reserv.name); - } - } - } -} - -/* The function recursively processes IR of reservation and defines - max and min cycle for reservation of unit and for result in the - reservation. */ -static int -process_regexp_cycles (regexp, start_cycle) - regexp_t regexp; - int start_cycle; -{ - int i; - - if (regexp->mode == rm_unit) - { - if (regexp->regexp.unit.unit_decl->max_occ_cycle_num < start_cycle) - regexp->regexp.unit.unit_decl->max_occ_cycle_num = start_cycle; - return start_cycle; - } - else if (regexp->mode == rm_reserv) - return process_regexp_cycles (regexp->regexp.reserv.reserv_decl->regexp, - start_cycle); - else if (regexp->mode == rm_repeat) - { - for (i = 0; i < regexp->regexp.repeat.repeat_num; i++) - start_cycle = process_regexp_cycles (regexp->regexp.repeat.regexp, - start_cycle) + 1; - return start_cycle; - } - else if (regexp->mode == rm_sequence) - { - for (i = 0; i < regexp->regexp.sequence.regexps_num; i++) - start_cycle - = process_regexp_cycles (regexp->regexp.sequence.regexps [i], - start_cycle) + 1; - return start_cycle; - } - else if (regexp->mode == rm_allof) - { - int finish_cycle = 0; - int cycle; - - for (i = 0; i < regexp->regexp.allof.regexps_num; i++) - { - cycle = process_regexp_cycles (regexp->regexp.allof.regexps [i], - start_cycle); - if (finish_cycle < cycle) - finish_cycle = cycle; - } - return finish_cycle; - } - else if (regexp->mode == rm_oneof) - { - int finish_cycle = 0; - int cycle; - - for (i = 0; i < regexp->regexp.oneof.regexps_num; i++) - { - cycle = process_regexp_cycles (regexp->regexp.oneof.regexps [i], - start_cycle); - if (finish_cycle < cycle) - finish_cycle = cycle; - } - return finish_cycle; - } - else - { - if (regexp->mode != rm_nothing) - abort (); - return start_cycle; - } -} - -/* The following function is called only for correct program. The - function defines max reservation of insns in cycles. */ -static void -evaluate_max_reserv_cycles () -{ - int max_insn_cycles_num; - decl_t decl; - int i; - - description->max_insn_reserv_cycles = 0; - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_insn_reserv) - { - max_insn_cycles_num - = process_regexp_cycles (decl->decl.insn_reserv.regexp, 0); - if (description->max_insn_reserv_cycles < max_insn_cycles_num) - description->max_insn_reserv_cycles = max_insn_cycles_num; - } - } -} - -/* The following function calls functions for checking all - description. */ -static void -check_all_description () -{ - process_decls (); - check_automaton_usage (); - process_regexp_decls (); - check_usage (); - check_loops_in_regexps (); - if (!have_error) - evaluate_max_reserv_cycles (); -} - - - -/* The page contains abstract data `ticker'. This data is used to - report time of different phases of building automata. It is - possibly to write a description for which automata will be built - during several minutes even on fast machine. */ - -/* The following function creates ticker and makes it active. */ -static ticker_t -create_ticker () -{ - ticker_t ticker; - - ticker.modified_creation_time = get_run_time (); - ticker.incremented_off_time = 0; - return ticker; -} - -/* The following function switches off given ticker. */ -static void -ticker_off (ticker) - ticker_t *ticker; -{ - if (ticker->incremented_off_time == 0) - ticker->incremented_off_time = get_run_time () + 1; -} - -/* The following function switches on given ticker. */ -static void -ticker_on (ticker) - ticker_t *ticker; -{ - if (ticker->incremented_off_time != 0) - { - ticker->modified_creation_time - += get_run_time () - ticker->incremented_off_time + 1; - ticker->incremented_off_time = 0; - } -} - -/* The following function returns current time in milliseconds since - the moment when given ticker was created. */ -static int -active_time (ticker) - ticker_t ticker; -{ - if (ticker.incremented_off_time != 0) - return ticker.incremented_off_time - 1 - ticker.modified_creation_time; - else - return get_run_time () - ticker.modified_creation_time; -} - -/* The following function returns string representation of active time - of given ticker. The result is string representation of seconds - with accuracy of 1/100 second. Only result of the last call of the - function exists. Therefore the following code is not correct - - printf ("parser time: %s\ngeneration time: %s\n", - active_time_string (parser_ticker), - active_time_string (generation_ticker)); - - Correct code has to be the following - - printf ("parser time: %s\n", active_time_string (parser_ticker)); - printf ("generation time: %s\n", - active_time_string (generation_ticker)); - -*/ -static void -print_active_time (f, ticker) - FILE *f; - ticker_t ticker; -{ - int msecs; - - msecs = active_time (ticker); - fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000); -} - - - -/* The following variable value is number of automaton which are - really being created. This value is defined on the base of - argument of option `-split'. If the variable has zero value the - number of automata is defined by the constructions `%automaton'. - This case occures when option `-split' is absent or has zero - argument. If constructions `define_automaton' is absent only one - automaton is created. */ -static int automata_num; - -/* The following variable values are times of - o transformation of regular expressions - o building NDFA (DFA if !ndfa_flag) - o NDFA -> DFA (simply the same automaton if !ndfa_flag) - o DFA minimization - o building insn equivalence classes - o all previous ones - o code output */ -static ticker_t transform_time; -static ticker_t NDFA_time; -static ticker_t NDFA_to_DFA_time; -static ticker_t minimize_time; -static ticker_t equiv_time; -static ticker_t automaton_generation_time; -static ticker_t output_time; - -/* The following variable values are times of - all checking - all generation - all pipeline hazard translator work */ -static ticker_t check_time; -static ticker_t generation_time; -static ticker_t all_time; - - - -/* Pseudo insn decl which denotes advancing cycle. */ -static decl_t advance_cycle_insn_decl; -static void -add_advance_cycle_insn_decl () -{ - advance_cycle_insn_decl = create_node (sizeof (struct decl)); - advance_cycle_insn_decl->mode = dm_insn_reserv; - advance_cycle_insn_decl->pos = no_pos; - advance_cycle_insn_decl->decl.insn_reserv.regexp = NULL; - advance_cycle_insn_decl->decl.insn_reserv.name = (char *) "$advance_cycle"; - advance_cycle_insn_decl->decl.insn_reserv.insn_num = description->insns_num; - description->decls [description->decls_num] = advance_cycle_insn_decl; - description->decls_num++; - description->insns_num++; - num_dfa_decls++; -} - - -/* Abstract data `alternative states' which reperesents - nondeterministic nature of the description (see comments for - structures alt_state and state). */ - -/* List of free states. */ -static alt_state_t first_free_alt_state; - -#ifndef NDEBUG -/* The following variables is maximal number of allocated nodes - alt_state. */ -static int allocated_alt_states_num = 0; -#endif - -/* The following function returns free node alt_state. It may be new - allocated node or node freed eralier. */ -static alt_state_t -get_free_alt_state () -{ - alt_state_t result; - - if (first_free_alt_state != NULL) - { - result = first_free_alt_state; - first_free_alt_state = first_free_alt_state->next_alt_state; - } - else - { -#ifndef NDEBUG - allocated_alt_states_num++; -#endif - result = create_node (sizeof (struct alt_state)); - } - result->state = NULL; - result->next_alt_state = NULL; - result->next_sorted_alt_state = NULL; - return result; -} - -/* The function frees node ALT_STATE. */ -static void -free_alt_state (alt_state) - alt_state_t alt_state; -{ - if (alt_state == NULL) - return; - alt_state->next_alt_state = first_free_alt_state; - first_free_alt_state = alt_state; -} - -/* The function frees list started with node ALT_STATE_LIST. */ -static void -free_alt_states (alt_states_list) - alt_state_t alt_states_list; -{ - alt_state_t curr_alt_state; - alt_state_t next_alt_state; - - for (curr_alt_state = alt_states_list; - curr_alt_state != NULL; - curr_alt_state = next_alt_state) - { - next_alt_state = curr_alt_state->next_alt_state; - free_alt_state (curr_alt_state); - } -} - -/* The function compares unique numbers of alt states. */ -static int -alt_state_cmp (alt_state_ptr_1, alt_state_ptr_2) - const void *alt_state_ptr_1; - const void *alt_state_ptr_2; -{ - if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num - == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num) - return 0; - else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num - < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num) - return -1; - else - return 1; -} - -/* The function sorts ALT_STATES_LIST and removes duplicated alt - states from the list. The comparison key is alt state unique - number. */ -static alt_state_t -uniq_sort_alt_states (alt_states_list) - alt_state_t alt_states_list; -{ - alt_state_t curr_alt_state; - vla_ptr_t alt_states; - size_t i; - size_t prev_unique_state_ind; - alt_state_t result; - alt_state_t *result_ptr; - - VLA_PTR_CREATE (alt_states, 150, "alt_states"); - for (curr_alt_state = alt_states_list; - curr_alt_state != NULL; - curr_alt_state = curr_alt_state->next_alt_state) - VLA_PTR_ADD (alt_states, curr_alt_state); - qsort (VLA_PTR_BEGIN (alt_states), VLA_PTR_LENGTH (alt_states), - sizeof (alt_state_t), alt_state_cmp); - if (VLA_PTR_LENGTH (alt_states) == 0) - result = NULL; - else - { - result_ptr = VLA_PTR_BEGIN (alt_states); - prev_unique_state_ind = 0; - for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++) - if (result_ptr [prev_unique_state_ind]->state != result_ptr [i]->state) - { - prev_unique_state_ind++; - result_ptr [prev_unique_state_ind] = result_ptr [i]; - } -#if 0 - for (i = prev_unique_state_ind + 1; i < VLA_PTR_LENGTH (alt_states); i++) - free_alt_state (result_ptr [i]); -#endif - VLA_PTR_SHORTEN (alt_states, i - prev_unique_state_ind - 1); - result_ptr = VLA_PTR_BEGIN (alt_states); - for (i = 1; i < VLA_PTR_LENGTH (alt_states); i++) - result_ptr [i - 1]->next_sorted_alt_state = result_ptr [i]; - result_ptr [i - 1]->next_sorted_alt_state = NULL; - result = *result_ptr; - } - VLA_PTR_DELETE (alt_states); - return result; -} - -/* The function checks equality of alt state lists. Remember that the - lists must be already sorted by the previous function. */ -static int -alt_states_eq (alt_states_1, alt_states_2) - alt_state_t alt_states_1; - alt_state_t alt_states_2; -{ - while (alt_states_1 != NULL && alt_states_2 != NULL - && alt_state_cmp (&alt_states_1, &alt_states_2) == 0) - { - alt_states_1 = alt_states_1->next_sorted_alt_state; - alt_states_2 = alt_states_2->next_sorted_alt_state; - } - return alt_states_1 == alt_states_2; -} - -/* Initialization of the abstract data. */ -static void -initiate_alt_states () -{ - first_free_alt_state = NULL; -} - -/* Finishing work with the abstract data. */ -static void -finish_alt_states () -{ -} - - - -/* The page contains macros for work with bits strings. We could use - standard gcc bitmap or sbitmap but it would result in difficulties - of building canadian cross. */ - -/* Set bit number bitno in the bit string. The macro is not side - effect proof. */ -#define SET_BIT(bitstring, bitno) \ - (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT) - -/* Test if bit number bitno in the bitstring is set. The macro is not - side effect proof. */ -#define TEST_BIT(bitstring, bitno) \ - (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1) - - - -/* This page contains abstract data `state'. */ - -/* Maximal length of reservations in cycles (> 1). */ -static int max_cycles_num; - -/* Number of set elements (see type set_el_t) needed for - representation of one cycle reservation. It is depended on units - number. */ -static int els_in_cycle_reserv; - -/* Number of set elements (see type set_el_t) needed for - representation of maximal length reservation. Deterministic - reservation is stored as set (bit string) of length equal to the - variable value * number of bits in set_el_t. */ -static int els_in_reservs; - -/* VLA for representation of array of pointers to unit - declarations. */ -static vla_ptr_t units_container; - -/* The start address of the array. */ -static struct unit_decl **units_array; - -/* Empty reservation of maximal length. */ -static reserv_sets_t empty_reserv; - -/* The state table itself is represented by the following variable. */ -static htab_t state_table; - -/* VLA for representation of array of pointers to free nodes - `state'. */ -static vla_ptr_t free_states; - -static int curr_unique_state_num; - -#ifndef NDEBUG -/* The following variables is maximal number of allocated nodes - `state'. */ -static int allocated_states_num = 0; -#endif - -/* Allocate new reservation set. */ -static reserv_sets_t -alloc_empty_reserv_sets () -{ - reserv_sets_t result; - - obstack_blank (&irp, els_in_reservs * sizeof (set_el_t)); - result = (reserv_sets_t) obstack_base (&irp); - obstack_finish (&irp); - memset (result, 0, els_in_reservs * sizeof (set_el_t)); - return result; -} - -/* Hash value of reservation set. */ -static unsigned -reserv_sets_hash_value (reservs) - reserv_sets_t reservs; -{ - unsigned int hash_value; - int reservs_num; - set_el_t *reserv_ptr; - - hash_value = 0; - reservs_num = els_in_reservs; - reserv_ptr = reservs; - while (reservs_num != 0) - { - reservs_num--; - hash_value = ((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT) - | (hash_value << CHAR_BIT)) + *reserv_ptr; - reserv_ptr++; - } - return hash_value; -} - -/* Comparison of given reservation sets. */ -static int -reserv_sets_cmp (reservs_1, reservs_2) - reserv_sets_t reservs_1; - reserv_sets_t reservs_2; -{ - int reservs_num; - set_el_t *reserv_ptr_1; - set_el_t *reserv_ptr_2; - - if (reservs_1 == NULL || reservs_2 == NULL) - abort (); - reservs_num = els_in_reservs; - reserv_ptr_1 = reservs_1; - reserv_ptr_2 = reservs_2; - while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2) - { - reservs_num--; - reserv_ptr_1++; - reserv_ptr_2++; - } - if (reservs_num == 0) - return 0; - else if (*reserv_ptr_1 < *reserv_ptr_2) - return -1; - else - return 1; -} - -/* The function checks equality of the reservation sets. */ -static int -reserv_sets_eq (reservs_1, reservs_2) - reserv_sets_t reservs_1; - reserv_sets_t reservs_2; -{ - return reserv_sets_cmp (reservs_1, reservs_2) == 0; -} - -/* Set up in the reservation set that unit with UNIT_NUM is used on - CYCLE_NUM. */ -static void -set_unit_reserv (reservs, cycle_num, unit_num) - reserv_sets_t reservs; - int cycle_num; - int unit_num; -{ - if (cycle_num >= max_cycles_num) - abort (); - SET_BIT (reservs, cycle_num * els_in_cycle_reserv - * sizeof (set_el_t) * CHAR_BIT + unit_num); -} - -/* Set up in the reservation set RESERVS that unit with UNIT_NUM is - used on CYCLE_NUM. */ -static int -test_unit_reserv (reservs, cycle_num, unit_num) - reserv_sets_t reservs; - int cycle_num; - int unit_num; -{ - if (cycle_num >= max_cycles_num) - abort (); - return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv - * sizeof (set_el_t) * CHAR_BIT + unit_num); -} - -/* The function checks that the reservation set represents no one unit - reservation. */ -static int -it_is_empty_reserv_sets (operand) - reserv_sets_t operand; -{ - set_el_t *reserv_ptr; - int reservs_num; - - if (operand == NULL) - abort (); - for (reservs_num = els_in_reservs, reserv_ptr = operand; - reservs_num != 0; - reserv_ptr++, reservs_num--) - if (*reserv_ptr != 0) - return 0; - return 1; -} - -/* The function checks that the reservation sets are intersected, - i.e. there is a unit reservation on a cycle in both reservation - sets. */ -static int -reserv_sets_are_intersected (operand_1, operand_2) - reserv_sets_t operand_1; - reserv_sets_t operand_2; -{ - set_el_t *el_ptr_1; - set_el_t *el_ptr_2; - set_el_t *cycle_ptr_1; - set_el_t *cycle_ptr_2; - int nonzero_p; - - if (operand_1 == NULL || operand_2 == NULL) - abort (); - for (el_ptr_1 = operand_1, el_ptr_2 = operand_2; - el_ptr_1 < operand_1 + els_in_reservs; - el_ptr_1++, el_ptr_2++) - if (*el_ptr_1 & *el_ptr_2) - return 1; - for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2; - cycle_ptr_1 < operand_1 + els_in_reservs; - cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv) - { - for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2); - el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv; - el_ptr_1++, el_ptr_2++) - if (*el_ptr_1 & *el_ptr_2) - return 1; - nonzero_p = 0; - for (el_ptr_1 = cycle_ptr_1, - el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 1); - el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv; - el_ptr_1++, el_ptr_2++) - if (*el_ptr_1 & *el_ptr_2) - break; - else if (*el_ptr_2 != 0) - nonzero_p = 1; - if (nonzero_p && el_ptr_1 >= cycle_ptr_1 + els_in_cycle_reserv) - return 1; - for (el_ptr_1 = cycle_ptr_1, - el_ptr_2 = get_presence_absence_set (cycle_ptr_2, 0); - el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv; - el_ptr_1++, el_ptr_2++) - /* It looks like code for exclusion but exclusion set is - made as symmetric relation preliminary. */ - if (*el_ptr_1 & *el_ptr_2) - return 1; - } - return 0; -} - -/* The function sets up RESULT bits by bits of OPERAND shifted on one - cpu cycle. The remaining bits of OPERAND (representing the last - cycle unit reservations) are not chenged. */ -static void -reserv_sets_shift (result, operand) - reserv_sets_t result; - reserv_sets_t operand; -{ - int i; - - if (result == NULL || operand == NULL || result == operand) - abort (); - for (i = els_in_cycle_reserv; i < els_in_reservs; i++) - result [i - els_in_cycle_reserv] = operand [i]; -} - -/* OR of the reservation sets. */ -static void -reserv_sets_or (result, operand_1, operand_2) - reserv_sets_t result; - reserv_sets_t operand_1; - reserv_sets_t operand_2; -{ - set_el_t *el_ptr_1; - set_el_t *el_ptr_2; - set_el_t *result_set_el_ptr; - - if (result == NULL || operand_1 == NULL || operand_2 == NULL) - abort (); - for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result; - el_ptr_1 < operand_1 + els_in_reservs; - el_ptr_1++, el_ptr_2++, result_set_el_ptr++) - *result_set_el_ptr = *el_ptr_1 | *el_ptr_2; -} - -/* AND of the reservation sets. */ -static void -reserv_sets_and (result, operand_1, operand_2) - reserv_sets_t result; - reserv_sets_t operand_1; - reserv_sets_t operand_2; -{ - set_el_t *el_ptr_1; - set_el_t *el_ptr_2; - set_el_t *result_set_el_ptr; - - if (result == NULL || operand_1 == NULL || operand_2 == NULL) - abort (); - for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result; - el_ptr_1 < operand_1 + els_in_reservs; - el_ptr_1++, el_ptr_2++, result_set_el_ptr++) - *result_set_el_ptr = *el_ptr_1 & *el_ptr_2; -} - -/* The function outputs string representation of units reservation on - cycle START_CYCLE in the reservation set. The function uses repeat - construction if REPETITION_NUM > 1. */ -static void -output_cycle_reservs (f, reservs, start_cycle, repetition_num) - FILE *f; - reserv_sets_t reservs; - int start_cycle; - int repetition_num; -{ - int unit_num; - int reserved_units_num; - - reserved_units_num = 0; - for (unit_num = 0; unit_num < description->units_num; unit_num++) - if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv - * sizeof (set_el_t) * CHAR_BIT + unit_num)) - reserved_units_num++; - if (repetition_num <= 0) - abort (); - if (repetition_num != 1 && reserved_units_num > 1) - fprintf (f, "("); - reserved_units_num = 0; - for (unit_num = 0; - unit_num < description->units_num; - unit_num++) - if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv - * sizeof (set_el_t) * CHAR_BIT + unit_num)) - { - if (reserved_units_num != 0) - fprintf (f, "+"); - reserved_units_num++; - fprintf (f, "%s", units_array [unit_num]->name); - } - if (reserved_units_num == 0) - fprintf (f, NOTHING_NAME); - if (repetition_num <= 0) - abort (); - if (reserved_units_num != 0 && repetition_num != 1) - { - if (reserved_units_num > 1) - fprintf (f, ")"); - fprintf (f, "*%d", repetition_num); - } -} - -/* The function outputs string representation of units reservation in - the reservation set. */ -static void -output_reserv_sets (f, reservs) - FILE *f; - reserv_sets_t reservs; -{ - int start_cycle = 0; - int cycle; - int repetition_num; - int next_cycle_output_flag; - - repetition_num = 0; - next_cycle_output_flag = 0; - for (cycle = 0; cycle < max_cycles_num; cycle++) - if (repetition_num == 0) - { - repetition_num++; - start_cycle = cycle; - } - else if (memcmp - ((char *) reservs + start_cycle * els_in_cycle_reserv - * sizeof (set_el_t), - (char *) reservs + cycle * els_in_cycle_reserv - * sizeof (set_el_t), - els_in_cycle_reserv * sizeof (set_el_t)) == 0) - repetition_num++; - else - { - if (next_cycle_output_flag) - fprintf (f, ", "); - output_cycle_reservs (f, reservs, start_cycle, repetition_num); - next_cycle_output_flag = 1; - repetition_num = 1; - start_cycle = cycle; - } - if (!next_cycle_output_flag) - { - if (next_cycle_output_flag) - fprintf (f, ", "); - output_cycle_reservs (f, reservs, start_cycle, repetition_num); - } -} - -/* The following function returns free node state for AUTOMATON. It - may be new allocated node or node freed eralier. The function also - allocates reservation set if WITH_RESERVS has nonzero value. */ -static state_t -get_free_state (with_reservs, automaton) - int with_reservs; - automaton_t automaton; -{ - state_t result; - - if (max_cycles_num <= 0 || automaton == NULL) - abort (); - if (VLA_PTR_LENGTH (free_states) != 0) - { - result = VLA_PTR (free_states, VLA_PTR_LENGTH (free_states) - 1); - VLA_PTR_SHORTEN (free_states, 1); - result->automaton = automaton; - result->first_out_arc = NULL; - result->it_was_placed_in_stack_for_NDFA_forming = 0; - result->it_was_placed_in_stack_for_DFA_forming = 0; - result->component_states = NULL; - result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH; - } - else - { -#ifndef NDEBUG - allocated_states_num++; -#endif - result = create_node (sizeof (struct state)); - result->automaton = automaton; - result->first_out_arc = NULL; - result->unique_num = curr_unique_state_num; - result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH; - curr_unique_state_num++; - } - if (with_reservs) - { - if (result->reservs == NULL) - result->reservs = alloc_empty_reserv_sets (); - else - memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t)); - } - return result; -} - -/* The function frees node STATE. */ -static void -free_state (state) - state_t state; -{ - free_alt_states (state->component_states); - VLA_PTR_ADD (free_states, state); -} - -/* Hash value of STATE. If STATE represents deterministic state it is - simply hash value of the corresponding reservation set. Otherwise - it is formed from hash values of the component deterministic - states. One more key is order number of state automaton. */ -static unsigned -state_hash (state) - const void *state; -{ - unsigned int hash_value; - alt_state_t alt_state; - - if (((state_t) state)->component_states == NULL) - hash_value = reserv_sets_hash_value (((state_t) state)->reservs); - else - { - hash_value = 0; - for (alt_state = ((state_t) state)->component_states; - alt_state != NULL; - alt_state = alt_state->next_sorted_alt_state) - hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT) - | (hash_value << CHAR_BIT)) - + alt_state->state->unique_num); - } - hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT) - | (hash_value << CHAR_BIT)) - + ((state_t) state)->automaton->automaton_order_num); - return hash_value; -} - -/* Return nonzero value if the states are the same. */ -static int -state_eq_p (state_1, state_2) - const void *state_1; - const void *state_2; -{ - alt_state_t alt_state_1; - alt_state_t alt_state_2; - - if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton) - return 0; - else if (((state_t) state_1)->component_states == NULL - && ((state_t) state_2)->component_states == NULL) - return reserv_sets_eq (((state_t) state_1)->reservs, - ((state_t) state_2)->reservs); - else if (((state_t) state_1)->component_states != NULL - && ((state_t) state_2)->component_states != NULL) - { - for (alt_state_1 = ((state_t) state_1)->component_states, - alt_state_2 = ((state_t) state_2)->component_states; - alt_state_1 != NULL && alt_state_2 != NULL; - alt_state_1 = alt_state_1->next_sorted_alt_state, - alt_state_2 = alt_state_2->next_sorted_alt_state) - /* All state in the list must be already in the hash table. - Also the lists must be sorted. */ - if (alt_state_1->state != alt_state_2->state) - return 0; - return alt_state_1 == alt_state_2; - } - else - return 0; -} - -/* Insert STATE into the state table. */ -static state_t -insert_state (state) - state_t state; -{ - void **entry_ptr; - - entry_ptr = htab_find_slot (state_table, (void *) state, 1); - if (*entry_ptr == NULL) - *entry_ptr = (void *) state; - return (state_t) *entry_ptr; -} - -/* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to - deterministic STATE. */ -static void -set_state_reserv (state, cycle_num, unit_num) - state_t state; - int cycle_num; - int unit_num; -{ - set_unit_reserv (state->reservs, cycle_num, unit_num); -} - -/* Return nonzero value if the deterministic states contains a - reservation of the same cpu unit on the same cpu cycle. */ -static int -intersected_state_reservs_p (state1, state2) - state_t state1; - state_t state2; -{ - if (state1->automaton != state2->automaton) - abort (); - return reserv_sets_are_intersected (state1->reservs, state2->reservs); -} - -/* Return deterministic state (inserted into the table) which - representing the automaton state whic is union of reservations of - deterministic states. */ -static state_t -states_union (state1, state2) - state_t state1; - state_t state2; -{ - state_t result; - state_t state_in_table; - - if (state1->automaton != state2->automaton) - abort (); - result = get_free_state (1, state1->automaton); - reserv_sets_or (result->reservs, state1->reservs, state2->reservs); - state_in_table = insert_state (result); - if (result != state_in_table) - { - free_state (result); - result = state_in_table; - } - return result; -} - -/* Return deterministic state (inserted into the table) which - represent the automaton state is obtained from deterministic STATE - by advancing cpu cycle. */ -static state_t -state_shift (state) - state_t state; -{ - state_t result; - state_t state_in_table; - - result = get_free_state (1, state->automaton); - reserv_sets_shift (result->reservs, state->reservs); - state_in_table = insert_state (result); - if (result != state_in_table) - { - free_state (result); - result = state_in_table; - } - return result; -} - -/* Initialization of the abstract data. */ -static void -initiate_states () -{ - decl_t decl; - int i; - - VLA_PTR_CREATE (units_container, description->units_num, "units_container"); - units_array - = (description->decls_num ? VLA_PTR_BEGIN (units_container) : NULL); - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_unit) - units_array [decl->decl.unit.unit_num] = &decl->decl.unit; - } - max_cycles_num = description->max_insn_reserv_cycles; - if (max_cycles_num == 0) - max_cycles_num++; - els_in_cycle_reserv - = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1) - / (sizeof (set_el_t) * CHAR_BIT)); - els_in_reservs = els_in_cycle_reserv * max_cycles_num; - curr_unique_state_num = 0; - initiate_alt_states (); - VLA_PTR_CREATE (free_states, 1500, "free states"); - state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0); - empty_reserv = alloc_empty_reserv_sets (); -} - -/* Finisging work with the abstract data. */ -static void -finish_states () -{ - VLA_PTR_DELETE (units_container); - htab_delete (state_table); - VLA_PTR_DELETE (free_states); - finish_alt_states (); -} - - - -/* Abstract data `arcs'. */ - -/* List of free arcs. */ -static arc_t first_free_arc; - -#ifndef NDEBUG -/* The following variables is maximal number of allocated nodes - `arc'. */ -static int allocated_arcs_num = 0; -#endif - -/* The function frees node ARC. */ -static void -free_arc (arc) - arc_t arc; -{ - arc->next_out_arc = first_free_arc; - first_free_arc = arc; -} - -/* The function removes and frees ARC staring from FROM_STATE. */ -static void -remove_arc (from_state, arc) - state_t from_state; - arc_t arc; -{ - arc_t prev_arc; - arc_t curr_arc; - - if (arc == NULL) - abort (); - for (prev_arc = NULL, curr_arc = from_state->first_out_arc; - curr_arc != NULL; - prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc) - if (curr_arc == arc) - break; - if (curr_arc == NULL) - abort (); - if (prev_arc == NULL) - from_state->first_out_arc = arc->next_out_arc; - else - prev_arc->next_out_arc = arc->next_out_arc; - free_arc (arc); -} - -/* The functions returns arc with given characteristics (or NULL if - the arc does not exist). */ -static arc_t -find_arc (from_state, to_state, insn) - state_t from_state; - state_t to_state; - ainsn_t insn; -{ - arc_t arc; - - for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc)) - if (arc->to_state == to_state && arc->insn == insn) - return arc; - return NULL; -} - -/* The function adds arc from FROM_STATE to TO_STATE marked by AINSN - and with given STATE_ALTS. The function returns added arc (or - already existing arc). */ -static arc_t -add_arc (from_state, to_state, ainsn, state_alts) - state_t from_state; - state_t to_state; - ainsn_t ainsn; - int state_alts; -{ - arc_t new_arc; - - new_arc = find_arc (from_state, to_state, ainsn); - if (new_arc != NULL) - return new_arc; - if (first_free_arc == NULL) - { -#ifndef NDEBUG - allocated_arcs_num++; -#endif - new_arc = create_node (sizeof (struct arc)); - new_arc->to_state = NULL; - new_arc->insn = NULL; - new_arc->next_out_arc = NULL; - } - else - { - new_arc = first_free_arc; - first_free_arc = first_free_arc->next_out_arc; - } - new_arc->to_state = to_state; - new_arc->insn = ainsn; - ainsn->arc_exists_p = 1; - new_arc->next_out_arc = from_state->first_out_arc; - from_state->first_out_arc = new_arc; - new_arc->next_arc_marked_by_insn = NULL; - new_arc->state_alts = state_alts; - return new_arc; -} - -/* The function returns the first arc starting from STATE. */ -static arc_t -first_out_arc (state) - state_t state; -{ - return state->first_out_arc; -} - -/* The function returns next out arc after ARC. */ -static arc_t -next_out_arc (arc) - arc_t arc; -{ - return arc->next_out_arc; -} - -/* Initialization of the abstract data. */ -static void -initiate_arcs () -{ - first_free_arc = NULL; -} - -/* Finishing work with the abstract data. */ -static void -finish_arcs () -{ -} - - - -/* The page contains abstract data for work with exclusion sets (see - exclusion_set in file rtl.def). */ - -/* The following variable refers to an exclusion set returned by - get_excl_set. This is bit string of length equal to cpu units - number. If exclusion set for given unit contains 1 for a unit, - then simultaneous reservation of the units is prohibited. */ -static reserv_sets_t excl_set; - -/* The array contains exclusion sets for each unit. */ -static reserv_sets_t *unit_excl_set_table; - -/* The following function forms the array containing exclusion sets - for each unit. */ -static void -initiate_excl_sets () -{ - decl_t decl; - reserv_sets_t unit_excl_set; - unit_set_el_t el; - int i; - - obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t)); - excl_set = (reserv_sets_t) obstack_base (&irp); - obstack_finish (&irp); - obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t)); - unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp); - obstack_finish (&irp); - /* Evaluate unit exclusion sets. */ - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_unit) - { - obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t)); - unit_excl_set = (reserv_sets_t) obstack_base (&irp); - obstack_finish (&irp); - memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t)); - for (el = decl->decl.unit.excl_list; - el != NULL; - el = el->next_unit_set_el) - SET_BIT (unit_excl_set, el->unit_decl->unit_num); - unit_excl_set_table [decl->decl.unit.unit_num] = unit_excl_set; - } - } -} - -/* The function sets up and return EXCL_SET which is union of - exclusion sets for each unit in IN_SET. */ -static reserv_sets_t -get_excl_set (in_set) - reserv_sets_t in_set; -{ - int excl_char_num; - int chars_num; - int i; - int start_unit_num; - int unit_num; - - chars_num = els_in_cycle_reserv * sizeof (set_el_t); - memset (excl_set, 0, chars_num); - for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++) - if (((unsigned char *) in_set) [excl_char_num]) - for (i = CHAR_BIT - 1; i >= 0; i--) - if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1) - { - start_unit_num = excl_char_num * CHAR_BIT + i; - if (start_unit_num >= description->units_num) - return excl_set; - for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++) - { - excl_set [unit_num] - |= unit_excl_set_table [start_unit_num] [unit_num]; - } - } - return excl_set; -} - - - -/* The page contains abstract data for work with presence/absence sets - (see presence_set/absence_set in file rtl.def). */ - -/* The following variables refer to correspondingly an presence and an - absence set returned by get_presence_absence_set. This is bit - string of length equal to cpu units number. */ -static reserv_sets_t presence_set, absence_set; - -/* The following arrays contain correspondingly presence and absence - sets for each unit. */ -static reserv_sets_t *unit_presence_set_table, *unit_absence_set_table; - -/* The following function forms the array containing presence and - absence sets for each unit */ -static void -initiate_presence_absence_sets () -{ - decl_t decl; - reserv_sets_t unit_set; - unit_set_el_t el; - int i; - - obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t)); - presence_set = (reserv_sets_t) obstack_base (&irp); - obstack_finish (&irp); - obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t)); - unit_presence_set_table = (reserv_sets_t *) obstack_base (&irp); - obstack_finish (&irp); - obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t)); - absence_set = (reserv_sets_t) obstack_base (&irp); - obstack_finish (&irp); - obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t)); - unit_absence_set_table = (reserv_sets_t *) obstack_base (&irp); - obstack_finish (&irp); - /* Evaluate unit presence/absence sets. */ - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_unit) - { - obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t)); - unit_set = (reserv_sets_t) obstack_base (&irp); - obstack_finish (&irp); - memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t)); - for (el = decl->decl.unit.presence_list; - el != NULL; - el = el->next_unit_set_el) - SET_BIT (unit_set, el->unit_decl->unit_num); - unit_presence_set_table [decl->decl.unit.unit_num] = unit_set; - - obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t)); - unit_set = (reserv_sets_t) obstack_base (&irp); - obstack_finish (&irp); - memset (unit_set, 0, els_in_cycle_reserv * sizeof (set_el_t)); - for (el = decl->decl.unit.absence_list; - el != NULL; - el = el->next_unit_set_el) - SET_BIT (unit_set, el->unit_decl->unit_num); - unit_absence_set_table [decl->decl.unit.unit_num] = unit_set; - } - } -} - -/* The function sets up and return PRESENCE_SET (if PRESENCE_P) or - ABSENCE_SET which is union of corresponding sets for each unit in - IN_SET. */ -static reserv_sets_t -get_presence_absence_set (in_set, presence_p) - reserv_sets_t in_set; - int presence_p; -{ - int char_num; - int chars_num; - int i; - int start_unit_num; - int unit_num; - - chars_num = els_in_cycle_reserv * sizeof (set_el_t); - if (presence_p) - memset (presence_set, 0, chars_num); - else - memset (absence_set, 0, chars_num); - for (char_num = 0; char_num < chars_num; char_num++) - if (((unsigned char *) in_set) [char_num]) - for (i = CHAR_BIT - 1; i >= 0; i--) - if ((((unsigned char *) in_set) [char_num] >> i) & 1) - { - start_unit_num = char_num * CHAR_BIT + i; - if (start_unit_num >= description->units_num) - return (presence_p ? presence_set : absence_set); - for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++) - if (presence_p) - presence_set [unit_num] - |= unit_presence_set_table [start_unit_num] [unit_num]; - else - absence_set [unit_num] - |= unit_absence_set_table [start_unit_num] [unit_num]; - } - return (presence_p ? presence_set : absence_set); -} - - - -/* This page contains code for transformation of original reservations - described in .md file. The main goal of transformations is - simplifying reservation and lifting up all `|' on the top of IR - reservation representation. */ - - -/* The following function makes copy of IR representation of - reservation. The function also substitutes all reservations - defined by define_reservation by corresponding value during making - the copy. */ -static regexp_t -copy_insn_regexp (regexp) - regexp_t regexp; -{ - regexp_t result; - int i; - - if (regexp->mode == rm_reserv) - result = copy_insn_regexp (regexp->regexp.reserv.reserv_decl->regexp); - else if (regexp->mode == rm_unit) - result = copy_node (regexp, sizeof (struct regexp)); - else if (regexp->mode == rm_repeat) - { - result = copy_node (regexp, sizeof (struct regexp)); - result->regexp.repeat.regexp - = copy_insn_regexp (regexp->regexp.repeat.regexp); - } - else if (regexp->mode == rm_sequence) - { - result = copy_node (regexp, - sizeof (struct regexp) + sizeof (regexp_t) - * (regexp->regexp.sequence.regexps_num - 1)); - for (i = 0; i < regexp->regexp.sequence.regexps_num; i++) - result->regexp.sequence.regexps [i] - = copy_insn_regexp (regexp->regexp.sequence.regexps [i]); - } - else if (regexp->mode == rm_allof) - { - result = copy_node (regexp, - sizeof (struct regexp) + sizeof (regexp_t) - * (regexp->regexp.allof.regexps_num - 1)); - for (i = 0; i < regexp->regexp.allof.regexps_num; i++) - result->regexp.allof.regexps [i] - = copy_insn_regexp (regexp->regexp.allof.regexps [i]); - } - else if (regexp->mode == rm_oneof) - { - result = copy_node (regexp, - sizeof (struct regexp) + sizeof (regexp_t) - * (regexp->regexp.oneof.regexps_num - 1)); - for (i = 0; i < regexp->regexp.oneof.regexps_num; i++) - result->regexp.oneof.regexps [i] - = copy_insn_regexp (regexp->regexp.oneof.regexps [i]); - } - else - { - if (regexp->mode != rm_nothing) - abort (); - result = copy_node (regexp, sizeof (struct regexp)); - } - return result; -} - -/* The following variable is set up 1 if a transformation has been - applied. */ -static int regexp_transformed_p; - -/* The function makes transformation - A*N -> A, A, ... */ -static regexp_t -transform_1 (regexp) - regexp_t regexp; -{ - int i; - int repeat_num; - regexp_t operand; - pos_t pos; - - if (regexp->mode == rm_repeat) - { - repeat_num = regexp->regexp.repeat.repeat_num; - if (repeat_num <= 1) - abort (); - operand = regexp->regexp.repeat.regexp; - pos = regexp->mode; - regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t) - * (repeat_num - 1)); - regexp->mode = rm_sequence; - regexp->pos = pos; - regexp->regexp.sequence.regexps_num = repeat_num; - for (i = 0; i < repeat_num; i++) - regexp->regexp.sequence.regexps [i] = copy_insn_regexp (operand); - regexp_transformed_p = 1; - } - return regexp; -} - -/* The function makes transformations - ...,(A,B,...),C,... -> ...,A,B,...,C,... - ...+(A+B+...)+C+... -> ...+A+B+...+C+... - ...|(A|B|...)|C|... -> ...|A|B|...|C|... */ -static regexp_t -transform_2 (regexp) - regexp_t regexp; -{ - if (regexp->mode == rm_sequence) - { - regexp_t sequence; - regexp_t result; - int sequence_index; - int i, j; - - for (i = 0; i < regexp->regexp.sequence.regexps_num; i++) - if (regexp->regexp.sequence.regexps [i]->mode == rm_sequence) - { - sequence_index = i; - sequence = regexp->regexp.sequence.regexps [i]; - break; - } - if (i < regexp->regexp.sequence.regexps_num) - { - if (sequence->regexp.sequence.regexps_num <= 1 - || regexp->regexp.sequence.regexps_num <= 1) - abort (); - result = create_node (sizeof (struct regexp) - + sizeof (regexp_t) - * (regexp->regexp.sequence.regexps_num - + sequence->regexp.sequence.regexps_num - - 2)); - result->mode = rm_sequence; - result->pos = regexp->pos; - result->regexp.sequence.regexps_num - = (regexp->regexp.sequence.regexps_num - + sequence->regexp.sequence.regexps_num - 1); - for (i = 0; i < regexp->regexp.sequence.regexps_num; i++) - if (i < sequence_index) - result->regexp.sequence.regexps [i] - = copy_insn_regexp (regexp->regexp.sequence.regexps [i]); - else if (i > sequence_index) - result->regexp.sequence.regexps - [i + sequence->regexp.sequence.regexps_num - 1] - = copy_insn_regexp (regexp->regexp.sequence.regexps [i]); - else - for (j = 0; j < sequence->regexp.sequence.regexps_num; j++) - result->regexp.sequence.regexps [i + j] - = copy_insn_regexp (sequence->regexp.sequence.regexps [j]); - regexp_transformed_p = 1; - regexp = result; - } - } - else if (regexp->mode == rm_allof) - { - regexp_t allof; - regexp_t result; - int allof_index; - int i, j; - - for (i = 0; i < regexp->regexp.allof.regexps_num; i++) - if (regexp->regexp.allof.regexps [i]->mode == rm_allof) - { - allof_index = i; - allof = regexp->regexp.allof.regexps [i]; - break; - } - if (i < regexp->regexp.allof.regexps_num) - { - if (allof->regexp.allof.regexps_num <= 1 - || regexp->regexp.allof.regexps_num <= 1) - abort (); - result = create_node (sizeof (struct regexp) - + sizeof (regexp_t) - * (regexp->regexp.allof.regexps_num - + allof->regexp.allof.regexps_num - 2)); - result->mode = rm_allof; - result->pos = regexp->pos; - result->regexp.allof.regexps_num - = (regexp->regexp.allof.regexps_num - + allof->regexp.allof.regexps_num - 1); - for (i = 0; i < regexp->regexp.allof.regexps_num; i++) - if (i < allof_index) - result->regexp.allof.regexps [i] - = copy_insn_regexp (regexp->regexp.allof.regexps [i]); - else if (i > allof_index) - result->regexp.allof.regexps - [i + allof->regexp.allof.regexps_num - 1] - = copy_insn_regexp (regexp->regexp.allof.regexps [i]); - else - for (j = 0; j < allof->regexp.allof.regexps_num; j++) - result->regexp.allof.regexps [i + j] - = copy_insn_regexp (allof->regexp.allof.regexps [j]); - regexp_transformed_p = 1; - regexp = result; - } - } - else if (regexp->mode == rm_oneof) - { - regexp_t oneof; - regexp_t result; - int oneof_index; - int i, j; - - for (i = 0; i < regexp->regexp.oneof.regexps_num; i++) - if (regexp->regexp.oneof.regexps [i]->mode == rm_oneof) - { - oneof_index = i; - oneof = regexp->regexp.oneof.regexps [i]; - break; - } - if (i < regexp->regexp.oneof.regexps_num) - { - if (oneof->regexp.oneof.regexps_num <= 1 - || regexp->regexp.oneof.regexps_num <= 1) - abort (); - result = create_node (sizeof (struct regexp) - + sizeof (regexp_t) - * (regexp->regexp.oneof.regexps_num - + oneof->regexp.oneof.regexps_num - 2)); - result->mode = rm_oneof; - result->pos = regexp->pos; - result->regexp.oneof.regexps_num - = (regexp->regexp.oneof.regexps_num - + oneof->regexp.oneof.regexps_num - 1); - for (i = 0; i < regexp->regexp.oneof.regexps_num; i++) - if (i < oneof_index) - result->regexp.oneof.regexps [i] - = copy_insn_regexp (regexp->regexp.oneof.regexps [i]); - else if (i > oneof_index) - result->regexp.oneof.regexps - [i + oneof->regexp.oneof.regexps_num - 1] - = copy_insn_regexp (regexp->regexp.oneof.regexps [i]); - else - for (j = 0; j < oneof->regexp.oneof.regexps_num; j++) - result->regexp.oneof.regexps [i + j] - = copy_insn_regexp (oneof->regexp.oneof.regexps [j]); - regexp_transformed_p = 1; - regexp = result; - } - } - return regexp; -} - -/* The function makes transformations - ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|... - ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|... */ -static regexp_t -transform_3 (regexp) - regexp_t regexp; -{ - if (regexp->mode == rm_sequence) - { - regexp_t oneof; - int oneof_index; - regexp_t result; - regexp_t sequence; - int i, j; - - for (i = 0; i < regexp->regexp.sequence.regexps_num; i++) - if (regexp->regexp.sequence.regexps [i]->mode == rm_oneof) - { - oneof_index = i; - oneof = regexp->regexp.sequence.regexps [i]; - break; - } - if (i < regexp->regexp.sequence.regexps_num) - { - if (oneof->regexp.oneof.regexps_num <= 1 - || regexp->regexp.sequence.regexps_num <= 1) - abort (); - result = create_node (sizeof (struct regexp) - + sizeof (regexp_t) - * (oneof->regexp.oneof.regexps_num - 1)); - result->mode = rm_oneof; - result->pos = regexp->pos; - result->regexp.oneof.regexps_num = oneof->regexp.oneof.regexps_num; - for (i = 0; i < result->regexp.oneof.regexps_num; i++) - { - sequence - = create_node (sizeof (struct regexp) - + sizeof (regexp_t) - * (regexp->regexp.sequence.regexps_num - 1)); - sequence->mode = rm_sequence; - sequence->pos = regexp->pos; - sequence->regexp.sequence.regexps_num - = regexp->regexp.sequence.regexps_num; - result->regexp.oneof.regexps [i] = sequence; - for (j = 0; j < sequence->regexp.sequence.regexps_num; j++) - if (j != oneof_index) - sequence->regexp.sequence.regexps [j] - = copy_insn_regexp (regexp->regexp.sequence.regexps [j]); - else - sequence->regexp.sequence.regexps [j] - = copy_insn_regexp (oneof->regexp.oneof.regexps [i]); - } - regexp_transformed_p = 1; - regexp = result; - } - } - else if (regexp->mode == rm_allof) - { - regexp_t oneof; - int oneof_index; - regexp_t result; - regexp_t allof; - int i, j; - - for (i = 0; i < regexp->regexp.allof.regexps_num; i++) - if (regexp->regexp.allof.regexps [i]->mode == rm_oneof) - { - oneof_index = i; - oneof = regexp->regexp.allof.regexps [i]; - break; - } - if (i < regexp->regexp.allof.regexps_num) - { - if (oneof->regexp.oneof.regexps_num <= 1 - || regexp->regexp.allof.regexps_num <= 1) - abort (); - result = create_node (sizeof (struct regexp) - + sizeof (regexp_t) - * (oneof->regexp.oneof.regexps_num - 1)); - result->mode = rm_oneof; - result->pos = regexp->pos; - result->regexp.oneof.regexps_num = oneof->regexp.oneof.regexps_num; - for (i = 0; i < result->regexp.oneof.regexps_num; i++) - { - allof - = create_node (sizeof (struct regexp) - + sizeof (regexp_t) - * (regexp->regexp.allof.regexps_num - 1)); - allof->mode = rm_allof; - allof->pos = regexp->pos; - allof->regexp.allof.regexps_num - = regexp->regexp.allof.regexps_num; - result->regexp.oneof.regexps [i] = allof; - for (j = 0; j < allof->regexp.allof.regexps_num; j++) - if (j != oneof_index) - allof->regexp.allof.regexps [j] - = copy_insn_regexp (regexp->regexp.allof.regexps [j]); - else - allof->regexp.allof.regexps [j] - = copy_insn_regexp (oneof->regexp.oneof.regexps [i]); - } - regexp_transformed_p = 1; - regexp = result; - } - } - return regexp; -} - -/* The function traverses IR of reservation and applies transformations - implemented by FUNC. */ -static regexp_t -regexp_transform_func (regexp, func) - regexp_t regexp; - regexp_t (*func) PARAMS ((regexp_t regexp)); -{ - int i; - - if (regexp->mode == rm_sequence) - for (i = 0; i < regexp->regexp.sequence.regexps_num; i++) - regexp->regexp.sequence.regexps [i] - = regexp_transform_func (regexp->regexp.sequence.regexps [i], func); - else if (regexp->mode == rm_allof) - for (i = 0; i < regexp->regexp.allof.regexps_num; i++) - regexp->regexp.allof.regexps [i] - = regexp_transform_func (regexp->regexp.allof.regexps [i], func); - else if (regexp->mode == rm_oneof) - for (i = 0; i < regexp->regexp.oneof.regexps_num; i++) - regexp->regexp.oneof.regexps [i] - = regexp_transform_func (regexp->regexp.oneof.regexps [i], func); - else if (regexp->mode == rm_repeat) - regexp->regexp.repeat.regexp - = regexp_transform_func (regexp->regexp.repeat.regexp, func); - else if (regexp->mode != rm_nothing && regexp->mode != rm_unit) - abort (); - return (*func) (regexp); -} - -/* The function applies all transformations for IR representation of - reservation REGEXP. */ -static regexp_t -transform_regexp (regexp) - regexp_t regexp; -{ - regexp = regexp_transform_func (regexp, transform_1); - do - { - regexp_transformed_p = 0; - regexp = regexp_transform_func (regexp, transform_2); - regexp = regexp_transform_func (regexp, transform_3); - } - while (regexp_transformed_p); - return regexp; -} - -/* The function applys all transformations for reservations of all - insn declarations. */ -static void -transform_insn_regexps () -{ - decl_t decl; - int i; - - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl) - decl->decl.insn_reserv.transformed_regexp - = transform_regexp (copy_insn_regexp - (decl->decl.insn_reserv.regexp)); - } -} - - - -/* The page contains code for building alt_states (see comments for - IR) describing all possible insns reservations of an automaton. */ - -/* Current state being formed for which the current alt_state - refers. */ -static state_t state_being_formed; - -/* Current alt_state being formed. */ -static alt_state_t alt_state_being_formed; - -/* This recursive function processes `,' and units in reservation - REGEXP for forming alt_states of AUTOMATON. It is believed that - CURR_CYCLE is start cycle of all reservation REGEXP. */ -static int -process_seq_for_forming_states (regexp, automaton, curr_cycle) - regexp_t regexp; - automaton_t automaton; - int curr_cycle; -{ - int i; - - if (regexp == NULL) - return curr_cycle; - else if (regexp->mode == rm_unit) - { - if (regexp->regexp.unit.unit_decl->corresponding_automaton_num - == automaton->automaton_order_num) - set_state_reserv (state_being_formed, curr_cycle, - regexp->regexp.unit.unit_decl->unit_num); - return curr_cycle; - } - else if (regexp->mode == rm_sequence) - { - for (i = 0; i < regexp->regexp.sequence.regexps_num; i++) - curr_cycle - = process_seq_for_forming_states - (regexp->regexp.sequence.regexps [i], automaton, curr_cycle) + 1; - return curr_cycle; - } - else if (regexp->mode == rm_allof) - { - int finish_cycle = 0; - int cycle; - - for (i = 0; i < regexp->regexp.allof.regexps_num; i++) - { - cycle - = process_seq_for_forming_states (regexp->regexp.allof.regexps [i], - automaton, curr_cycle); - if (finish_cycle < cycle) - finish_cycle = cycle; - } - return finish_cycle; - } - else - { - if (regexp->mode != rm_nothing) - abort (); - return curr_cycle; - } -} - -/* This recursive function finishes forming ALT_STATE of AUTOMATON and - inserts alt_state into the table. */ -static void -finish_forming_alt_state (alt_state, automaton) - alt_state_t alt_state; - automaton_t automaton ATTRIBUTE_UNUSED; -{ - state_t state_in_table; - state_t corresponding_state; - - corresponding_state = alt_state->state; - state_in_table = insert_state (corresponding_state); - if (state_in_table != corresponding_state) - { - free_state (corresponding_state); - alt_state->state = state_in_table; - } -} - -/* The following variable value is current automaton insn for whose - reservation the alt states are created. */ -static ainsn_t curr_ainsn; - -/* This recursive function processes `|' in reservation REGEXP for - forming alt_states of AUTOMATON. List of the alt states should - have the same order as in the description. */ -static void -process_alts_for_forming_states (regexp, automaton, inside_oneof_p) - regexp_t regexp; - automaton_t automaton; - int inside_oneof_p; -{ - int i; - - if (regexp->mode != rm_oneof) - { - alt_state_being_formed = get_free_alt_state (); - state_being_formed = get_free_state (1, automaton); - alt_state_being_formed->state = state_being_formed; - /* We inserts in reverse order but we process alternatives also - in reverse order. So we have the same order of alternative - as in the description. */ - alt_state_being_formed->next_alt_state = curr_ainsn->alt_states; - curr_ainsn->alt_states = alt_state_being_formed; - (void) process_seq_for_forming_states (regexp, automaton, 0); - finish_forming_alt_state (alt_state_being_formed, automaton); - } - else - { - if (inside_oneof_p) - abort (); - /* We processes it in reverse order to get list with the same - order as in the description. See also the previous - commentary. */ - for (i = regexp->regexp.oneof.regexps_num - 1; i >= 0; i--) - process_alts_for_forming_states (regexp->regexp.oneof.regexps [i], - automaton, 1); - } -} - -/* Create nodes alt_state for all AUTOMATON insns. */ -static void -create_alt_states (automaton) - automaton_t automaton; -{ - struct insn_reserv_decl *reserv_decl; - - for (curr_ainsn = automaton->ainsn_list; - curr_ainsn != NULL; - curr_ainsn = curr_ainsn->next_ainsn) - { - reserv_decl = curr_ainsn->insn_reserv_decl; - if (reserv_decl != &advance_cycle_insn_decl->decl.insn_reserv) - { - curr_ainsn->alt_states = NULL; - process_alts_for_forming_states (reserv_decl->transformed_regexp, - automaton, 0); - curr_ainsn->sorted_alt_states - = uniq_sort_alt_states (curr_ainsn->alt_states); - } - } -} - - - -/* The page contains major code for building DFA(s) for fast pipeline - hazards recognition. */ - -/* The function forms list of ainsns of AUTOMATON with the same - reservation. */ -static void -form_ainsn_with_same_reservs (automaton) - automaton_t automaton; -{ - ainsn_t curr_ainsn; - size_t i; - vla_ptr_t first_insns; - vla_ptr_t last_insns; - - VLA_PTR_CREATE (first_insns, 150, "first insns with the same reservs"); - VLA_PTR_CREATE (last_insns, 150, "last insns with the same reservs"); - for (curr_ainsn = automaton->ainsn_list; - curr_ainsn != NULL; - curr_ainsn = curr_ainsn->next_ainsn) - if (curr_ainsn->insn_reserv_decl - == &advance_cycle_insn_decl->decl.insn_reserv) - { - curr_ainsn->next_same_reservs_insn = NULL; - curr_ainsn->first_insn_with_same_reservs = 1; - } - else - { - for (i = 0; i < VLA_PTR_LENGTH (first_insns); i++) - if (alt_states_eq - (curr_ainsn->sorted_alt_states, - ((ainsn_t) VLA_PTR (first_insns, i))->sorted_alt_states)) - break; - curr_ainsn->next_same_reservs_insn = NULL; - if (i < VLA_PTR_LENGTH (first_insns)) - { - curr_ainsn->first_insn_with_same_reservs = 0; - ((ainsn_t) VLA_PTR (last_insns, i))->next_same_reservs_insn - = curr_ainsn; - VLA_PTR (last_insns, i) = curr_ainsn; - } - else - { - VLA_PTR_ADD (first_insns, curr_ainsn); - VLA_PTR_ADD (last_insns, curr_ainsn); - curr_ainsn->first_insn_with_same_reservs = 1; - } - } - VLA_PTR_DELETE (first_insns); - VLA_PTR_DELETE (last_insns); -} - -/* The following function creates all states of nondeterministic (if - NDFA_FLAG has nonzero value) or deterministic AUTOMATON. */ -static void -make_automaton (automaton) - automaton_t automaton; -{ - ainsn_t ainsn; - struct insn_reserv_decl *insn_reserv_decl; - alt_state_t alt_state; - state_t state; - state_t start_state; - state_t state2; - ainsn_t advance_cycle_ainsn; - arc_t added_arc; - vla_ptr_t state_stack; - - VLA_PTR_CREATE (state_stack, 150, "state stack"); - /* Create the start state (empty state). */ - start_state = insert_state (get_free_state (1, automaton)); - automaton->start_state = start_state; - start_state->it_was_placed_in_stack_for_NDFA_forming = 1; - VLA_PTR_ADD (state_stack, start_state); - while (VLA_PTR_LENGTH (state_stack) != 0) - { - state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1); - VLA_PTR_SHORTEN (state_stack, 1); - advance_cycle_ainsn = NULL; - for (ainsn = automaton->ainsn_list; - ainsn != NULL; - ainsn = ainsn->next_ainsn) - if (ainsn->first_insn_with_same_reservs) - { - insn_reserv_decl = ainsn->insn_reserv_decl; - if (insn_reserv_decl != &advance_cycle_insn_decl->decl.insn_reserv) - { - /* We process alt_states in the same order as they are - present in the description. */ - added_arc = NULL; - for (alt_state = ainsn->alt_states; - alt_state != NULL; - alt_state = alt_state->next_alt_state) - { - state2 = alt_state->state; - if (!intersected_state_reservs_p (state, state2)) - { - state2 = states_union (state, state2); - if (!state2->it_was_placed_in_stack_for_NDFA_forming) - { - state2->it_was_placed_in_stack_for_NDFA_forming - = 1; - VLA_PTR_ADD (state_stack, state2); - } - added_arc = add_arc (state, state2, ainsn, 1); - if (!ndfa_flag) - break; - } - } - if (!ndfa_flag && added_arc != NULL) - { - added_arc->state_alts = 0; - for (alt_state = ainsn->alt_states; - alt_state != NULL; - alt_state = alt_state->next_alt_state) - { - state2 = alt_state->state; - if (!intersected_state_reservs_p (state, state2)) - added_arc->state_alts++; - } - } - } - else - advance_cycle_ainsn = ainsn; - } - /* Add transition to advance cycle. */ - state2 = state_shift (state); - if (!state2->it_was_placed_in_stack_for_NDFA_forming) - { - state2->it_was_placed_in_stack_for_NDFA_forming = 1; - VLA_PTR_ADD (state_stack, state2); - } - if (advance_cycle_ainsn == NULL) - abort (); - add_arc (state, state2, advance_cycle_ainsn, 1); - } - VLA_PTR_DELETE (state_stack); -} - -/* Foms lists of all arcs of STATE marked by the same ainsn. */ -static void -form_arcs_marked_by_insn (state) - state_t state; -{ - decl_t decl; - arc_t arc; - int i; - - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_insn_reserv) - decl->decl.insn_reserv.arcs_marked_by_insn = NULL; - } - for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) - { - if (arc->insn == NULL) - abort (); - arc->next_arc_marked_by_insn - = arc->insn->insn_reserv_decl->arcs_marked_by_insn; - arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc; - } -} - -/* The function creates composed state (see comments for IR) from - ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the - same insn. If the composed state is not in STATE_STACK yet, it is - popped to STATE_STACK. */ -static void -create_composed_state (original_state, arcs_marked_by_insn, state_stack) - state_t original_state; - arc_t arcs_marked_by_insn; - vla_ptr_t *state_stack; -{ - state_t state; - alt_state_t curr_alt_state; - alt_state_t new_alt_state; - arc_t curr_arc; - arc_t next_arc; - state_t state_in_table; - state_t temp_state; - alt_state_t canonical_alt_states_list; - int alts_number; - - if (arcs_marked_by_insn == NULL) - return; - if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL) - state = arcs_marked_by_insn->to_state; - else - { - if (!ndfa_flag) - abort (); - /* Create composed state. */ - state = get_free_state (0, arcs_marked_by_insn->to_state->automaton); - curr_alt_state = NULL; - for (curr_arc = arcs_marked_by_insn; - curr_arc != NULL; - curr_arc = curr_arc->next_arc_marked_by_insn) - { - new_alt_state = get_free_alt_state (); - new_alt_state->next_alt_state = curr_alt_state; - new_alt_state->state = curr_arc->to_state; - if (curr_arc->to_state->component_states != NULL) - abort (); - curr_alt_state = new_alt_state; - } - /* There are not identical sets in the alt state list. */ - canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state); - if (canonical_alt_states_list->next_sorted_alt_state == NULL) - { - temp_state = state; - state = canonical_alt_states_list->state; - free_state (temp_state); - } - else - { - state->component_states = canonical_alt_states_list; - state_in_table = insert_state (state); - if (state_in_table != state) - { - if (!state_in_table->it_was_placed_in_stack_for_DFA_forming) - abort (); - free_state (state); - state = state_in_table; - } - else - { - if (state->it_was_placed_in_stack_for_DFA_forming) - abort (); - for (curr_alt_state = state->component_states; - curr_alt_state != NULL; - curr_alt_state = curr_alt_state->next_sorted_alt_state) - for (curr_arc = first_out_arc (curr_alt_state->state); - curr_arc != NULL; - curr_arc = next_out_arc (curr_arc)) - add_arc (state, curr_arc->to_state, curr_arc->insn, 1); - } - arcs_marked_by_insn->to_state = state; - for (alts_number = 0, - curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn; - curr_arc != NULL; - curr_arc = next_arc) - { - next_arc = curr_arc->next_arc_marked_by_insn; - remove_arc (original_state, curr_arc); - alts_number++; - } - arcs_marked_by_insn->state_alts = alts_number; - } - } - if (!state->it_was_placed_in_stack_for_DFA_forming) - { - state->it_was_placed_in_stack_for_DFA_forming = 1; - VLA_PTR_ADD (*state_stack, state); - } -} - -/* The function transformes nondeterminstic AUTOMATON into - deterministic. */ -static void -NDFA_to_DFA (automaton) - automaton_t automaton; -{ - state_t start_state; - state_t state; - decl_t decl; - vla_ptr_t state_stack; - int i; - - VLA_PTR_CREATE (state_stack, 150, "state stack"); - /* Create the start state (empty state). */ - start_state = automaton->start_state; - start_state->it_was_placed_in_stack_for_DFA_forming = 1; - VLA_PTR_ADD (state_stack, start_state); - while (VLA_PTR_LENGTH (state_stack) != 0) - { - state = VLA_PTR (state_stack, VLA_PTR_LENGTH (state_stack) - 1); - VLA_PTR_SHORTEN (state_stack, 1); - form_arcs_marked_by_insn (state); - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_insn_reserv) - create_composed_state - (state, decl->decl.insn_reserv.arcs_marked_by_insn, - &state_stack); - } - } - VLA_PTR_DELETE (state_stack); -} - -/* The following variable value is current number (1, 2, ...) of passing - graph of states. */ -static int curr_state_graph_pass_num; - -/* This recursive function passes all states achieved from START_STATE - and applies APPLIED_FUNC to them. */ -static void -pass_state_graph (start_state, applied_func) - state_t start_state; - void (*applied_func) PARAMS ((state_t state)); -{ - arc_t arc; - - if (start_state->pass_num == curr_state_graph_pass_num) - return; - start_state->pass_num = curr_state_graph_pass_num; - (*applied_func) (start_state); - for (arc = first_out_arc (start_state); - arc != NULL; - arc = next_out_arc (arc)) - pass_state_graph (arc->to_state, applied_func); -} - -/* This recursive function passes all states of AUTOMATON and applies - APPLIED_FUNC to them. */ -static void -pass_states (automaton, applied_func) - automaton_t automaton; - void (*applied_func) PARAMS ((state_t state)); -{ - curr_state_graph_pass_num++; - pass_state_graph (automaton->start_state, applied_func); -} - -/* The function initializes code for passing of all states. */ -static void -initiate_pass_states () -{ - curr_state_graph_pass_num = 0; -} - -/* The following vla is used for storing pointers to all achieved - states. */ -static vla_ptr_t all_achieved_states; - -/* This function is called by function pass_states to add an achieved - STATE. */ -static void -add_achieved_state (state) - state_t state; -{ - VLA_PTR_ADD (all_achieved_states, state); -} - -/* The function sets up equivalence numbers of insns which mark all - out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has - nonzero value) or by equiv_class_num_2 of the destination state. - The function returns number of out arcs of STATE. */ -static int -set_out_arc_insns_equiv_num (state, odd_iteration_flag) - state_t state; - int odd_iteration_flag; -{ - int state_out_arcs_num; - arc_t arc; - - state_out_arcs_num = 0; - for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) - { - if (arc->insn->insn_reserv_decl->equiv_class_num != 0 - || arc->insn->insn_reserv_decl->state_alts != 0) - abort (); - state_out_arcs_num++; - arc->insn->insn_reserv_decl->equiv_class_num - = (odd_iteration_flag - ? arc->to_state->equiv_class_num_1 - : arc->to_state->equiv_class_num_2); - arc->insn->insn_reserv_decl->state_alts = arc->state_alts; - if (arc->insn->insn_reserv_decl->equiv_class_num == 0 - || arc->insn->insn_reserv_decl->state_alts <= 0) - abort (); - } - return state_out_arcs_num; -} - -/* The function clears equivalence numbers and alt_states in all insns - which mark all out arcs of STATE. */ -static void -clear_arc_insns_equiv_num (state) - state_t state; -{ - arc_t arc; - - for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) - { - arc->insn->insn_reserv_decl->equiv_class_num = 0; - arc->insn->insn_reserv_decl->state_alts = 0; - } -} - -/* The function copies pointers to equivalent states from vla FROM - into vla TO. */ -static void -copy_equiv_class (to, from) - vla_ptr_t *to; - const vla_ptr_t *from; -{ - state_t *class_ptr; - - VLA_PTR_NULLIFY (*to); - for (class_ptr = VLA_PTR_BEGIN (*from); - class_ptr <= (state_t *) VLA_PTR_LAST (*from); - class_ptr++) - VLA_PTR_ADD (*to, *class_ptr); -} - -/* The function returns nonzero value if STATE is not equivalent to - another state from the same current partition on equivalence - classes Another state has ORIGINAL_STATE_OUT_ARCS_NUM number of - output arcs. Iteration of making equivalence partition is defined - by ODD_ITERATION_FLAG. */ -static int -state_is_differed (state, original_state_out_arcs_num, odd_iteration_flag) - state_t state; - int original_state_out_arcs_num; - int odd_iteration_flag; -{ - arc_t arc; - int state_out_arcs_num; - - state_out_arcs_num = 0; - for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) - { - state_out_arcs_num++; - if ((odd_iteration_flag - ? arc->to_state->equiv_class_num_1 - : arc->to_state->equiv_class_num_2) - != arc->insn->insn_reserv_decl->equiv_class_num - || (arc->insn->insn_reserv_decl->state_alts != arc->state_alts)) - return 1; - } - return state_out_arcs_num != original_state_out_arcs_num; -} - -/* The function makes initial partition of STATES on equivalent - classes. */ -static state_t -init_equiv_class (states, states_num) - state_t *states; - int states_num; -{ - state_t *state_ptr; - state_t result_equiv_class; - - result_equiv_class = NULL; - for (state_ptr = states; state_ptr < states + states_num; state_ptr++) - { - (*state_ptr)->equiv_class_num_1 = 1; - (*state_ptr)->next_equiv_class_state = result_equiv_class; - result_equiv_class = *state_ptr; - } - return result_equiv_class; -} - -/* The function processes equivalence class given by its pointer - EQUIV_CLASS_PTR on odd iteration if ODD_ITERATION_FLAG. If there - are not equvalent states, the function partitions the class - removing nonequivalent states and placing them in - *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans - assigns it to the state equivalence number. If the class has been - partitioned, the function returns nonzero value. */ -static int -partition_equiv_class (equiv_class_ptr, odd_iteration_flag, - next_iteration_classes, new_equiv_class_num_ptr) - state_t *equiv_class_ptr; - int odd_iteration_flag; - vla_ptr_t *next_iteration_classes; - int *new_equiv_class_num_ptr; -{ - state_t new_equiv_class; - int partition_p; - state_t first_state; - state_t curr_state; - state_t prev_state; - state_t next_state; - int out_arcs_num; - - partition_p = 0; - if (*equiv_class_ptr == NULL) - abort (); - for (first_state = *equiv_class_ptr; - first_state != NULL; - first_state = new_equiv_class) - { - new_equiv_class = NULL; - if (first_state->next_equiv_class_state != NULL) - { - /* There are more one states in the class equivalence. */ - out_arcs_num = set_out_arc_insns_equiv_num (first_state, - odd_iteration_flag); - for (prev_state = first_state, - curr_state = first_state->next_equiv_class_state; - curr_state != NULL; - curr_state = next_state) - { - next_state = curr_state->next_equiv_class_state; - if (state_is_differed (curr_state, out_arcs_num, - odd_iteration_flag)) - { - /* Remove curr state from the class equivalence. */ - prev_state->next_equiv_class_state = next_state; - /* Add curr state to the new class equivalence. */ - curr_state->next_equiv_class_state = new_equiv_class; - if (new_equiv_class == NULL) - (*new_equiv_class_num_ptr)++; - if (odd_iteration_flag) - curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr; - else - curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr; - new_equiv_class = curr_state; - partition_p = 1; - } - else - prev_state = curr_state; - } - clear_arc_insns_equiv_num (first_state); - } - if (new_equiv_class != NULL) - VLA_PTR_ADD (*next_iteration_classes, new_equiv_class); - } - return partition_p; -} - -/* The function finds equivalent states of AUTOMATON. */ -static void -evaluate_equiv_classes (automaton, equiv_classes) - automaton_t automaton; - vla_ptr_t *equiv_classes; -{ - state_t new_equiv_class; - int new_equiv_class_num; - int odd_iteration_flag; - int finish_flag; - vla_ptr_t next_iteration_classes; - state_t *equiv_class_ptr; - state_t *state_ptr; - - VLA_PTR_CREATE (all_achieved_states, 1500, "all achieved states"); - pass_states (automaton, add_achieved_state); - new_equiv_class = init_equiv_class (VLA_PTR_BEGIN (all_achieved_states), - VLA_PTR_LENGTH (all_achieved_states)); - odd_iteration_flag = 0; - new_equiv_class_num = 1; - VLA_PTR_CREATE (next_iteration_classes, 150, "next iteration classes"); - VLA_PTR_ADD (next_iteration_classes, new_equiv_class); - do - { - odd_iteration_flag = !odd_iteration_flag; - finish_flag = 1; - copy_equiv_class (equiv_classes, &next_iteration_classes); - /* Transfer equiv numbers for the next iteration. */ - for (state_ptr = VLA_PTR_BEGIN (all_achieved_states); - state_ptr <= (state_t *) VLA_PTR_LAST (all_achieved_states); - state_ptr++) - if (odd_iteration_flag) - (*state_ptr)->equiv_class_num_2 = (*state_ptr)->equiv_class_num_1; - else - (*state_ptr)->equiv_class_num_1 = (*state_ptr)->equiv_class_num_2; - for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes); - equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes); - equiv_class_ptr++) - if (partition_equiv_class (equiv_class_ptr, odd_iteration_flag, - &next_iteration_classes, - &new_equiv_class_num)) - finish_flag = 0; - } - while (!finish_flag); - VLA_PTR_DELETE (next_iteration_classes); - VLA_PTR_DELETE (all_achieved_states); -} - -/* The function merges equivalent states of AUTOMATON. */ -static void -merge_states (automaton, equiv_classes) - automaton_t automaton; - vla_ptr_t *equiv_classes; -{ - state_t *equiv_class_ptr; - state_t curr_state; - state_t new_state; - state_t first_class_state; - alt_state_t alt_states; - alt_state_t new_alt_state; - arc_t curr_arc; - arc_t next_arc; - - /* Create states corresponding to equivalence classes containing two - or more states. */ - for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes); - equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes); - equiv_class_ptr++) - if ((*equiv_class_ptr)->next_equiv_class_state != NULL) - { - /* There are more one states in the class equivalence. */ - /* Create new compound state. */ - new_state = get_free_state (0, automaton); - alt_states = NULL; - first_class_state = *equiv_class_ptr; - for (curr_state = first_class_state; - curr_state != NULL; - curr_state = curr_state->next_equiv_class_state) - { - curr_state->equiv_class_state = new_state; - new_alt_state = get_free_alt_state (); - new_alt_state->state = curr_state; - new_alt_state->next_sorted_alt_state = alt_states; - alt_states = new_alt_state; - } - new_state->component_states = alt_states; - } - else - (*equiv_class_ptr)->equiv_class_state = *equiv_class_ptr; - for (equiv_class_ptr = VLA_PTR_BEGIN (*equiv_classes); - equiv_class_ptr <= (state_t *) VLA_PTR_LAST (*equiv_classes); - equiv_class_ptr++) - if ((*equiv_class_ptr)->next_equiv_class_state != NULL) - { - first_class_state = *equiv_class_ptr; - /* Create new arcs output from the state corresponding to - equiv class. */ - for (curr_arc = first_out_arc (first_class_state); - curr_arc != NULL; - curr_arc = next_out_arc (curr_arc)) - add_arc (first_class_state->equiv_class_state, - curr_arc->to_state->equiv_class_state, - curr_arc->insn, curr_arc->state_alts); - /* Delete output arcs from states of given class equivalence. */ - for (curr_state = first_class_state; - curr_state != NULL; - curr_state = curr_state->next_equiv_class_state) - { - if (automaton->start_state == curr_state) - automaton->start_state = curr_state->equiv_class_state; - /* Delete the state and its output arcs. */ - for (curr_arc = first_out_arc (curr_state); - curr_arc != NULL; - curr_arc = next_arc) - { - next_arc = next_out_arc (curr_arc); - free_arc (curr_arc); - } - } - } - else - { - /* Change `to_state' of arcs output from the state of given - equivalence class. */ - for (curr_arc = first_out_arc (*equiv_class_ptr); - curr_arc != NULL; - curr_arc = next_out_arc (curr_arc)) - curr_arc->to_state = curr_arc->to_state->equiv_class_state; - } -} - -/* The function sets up new_cycle_p for states if there is arc to the - state marked by advance_cycle_insn_decl. */ -static void -set_new_cycle_flags (state) - state_t state; -{ - arc_t arc; - - for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) - if (arc->insn->insn_reserv_decl - == &advance_cycle_insn_decl->decl.insn_reserv) - arc->to_state->new_cycle_p = 1; -} - -/* The top level function for minimization of deterministic - AUTOMATON. */ -static void -minimize_DFA (automaton) - automaton_t automaton; -{ - vla_ptr_t equiv_classes; - - VLA_PTR_CREATE (equiv_classes, 1500, "equivalence classes"); - evaluate_equiv_classes (automaton, &equiv_classes); - merge_states (automaton, &equiv_classes); - pass_states (automaton, set_new_cycle_flags); - VLA_PTR_DELETE (equiv_classes); -} - -/* Values of two variables are counted number of states and arcs in an - automaton. */ -static int curr_counted_states_num; -static int curr_counted_arcs_num; - -/* The function is called by function `pass_states' to count states - and arcs of an automaton. */ -static void -incr_states_and_arcs_nums (state) - state_t state; -{ - arc_t arc; - - curr_counted_states_num++; - for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) - curr_counted_arcs_num++; -} - -/* The function counts states and arcs of AUTOMATON. */ -static void -count_states_and_arcs (automaton, states_num, arcs_num) - automaton_t automaton; - int *states_num; - int *arcs_num; -{ - curr_counted_states_num = 0; - curr_counted_arcs_num = 0; - pass_states (automaton, incr_states_and_arcs_nums); - *states_num = curr_counted_states_num; - *arcs_num = curr_counted_arcs_num; -} - -/* The function builds one DFA AUTOMATON for fast pipeline hazards - recognition after checking and simplifying IR of the - description. */ -static void -build_automaton (automaton) - automaton_t automaton; -{ - int states_num; - int arcs_num; - - ticker_on (&NDFA_time); - make_automaton (automaton); - ticker_off (&NDFA_time); - count_states_and_arcs (automaton, &states_num, &arcs_num); - automaton->NDFA_states_num = states_num; - automaton->NDFA_arcs_num = arcs_num; - ticker_on (&NDFA_to_DFA_time); - NDFA_to_DFA (automaton); - ticker_off (&NDFA_to_DFA_time); - count_states_and_arcs (automaton, &states_num, &arcs_num); - automaton->DFA_states_num = states_num; - automaton->DFA_arcs_num = arcs_num; - if (!no_minimization_flag) - { - ticker_on (&minimize_time); - minimize_DFA (automaton); - ticker_off (&minimize_time); - count_states_and_arcs (automaton, &states_num, &arcs_num); - automaton->minimal_DFA_states_num = states_num; - automaton->minimal_DFA_arcs_num = arcs_num; - } -} - - - -/* The page contains code for enumeration of all states of an automaton. */ - -/* Variable used for enumeration of all states of an automaton. Its - value is current number of automaton states. */ -static int curr_state_order_num; - -/* The function is called by function `pass_states' for enumerating - states. */ -static void -set_order_state_num (state) - state_t state; -{ - state->order_state_num = curr_state_order_num; - curr_state_order_num++; -} - -/* The function enumerates all states of AUTOMATON. */ -static void -enumerate_states (automaton) - automaton_t automaton; -{ - curr_state_order_num = 0; - pass_states (automaton, set_order_state_num); - automaton->achieved_states_num = curr_state_order_num; -} - - - -/* The page contains code for finding equivalent automaton insns - (ainsns). */ - -/* The function inserts AINSN into cyclic list - CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */ -static ainsn_t -insert_ainsn_into_equiv_class (ainsn, cyclic_equiv_class_insn_list) - ainsn_t ainsn; - ainsn_t cyclic_equiv_class_insn_list; -{ - if (cyclic_equiv_class_insn_list == NULL) - ainsn->next_equiv_class_insn = ainsn; - else - { - ainsn->next_equiv_class_insn - = cyclic_equiv_class_insn_list->next_equiv_class_insn; - cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn; - } - return ainsn; -} - -/* The function deletes equiv_class_insn into cyclic list of - equivalent ainsns. */ -static void -delete_ainsn_from_equiv_class (equiv_class_insn) - ainsn_t equiv_class_insn; -{ - ainsn_t curr_equiv_class_insn; - ainsn_t prev_equiv_class_insn; - - prev_equiv_class_insn = equiv_class_insn; - for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn; - curr_equiv_class_insn != equiv_class_insn; - curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn) - prev_equiv_class_insn = curr_equiv_class_insn; - if (prev_equiv_class_insn != equiv_class_insn) - prev_equiv_class_insn->next_equiv_class_insn - = equiv_class_insn->next_equiv_class_insn; -} - -/* The function processes AINSN of a state in order to find equivalent - ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the - state. */ -static void -process_insn_equiv_class (ainsn, insn_arcs_array) - ainsn_t ainsn; - arc_t *insn_arcs_array; -{ - ainsn_t next_insn; - ainsn_t curr_insn; - ainsn_t cyclic_insn_list; - arc_t arc; - - if (insn_arcs_array [ainsn->insn_reserv_decl->insn_num] == NULL) - abort (); - curr_insn = ainsn; - /* New class of ainsns which are not equivalent to given ainsn. */ - cyclic_insn_list = NULL; - do - { - next_insn = curr_insn->next_equiv_class_insn; - arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num]; - if (arc == NULL - || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state - != arc->to_state)) - { - delete_ainsn_from_equiv_class (curr_insn); - cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn, - cyclic_insn_list); - } - curr_insn = next_insn; - } - while (curr_insn != ainsn); -} - -/* The function processes STATE in order to find equivalent ainsns. */ -static void -process_state_for_insn_equiv_partition (state) - state_t state; -{ - arc_t arc; - arc_t *insn_arcs_array; - int i; - vla_ptr_t insn_arcs_vect; - - VLA_PTR_CREATE (insn_arcs_vect, 500, "insn arcs vector"); - VLA_PTR_EXPAND (insn_arcs_vect, description->insns_num); - insn_arcs_array = VLA_PTR_BEGIN (insn_arcs_vect); - /* Process insns of the arcs. */ - for (i = 0; i < description->insns_num; i++) - insn_arcs_array [i] = NULL; - for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) - insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc; - for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) - process_insn_equiv_class (arc->insn, insn_arcs_array); - VLA_PTR_DELETE (insn_arcs_vect); -} - -/* The function searches for equivalent ainsns of AUTOMATON. */ -static void -set_insn_equiv_classes (automaton) - automaton_t automaton; -{ - ainsn_t ainsn; - ainsn_t first_insn; - ainsn_t curr_insn; - ainsn_t cyclic_insn_list; - ainsn_t insn_with_same_reservs; - int equiv_classes_num; - - /* All insns are included in one equivalence class. */ - cyclic_insn_list = NULL; - for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn) - if (ainsn->first_insn_with_same_reservs) - cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn, - cyclic_insn_list); - /* Process insns in order to make equivalence partition. */ - pass_states (automaton, process_state_for_insn_equiv_partition); - /* Enumerate equiv classes. */ - for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn) - /* Set undefined value. */ - ainsn->insn_equiv_class_num = -1; - equiv_classes_num = 0; - for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn) - if (ainsn->insn_equiv_class_num < 0) - { - first_insn = ainsn; - if (!first_insn->first_insn_with_same_reservs) - abort (); - first_insn->first_ainsn_with_given_equialence_num = 1; - curr_insn = first_insn; - do - { - for (insn_with_same_reservs = curr_insn; - insn_with_same_reservs != NULL; - insn_with_same_reservs - = insn_with_same_reservs->next_same_reservs_insn) - insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num; - curr_insn = curr_insn->next_equiv_class_insn; - } - while (curr_insn != first_insn); - equiv_classes_num++; - } - automaton->insn_equiv_classes_num = equiv_classes_num; -} - - - -/* This page contains code for creating DFA(s) and calls functions - building them. */ - - -/* The following value is used to prevent floating point overflow for - estimating an automaton bound. The value should be less DBL_MAX on - the host machine. We use here approximate minimum of maximal - double floating point value required by ANSI C standard. It - will work for non ANSI sun compiler too. */ - -#define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37 - -/* The function estimate size of the single DFA used by PHR (pipeline - hazards recognizer). */ -static double -estimate_one_automaton_bound () -{ - decl_t decl; - double one_automaton_estimation_bound; - double root_value; - int i; - - one_automaton_estimation_bound = 1.0; - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_unit) - { - root_value = exp (log (decl->decl.unit.max_occ_cycle_num + 1.0) - / automata_num); - if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value - > one_automaton_estimation_bound) - one_automaton_estimation_bound *= root_value; - } - } - return one_automaton_estimation_bound; -} - -/* The function compares unit declarations acoording to their maximal - cycle in reservations. */ -static int -compare_max_occ_cycle_nums (unit_decl_1, unit_decl_2) - const void *unit_decl_1; - const void *unit_decl_2; -{ - if (((*(decl_t *) unit_decl_1)->decl.unit.max_occ_cycle_num) - < ((*(decl_t *) unit_decl_2)->decl.unit.max_occ_cycle_num)) - return 1; - else if (((*(decl_t *) unit_decl_1)->decl.unit.max_occ_cycle_num) - == ((*(decl_t *) unit_decl_2)->decl.unit.max_occ_cycle_num)) - return 0; - else - return -1; -} - -/* The function makes heuristic assigning automata to units. Actually - efficacy of the algorithm has been checked yet??? */ -static void -units_to_automata_heuristic_distr () -{ - double estimation_bound; - decl_t decl; - decl_t *unit_decl_ptr; - int automaton_num; - int rest_units_num; - double bound_value; - vla_ptr_t unit_decls; - int i; - - if (description->units_num == 0) - return; - estimation_bound = estimate_one_automaton_bound (); - VLA_PTR_CREATE (unit_decls, 150, "unit decls"); - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_unit) - VLA_PTR_ADD (unit_decls, decl); - } - qsort (VLA_PTR_BEGIN (unit_decls), VLA_PTR_LENGTH (unit_decls), - sizeof (decl_t), compare_max_occ_cycle_nums); - automaton_num = 0; - unit_decl_ptr = VLA_PTR_BEGIN (unit_decls); - bound_value = (*unit_decl_ptr)->decl.unit.max_occ_cycle_num; - (*unit_decl_ptr)->decl.unit.corresponding_automaton_num = automaton_num; - for (unit_decl_ptr++; - unit_decl_ptr <= (decl_t *) VLA_PTR_LAST (unit_decls); - unit_decl_ptr++) - { - rest_units_num - = ((decl_t *) VLA_PTR_LAST (unit_decls) - unit_decl_ptr + 1); - if (automata_num - automaton_num - 1 > rest_units_num) - abort (); - if (automaton_num < automata_num - 1 - && ((automata_num - automaton_num - 1 == rest_units_num) - || (bound_value - > (estimation_bound - / ((*unit_decl_ptr)->decl.unit.max_occ_cycle_num))))) - { - bound_value = (*unit_decl_ptr)->decl.unit.max_occ_cycle_num; - automaton_num++; - } - else - bound_value *= (*unit_decl_ptr)->decl.unit.max_occ_cycle_num; - (*unit_decl_ptr)->decl.unit.corresponding_automaton_num = automaton_num; - } - if (automaton_num != automata_num - 1) - abort (); - VLA_PTR_DELETE (unit_decls); -} - -/* The functions creates automaton insns for each automata. Automaton - insn is simply insn for given automaton which makes reservation - only of units of the automaton. */ -static ainsn_t -create_ainsns () -{ - decl_t decl; - ainsn_t first_ainsn; - ainsn_t curr_ainsn; - ainsn_t prev_ainsn; - int i; - - first_ainsn = NULL; - prev_ainsn = NULL; - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_insn_reserv) - { - curr_ainsn = create_node (sizeof (struct ainsn)); - curr_ainsn->insn_reserv_decl = &decl->decl.insn_reserv; - curr_ainsn->next_ainsn = NULL; - if (prev_ainsn == NULL) - first_ainsn = curr_ainsn; - else - prev_ainsn->next_ainsn = curr_ainsn; - prev_ainsn = curr_ainsn; - } - } - return first_ainsn; -} - -/* The function assigns automata to units according to constructions - `define_automaton' in the description. */ -static void -units_to_automata_distr () -{ - decl_t decl; - int i; - - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_unit) - { - if (decl->decl.unit.automaton_decl == NULL - || (decl->decl.unit.automaton_decl->corresponding_automaton - == NULL)) - /* Distribute to the first automaton. */ - decl->decl.unit.corresponding_automaton_num = 0; - else - decl->decl.unit.corresponding_automaton_num - = (decl->decl.unit.automaton_decl - ->corresponding_automaton->automaton_order_num); - } - } -} - -/* The function creates DFA(s) for fast pipeline hazards recognition - after checking and simplifying IR of the description. */ -static void -create_automata () -{ - automaton_t curr_automaton; - automaton_t prev_automaton; - decl_t decl; - int curr_automaton_num; - int i; - - if (automata_num != 0) - { - units_to_automata_heuristic_distr (); - for (prev_automaton = NULL, curr_automaton_num = 0; - curr_automaton_num < automata_num; - curr_automaton_num++, prev_automaton = curr_automaton) - { - curr_automaton = create_node (sizeof (struct automaton)); - curr_automaton->ainsn_list = create_ainsns (); - curr_automaton->corresponding_automaton_decl = NULL; - curr_automaton->next_automaton = NULL; - curr_automaton->automaton_order_num = curr_automaton_num; - if (prev_automaton == NULL) - description->first_automaton = curr_automaton; - else - prev_automaton->next_automaton = curr_automaton; - } - } - else - { - curr_automaton_num = 0; - prev_automaton = NULL; - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_automaton - && decl->decl.automaton.automaton_is_used) - { - curr_automaton = create_node (sizeof (struct automaton)); - curr_automaton->ainsn_list = create_ainsns (); - curr_automaton->corresponding_automaton_decl - = &decl->decl.automaton; - curr_automaton->next_automaton = NULL; - decl->decl.automaton.corresponding_automaton = curr_automaton; - curr_automaton->automaton_order_num = curr_automaton_num; - if (prev_automaton == NULL) - description->first_automaton = curr_automaton; - else - prev_automaton->next_automaton = curr_automaton; - curr_automaton_num++; - prev_automaton = curr_automaton; - } - } - if (curr_automaton_num == 0) - { - curr_automaton = create_node (sizeof (struct automaton)); - curr_automaton->ainsn_list = create_ainsns (); - curr_automaton->corresponding_automaton_decl = NULL; - curr_automaton->next_automaton = NULL; - description->first_automaton = curr_automaton; - } - units_to_automata_distr (); - } - NDFA_time = create_ticker (); - ticker_off (&NDFA_time); - NDFA_to_DFA_time = create_ticker (); - ticker_off (&NDFA_to_DFA_time); - minimize_time = create_ticker (); - ticker_off (&minimize_time); - equiv_time = create_ticker (); - ticker_off (&equiv_time); - for (curr_automaton = description->first_automaton; - curr_automaton != NULL; - curr_automaton = curr_automaton->next_automaton) - { - create_alt_states (curr_automaton); - form_ainsn_with_same_reservs (curr_automaton); - build_automaton (curr_automaton); - enumerate_states (curr_automaton); - ticker_on (&equiv_time); - set_insn_equiv_classes (curr_automaton); - ticker_off (&equiv_time); - } -} - - - -/* This page contains code for forming string representation of - regexp. The representation is formed on IR obstack. So you should - not work with IR obstack between regexp_representation and - finish_regexp_representation calls. */ - -/* This recursive function forms string representation of regexp - (without tailing '\0'). */ -static void -form_regexp (regexp) - regexp_t regexp; -{ - int i; - - if (regexp->mode == rm_unit || regexp->mode == rm_reserv) - { - const char *name = (regexp->mode == rm_unit - ? regexp->regexp.unit.name - : regexp->regexp.reserv.name); - - obstack_grow (&irp, name, strlen (name)); - } - else if (regexp->mode == rm_sequence) - for (i = 0; i < regexp->regexp.sequence.regexps_num; i++) - { - if (i != 0) - obstack_1grow (&irp, ','); - form_regexp (regexp->regexp.sequence.regexps [i]); - } - else if (regexp->mode == rm_allof) - { - obstack_1grow (&irp, '('); - for (i = 0; i < regexp->regexp.allof.regexps_num; i++) - { - if (i != 0) - obstack_1grow (&irp, '+'); - if (regexp->regexp.allof.regexps[i]->mode == rm_sequence - || regexp->regexp.oneof.regexps[i]->mode == rm_oneof) - obstack_1grow (&irp, '('); - form_regexp (regexp->regexp.allof.regexps [i]); - if (regexp->regexp.allof.regexps[i]->mode == rm_sequence - || regexp->regexp.oneof.regexps[i]->mode == rm_oneof) - obstack_1grow (&irp, ')'); - } - obstack_1grow (&irp, ')'); - } - else if (regexp->mode == rm_oneof) - for (i = 0; i < regexp->regexp.oneof.regexps_num; i++) - { - if (i != 0) - obstack_1grow (&irp, '|'); - if (regexp->regexp.oneof.regexps[i]->mode == rm_sequence) - obstack_1grow (&irp, '('); - form_regexp (regexp->regexp.oneof.regexps [i]); - if (regexp->regexp.oneof.regexps[i]->mode == rm_sequence) - obstack_1grow (&irp, ')'); - } - else if (regexp->mode == rm_repeat) - { - char digits [30]; - - if (regexp->regexp.repeat.regexp->mode == rm_sequence - || regexp->regexp.repeat.regexp->mode == rm_allof - || regexp->regexp.repeat.regexp->mode == rm_oneof) - obstack_1grow (&irp, '('); - form_regexp (regexp->regexp.repeat.regexp); - if (regexp->regexp.repeat.regexp->mode == rm_sequence - || regexp->regexp.repeat.regexp->mode == rm_allof - || regexp->regexp.repeat.regexp->mode == rm_oneof) - obstack_1grow (&irp, ')'); - sprintf (digits, "*%d", regexp->regexp.repeat.repeat_num); - obstack_grow (&irp, digits, strlen (digits)); - } - else if (regexp->mode == rm_nothing) - obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME)); - else - abort (); -} - -/* The function returns string representation of REGEXP on IR - obstack. */ -static const char * -regexp_representation (regexp) - regexp_t regexp; -{ - form_regexp (regexp); - obstack_1grow (&irp, '\0'); - return obstack_base (&irp); -} - -/* The function frees memory allocated for last formed string - representation of regexp. */ -static void -finish_regexp_representation () -{ - int length = obstack_object_size (&irp); - - obstack_blank_fast (&irp, -length); -} - - - -/* This page contains code for output PHR (pipeline hazards recognizer). */ - -/* The function outputs minimal C type which is sufficient for - representation numbers in range min_range_value and - max_range_value. Because host machine and build machine may be - different, we use here minimal values required by ANSI C standard - instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good - approximation. */ - -static void -output_range_type (f, min_range_value, max_range_value) - FILE *f; - long int min_range_value; - long int max_range_value; -{ - if (min_range_value >= 0 && max_range_value <= 255) - fprintf (f, "unsigned char"); - else if (min_range_value >= -127 && max_range_value <= 127) - fprintf (f, "signed char"); - else if (min_range_value >= 0 && max_range_value <= 65535) - fprintf (f, "unsigned short"); - else if (min_range_value >= -32767 && max_range_value <= 32767) - fprintf (f, "short"); - else - fprintf (f, "int"); -} - -/* The following macro value is used as value of member - `longest_path_length' of state when we are processing path and the - state on the path. */ - -#define ON_THE_PATH -2 - -/* The following recursive function searches for the length of the - longest path starting from STATE which does not contain cycles and - `cycle advance' arcs. */ - -static int -longest_path_length (state) - state_t state; -{ - arc_t arc; - int length, result; - - if (state->longest_path_length == ON_THE_PATH) - /* We don't expect the path cycle here. Our graph may contain - only cycles with one state on the path not containing `cycle - advance' arcs -- see comment below. */ - abort (); - else if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH) - /* We alreday visited the state. */ - return state->longest_path_length; - - result = 0; - for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) - /* Ignore cycles containing one state and `cycle advance' arcs. */ - if (arc->to_state != state - && (arc->insn->insn_reserv_decl - != &advance_cycle_insn_decl->decl.insn_reserv)) - { - length = longest_path_length (arc->to_state); - if (length > result) - result = length; - } - state->longest_path_length = result + 1; - return result; -} - -/* The following variable value is value of the corresponding global - variable in the automaton based pipeline interface. */ - -static int max_dfa_issue_rate; - -/* The following function processes the longest path length staring - from STATE to find MAX_DFA_ISSUE_RATE. */ - -static void -process_state_longest_path_length (state) - state_t state; -{ - int value; - - value = longest_path_length (state); - if (value > max_dfa_issue_rate) - max_dfa_issue_rate = value; -} - -/* The following nacro value is name of the corresponding global - variable in the automaton based pipeline interface. */ - -#define MAX_DFA_ISSUE_RATE_VAR_NAME "max_dfa_issue_rate" - -/* The following function calculates value of the the corresponding - global variable and outputs its declaration. */ - -static void -output_dfa_max_issue_rate (void) -{ - automaton_t automaton; - - if (UNDEFINED_LONGEST_PATH_LENGTH == ON_THE_PATH || ON_THE_PATH >= 0) - abort (); - max_dfa_issue_rate = 0; - for (automaton = description->first_automaton; - automaton != NULL; - automaton = automaton->next_automaton) - pass_states (automaton, process_state_longest_path_length); - fprintf (output_file, "\nint %s = %d;\n", - MAX_DFA_ISSUE_RATE_VAR_NAME, max_dfa_issue_rate); -} - -/* The function outputs all initialization values of VECT with length - vect_length. */ -static void -output_vect (vect, vect_length) - vect_el_t *vect; - int vect_length; -{ - int els_on_line; - - els_on_line = 1; - if (vect_length == 0) - fprintf (output_file, - "0 /* This is dummy el because the vect is empty */"); - else - { - do - { - fprintf (output_file, "%5ld", (long) *vect); - vect_length--; - if (els_on_line == 10) - { - els_on_line = 0; - fprintf (output_file, ",\n"); - } - else if (vect_length != 0) - fprintf (output_file, ", "); - els_on_line++; - vect++; - } - while (vect_length != 0); - } -} - -/* The following is name of the structure which represents DFA(s) for - PHR. */ -#define CHIP_NAME "DFA_chip" - -/* The following is name of member which represents state of a DFA for - PHR. */ -static void -output_chip_member_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - if (automaton->corresponding_automaton_decl == NULL) - fprintf (f, "automaton_state_%d", automaton->automaton_order_num); - else - fprintf (f, "%s_automaton_state", - automaton->corresponding_automaton_decl->name); -} - -/* The following is name of temporary variable which stores state of a - DFA for PHR. */ -static void -output_temp_chip_member_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - fprintf (f, "_"); - output_chip_member_name (f, automaton); -} - -/* This is name of macro value which is code of pseudo_insn - representing advancing cpu cycle. Its value is used as internal - code unknown insn. */ -#define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE" - -/* Output name of translate vector for given automaton. */ -static void -output_translate_vect_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - if (automaton->corresponding_automaton_decl == NULL) - fprintf (f, "translate_%d", automaton->automaton_order_num); - else - fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name); -} - -/* Output name for simple transition table representation. */ -static void -output_trans_full_vect_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - if (automaton->corresponding_automaton_decl == NULL) - fprintf (f, "transitions_%d", automaton->automaton_order_num); - else - fprintf (f, "%s_transitions", - automaton->corresponding_automaton_decl->name); -} - -/* Output name of comb vector of the transition table for given - automaton. */ -static void -output_trans_comb_vect_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - if (automaton->corresponding_automaton_decl == NULL) - fprintf (f, "transitions_%d", automaton->automaton_order_num); - else - fprintf (f, "%s_transitions", - automaton->corresponding_automaton_decl->name); -} - -/* Output name of check vector of the transition table for given - automaton. */ -static void -output_trans_check_vect_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - if (automaton->corresponding_automaton_decl == NULL) - fprintf (f, "check_%d", automaton->automaton_order_num); - else - fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name); -} - -/* Output name of base vector of the transition table for given - automaton. */ -static void -output_trans_base_vect_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - if (automaton->corresponding_automaton_decl == NULL) - fprintf (f, "base_%d", automaton->automaton_order_num); - else - fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name); -} - -/* Output name for simple alternatives number representation. */ -static void -output_state_alts_full_vect_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - if (automaton->corresponding_automaton_decl == NULL) - fprintf (f, "state_alts_%d", automaton->automaton_order_num); - else - fprintf (f, "%s_state_alts", - automaton->corresponding_automaton_decl->name); -} - -/* Output name of comb vector of the alternatives number table for given - automaton. */ -static void -output_state_alts_comb_vect_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - if (automaton->corresponding_automaton_decl == NULL) - fprintf (f, "state_alts_%d", automaton->automaton_order_num); - else - fprintf (f, "%s_state_alts", - automaton->corresponding_automaton_decl->name); -} - -/* Output name of check vector of the alternatives number table for given - automaton. */ -static void -output_state_alts_check_vect_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - if (automaton->corresponding_automaton_decl == NULL) - fprintf (f, "check_state_alts_%d", automaton->automaton_order_num); - else - fprintf (f, "%s_check_state_alts", - automaton->corresponding_automaton_decl->name); -} - -/* Output name of base vector of the alternatives number table for given - automaton. */ -static void -output_state_alts_base_vect_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - if (automaton->corresponding_automaton_decl == NULL) - fprintf (f, "base_state_alts_%d", automaton->automaton_order_num); - else - fprintf (f, "%s_base_state_alts", - automaton->corresponding_automaton_decl->name); -} - -/* Output name of simple min issue delay table representation. */ -static void -output_min_issue_delay_vect_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - if (automaton->corresponding_automaton_decl == NULL) - fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num); - else - fprintf (f, "%s_min_issue_delay", - automaton->corresponding_automaton_decl->name); -} - -/* Output name of deadlock vector for given automaton. */ -static void -output_dead_lock_vect_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - if (automaton->corresponding_automaton_decl == NULL) - fprintf (f, "dead_lock_%d", automaton->automaton_order_num); - else - fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name); -} - -/* Output name of reserved units table for AUTOMATON into file F. */ -static void -output_reserved_units_table_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - if (automaton->corresponding_automaton_decl == NULL) - fprintf (f, "reserved_units_%d", automaton->automaton_order_num); - else - fprintf (f, "%s_reserved_units", - automaton->corresponding_automaton_decl->name); -} - -/* Name of the PHR interface macro. */ -#define AUTOMATON_STATE_ALTS_MACRO_NAME "AUTOMATON_STATE_ALTS" - -/* Name of the PHR interface macro. */ -#define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY" - -/* Names of an internal functions: */ -#define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay" - -/* This is external type of DFA(s) state. */ -#define STATE_TYPE_NAME "state_t" - -#define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition" - -#define INTERNAL_STATE_ALTS_FUNC_NAME "internal_state_alts" - -#define INTERNAL_RESET_FUNC_NAME "internal_reset" - -#define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p" - -#define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency" - -/* Name of cache of insn dfa codes. */ -#define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes" - -/* Names of the PHR interface functions: */ -#define SIZE_FUNC_NAME "state_size" - -#define TRANSITION_FUNC_NAME "state_transition" - -#define STATE_ALTS_FUNC_NAME "state_alts" - -#define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay" - -#define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay" - -#define DEAD_LOCK_FUNC_NAME "state_dead_lock_p" - -#define RESET_FUNC_NAME "state_reset" - -#define INSN_LATENCY_FUNC_NAME "insn_latency" - -#define PRINT_RESERVATION_FUNC_NAME "print_reservation" - -#define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code" - -#define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p" - -#define DFA_START_FUNC_NAME "dfa_start" - -#define DFA_FINISH_FUNC_NAME "dfa_finish" - -/* Names of parameters of the PHR interface functions. */ -#define STATE_NAME "state" - -#define INSN_PARAMETER_NAME "insn" - -#define INSN2_PARAMETER_NAME "insn2" - -#define CHIP_PARAMETER_NAME "chip" - -#define FILE_PARAMETER_NAME "f" - -#define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name" - -#define CPU_CODE_PARAMETER_NAME "cpu_unit_code" - -/* Names of the variables whose values are internal insn code of rtx - insn. */ -#define INTERNAL_INSN_CODE_NAME "insn_code" - -#define INTERNAL_INSN2_CODE_NAME "insn2_code" - -/* Names of temporary variables in some functions. */ -#define TEMPORARY_VARIABLE_NAME "temp" - -#define I_VARIABLE_NAME "i" - -/* Name of result variable in some functions. */ -#define RESULT_VARIABLE_NAME "res" - -/* Name of function (attribute) to translate insn into number of insn - alternatives reservation. */ -#define INSN_ALTS_FUNC_NAME "insn_alts" - -/* Name of function (attribute) to translate insn into internal insn - code. */ -#define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code" - -/* Name of function (attribute) to translate insn into internal insn - code with caching. */ -#define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code" - -/* Name of function (attribute) to translate insn into internal insn - code. */ -#define INSN_DEFAULT_LATENCY_FUNC_NAME "insn_default_latency" - -/* Name of function (attribute) to translate insn into internal insn - code. */ -#define BYPASS_P_FUNC_NAME "bypass_p" - -/* Output C type which is used for representation of codes of states - of AUTOMATON. */ -static void -output_state_member_type (f, automaton) - FILE *f; - automaton_t automaton; -{ - output_range_type (f, 0, automaton->achieved_states_num); -} - -/* Output definition of the structure representing current DFA(s) - state(s). */ -static void -output_chip_definitions () -{ - automaton_t automaton; - - fprintf (output_file, "struct %s\n{\n", CHIP_NAME); - for (automaton = description->first_automaton; - automaton != NULL; - automaton = automaton->next_automaton) - { - fprintf (output_file, " "); - output_state_member_type (output_file, automaton); - fprintf (output_file, " "); - output_chip_member_name (output_file, automaton); - fprintf (output_file, ";\n"); - } - fprintf (output_file, "};\n\n"); -#if 0 - fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME); -#endif -} - - -/* The function outputs translate vector of internal insn code into - insn equivalence class number. The equivalence class number is - used to access to table and vectors reprewsenting DFA(s). */ -static void -output_translate_vect (automaton) - automaton_t automaton; -{ - ainsn_t ainsn; - int insn_value; - vla_hwint_t translate_vect; - - VLA_HWINT_CREATE (translate_vect, 250, "translate vector"); - VLA_HWINT_EXPAND (translate_vect, description->insns_num); - for (insn_value = 0; insn_value <= description->insns_num; insn_value++) - /* Undefined value */ - VLA_HWINT (translate_vect, insn_value) = automaton->insn_equiv_classes_num; - for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn) - VLA_HWINT (translate_vect, ainsn->insn_reserv_decl->insn_num) - = ainsn->insn_equiv_class_num; - fprintf (output_file, - "/* Vector translating external insn codes to internal ones.*/\n"); - fprintf (output_file, "static const "); - output_range_type (output_file, 0, automaton->insn_equiv_classes_num); - fprintf (output_file, " "); - output_translate_vect_name (output_file, automaton); - fprintf (output_file, "[] = {\n"); - output_vect (VLA_HWINT_BEGIN (translate_vect), - VLA_HWINT_LENGTH (translate_vect)); - fprintf (output_file, "};\n\n"); - VLA_HWINT_DELETE (translate_vect); -} - -/* The value in a table state x ainsn -> something which represents - undefined value. */ -static int undefined_vect_el_value; - -/* The following function returns nonzero value if the best - representation of the table is comb vector. */ -static int -comb_vect_p (tab) - state_ainsn_table_t tab; -{ - return (2 * VLA_HWINT_LENGTH (tab->full_vect) - > 5 * VLA_HWINT_LENGTH (tab->comb_vect)); -} - -/* The following function creates new table for AUTOMATON. */ -static state_ainsn_table_t -create_state_ainsn_table (automaton) - automaton_t automaton; -{ - state_ainsn_table_t tab; - int full_vect_length; - int i; - - tab = create_node (sizeof (struct state_ainsn_table)); - tab->automaton = automaton; - VLA_HWINT_CREATE (tab->comb_vect, 10000, "comb vector"); - VLA_HWINT_CREATE (tab->check_vect, 10000, "check vector"); - VLA_HWINT_CREATE (tab->base_vect, 1000, "base vector"); - VLA_HWINT_EXPAND (tab->base_vect, automaton->achieved_states_num); - VLA_HWINT_CREATE (tab->full_vect, 10000, "full vector"); - full_vect_length = (automaton->insn_equiv_classes_num - * automaton->achieved_states_num); - VLA_HWINT_EXPAND (tab->full_vect, full_vect_length); - for (i = 0; i < full_vect_length; i++) - VLA_HWINT (tab->full_vect, i) = undefined_vect_el_value; - tab->min_base_vect_el_value = 0; - tab->max_base_vect_el_value = 0; - tab->min_comb_vect_el_value = 0; - tab->max_comb_vect_el_value = 0; - return tab; -} - -/* The following function outputs the best C representation of the - table TAB of given TABLE_NAME. */ -static void -output_state_ainsn_table (tab, table_name, output_full_vect_name_func, - output_comb_vect_name_func, - output_check_vect_name_func, - output_base_vect_name_func) - state_ainsn_table_t tab; - char *table_name; - void (*output_full_vect_name_func) PARAMS ((FILE *, automaton_t)); - void (*output_comb_vect_name_func) PARAMS ((FILE *, automaton_t)); - void (*output_check_vect_name_func) PARAMS ((FILE *, automaton_t)); - void (*output_base_vect_name_func) PARAMS ((FILE *, automaton_t)); -{ - if (!comb_vect_p (tab)) - { - fprintf (output_file, "/* Vector for %s. */\n", table_name); - fprintf (output_file, "static const "); - output_range_type (output_file, tab->min_comb_vect_el_value, - tab->max_comb_vect_el_value); - fprintf (output_file, " "); - (*output_full_vect_name_func) (output_file, tab->automaton); - fprintf (output_file, "[] = {\n"); - output_vect (VLA_HWINT_BEGIN (tab->full_vect), - VLA_HWINT_LENGTH (tab->full_vect)); - fprintf (output_file, "};\n\n"); - } - else - { - fprintf (output_file, "/* Comb vector for %s. */\n", table_name); - fprintf (output_file, "static const "); - output_range_type (output_file, tab->min_comb_vect_el_value, - tab->max_comb_vect_el_value); - fprintf (output_file, " "); - (*output_comb_vect_name_func) (output_file, tab->automaton); - fprintf (output_file, "[] = {\n"); - output_vect (VLA_HWINT_BEGIN (tab->comb_vect), - VLA_HWINT_LENGTH (tab->comb_vect)); - fprintf (output_file, "};\n\n"); - fprintf (output_file, "/* Check vector for %s. */\n", table_name); - fprintf (output_file, "static const "); - output_range_type (output_file, 0, tab->automaton->achieved_states_num); - fprintf (output_file, " "); - (*output_check_vect_name_func) (output_file, tab->automaton); - fprintf (output_file, "[] = {\n"); - output_vect (VLA_HWINT_BEGIN (tab->check_vect), - VLA_HWINT_LENGTH (tab->check_vect)); - fprintf (output_file, "};\n\n"); - fprintf (output_file, "/* Base vector for %s. */\n", table_name); - fprintf (output_file, "static const "); - output_range_type (output_file, tab->min_base_vect_el_value, - tab->max_base_vect_el_value); - fprintf (output_file, " "); - (*output_base_vect_name_func) (output_file, tab->automaton); - fprintf (output_file, "[] = {\n"); - output_vect (VLA_HWINT_BEGIN (tab->base_vect), - VLA_HWINT_LENGTH (tab->base_vect)); - fprintf (output_file, "};\n\n"); - } -} - -/* The following function adds vector with length VECT_LENGTH and - elements pointed by VECT to table TAB as its line with number - VECT_NUM. */ -static void -add_vect (tab, vect_num, vect, vect_length) - state_ainsn_table_t tab; - int vect_num; - vect_el_t *vect; - int vect_length; -{ - int real_vect_length; - vect_el_t *comb_vect_start; - vect_el_t *check_vect_start; - int comb_vect_index; - int comb_vect_els_num; - int vect_index; - int first_unempty_vect_index; - int additional_els_num; - int no_state_value; - vect_el_t vect_el; - int i; - - if (vect_length == 0) - abort (); - real_vect_length = tab->automaton->insn_equiv_classes_num; - if (vect [vect_length - 1] == undefined_vect_el_value) - abort (); - /* Form full vector in the table: */ - for (i = 0; i < vect_length; i++) - VLA_HWINT (tab->full_vect, - i + tab->automaton->insn_equiv_classes_num * vect_num) - = vect [i]; - /* Form comb vector in the table: */ - if (VLA_HWINT_LENGTH (tab->comb_vect) != VLA_HWINT_LENGTH (tab->check_vect)) - abort (); - comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect); - comb_vect_els_num = VLA_HWINT_LENGTH (tab->comb_vect); - for (first_unempty_vect_index = 0; - first_unempty_vect_index < vect_length; - first_unempty_vect_index++) - if (vect [first_unempty_vect_index] != undefined_vect_el_value) - break; - /* Search for the place in comb vect for the inserted vect. */ - for (comb_vect_index = 0; - comb_vect_index < comb_vect_els_num; - comb_vect_index++) - { - for (vect_index = first_unempty_vect_index; - vect_index < vect_length - && vect_index + comb_vect_index < comb_vect_els_num; - vect_index++) - if (vect [vect_index] != undefined_vect_el_value - && (comb_vect_start [vect_index + comb_vect_index] - != undefined_vect_el_value)) - break; - if (vect_index >= vect_length - || vect_index + comb_vect_index >= comb_vect_els_num) - break; - } - /* Slot was found. */ - additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num; - if (additional_els_num < 0) - additional_els_num = 0; - /* Expand comb and check vectors. */ - vect_el = undefined_vect_el_value; - no_state_value = tab->automaton->achieved_states_num; - while (additional_els_num > 0) - { - VLA_HWINT_ADD (tab->comb_vect, vect_el); - VLA_HWINT_ADD (tab->check_vect, no_state_value); - additional_els_num--; - } - comb_vect_start = VLA_HWINT_BEGIN (tab->comb_vect); - check_vect_start = VLA_HWINT_BEGIN (tab->check_vect); - if (VLA_HWINT_LENGTH (tab->comb_vect) - < (size_t) (comb_vect_index + real_vect_length)) - abort (); - /* Fill comb and check vectors. */ - for (vect_index = 0; vect_index < vect_length; vect_index++) - if (vect [vect_index] != undefined_vect_el_value) - { - if (comb_vect_start [comb_vect_index + vect_index] - != undefined_vect_el_value) - abort (); - comb_vect_start [comb_vect_index + vect_index] = vect [vect_index]; - if (vect [vect_index] < 0) - abort (); - if (tab->max_comb_vect_el_value < vect [vect_index]) - tab->max_comb_vect_el_value = vect [vect_index]; - if (tab->min_comb_vect_el_value > vect [vect_index]) - tab->min_comb_vect_el_value = vect [vect_index]; - check_vect_start [comb_vect_index + vect_index] = vect_num; - } - if (tab->max_base_vect_el_value < comb_vect_index) - tab->max_base_vect_el_value = comb_vect_index; - if (tab->min_base_vect_el_value > comb_vect_index) - tab->min_base_vect_el_value = comb_vect_index; - VLA_HWINT (tab->base_vect, vect_num) = comb_vect_index; -} - -/* Return number of out arcs of STATE. */ -static int -out_state_arcs_num (state) - state_t state; -{ - int result; - arc_t arc; - - result = 0; - for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) - { - if (arc->insn == NULL) - abort (); - if (arc->insn->first_ainsn_with_given_equialence_num) - result++; - } - return result; -} - -/* Compare number of possible transitions from the states. */ -static int -compare_transition_els_num (state_ptr_1, state_ptr_2) - const void *state_ptr_1; - const void *state_ptr_2; -{ - int transition_els_num_1; - int transition_els_num_2; - - transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1); - transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2); - if (transition_els_num_1 < transition_els_num_2) - return 1; - else if (transition_els_num_1 == transition_els_num_2) - return 0; - else - return -1; -} - -/* The function adds element EL_VALUE to vector VECT for a table state - x AINSN. */ -static void -add_vect_el (vect, ainsn, el_value) - vla_hwint_t *vect; - ainsn_t ainsn; - int el_value; -{ - int equiv_class_num; - int vect_index; - - if (ainsn == NULL) - abort (); - equiv_class_num = ainsn->insn_equiv_class_num; - for (vect_index = VLA_HWINT_LENGTH (*vect); - vect_index <= equiv_class_num; - vect_index++) - VLA_HWINT_ADD (*vect, undefined_vect_el_value); - VLA_HWINT (*vect, equiv_class_num) = el_value; -} - -/* This is for forming vector of states of an automaton. */ -static vla_ptr_t output_states_vect; - -/* The function is called by function pass_states. The function adds - STATE to `output_states_vect'. */ -static void -add_states_vect_el (state) - state_t state; -{ - VLA_PTR_ADD (output_states_vect, state); -} - -/* Form and output vectors (comb, check, base or full vector) - representing transition table of AUTOMATON. */ -static void -output_trans_table (automaton) - automaton_t automaton; -{ - state_t *state_ptr; - arc_t arc; - vla_hwint_t transition_vect; - - undefined_vect_el_value = automaton->achieved_states_num; - automaton->trans_table = create_state_ainsn_table (automaton); - /* Create vect of pointers to states ordered by num of transitions - from the state (state with the maximum num is the first). */ - VLA_PTR_CREATE (output_states_vect, 1500, "output states vector"); - pass_states (automaton, add_states_vect_el); - qsort (VLA_PTR_BEGIN (output_states_vect), - VLA_PTR_LENGTH (output_states_vect), - sizeof (state_t), compare_transition_els_num); - VLA_HWINT_CREATE (transition_vect, 500, "transition vector"); - for (state_ptr = VLA_PTR_BEGIN (output_states_vect); - state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect); - state_ptr++) - { - VLA_HWINT_NULLIFY (transition_vect); - for (arc = first_out_arc (*state_ptr); - arc != NULL; - arc = next_out_arc (arc)) - { - if (arc->insn == NULL) - abort (); - if (arc->insn->first_ainsn_with_given_equialence_num) - add_vect_el (&transition_vect, arc->insn, - arc->to_state->order_state_num); - } - add_vect (automaton->trans_table, (*state_ptr)->order_state_num, - VLA_HWINT_BEGIN (transition_vect), - VLA_HWINT_LENGTH (transition_vect)); - } - output_state_ainsn_table - (automaton->trans_table, (char *) "state transitions", - output_trans_full_vect_name, output_trans_comb_vect_name, - output_trans_check_vect_name, output_trans_base_vect_name); - VLA_PTR_DELETE (output_states_vect); - VLA_HWINT_DELETE (transition_vect); -} - -/* Form and output vectors (comb, check, base or simple vect) - representing alts number table of AUTOMATON. The table is state x - ainsn -> number of possible alternative reservations by the - ainsn. */ -static void -output_state_alts_table (automaton) - automaton_t automaton; -{ - state_t *state_ptr; - arc_t arc; - vla_hwint_t state_alts_vect; - - undefined_vect_el_value = 0; /* no alts when transition is not possible */ - automaton->state_alts_table = create_state_ainsn_table (automaton); - /* Create vect of pointers to states ordered by num of transitions - from the state (state with the maximum num is the first). */ - VLA_PTR_CREATE (output_states_vect, 1500, "output states vector"); - pass_states (automaton, add_states_vect_el); - qsort (VLA_PTR_BEGIN (output_states_vect), - VLA_PTR_LENGTH (output_states_vect), - sizeof (state_t), compare_transition_els_num); - /* Create base, comb, and check vectors. */ - VLA_HWINT_CREATE (state_alts_vect, 500, "state alts vector"); - for (state_ptr = VLA_PTR_BEGIN (output_states_vect); - state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect); - state_ptr++) - { - VLA_HWINT_NULLIFY (state_alts_vect); - for (arc = first_out_arc (*state_ptr); - arc != NULL; - arc = next_out_arc (arc)) - { - if (arc->insn == NULL) - abort (); - if (arc->insn->first_ainsn_with_given_equialence_num) - add_vect_el (&state_alts_vect, arc->insn, arc->state_alts); - } - add_vect (automaton->state_alts_table, (*state_ptr)->order_state_num, - VLA_HWINT_BEGIN (state_alts_vect), - VLA_HWINT_LENGTH (state_alts_vect)); - } - output_state_ainsn_table - (automaton->state_alts_table, (char *) "state insn alternatives", - output_state_alts_full_vect_name, output_state_alts_comb_vect_name, - output_state_alts_check_vect_name, output_state_alts_base_vect_name); - VLA_PTR_DELETE (output_states_vect); - VLA_HWINT_DELETE (state_alts_vect); -} - -/* The current number of passing states to find minimal issue delay - value for an ainsn and state. */ -static int curr_state_pass_num; - - -/* This recursive function passes states to find minimal issue delay - value for AINSN. The state being visited is STATE. */ -static void -min_issue_delay_pass_states (state, ainsn) - state_t state; - ainsn_t ainsn; -{ - arc_t arc; - int min_insn_issue_delay, insn_issue_delay; - - if (state->state_pass_num == curr_state_pass_num) - return; - state->state_pass_num = curr_state_pass_num; - min_insn_issue_delay = state->min_insn_issue_delay = -1; - for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) - if (arc->insn == ainsn) - { - min_insn_issue_delay = 0; - break; - } - else - { - min_issue_delay_pass_states (arc->to_state, ainsn); - if (arc->to_state->min_insn_issue_delay != -1) - { - insn_issue_delay - = (arc->to_state->min_insn_issue_delay - + (arc->insn->insn_reserv_decl - == &advance_cycle_insn_decl->decl.insn_reserv ? 1 : 0)); - if (min_insn_issue_delay == -1 - || min_insn_issue_delay > insn_issue_delay) - min_insn_issue_delay = insn_issue_delay; - } - } - state->min_insn_issue_delay = min_insn_issue_delay; -} - -/* The function searches minimal issue delay value for AINSN in STATE. - The function can return negative can not issue AINSN. We will - report about it later. */ -static int -min_issue_delay (state, ainsn) - state_t state; - ainsn_t ainsn; -{ - curr_state_pass_num++; - min_issue_delay_pass_states (state, ainsn); - return state->min_insn_issue_delay; -} - -/* The function initiates code for finding minimal issue delay values. - It should be called only once. */ -static void -initiate_min_issue_delay_pass_states () -{ - curr_state_pass_num = 0; -} - -/* Form and output vectors representing minimal issue delay table of - AUTOMATON. The table is state x ainsn -> minimal issue delay of - the ainsn. */ -static void -output_min_issue_delay_table (automaton) - automaton_t automaton; -{ - vla_hwint_t min_issue_delay_vect; - vla_hwint_t compressed_min_issue_delay_vect; - vect_el_t min_delay; - ainsn_t ainsn; - state_t *state_ptr; - int i; - - /* Create vect of pointers to states ordered by num of transitions - from the state (state with the maximum num is the first). */ - VLA_PTR_CREATE (output_states_vect, 1500, "output states vector"); - pass_states (automaton, add_states_vect_el); - VLA_HWINT_CREATE (min_issue_delay_vect, 1500, "min issue delay vector"); - VLA_HWINT_EXPAND (min_issue_delay_vect, - VLA_HWINT_LENGTH (output_states_vect) - * automaton->insn_equiv_classes_num); - for (i = 0; - i < ((int) VLA_HWINT_LENGTH (output_states_vect) - * automaton->insn_equiv_classes_num); - i++) - VLA_HWINT (min_issue_delay_vect, i) = 0; - automaton->max_min_delay = 0; - for (state_ptr = VLA_PTR_BEGIN (output_states_vect); - state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect); - state_ptr++) - { - for (ainsn = automaton->ainsn_list; - ainsn != NULL; - ainsn = ainsn->next_ainsn) - if (ainsn->first_ainsn_with_given_equialence_num) - { - min_delay = min_issue_delay (*state_ptr, ainsn); - if (automaton->max_min_delay < min_delay) - automaton->max_min_delay = min_delay; - VLA_HWINT (min_issue_delay_vect, - (*state_ptr)->order_state_num - * automaton->insn_equiv_classes_num - + ainsn->insn_equiv_class_num) = min_delay; - } - } - fprintf (output_file, "/* Vector of min issue delay of insns.*/\n"); - fprintf (output_file, "static const "); - output_range_type (output_file, 0, automaton->max_min_delay); - fprintf (output_file, " "); - output_min_issue_delay_vect_name (output_file, automaton); - fprintf (output_file, "[] = {\n"); - /* Compress the vector */ - if (automaton->max_min_delay < 2) - automaton->min_issue_delay_table_compression_factor = 8; - else if (automaton->max_min_delay < 4) - automaton->min_issue_delay_table_compression_factor = 4; - else if (automaton->max_min_delay < 16) - automaton->min_issue_delay_table_compression_factor = 2; - else - automaton->min_issue_delay_table_compression_factor = 1; - VLA_HWINT_CREATE (compressed_min_issue_delay_vect, 1500, - "compressed min issue delay vector"); - VLA_HWINT_EXPAND (compressed_min_issue_delay_vect, - (VLA_HWINT_LENGTH (min_issue_delay_vect) - + automaton->min_issue_delay_table_compression_factor - - 1) - / automaton->min_issue_delay_table_compression_factor); - for (i = 0; - i < (int) VLA_HWINT_LENGTH (compressed_min_issue_delay_vect); - i++) - VLA_HWINT (compressed_min_issue_delay_vect, i) = 0; - for (i = 0; i < (int) VLA_HWINT_LENGTH (min_issue_delay_vect); i++) - VLA_HWINT (compressed_min_issue_delay_vect, - i / automaton->min_issue_delay_table_compression_factor) - |= (VLA_HWINT (min_issue_delay_vect, i) - << (8 - (i % automaton->min_issue_delay_table_compression_factor - + 1) - * (8 / automaton->min_issue_delay_table_compression_factor))); - output_vect (VLA_HWINT_BEGIN (compressed_min_issue_delay_vect), - VLA_HWINT_LENGTH (compressed_min_issue_delay_vect)); - fprintf (output_file, "};\n\n"); - VLA_PTR_DELETE (output_states_vect); - VLA_HWINT_DELETE (min_issue_delay_vect); - VLA_HWINT_DELETE (compressed_min_issue_delay_vect); -} - -#ifndef NDEBUG -/* Number of states which contains transition only by advancing cpu - cycle. */ -static int locked_states_num; -#endif - -/* Form and output vector representing the locked states of - AUTOMATON. */ -static void -output_dead_lock_vect (automaton) - automaton_t automaton; -{ - state_t *state_ptr; - arc_t arc; - vla_hwint_t dead_lock_vect; - - /* Create vect of pointers to states ordered by num of - transitions from the state (state with the maximum num is the - first). */ - VLA_PTR_CREATE (output_states_vect, 1500, "output states vector"); - pass_states (automaton, add_states_vect_el); - VLA_HWINT_CREATE (dead_lock_vect, 1500, "is dead locked vector"); - VLA_HWINT_EXPAND (dead_lock_vect, VLA_HWINT_LENGTH (output_states_vect)); - for (state_ptr = VLA_PTR_BEGIN (output_states_vect); - state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect); - state_ptr++) - { - arc = first_out_arc (*state_ptr); - if (arc == NULL) - abort (); - VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num) - = (next_out_arc (arc) == NULL - && (arc->insn->insn_reserv_decl - == &advance_cycle_insn_decl->decl.insn_reserv) ? 1 : 0); -#ifndef NDEBUG - if (VLA_HWINT (dead_lock_vect, (*state_ptr)->order_state_num)) - locked_states_num++; -#endif - } - fprintf (output_file, "/* Vector for locked state flags. */\n"); - fprintf (output_file, "static const "); - output_range_type (output_file, 0, 1); - fprintf (output_file, " "); - output_dead_lock_vect_name (output_file, automaton); - fprintf (output_file, "[] = {\n"); - output_vect (VLA_HWINT_BEGIN (dead_lock_vect), - VLA_HWINT_LENGTH (dead_lock_vect)); - fprintf (output_file, "};\n\n"); - VLA_HWINT_DELETE (dead_lock_vect); - VLA_PTR_DELETE (output_states_vect); -} - -/* Form and output vector representing reserved units of the states of - AUTOMATON. */ -static void -output_reserved_units_table (automaton) - automaton_t automaton; -{ - state_t *curr_state_ptr; - vla_hwint_t reserved_units_table; - size_t state_byte_size; - int i; - - /* Create vect of pointers to states. */ - VLA_PTR_CREATE (output_states_vect, 1500, "output states vector"); - pass_states (automaton, add_states_vect_el); - /* Create vector. */ - VLA_HWINT_CREATE (reserved_units_table, 1500, "reserved units vector"); - state_byte_size = (description->query_units_num + 7) / 8; - VLA_HWINT_EXPAND (reserved_units_table, - VLA_HWINT_LENGTH (output_states_vect) * state_byte_size); - for (i = 0; - i < (int) (VLA_HWINT_LENGTH (output_states_vect) * state_byte_size); - i++) - VLA_HWINT (reserved_units_table, i) = 0; - for (curr_state_ptr = VLA_PTR_BEGIN (output_states_vect); - curr_state_ptr <= (state_t *) VLA_PTR_LAST (output_states_vect); - curr_state_ptr++) - { - for (i = 0; i < description->units_num; i++) - if (units_array [i]->query_p) - { - if (test_unit_reserv ((*curr_state_ptr)->reservs, 0, i)) - VLA_HWINT (reserved_units_table, - (*curr_state_ptr)->order_state_num * state_byte_size - + units_array [i]->query_num / 8) - += (1 << (units_array [i]->query_num % 8)); - } - } - fprintf (output_file, "/* Vector for reserved units of states. */\n"); - fprintf (output_file, "static const "); - output_range_type (output_file, 0, 255); - fprintf (output_file, " "); - output_reserved_units_table_name (output_file, automaton); - fprintf (output_file, "[] = {\n"); - output_vect (VLA_HWINT_BEGIN (reserved_units_table), - VLA_HWINT_LENGTH (reserved_units_table)); - fprintf (output_file, "};\n\n"); - VLA_HWINT_DELETE (reserved_units_table); - VLA_PTR_DELETE (output_states_vect); -} - -/* The function outputs all tables representing DFA(s) used for fast - pipeline hazards recognition. */ -static void -output_tables () -{ - automaton_t automaton; - -#ifndef NDEBUG - locked_states_num = 0; -#endif - initiate_min_issue_delay_pass_states (); - for (automaton = description->first_automaton; - automaton != NULL; - automaton = automaton->next_automaton) - { - output_translate_vect (automaton); - output_trans_table (automaton); - fprintf (output_file, "\n#if %s\n", AUTOMATON_STATE_ALTS_MACRO_NAME); - output_state_alts_table (automaton); - fprintf (output_file, "\n#endif /* #if %s */\n\n", - AUTOMATON_STATE_ALTS_MACRO_NAME); - output_min_issue_delay_table (automaton); - output_dead_lock_vect (automaton); - if (no_minimization_flag) - { - fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME); - output_reserved_units_table (automaton); - fprintf (output_file, "\n#endif /* #if %s */\n\n", - CPU_UNITS_QUERY_MACRO_NAME); - } - } - fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME, - advance_cycle_insn_decl->decl.insn_reserv.insn_num); -} - -/* The function outputs definition and value of PHR interface variable - `max_insn_queue_index' */ -static void -output_max_insn_queue_index_def () -{ - int i; - - for (i = 0; (1 << i) <= description->max_insn_reserv_cycles; i++) - ; - if (i < 0) - abort (); - fprintf (output_file, "\nint max_insn_queue_index = %d;\n\n", (1 << i) - 1); -} - - -/* Output function `internal_min_issue_delay'. */ -static void -output_internal_min_issue_delay_func () -{ - automaton_t automaton; - - fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n", - INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, CHIP_NAME); - fprintf (output_file, - "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n", - INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME, - CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, - CHIP_PARAMETER_NAME); - fprintf (output_file, "{\n int %s;\n int %s;\n", - TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME); - for (automaton = description->first_automaton; - automaton != NULL; - automaton = automaton->next_automaton) - { - fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME); - output_min_issue_delay_vect_name (output_file, automaton); - fprintf (output_file, - (automaton->min_issue_delay_table_compression_factor != 1 - ? " [(" : " [")); - output_translate_vect_name (output_file, automaton); - fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME); - fprintf (output_file, "%s->", CHIP_PARAMETER_NAME); - output_chip_member_name (output_file, automaton); - fprintf (output_file, " * %d", automaton->insn_equiv_classes_num); - if (automaton->min_issue_delay_table_compression_factor == 1) - fprintf (output_file, "];\n"); - else - { - fprintf (output_file, ") / %d];\n", - automaton->min_issue_delay_table_compression_factor); - fprintf (output_file, " %s = (%s >> (8 - (", - TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME); - output_translate_vect_name (output_file, automaton); - fprintf - (output_file, " [%s] %% %d + 1) * %d)) & %d;\n", - INTERNAL_INSN_CODE_NAME, - automaton->min_issue_delay_table_compression_factor, - 8 / automaton->min_issue_delay_table_compression_factor, - (1 << (8 / automaton->min_issue_delay_table_compression_factor)) - - 1); - } - if (automaton == description->first_automaton) - fprintf (output_file, " %s = %s;\n", - RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME); - else - { - fprintf (output_file, " if (%s > %s)\n", - TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME); - fprintf (output_file, " %s = %s;\n", - RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME); - } - } - fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME); - fprintf (output_file, "}\n\n"); -} - -/* Output function `internal_state_transition'. */ -static void -output_internal_trans_func () -{ - automaton_t curr_automaton; - automaton_t next_automaton; - - fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n", - INTERNAL_TRANSITION_FUNC_NAME, CHIP_NAME); - fprintf (output_file, - "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n", - INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, - CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, - CHIP_NAME, CHIP_PARAMETER_NAME); - fprintf (output_file, "{\n int %s;\n", TEMPORARY_VARIABLE_NAME); - if (description->first_automaton != NULL) - for (curr_automaton = description->first_automaton;; - curr_automaton = next_automaton) - { - next_automaton = curr_automaton->next_automaton; - if (next_automaton == NULL) - break; - fprintf (output_file, " "); - output_state_member_type (output_file, curr_automaton); - fprintf (output_file, " "); - output_temp_chip_member_name (output_file, curr_automaton); - fprintf (output_file, ";\n"); - } - for (curr_automaton = description->first_automaton; - curr_automaton != NULL; - curr_automaton = curr_automaton->next_automaton) - if (comb_vect_p (curr_automaton->trans_table)) - { - fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME); - output_trans_base_vect_name (output_file, curr_automaton); - fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME); - output_chip_member_name (output_file, curr_automaton); - fprintf (output_file, "] + "); - output_translate_vect_name (output_file, curr_automaton); - fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME); - fprintf (output_file, " if ("); - output_trans_check_vect_name (output_file, curr_automaton); - fprintf (output_file, " [%s] != %s->", - TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME); - output_chip_member_name (output_file, curr_automaton); - fprintf (output_file, ")\n"); - fprintf (output_file, " return %s (%s, %s);\n", - INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME, - CHIP_PARAMETER_NAME); - fprintf (output_file, " else\n"); - fprintf (output_file, " "); - if (curr_automaton->next_automaton != NULL) - output_temp_chip_member_name (output_file, curr_automaton); - else - { - fprintf (output_file, "%s->", CHIP_PARAMETER_NAME); - output_chip_member_name (output_file, curr_automaton); - } - fprintf (output_file, " = "); - output_trans_comb_vect_name (output_file, curr_automaton); - fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME); - } - else - { - fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME); - output_trans_full_vect_name (output_file, curr_automaton); - fprintf (output_file, " ["); - output_translate_vect_name (output_file, curr_automaton); - fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME); - fprintf (output_file, "%s->", CHIP_PARAMETER_NAME); - output_chip_member_name (output_file, curr_automaton); - fprintf (output_file, " * %d];\n", - curr_automaton->insn_equiv_classes_num); - fprintf (output_file, " if (%s >= %d)\n", TEMPORARY_VARIABLE_NAME, - curr_automaton->achieved_states_num); - fprintf (output_file, " return %s (%s, %s);\n", - INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME, - CHIP_PARAMETER_NAME); - fprintf (output_file, " else\n "); - if (curr_automaton->next_automaton != NULL) - output_temp_chip_member_name (output_file, curr_automaton); - else - { - fprintf (output_file, "%s->", CHIP_PARAMETER_NAME); - output_chip_member_name (output_file, curr_automaton); - } - fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME); - } - if (description->first_automaton != NULL) - for (curr_automaton = description->first_automaton;; - curr_automaton = next_automaton) - { - next_automaton = curr_automaton->next_automaton; - if (next_automaton == NULL) - break; - fprintf (output_file, " %s->", CHIP_PARAMETER_NAME); - output_chip_member_name (output_file, curr_automaton); - fprintf (output_file, " = "); - output_temp_chip_member_name (output_file, curr_automaton); - fprintf (output_file, ";\n"); - } - fprintf (output_file, " return -1;\n"); - fprintf (output_file, "}\n\n"); -} - -/* Output code - - if (insn != 0) - { - insn_code = dfa_insn_code (insn); - if (insn_code > DFA__ADVANCE_CYCLE) - return code; - } - else - insn_code = DFA__ADVANCE_CYCLE; - - where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and - code denotes CODE. */ -static void -output_internal_insn_code_evaluation (insn_name, insn_code_name, code) - const char *insn_name; - const char *insn_code_name; - int code; -{ - fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name); - fprintf (output_file, " %s = %s (%s);\n", insn_code_name, - DFA_INSN_CODE_FUNC_NAME, insn_name); - fprintf (output_file, " if (%s > %s)\n return %d;\n", - insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code); - fprintf (output_file, " }\n else\n %s = %s;\n\n", - insn_code_name, ADVANCE_CYCLE_VALUE_NAME); -} - - -/* The function outputs function `dfa_insn_code'. */ -static void -output_dfa_insn_code_func () -{ - fprintf (output_file, "#ifdef __GNUC__\n__inline__\n#endif\n"); - fprintf (output_file, "static int %s PARAMS ((rtx));\n", - DFA_INSN_CODE_FUNC_NAME); - fprintf (output_file, "static int\n%s (%s)\n\trtx %s;\n", - DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME, INSN_PARAMETER_NAME); - fprintf (output_file, "{\n int %s;\n\n", INTERNAL_INSN_CODE_NAME); - fprintf (output_file, " if ((%s = %s [INSN_UID (%s)]) < 0)\n {\n", - INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME, - INSN_PARAMETER_NAME); - fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME, - INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME); - fprintf (output_file, " %s [INSN_UID (%s)] = %s;\n", - DFA_INSN_CODES_VARIABLE_NAME, INSN_PARAMETER_NAME, - INTERNAL_INSN_CODE_NAME); - fprintf (output_file, " }\n return %s;\n}\n\n", - INTERNAL_INSN_CODE_NAME); -} - -/* The function outputs PHR interface function `state_transition'. */ -static void -output_trans_func () -{ - fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n", - TRANSITION_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME, - STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME); - fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME); - output_internal_insn_code_evaluation (INSN_PARAMETER_NAME, - INTERNAL_INSN_CODE_NAME, -1); - fprintf (output_file, " return %s (%s, %s);\n}\n\n", - INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME); -} - -/* Output function `internal_state_alts'. */ -static void -output_internal_state_alts_func () -{ - automaton_t automaton; - - fprintf (output_file, "static int %s PARAMS ((int, struct %s *));\n", - INTERNAL_STATE_ALTS_FUNC_NAME, CHIP_NAME); - fprintf (output_file, - "static int\n%s (%s, %s)\n\tint %s;\n\tstruct %s *%s;\n", - INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, - CHIP_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, - CHIP_PARAMETER_NAME); - fprintf (output_file, "{\n int %s;\n", RESULT_VARIABLE_NAME); - for (automaton = description->first_automaton; - automaton != NULL; - automaton = automaton->next_automaton) - if (comb_vect_p (automaton->state_alts_table)) - { - fprintf (output_file, " int %s;\n", TEMPORARY_VARIABLE_NAME); - break; - } - for (automaton = description->first_automaton; - automaton != NULL; - automaton = automaton->next_automaton) - if (comb_vect_p (automaton->state_alts_table)) - { - fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME); - output_state_alts_base_vect_name (output_file, automaton); - fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME); - output_chip_member_name (output_file, automaton); - fprintf (output_file, "] + "); - output_translate_vect_name (output_file, automaton); - fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME); - fprintf (output_file, " if ("); - output_state_alts_check_vect_name (output_file, automaton); - fprintf (output_file, " [%s] != %s->", - TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME); - output_chip_member_name (output_file, automaton); - fprintf (output_file, ")\n"); - fprintf (output_file, " return 0;\n"); - fprintf (output_file, " else\n"); - fprintf (output_file, - (automaton == description->first_automaton - ? " %s = " : " %s += "), RESULT_VARIABLE_NAME); - output_state_alts_comb_vect_name (output_file, automaton); - fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME); - } - else - { - fprintf (output_file, - (automaton == description->first_automaton - ? "\n %s = " : " %s += "), RESULT_VARIABLE_NAME); - output_state_alts_full_vect_name (output_file, automaton); - fprintf (output_file, " ["); - output_translate_vect_name (output_file, automaton); - fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME); - fprintf (output_file, "%s->", CHIP_PARAMETER_NAME); - output_chip_member_name (output_file, automaton); - fprintf (output_file, " * %d];\n", automaton->insn_equiv_classes_num); - } - fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME); - fprintf (output_file, "}\n\n"); -} - -/* The function outputs PHR interface function `state_alts'. */ -static void -output_state_alts_func () -{ - fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n", - STATE_ALTS_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME, - STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME); - fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME); - output_internal_insn_code_evaluation (INSN_PARAMETER_NAME, - INTERNAL_INSN_CODE_NAME, 0); - fprintf (output_file, " return %s (%s, %s);\n}\n\n", - INTERNAL_STATE_ALTS_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME); -} - -/* Output function `min_issue_delay'. */ -static void -output_min_issue_delay_func () -{ - fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\trtx %s;\n", - MIN_ISSUE_DELAY_FUNC_NAME, STATE_NAME, INSN_PARAMETER_NAME, - STATE_TYPE_NAME, STATE_NAME, INSN_PARAMETER_NAME); - fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME); - fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME); - fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME, - DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME); - fprintf (output_file, " if (%s > %s)\n return 0;\n", - INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME); - fprintf (output_file, " }\n else\n %s = %s;\n", - INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME); - fprintf (output_file, "\n return %s (%s, %s);\n", - INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME, - STATE_NAME); - fprintf (output_file, "}\n\n"); -} - -/* Output function `internal_dead_lock'. */ -static void -output_internal_dead_lock_func () -{ - automaton_t automaton; - - fprintf (output_file, "static int %s PARAMS ((struct %s *));\n", - INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME); - fprintf (output_file, "static int\n%s (%s)\n\tstruct %s *%s;\n", - INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_PARAMETER_NAME, CHIP_NAME, - CHIP_PARAMETER_NAME); - fprintf (output_file, "{\n"); - for (automaton = description->first_automaton; - automaton != NULL; - automaton = automaton->next_automaton) - { - fprintf (output_file, " if ("); - output_dead_lock_vect_name (output_file, automaton); - fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME); - output_chip_member_name (output_file, automaton); - fprintf (output_file, "])\n return 1/* TRUE */;\n"); - } - fprintf (output_file, " return 0/* FALSE */;\n}\n\n"); -} - -/* The function outputs PHR interface function `state_dead_lock_p'. */ -static void -output_dead_lock_func () -{ - fprintf (output_file, "int\n%s (%s)\n\t%s %s;\n", - DEAD_LOCK_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME); - fprintf (output_file, "{\n return %s (%s);\n}\n\n", - INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME); -} - -/* Output function `internal_reset'. */ -static void -output_internal_reset_func () -{ - fprintf (output_file, "static void %s PARAMS ((struct %s *));\n", - INTERNAL_RESET_FUNC_NAME, CHIP_NAME); - fprintf (output_file, "static void\n%s (%s)\n\tstruct %s *%s;\n", - INTERNAL_RESET_FUNC_NAME, CHIP_PARAMETER_NAME, - CHIP_NAME, CHIP_PARAMETER_NAME); - fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n", - CHIP_PARAMETER_NAME, CHIP_NAME); -} - -/* The function outputs PHR interface function `state_size'. */ -static void -output_size_func () -{ - fprintf (output_file, "int\n%s ()\n", SIZE_FUNC_NAME); - fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME); -} - -/* The function outputs PHR interface function `state_reset'. */ -static void -output_reset_func () -{ - fprintf (output_file, "void\n%s (%s)\n\t %s %s;\n", - RESET_FUNC_NAME, STATE_NAME, STATE_TYPE_NAME, STATE_NAME); - fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME, - STATE_NAME); -} - -/* Output function `min_insn_conflict_delay'. */ -static void -output_min_insn_conflict_delay_func () -{ - fprintf (output_file, - "int\n%s (%s, %s, %s)\n\t%s %s;\n\trtx %s;\n\trtx %s;\n", - MIN_INSN_CONFLICT_DELAY_FUNC_NAME, - STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME, - STATE_TYPE_NAME, STATE_NAME, - INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME); - fprintf (output_file, "{\n struct %s %s;\n int %s, %s;\n", - CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME, - INTERNAL_INSN2_CODE_NAME); - output_internal_insn_code_evaluation (INSN_PARAMETER_NAME, - INTERNAL_INSN_CODE_NAME, 0); - output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME, - INTERNAL_INSN2_CODE_NAME, 0); - fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n", - CHIP_NAME, STATE_NAME, CHIP_NAME); - fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME); - fprintf (output_file, " if (%s (%s, &%s) > 0)\n abort ();\n", - INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME); - fprintf (output_file, " return %s (%s, &%s);\n", - INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME, - CHIP_NAME); - fprintf (output_file, "}\n\n"); -} - -/* Output function `internal_insn_latency'. */ -static void -output_internal_insn_latency_func () -{ - decl_t decl; - struct bypass_decl *bypass; - int i; - - fprintf (output_file, "static int %s PARAMS ((int, int, rtx, rtx));\n", - INTERNAL_INSN_LATENCY_FUNC_NAME); - fprintf (output_file, "static int\n%s (%s, %s, %s, %s)", - INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME, - INTERNAL_INSN2_CODE_NAME, - INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME); - fprintf (output_file, "\n\tint %s;\n\tint %s;\n", - INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME); - fprintf (output_file, - "\trtx %s ATTRIBUTE_UNUSED;\n\trtx %s ATTRIBUTE_UNUSED;\n", - INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME); - fprintf (output_file, "{\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME); - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_insn_reserv) - { - fprintf (output_file, " case %d:\n", - decl->decl.insn_reserv.insn_num); - if (decl->decl.insn_reserv.bypass_list == NULL) - fprintf (output_file, " return (%s != %s ? %d : 0);\n", - INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME, - decl->decl.insn_reserv.default_latency); - else - { - fprintf (output_file, " switch (%s)\n {\n", - INTERNAL_INSN2_CODE_NAME); - for (bypass = decl->decl.insn_reserv.bypass_list; - bypass != NULL; - bypass = bypass->next) - { - fprintf (output_file, " case %d:\n", - bypass->in_insn_reserv->insn_num); - if (bypass->bypass_guard_name == NULL) - fprintf (output_file, " return %d;\n", - bypass->latency); - else - fprintf (output_file, - " return (%s (%s, %s) ? %d : %d);\n", - bypass->bypass_guard_name, INSN_PARAMETER_NAME, - INSN2_PARAMETER_NAME, bypass->latency, - decl->decl.insn_reserv.default_latency); - } - fprintf (output_file, " default:\n"); - fprintf (output_file, - " return (%s != %s ? %d : 0);\n }\n", - INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME, - decl->decl.insn_reserv.default_latency); - - } - } - } - fprintf (output_file, " default:\n return 0;\n }\n}\n\n"); -} - -/* The function outputs PHR interface function `insn_latency'. */ -static void -output_insn_latency_func () -{ - fprintf (output_file, "int\n%s (%s, %s)\n\trtx %s;\n\trtx %s;\n", - INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME, - INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME); - fprintf (output_file, "{\n int %s, %s;\n", - INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME); - output_internal_insn_code_evaluation (INSN_PARAMETER_NAME, - INTERNAL_INSN_CODE_NAME, 0); - output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME, - INTERNAL_INSN2_CODE_NAME, 0); - fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n", - INTERNAL_INSN_LATENCY_FUNC_NAME, - INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME, - INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME); -} - -/* The function outputs PHR interface function `print_reservation'. */ -static void -output_print_reservation_func () -{ - decl_t decl; - int i; - - fprintf (output_file, "void\n%s (%s, %s)\n\tFILE *%s;\n\trtx %s;\n", - PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME, - INSN_PARAMETER_NAME, FILE_PARAMETER_NAME, - INSN_PARAMETER_NAME); - fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME); - fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME); - fprintf (output_file, " %s = %s (%s);\n", - INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME, - INSN_PARAMETER_NAME); - fprintf (output_file, " if (%s > %s)\n", - INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME); - fprintf (output_file, " {\n fprintf (%s, \"%s\");\n", - FILE_PARAMETER_NAME, NOTHING_NAME); - fprintf (output_file, " return;\n }\n"); - fprintf (output_file, " }\n else\n"); - fprintf (output_file, - " {\n fprintf (%s, \"%s\");\n return;\n }\n", - FILE_PARAMETER_NAME, NOTHING_NAME); - fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME); - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl) - { - fprintf (output_file, - " case %d:\n", decl->decl.insn_reserv.insn_num); - fprintf (output_file, - " fprintf (%s, \"%s\");\n break;\n", - FILE_PARAMETER_NAME, - regexp_representation (decl->decl.insn_reserv.regexp)); - finish_regexp_representation (); - } - } - fprintf (output_file, " default:\n fprintf (%s, \"%s\");\n }\n", - FILE_PARAMETER_NAME, NOTHING_NAME); - fprintf (output_file, "}\n\n"); -} - -/* The following function is used to sort unit declaration by their - names. */ -static int -units_cmp (unit1, unit2) - const void *unit1, *unit2; -{ - const struct unit_decl *u1 = *(struct unit_decl **) unit1; - const struct unit_decl *u2 = *(struct unit_decl **) unit2; - - return strcmp (u1->name, u2->name); -} - -/* The following macro value is name of struct containing unit name - and unit code. */ -#define NAME_CODE_STRUCT_NAME "name_code" - -/* The following macro value is name of table of struct name_code. */ -#define NAME_CODE_TABLE_NAME "name_code_table" - -/* The following macro values are member names for struct name_code. */ -#define NAME_MEMBER_NAME "name" -#define CODE_MEMBER_NAME "code" - -/* The following macro values are local variable names for function - `get_cpu_unit_code'. */ -#define CMP_VARIABLE_NAME "cmp" -#define LOW_VARIABLE_NAME "l" -#define MIDDLE_VARIABLE_NAME "m" -#define HIGH_VARIABLE_NAME "h" - -/* The following function outputs function to obtain internal cpu unit - code by the cpu unit name. */ -static void -output_get_cpu_unit_code_func () -{ - int i; - struct unit_decl **units; - - fprintf (output_file, "int\n%s (%s)\n\tconst char *%s;\n", - GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME, - CPU_UNIT_NAME_PARAMETER_NAME); - fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n", - NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME); - fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME, - LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME); - fprintf (output_file, " static struct %s %s [] =\n {\n", - NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME); - units = (struct unit_decl **) xmalloc (sizeof (struct unit_decl *) - * description->units_num); - memcpy (units, units_array, - sizeof (struct unit_decl *) * description->units_num); - qsort (units, description->units_num, - sizeof (struct unit_decl *), units_cmp); - for (i = 0; i < description->units_num; i++) - if (units [i]->query_p) - fprintf (output_file, " {\"%s\", %d},\n", - units[i]->name, units[i]->query_num); - fprintf (output_file, " };\n\n"); - fprintf (output_file, " /* The following is binary search: */\n"); - fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME); - fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n", - HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME); - fprintf (output_file, " while (%s <= %s)\n {\n", - LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME); - fprintf (output_file, " %s = (%s + %s) / 2;\n", - MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME); - fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n", - CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME, - NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME); - fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME); - fprintf (output_file, " %s = %s - 1;\n", - HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME); - fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME); - fprintf (output_file, " %s = %s + 1;\n", - LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME); - fprintf (output_file, " else\n"); - fprintf (output_file, " return %s [%s].%s;\n }\n", - NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME); - fprintf (output_file, " return -1;\n}\n\n"); - free (units); -} - -/* The following function outputs function to check reservation of cpu - unit (its internal code will be passed as the function argument) in - given cpu state. */ -static void -output_cpu_unit_reservation_p () -{ - automaton_t automaton; - - fprintf (output_file, "int\n%s (%s, %s)\n\t%s %s;\n\tint %s;\n", - CPU_UNIT_RESERVATION_P_FUNC_NAME, STATE_NAME, - CPU_CODE_PARAMETER_NAME, STATE_TYPE_NAME, STATE_NAME, - CPU_CODE_PARAMETER_NAME); - fprintf (output_file, "{\n if (%s < 0 || %s >= %d)\n abort ();\n", - CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME, - description->query_units_num); - for (automaton = description->first_automaton; - automaton != NULL; - automaton = automaton->next_automaton) - { - fprintf (output_file, " if (("); - output_reserved_units_table_name (output_file, automaton); - fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME); - output_chip_member_name (output_file, automaton); - fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n", - (description->query_units_num + 7) / 8, - CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME); - fprintf (output_file, " return 1;\n"); - } - fprintf (output_file, " return 0;\n}\n\n"); -} - -/* The function outputs PHR interface function `dfa_start'. */ -static void -output_dfa_start_func () -{ - fprintf (output_file, - "void\n%s ()\n{\n int %s;\n int %s = get_max_uid ();\n\n", - DFA_START_FUNC_NAME, I_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME); - fprintf (output_file, " %s = (int *) xmalloc (%s * sizeof (int));\n", - DFA_INSN_CODES_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME); - fprintf (output_file, - " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n", - I_VARIABLE_NAME, I_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME, - I_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME); -} - -/* The function outputs PHR interface function `dfa_finish'. */ -static void -output_dfa_finish_func () -{ - fprintf (output_file, "void\n%s ()\n{\n free (%s);\n}\n\n", - DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME); -} - - - -/* The page contains code for output description file (readable - representation of original description and generated DFA(s). */ - -/* The function outputs string representation of IR reservation. */ -static void -output_regexp (regexp) - regexp_t regexp; -{ - fprintf (output_description_file, "%s", regexp_representation (regexp)); - finish_regexp_representation (); -} - -/* Output names of units in LIST separated by comma. */ -static void -output_unit_set_el_list (list) - unit_set_el_t list; -{ - unit_set_el_t el; - - for (el = list; el != NULL; el = el->next_unit_set_el) - { - if (el != list) - fprintf (output_description_file, ","); - fprintf (output_description_file, "%s", el->unit_decl->name); - } -} - -/* The function outputs string representation of IR define_reservation - and define_insn_reservation. */ -static void -output_description () -{ - decl_t decl; - int i; - - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_unit) - { - if (decl->decl.unit.excl_list != NULL) - { - fprintf (output_description_file, "unit %s exlusion_set: ", - decl->decl.unit.name); - output_unit_set_el_list (decl->decl.unit.excl_list); - fprintf (output_description_file, "\n"); - } - if (decl->decl.unit.presence_list != NULL) - { - fprintf (output_description_file, "unit %s presence_set: ", - decl->decl.unit.name); - output_unit_set_el_list (decl->decl.unit.presence_list); - fprintf (output_description_file, "\n"); - } - if (decl->decl.unit.absence_list != NULL) - { - fprintf (output_description_file, "unit %s absence_set: ", - decl->decl.unit.name); - output_unit_set_el_list (decl->decl.unit.absence_list); - fprintf (output_description_file, "\n"); - } - } - } - fprintf (output_description_file, "\n"); - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_reserv) - { - fprintf (output_description_file, "reservation "); - fprintf (output_description_file, decl->decl.reserv.name); - fprintf (output_description_file, ": "); - output_regexp (decl->decl.reserv.regexp); - fprintf (output_description_file, "\n"); - } - else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl) - { - fprintf (output_description_file, "insn reservation %s ", - decl->decl.insn_reserv.name); - print_rtl (output_description_file, decl->decl.insn_reserv.condexp); - fprintf (output_description_file, ": "); - output_regexp (decl->decl.insn_reserv.regexp); - fprintf (output_description_file, "\n"); - } - else if (decl->mode == dm_bypass) - fprintf (output_description_file, "bypass %d %s %s\n", - decl->decl.bypass.latency, decl->decl.bypass.out_insn_name, - decl->decl.bypass.in_insn_name); - } - fprintf (output_description_file, "\n\f\n"); -} - -/* The function outputs name of AUTOMATON. */ -static void -output_automaton_name (f, automaton) - FILE *f; - automaton_t automaton; -{ - if (automaton->corresponding_automaton_decl == NULL) - fprintf (f, "#%d", automaton->automaton_order_num); - else - fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name); -} - -/* Maximal length of line for pretty printing into description - file. */ -#define MAX_LINE_LENGTH 70 - -/* The function outputs units name belonging to AUTOMATON. */ -static void -output_automaton_units (automaton) - automaton_t automaton; -{ - decl_t decl; - char *name; - int curr_line_length; - int there_is_an_automaton_unit; - int i; - - fprintf (output_description_file, "\n Coresponding units:\n"); - fprintf (output_description_file, " "); - curr_line_length = 4; - there_is_an_automaton_unit = 0; - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_unit - && (decl->decl.unit.corresponding_automaton_num - == automaton->automaton_order_num)) - { - there_is_an_automaton_unit = 1; - name = decl->decl.unit.name; - if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH ) - { - curr_line_length = strlen (name) + 4; - fprintf (output_description_file, "\n "); - } - else - { - curr_line_length += strlen (name) + 1; - fprintf (output_description_file, " "); - } - fprintf (output_description_file, name); - } - } - if (!there_is_an_automaton_unit) - fprintf (output_description_file, "<None>"); - fprintf (output_description_file, "\n\n"); -} - -/* The following variable is used for forming array of all possible cpu unit - reservations described by the current DFA state. */ -static vla_ptr_t state_reservs; - -/* The function forms `state_reservs' for STATE. */ -static void -add_state_reservs (state) - state_t state; -{ - alt_state_t curr_alt_state; - reserv_sets_t reservs; - - if (state->component_states != NULL) - for (curr_alt_state = state->component_states; - curr_alt_state != NULL; - curr_alt_state = curr_alt_state->next_sorted_alt_state) - add_state_reservs (curr_alt_state->state); - else - { - reservs = state->reservs; - VLA_PTR_ADD (state_reservs, reservs); - } -} - -/* The function outputs readable represenatation of all out arcs of - STATE. */ -static void -output_state_arcs (state) - state_t state; -{ - arc_t arc; - ainsn_t ainsn; - char *insn_name; - int curr_line_length; - - for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc)) - { - ainsn = arc->insn; - if (!ainsn->first_insn_with_same_reservs) - abort (); - fprintf (output_description_file, " "); - curr_line_length = 7; - fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num); - do - { - insn_name = ainsn->insn_reserv_decl->name; - if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH) - { - if (ainsn != arc->insn) - { - fprintf (output_description_file, ",\n "); - curr_line_length = strlen (insn_name) + 6; - } - else - curr_line_length += strlen (insn_name); - } - else - { - curr_line_length += strlen (insn_name); - if (ainsn != arc->insn) - { - curr_line_length += 2; - fprintf (output_description_file, ", "); - } - } - fprintf (output_description_file, insn_name); - ainsn = ainsn->next_same_reservs_insn; - } - while (ainsn != NULL); - fprintf (output_description_file, " %d (%d)\n", - arc->to_state->order_state_num, arc->state_alts); - } - fprintf (output_description_file, "\n"); -} - -/* The following function is used for sorting possible cpu unit - reservation of a DFA state. */ -static int -state_reservs_cmp (reservs_ptr_1, reservs_ptr_2) - const void *reservs_ptr_1; - const void *reservs_ptr_2; -{ - return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1, - *(reserv_sets_t *) reservs_ptr_2); -} - -/* The following function is used for sorting possible cpu unit - reservation of a DFA state. */ -static void -remove_state_duplicate_reservs () -{ - reserv_sets_t *reservs_ptr; - reserv_sets_t *last_formed_reservs_ptr; - - last_formed_reservs_ptr = NULL; - for (reservs_ptr = VLA_PTR_BEGIN (state_reservs); - reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs); - reservs_ptr++) - if (last_formed_reservs_ptr == NULL) - last_formed_reservs_ptr = reservs_ptr; - else if (reserv_sets_cmp (*last_formed_reservs_ptr, *reservs_ptr) != 0) - { - ++last_formed_reservs_ptr; - *last_formed_reservs_ptr = *reservs_ptr; - } - VLA_PTR_SHORTEN (state_reservs, reservs_ptr - last_formed_reservs_ptr - 1); -} - -/* The following function output readable representation of DFA(s) - state used for fast recognition of pipeline hazards. State is - described by possible (current and scehduled) cpu unit - reservations. */ -static void -output_state (state) - state_t state; -{ - reserv_sets_t *reservs_ptr; - - VLA_PTR_CREATE (state_reservs, 150, "state reservations"); - fprintf (output_description_file, " State #%d", state->order_state_num); - fprintf (output_description_file, - state->new_cycle_p ? " (new cycle)\n" : "\n"); - add_state_reservs (state); - qsort (VLA_PTR_BEGIN (state_reservs), VLA_PTR_LENGTH (state_reservs), - sizeof (reserv_sets_t), state_reservs_cmp); - remove_state_duplicate_reservs (); - for (reservs_ptr = VLA_PTR_BEGIN (state_reservs); - reservs_ptr <= (reserv_sets_t *) VLA_PTR_LAST (state_reservs); - reservs_ptr++) - { - fprintf (output_description_file, " "); - output_reserv_sets (output_description_file, *reservs_ptr); - fprintf (output_description_file, "\n"); - } - fprintf (output_description_file, "\n"); - output_state_arcs (state); - VLA_PTR_DELETE (state_reservs); -} - -/* The following function output readable representation of - DFAs used for fast recognition of pipeline hazards. */ -static void -output_automaton_descriptions () -{ - automaton_t automaton; - - for (automaton = description->first_automaton; - automaton != NULL; - automaton = automaton->next_automaton) - { - fprintf (output_description_file, "\nAutomaton "); - output_automaton_name (output_description_file, automaton); - fprintf (output_description_file, "\n"); - output_automaton_units (automaton); - pass_states (automaton, output_state); - } -} - - - -/* The page contains top level function for generation DFA(s) used for - PHR. */ - -/* The function outputs statistics about work of different phases of - DFA generator. */ -static void -output_statistics (f) - FILE *f; -{ - automaton_t automaton; -#ifndef NDEBUG - int transition_comb_vect_els = 0; - int transition_full_vect_els = 0; - int state_alts_comb_vect_els = 0; - int state_alts_full_vect_els = 0; - int min_issue_delay_vect_els = 0; -#endif - - for (automaton = description->first_automaton; - automaton != NULL; - automaton = automaton->next_automaton) - { - fprintf (f, "\nAutomaton "); - output_automaton_name (f, automaton); - fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n", - automaton->NDFA_states_num, automaton->NDFA_arcs_num); - fprintf (f, " %5d DFA states, %5d DFA arcs\n", - automaton->DFA_states_num, automaton->DFA_arcs_num); - if (!no_minimization_flag) - fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n", - automaton->minimal_DFA_states_num, - automaton->minimal_DFA_arcs_num); - fprintf (f, " %5d all insns %5d insn equivalence classes\n", - description->insns_num, automaton->insn_equiv_classes_num); -#ifndef NDEBUG - fprintf - (f, "%5ld transition comb vector els, %5ld trans table els: %s\n", - (long) VLA_HWINT_LENGTH (automaton->trans_table->comb_vect), - (long) VLA_HWINT_LENGTH (automaton->trans_table->full_vect), - (comb_vect_p (automaton->trans_table) - ? "use comb vect" : "use simple vect")); - fprintf - (f, "%5ld state alts comb vector els, %5ld state alts table els: %s\n", - (long) VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect), - (long) VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect), - (comb_vect_p (automaton->state_alts_table) - ? "use comb vect" : "use simple vect")); - fprintf - (f, "%5ld min delay table els, compression factor %d\n", - (long) automaton->DFA_states_num * automaton->insn_equiv_classes_num, - automaton->min_issue_delay_table_compression_factor); - transition_comb_vect_els - += VLA_HWINT_LENGTH (automaton->trans_table->comb_vect); - transition_full_vect_els - += VLA_HWINT_LENGTH (automaton->trans_table->full_vect); - state_alts_comb_vect_els - += VLA_HWINT_LENGTH (automaton->state_alts_table->comb_vect); - state_alts_full_vect_els - += VLA_HWINT_LENGTH (automaton->state_alts_table->full_vect); - min_issue_delay_vect_els - += automaton->DFA_states_num * automaton->insn_equiv_classes_num; -#endif - } -#ifndef NDEBUG - fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n", - allocated_states_num, allocated_arcs_num); - fprintf (f, "%5d all allocated alternative states\n", - allocated_alt_states_num); - fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n", - transition_comb_vect_els, transition_full_vect_els); - fprintf - (f, "%5d all state alts comb vector els, %5d all state alts table els\n", - state_alts_comb_vect_els, state_alts_full_vect_els); - fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els); - fprintf (f, "%5d locked states num\n", locked_states_num); -#endif -} - -/* The function output times of work of different phases of DFA - generator. */ -static void -output_time_statistics (f) - FILE *f; -{ - fprintf (f, "\n transformation: "); - print_active_time (f, transform_time); - fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: ")); - print_active_time (f, NDFA_time); - if (ndfa_flag) - { - fprintf (f, ", NDFA -> DFA: "); - print_active_time (f, NDFA_to_DFA_time); - } - fprintf (f, "\n DFA minimization: "); - print_active_time (f, minimize_time); - fprintf (f, ", making insn equivalence: "); - print_active_time (f, equiv_time); - fprintf (f, "\n all automaton generation: "); - print_active_time (f, automaton_generation_time); - fprintf (f, ", output: "); - print_active_time (f, output_time); - fprintf (f, "\n"); -} - -/* The function generates DFA (deterministic finate state automaton) - for fast recognition of pipeline hazards. No errors during - checking must be fixed before this function call. */ -static void -generate () -{ - automata_num = split_argument; - if (description->units_num < automata_num) - automata_num = description->units_num; - initiate_states (); - initiate_arcs (); - initiate_pass_states (); - initiate_excl_sets (); - initiate_presence_absence_sets (); - automaton_generation_time = create_ticker (); - transform_time = create_ticker (); - add_advance_cycle_insn_decl (); - fprintf (stderr, "Reservation transformation..."); - fflush (stderr); - transform_insn_regexps (); - fprintf (stderr, "done\n"); - ticker_off (&transform_time); - fprintf (stderr, "Create automata..."); - fflush (stderr); - create_automata (); - fprintf (stderr, "done\n"); - ticker_off (&automaton_generation_time); -} - - - -/* The following function creates attribute which order number of insn - in pipeline hazard description translator. */ -static void -make_insn_alts_attr () -{ - int i, insn_num; - decl_t decl; - rtx condexp; - - condexp = rtx_alloc (COND); - XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2); - XEXP (condexp, 1) = make_numeric_value (0); - for (i = insn_num = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl) - { - XVECEXP (condexp, 0, 2 * insn_num) = decl->decl.insn_reserv.condexp; - XVECEXP (condexp, 0, 2 * insn_num + 1) - = make_numeric_value (decl->decl.insn_reserv.transformed_regexp - ->regexp.oneof.regexps_num); - insn_num++; - } - } - if (description->insns_num != insn_num + 1) - abort (); - make_internal_attr (attr_printf (sizeof ("*") - + strlen (INSN_ALTS_FUNC_NAME) + 1, - "*%s", INSN_ALTS_FUNC_NAME), - condexp, 0); -} - - - -/* The following function creates attribute which is order number of - insn in pipeline hazard description translator. */ -static void -make_internal_dfa_insn_code_attr () -{ - int i, insn_num; - decl_t decl; - rtx condexp; - - condexp = rtx_alloc (COND); - XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2); - XEXP (condexp, 1) = make_numeric_value (advance_cycle_insn_decl - ->decl.insn_reserv.insn_num + 1); - for (i = insn_num = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl) - { - XVECEXP (condexp, 0, 2 * insn_num) = decl->decl.insn_reserv.condexp; - XVECEXP (condexp, 0, 2 * insn_num + 1) - = make_numeric_value (decl->decl.insn_reserv.insn_num); - insn_num++; - } - } - if (description->insns_num != insn_num + 1) - abort (); - make_internal_attr - (attr_printf (sizeof ("*") - + strlen (INTERNAL_DFA_INSN_CODE_FUNC_NAME) + 1, - "*%s", INTERNAL_DFA_INSN_CODE_FUNC_NAME), - condexp, 0); -} - - - -/* The following function creates attribute which order number of insn - in pipeline hazard description translator. */ -static void -make_default_insn_latency_attr () -{ - int i, insn_num; - decl_t decl; - rtx condexp; - - condexp = rtx_alloc (COND); - XVEC (condexp, 0) = rtvec_alloc ((description->insns_num - 1) * 2); - XEXP (condexp, 1) = make_numeric_value (0); - for (i = insn_num = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl) - { - XVECEXP (condexp, 0, 2 * insn_num) = decl->decl.insn_reserv.condexp; - XVECEXP (condexp, 0, 2 * insn_num + 1) - = make_numeric_value (decl->decl.insn_reserv.default_latency); - insn_num++; - } - } - if (description->insns_num != insn_num + 1) - abort (); - make_internal_attr (attr_printf (sizeof ("*") - + strlen (INSN_DEFAULT_LATENCY_FUNC_NAME) - + 1, "*%s", INSN_DEFAULT_LATENCY_FUNC_NAME), - condexp, 0); -} - - - -/* The following function creates attribute which returns 1 if given - output insn has bypassing and 0 otherwise. */ -static void -make_bypass_attr () -{ - int i, bypass_insn; - int bypass_insns_num = 0; - decl_t decl; - rtx result_rtx; - - for (i = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_insn_reserv - && decl->decl.insn_reserv.condexp != NULL - && decl->decl.insn_reserv.bypass_list != NULL) - bypass_insns_num++; - } - if (bypass_insns_num == 0) - result_rtx = make_numeric_value (0); - else - { - result_rtx = rtx_alloc (COND); - XVEC (result_rtx, 0) = rtvec_alloc (bypass_insns_num * 2); - XEXP (result_rtx, 1) = make_numeric_value (0); - - for (i = bypass_insn = 0; i < description->decls_num; i++) - { - decl = description->decls [i]; - if (decl->mode == dm_insn_reserv - && decl->decl.insn_reserv.condexp != NULL - && decl->decl.insn_reserv.bypass_list != NULL) - { - XVECEXP (result_rtx, 0, 2 * bypass_insn) - = decl->decl.insn_reserv.condexp; - XVECEXP (result_rtx, 0, 2 * bypass_insn + 1) - = make_numeric_value (1); - bypass_insn++; - } - } - } - make_internal_attr (attr_printf (sizeof ("*") - + strlen (BYPASS_P_FUNC_NAME) + 1, - "*%s", BYPASS_P_FUNC_NAME), - result_rtx, 0); -} - - - -/* This page mainly contains top level functions of pipeline hazards - description translator. */ - -/* The following macro value is suffix of name of description file of - pipeline hazards description translator. */ -#define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa" - -/* The function returns suffix of given file name. The returned - string can not be changed. */ -static const char * -file_name_suffix (file_name) - const char *file_name; -{ - const char *last_period; - - for (last_period = NULL; *file_name != '\0'; file_name++) - if (*file_name == '.') - last_period = file_name; - return (last_period == NULL ? file_name : last_period); -} - -/* The function returns base name of given file name, i.e. pointer to - first char after last `/' (or `\' for WIN32) in given file name, - given file name itself if the directory name is absent. The - returned string can not be changed. */ -static const char * -base_file_name (file_name) - const char *file_name; -{ - int directory_name_length; - - directory_name_length = strlen (file_name); -#ifdef WIN32 - while (directory_name_length >= 0 && file_name[directory_name_length] != '/' - && file_name[directory_name_length] != '\\') -#else - while (directory_name_length >= 0 && file_name[directory_name_length] != '/') -#endif - directory_name_length--; - return file_name + directory_name_length + 1; -} - -/* The following is top level function to initialize the work of - pipeline hazards description translator. */ -void -initiate_automaton_gen (argc, argv) - int argc; - char **argv; -{ - const char *base_name; - int i; - - ndfa_flag = 0; - split_argument = 0; /* default value */ - no_minimization_flag = 0; - time_flag = 0; - v_flag = 0; - w_flag = 0; - for (i = 2; i < argc; i++) - if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0) - no_minimization_flag = 1; - else if (strcmp (argv [i], "-time") == 0) - time_flag = 1; - else if (strcmp (argv [i], "-v") == 0) - v_flag = 1; - else if (strcmp (argv [i], W_OPTION) == 0) - w_flag = 1; - else if (strcmp (argv [i], NDFA_OPTION) == 0) - ndfa_flag = 1; - else if (strcmp (argv [i], "-split") == 0) - { - if (i + 1 >= argc) - fatal ("-split has no argument."); - fatal ("option `-split' has not been implemented yet\n"); - /* split_argument = atoi (argument_vect [i + 1]); */ - } - VLA_PTR_CREATE (decls, 150, "decls"); - /* Initialize IR storage. */ - obstack_init (&irp); - initiate_automaton_decl_table (); - initiate_insn_decl_table (); - initiate_decl_table (); - output_file = stdout; - output_description_file = NULL; - base_name = base_file_name (argv[1]); - obstack_grow (&irp, base_name, - strlen (base_name) - strlen (file_name_suffix (base_name))); - obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX, - strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1); - obstack_1grow (&irp, '\0'); - output_description_file_name = obstack_base (&irp); - obstack_finish (&irp); -} - -/* The following function checks existence at least one arc marked by - each insn. */ -static void -check_automata () -{ - automaton_t automaton; - ainsn_t ainsn, reserv_ainsn; - - for (automaton = description->first_automaton; - automaton != NULL; - automaton = automaton->next_automaton) - { - for (ainsn = automaton->ainsn_list; - ainsn != NULL; - ainsn = ainsn->next_ainsn) - if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p) - { - for (reserv_ainsn = ainsn; - reserv_ainsn != NULL; - reserv_ainsn = reserv_ainsn->next_same_reservs_insn) - if (automaton->corresponding_automaton_decl != NULL) - { - if (!w_flag) - error ("Automaton `%s': Insn `%s' will never be issued", - automaton->corresponding_automaton_decl->name, - reserv_ainsn->insn_reserv_decl->name); - else - warning - ("Automaton `%s': Insn `%s' will never be issued", - automaton->corresponding_automaton_decl->name, - reserv_ainsn->insn_reserv_decl->name); - } - else - { - if (!w_flag) - error ("Insn `%s' will never be issued", - reserv_ainsn->insn_reserv_decl->name); - else - warning ("Insn `%s' will never be issued", - reserv_ainsn->insn_reserv_decl->name); - } - } - } -} - -/* The following is top level function to generate automat(a,on) for - fast recognition of pipeline hazards. */ -void -expand_automata () -{ - int i; - - description = create_node (sizeof (struct description) - /* One entry for cycle advancing insn. */ - + sizeof (decl_t) * VLA_PTR_LENGTH (decls)); - description->decls_num = VLA_PTR_LENGTH (decls); - description->query_units_num = 0; - for (i = 0; i < description->decls_num; i++) - { - description->decls [i] = VLA_PTR (decls, i); - if (description->decls [i]->mode == dm_unit - && description->decls [i]->decl.unit.query_p) - description->decls [i]->decl.unit.query_num - = description->query_units_num++; - } - all_time = create_ticker (); - check_time = create_ticker (); - fprintf (stderr, "Check description..."); - fflush (stderr); - check_all_description (); - fprintf (stderr, "done\n"); - ticker_off (&check_time); - generation_time = create_ticker (); - if (!have_error) - { - generate (); - check_automata (); - if (!have_error) - { - fprintf (stderr, "Generation of attributes..."); - fflush (stderr); - make_internal_dfa_insn_code_attr (); - make_insn_alts_attr (); - make_default_insn_latency_attr (); - make_bypass_attr (); - fprintf (stderr, "done\n"); - } - } - ticker_off (&generation_time); - ticker_off (&all_time); - fprintf (stderr, "All other genattrtab stuff..."); - fflush (stderr); -} - -/* The following is top level function to output PHR and to finish - work with pipeline description translator. */ -void -write_automata () -{ - fprintf (stderr, "done\n"); - if (have_error) - fatal ("Errors in DFA description"); - ticker_on (&all_time); - output_time = create_ticker (); - fprintf (stderr, "Forming and outputing automata tables..."); - fflush (stderr); - output_dfa_max_issue_rate (); - output_tables (); - fprintf (stderr, "done\n"); - fprintf (stderr, "Output functions to work with automata..."); - fflush (stderr); - output_chip_definitions (); - output_max_insn_queue_index_def (); - output_internal_min_issue_delay_func (); - output_internal_trans_func (); - /* Cache of insn dfa codes: */ - fprintf (output_file, "\nstatic int *%s;\n\n", DFA_INSN_CODES_VARIABLE_NAME); - output_dfa_insn_code_func (); - output_trans_func (); - fprintf (output_file, "\n#if %s\n\n", AUTOMATON_STATE_ALTS_MACRO_NAME); - output_internal_state_alts_func (); - output_state_alts_func (); - fprintf (output_file, "\n#endif /* #if %s */\n\n", - AUTOMATON_STATE_ALTS_MACRO_NAME); - output_min_issue_delay_func (); - output_internal_dead_lock_func (); - output_dead_lock_func (); - output_size_func (); - output_internal_reset_func (); - output_reset_func (); - output_min_insn_conflict_delay_func (); - output_internal_insn_latency_func (); - output_insn_latency_func (); - output_print_reservation_func (); - if (no_minimization_flag) - { - fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME); - output_get_cpu_unit_code_func (); - output_cpu_unit_reservation_p (); - fprintf (output_file, "\n#endif /* #if %s */\n\n", - CPU_UNITS_QUERY_MACRO_NAME); - } - output_dfa_start_func (); - output_dfa_finish_func (); - fprintf (stderr, "done\n"); - if (v_flag) - { - output_description_file = fopen (output_description_file_name, "w"); - if (output_description_file == NULL) - { - perror (output_description_file_name); - exit (FATAL_EXIT_CODE); - } - fprintf (stderr, "Output automata description..."); - fflush (stderr); - output_description (); - output_automaton_descriptions (); - fprintf (stderr, "done\n"); - output_statistics (output_description_file); - } - output_statistics (stderr); - ticker_off (&output_time); - output_time_statistics (stderr); - finish_states (); - finish_arcs (); - if (time_flag) - { - fprintf (stderr, "Summary:\n"); - fprintf (stderr, " check time "); - print_active_time (stderr, check_time); - fprintf (stderr, ", generation time "); - print_active_time (stderr, generation_time); - fprintf (stderr, ", all time "); - print_active_time (stderr, all_time); - fprintf (stderr, "\n"); - } - /* Finish all work. */ - if (output_description_file != NULL) - { - fflush (output_description_file); - if (ferror (stdout) != 0) - fatal ("Error in writing DFA description file %s", - output_description_file_name); - fclose (output_description_file); - } - finish_automaton_decl_table (); - finish_insn_decl_table (); - finish_decl_table (); - obstack_free (&irp, NULL); - if (have_error && output_description_file != NULL) - remove (output_description_file_name); -} |