xref: /netbsd-src/external/gpl3/gdb/dist/sim/igen/gen-idecode.c (revision 71f621822dbfd5073a314948bec169b7bb05f7be)
14e98e3e1Schristos /* The IGEN simulator generator for GDB, the GNU Debugger.
24e98e3e1Schristos 
3*71f62182Schristos    Copyright 2002-2024 Free Software Foundation, Inc.
44e98e3e1Schristos 
54e98e3e1Schristos    Contributed by Andrew Cagney.
64e98e3e1Schristos 
74e98e3e1Schristos    This file is part of GDB.
84e98e3e1Schristos 
94e98e3e1Schristos    This program is free software; you can redistribute it and/or modify
104e98e3e1Schristos    it under the terms of the GNU General Public License as published by
114e98e3e1Schristos    the Free Software Foundation; either version 3 of the License, or
124e98e3e1Schristos    (at your option) any later version.
134e98e3e1Schristos 
144e98e3e1Schristos    This program is distributed in the hope that it will be useful,
154e98e3e1Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
164e98e3e1Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
174e98e3e1Schristos    GNU General Public License for more details.
184e98e3e1Schristos 
194e98e3e1Schristos    You should have received a copy of the GNU General Public License
204e98e3e1Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
214e98e3e1Schristos 
224e98e3e1Schristos 
234e98e3e1Schristos #include "misc.h"
244e98e3e1Schristos #include "lf.h"
254e98e3e1Schristos #include "table.h"
264e98e3e1Schristos #include "filter.h"
274e98e3e1Schristos #include "igen.h"
284e98e3e1Schristos 
294e98e3e1Schristos #include "ld-insn.h"
304e98e3e1Schristos #include "ld-decode.h"
314e98e3e1Schristos 
324e98e3e1Schristos #include "gen.h"
334e98e3e1Schristos 
344e98e3e1Schristos #include "gen-idecode.h"
354e98e3e1Schristos #include "gen-icache.h"
364e98e3e1Schristos #include "gen-semantics.h"
374e98e3e1Schristos 
384e98e3e1Schristos 
394e98e3e1Schristos 
404e98e3e1Schristos static void
414b169a6bSchristos lf_print_opcodes (lf *file, const gen_entry *table)
424e98e3e1Schristos {
434e98e3e1Schristos   if (table !=NULL)
444e98e3e1Schristos     {
454e98e3e1Schristos       while (1)
464e98e3e1Schristos 	{
474e98e3e1Schristos 	  ASSERT (table->opcode != NULL);
484e98e3e1Schristos 	  lf_printf (file, "_%d_%d",
494e98e3e1Schristos 		     table->opcode->first, table->opcode->last);
504e98e3e1Schristos 	  if (table->parent == NULL)
514e98e3e1Schristos 	    break;
524e98e3e1Schristos 	  lf_printf (file, "__%d", table->opcode_nr);
534e98e3e1Schristos 	  table = table->parent;
544e98e3e1Schristos 	}
554e98e3e1Schristos     }
564e98e3e1Schristos }
574e98e3e1Schristos 
584e98e3e1Schristos 
594e98e3e1Schristos 
604e98e3e1Schristos 
614e98e3e1Schristos static void
624e98e3e1Schristos print_idecode_ifetch (lf *file,
634e98e3e1Schristos 		      int previous_nr_prefetched_words,
644e98e3e1Schristos 		      int current_nr_prefetched_words)
654e98e3e1Schristos {
664e98e3e1Schristos   int word_nr;
674e98e3e1Schristos   for (word_nr = previous_nr_prefetched_words;
684e98e3e1Schristos        word_nr < current_nr_prefetched_words; word_nr++)
694e98e3e1Schristos     {
704e98e3e1Schristos       lf_printf (file,
714e98e3e1Schristos 		 "instruction_word instruction_%d = IMEM%d_IMMED (cia, %d);\n",
724e98e3e1Schristos 		 word_nr, options.insn_bit_size, word_nr);
734e98e3e1Schristos 
744e98e3e1Schristos     }
754e98e3e1Schristos }
764e98e3e1Schristos 
774e98e3e1Schristos 
784e98e3e1Schristos 
794e98e3e1Schristos /****************************************************************/
804e98e3e1Schristos 
814e98e3e1Schristos 
824e98e3e1Schristos static void
834b169a6bSchristos lf_print_table_name (lf *file, const gen_entry *table)
844e98e3e1Schristos {
854e98e3e1Schristos   lf_printf (file, "idecode_table");
864e98e3e1Schristos   lf_print_opcodes (file, table);
874e98e3e1Schristos }
884e98e3e1Schristos 
894e98e3e1Schristos 
904e98e3e1Schristos 
914e98e3e1Schristos static void
924b169a6bSchristos print_idecode_table (lf *file, const gen_entry *entry, const char *result)
934e98e3e1Schristos {
944e98e3e1Schristos   lf_printf (file, "/* prime the search */\n");
954e98e3e1Schristos   lf_printf (file, "idecode_table_entry *table = ");
964e98e3e1Schristos   lf_print_table_name (file, entry);
974e98e3e1Schristos   lf_printf (file, ";\n");
984e98e3e1Schristos   lf_printf (file, "int opcode = EXTRACTED%d (instruction, %d, %d);\n",
994e98e3e1Schristos 	     options.insn_bit_size,
1004e98e3e1Schristos 	     i2target (options.hi_bit_nr, entry->opcode->first),
1014e98e3e1Schristos 	     i2target (options.hi_bit_nr, entry->opcode->last));
1024e98e3e1Schristos   lf_printf (file, "idecode_table_entry *table_entry = table + opcode;\n");
1034e98e3e1Schristos 
1044e98e3e1Schristos   lf_printf (file, "\n");
1054e98e3e1Schristos   lf_printf (file, "/* iterate until a leaf */\n");
1064e98e3e1Schristos   lf_printf (file, "while (1) {\n");
1074e98e3e1Schristos   lf_printf (file, "  signed shift = table_entry->shift;\n");
1084e98e3e1Schristos   lf_printf (file, "if (shift == function_entry) break;\n");
1094e98e3e1Schristos   lf_printf (file, "  if (shift >= 0) {\n");
1104e98e3e1Schristos   lf_printf (file, "    table = ((idecode_table_entry*)\n");
1114e98e3e1Schristos   lf_printf (file, "             table_entry->function_or_table);\n");
1124e98e3e1Schristos   lf_printf (file, "    opcode = ((instruction & table_entry->mask)\n");
1134e98e3e1Schristos   lf_printf (file, "              >> shift);\n");
1144e98e3e1Schristos   lf_printf (file, "    table_entry = table + opcode;\n");
1154e98e3e1Schristos   lf_printf (file, "  }\n");
1164e98e3e1Schristos   lf_printf (file, "  else {\n");
1174e98e3e1Schristos   lf_printf (file, "    /* must be a boolean */\n");
1184e98e3e1Schristos   lf_printf (file, "    ASSERT(table_entry->shift == boolean_entry);\n");
1194e98e3e1Schristos   lf_printf (file, "    opcode = ((instruction & table_entry->mask)\n");
1204e98e3e1Schristos   lf_printf (file, "              != table_entry->value);\n");
1214e98e3e1Schristos   lf_printf (file, "    table = ((idecode_table_entry*)\n");
1224e98e3e1Schristos   lf_printf (file, "             table_entry->function_or_table);\n");
1234e98e3e1Schristos   lf_printf (file, "    table_entry = table + opcode;\n");
1244e98e3e1Schristos   lf_printf (file, "  }\n");
1254e98e3e1Schristos   lf_printf (file, "}\n");
1264e98e3e1Schristos 
1274e98e3e1Schristos   lf_printf (file, "\n");
1284e98e3e1Schristos   lf_printf (file, "/* call the leaf code */\n");
1294e98e3e1Schristos   if (options.gen.code == generate_jumps)
1304e98e3e1Schristos     {
1314e98e3e1Schristos       lf_printf (file, "goto *table_entry->function_or_table;\n");
1324e98e3e1Schristos     }
1334e98e3e1Schristos   else
1344e98e3e1Schristos     {
1354e98e3e1Schristos       lf_printf (file, "%s ", result);
1364e98e3e1Schristos       if (options.gen.icache)
1374e98e3e1Schristos 	{
1384e98e3e1Schristos 	  lf_printf (file,
1394e98e3e1Schristos 		     "(((idecode_icache*)table_entry->function_or_table)\n");
1404e98e3e1Schristos 	  lf_printf (file, "  (");
1414e98e3e1Schristos 	  print_icache_function_actual (file, 1);
1424e98e3e1Schristos 	  lf_printf (file, "));\n");
1434e98e3e1Schristos 	}
1444e98e3e1Schristos       else
1454e98e3e1Schristos 	{
1464e98e3e1Schristos 	  lf_printf (file,
1474e98e3e1Schristos 		     "((idecode_semantic*)table_entry->function_or_table)\n");
1484e98e3e1Schristos 	  lf_printf (file, "  (");
1494e98e3e1Schristos 	  print_semantic_function_actual (file, 1);
1504e98e3e1Schristos 	  lf_printf (file, ");\n");
1514e98e3e1Schristos 	}
1524e98e3e1Schristos     }
1534e98e3e1Schristos }
1544e98e3e1Schristos 
1554e98e3e1Schristos 
1564e98e3e1Schristos static void
1574b169a6bSchristos print_idecode_table_start (lf *file,
1584b169a6bSchristos 			   const gen_entry *table, int depth, void *data)
1594e98e3e1Schristos {
1604e98e3e1Schristos   ASSERT (depth == 0);
1614e98e3e1Schristos   /* start of the table */
1624e98e3e1Schristos   if (table->opcode_rule->gen == array_gen)
1634e98e3e1Schristos     {
1644e98e3e1Schristos       lf_printf (file, "\n");
1654e98e3e1Schristos       lf_printf (file, "static idecode_table_entry ");
1664e98e3e1Schristos       lf_print_table_name (file, table);
1674e98e3e1Schristos       lf_printf (file, "[] = {\n");
1684e98e3e1Schristos     }
1694e98e3e1Schristos }
1704e98e3e1Schristos 
1714e98e3e1Schristos static void
1724b169a6bSchristos print_idecode_table_leaf (lf *file,
1734b169a6bSchristos 			  const gen_entry *entry, int depth, void *data)
1744e98e3e1Schristos {
1754b169a6bSchristos   const gen_entry *master_entry;
1764e98e3e1Schristos   ASSERT (entry->parent != NULL);
1774e98e3e1Schristos   ASSERT (depth == 0);
1784e98e3e1Schristos   if (entry->combined_parent == NULL)
1794e98e3e1Schristos     master_entry = entry;
1804e98e3e1Schristos   else
1814e98e3e1Schristos     master_entry = entry->combined_parent;
1824e98e3e1Schristos 
1834e98e3e1Schristos   /* add an entry to the table */
1844e98e3e1Schristos   if (entry->parent->opcode_rule->gen == array_gen)
1854e98e3e1Schristos     {
1864e98e3e1Schristos       lf_printf (file, "  /*%d*/ { ", entry->opcode_nr);
1874e98e3e1Schristos       if (entry->opcode == NULL)
1884e98e3e1Schristos 	{
1894e98e3e1Schristos 	  ASSERT (entry->nr_insns == 1);
1904e98e3e1Schristos 	  /* table leaf entry */
1914e98e3e1Schristos 	  lf_printf (file, "function_entry, 0, 0, ");
1924e98e3e1Schristos 	  if (options.gen.code == generate_jumps)
1934e98e3e1Schristos 	    {
1944e98e3e1Schristos 	      lf_printf (file, "&&");
1954e98e3e1Schristos 	    }
1964e98e3e1Schristos 	  print_function_name (file,
1974e98e3e1Schristos 			       entry->insns->insn->name,
1984e98e3e1Schristos 			       entry->insns->insn->format_name,
1994e98e3e1Schristos 			       NULL,
2004e98e3e1Schristos 			       master_entry->expanded_bits,
2014e98e3e1Schristos 			       (options.gen.icache
2024e98e3e1Schristos 				? function_name_prefix_icache
2034e98e3e1Schristos 				: function_name_prefix_semantics));
2044e98e3e1Schristos 	}
2054e98e3e1Schristos       else if (entry->opcode_rule->gen == switch_gen
2064e98e3e1Schristos 	       || entry->opcode_rule->gen == goto_switch_gen
2074e98e3e1Schristos 	       || entry->opcode_rule->gen == padded_switch_gen)
2084e98e3e1Schristos 	{
2094e98e3e1Schristos 	  /* table calling switch statement */
2104e98e3e1Schristos 	  lf_printf (file, "function_entry, 0, 0, ");
2114e98e3e1Schristos 	  if (options.gen.code == generate_jumps)
2124e98e3e1Schristos 	    {
2134e98e3e1Schristos 	      lf_printf (file, "&&");
2144e98e3e1Schristos 	    }
2154e98e3e1Schristos 	  lf_print_table_name (file, entry);
2164e98e3e1Schristos 	}
2174e98e3e1Schristos       else if (entry->opcode->is_boolean)
2184e98e3e1Schristos 	{
2194e98e3e1Schristos 	  /* table `calling' boolean table */
2204e98e3e1Schristos 	  lf_printf (file, "boolean_entry, ");
2214e98e3e1Schristos 	  lf_printf (file, "MASK32(%d, %d), ",
2224e98e3e1Schristos 		     i2target (options.hi_bit_nr, entry->opcode->first),
2234e98e3e1Schristos 		     i2target (options.hi_bit_nr, entry->opcode->last));
2244e98e3e1Schristos 	  lf_printf (file, "INSERTED32(%d, %d, %d), ",
2254e98e3e1Schristos 		     entry->opcode->boolean_constant,
2264e98e3e1Schristos 		     i2target (options.hi_bit_nr, entry->opcode->first),
2274e98e3e1Schristos 		     i2target (options.hi_bit_nr, entry->opcode->last));
2284e98e3e1Schristos 	  lf_print_table_name (file, entry);
2294e98e3e1Schristos 	}
2304e98e3e1Schristos       else
2314e98e3e1Schristos 	{
2324e98e3e1Schristos 	  /* table `calling' another table */
2334e98e3e1Schristos 	  lf_printf (file, "%d, ",
2344e98e3e1Schristos 		     options.insn_bit_size - entry->opcode->last - 1);
2354e98e3e1Schristos 	  lf_printf (file, "MASK%d(%d,%d), ", options.insn_bit_size,
2364e98e3e1Schristos 		     i2target (options.hi_bit_nr, entry->opcode->first),
2374e98e3e1Schristos 		     i2target (options.hi_bit_nr, entry->opcode->last));
2384e98e3e1Schristos 	  lf_printf (file, "0, ");
2394e98e3e1Schristos 	  lf_print_table_name (file, entry);
2404e98e3e1Schristos 	}
2414e98e3e1Schristos       lf_printf (file, " },\n");
2424e98e3e1Schristos     }
2434e98e3e1Schristos }
2444e98e3e1Schristos 
2454e98e3e1Schristos static void
2464b169a6bSchristos print_idecode_table_end (lf *file,
2474b169a6bSchristos 			 const gen_entry *table, int depth, void *data)
2484e98e3e1Schristos {
2494e98e3e1Schristos   ASSERT (depth == 0);
2504e98e3e1Schristos   if (table->opcode_rule->gen == array_gen)
2514e98e3e1Schristos     {
2524e98e3e1Schristos       lf_printf (file, "};\n");
2534e98e3e1Schristos     }
2544e98e3e1Schristos }
2554e98e3e1Schristos 
2564e98e3e1Schristos /****************************************************************/
2574e98e3e1Schristos 
2584e98e3e1Schristos 
2594e98e3e1Schristos static void
2604b169a6bSchristos print_goto_switch_name (lf *file, const gen_entry *entry)
2614e98e3e1Schristos {
2624e98e3e1Schristos   lf_printf (file, "case_");
2634e98e3e1Schristos   if (entry->opcode == NULL)
2644e98e3e1Schristos     {
2654e98e3e1Schristos       print_function_name (file,
2664e98e3e1Schristos 			   entry->insns->insn->name,
2674e98e3e1Schristos 			   entry->insns->insn->format_name,
2684e98e3e1Schristos 			   NULL,
2694e98e3e1Schristos 			   entry->expanded_bits,
2704e98e3e1Schristos 			   (options.gen.icache
2714e98e3e1Schristos 			    ? function_name_prefix_icache
2724e98e3e1Schristos 			    : function_name_prefix_semantics));
2734e98e3e1Schristos     }
2744e98e3e1Schristos   else
2754e98e3e1Schristos     {
2764e98e3e1Schristos       lf_print_table_name (file, entry);
2774e98e3e1Schristos     }
2784e98e3e1Schristos }
2794e98e3e1Schristos 
2804e98e3e1Schristos static void
2814e98e3e1Schristos print_goto_switch_table_leaf (lf *file,
2824b169a6bSchristos 			      const gen_entry *entry, int depth, void *data)
2834e98e3e1Schristos {
2844e98e3e1Schristos   ASSERT (entry->parent != NULL);
2854e98e3e1Schristos   ASSERT (depth == 0);
2864e98e3e1Schristos   ASSERT (entry->parent->opcode_rule->gen == goto_switch_gen);
2874e98e3e1Schristos   ASSERT (entry->parent->opcode);
2884e98e3e1Schristos 
2894e98e3e1Schristos   lf_printf (file, "/* %d */ &&", entry->opcode_nr);
2904e98e3e1Schristos   if (entry->combined_parent != NULL)
2914e98e3e1Schristos     print_goto_switch_name (file, entry->combined_parent);
2924e98e3e1Schristos   else
2934e98e3e1Schristos     print_goto_switch_name (file, entry);
2944e98e3e1Schristos   lf_printf (file, ",\n");
2954e98e3e1Schristos }
2964e98e3e1Schristos 
2974e98e3e1Schristos static void
2984b169a6bSchristos print_goto_switch_break (lf *file, const gen_entry *entry)
2994e98e3e1Schristos {
3004e98e3e1Schristos   lf_printf (file, "goto break_");
3014e98e3e1Schristos   lf_print_table_name (file, entry->parent);
3024e98e3e1Schristos   lf_printf (file, ";\n");
3034e98e3e1Schristos }
3044e98e3e1Schristos 
3054e98e3e1Schristos 
3064e98e3e1Schristos static void
3074b169a6bSchristos print_goto_switch_table (lf *file, const gen_entry *table)
3084e98e3e1Schristos {
3094e98e3e1Schristos   lf_printf (file, "const static void *");
3104e98e3e1Schristos   lf_print_table_name (file, table);
3114e98e3e1Schristos   lf_printf (file, "[] = {\n");
3124e98e3e1Schristos   lf_indent (file, +2);
3134e98e3e1Schristos   gen_entry_traverse_tree (file, table, 0, NULL /*start */ ,
3144e98e3e1Schristos 			   print_goto_switch_table_leaf, NULL /*end */ ,
3154e98e3e1Schristos 			   NULL /*data */ );
3164e98e3e1Schristos   lf_indent (file, -2);
3174e98e3e1Schristos   lf_printf (file, "};\n");
3184e98e3e1Schristos }
3194e98e3e1Schristos 
3204e98e3e1Schristos 
3214b169a6bSchristos void print_idecode_switch
3224b169a6bSchristos   (lf *file, const gen_entry *table, const char *result);
3234e98e3e1Schristos 
3244e98e3e1Schristos static void
3254b169a6bSchristos print_idecode_switch_start (lf *file,
3264b169a6bSchristos 			    const gen_entry *table, int depth, void *data)
3274e98e3e1Schristos {
3284e98e3e1Schristos   /* const char *result = data; */
3294e98e3e1Schristos   ASSERT (depth == 0);
3304e98e3e1Schristos   ASSERT (table->opcode_rule->gen == switch_gen
3314e98e3e1Schristos 	  || table->opcode_rule->gen == goto_switch_gen
3324e98e3e1Schristos 	  || table->opcode_rule->gen == padded_switch_gen);
3334e98e3e1Schristos 
3344e98e3e1Schristos   if (table->opcode->is_boolean
3354e98e3e1Schristos       || table->opcode_rule->gen == switch_gen
3364e98e3e1Schristos       || table->opcode_rule->gen == padded_switch_gen)
3374e98e3e1Schristos     {
3384e98e3e1Schristos       lf_printf (file, "switch (EXTRACTED%d (instruction_%d, %d, %d))\n",
3394e98e3e1Schristos 		 options.insn_bit_size,
3404e98e3e1Schristos 		 table->opcode_rule->word_nr,
3414e98e3e1Schristos 		 i2target (options.hi_bit_nr, table->opcode->first),
3424e98e3e1Schristos 		 i2target (options.hi_bit_nr, table->opcode->last));
3434e98e3e1Schristos       lf_indent (file, +2);
3444e98e3e1Schristos       lf_printf (file, "{\n");
3454e98e3e1Schristos     }
3464e98e3e1Schristos   else if (table->opcode_rule->gen == goto_switch_gen)
3474e98e3e1Schristos     {
3484e98e3e1Schristos       if (table->parent != NULL
3494e98e3e1Schristos 	  && (table->parent->opcode_rule->gen == switch_gen
3504e98e3e1Schristos 	      || table->parent->opcode_rule->gen == goto_switch_gen
3514e98e3e1Schristos 	      || table->parent->opcode_rule->gen == padded_switch_gen))
3524e98e3e1Schristos 	{
3534e98e3e1Schristos 	  lf_printf (file, "{\n");
3544e98e3e1Schristos 	  lf_indent (file, +2);
3554e98e3e1Schristos 	}
3564e98e3e1Schristos       print_goto_switch_table (file, table);
3574e98e3e1Schristos       lf_printf (file, "ASSERT (EXTRACTED%d (instruction_%d, %d, %d)\n",
3584e98e3e1Schristos 		 options.insn_bit_size,
3594e98e3e1Schristos 		 table->opcode->word_nr,
3604e98e3e1Schristos 		 i2target (options.hi_bit_nr, table->opcode->first),
3614e98e3e1Schristos 		 i2target (options.hi_bit_nr, table->opcode->last));
3624e98e3e1Schristos       lf_printf (file, "        < (sizeof (");
3634e98e3e1Schristos       lf_print_table_name (file, table);
3644e98e3e1Schristos       lf_printf (file, ") / sizeof(void*)));\n");
3654e98e3e1Schristos       lf_printf (file, "goto *");
3664e98e3e1Schristos       lf_print_table_name (file, table);
3674e98e3e1Schristos       lf_printf (file, "[EXTRACTED%d (instruction_%d, %d, %d)];\n",
3684e98e3e1Schristos 		 options.insn_bit_size,
3694e98e3e1Schristos 		 table->opcode->word_nr,
3704e98e3e1Schristos 		 i2target (options.hi_bit_nr, table->opcode->first),
3714e98e3e1Schristos 		 i2target (options.hi_bit_nr, table->opcode->last));
3724e98e3e1Schristos     }
3734e98e3e1Schristos   else
3744e98e3e1Schristos     {
3754e98e3e1Schristos       ASSERT ("bad switch" == NULL);
3764e98e3e1Schristos     }
3774e98e3e1Schristos }
3784e98e3e1Schristos 
3794e98e3e1Schristos 
3804e98e3e1Schristos static void
3814b169a6bSchristos print_idecode_switch_leaf (lf *file,
3824b169a6bSchristos 			   const gen_entry *entry, int depth, void *data)
3834e98e3e1Schristos {
3844e98e3e1Schristos   const char *result = data;
3854e98e3e1Schristos   ASSERT (entry->parent != NULL);
3864e98e3e1Schristos   ASSERT (depth == 0);
3874e98e3e1Schristos   ASSERT (entry->parent->opcode_rule->gen == switch_gen
3884e98e3e1Schristos 	  || entry->parent->opcode_rule->gen == goto_switch_gen
3894e98e3e1Schristos 	  || entry->parent->opcode_rule->gen == padded_switch_gen);
3904e98e3e1Schristos   ASSERT (entry->parent->opcode);
3914e98e3e1Schristos 
3924e98e3e1Schristos   /* skip over any instructions combined into another entry */
3934e98e3e1Schristos   if (entry->combined_parent != NULL)
3944e98e3e1Schristos     return;
3954e98e3e1Schristos 
3964e98e3e1Schristos   if (entry->parent->opcode->is_boolean && entry->opcode_nr == 0)
3974e98e3e1Schristos     {
3984e98e3e1Schristos       /* case: boolean false target */
3994e98e3e1Schristos       lf_printf (file, "case %d:\n", entry->parent->opcode->boolean_constant);
4004e98e3e1Schristos     }
4014e98e3e1Schristos   else if (entry->parent->opcode->is_boolean && entry->opcode_nr != 0)
4024e98e3e1Schristos     {
4034e98e3e1Schristos       /* case: boolean true case */
4044e98e3e1Schristos       lf_printf (file, "default:\n");
4054e98e3e1Schristos     }
4064e98e3e1Schristos   else if (entry->parent->opcode_rule->gen == switch_gen
4074e98e3e1Schristos 	   || entry->parent->opcode_rule->gen == padded_switch_gen)
4084e98e3e1Schristos     {
4094e98e3e1Schristos       /* case: <opcode-nr> - switch */
4104b169a6bSchristos       const gen_entry *cob;
4114e98e3e1Schristos       for (cob = entry; cob != NULL; cob = cob->combined_next)
4124e98e3e1Schristos 	lf_printf (file, "case %d:\n", cob->opcode_nr);
4134e98e3e1Schristos     }
4144e98e3e1Schristos   else if (entry->parent->opcode_rule->gen == goto_switch_gen)
4154e98e3e1Schristos     {
4164e98e3e1Schristos       /* case: <opcode-nr> - goto-switch */
4174e98e3e1Schristos       print_goto_switch_name (file, entry);
4184e98e3e1Schristos       lf_printf (file, ":\n");
4194e98e3e1Schristos     }
4204e98e3e1Schristos   else
4214e98e3e1Schristos     {
4224e98e3e1Schristos       ERROR ("bad switch");
4234e98e3e1Schristos     }
4244e98e3e1Schristos   lf_printf (file, "  {\n");
4254e98e3e1Schristos   lf_indent (file, +4);
4264e98e3e1Schristos   {
4274e98e3e1Schristos     if (entry->opcode == NULL)
4284e98e3e1Schristos       {
4294e98e3e1Schristos 	/* switch calling leaf */
4304e98e3e1Schristos 	ASSERT (entry->nr_insns == 1);
4314e98e3e1Schristos 	print_idecode_ifetch (file, entry->nr_prefetched_words,
4324e98e3e1Schristos 			      entry->insns->semantic->nr_prefetched_words);
4334e98e3e1Schristos 	switch (options.gen.code)
4344e98e3e1Schristos 	  {
4354e98e3e1Schristos 	  case generate_jumps:
4364e98e3e1Schristos 	    lf_printf (file, "goto ");
4374e98e3e1Schristos 	    break;
4384e98e3e1Schristos 	  case generate_calls:
4394e98e3e1Schristos 	    lf_printf (file, "%s", result);
4404e98e3e1Schristos 	    break;
4414e98e3e1Schristos 	  }
4424e98e3e1Schristos 	print_function_name (file,
4434e98e3e1Schristos 			     entry->insns->insn->name,
4444e98e3e1Schristos 			     entry->insns->insn->format_name,
4454e98e3e1Schristos 			     NULL,
4464e98e3e1Schristos 			     entry->expanded_bits,
4474e98e3e1Schristos 			     (options.gen.icache
4484e98e3e1Schristos 			      ? function_name_prefix_icache
4494e98e3e1Schristos 			      : function_name_prefix_semantics));
4504e98e3e1Schristos 	if (options.gen.code == generate_calls)
4514e98e3e1Schristos 	  {
4524e98e3e1Schristos 	    lf_printf (file, " (");
4534e98e3e1Schristos 	    print_semantic_function_actual (file,
4544e98e3e1Schristos 					    entry->insns->semantic->
4554e98e3e1Schristos 					    nr_prefetched_words);
4564e98e3e1Schristos 	    lf_printf (file, ")");
4574e98e3e1Schristos 	  }
4584e98e3e1Schristos 	lf_printf (file, ";\n");
4594e98e3e1Schristos       }
4604e98e3e1Schristos     else if (entry->opcode_rule->gen == switch_gen
4614e98e3e1Schristos 	     || entry->opcode_rule->gen == goto_switch_gen
4624e98e3e1Schristos 	     || entry->opcode_rule->gen == padded_switch_gen)
4634e98e3e1Schristos       {
4644e98e3e1Schristos 	/* switch calling switch */
4654e98e3e1Schristos 	lf_printf (file, "{\n");
4664e98e3e1Schristos 	lf_indent (file, +2);
4674e98e3e1Schristos 	print_idecode_ifetch (file, entry->parent->nr_prefetched_words,
4684e98e3e1Schristos 			      entry->nr_prefetched_words);
4694e98e3e1Schristos 	print_idecode_switch (file, entry, result);
4704e98e3e1Schristos 	lf_indent (file, -2);
4714e98e3e1Schristos 	lf_printf (file, "}\n");
4724e98e3e1Schristos       }
4734e98e3e1Schristos     else
4744e98e3e1Schristos       {
4754e98e3e1Schristos 	/* switch looking up a table */
4764e98e3e1Schristos 	lf_printf (file, "{\n");
4774e98e3e1Schristos 	lf_indent (file, +2);
4784e98e3e1Schristos 	print_idecode_ifetch (file, entry->parent->nr_prefetched_words,
4794e98e3e1Schristos 			      entry->nr_prefetched_words);
4804e98e3e1Schristos 	print_idecode_table (file, entry, result);
4814e98e3e1Schristos 	lf_indent (file, -2);
4824e98e3e1Schristos 	lf_printf (file, "}\n");
4834e98e3e1Schristos       }
4844e98e3e1Schristos     if (entry->parent->opcode->is_boolean
4854e98e3e1Schristos 	|| entry->parent->opcode_rule->gen == switch_gen
4864e98e3e1Schristos 	|| entry->parent->opcode_rule->gen == padded_switch_gen)
4874e98e3e1Schristos       {
4884e98e3e1Schristos 	lf_printf (file, "break;\n");
4894e98e3e1Schristos       }
4904e98e3e1Schristos     else if (entry->parent->opcode_rule->gen == goto_switch_gen)
4914e98e3e1Schristos       {
4924e98e3e1Schristos 	print_goto_switch_break (file, entry);
4934e98e3e1Schristos       }
4944e98e3e1Schristos     else
4954e98e3e1Schristos       {
4964e98e3e1Schristos 	ERROR ("bad switch");
4974e98e3e1Schristos       }
4984e98e3e1Schristos   }
4994e98e3e1Schristos   lf_indent (file, -4);
5004e98e3e1Schristos   lf_printf (file, "  }\n");
5014e98e3e1Schristos }
5024e98e3e1Schristos 
5034e98e3e1Schristos 
5044e98e3e1Schristos static void
5054e98e3e1Schristos print_idecode_switch_illegal (lf *file, const char *result)
5064e98e3e1Schristos {
5074e98e3e1Schristos   lf_indent (file, +2);
5084e98e3e1Schristos   print_idecode_invalid (file, result, invalid_illegal);
5094e98e3e1Schristos   lf_printf (file, "break;\n");
5104e98e3e1Schristos   lf_indent (file, -2);
5114e98e3e1Schristos }
5124e98e3e1Schristos 
5134e98e3e1Schristos static void
5144b169a6bSchristos print_idecode_switch_end (lf *file,
5154b169a6bSchristos 			  const gen_entry *table, int depth, void *data)
5164e98e3e1Schristos {
5174e98e3e1Schristos   const char *result = data;
5184e98e3e1Schristos   ASSERT (depth == 0);
5194e98e3e1Schristos   ASSERT (table->opcode_rule->gen == switch_gen
5204e98e3e1Schristos 	  || table->opcode_rule->gen == goto_switch_gen
5214e98e3e1Schristos 	  || table->opcode_rule->gen == padded_switch_gen);
5224e98e3e1Schristos   ASSERT (table->opcode);
5234e98e3e1Schristos 
5244e98e3e1Schristos   if (table->opcode->is_boolean)
5254e98e3e1Schristos     {
5264e98e3e1Schristos       lf_printf (file, "}\n");
5274e98e3e1Schristos       lf_indent (file, -2);
5284e98e3e1Schristos     }
5294e98e3e1Schristos   else if (table->opcode_rule->gen == switch_gen
5304e98e3e1Schristos 	   || table->opcode_rule->gen == padded_switch_gen)
5314e98e3e1Schristos     {
5324e98e3e1Schristos       lf_printf (file, "default:\n");
5334e98e3e1Schristos       lf_indent (file, +2);
5344e98e3e1Schristos       if (table->nr_entries == table->opcode->nr_opcodes)
5354e98e3e1Schristos 	{
5364e98e3e1Schristos 	  print_sim_engine_abort (file,
5374e98e3e1Schristos 				  "Internal error - bad switch generated");
5384e98e3e1Schristos 	  lf_printf (file, "%sNULL_CIA;\n", result);
5394e98e3e1Schristos 	  lf_printf (file, "break;\n");
5404e98e3e1Schristos 	}
5414e98e3e1Schristos       else
5424e98e3e1Schristos 	{
5434e98e3e1Schristos 	  print_idecode_switch_illegal (file, result);
5444e98e3e1Schristos 	}
5454e98e3e1Schristos       lf_indent (file, -2);
5464e98e3e1Schristos       lf_printf (file, "}\n");
5474e98e3e1Schristos       lf_indent (file, -2);
5484e98e3e1Schristos     }
5494e98e3e1Schristos   else if (table->opcode_rule->gen == goto_switch_gen)
5504e98e3e1Schristos     {
5514e98e3e1Schristos       lf_printf (file, "illegal_");
5524e98e3e1Schristos       lf_print_table_name (file, table);
5534e98e3e1Schristos       lf_printf (file, ":\n");
5544e98e3e1Schristos       print_idecode_invalid (file, result, invalid_illegal);
5554e98e3e1Schristos       lf_printf (file, "break_");
5564e98e3e1Schristos       lf_print_table_name (file, table);
5574e98e3e1Schristos       lf_printf (file, ":;\n");
5584e98e3e1Schristos       if (table->parent != NULL
5594e98e3e1Schristos 	  && (table->parent->opcode_rule->gen == switch_gen
5604e98e3e1Schristos 	      || table->parent->opcode_rule->gen == goto_switch_gen
5614e98e3e1Schristos 	      || table->parent->opcode_rule->gen == padded_switch_gen))
5624e98e3e1Schristos 	{
5634e98e3e1Schristos 	  lf_indent (file, -2);
5644e98e3e1Schristos 	  lf_printf (file, "}\n");
5654e98e3e1Schristos 	}
5664e98e3e1Schristos     }
5674e98e3e1Schristos   else
5684e98e3e1Schristos     {
5694e98e3e1Schristos       ERROR ("bad switch");
5704e98e3e1Schristos     }
5714e98e3e1Schristos }
5724e98e3e1Schristos 
5734e98e3e1Schristos 
5744e98e3e1Schristos void
5754b169a6bSchristos print_idecode_switch (lf *file, const gen_entry *table, const char *result)
5764e98e3e1Schristos {
5774e98e3e1Schristos   gen_entry_traverse_tree (file, table,
5784e98e3e1Schristos 			   0,
5794e98e3e1Schristos 			   print_idecode_switch_start,
5804e98e3e1Schristos 			   print_idecode_switch_leaf,
5814e98e3e1Schristos 			   print_idecode_switch_end, (void *) result);
5824e98e3e1Schristos }
5834e98e3e1Schristos 
5844e98e3e1Schristos 
5854e98e3e1Schristos static void
5864e98e3e1Schristos print_idecode_switch_function_header (lf *file,
5874b169a6bSchristos 				      const gen_entry *table,
5884e98e3e1Schristos 				      int is_function_definition,
5894e98e3e1Schristos 				      int nr_prefetched_words)
5904e98e3e1Schristos {
5914e98e3e1Schristos   lf_printf (file, "\n");
5924e98e3e1Schristos   if (options.gen.code == generate_calls)
5934e98e3e1Schristos     {
5944e98e3e1Schristos       lf_printf (file, "static ");
5954e98e3e1Schristos       if (options.gen.icache)
5964e98e3e1Schristos 	{
5974e98e3e1Schristos 	  lf_printf (file, "idecode_semantic *");
5984e98e3e1Schristos 	}
5994e98e3e1Schristos       else
6004e98e3e1Schristos 	{
6014e98e3e1Schristos 	  lf_printf (file, "unsigned_word");
6024e98e3e1Schristos 	}
6034e98e3e1Schristos       if (is_function_definition)
6044e98e3e1Schristos 	{
6054e98e3e1Schristos 	  lf_printf (file, "\n");
6064e98e3e1Schristos 	}
6074e98e3e1Schristos       else
6084e98e3e1Schristos 	{
6094e98e3e1Schristos 	  lf_printf (file, " ");
6104e98e3e1Schristos 	}
6114e98e3e1Schristos       lf_print_table_name (file, table);
6124e98e3e1Schristos       lf_printf (file, "\n(");
6134e98e3e1Schristos       print_icache_function_formal (file, nr_prefetched_words);
6144e98e3e1Schristos       lf_printf (file, ")");
6154e98e3e1Schristos       if (!is_function_definition)
6164e98e3e1Schristos 	{
6174e98e3e1Schristos 	  lf_printf (file, ";");
6184e98e3e1Schristos 	}
6194e98e3e1Schristos       lf_printf (file, "\n");
6204e98e3e1Schristos     }
6214e98e3e1Schristos   if (options.gen.code == generate_jumps && is_function_definition)
6224e98e3e1Schristos     {
6234e98e3e1Schristos       lf_indent (file, -1);
6244e98e3e1Schristos       lf_print_table_name (file, table);
6254e98e3e1Schristos       lf_printf (file, ":\n");
6264e98e3e1Schristos       lf_indent (file, +1);
6274e98e3e1Schristos     }
6284e98e3e1Schristos }
6294e98e3e1Schristos 
6304e98e3e1Schristos 
6314e98e3e1Schristos static void
6324b169a6bSchristos idecode_declare_if_switch (lf *file,
6334b169a6bSchristos 			   const gen_entry *table, int depth, void *data)
6344e98e3e1Schristos {
6354e98e3e1Schristos   if ((table->opcode_rule->gen == switch_gen || table->opcode_rule->gen == goto_switch_gen || table->opcode_rule->gen == padded_switch_gen) &&table->parent != NULL	/* don't declare the top one yet */
6364e98e3e1Schristos       && table->parent->opcode_rule->gen == array_gen)
6374e98e3e1Schristos     {
6384e98e3e1Schristos       print_idecode_switch_function_header (file,
6394e98e3e1Schristos 					    table,
6404e98e3e1Schristos 					    0 /*isnt function definition */ ,
6414e98e3e1Schristos 					    0);
6424e98e3e1Schristos     }
6434e98e3e1Schristos }
6444e98e3e1Schristos 
6454e98e3e1Schristos 
6464e98e3e1Schristos static void
6474b169a6bSchristos idecode_expand_if_switch (lf *file,
6484b169a6bSchristos 			  const gen_entry *table, int depth, void *data)
6494e98e3e1Schristos {
6504e98e3e1Schristos   if ((table->opcode_rule->gen == switch_gen || table->opcode_rule->gen == goto_switch_gen || table->opcode_rule->gen == padded_switch_gen) &&table->parent != NULL	/* don't expand the top one yet */
6514e98e3e1Schristos       && table->parent->opcode_rule->gen == array_gen)
6524e98e3e1Schristos     {
6534e98e3e1Schristos       print_idecode_switch_function_header (file,
6544e98e3e1Schristos 					    table,
6554e98e3e1Schristos 					    1 /*is function definition */ ,
6564e98e3e1Schristos 					    0);
6574e98e3e1Schristos       if (options.gen.code == generate_calls)
6584e98e3e1Schristos 	{
6594e98e3e1Schristos 	  lf_printf (file, "{\n");
6604e98e3e1Schristos 	  lf_indent (file, +2);
6614e98e3e1Schristos 	}
6624e98e3e1Schristos       print_idecode_switch (file, table, "return");
6634e98e3e1Schristos       if (options.gen.code == generate_calls)
6644e98e3e1Schristos 	{
6654e98e3e1Schristos 	  lf_indent (file, -2);
6664e98e3e1Schristos 	  lf_printf (file, "}\n");
6674e98e3e1Schristos 	}
6684e98e3e1Schristos     }
6694e98e3e1Schristos }
6704e98e3e1Schristos 
6714e98e3e1Schristos 
6724e98e3e1Schristos /****************************************************************/
6734e98e3e1Schristos 
6744e98e3e1Schristos 
6754e98e3e1Schristos void
6764b169a6bSchristos print_idecode_lookups (lf *file,
6774b169a6bSchristos 		       const gen_entry *table,
6784b169a6bSchristos 		       cache_entry *cache_rules)
6794e98e3e1Schristos {
6804e98e3e1Schristos   int depth;
6814e98e3e1Schristos 
6824e98e3e1Schristos   /* output switch function declarations where needed by tables */
6834e98e3e1Schristos   gen_entry_traverse_tree (file, table, 1, idecode_declare_if_switch,	/* START */
6844e98e3e1Schristos 			   NULL, NULL, NULL);
6854e98e3e1Schristos 
6864e98e3e1Schristos   /* output tables where needed */
6874e98e3e1Schristos   for (depth = gen_entry_depth (table); depth > 0; depth--)
6884e98e3e1Schristos     {
6894e98e3e1Schristos       gen_entry_traverse_tree (file, table,
6904e98e3e1Schristos 			       1 - depth,
6914e98e3e1Schristos 			       print_idecode_table_start,
6924e98e3e1Schristos 			       print_idecode_table_leaf,
6934e98e3e1Schristos 			       print_idecode_table_end, NULL);
6944e98e3e1Schristos     }
6954e98e3e1Schristos 
6964e98e3e1Schristos   /* output switch functions where needed */
6974e98e3e1Schristos   gen_entry_traverse_tree (file, table, 1, idecode_expand_if_switch,	/* START */
6984e98e3e1Schristos 			   NULL, NULL, NULL);
6994e98e3e1Schristos }
7004e98e3e1Schristos 
7014e98e3e1Schristos 
7024e98e3e1Schristos void
7034b169a6bSchristos print_idecode_body (lf *file, const gen_entry *table, const char *result)
7044e98e3e1Schristos {
7054e98e3e1Schristos   if (table->opcode_rule->gen == switch_gen
7064e98e3e1Schristos       || table->opcode_rule->gen == goto_switch_gen
7074e98e3e1Schristos       || table->opcode_rule->gen == padded_switch_gen)
7084e98e3e1Schristos     {
7094e98e3e1Schristos       print_idecode_switch (file, table, result);
7104e98e3e1Schristos     }
7114e98e3e1Schristos   else
7124e98e3e1Schristos     {
7134e98e3e1Schristos       print_idecode_table (file, table, result);
7144e98e3e1Schristos     }
7154e98e3e1Schristos }
7164e98e3e1Schristos 
7174e98e3e1Schristos 
7184e98e3e1Schristos /****************************************************************/
7194e98e3e1Schristos 
7204e98e3e1Schristos /* Output code to do any final checks on the decoded instruction.
7214e98e3e1Schristos    This includes things like verifying any on decoded fields have the
7224e98e3e1Schristos    correct value and checking that (for floating point) floating point
7234e98e3e1Schristos    hardware isn't disabled */
7244e98e3e1Schristos 
7254e98e3e1Schristos void
7264e98e3e1Schristos print_idecode_validate (lf *file,
7274b169a6bSchristos 			const insn_entry *instruction,
7284b169a6bSchristos 			const insn_opcodes *opcode_paths)
7294e98e3e1Schristos {
7304e98e3e1Schristos   /* Validate: unchecked instruction fields
7314e98e3e1Schristos 
7324e98e3e1Schristos      If any constant fields in the instruction were not checked by the
7334e98e3e1Schristos      idecode tables, output code to check that they have the correct
7344e98e3e1Schristos      value here */
7354e98e3e1Schristos   {
7364e98e3e1Schristos     int nr_checks = 0;
7374e98e3e1Schristos     int word_nr;
7384e98e3e1Schristos     lf_printf (file, "\n");
7394e98e3e1Schristos     lf_indent_suppress (file);
7404e98e3e1Schristos     lf_printf (file, "#if defined (WITH_RESERVED_BITS)\n");
7414e98e3e1Schristos     lf_printf (file, "/* validate: ");
7424e98e3e1Schristos     print_insn_words (file, instruction);
7434e98e3e1Schristos     lf_printf (file, " */\n");
7444e98e3e1Schristos     for (word_nr = 0; word_nr < instruction->nr_words; word_nr++)
7454e98e3e1Schristos       {
7464e98e3e1Schristos 	insn_uint check_mask = 0;
7474e98e3e1Schristos 	insn_uint check_val = 0;
7484e98e3e1Schristos 	insn_word_entry *word = instruction->word[word_nr];
7494e98e3e1Schristos 	int bit_nr;
7504e98e3e1Schristos 
7514e98e3e1Schristos 	/* form check_mask/check_val containing what needs to be checked
7524e98e3e1Schristos 	   in the instruction */
7534e98e3e1Schristos 	for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++)
7544e98e3e1Schristos 	  {
7554e98e3e1Schristos 	    insn_bit_entry *bit = word->bit[bit_nr];
7564e98e3e1Schristos 	    insn_field_entry *field = bit->field;
7574e98e3e1Schristos 
7584e98e3e1Schristos 	    /* Make space for the next bit */
7594e98e3e1Schristos 	    check_mask <<= 1;
7604e98e3e1Schristos 	    check_val <<= 1;
7614e98e3e1Schristos 
7624e98e3e1Schristos 	    /* Only need to validate constant (and reserved)
7634e98e3e1Schristos 	       bits. Skip any others */
7644e98e3e1Schristos 	    if (field->type != insn_field_int
765a2e2270fSchristos 		&& field->type != insn_field_reserved
766a2e2270fSchristos 		/* Consider a named field equal to a value to be just as
767a2e2270fSchristos 		   constant as an integer field.  */
768a2e2270fSchristos 		&& (field->type != insn_field_string
769a2e2270fSchristos 		    || field->conditions == NULL
770a2e2270fSchristos 		    || field->conditions->test != insn_field_cond_eq
771a2e2270fSchristos 		    || field->conditions->type != insn_field_cond_value))
7724e98e3e1Schristos 	      continue;
7734e98e3e1Schristos 
7744e98e3e1Schristos 	    /* Look through the list of opcode paths that lead to this
7754e98e3e1Schristos 	       instruction.  See if any have failed to check the
7764e98e3e1Schristos 	       relevant bit */
7774e98e3e1Schristos 	    if (opcode_paths != NULL)
7784e98e3e1Schristos 	      {
7794b169a6bSchristos 		const insn_opcodes *entry;
7804e98e3e1Schristos 		for (entry = opcode_paths; entry != NULL; entry = entry->next)
7814e98e3e1Schristos 		  {
7824e98e3e1Schristos 		    opcode_field *opcode;
7834e98e3e1Schristos 		    for (opcode = entry->opcode;
7844e98e3e1Schristos 			 opcode != NULL; opcode = opcode->parent)
7854e98e3e1Schristos 		      {
7864e98e3e1Schristos 			if (opcode->word_nr == word_nr
7874e98e3e1Schristos 			    && opcode->first <= bit_nr
7884e98e3e1Schristos 			    && opcode->last >= bit_nr)
7894e98e3e1Schristos 			  /* we've decoded on this bit */
7904e98e3e1Schristos 			  break;
7914e98e3e1Schristos 		      }
7924e98e3e1Schristos 		    if (opcode == NULL)
7934e98e3e1Schristos 		      /* the bit wasn't decoded on */
7944e98e3e1Schristos 		      break;
7954e98e3e1Schristos 		  }
7964e98e3e1Schristos 		if (entry == NULL)
7974e98e3e1Schristos 		  /* all the opcode paths decoded on BIT_NR, no need
7984e98e3e1Schristos 		     to check it */
7994e98e3e1Schristos 		  continue;
8004e98e3e1Schristos 	      }
8014e98e3e1Schristos 
8024e98e3e1Schristos 	    check_mask |= 1;
8034e98e3e1Schristos 	    check_val |= bit->value;
8044e98e3e1Schristos 	  }
8054e98e3e1Schristos 
8064e98e3e1Schristos 	/* if any bits not checked by opcode tables, output code to check them */
8074e98e3e1Schristos 	if (check_mask)
8084e98e3e1Schristos 	  {
8094e98e3e1Schristos 	    if (nr_checks == 0)
8104e98e3e1Schristos 	      {
8114e98e3e1Schristos 		lf_printf (file, "if (WITH_RESERVED_BITS)\n");
8124e98e3e1Schristos 		lf_printf (file, "  {\n");
8134e98e3e1Schristos 		lf_indent (file, +4);
8144e98e3e1Schristos 	      }
8154e98e3e1Schristos 	    nr_checks++;
8164e98e3e1Schristos 	    if (options.insn_bit_size > 32)
8174e98e3e1Schristos 	      {
8184e98e3e1Schristos 		lf_printf (file, "if ((instruction_%d\n", word_nr);
8194e98e3e1Schristos 		lf_printf (file, "     & UNSIGNED64 (0x%08lx%08lx))\n",
8204e98e3e1Schristos 			   (unsigned long) (check_mask >> 32),
8214e98e3e1Schristos 			   (unsigned long) (check_mask));
8224e98e3e1Schristos 		lf_printf (file, "    != UNSIGNED64 (0x%08lx%08lx))\n",
8234e98e3e1Schristos 			   (unsigned long) (check_val >> 32),
8244e98e3e1Schristos 			   (unsigned long) (check_val));
8254e98e3e1Schristos 	      }
8264e98e3e1Schristos 	    else
8274e98e3e1Schristos 	      {
8284e98e3e1Schristos 		lf_printf (file,
8294e98e3e1Schristos 			   "if ((instruction_%d & 0x%08lx) != 0x%08lx)\n",
8304e98e3e1Schristos 			   word_nr, (unsigned long) (check_mask),
8314e98e3e1Schristos 			   (unsigned long) (check_val));
8324e98e3e1Schristos 	      }
8334e98e3e1Schristos 	    lf_indent (file, +2);
8344e98e3e1Schristos 	    print_idecode_invalid (file, "return", invalid_illegal);
8354e98e3e1Schristos 	    lf_indent (file, -2);
8364e98e3e1Schristos 	  }
8374e98e3e1Schristos       }
8384e98e3e1Schristos     if (nr_checks > 0)
8394e98e3e1Schristos       {
8404e98e3e1Schristos 	lf_indent (file, -4);
8414e98e3e1Schristos 	lf_printf (file, "  }\n");
8424e98e3e1Schristos       }
8434e98e3e1Schristos     lf_indent_suppress (file);
8444e98e3e1Schristos     lf_printf (file, "#endif\n");
8454e98e3e1Schristos   }
8464e98e3e1Schristos 
8474e98e3e1Schristos   /* Validate: Floating Point hardware
8484e98e3e1Schristos 
8494e98e3e1Schristos      If the simulator is being built with out floating point hardware
8504e98e3e1Schristos      (different to it being disabled in the MSR) then floating point
8514e98e3e1Schristos      instructions are invalid */
8524e98e3e1Schristos   {
8534e98e3e1Schristos     if (filter_is_member (instruction->flags, "f"))
8544e98e3e1Schristos       {
8554e98e3e1Schristos 	lf_printf (file, "\n");
8564e98e3e1Schristos 	lf_indent_suppress (file);
8574e98e3e1Schristos 	lf_printf (file, "#if defined(CURRENT_FLOATING_POINT)\n");
8584e98e3e1Schristos 	lf_printf (file, "/* Validate: FP hardware exists */\n");
8594e98e3e1Schristos 	lf_printf (file,
8604e98e3e1Schristos 		   "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT) {\n");
8614e98e3e1Schristos 	lf_indent (file, +2);
8624e98e3e1Schristos 	print_idecode_invalid (file, "return", invalid_illegal);
8634e98e3e1Schristos 	lf_indent (file, -2);
8644e98e3e1Schristos 	lf_printf (file, "}\n");
8654e98e3e1Schristos 	lf_indent_suppress (file);
8664e98e3e1Schristos 	lf_printf (file, "#endif\n");
8674e98e3e1Schristos       }
8684e98e3e1Schristos   }
8694e98e3e1Schristos 
8704e98e3e1Schristos   /* Validate: Floating Point available
8714e98e3e1Schristos 
8724e98e3e1Schristos      If floating point is not available, we enter a floating point
8734e98e3e1Schristos      unavailable interrupt into the cache instead of the instruction
8744e98e3e1Schristos      proper.
8754e98e3e1Schristos 
8764e98e3e1Schristos      The PowerPC spec requires a CSI after MSR[FP] is changed and when
8774e98e3e1Schristos      ever a CSI occures we flush the instruction cache. */
8784e98e3e1Schristos 
8794e98e3e1Schristos   {
8804e98e3e1Schristos     if (filter_is_member (instruction->flags, "f"))
8814e98e3e1Schristos       {
8824e98e3e1Schristos 	lf_printf (file, "\n");
8834e98e3e1Schristos 	lf_indent_suppress (file);
8844e98e3e1Schristos 	lf_printf (file, "#if defined(IS_FP_AVAILABLE)\n");
8854e98e3e1Schristos 	lf_printf (file, "/* Validate: FP available according to cpu */\n");
8864e98e3e1Schristos 	lf_printf (file, "if (!IS_FP_AVAILABLE) {\n");
8874e98e3e1Schristos 	lf_indent (file, +2);
8884e98e3e1Schristos 	print_idecode_invalid (file, "return", invalid_fp_unavailable);
8894e98e3e1Schristos 	lf_indent (file, -2);
8904e98e3e1Schristos 	lf_printf (file, "}\n");
8914e98e3e1Schristos 	lf_indent_suppress (file);
8924e98e3e1Schristos 	lf_printf (file, "#endif\n");
8934e98e3e1Schristos       }
8944e98e3e1Schristos   }
8954e98e3e1Schristos 
8964e98e3e1Schristos   /* Validate: Validate Instruction in correct slot
8974e98e3e1Schristos 
8984e98e3e1Schristos      Some architectures place restrictions on the slot that an
8994e98e3e1Schristos      instruction can be issued in */
9004e98e3e1Schristos 
9014e98e3e1Schristos   {
9024e98e3e1Schristos     if (filter_is_member (instruction->options, "s")
9034e98e3e1Schristos 	|| options.gen.slot_verification)
9044e98e3e1Schristos       {
9054e98e3e1Schristos 	lf_printf (file, "\n");
9064e98e3e1Schristos 	lf_indent_suppress (file);
9074e98e3e1Schristos 	lf_printf (file, "#if defined(IS_WRONG_SLOT)\n");
9084e98e3e1Schristos 	lf_printf (file,
9094e98e3e1Schristos 		   "/* Validate: Instruction issued in correct slot */\n");
9104e98e3e1Schristos 	lf_printf (file, "if (IS_WRONG_SLOT) {\n");
9114e98e3e1Schristos 	lf_indent (file, +2);
9124e98e3e1Schristos 	print_idecode_invalid (file, "return", invalid_wrong_slot);
9134e98e3e1Schristos 	lf_indent (file, -2);
9144e98e3e1Schristos 	lf_printf (file, "}\n");
9154e98e3e1Schristos 	lf_indent_suppress (file);
9164e98e3e1Schristos 	lf_printf (file, "#endif\n");
9174e98e3e1Schristos       }
9184e98e3e1Schristos   }
9194e98e3e1Schristos 
9204e98e3e1Schristos }
9214e98e3e1Schristos 
9224e98e3e1Schristos 
9234e98e3e1Schristos /****************************************************************/
9244e98e3e1Schristos 
9254e98e3e1Schristos 
9264e98e3e1Schristos void
9274e98e3e1Schristos print_idecode_issue_function_header (lf *file,
9284e98e3e1Schristos 				     const char *processor,
9294e98e3e1Schristos 				     function_decl_type decl_type,
9304e98e3e1Schristos 				     int nr_prefetched_words)
9314e98e3e1Schristos {
9324e98e3e1Schristos   int indent;
9334e98e3e1Schristos   lf_printf (file, "\n");
9344e98e3e1Schristos   switch (decl_type)
9354e98e3e1Schristos     {
9364e98e3e1Schristos     case is_function_declaration:
9374e98e3e1Schristos       lf_print__function_type_function (file, print_semantic_function_type,
9384e98e3e1Schristos 					"INLINE_IDECODE", " ");
9394e98e3e1Schristos       break;
9404e98e3e1Schristos     case is_function_definition:
9414e98e3e1Schristos       lf_print__function_type_function (file, print_semantic_function_type,
9424e98e3e1Schristos 					"INLINE_IDECODE", "\n");
9434e98e3e1Schristos       break;
9444e98e3e1Schristos     case is_function_variable:
9458dffb485Schristos       if (lf_get_file_type (file) == lf_is_h)
9468dffb485Schristos 	lf_printf (file, "extern ");
9474e98e3e1Schristos       print_semantic_function_type (file);
9484e98e3e1Schristos       lf_printf (file, " (*");
9494e98e3e1Schristos       break;
9504e98e3e1Schristos     }
9514e98e3e1Schristos   indent = print_function_name (file,
9524e98e3e1Schristos 				"issue",
9534e98e3e1Schristos 				NULL,
9544e98e3e1Schristos 				processor,
9554e98e3e1Schristos 				NULL, function_name_prefix_idecode);
9564e98e3e1Schristos   switch (decl_type)
9574e98e3e1Schristos     {
9584e98e3e1Schristos     case is_function_definition:
9594e98e3e1Schristos       indent += lf_printf (file, " (");
9604e98e3e1Schristos       break;
9614e98e3e1Schristos     case is_function_declaration:
9624e98e3e1Schristos       lf_putstr (file, "\n(");
9634e98e3e1Schristos       indent = 1;
9644e98e3e1Schristos       break;
9654e98e3e1Schristos     case is_function_variable:
9664e98e3e1Schristos       lf_putstr (file, ")\n(");
9674e98e3e1Schristos       indent = 1;
9684e98e3e1Schristos       break;
9694e98e3e1Schristos     }
9704e98e3e1Schristos   lf_indent (file, +indent);
9714e98e3e1Schristos   print_semantic_function_formal (file, nr_prefetched_words);
9724e98e3e1Schristos   lf_putstr (file, ")");
9734e98e3e1Schristos   lf_indent (file, -indent);
9744e98e3e1Schristos   switch (decl_type)
9754e98e3e1Schristos     {
9764e98e3e1Schristos     case is_function_definition:
9774e98e3e1Schristos       lf_printf (file, "\n");
9784e98e3e1Schristos       break;
9794e98e3e1Schristos     case is_function_declaration:
9804e98e3e1Schristos     case is_function_variable:
9814e98e3e1Schristos       lf_putstr (file, ";\n");
9824e98e3e1Schristos       break;
9834e98e3e1Schristos     }
9844e98e3e1Schristos }
9854e98e3e1Schristos 
9864e98e3e1Schristos 
9874e98e3e1Schristos 
9884e98e3e1Schristos void
9894e98e3e1Schristos print_idecode_globals (lf *file)
9904e98e3e1Schristos {
9914e98e3e1Schristos   lf_printf (file, "enum {\n");
9924e98e3e1Schristos   lf_printf (file, "  /* greater or equal to zero => table */\n");
9934e98e3e1Schristos   lf_printf (file, "  function_entry = -1,\n");
9944e98e3e1Schristos   lf_printf (file, "  boolean_entry = -2,\n");
9954e98e3e1Schristos   lf_printf (file, "};\n");
9964e98e3e1Schristos   lf_printf (file, "\n");
9974e98e3e1Schristos   lf_printf (file, "typedef struct _idecode_table_entry {\n");
9984e98e3e1Schristos   lf_printf (file, "  int shift;\n");
9994b169a6bSchristos   lf_printf (file, "  uint%d_t mask;\n", options.insn_bit_size);
10004b169a6bSchristos   lf_printf (file, "  uint%d_t value;\n", options.insn_bit_size);
10014e98e3e1Schristos   lf_printf (file, "  void *function_or_table;\n");
10024e98e3e1Schristos   lf_printf (file, "} idecode_table_entry;\n");
10034e98e3e1Schristos }
1004