/*  This file is part of the program psim.

    Copyright (C) 1994,1995,1996, Andrew Cagney <cagney@highland.com.au>

    This program 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 of the License, or
    (at your option) any later version.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
    */

/* Instruction decode table:

   <decode-rule> ::=
       { <option> }
       ":" [ <first> ]
       ":" [ <last> ]
       ":" [ <force-first> ]
       ":" [ <force-last> ]
       ":" [ <constant-field-names> ]
       ":" [ <word-nr> ]
       ":" [ <format-names> ]
       ":" [ <model-names> ]
       ":" [ <constant> ]
       ":" [ <path> { "," <path> } ]
       { ":" <special-mask>
         ":" [ "!" ] <special-value>
         ":" <word-nr> }
       <nl>
       ;


   <path> ::= <int> "," <int> ;;

   <option> ::=
       <reserved-options>
       | <code-options>
       | <optimize-options>
       | <decode-options>
       | <constant>
       | <search-options>
       ;

   <reserved-options> ::= "zero-reserved" ;
   <gen-options> ::= "array" | "switch" | "padded-switch" | "goto-switch" ;
   <optimize-options> ::= "duplicate" | "combine"
   <decode-options> ::= "normal" | "boolean" ;
   <search-options> ::= "constants" | "variables" | "mixed"

   Ignore the below:


   The instruction decode table contains rules that dictate how igen
   is going to firstly break down the opcode table and secondly

   The table that follows is used by gen to construct a decision tree
   that can identify each possible instruction.  Gen then outputs this
   decision tree as (according to config) a table or switch statement
   as the function idecode.

   In parallel to this, as mentioned above, WITH_EXPANDED_SEMANTICS
   determines of the semantic functions themselves should be expanded
   in a similar way.

   <first>
   <last>

   Range of bits (within the instruction) that should be searched for
   an instruction field.  Within such ranges, gen looks for opcodes
   (constants), registers (strings) and reserved bits (slash) and
   according to the rules that follows includes or excludes them from
   a possible instruction field.

   <force_first>
   <force_last>

   If an instruction field was found, enlarge the field size so that
   it is forced to at least include bits starting from <force_first>
   (<force_last>).  To stop this occuring, use <force_first> = <last>
   + 1 and <force_last> = <first> - 1.

   <force_reserved>

   Treat `/' (reserved) fields as a constant (zero) instead of
   variable when looking for an instruction field.

   <force_expansion>

   Treat any contained register (string) fields as constant when
   determining the instruction field.  For the instruction decode (and
   controled by IDECODE_EXPAND_SEMANTICS) this forces the expansion of
   what would otherwize be non constant bits of an instruction.

   <use_switch>

   Should this table be expanded using a switch statement (val 1) and
   if so, should it be padded with entries so as to force the compiler
   to generate a jump table (val 2). Or a branch table (val 3).

   <special_mask>
   <special_value>
   <special_rule>
   <special_constant>

   Special rule to fine tune how specific (or groups) of instructions
   are expanded.  The applicability of the rule is determined by

     <special_mask> != 0 && (instruction> & <special_mask>) == <special_value>

   Where <instruction> is obtained by looking only at constant fields
   with in an instructions spec.  When determining an expansion, the
   rule is only considered when a node contains a single instruction.
   <special_rule> can be any of:

        0: for this instruction, expand by earlier rules
   	1: expand bits <force_low> .. <force_hi> only
	2: boolean expansion of only zero/non-zero cases
	3: boolean expansion of equality of special constant

	*/


typedef enum {
  normal_decode_rule,
  boolean_rule,
} decode_special_type;


typedef enum {
  invalid_gen,
  array_gen,
  switch_gen,
  padded_switch_gen,
  goto_switch_gen,
} decode_gen_type;


enum {
  decode_cond_mask_field,
  decode_cond_value_field,
  decode_cond_word_nr_field,
  nr_decode_cond_fields,
};

typedef struct _decode_path decode_path;
struct _decode_path {
  int opcode_nr;
  decode_path *parent;
};

typedef struct _decode_path_list decode_path_list;
struct _decode_path_list {
  decode_path *path;
  decode_path_list *next;
};


typedef struct _decode_cond decode_cond;
struct _decode_cond {
  int word_nr;
  int mask[max_insn_bit_size];
  int value[max_insn_bit_size];
  int is_equal;
  decode_cond *next;
};

typedef enum {
  decode_find_mixed,
  decode_find_constants,
  decode_find_strings,
} decode_search_type;

enum {
  decode_options_field,
  decode_first_field,
  decode_last_field,
  decode_force_first_field,
  decode_force_last_field,
  decode_constant_field_names_field,
  decode_word_nr_field,
  decode_format_names_field,
  decode_model_names_field,
  decode_paths_field,
  nr_decode_fields,
  min_nr_decode_fields = decode_last_field + 1,
};


typedef struct _decode_table decode_table;
struct _decode_table {
  line_ref *line;
  decode_special_type type;
  decode_gen_type gen;
  decode_search_type search;
  int first;
  int last;
  int force_first;
  int force_last;
  filter *constant_field_names;
  int word_nr;
  /* if a boolean */
  unsigned constant;
  /* options */
  int with_zero_reserved;
  int with_duplicates;
  int with_combine;
  /* conditions on the rule being applied */
  decode_path_list *paths;
  filter *format_names;
  filter *model_names;
  decode_cond *conditions;
  decode_table *next;
};


extern decode_table *load_decode_table
(char *file_name);

extern int decode_table_max_word_nr
(decode_table *rule);

extern void dump_decode_rule
(lf *file,
 char *prefix,
 decode_table *rule,
 char *suffix);
