xref: /netbsd/external/gpl3/gdb/dist/sim/igen/igen.c (revision 1424dfb3)
166e63ce3Schristos /* The IGEN simulator generator for GDB, the GNU Debugger.
266e63ce3Schristos 
3*1424dfb3Schristos    Copyright 2002-2020 Free Software Foundation, Inc.
466e63ce3Schristos 
566e63ce3Schristos    Contributed by Andrew Cagney.
666e63ce3Schristos 
766e63ce3Schristos    This file is part of GDB.
866e63ce3Schristos 
966e63ce3Schristos    This program is free software; you can redistribute it and/or modify
1066e63ce3Schristos    it under the terms of the GNU General Public License as published by
1166e63ce3Schristos    the Free Software Foundation; either version 3 of the License, or
1266e63ce3Schristos    (at your option) any later version.
1366e63ce3Schristos 
1466e63ce3Schristos    This program is distributed in the hope that it will be useful,
1566e63ce3Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1666e63ce3Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1766e63ce3Schristos    GNU General Public License for more details.
1866e63ce3Schristos 
1966e63ce3Schristos    You should have received a copy of the GNU General Public License
2066e63ce3Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
2166e63ce3Schristos 
2266e63ce3Schristos 
2366e63ce3Schristos 
2466e63ce3Schristos #include <getopt.h>
2566e63ce3Schristos 
2666e63ce3Schristos #include "misc.h"
2766e63ce3Schristos #include "lf.h"
2866e63ce3Schristos #include "table.h"
2966e63ce3Schristos #include "config.h"
3066e63ce3Schristos #include "filter.h"
3166e63ce3Schristos 
3266e63ce3Schristos #include "igen.h"
3366e63ce3Schristos 
3466e63ce3Schristos #include "ld-insn.h"
3566e63ce3Schristos #include "ld-decode.h"
3666e63ce3Schristos #include "ld-cache.h"
3766e63ce3Schristos 
3866e63ce3Schristos #include "gen.h"
3966e63ce3Schristos 
4066e63ce3Schristos #include "gen-model.h"
4166e63ce3Schristos #include "gen-icache.h"
4266e63ce3Schristos #include "gen-itable.h"
4366e63ce3Schristos #include "gen-idecode.h"
4466e63ce3Schristos #include "gen-semantics.h"
4566e63ce3Schristos #include "gen-engine.h"
4666e63ce3Schristos #include "gen-support.h"
4766e63ce3Schristos #include "gen-engine.h"
4866e63ce3Schristos 
4966e63ce3Schristos 
5066e63ce3Schristos /****************************************************************/
5166e63ce3Schristos 
5266e63ce3Schristos 
5366e63ce3Schristos /* Semantic functions */
5466e63ce3Schristos 
5566e63ce3Schristos int
print_semantic_function_formal(lf * file,int nr_prefetched_words)5666e63ce3Schristos print_semantic_function_formal (lf *file, int nr_prefetched_words)
5766e63ce3Schristos {
5866e63ce3Schristos   int nr = 0;
5966e63ce3Schristos   int word_nr;
6066e63ce3Schristos   if (options.gen.icache || nr_prefetched_words < 0)
6166e63ce3Schristos     {
6266e63ce3Schristos       nr += lf_printf (file, "SIM_DESC sd,\n");
6366e63ce3Schristos       nr += lf_printf (file, "%sidecode_cache *cache_entry,\n",
6466e63ce3Schristos 		       options.module.global.prefix.l);
6566e63ce3Schristos       nr += lf_printf (file, "%sinstruction_address cia",
6666e63ce3Schristos 		       options.module.global.prefix.l);
6766e63ce3Schristos     }
6866e63ce3Schristos   else if (options.gen.smp)
6966e63ce3Schristos     {
7066e63ce3Schristos       nr += lf_printf (file, "sim_cpu *cpu,\n");
7166e63ce3Schristos       for (word_nr = 0; word_nr < nr_prefetched_words; word_nr++)
7266e63ce3Schristos 	{
7366e63ce3Schristos 	  nr += lf_printf (file, "%sinstruction_word instruction_%d,\n",
7466e63ce3Schristos 			   options.module.global.prefix.l, word_nr);
7566e63ce3Schristos 	}
7666e63ce3Schristos       nr += lf_printf (file, "%sinstruction_address cia",
7766e63ce3Schristos 		       options.module.global.prefix.l);
7866e63ce3Schristos     }
7966e63ce3Schristos   else
8066e63ce3Schristos     {
8166e63ce3Schristos       nr += lf_printf (file, "SIM_DESC sd,\n");
8266e63ce3Schristos       for (word_nr = 0; word_nr < nr_prefetched_words; word_nr++)
8366e63ce3Schristos 	{
8466e63ce3Schristos 	  nr += lf_printf (file, "%sinstruction_word instruction_%d,\n",
8566e63ce3Schristos 			   options.module.global.prefix.l, word_nr);
8666e63ce3Schristos 	}
8766e63ce3Schristos       nr += lf_printf (file, "%sinstruction_address cia",
8866e63ce3Schristos 		       options.module.global.prefix.l);
8966e63ce3Schristos     }
9066e63ce3Schristos   return nr;
9166e63ce3Schristos }
9266e63ce3Schristos 
9366e63ce3Schristos int
print_semantic_function_actual(lf * file,int nr_prefetched_words)9466e63ce3Schristos print_semantic_function_actual (lf *file, int nr_prefetched_words)
9566e63ce3Schristos {
9666e63ce3Schristos   int nr = 0;
9766e63ce3Schristos   int word_nr;
9866e63ce3Schristos   if (options.gen.icache || nr_prefetched_words < 0)
9966e63ce3Schristos     {
10066e63ce3Schristos       nr += lf_printf (file, "sd, cache_entry, cia");
10166e63ce3Schristos     }
10266e63ce3Schristos   else
10366e63ce3Schristos     {
10466e63ce3Schristos       if (options.gen.smp)
10566e63ce3Schristos 	nr += lf_printf (file, "cpu");
10666e63ce3Schristos       else
10766e63ce3Schristos 	nr += lf_printf (file, "sd");
10866e63ce3Schristos       for (word_nr = 0; word_nr < nr_prefetched_words; word_nr++)
10966e63ce3Schristos 	nr += lf_printf (file, ", instruction_%d", word_nr);
11066e63ce3Schristos       nr += lf_printf (file, ", cia");
11166e63ce3Schristos     }
11266e63ce3Schristos   return nr;
11366e63ce3Schristos }
11466e63ce3Schristos 
11566e63ce3Schristos int
print_semantic_function_type(lf * file)11666e63ce3Schristos print_semantic_function_type (lf *file)
11766e63ce3Schristos {
11866e63ce3Schristos   int nr = 0;
11966e63ce3Schristos   nr += lf_printf (file, "%sinstruction_address",
12066e63ce3Schristos 		   options.module.global.prefix.l);
12166e63ce3Schristos   return nr;
12266e63ce3Schristos }
12366e63ce3Schristos 
12466e63ce3Schristos 
12566e63ce3Schristos /* Idecode functions */
12666e63ce3Schristos 
12766e63ce3Schristos int
print_icache_function_formal(lf * file,int nr_prefetched_words)12866e63ce3Schristos print_icache_function_formal (lf *file, int nr_prefetched_words)
12966e63ce3Schristos {
13066e63ce3Schristos   int nr = 0;
13166e63ce3Schristos   int word_nr;
13266e63ce3Schristos   if (options.gen.smp)
13366e63ce3Schristos     nr += lf_printf (file, "sim_cpu *cpu,\n");
13466e63ce3Schristos   else
13566e63ce3Schristos     nr += lf_printf (file, "SIM_DESC sd,\n");
13666e63ce3Schristos   for (word_nr = 0; word_nr < nr_prefetched_words; word_nr++)
13766e63ce3Schristos     nr += lf_printf (file, " %sinstruction_word instruction_%d,\n",
13866e63ce3Schristos 		     options.module.global.prefix.l, word_nr);
13966e63ce3Schristos   nr += lf_printf (file, " %sinstruction_address cia,\n",
14066e63ce3Schristos 		   options.module.global.prefix.l);
14166e63ce3Schristos   nr += lf_printf (file, " %sidecode_cache *cache_entry",
14266e63ce3Schristos 		   options.module.global.prefix.l);
14366e63ce3Schristos   return nr;
14466e63ce3Schristos }
14566e63ce3Schristos 
14666e63ce3Schristos int
print_icache_function_actual(lf * file,int nr_prefetched_words)14766e63ce3Schristos print_icache_function_actual (lf *file, int nr_prefetched_words)
14866e63ce3Schristos {
14966e63ce3Schristos   int nr = 0;
15066e63ce3Schristos   int word_nr;
15166e63ce3Schristos   if (options.gen.smp)
15266e63ce3Schristos     nr += lf_printf (file, "cpu");
15366e63ce3Schristos   else
15466e63ce3Schristos     nr += lf_printf (file, "sd");
15566e63ce3Schristos   for (word_nr = 0; word_nr < nr_prefetched_words; word_nr++)
15666e63ce3Schristos     nr += lf_printf (file, ", instruction_%d", word_nr);
15766e63ce3Schristos   nr += lf_printf (file, ", cia, cache_entry");
15866e63ce3Schristos   return nr;
15966e63ce3Schristos }
16066e63ce3Schristos 
16166e63ce3Schristos int
print_icache_function_type(lf * file)16266e63ce3Schristos print_icache_function_type (lf *file)
16366e63ce3Schristos {
16466e63ce3Schristos   int nr;
16566e63ce3Schristos   if (options.gen.semantic_icache)
16666e63ce3Schristos     {
16766e63ce3Schristos       nr = print_semantic_function_type (file);
16866e63ce3Schristos     }
16966e63ce3Schristos   else
17066e63ce3Schristos     {
17166e63ce3Schristos       nr = lf_printf (file, "%sidecode_semantic *",
17266e63ce3Schristos 		      options.module.global.prefix.l);
17366e63ce3Schristos     }
17466e63ce3Schristos   return nr;
17566e63ce3Schristos }
17666e63ce3Schristos 
17766e63ce3Schristos 
17866e63ce3Schristos /* Function names */
17966e63ce3Schristos 
18066e63ce3Schristos static int
print_opcode_bits(lf * file,opcode_bits * bits)18166e63ce3Schristos print_opcode_bits (lf *file, opcode_bits *bits)
18266e63ce3Schristos {
18366e63ce3Schristos   int nr = 0;
18466e63ce3Schristos   if (bits == NULL)
18566e63ce3Schristos     return nr;
18666e63ce3Schristos   nr += lf_putchr (file, '_');
18766e63ce3Schristos   nr += lf_putstr (file, bits->field->val_string);
18866e63ce3Schristos   if (bits->opcode->is_boolean && bits->value == 0)
18966e63ce3Schristos     nr += lf_putint (file, bits->opcode->boolean_constant);
19066e63ce3Schristos   else if (!bits->opcode->is_boolean)
19166e63ce3Schristos     {
19266e63ce3Schristos       if (bits->opcode->last < bits->field->last)
19366e63ce3Schristos 	nr +=
19466e63ce3Schristos 	  lf_putint (file,
19566e63ce3Schristos 		     bits->value << (bits->field->last - bits->opcode->last));
19666e63ce3Schristos       else
19766e63ce3Schristos 	nr += lf_putint (file, bits->value);
19866e63ce3Schristos     }
19966e63ce3Schristos   nr += print_opcode_bits (file, bits->next);
20066e63ce3Schristos   return nr;
20166e63ce3Schristos }
20266e63ce3Schristos 
20366e63ce3Schristos static int
print_c_name(lf * file,const char * name)20466e63ce3Schristos print_c_name (lf *file, const char *name)
20566e63ce3Schristos {
20666e63ce3Schristos   int nr = 0;
20766e63ce3Schristos   const char *pos;
20866e63ce3Schristos   for (pos = name; *pos != '\0'; pos++)
20966e63ce3Schristos     {
21066e63ce3Schristos       switch (*pos)
21166e63ce3Schristos 	{
21266e63ce3Schristos 	case '/':
21366e63ce3Schristos 	case '-':
21466e63ce3Schristos 	  break;
21566e63ce3Schristos 	case ' ':
21666e63ce3Schristos 	case '.':
21766e63ce3Schristos 	  nr += lf_putchr (file, '_');
21866e63ce3Schristos 	  break;
21966e63ce3Schristos 	default:
22066e63ce3Schristos 	  nr += lf_putchr (file, *pos);
22166e63ce3Schristos 	  break;
22266e63ce3Schristos 	}
22366e63ce3Schristos     }
22466e63ce3Schristos   return nr;
22566e63ce3Schristos }
22666e63ce3Schristos 
22766e63ce3Schristos extern int
print_function_name(lf * file,const char * basename,const char * format_name,const char * model_name,opcode_bits * expanded_bits,lf_function_name_prefixes prefix)22866e63ce3Schristos print_function_name (lf *file,
22966e63ce3Schristos 		     const char *basename,
23066e63ce3Schristos 		     const char *format_name,
23166e63ce3Schristos 		     const char *model_name,
23266e63ce3Schristos 		     opcode_bits *expanded_bits,
23366e63ce3Schristos 		     lf_function_name_prefixes prefix)
23466e63ce3Schristos {
23566e63ce3Schristos   int nr = 0;
23666e63ce3Schristos   /* the prefix */
23766e63ce3Schristos   switch (prefix)
23866e63ce3Schristos     {
23966e63ce3Schristos     case function_name_prefix_semantics:
24066e63ce3Schristos       nr += lf_printf (file, "%s", options.module.semantics.prefix.l);
24166e63ce3Schristos       nr += lf_printf (file, "semantic_");
24266e63ce3Schristos       break;
24366e63ce3Schristos     case function_name_prefix_idecode:
24466e63ce3Schristos       nr += lf_printf (file, "%s", options.module.idecode.prefix.l);
24566e63ce3Schristos       nr += lf_printf (file, "idecode_");
24666e63ce3Schristos       break;
24766e63ce3Schristos     case function_name_prefix_itable:
24866e63ce3Schristos       nr += lf_printf (file, "%sitable_", options.module.itable.prefix.l);
24966e63ce3Schristos       break;
25066e63ce3Schristos     case function_name_prefix_icache:
25166e63ce3Schristos       nr += lf_printf (file, "%s", options.module.icache.prefix.l);
25266e63ce3Schristos       nr += lf_printf (file, "icache_");
25366e63ce3Schristos       break;
25466e63ce3Schristos     case function_name_prefix_engine:
25566e63ce3Schristos       nr += lf_printf (file, "%s", options.module.engine.prefix.l);
25666e63ce3Schristos       nr += lf_printf (file, "engine_");
25766e63ce3Schristos     default:
25866e63ce3Schristos       break;
25966e63ce3Schristos     }
26066e63ce3Schristos 
26166e63ce3Schristos   if (model_name != NULL)
26266e63ce3Schristos     {
26366e63ce3Schristos       nr += print_c_name (file, model_name);
26466e63ce3Schristos       nr += lf_printf (file, "_");
26566e63ce3Schristos     }
26666e63ce3Schristos 
26766e63ce3Schristos   /* the function name */
26866e63ce3Schristos   nr += print_c_name (file, basename);
26966e63ce3Schristos 
27066e63ce3Schristos   /* the format name if available */
27166e63ce3Schristos   if (format_name != NULL)
27266e63ce3Schristos     {
27366e63ce3Schristos       nr += lf_printf (file, "_");
27466e63ce3Schristos       nr += print_c_name (file, format_name);
27566e63ce3Schristos     }
27666e63ce3Schristos 
27766e63ce3Schristos   /* the suffix */
27866e63ce3Schristos   nr += print_opcode_bits (file, expanded_bits);
27966e63ce3Schristos 
28066e63ce3Schristos   return nr;
28166e63ce3Schristos }
28266e63ce3Schristos 
28366e63ce3Schristos 
28466e63ce3Schristos void
print_my_defines(lf * file,const char * basename,const char * format_name,opcode_bits * expanded_bits)28566e63ce3Schristos print_my_defines (lf *file,
28666e63ce3Schristos 		  const char *basename,
28766e63ce3Schristos 		  const char *format_name, opcode_bits *expanded_bits)
28866e63ce3Schristos {
28966e63ce3Schristos   /* #define MY_INDEX xxxxx */
29066e63ce3Schristos   lf_indent_suppress (file);
29166e63ce3Schristos   lf_printf (file, "#undef MY_INDEX\n");
29266e63ce3Schristos   lf_indent_suppress (file);
29366e63ce3Schristos   lf_printf (file, "#define MY_INDEX ");
29466e63ce3Schristos   print_function_name (file,
29566e63ce3Schristos 		       basename, format_name, NULL,
29666e63ce3Schristos 		       NULL, function_name_prefix_itable);
29766e63ce3Schristos   lf_printf (file, "\n");
29866e63ce3Schristos   /* #define MY_PREFIX xxxxxx */
29966e63ce3Schristos   lf_indent_suppress (file);
30066e63ce3Schristos   lf_printf (file, "#undef ");
30166e63ce3Schristos   print_function_name (file,
30266e63ce3Schristos 		       basename, format_name, NULL,
30366e63ce3Schristos 		       expanded_bits, function_name_prefix_none);
30466e63ce3Schristos   lf_printf (file, "\n");
30566e63ce3Schristos   lf_indent_suppress (file);
30666e63ce3Schristos   lf_printf (file, "#undef MY_PREFIX\n");
30766e63ce3Schristos   lf_indent_suppress (file);
30866e63ce3Schristos   lf_printf (file, "#define MY_PREFIX ");
30966e63ce3Schristos   print_function_name (file,
31066e63ce3Schristos 		       basename, format_name, NULL,
31166e63ce3Schristos 		       expanded_bits, function_name_prefix_none);
31266e63ce3Schristos   lf_printf (file, "\n");
31366e63ce3Schristos   /* #define MY_NAME xxxxxx */
31466e63ce3Schristos   lf_indent_suppress (file);
31566e63ce3Schristos   lf_indent_suppress (file);
31666e63ce3Schristos   lf_printf (file, "#undef MY_NAME\n");
31766e63ce3Schristos   lf_indent_suppress (file);
31866e63ce3Schristos   lf_printf (file, "#define MY_NAME \"");
31966e63ce3Schristos   print_function_name (file,
32066e63ce3Schristos 		       basename, format_name, NULL,
32166e63ce3Schristos 		       expanded_bits, function_name_prefix_none);
32266e63ce3Schristos   lf_printf (file, "\"\n");
32366e63ce3Schristos }
32466e63ce3Schristos 
32566e63ce3Schristos 
32666e63ce3Schristos static int
print_itrace_prefix(lf * file)32766e63ce3Schristos print_itrace_prefix (lf *file)
32866e63ce3Schristos {
32966e63ce3Schristos   const char *prefix = "trace_prefix (";
33066e63ce3Schristos   int indent = strlen (prefix);
33166e63ce3Schristos   lf_printf (file, "%sSD, CPU, cia, CIA, TRACE_LINENUM_P (CPU), \\\n",
33266e63ce3Schristos 	     prefix);
33366e63ce3Schristos   lf_indent (file, +indent);
33466e63ce3Schristos   lf_printf (file, "%sitable[MY_INDEX].file, \\\n",
33566e63ce3Schristos 	     options.module.itable.prefix.l);
33666e63ce3Schristos   lf_printf (file, "%sitable[MY_INDEX].line_nr, \\\n",
33766e63ce3Schristos 	     options.module.itable.prefix.l);
33866e63ce3Schristos   lf_printf (file, "\"");
33966e63ce3Schristos   return indent;
34066e63ce3Schristos }
34166e63ce3Schristos 
34266e63ce3Schristos 
34366e63ce3Schristos static void
print_itrace_format(lf * file,insn_mnemonic_entry * assembler)34466e63ce3Schristos print_itrace_format (lf *file, insn_mnemonic_entry *assembler)
34566e63ce3Schristos {
34666e63ce3Schristos   /* pass=1 is fmt string; pass=2 is arguments */
34766e63ce3Schristos   int pass;
34866e63ce3Schristos   /* print the format string */
34966e63ce3Schristos   for (pass = 1; pass <= 2; pass++)
35066e63ce3Schristos     {
35166e63ce3Schristos       const char *chp = assembler->format;
35266e63ce3Schristos       chp++;			/* skip the leading quote */
35366e63ce3Schristos       /* write out the format/args */
35466e63ce3Schristos       while (*chp != '\0')
35566e63ce3Schristos 	{
35666e63ce3Schristos 	  if (chp[0] == '\\' && (chp[1] == '<' || chp[1] == '>'))
35766e63ce3Schristos 	    {
35866e63ce3Schristos 	      if (pass == 1)
35966e63ce3Schristos 		lf_putchr (file, chp[1]);
36066e63ce3Schristos 	      chp += 2;
36166e63ce3Schristos 	    }
36266e63ce3Schristos 	  else if (chp[0] == '<' || chp[0] == '%')
36366e63ce3Schristos 	    {
36466e63ce3Schristos 	      /* parse [ "%" ... ] "<" [ func "#" ] param ">" */
36566e63ce3Schristos 	      const char *fmt;
36666e63ce3Schristos 	      const char *func;
36766e63ce3Schristos 	      int strlen_func;
36866e63ce3Schristos 	      const char *param;
36966e63ce3Schristos 	      int strlen_param;
37066e63ce3Schristos 	      /* the "%" ... "<" format */
37166e63ce3Schristos 	      fmt = chp;
37266e63ce3Schristos 	      while (chp[0] != '<' && chp[0] != '\0')
37366e63ce3Schristos 		chp++;
37466e63ce3Schristos 	      if (chp[0] != '<')
37566e63ce3Schristos 		error (assembler->line, "Missing `<' after `%%'\n");
37666e63ce3Schristos 	      chp++;
37766e63ce3Schristos 	      /* [ "func" # ] OR "param" */
37866e63ce3Schristos 	      func = chp;
37966e63ce3Schristos 	      param = chp;
38066e63ce3Schristos 	      while (chp[0] != '>' && chp[0] != '#' && chp[0] != '\0')
38166e63ce3Schristos 		chp++;
38266e63ce3Schristos 	      strlen_func = chp - func;
38366e63ce3Schristos 	      if (chp[0] == '#')
38466e63ce3Schristos 		{
38566e63ce3Schristos 		  chp++;
38666e63ce3Schristos 		  param = chp;
38766e63ce3Schristos 		  while (chp[0] != '>' && chp[0] != '\0')
38866e63ce3Schristos 		    chp++;
38966e63ce3Schristos 		}
39066e63ce3Schristos 	      strlen_param = chp - param;
39166e63ce3Schristos 	      if (chp[0] != '>')
39266e63ce3Schristos 		error (assembler->line,
39366e63ce3Schristos 		       "Missing closing `>' in assembler string\n");
39466e63ce3Schristos 	      chp++;
39566e63ce3Schristos 	      /* now process it */
39666e63ce3Schristos 	      if (pass == 2)
39766e63ce3Schristos 		lf_printf (file, ", \\\n");
39866e63ce3Schristos 	      if (strncmp (fmt, "<", 1) == 0)
39966e63ce3Schristos 		/* implicit long int format */
40066e63ce3Schristos 		{
40166e63ce3Schristos 		  if (pass == 1)
40266e63ce3Schristos 		    lf_printf (file, "%%ld");
40366e63ce3Schristos 		  else
40466e63ce3Schristos 		    {
40566e63ce3Schristos 		      lf_printf (file, "(long) ");
40666e63ce3Schristos 		      lf_write (file, param, strlen_param);
40766e63ce3Schristos 		    }
40866e63ce3Schristos 		}
40966e63ce3Schristos 	      else if (strncmp (fmt, "%<", 2) == 0)
41066e63ce3Schristos 		/* explicit format */
41166e63ce3Schristos 		{
41266e63ce3Schristos 		  if (pass == 1)
41366e63ce3Schristos 		    lf_printf (file, "%%");
41466e63ce3Schristos 		  else
41566e63ce3Schristos 		    lf_write (file, param, strlen_param);
41666e63ce3Schristos 		}
41766e63ce3Schristos 	      else if (strncmp (fmt, "%s<", 3) == 0)
41866e63ce3Schristos 		/* string format */
41966e63ce3Schristos 		{
42066e63ce3Schristos 		  if (pass == 1)
42166e63ce3Schristos 		    lf_printf (file, "%%s");
42266e63ce3Schristos 		  else
42366e63ce3Schristos 		    {
42466e63ce3Schristos 		      lf_printf (file, "%sstr_",
42566e63ce3Schristos 				 options.module.global.prefix.l);
42666e63ce3Schristos 		      lf_write (file, func, strlen_func);
42766e63ce3Schristos 		      lf_printf (file, " (SD_, ");
42866e63ce3Schristos 		      lf_write (file, param, strlen_param);
42966e63ce3Schristos 		      lf_printf (file, ")");
43066e63ce3Schristos 		    }
43166e63ce3Schristos 		}
43266e63ce3Schristos 	      else if (strncmp (fmt, "%lx<", 4) == 0)
43366e63ce3Schristos 		/* simple hex */
43466e63ce3Schristos 		{
43566e63ce3Schristos 		  if (pass == 1)
43666e63ce3Schristos 		    lf_printf (file, "%%lx");
43766e63ce3Schristos 		  else
43866e63ce3Schristos 		    {
43966e63ce3Schristos 		      lf_printf (file, "(unsigned long) ");
44066e63ce3Schristos 		      lf_write (file, param, strlen_param);
44166e63ce3Schristos 		    }
44266e63ce3Schristos 		}
44366e63ce3Schristos 	      else if (strncmp (fmt, "%#lx<", 5) == 0)
44466e63ce3Schristos 		/* simple hex with 0x prefix */
44566e63ce3Schristos 		{
44666e63ce3Schristos 		  if (pass == 1)
44766e63ce3Schristos 		    lf_printf (file, "%%#lx");
44866e63ce3Schristos 		  else
44966e63ce3Schristos 		    {
45066e63ce3Schristos 		      lf_printf (file, "(unsigned long) ");
45166e63ce3Schristos 		      lf_write (file, param, strlen_param);
45266e63ce3Schristos 		    }
45366e63ce3Schristos 		}
45466e63ce3Schristos 	      else if (strncmp (fmt, "%08lx<", 6) == 0)
45566e63ce3Schristos 		/* simple hex */
45666e63ce3Schristos 		{
45766e63ce3Schristos 		  if (pass == 1)
45866e63ce3Schristos 		    lf_printf (file, "%%08lx");
45966e63ce3Schristos 		  else
46066e63ce3Schristos 		    {
46166e63ce3Schristos 		      lf_printf (file, "(unsigned long) ");
46266e63ce3Schristos 		      lf_write (file, param, strlen_param);
46366e63ce3Schristos 		    }
46466e63ce3Schristos 		}
46566e63ce3Schristos 	      else
46666e63ce3Schristos 		error (assembler->line, "Unknown assembler string format\n");
46766e63ce3Schristos 	    }
46866e63ce3Schristos 	  else
46966e63ce3Schristos 	    {
47066e63ce3Schristos 	      if (pass == 1)
47166e63ce3Schristos 		lf_putchr (file, chp[0]);
47266e63ce3Schristos 	      chp += 1;
47366e63ce3Schristos 	    }
47466e63ce3Schristos 	}
47566e63ce3Schristos     }
47666e63ce3Schristos   lf_printf (file, ");\n");
47766e63ce3Schristos }
47866e63ce3Schristos 
47966e63ce3Schristos 
48066e63ce3Schristos void
print_itrace(lf * file,insn_entry * insn,int idecode)48166e63ce3Schristos print_itrace (lf *file, insn_entry * insn, int idecode)
48266e63ce3Schristos {
48366e63ce3Schristos   /* NB: Here we escape each EOLN. This is so that the the compiler
48466e63ce3Schristos      treats a trace function call as a single line.  Consequently any
48566e63ce3Schristos      errors in the line are refered back to the same igen assembler
48666e63ce3Schristos      source line */
48766e63ce3Schristos   const char *phase = (idecode) ? "DECODE" : "INSN";
48866e63ce3Schristos   lf_printf (file, "\n");
48966e63ce3Schristos   lf_indent_suppress (file);
49066e63ce3Schristos   lf_printf (file, "#if defined (WITH_TRACE)\n");
49166e63ce3Schristos   lf_printf (file, "/* generate a trace prefix if any tracing enabled */\n");
49266e63ce3Schristos   lf_printf (file, "if (TRACE_ANY_P (CPU))\n");
49366e63ce3Schristos   lf_printf (file, "  {\n");
49466e63ce3Schristos   lf_indent (file, +4);
49566e63ce3Schristos   {
49666e63ce3Schristos     if (insn->mnemonics != NULL)
49766e63ce3Schristos       {
49866e63ce3Schristos 	insn_mnemonic_entry *assembler = insn->mnemonics;
49966e63ce3Schristos 	int is_first = 1;
50066e63ce3Schristos 	do
50166e63ce3Schristos 	  {
50266e63ce3Schristos 	    if (assembler->condition != NULL)
50366e63ce3Schristos 	      {
50466e63ce3Schristos 		int indent;
50566e63ce3Schristos 		lf_printf (file, "%sif (%s)\n",
50666e63ce3Schristos 			   is_first ? "" : "else ", assembler->condition);
50766e63ce3Schristos 		lf_indent (file, +2);
50866e63ce3Schristos 		lf_print__line_ref (file, assembler->line);
50966e63ce3Schristos 		indent = print_itrace_prefix (file);
51066e63ce3Schristos 		print_itrace_format (file, assembler);
51166e63ce3Schristos 		lf_print__internal_ref (file);
51266e63ce3Schristos 		lf_indent (file, -indent);
51366e63ce3Schristos 		lf_indent (file, -2);
51466e63ce3Schristos 		if (assembler->next == NULL)
51566e63ce3Schristos 		  error (assembler->line,
51666e63ce3Schristos 			 "Missing final unconditional assembler\n");
51766e63ce3Schristos 	      }
51866e63ce3Schristos 	    else
51966e63ce3Schristos 	      {
52066e63ce3Schristos 		int indent;
52166e63ce3Schristos 		if (!is_first)
52266e63ce3Schristos 		  {
52366e63ce3Schristos 		    lf_printf (file, "else\n");
52466e63ce3Schristos 		    lf_indent (file, +2);
52566e63ce3Schristos 		  }
52666e63ce3Schristos 		lf_print__line_ref (file, assembler->line);
52766e63ce3Schristos 		indent = print_itrace_prefix (file);
52866e63ce3Schristos 		print_itrace_format (file, assembler);
52966e63ce3Schristos 		lf_print__internal_ref (file);
53066e63ce3Schristos 		lf_indent (file, -indent);
53166e63ce3Schristos 		if (!is_first)
53266e63ce3Schristos 		  lf_indent (file, -2);
53366e63ce3Schristos 		if (assembler->next != NULL)
53466e63ce3Schristos 		  error (assembler->line,
53566e63ce3Schristos 			 "Unconditional assembler is not last\n");
53666e63ce3Schristos 	      }
53766e63ce3Schristos 	    is_first = 0;
53866e63ce3Schristos 	    assembler = assembler->next;
53966e63ce3Schristos 	  }
54066e63ce3Schristos 	while (assembler != NULL);
54166e63ce3Schristos       }
54266e63ce3Schristos     else
54366e63ce3Schristos       {
54466e63ce3Schristos 	int indent;
54566e63ce3Schristos 	lf_indent (file, +2);
54666e63ce3Schristos 	lf_print__line_ref (file, insn->line);
54766e63ce3Schristos 	indent = print_itrace_prefix (file);
54866e63ce3Schristos 	lf_printf (file, "%%s\", \\\n");
54966e63ce3Schristos 	lf_printf (file, "itable[MY_INDEX].name);\n");
55066e63ce3Schristos 	lf_print__internal_ref (file);
55166e63ce3Schristos 	lf_indent (file, -indent);
55266e63ce3Schristos 	lf_indent (file, -2);
55366e63ce3Schristos       }
55466e63ce3Schristos     lf_printf (file, "/* trace the instruction execution if enabled */\n");
55566e63ce3Schristos     lf_printf (file, "if (TRACE_%s_P (CPU))\n", phase);
55666e63ce3Schristos     lf_printf (file,
55766e63ce3Schristos 	       "  trace_generic (SD, CPU, TRACE_%s_IDX, \" %%s\", itable[MY_INDEX].name);\n",
55866e63ce3Schristos 	       phase);
55966e63ce3Schristos   }
56066e63ce3Schristos   lf_indent (file, -4);
56166e63ce3Schristos   lf_printf (file, "  }\n");
56266e63ce3Schristos   lf_indent_suppress (file);
56366e63ce3Schristos   lf_printf (file, "#endif\n");
56466e63ce3Schristos }
56566e63ce3Schristos 
56666e63ce3Schristos 
56766e63ce3Schristos void
print_sim_engine_abort(lf * file,const char * message)56866e63ce3Schristos print_sim_engine_abort (lf *file, const char *message)
56966e63ce3Schristos {
57066e63ce3Schristos   lf_printf (file, "sim_engine_abort (SD, CPU, cia, ");
57166e63ce3Schristos   lf_printf (file, "\"%s\"", message);
57266e63ce3Schristos   lf_printf (file, ");\n");
57366e63ce3Schristos }
57466e63ce3Schristos 
57566e63ce3Schristos 
57666e63ce3Schristos void
print_include(lf * file,igen_module module)57766e63ce3Schristos print_include (lf *file, igen_module module)
57866e63ce3Schristos {
57966e63ce3Schristos   lf_printf (file, "#include \"%s%s.h\"\n", module.prefix.l, module.suffix.l);
58066e63ce3Schristos }
58166e63ce3Schristos 
58266e63ce3Schristos void
print_include_inline(lf * file,igen_module module)58366e63ce3Schristos print_include_inline (lf *file, igen_module module)
58466e63ce3Schristos {
58566e63ce3Schristos   lf_printf (file, "#if C_REVEALS_MODULE_P (%s_INLINE)\n", module.suffix.u);
58666e63ce3Schristos   lf_printf (file, "#include \"%s%s.c\"\n", module.prefix.l, module.suffix.l);
58766e63ce3Schristos   lf_printf (file, "#else\n");
58866e63ce3Schristos   print_include (file, module);
58966e63ce3Schristos   lf_printf (file, "#endif\n");
59066e63ce3Schristos   lf_printf (file, "\n");
59166e63ce3Schristos }
59266e63ce3Schristos 
59366e63ce3Schristos void
print_includes(lf * file)59466e63ce3Schristos print_includes (lf *file)
59566e63ce3Schristos {
59666e63ce3Schristos   lf_printf (file, "\n");
59766e63ce3Schristos   lf_printf (file, "#include \"sim-inline.c\"\n");
59866e63ce3Schristos   lf_printf (file, "\n");
59966e63ce3Schristos   print_include_inline (file, options.module.itable);
60066e63ce3Schristos   print_include_inline (file, options.module.idecode);
60166e63ce3Schristos   print_include_inline (file, options.module.support);
60266e63ce3Schristos }
60366e63ce3Schristos 
60466e63ce3Schristos 
60566e63ce3Schristos /****************************************************************/
60666e63ce3Schristos 
60766e63ce3Schristos 
60866e63ce3Schristos static void
gen_semantics_h(lf * file,insn_list * semantics,int max_nr_words)60966e63ce3Schristos gen_semantics_h (lf *file, insn_list *semantics, int max_nr_words)
61066e63ce3Schristos {
61166e63ce3Schristos   int word_nr;
61266e63ce3Schristos   insn_list *semantic;
61366e63ce3Schristos   for (word_nr = -1; word_nr <= max_nr_words; word_nr++)
61466e63ce3Schristos     {
61566e63ce3Schristos       lf_printf (file, "typedef ");
61666e63ce3Schristos       print_semantic_function_type (file);
61766e63ce3Schristos       lf_printf (file, " %sidecode_semantic", options.module.global.prefix.l);
61866e63ce3Schristos       if (word_nr >= 0)
61966e63ce3Schristos 	lf_printf (file, "_%d", word_nr);
62066e63ce3Schristos       lf_printf (file, "\n(");
62166e63ce3Schristos       lf_indent (file, +1);
62266e63ce3Schristos       print_semantic_function_formal (file, word_nr);
62366e63ce3Schristos       lf_indent (file, -1);
62466e63ce3Schristos       lf_printf (file, ");\n");
62566e63ce3Schristos       lf_printf (file, "\n");
62666e63ce3Schristos     }
62766e63ce3Schristos   switch (options.gen.code)
62866e63ce3Schristos     {
62966e63ce3Schristos     case generate_calls:
63066e63ce3Schristos       for (semantic = semantics; semantic != NULL; semantic = semantic->next)
63166e63ce3Schristos 	{
63266e63ce3Schristos 	  /* Ignore any special/internal instructions */
63366e63ce3Schristos 	  if (semantic->insn->nr_words == 0)
63466e63ce3Schristos 	    continue;
63566e63ce3Schristos 	  print_semantic_declaration (file,
63666e63ce3Schristos 				      semantic->insn,
63766e63ce3Schristos 				      semantic->expanded_bits,
63866e63ce3Schristos 				      semantic->opcodes,
63966e63ce3Schristos 				      semantic->nr_prefetched_words);
64066e63ce3Schristos 	}
64166e63ce3Schristos       break;
64266e63ce3Schristos     case generate_jumps:
64366e63ce3Schristos       lf_print__this_file_is_empty (file, "generating jumps");
64466e63ce3Schristos       break;
64566e63ce3Schristos     }
64666e63ce3Schristos }
64766e63ce3Schristos 
64866e63ce3Schristos 
64966e63ce3Schristos static void
gen_semantics_c(lf * file,insn_list * semantics,cache_entry * cache_rules)65066e63ce3Schristos gen_semantics_c (lf *file, insn_list *semantics, cache_entry *cache_rules)
65166e63ce3Schristos {
65266e63ce3Schristos   if (options.gen.code == generate_calls)
65366e63ce3Schristos     {
65466e63ce3Schristos       insn_list *semantic;
65566e63ce3Schristos       print_includes (file);
65666e63ce3Schristos       print_include (file, options.module.semantics);
65766e63ce3Schristos       lf_printf (file, "\n");
65866e63ce3Schristos 
65966e63ce3Schristos       for (semantic = semantics; semantic != NULL; semantic = semantic->next)
66066e63ce3Schristos 	{
66166e63ce3Schristos 	  /* Ignore any special/internal instructions */
66266e63ce3Schristos 	  if (semantic->insn->nr_words == 0)
66366e63ce3Schristos 	    continue;
66466e63ce3Schristos 	  print_semantic_definition (file,
66566e63ce3Schristos 				     semantic->insn,
66666e63ce3Schristos 				     semantic->expanded_bits,
66766e63ce3Schristos 				     semantic->opcodes,
66866e63ce3Schristos 				     cache_rules,
66966e63ce3Schristos 				     semantic->nr_prefetched_words);
67066e63ce3Schristos 	}
67166e63ce3Schristos     }
67266e63ce3Schristos   else
67366e63ce3Schristos     {
67466e63ce3Schristos       lf_print__this_file_is_empty (file, "generating jump engine");
67566e63ce3Schristos     }
67666e63ce3Schristos }
67766e63ce3Schristos 
67866e63ce3Schristos 
67966e63ce3Schristos /****************************************************************/
68066e63ce3Schristos 
68166e63ce3Schristos 
68266e63ce3Schristos static void
gen_icache_h(lf * file,insn_list * semantic,function_entry * functions,int max_nr_words)68366e63ce3Schristos gen_icache_h (lf *file,
68466e63ce3Schristos 	      insn_list *semantic,
68566e63ce3Schristos 	      function_entry * functions, int max_nr_words)
68666e63ce3Schristos {
68766e63ce3Schristos   int word_nr;
68866e63ce3Schristos   for (word_nr = 0; word_nr <= max_nr_words; word_nr++)
68966e63ce3Schristos     {
69066e63ce3Schristos       lf_printf (file, "typedef ");
69166e63ce3Schristos       print_icache_function_type (file);
69266e63ce3Schristos       lf_printf (file, " %sidecode_icache_%d\n(",
69366e63ce3Schristos 		 options.module.global.prefix.l, word_nr);
69466e63ce3Schristos       print_icache_function_formal (file, word_nr);
69566e63ce3Schristos       lf_printf (file, ");\n");
69666e63ce3Schristos       lf_printf (file, "\n");
69766e63ce3Schristos     }
69866e63ce3Schristos   if (options.gen.code == generate_calls && options.gen.icache)
69966e63ce3Schristos     {
70066e63ce3Schristos       function_entry_traverse (file, functions,
70166e63ce3Schristos 			       print_icache_internal_function_declaration,
70266e63ce3Schristos 			       NULL);
70366e63ce3Schristos       while (semantic != NULL)
70466e63ce3Schristos 	{
70566e63ce3Schristos 	  print_icache_declaration (file,
70666e63ce3Schristos 				    semantic->insn,
70766e63ce3Schristos 				    semantic->expanded_bits,
70866e63ce3Schristos 				    semantic->opcodes,
70966e63ce3Schristos 				    semantic->nr_prefetched_words);
71066e63ce3Schristos 	  semantic = semantic->next;
71166e63ce3Schristos 	}
71266e63ce3Schristos     }
71366e63ce3Schristos   else
71466e63ce3Schristos     {
71566e63ce3Schristos       lf_print__this_file_is_empty (file, "generating jump engine");
71666e63ce3Schristos     }
71766e63ce3Schristos }
71866e63ce3Schristos 
71966e63ce3Schristos static void
gen_icache_c(lf * file,insn_list * semantic,function_entry * functions,cache_entry * cache_rules)72066e63ce3Schristos gen_icache_c (lf *file,
72166e63ce3Schristos 	      insn_list *semantic,
72266e63ce3Schristos 	      function_entry * functions, cache_entry *cache_rules)
72366e63ce3Schristos {
72466e63ce3Schristos   /* output `internal' invalid/floating-point unavailable functions
72566e63ce3Schristos      where needed */
72666e63ce3Schristos   if (options.gen.code == generate_calls && options.gen.icache)
72766e63ce3Schristos     {
72866e63ce3Schristos       lf_printf (file, "\n");
72966e63ce3Schristos       lf_printf (file, "#include \"cpu.h\"\n");
73066e63ce3Schristos       lf_printf (file, "#include \"idecode.h\"\n");
73166e63ce3Schristos       lf_printf (file, "#include \"semantics.h\"\n");
73266e63ce3Schristos       lf_printf (file, "#include \"icache.h\"\n");
73366e63ce3Schristos       lf_printf (file, "#include \"support.h\"\n");
73466e63ce3Schristos       lf_printf (file, "\n");
73566e63ce3Schristos       function_entry_traverse (file, functions,
73666e63ce3Schristos 			       print_icache_internal_function_definition,
73766e63ce3Schristos 			       NULL);
73866e63ce3Schristos       lf_printf (file, "\n");
73966e63ce3Schristos       while (semantic != NULL)
74066e63ce3Schristos 	{
74166e63ce3Schristos 	  print_icache_definition (file,
74266e63ce3Schristos 				   semantic->insn,
74366e63ce3Schristos 				   semantic->expanded_bits,
74466e63ce3Schristos 				   semantic->opcodes,
74566e63ce3Schristos 				   cache_rules,
74666e63ce3Schristos 				   semantic->nr_prefetched_words);
74766e63ce3Schristos 	  semantic = semantic->next;
74866e63ce3Schristos 	}
74966e63ce3Schristos     }
75066e63ce3Schristos   else
75166e63ce3Schristos     {
75266e63ce3Schristos       lf_print__this_file_is_empty (file, "generating jump engine");
75366e63ce3Schristos     }
75466e63ce3Schristos }
75566e63ce3Schristos 
75666e63ce3Schristos 
75766e63ce3Schristos /****************************************************************/
75866e63ce3Schristos 
75966e63ce3Schristos 
76066e63ce3Schristos static void
gen_idecode_h(lf * file,gen_table * gen,insn_table * insns,cache_entry * cache_rules)76166e63ce3Schristos gen_idecode_h (lf *file,
76266e63ce3Schristos 	       gen_table *gen, insn_table *insns, cache_entry *cache_rules)
76366e63ce3Schristos {
76466e63ce3Schristos   lf_printf (file, "typedef unsigned%d %sinstruction_word;\n",
76566e63ce3Schristos 	     options.insn_bit_size, options.module.global.prefix.l);
76666e63ce3Schristos   if (options.gen.delayed_branch)
76766e63ce3Schristos     {
76866e63ce3Schristos       lf_printf (file, "typedef struct _%sinstruction_address {\n",
76966e63ce3Schristos 		 options.module.global.prefix.l);
77066e63ce3Schristos       lf_printf (file, "  address_word ip; /* instruction pointer */\n");
77166e63ce3Schristos       lf_printf (file, "  address_word dp; /* delayed-slot pointer */\n");
77266e63ce3Schristos       lf_printf (file, "} %sinstruction_address;\n",
77366e63ce3Schristos 		 options.module.global.prefix.l);
77466e63ce3Schristos     }
77566e63ce3Schristos   else
77666e63ce3Schristos     {
77766e63ce3Schristos       lf_printf (file, "typedef address_word %sinstruction_address;\n",
77866e63ce3Schristos 		 options.module.global.prefix.l);
77966e63ce3Schristos 
78066e63ce3Schristos     }
78166e63ce3Schristos   if (options.gen.nia == nia_is_invalid
78266e63ce3Schristos       && strlen (options.module.global.prefix.u) > 0)
78366e63ce3Schristos     {
78466e63ce3Schristos       lf_indent_suppress (file);
78566e63ce3Schristos       lf_printf (file, "#define %sINVALID_INSTRUCTION_ADDRESS ",
78666e63ce3Schristos 		 options.module.global.prefix.u);
78766e63ce3Schristos       lf_printf (file, "INVALID_INSTRUCTION_ADDRESS\n");
78866e63ce3Schristos     }
78966e63ce3Schristos   lf_printf (file, "\n");
79066e63ce3Schristos   print_icache_struct (file, insns, cache_rules);
79166e63ce3Schristos   lf_printf (file, "\n");
79266e63ce3Schristos   if (options.gen.icache)
79366e63ce3Schristos     {
79466e63ce3Schristos       ERROR ("FIXME - idecode with icache suffering from bit-rot");
79566e63ce3Schristos     }
79666e63ce3Schristos   else
79766e63ce3Schristos     {
79866e63ce3Schristos       gen_list *entry;
79966e63ce3Schristos       for (entry = gen->tables; entry != NULL; entry = entry->next)
80066e63ce3Schristos 	{
80166e63ce3Schristos 	  print_idecode_issue_function_header (file,
80266e63ce3Schristos 					       (options.gen.multi_sim
80366e63ce3Schristos 						? entry->model->name
80466e63ce3Schristos 						: NULL),
80566e63ce3Schristos 					       is_function_declaration,
80666e63ce3Schristos 					       1 /*ALWAYS ONE WORD */ );
80766e63ce3Schristos 	}
80866e63ce3Schristos       if (options.gen.multi_sim)
80966e63ce3Schristos 	{
81066e63ce3Schristos 	  print_idecode_issue_function_header (file,
81166e63ce3Schristos 					       NULL,
81266e63ce3Schristos 					       is_function_variable,
81366e63ce3Schristos 					       1 /*ALWAYS ONE WORD */ );
81466e63ce3Schristos 	}
81566e63ce3Schristos     }
81666e63ce3Schristos }
81766e63ce3Schristos 
81866e63ce3Schristos 
81966e63ce3Schristos static void
gen_idecode_c(lf * file,gen_table * gen,insn_table * isa,cache_entry * cache_rules)82066e63ce3Schristos gen_idecode_c (lf *file,
82166e63ce3Schristos 	       gen_table *gen, insn_table *isa, cache_entry *cache_rules)
82266e63ce3Schristos {
82366e63ce3Schristos   /* the intro */
82466e63ce3Schristos   print_includes (file);
82566e63ce3Schristos   print_include_inline (file, options.module.semantics);
82666e63ce3Schristos   lf_printf (file, "\n");
82766e63ce3Schristos 
82866e63ce3Schristos   print_idecode_globals (file);
82966e63ce3Schristos   lf_printf (file, "\n");
83066e63ce3Schristos 
83166e63ce3Schristos   switch (options.gen.code)
83266e63ce3Schristos     {
83366e63ce3Schristos     case generate_calls:
83466e63ce3Schristos       {
83566e63ce3Schristos 	gen_list *entry;
83666e63ce3Schristos 	for (entry = gen->tables; entry != NULL; entry = entry->next)
83766e63ce3Schristos 	  {
83866e63ce3Schristos 	    print_idecode_lookups (file, entry->table, cache_rules);
83966e63ce3Schristos 
84066e63ce3Schristos 	    /* output the main idecode routine */
84166e63ce3Schristos 	    if (!options.gen.icache)
84266e63ce3Schristos 	      {
84366e63ce3Schristos 		print_idecode_issue_function_header (file,
84466e63ce3Schristos 						     (options.gen.multi_sim
84566e63ce3Schristos 						      ? entry->model->name
84666e63ce3Schristos 						      : NULL),
84766e63ce3Schristos 						     1 /*is definition */ ,
84866e63ce3Schristos 						     1 /*ALWAYS ONE WORD */ );
84966e63ce3Schristos 		lf_printf (file, "{\n");
85066e63ce3Schristos 		lf_indent (file, +2);
85166e63ce3Schristos 		lf_printf (file, "%sinstruction_address nia;\n",
85266e63ce3Schristos 			   options.module.global.prefix.l);
85366e63ce3Schristos 		print_idecode_body (file, entry->table, "nia =");
85466e63ce3Schristos 		lf_printf (file, "return nia;");
85566e63ce3Schristos 		lf_indent (file, -2);
85666e63ce3Schristos 		lf_printf (file, "}\n");
85766e63ce3Schristos 	      }
85866e63ce3Schristos 	  }
85966e63ce3Schristos 	break;
86066e63ce3Schristos       }
86166e63ce3Schristos     case generate_jumps:
86266e63ce3Schristos       {
86366e63ce3Schristos 	lf_print__this_file_is_empty (file, "generating a jump engine");
86466e63ce3Schristos 	break;
86566e63ce3Schristos       }
86666e63ce3Schristos     }
86766e63ce3Schristos }
86866e63ce3Schristos 
86966e63ce3Schristos 
87066e63ce3Schristos /****************************************************************/
87166e63ce3Schristos 
87266e63ce3Schristos 
87366e63ce3Schristos static void
gen_run_c(lf * file,gen_table * gen)87466e63ce3Schristos gen_run_c (lf *file, gen_table *gen)
87566e63ce3Schristos {
87666e63ce3Schristos   gen_list *entry;
87766e63ce3Schristos   lf_printf (file, "#include \"sim-main.h\"\n");
87866e63ce3Schristos   lf_printf (file, "#include \"engine.h\"\n");
87966e63ce3Schristos   lf_printf (file, "#include \"idecode.h\"\n");
88066e63ce3Schristos   lf_printf (file, "#include \"bfd.h\"\n");
88166e63ce3Schristos   lf_printf (file, "\n");
88266e63ce3Schristos 
88366e63ce3Schristos   if (options.gen.multi_sim)
88466e63ce3Schristos     {
88566e63ce3Schristos       print_idecode_issue_function_header (file, NULL, is_function_variable,
88666e63ce3Schristos 					   1);
88766e63ce3Schristos       lf_printf (file, "\n");
88866e63ce3Schristos       print_engine_run_function_header (file, NULL, is_function_variable);
88966e63ce3Schristos       lf_printf (file, "\n");
89066e63ce3Schristos     }
89166e63ce3Schristos 
89266e63ce3Schristos   lf_printf (file, "void\n");
89366e63ce3Schristos   lf_printf (file, "sim_engine_run (SIM_DESC sd,\n");
89466e63ce3Schristos   lf_printf (file, "                int next_cpu_nr,\n");
89566e63ce3Schristos   lf_printf (file, "                int nr_cpus,\n");
89666e63ce3Schristos   lf_printf (file, "                int siggnal)\n");
89766e63ce3Schristos   lf_printf (file, "{\n");
89866e63ce3Schristos   lf_indent (file, +2);
89966e63ce3Schristos   if (options.gen.multi_sim)
90066e63ce3Schristos     {
90166e63ce3Schristos       lf_printf (file, "int mach;\n");
90266e63ce3Schristos       lf_printf (file, "if (STATE_ARCHITECTURE (sd) == NULL)\n");
90366e63ce3Schristos       lf_printf (file, "  mach = 0;\n");
90466e63ce3Schristos       lf_printf (file, "else\n");
90566e63ce3Schristos       lf_printf (file, "  mach = STATE_ARCHITECTURE (sd)->mach;\n");
90666e63ce3Schristos       lf_printf (file, "switch (mach)\n");
90766e63ce3Schristos       lf_printf (file, "  {\n");
90866e63ce3Schristos       lf_indent (file, +2);
90966e63ce3Schristos       for (entry = gen->tables; entry != NULL; entry = entry->next)
91066e63ce3Schristos 	{
91166e63ce3Schristos 	  if (options.gen.default_model != NULL
91266e63ce3Schristos 	      && (strcmp (entry->model->name, options.gen.default_model) == 0
91366e63ce3Schristos 		  || strcmp (entry->model->full_name,
91466e63ce3Schristos 			     options.gen.default_model) == 0))
91566e63ce3Schristos 	    lf_printf (file, "default:\n");
91666e63ce3Schristos 	  lf_printf (file, "case bfd_mach_%s:\n", entry->model->full_name);
91766e63ce3Schristos 	  lf_indent (file, +2);
91866e63ce3Schristos 	  print_function_name (file, "issue", NULL,	/* format name */
91966e63ce3Schristos 			       NULL,	/* NO processor */
92066e63ce3Schristos 			       NULL,	/* expanded bits */
92166e63ce3Schristos 			       function_name_prefix_idecode);
92266e63ce3Schristos 	  lf_printf (file, " = ");
92366e63ce3Schristos 	  print_function_name (file, "issue", NULL,	/* format name */
92466e63ce3Schristos 			       entry->model->name, NULL,	/* expanded bits */
92566e63ce3Schristos 			       function_name_prefix_idecode);
92666e63ce3Schristos 	  lf_printf (file, ";\n");
92766e63ce3Schristos 	  print_function_name (file, "run", NULL,	/* format name */
92866e63ce3Schristos 			       NULL,	/* NO processor */
92966e63ce3Schristos 			       NULL,	/* expanded bits */
93066e63ce3Schristos 			       function_name_prefix_engine);
93166e63ce3Schristos 	  lf_printf (file, " = ");
93266e63ce3Schristos 	  print_function_name (file, "run", NULL,	/* format name */
93366e63ce3Schristos 			       entry->model->name, NULL,	/* expanded bits */
93466e63ce3Schristos 			       function_name_prefix_engine);
93566e63ce3Schristos 	  lf_printf (file, ";\n");
93666e63ce3Schristos 	  lf_printf (file, "break;\n");
93766e63ce3Schristos 	  lf_indent (file, -2);
93866e63ce3Schristos 	}
93966e63ce3Schristos       if (options.gen.default_model == NULL)
94066e63ce3Schristos 	{
94166e63ce3Schristos 	  lf_printf (file, "default:\n");
94266e63ce3Schristos 	  lf_indent (file, +2);
94366e63ce3Schristos 	  lf_printf (file, "sim_engine_abort (sd, NULL, NULL_CIA,\n");
94466e63ce3Schristos 	  lf_printf (file,
94566e63ce3Schristos 		     "                  \"sim_engine_run - unknown machine\");\n");
94666e63ce3Schristos 	  lf_printf (file, "break;\n");
94766e63ce3Schristos 	  lf_indent (file, -2);
94866e63ce3Schristos 	}
94966e63ce3Schristos       lf_indent (file, -2);
95066e63ce3Schristos       lf_printf (file, "  }\n");
95166e63ce3Schristos     }
95266e63ce3Schristos   print_function_name (file, "run", NULL,	/* format name */
95366e63ce3Schristos 		       NULL,	/* NO processor */
95466e63ce3Schristos 		       NULL,	/* expanded bits */
95566e63ce3Schristos 		       function_name_prefix_engine);
95666e63ce3Schristos   lf_printf (file, " (sd, next_cpu_nr, nr_cpus, siggnal);\n");
95766e63ce3Schristos   lf_indent (file, -2);
95866e63ce3Schristos   lf_printf (file, "}\n");
95966e63ce3Schristos }
96066e63ce3Schristos 
96166e63ce3Schristos /****************************************************************/
96266e63ce3Schristos 
96366e63ce3Schristos static gen_table *
do_gen(insn_table * isa,decode_table * decode_rules)96466e63ce3Schristos do_gen (insn_table *isa, decode_table *decode_rules)
96566e63ce3Schristos {
96666e63ce3Schristos   gen_table *gen;
96766e63ce3Schristos   if (decode_rules == NULL)
96866e63ce3Schristos     error (NULL, "Must specify a decode table\n");
96966e63ce3Schristos   if (isa == NULL)
97066e63ce3Schristos     error (NULL, "Must specify an instruction table\n");
97166e63ce3Schristos   if (decode_table_max_word_nr (decode_rules) > 0)
97266e63ce3Schristos     options.gen.multi_word = decode_table_max_word_nr (decode_rules);
97366e63ce3Schristos   gen = make_gen_tables (isa, decode_rules);
97466e63ce3Schristos   gen_tables_expand_insns (gen);
97566e63ce3Schristos   gen_tables_expand_semantics (gen);
97666e63ce3Schristos   return gen;
97766e63ce3Schristos }
97866e63ce3Schristos 
97966e63ce3Schristos /****************************************************************/
98066e63ce3Schristos 
98166e63ce3Schristos igen_options options;
98266e63ce3Schristos 
98366e63ce3Schristos int
main(int argc,char ** argv,char ** envp)98466e63ce3Schristos main (int argc, char **argv, char **envp)
98566e63ce3Schristos {
98666e63ce3Schristos   cache_entry *cache_rules = NULL;
98766e63ce3Schristos   lf_file_references file_references = lf_include_references;
98866e63ce3Schristos   decode_table *decode_rules = NULL;
98966e63ce3Schristos   insn_table *isa = NULL;
99066e63ce3Schristos   gen_table *gen = NULL;
99166e63ce3Schristos   char *real_file_name = NULL;
99266e63ce3Schristos   int is_header = 0;
99366e63ce3Schristos   int ch;
99466e63ce3Schristos   lf *standard_out =
99566e63ce3Schristos     lf_open ("-", "stdout", lf_omit_references, lf_is_text, "igen");
99666e63ce3Schristos 
99766e63ce3Schristos   INIT_OPTIONS ();
99866e63ce3Schristos 
99966e63ce3Schristos   if (argc == 1)
100066e63ce3Schristos     {
100166e63ce3Schristos       printf ("Usage:\n");
100266e63ce3Schristos       printf ("\n");
100366e63ce3Schristos       printf ("  igen <config-opts> ... <input-opts>... <output-opts>...\n");
100466e63ce3Schristos       printf ("\n");
100566e63ce3Schristos       printf ("Config options:\n");
100666e63ce3Schristos       printf ("\n");
100766e63ce3Schristos       printf ("  -B <bit-size>\n");
100866e63ce3Schristos       printf ("\t Set the number of bits in an instruction (deprecated).\n");
100966e63ce3Schristos       printf
101066e63ce3Schristos 	("\t This option can now be set directly in the instruction table.\n");
101166e63ce3Schristos       printf ("\n");
101266e63ce3Schristos       printf ("  -D <data-structure>\n");
101366e63ce3Schristos       printf
101466e63ce3Schristos 	("\t Dump the specified data structure to stdout. Valid structures include:\n");
101566e63ce3Schristos       printf
101666e63ce3Schristos 	("\t processor-names - list the names of all the processors (models)\n");
101766e63ce3Schristos       printf ("\n");
101866e63ce3Schristos       printf ("  -F <filter-list>\n");
101966e63ce3Schristos       printf
102066e63ce3Schristos 	("\t Filter out any instructions with a non-empty flags field that contains\n");
102166e63ce3Schristos       printf ("\t a flag not listed in the <filter-list>.\n");
102266e63ce3Schristos       printf ("\n");
102366e63ce3Schristos       printf ("  -H <high-bit>\n");
102466e63ce3Schristos       printf
102566e63ce3Schristos 	("\t Set the number of the high (most significant) instruction bit (deprecated).\n");
102666e63ce3Schristos       printf
102766e63ce3Schristos 	("\t This option can now be set directly in the instruction table.\n");
102866e63ce3Schristos       printf ("\n");
102966e63ce3Schristos       printf ("  -I <directory>\n");
103066e63ce3Schristos       printf
103166e63ce3Schristos 	("\t Add <directory> to the list of directories searched when opening a file\n");
103266e63ce3Schristos       printf ("\n");
103366e63ce3Schristos       printf ("  -M <model-list>\n");
103466e63ce3Schristos       printf
103566e63ce3Schristos 	("\t Filter out any instructions that do not support at least one of the listed\n");
103666e63ce3Schristos       printf
103766e63ce3Schristos 	("\t models (An instructions with no model information is considered to support\n");
103866e63ce3Schristos       printf ("\t all models.).\n");
103966e63ce3Schristos       printf ("\n");
104066e63ce3Schristos       printf ("  -N <nr-cpus>\n");
104166e63ce3Schristos       printf ("\t Generate a simulator supporting <nr-cpus>\n");
104266e63ce3Schristos       printf
104366e63ce3Schristos 	("\t Specify `-N 0' to disable generation of the SMP. Specifying `-N 1' will\n");
104466e63ce3Schristos       printf
104566e63ce3Schristos 	("\t still generate an SMP enabled simulator but will only support one CPU.\n");
104666e63ce3Schristos       printf ("\n");
104766e63ce3Schristos       printf ("  -T <mechanism>\n");
104866e63ce3Schristos       printf
104966e63ce3Schristos 	("\t Override the decode mechanism specified by the decode rules\n");
105066e63ce3Schristos       printf ("\n");
105166e63ce3Schristos       printf ("  -P <prefix>\n");
105266e63ce3Schristos       printf
105366e63ce3Schristos 	("\t Prepend global names (except itable) with the string <prefix>.\n");
105466e63ce3Schristos       printf
105566e63ce3Schristos 	("\t Specify -P <module>=<prefix> to set a specific <module>'s prefix.\n");
105666e63ce3Schristos       printf ("\n");
105766e63ce3Schristos       printf ("  -S <suffix>\n");
105866e63ce3Schristos       printf
105966e63ce3Schristos 	("\t Replace a global name (suffix) (except itable) with the string <suffix>.\n");
106066e63ce3Schristos       printf
106166e63ce3Schristos 	("\t Specify -S <module>=<suffix> to change a specific <module>'s name (suffix).\n");
106266e63ce3Schristos       printf ("\n");
106366e63ce3Schristos       printf ("  -Werror\n");
106466e63ce3Schristos       printf ("\t Make warnings errors\n");
106566e63ce3Schristos       printf ("  -Wnodiscard\n");
106666e63ce3Schristos       printf
106766e63ce3Schristos 	("\t Suppress warnings about discarded functions and instructions\n");
106866e63ce3Schristos       printf ("  -Wnowidth\n");
106966e63ce3Schristos       printf
107066e63ce3Schristos 	("\t Suppress warnings about instructions with invalid widths\n");
107166e63ce3Schristos       printf ("  -Wnounimplemented\n");
107266e63ce3Schristos       printf ("\t Suppress warnings about unimplemented instructions\n");
107366e63ce3Schristos       printf ("\n");
107466e63ce3Schristos       printf ("  -G [!]<gen-option>\n");
107566e63ce3Schristos       printf ("\t Any of the following options:\n");
107666e63ce3Schristos       printf ("\n");
107766e63ce3Schristos       printf
107866e63ce3Schristos 	("\t decode-duplicate       - Override the decode rules, forcing the duplication of\n");
107966e63ce3Schristos       printf ("\t                          semantic functions\n");
108066e63ce3Schristos       printf
108166e63ce3Schristos 	("\t decode-combine         - Combine any duplicated entries within a table\n");
108266e63ce3Schristos       printf
108366e63ce3Schristos 	("\t decode-zero-reserved   - Override the decode rules, forcing reserved bits to be\n");
108466e63ce3Schristos       printf ("\t                          treated as zero.\n");
108566e63ce3Schristos       printf
108666e63ce3Schristos 	("\t decode-switch-is-goto  - Overfide the padded-switch code type as a goto-switch\n");
108766e63ce3Schristos       printf ("\n");
108866e63ce3Schristos       printf
108966e63ce3Schristos 	("\t gen-conditional-issue  - conditionally issue each instruction\n");
109066e63ce3Schristos       printf
109166e63ce3Schristos 	("\t gen-delayed-branch     - need both cia and nia passed around\n");
109266e63ce3Schristos       printf
109366e63ce3Schristos 	("\t gen-direct-access      - use #defines to directly access values\n");
109466e63ce3Schristos       printf
109566e63ce3Schristos 	("\t gen-zero-r<N>          - arch assumes GPR(<N>) == 0, keep it that way\n");
109666e63ce3Schristos       printf
109766e63ce3Schristos 	("\t gen-icache[=<N>        - generate an instruction cracking cache of size <N>\n");
109866e63ce3Schristos       printf ("\t                          Default size is %d\n",
109966e63ce3Schristos 	      options.gen.icache_size);
110066e63ce3Schristos       printf
110166e63ce3Schristos 	("\t gen-insn-in-icache     - save original instruction when cracking\n");
110266e63ce3Schristos       printf
110366e63ce3Schristos 	("\t gen-multi-sim[=MODEL]  - generate multiple simulators - one per model\n");
110466e63ce3Schristos       printf
110566e63ce3Schristos 	("\t                          If specified MODEL is made the default architecture.\n");
110666e63ce3Schristos       printf
110766e63ce3Schristos 	("\t                          By default, a single simulator that will\n");
110866e63ce3Schristos       printf
110966e63ce3Schristos 	("\t                          execute any instruction is generated\n");
111066e63ce3Schristos       printf
111166e63ce3Schristos 	("\t gen-multi-word         - generate code allowing for multi-word insns\n");
111266e63ce3Schristos       printf
111366e63ce3Schristos 	("\t gen-semantic-icache    - include semantic code in cracking functions\n");
111466e63ce3Schristos       printf
111566e63ce3Schristos 	("\t gen-slot-verification  - perform slot verification as part of decode\n");
111666e63ce3Schristos       printf ("\t gen-nia-invalid        - NIA defaults to nia_invalid\n");
111766e63ce3Schristos       printf ("\t gen-nia-void           - do not compute/return NIA\n");
111866e63ce3Schristos       printf ("\n");
111966e63ce3Schristos       printf
112066e63ce3Schristos 	("\t trace-combine          - report combined entries a rule application\n");
112166e63ce3Schristos       printf
112266e63ce3Schristos 	("\t trace-entries          - report entries after a rules application\n");
112366e63ce3Schristos       printf ("\t trace-rule-rejection   - report each rule as rejected\n");
112466e63ce3Schristos       printf ("\t trace-rule-selection   - report each rule as selected\n");
112566e63ce3Schristos       printf
112666e63ce3Schristos 	("\t trace-insn-insertion   - report each instruction as it is inserted into a decode table\n");
112766e63ce3Schristos       printf
112866e63ce3Schristos 	("\t trace-rule-expansion   - report each instruction as it is expanded (before insertion into a decode table)\n");
112966e63ce3Schristos       printf ("\t trace-all              - enable all trace options\n");
113066e63ce3Schristos       printf ("\n");
113166e63ce3Schristos       printf
113266e63ce3Schristos 	("\t field-widths           - instruction formats specify widths (deprecated)\n");
113366e63ce3Schristos       printf
113466e63ce3Schristos 	("\t                          By default, an instruction format specifies bit\n");
113566e63ce3Schristos       printf ("\t                          positions\n");
113666e63ce3Schristos       printf
113766e63ce3Schristos 	("\t                          This option can now be set directly in the\n");
113866e63ce3Schristos       printf ("\t                          instruction table\n");
113966e63ce3Schristos       printf
114066e63ce3Schristos 	("\t jumps                  - use jumps instead of function calls\n");
114166e63ce3Schristos       printf
114266e63ce3Schristos 	("\t omit-line-numbers      - do not include line number information in the output\n");
114366e63ce3Schristos       printf ("\n");
114466e63ce3Schristos       printf ("Input options:\n");
114566e63ce3Schristos       printf ("\n");
114666e63ce3Schristos       printf ("  -k <cache-rules> (deprecated)\n");
114766e63ce3Schristos       printf ("  -o <decode-rules>\n");
114866e63ce3Schristos       printf ("  -i <instruction-table>\n");
114966e63ce3Schristos       printf ("\n");
115066e63ce3Schristos       printf ("Output options:\n");
115166e63ce3Schristos       printf ("\n");
115266e63ce3Schristos       printf ("  -x                    Perform expansion (required)\n");
115366e63ce3Schristos       printf
115466e63ce3Schristos 	("  -n <real-name>        Specify the real name of the next output file\n");
115566e63ce3Schristos       printf
115666e63ce3Schristos 	("  -h 		       Generate the header (.h) file rather than the body (.c)\n");
115766e63ce3Schristos       printf ("  -c <output-file>      output icache\n");
115866e63ce3Schristos       printf ("  -d <output-file>      output idecode\n");
115966e63ce3Schristos       printf ("  -e <output-file>      output engine\n");
116066e63ce3Schristos       printf ("  -f <output-file>      output support functions\n");
116166e63ce3Schristos       printf ("  -m <output-file>      output model\n");
116266e63ce3Schristos       printf ("  -r <output-file>      output multi-sim run\n");
116366e63ce3Schristos       printf ("  -s <output-file>      output schematic\n");
116466e63ce3Schristos       printf ("  -t <output-file>      output itable\n");
116566e63ce3Schristos     }
116666e63ce3Schristos 
116766e63ce3Schristos   while ((ch = getopt (argc, argv,
116866e63ce3Schristos 		       "B:D:F:G:H:I:M:N:P:T:W:o:k:i:n:hc:d:e:m:r:s:t:f:x"))
116966e63ce3Schristos 	 != -1)
117066e63ce3Schristos     {
117166e63ce3Schristos       fprintf (stderr, "  -%c ", ch);
117266e63ce3Schristos       if (optarg)
117366e63ce3Schristos 	fprintf (stderr, "%s ", optarg);
117466e63ce3Schristos       fprintf (stderr, "\\\n");
117566e63ce3Schristos 
117666e63ce3Schristos       switch (ch)
117766e63ce3Schristos 	{
117866e63ce3Schristos 
117966e63ce3Schristos 	case 'M':
118066e63ce3Schristos 	  filter_parse (&options.model_filter, optarg);
118166e63ce3Schristos 	  break;
118266e63ce3Schristos 
118366e63ce3Schristos 	case 'D':
118466e63ce3Schristos 	  if (strcmp (optarg, "processor-names"))
118566e63ce3Schristos 	    {
118666e63ce3Schristos 	      char *processor;
118766e63ce3Schristos 	      for (processor = filter_next (options.model_filter, "");
118866e63ce3Schristos 		   processor != NULL;
118966e63ce3Schristos 		   processor = filter_next (options.model_filter, processor))
119066e63ce3Schristos 		lf_printf (standard_out, "%s\n", processor);
119166e63ce3Schristos 	    }
119266e63ce3Schristos 	  else
119366e63ce3Schristos 	    error (NULL, "Unknown data structure %s, not dumped\n", optarg);
119466e63ce3Schristos 	  break;
119566e63ce3Schristos 
119666e63ce3Schristos 	case 'F':
119766e63ce3Schristos 	  filter_parse (&options.flags_filter, optarg);
119866e63ce3Schristos 	  break;
119966e63ce3Schristos 
120066e63ce3Schristos 	case 'I':
120166e63ce3Schristos 	  {
120266e63ce3Schristos 	    table_include **dir = &options.include;
120366e63ce3Schristos 	    while ((*dir) != NULL)
120466e63ce3Schristos 	      dir = &(*dir)->next;
120566e63ce3Schristos 	    (*dir) = ZALLOC (table_include);
120666e63ce3Schristos 	    (*dir)->dir = strdup (optarg);
120766e63ce3Schristos 	  }
120866e63ce3Schristos 	  break;
120966e63ce3Schristos 
121066e63ce3Schristos 	case 'B':
121166e63ce3Schristos 	  options.insn_bit_size = a2i (optarg);
121266e63ce3Schristos 	  if (options.insn_bit_size <= 0
121366e63ce3Schristos 	      || options.insn_bit_size > max_insn_bit_size)
121466e63ce3Schristos 	    {
121566e63ce3Schristos 	      error (NULL, "Instruction bitsize must be in range 1..%d\n",
121666e63ce3Schristos 		     max_insn_bit_size);
121766e63ce3Schristos 	    }
121866e63ce3Schristos 	  if (options.hi_bit_nr != options.insn_bit_size - 1
121966e63ce3Schristos 	      && options.hi_bit_nr != 0)
122066e63ce3Schristos 	    {
122166e63ce3Schristos 	      error (NULL, "Conflict betweem hi-bit-nr and insn-bit-size\n");
122266e63ce3Schristos 	    }
122366e63ce3Schristos 	  break;
122466e63ce3Schristos 
122566e63ce3Schristos 	case 'H':
122666e63ce3Schristos 	  options.hi_bit_nr = a2i (optarg);
122766e63ce3Schristos 	  if (options.hi_bit_nr != options.insn_bit_size - 1
122866e63ce3Schristos 	      && options.hi_bit_nr != 0)
122966e63ce3Schristos 	    {
123066e63ce3Schristos 	      error (NULL, "Conflict between hi-bit-nr and insn-bit-size\n");
123166e63ce3Schristos 	    }
123266e63ce3Schristos 	  break;
123366e63ce3Schristos 
123466e63ce3Schristos 	case 'N':
123566e63ce3Schristos 	  options.gen.smp = a2i (optarg);
123666e63ce3Schristos 	  break;
123766e63ce3Schristos 
123866e63ce3Schristos 	case 'P':
123966e63ce3Schristos 	case 'S':
124066e63ce3Schristos 	  {
124166e63ce3Schristos 	    igen_module *names;
124266e63ce3Schristos 	    igen_name *name;
124366e63ce3Schristos 	    char *chp;
124466e63ce3Schristos 	    chp = strchr (optarg, '=');
124566e63ce3Schristos 	    if (chp == NULL)
124666e63ce3Schristos 	      {
124766e63ce3Schristos 		names = &options.module.global;
124866e63ce3Schristos 		chp = optarg;
124966e63ce3Schristos 	      }
125066e63ce3Schristos 	    else
125166e63ce3Schristos 	      {
125266e63ce3Schristos 		chp = chp + 1;	/* skip `=' */
125366e63ce3Schristos 		names = NULL;
125466e63ce3Schristos 		if (strncmp (optarg, "global=", chp - optarg) == 0)
125566e63ce3Schristos 		  {
125666e63ce3Schristos 		    names = &options.module.global;
125766e63ce3Schristos 		  }
125866e63ce3Schristos 		if (strncmp (optarg, "engine=", chp - optarg) == 0)
125966e63ce3Schristos 		  {
126066e63ce3Schristos 		    names = &options.module.engine;
126166e63ce3Schristos 		  }
126266e63ce3Schristos 		if (strncmp (optarg, "icache=", chp - optarg) == 0)
126366e63ce3Schristos 		  {
126466e63ce3Schristos 		    names = &options.module.icache;
126566e63ce3Schristos 		  }
126666e63ce3Schristos 		if (strncmp (optarg, "idecode=", chp - optarg) == 0)
126766e63ce3Schristos 		  {
126866e63ce3Schristos 		    names = &options.module.idecode;
126966e63ce3Schristos 		  }
127066e63ce3Schristos 		if (strncmp (optarg, "itable=", chp - optarg) == 0)
127166e63ce3Schristos 		  {
127266e63ce3Schristos 		    names = &options.module.itable;
127366e63ce3Schristos 		  }
127466e63ce3Schristos 		if (strncmp (optarg, "semantics=", chp - optarg) == 0)
127566e63ce3Schristos 		  {
127666e63ce3Schristos 		    names = &options.module.semantics;
127766e63ce3Schristos 		  }
127866e63ce3Schristos 		if (strncmp (optarg, "support=", chp - optarg) == 0)
127966e63ce3Schristos 		  {
128066e63ce3Schristos 		    names = &options.module.support;
128166e63ce3Schristos 		  }
128266e63ce3Schristos 		if (names == NULL)
128366e63ce3Schristos 		  {
128466e63ce3Schristos 		    error (NULL, "Prefix `%s' unreconized\n", optarg);
128566e63ce3Schristos 		  }
128666e63ce3Schristos 	      }
128766e63ce3Schristos 	    switch (ch)
128866e63ce3Schristos 	      {
128966e63ce3Schristos 	      case 'P':
129066e63ce3Schristos 		name = &names->prefix;
129166e63ce3Schristos 		break;
129266e63ce3Schristos 	      case 'S':
129366e63ce3Schristos 		name = &names->suffix;
129466e63ce3Schristos 		break;
129566e63ce3Schristos 	      default:
129666e63ce3Schristos 		abort ();	/* Bad switch.  */
129766e63ce3Schristos 	      }
129866e63ce3Schristos 	    name->u = strdup (chp);
129966e63ce3Schristos 	    name->l = strdup (chp);
130066e63ce3Schristos 	    chp = name->u;
130166e63ce3Schristos 	    while (*chp)
130266e63ce3Schristos 	      {
130366e63ce3Schristos 		if (islower (*chp))
130466e63ce3Schristos 		  *chp = toupper (*chp);
130566e63ce3Schristos 		chp++;
130666e63ce3Schristos 	      }
130766e63ce3Schristos 	    if (name == &options.module.global.prefix)
130866e63ce3Schristos 	      {
130966e63ce3Schristos 		options.module.engine.prefix = options.module.global.prefix;
131066e63ce3Schristos 		options.module.icache.prefix = options.module.global.prefix;
131166e63ce3Schristos 		options.module.idecode.prefix = options.module.global.prefix;
131266e63ce3Schristos 		/* options.module.itable.prefix = options.module.global.prefix; */
131366e63ce3Schristos 		options.module.semantics.prefix =
131466e63ce3Schristos 		  options.module.global.prefix;
131566e63ce3Schristos 		options.module.support.prefix = options.module.global.prefix;
131666e63ce3Schristos 	      }
131766e63ce3Schristos 	    if (name == &options.module.global.suffix)
131866e63ce3Schristos 	      {
131966e63ce3Schristos 		options.module.engine.suffix = options.module.global.suffix;
132066e63ce3Schristos 		options.module.icache.suffix = options.module.global.suffix;
132166e63ce3Schristos 		options.module.idecode.suffix = options.module.global.suffix;
132266e63ce3Schristos 		/* options.module.itable.suffix = options.module.global.suffix; */
132366e63ce3Schristos 		options.module.semantics.suffix =
132466e63ce3Schristos 		  options.module.global.suffix;
132566e63ce3Schristos 		options.module.support.suffix = options.module.global.suffix;
132666e63ce3Schristos 	      }
132766e63ce3Schristos 	    break;
132866e63ce3Schristos 	  }
132966e63ce3Schristos 
133066e63ce3Schristos 	case 'W':
133166e63ce3Schristos 	  {
133266e63ce3Schristos 	    if (strcmp (optarg, "error") == 0)
133366e63ce3Schristos 	      options.warning = error;
133466e63ce3Schristos 	    else if (strcmp (optarg, "nodiscard") == 0)
133566e63ce3Schristos 	      options.warn.discard = 0;
133666e63ce3Schristos 	    else if (strcmp (optarg, "discard") == 0)
133766e63ce3Schristos 	      options.warn.discard = 1;
133866e63ce3Schristos 	    else if (strcmp (optarg, "nowidth") == 0)
133966e63ce3Schristos 	      options.warn.width = 0;
134066e63ce3Schristos 	    else if (strcmp (optarg, "width") == 0)
134166e63ce3Schristos 	      options.warn.width = 1;
134266e63ce3Schristos 	    else if (strcmp (optarg, "nounimplemented") == 0)
134366e63ce3Schristos 	      options.warn.unimplemented = 0;
134466e63ce3Schristos 	    else if (strcmp (optarg, "unimplemented") == 0)
134566e63ce3Schristos 	      options.warn.unimplemented = 1;
134666e63ce3Schristos 	    else
134766e63ce3Schristos 	      error (NULL, "Unknown -W argument `%s'\n", optarg);
134866e63ce3Schristos 	    break;
134966e63ce3Schristos 	  }
135066e63ce3Schristos 
135166e63ce3Schristos 
135266e63ce3Schristos 	case 'G':
135366e63ce3Schristos 	  {
135466e63ce3Schristos 	    int enable_p;
135566e63ce3Schristos 	    char *argp;
135666e63ce3Schristos 	    if (strncmp (optarg, "no-", strlen ("no-")) == 0)
135766e63ce3Schristos 	      {
135866e63ce3Schristos 		argp = optarg + strlen ("no-");
135966e63ce3Schristos 		enable_p = 0;
136066e63ce3Schristos 	      }
136166e63ce3Schristos 	    else if (strncmp (optarg, "!", strlen ("!")) == 0)
136266e63ce3Schristos 	      {
136366e63ce3Schristos 		argp = optarg + strlen ("no-");
136466e63ce3Schristos 		enable_p = 0;
136566e63ce3Schristos 	      }
136666e63ce3Schristos 	    else
136766e63ce3Schristos 	      {
136866e63ce3Schristos 		argp = optarg;
136966e63ce3Schristos 		enable_p = 1;
137066e63ce3Schristos 	      }
137166e63ce3Schristos 	    if (strcmp (argp, "decode-duplicate") == 0)
137266e63ce3Schristos 	      {
137366e63ce3Schristos 		options.decode.duplicate = enable_p;
137466e63ce3Schristos 	      }
137566e63ce3Schristos 	    else if (strcmp (argp, "decode-combine") == 0)
137666e63ce3Schristos 	      {
137766e63ce3Schristos 		options.decode.combine = enable_p;
137866e63ce3Schristos 	      }
137966e63ce3Schristos 	    else if (strcmp (argp, "decode-zero-reserved") == 0)
138066e63ce3Schristos 	      {
138166e63ce3Schristos 		options.decode.zero_reserved = enable_p;
138266e63ce3Schristos 	      }
138366e63ce3Schristos 
138466e63ce3Schristos 	    else if (strcmp (argp, "gen-conditional-issue") == 0)
138566e63ce3Schristos 	      {
138666e63ce3Schristos 		options.gen.conditional_issue = enable_p;
138766e63ce3Schristos 	      }
138866e63ce3Schristos 	    else if (strcmp (argp, "conditional-issue") == 0)
138966e63ce3Schristos 	      {
139066e63ce3Schristos 		options.gen.conditional_issue = enable_p;
139166e63ce3Schristos 		options.warning (NULL,
139266e63ce3Schristos 				 "Option conditional-issue replaced by gen-conditional-issue\n");
139366e63ce3Schristos 	      }
139466e63ce3Schristos 	    else if (strcmp (argp, "gen-delayed-branch") == 0)
139566e63ce3Schristos 	      {
139666e63ce3Schristos 		options.gen.delayed_branch = enable_p;
139766e63ce3Schristos 	      }
139866e63ce3Schristos 	    else if (strcmp (argp, "delayed-branch") == 0)
139966e63ce3Schristos 	      {
140066e63ce3Schristos 		options.gen.delayed_branch = enable_p;
140166e63ce3Schristos 		options.warning (NULL,
140266e63ce3Schristos 				 "Option delayed-branch replaced by gen-delayed-branch\n");
140366e63ce3Schristos 	      }
140466e63ce3Schristos 	    else if (strcmp (argp, "gen-direct-access") == 0)
140566e63ce3Schristos 	      {
140666e63ce3Schristos 		options.gen.direct_access = enable_p;
140766e63ce3Schristos 	      }
140866e63ce3Schristos 	    else if (strcmp (argp, "direct-access") == 0)
140966e63ce3Schristos 	      {
141066e63ce3Schristos 		options.gen.direct_access = enable_p;
141166e63ce3Schristos 		options.warning (NULL,
141266e63ce3Schristos 				 "Option direct-access replaced by gen-direct-access\n");
141366e63ce3Schristos 	      }
141466e63ce3Schristos 	    else if (strncmp (argp, "gen-zero-r", strlen ("gen-zero-r")) == 0)
141566e63ce3Schristos 	      {
141666e63ce3Schristos 		options.gen.zero_reg = enable_p;
141766e63ce3Schristos 		options.gen.zero_reg_nr = atoi (argp + strlen ("gen-zero-r"));
141866e63ce3Schristos 	      }
141966e63ce3Schristos 	    else if (strncmp (argp, "zero-r", strlen ("zero-r")) == 0)
142066e63ce3Schristos 	      {
142166e63ce3Schristos 		options.gen.zero_reg = enable_p;
142266e63ce3Schristos 		options.gen.zero_reg_nr = atoi (argp + strlen ("zero-r"));
142366e63ce3Schristos 		options.warning (NULL,
142466e63ce3Schristos 				 "Option zero-r<N> replaced by gen-zero-r<N>\n");
142566e63ce3Schristos 	      }
142666e63ce3Schristos 	    else if (strncmp (argp, "gen-icache", strlen ("gen-icache")) == 0)
142766e63ce3Schristos 	      {
142866e63ce3Schristos 		switch (argp[strlen ("gen-icache")])
142966e63ce3Schristos 		  {
143066e63ce3Schristos 		  case '=':
143166e63ce3Schristos 		    options.gen.icache_size =
143266e63ce3Schristos 		      atoi (argp + strlen ("gen-icache") + 1);
143366e63ce3Schristos 		    options.gen.icache = enable_p;
143466e63ce3Schristos 		    break;
143566e63ce3Schristos 		  case '\0':
143666e63ce3Schristos 		    options.gen.icache = enable_p;
143766e63ce3Schristos 		    break;
143866e63ce3Schristos 		  default:
143966e63ce3Schristos 		    error (NULL,
144066e63ce3Schristos 			   "Expecting -Ggen-icache or -Ggen-icache=<N>\n");
144166e63ce3Schristos 		  }
144266e63ce3Schristos 	      }
144366e63ce3Schristos 	    else if (strcmp (argp, "gen-insn-in-icache") == 0)
144466e63ce3Schristos 	      {
144566e63ce3Schristos 		options.gen.insn_in_icache = enable_p;
144666e63ce3Schristos 	      }
144766e63ce3Schristos 	    else if (strncmp (argp, "gen-multi-sim", strlen ("gen-multi-sim"))
144866e63ce3Schristos 		     == 0)
144966e63ce3Schristos 	      {
145066e63ce3Schristos 		char *arg = &argp[strlen ("gen-multi-sim")];
145166e63ce3Schristos 		switch (arg[0])
145266e63ce3Schristos 		  {
145366e63ce3Schristos 		  case '=':
145466e63ce3Schristos 		    options.gen.multi_sim = enable_p;
145566e63ce3Schristos 		    options.gen.default_model = arg + 1;
145666e63ce3Schristos 		    if (!filter_is_member
145766e63ce3Schristos 			(options.model_filter, options.gen.default_model))
145866e63ce3Schristos 		      error (NULL, "multi-sim model %s unknown\n",
145966e63ce3Schristos 			     options.gen.default_model);
146066e63ce3Schristos 		    break;
146166e63ce3Schristos 		  case '\0':
146266e63ce3Schristos 		    options.gen.multi_sim = enable_p;
146366e63ce3Schristos 		    options.gen.default_model = NULL;
146466e63ce3Schristos 		    break;
146566e63ce3Schristos 		  default:
146666e63ce3Schristos 		    error (NULL,
146766e63ce3Schristos 			   "Expecting -Ggen-multi-sim or -Ggen-multi-sim=<MODEL>\n");
146866e63ce3Schristos 		    break;
146966e63ce3Schristos 		  }
147066e63ce3Schristos 	      }
147166e63ce3Schristos 	    else if (strcmp (argp, "gen-multi-word") == 0)
147266e63ce3Schristos 	      {
147366e63ce3Schristos 		options.gen.multi_word = enable_p;
147466e63ce3Schristos 	      }
147566e63ce3Schristos 	    else if (strcmp (argp, "gen-semantic-icache") == 0)
147666e63ce3Schristos 	      {
147766e63ce3Schristos 		options.gen.semantic_icache = enable_p;
147866e63ce3Schristos 	      }
147966e63ce3Schristos 	    else if (strcmp (argp, "gen-slot-verification") == 0)
148066e63ce3Schristos 	      {
148166e63ce3Schristos 		options.gen.slot_verification = enable_p;
148266e63ce3Schristos 	      }
148366e63ce3Schristos 	    else if (strcmp (argp, "verify-slot") == 0)
148466e63ce3Schristos 	      {
148566e63ce3Schristos 		options.gen.slot_verification = enable_p;
148666e63ce3Schristos 		options.warning (NULL,
148766e63ce3Schristos 				 "Option verify-slot replaced by gen-slot-verification\n");
148866e63ce3Schristos 	      }
148966e63ce3Schristos 	    else if (strcmp (argp, "gen-nia-invalid") == 0)
149066e63ce3Schristos 	      {
149166e63ce3Schristos 		options.gen.nia = nia_is_invalid;
149266e63ce3Schristos 	      }
149366e63ce3Schristos 	    else if (strcmp (argp, "default-nia-minus-one") == 0)
149466e63ce3Schristos 	      {
149566e63ce3Schristos 		options.gen.nia = nia_is_invalid;
149666e63ce3Schristos 		options.warning (NULL,
149766e63ce3Schristos 				 "Option default-nia-minus-one replaced by gen-nia-invalid\n");
149866e63ce3Schristos 	      }
149966e63ce3Schristos 	    else if (strcmp (argp, "gen-nia-void") == 0)
150066e63ce3Schristos 	      {
150166e63ce3Schristos 		options.gen.nia = nia_is_void;
150266e63ce3Schristos 	      }
150366e63ce3Schristos 	    else if (strcmp (argp, "trace-all") == 0)
150466e63ce3Schristos 	      {
150566e63ce3Schristos 		memset (&options.trace, enable_p, sizeof (options.trace));
150666e63ce3Schristos 	      }
150766e63ce3Schristos 	    else if (strcmp (argp, "trace-combine") == 0)
150866e63ce3Schristos 	      {
150966e63ce3Schristos 		options.trace.combine = enable_p;
151066e63ce3Schristos 	      }
151166e63ce3Schristos 	    else if (strcmp (argp, "trace-entries") == 0)
151266e63ce3Schristos 	      {
151366e63ce3Schristos 		options.trace.entries = enable_p;
151466e63ce3Schristos 	      }
151566e63ce3Schristos 	    else if (strcmp (argp, "trace-rule-rejection") == 0)
151666e63ce3Schristos 	      {
151766e63ce3Schristos 		options.trace.rule_rejection = enable_p;
151866e63ce3Schristos 	      }
151966e63ce3Schristos 	    else if (strcmp (argp, "trace-rule-selection") == 0)
152066e63ce3Schristos 	      {
152166e63ce3Schristos 		options.trace.rule_selection = enable_p;
152266e63ce3Schristos 	      }
152366e63ce3Schristos 	    else if (strcmp (argp, "trace-insn-insertion") == 0)
152466e63ce3Schristos 	      {
152566e63ce3Schristos 		options.trace.insn_insertion = enable_p;
152666e63ce3Schristos 	      }
152766e63ce3Schristos 	    else if (strcmp (argp, "trace-insn-expansion") == 0)
152866e63ce3Schristos 	      {
152966e63ce3Schristos 		options.trace.insn_expansion = enable_p;
153066e63ce3Schristos 	      }
153166e63ce3Schristos 	    else if (strcmp (argp, "jumps") == 0)
153266e63ce3Schristos 	      {
153366e63ce3Schristos 		options.gen.code = generate_jumps;
153466e63ce3Schristos 	      }
153566e63ce3Schristos 	    else if (strcmp (argp, "field-widths") == 0)
153666e63ce3Schristos 	      {
153766e63ce3Schristos 		options.insn_specifying_widths = enable_p;
153866e63ce3Schristos 	      }
153966e63ce3Schristos 	    else if (strcmp (argp, "omit-line-numbers") == 0)
154066e63ce3Schristos 	      {
154166e63ce3Schristos 		file_references = lf_omit_references;
154266e63ce3Schristos 	      }
154366e63ce3Schristos 	    else
154466e63ce3Schristos 	      {
154566e63ce3Schristos 		error (NULL, "Unknown option %s\n", optarg);
154666e63ce3Schristos 	      }
154766e63ce3Schristos 	    break;
154866e63ce3Schristos 	  }
154966e63ce3Schristos 
155066e63ce3Schristos 	case 'i':
155166e63ce3Schristos 	  isa = load_insn_table (optarg, cache_rules);
155266e63ce3Schristos 	  if (isa->illegal_insn == NULL)
155366e63ce3Schristos 	    error (NULL, "illegal-instruction missing from insn table\n");
155466e63ce3Schristos 	  break;
155566e63ce3Schristos 
155666e63ce3Schristos 	case 'x':
155766e63ce3Schristos 	  gen = do_gen (isa, decode_rules);
155866e63ce3Schristos 	  break;
155966e63ce3Schristos 
156066e63ce3Schristos 	case 'o':
156166e63ce3Schristos 	  decode_rules = load_decode_table (optarg);
156266e63ce3Schristos 	  break;
156366e63ce3Schristos 
156466e63ce3Schristos 	case 'k':
156566e63ce3Schristos 	  if (isa != NULL)
156666e63ce3Schristos 	    error (NULL, "Cache file must appear before the insn file\n");
156766e63ce3Schristos 	  cache_rules = load_cache_table (optarg);
156866e63ce3Schristos 	  break;
156966e63ce3Schristos 
157066e63ce3Schristos 	case 'n':
157166e63ce3Schristos 	  real_file_name = strdup (optarg);
157266e63ce3Schristos 	  break;
157366e63ce3Schristos 
157466e63ce3Schristos 	case 'h':
157566e63ce3Schristos 	  is_header = 1;
157666e63ce3Schristos 	  break;
157766e63ce3Schristos 
157866e63ce3Schristos 	case 'c':
157966e63ce3Schristos 	case 'd':
158066e63ce3Schristos 	case 'e':
158166e63ce3Schristos 	case 'f':
158266e63ce3Schristos 	case 'm':
158366e63ce3Schristos 	case 'r':
158466e63ce3Schristos 	case 's':
158566e63ce3Schristos 	case 't':
158666e63ce3Schristos 	  {
158766e63ce3Schristos 	    lf *file = lf_open (optarg, real_file_name, file_references,
158866e63ce3Schristos 				(is_header ? lf_is_h : lf_is_c),
158966e63ce3Schristos 				argv[0]);
159066e63ce3Schristos 	    if (gen == NULL && ch != 't' && ch != 'm' && ch != 'f')
159166e63ce3Schristos 	      {
159266e63ce3Schristos 		options.warning (NULL,
159366e63ce3Schristos 				 "Explicitly generate tables with -x option\n");
159466e63ce3Schristos 		gen = do_gen (isa, decode_rules);
159566e63ce3Schristos 	      }
159666e63ce3Schristos 	    lf_print__file_start (file);
159766e63ce3Schristos 	    switch (ch)
159866e63ce3Schristos 	      {
159966e63ce3Schristos 	      case 'm':
160066e63ce3Schristos 		if (is_header)
160166e63ce3Schristos 		  gen_model_h (file, isa);
160266e63ce3Schristos 		else
160366e63ce3Schristos 		  gen_model_c (file, isa);
160466e63ce3Schristos 		break;
160566e63ce3Schristos 	      case 't':
160666e63ce3Schristos 		if (is_header)
160766e63ce3Schristos 		  gen_itable_h (file, isa);
160866e63ce3Schristos 		else
160966e63ce3Schristos 		  gen_itable_c (file, isa);
161066e63ce3Schristos 		break;
161166e63ce3Schristos 	      case 'f':
161266e63ce3Schristos 		if (is_header)
161366e63ce3Schristos 		  gen_support_h (file, isa);
161466e63ce3Schristos 		else
161566e63ce3Schristos 		  gen_support_c (file, isa);
161666e63ce3Schristos 		break;
161766e63ce3Schristos 	      case 'r':
161866e63ce3Schristos 		if (is_header)
161966e63ce3Schristos 		  options.warning (NULL, "-hr option ignored\n");
162066e63ce3Schristos 		else
162166e63ce3Schristos 		  gen_run_c (file, gen);
162266e63ce3Schristos 		break;
162366e63ce3Schristos 	      case 's':
162466e63ce3Schristos 		if (is_header)
162566e63ce3Schristos 		  gen_semantics_h (file, gen->semantics, isa->max_nr_words);
162666e63ce3Schristos 		else
162766e63ce3Schristos 		  gen_semantics_c (file, gen->semantics, isa->caches);
162866e63ce3Schristos 		break;
162966e63ce3Schristos 	      case 'd':
163066e63ce3Schristos 		if (is_header)
163166e63ce3Schristos 		  gen_idecode_h (file, gen, isa, cache_rules);
163266e63ce3Schristos 		else
163366e63ce3Schristos 		  gen_idecode_c (file, gen, isa, cache_rules);
163466e63ce3Schristos 		break;
163566e63ce3Schristos 	      case 'e':
163666e63ce3Schristos 		if (is_header)
163766e63ce3Schristos 		  gen_engine_h (file, gen, isa, cache_rules);
163866e63ce3Schristos 		else
163966e63ce3Schristos 		  gen_engine_c (file, gen, isa, cache_rules);
164066e63ce3Schristos 		break;
164166e63ce3Schristos 	      case 'c':
164266e63ce3Schristos 		if (is_header)
164366e63ce3Schristos 		  gen_icache_h (file,
164466e63ce3Schristos 				gen->semantics,
164566e63ce3Schristos 				isa->functions, isa->max_nr_words);
164666e63ce3Schristos 		else
164766e63ce3Schristos 		  gen_icache_c (file,
164866e63ce3Schristos 				gen->semantics, isa->functions, cache_rules);
164966e63ce3Schristos 		break;
165066e63ce3Schristos 	      }
165166e63ce3Schristos 	    lf_print__file_finish (file);
165266e63ce3Schristos 	    lf_close (file);
165366e63ce3Schristos 	    is_header = 0;
165466e63ce3Schristos 	  }
165566e63ce3Schristos 	  real_file_name = NULL;
165666e63ce3Schristos 	  break;
165766e63ce3Schristos 	default:
165866e63ce3Schristos 	  ERROR ("Bad switch");
165966e63ce3Schristos 	}
166066e63ce3Schristos     }
166166e63ce3Schristos   return (0);
166266e63ce3Schristos }
1663