Home | History | Annotate | Line # | Download | only in ppc
      1  1.1  christos /*  This file is part of the program psim.
      2  1.1  christos 
      3  1.1  christos     Copyright 1994, 1995, 1996, 1997, 2003 Andrew Cagney
      4  1.1  christos 
      5  1.1  christos     This program is free software; you can redistribute it and/or modify
      6  1.1  christos     it under the terms of the GNU General Public License as published by
      7  1.1  christos     the Free Software Foundation; either version 3 of the License, or
      8  1.1  christos     (at your option) any later version.
      9  1.1  christos 
     10  1.1  christos     This program is distributed in the hope that it will be useful,
     11  1.1  christos     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  1.1  christos     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  1.1  christos     GNU General Public License for more details.
     14  1.1  christos 
     15  1.1  christos     You should have received a copy of the GNU General Public License
     16  1.1  christos     along with this program; if not, see <http://www.gnu.org/licenses/>.
     17  1.1  christos 
     18  1.1  christos     */
     19  1.1  christos 
     20  1.1  christos #include "misc.h"
     21  1.1  christos #include "lf.h"
     22  1.6  christos #include "lf-ppc.h"
     23  1.1  christos #include "table.h"
     24  1.1  christos 
     25  1.1  christos #include "filter.h"
     26  1.6  christos #include "filter-ppc.h"
     27  1.1  christos 
     28  1.1  christos #include "ld-decode.h"
     29  1.1  christos #include "ld-cache.h"
     30  1.1  christos #include "ld-insn.h"
     31  1.1  christos 
     32  1.1  christos #include "igen.h"
     33  1.1  christos 
     34  1.1  christos #include "gen-idecode.h"
     35  1.1  christos #include "gen-icache.h"
     36  1.1  christos #include "gen-semantics.h"
     37  1.1  christos 
     38  1.1  christos 
     39  1.1  christos 
     40  1.1  christos static void
     41  1.1  christos lf_print_opcodes(lf *file,
     42  1.1  christos 		 insn_table *table)
     43  1.1  christos {
     44  1.1  christos   if (table != NULL) {
     45  1.1  christos     while (1) {
     46  1.1  christos       ASSERT(table->opcode != NULL);
     47  1.1  christos       lf_printf(file, "_%d_%d",
     48  1.1  christos 		table->opcode->first,
     49  1.1  christos 		table->opcode->last);
     50  1.1  christos       if (table->parent == NULL) break;
     51  1.1  christos       lf_printf(file, "__%d", table->opcode_nr);
     52  1.1  christos       table = table->parent;
     53  1.1  christos     }
     54  1.1  christos   }
     55  1.1  christos }
     56  1.1  christos 
     57  1.1  christos /****************************************************************/
     58  1.1  christos 
     59  1.1  christos 
     60  1.1  christos static void
     61  1.1  christos lf_print_table_name(lf *file,
     62  1.1  christos 		    insn_table *table)
     63  1.1  christos {
     64  1.1  christos   lf_printf(file, "idecode_table");
     65  1.1  christos   lf_print_opcodes(file, table);
     66  1.1  christos }
     67  1.1  christos 
     68  1.1  christos 
     69  1.1  christos 
     70  1.1  christos static void
     71  1.1  christos print_idecode_table(lf *file,
     72  1.1  christos 		    insn_table *entry,
     73  1.1  christos 		    const char *result)
     74  1.1  christos {
     75  1.1  christos   lf_printf(file, "/* prime the search */\n");
     76  1.1  christos   lf_printf(file, "idecode_table_entry *table = ");
     77  1.1  christos   lf_print_table_name(file, entry);
     78  1.1  christos   lf_printf(file, ";\n");
     79  1.1  christos   lf_printf(file, "int opcode = EXTRACTED32(instruction, %d, %d);\n",
     80  1.1  christos 	    i2target(hi_bit_nr, entry->opcode->first),
     81  1.1  christos 	    i2target(hi_bit_nr, entry->opcode->last));
     82  1.1  christos   lf_printf(file, "idecode_table_entry *table_entry = table + opcode;\n");
     83  1.1  christos 
     84  1.1  christos   lf_printf(file, "\n");
     85  1.1  christos   lf_printf(file, "/* iterate until a leaf */\n");
     86  1.1  christos   lf_printf(file, "while (1) {\n");
     87  1.1  christos   lf_printf(file, "  signed shift = table_entry->shift;\n");
     88  1.1  christos   lf_printf(file, "if (shift == function_entry) break;\n");
     89  1.1  christos   lf_printf(file, "  if (shift >= 0) {\n");
     90  1.1  christos   lf_printf(file, "    table = ((idecode_table_entry*)\n");
     91  1.1  christos   lf_printf(file, "             table_entry->function_or_table);\n");
     92  1.1  christos   lf_printf(file, "    opcode = ((instruction & table_entry->mask)\n");
     93  1.1  christos   lf_printf(file, "              >> shift);\n");
     94  1.1  christos   lf_printf(file, "    table_entry = table + opcode;\n");
     95  1.1  christos   lf_printf(file, "  }\n");
     96  1.1  christos   lf_printf(file, "  else {\n");
     97  1.1  christos   lf_printf(file, "    /* must be a boolean */\n");
     98  1.1  christos   lf_printf(file, "    ASSERT(table_entry->shift == boolean_entry);\n");
     99  1.1  christos   lf_printf(file, "    opcode = ((instruction & table_entry->mask)\n");
    100  1.1  christos   lf_printf(file, "              != table_entry->value);\n");
    101  1.1  christos   lf_printf(file, "    table = ((idecode_table_entry*)\n");
    102  1.1  christos   lf_printf(file, "             table_entry->function_or_table);\n");
    103  1.1  christos   lf_printf(file, "    table_entry = table + opcode;\n");
    104  1.1  christos   lf_printf(file, "  }\n");
    105  1.1  christos   lf_printf(file, "}\n");
    106  1.1  christos 
    107  1.1  christos   lf_printf(file, "\n");
    108  1.1  christos   lf_printf(file, "/* call the leaf code */\n");
    109  1.1  christos   if ((code & generate_jumps)) {
    110  1.1  christos     lf_printf(file, "goto *table_entry->function_or_table;\n");
    111  1.1  christos   }
    112  1.1  christos   else {
    113  1.1  christos     lf_printf(file, "%s ", result);
    114  1.1  christos     if ((code & generate_with_icache)) {
    115  1.1  christos       lf_printf(file, "(((idecode_icache*)table_entry->function_or_table)\n");
    116  1.1  christos       lf_printf(file, "  (%s));\n", ICACHE_FUNCTION_ACTUAL);
    117  1.1  christos     }
    118  1.1  christos     else {
    119  1.1  christos       lf_printf(file, "((idecode_semantic*)table_entry->function_or_table)\n");
    120  1.1  christos       lf_printf(file, "  (%s);\n", SEMANTIC_FUNCTION_ACTUAL);
    121  1.1  christos     }
    122  1.1  christos   }
    123  1.1  christos }
    124  1.1  christos 
    125  1.1  christos 
    126  1.1  christos static void
    127  1.1  christos print_idecode_table_start(insn_table *table,
    128  1.1  christos 			  lf *file,
    129  1.1  christos 			  void *data,
    130  1.1  christos 			  int depth)
    131  1.1  christos {
    132  1.1  christos   ASSERT(depth == 0);
    133  1.1  christos   /* start of the table */
    134  1.1  christos   if (table->opcode_rule->gen == array_gen) {
    135  1.1  christos     lf_printf(file, "\n");
    136  1.1  christos     lf_printf(file, "static idecode_table_entry ");
    137  1.1  christos     lf_print_table_name(file, table);
    138  1.1  christos     lf_printf(file, "[] = {\n");
    139  1.1  christos   }
    140  1.1  christos }
    141  1.1  christos 
    142  1.1  christos static void
    143  1.1  christos print_idecode_table_leaf(insn_table *entry,
    144  1.1  christos 			 lf *file,
    145  1.1  christos 			 void *data,
    146  1.1  christos 			 insn *instruction,
    147  1.1  christos 			 int depth)
    148  1.1  christos {
    149  1.1  christos   ASSERT(entry->parent != NULL);
    150  1.1  christos   ASSERT(depth == 0);
    151  1.1  christos 
    152  1.1  christos   /* add an entry to the table */
    153  1.1  christos   if (entry->parent->opcode_rule->gen == array_gen) {
    154  1.1  christos     lf_printf(file, "  /*%d*/ { ", entry->opcode_nr);
    155  1.1  christos     if (entry->opcode == NULL) {
    156  1.1  christos       /* table leaf entry */
    157  1.1  christos       lf_printf(file, "function_entry, 0, 0, ");
    158  1.1  christos       if ((code & generate_jumps))
    159  1.1  christos 	lf_printf(file, "&&");
    160  1.1  christos       print_function_name(file,
    161  1.1  christos 			  entry->insns->file_entry->fields[insn_name],
    162  1.1  christos 			  entry->expanded_bits,
    163  1.1  christos 			  ((code & generate_with_icache)
    164  1.1  christos 			   ? function_name_prefix_icache
    165  1.1  christos 			   : function_name_prefix_semantics));
    166  1.1  christos     }
    167  1.1  christos     else if (entry->opcode_rule->gen == switch_gen
    168  1.1  christos 	     || entry->opcode_rule->gen == goto_switch_gen
    169  1.1  christos 	     || entry->opcode_rule->gen == padded_switch_gen) {
    170  1.1  christos       /* table calling switch statement */
    171  1.1  christos       lf_printf(file, "function_entry, 0, 0, ");
    172  1.1  christos       if ((code & generate_jumps))
    173  1.1  christos 	lf_printf(file, "&&");
    174  1.1  christos       lf_print_table_name(file, entry);
    175  1.1  christos     }
    176  1.1  christos     else if (entry->opcode->is_boolean) {
    177  1.1  christos       /* table `calling' boolean table */
    178  1.1  christos       lf_printf(file, "boolean_entry, ");
    179  1.1  christos       lf_printf(file, "MASK32(%d, %d), ",
    180  1.1  christos 		i2target(hi_bit_nr, entry->opcode->first),
    181  1.1  christos 		i2target(hi_bit_nr, entry->opcode->last));
    182  1.1  christos       lf_printf(file, "INSERTED32(%d, %d, %d), ",
    183  1.1  christos 		entry->opcode->boolean_constant,
    184  1.1  christos 		i2target(hi_bit_nr, entry->opcode->first),
    185  1.1  christos 		i2target(hi_bit_nr, entry->opcode->last));
    186  1.1  christos       lf_print_table_name(file, entry);
    187  1.1  christos     }
    188  1.1  christos     else {
    189  1.1  christos       /* table `calling' another table */
    190  1.1  christos       lf_printf(file, "%d, ", insn_bit_size - entry->opcode->last - 1);
    191  1.1  christos       lf_printf(file, "MASK32(%d,%d), ",
    192  1.1  christos 		i2target(hi_bit_nr, entry->opcode->first),
    193  1.1  christos 		i2target(hi_bit_nr, entry->opcode->last));
    194  1.1  christos       lf_printf(file, "0, ");
    195  1.1  christos       lf_print_table_name(file, entry);
    196  1.1  christos     }
    197  1.1  christos     lf_printf(file, " },\n");
    198  1.1  christos   }
    199  1.1  christos }
    200  1.1  christos 
    201  1.1  christos static void
    202  1.1  christos print_idecode_table_end(insn_table *table,
    203  1.1  christos 			lf *file,
    204  1.1  christos 			void *data,
    205  1.1  christos 			int depth)
    206  1.1  christos {
    207  1.1  christos   ASSERT(depth == 0);
    208  1.1  christos   if (table->opcode_rule->gen == array_gen) {
    209  1.1  christos     lf_printf(file, "};\n");
    210  1.1  christos   }
    211  1.1  christos }
    212  1.1  christos 
    213  1.1  christos static void
    214  1.1  christos print_idecode_table_padding(insn_table *table,
    215  1.1  christos 			    lf *file,
    216  1.1  christos 			    void *data,
    217  1.1  christos 			    int depth,
    218  1.1  christos 			    int opcode_nr)
    219  1.1  christos {
    220  1.1  christos   ASSERT(depth == 0);
    221  1.1  christos   if (table->opcode_rule->gen == array_gen) {
    222  1.1  christos     lf_printf(file, "  /*%d*/ { function_entry, 0, 0, ", opcode_nr);
    223  1.1  christos     if ((code & generate_jumps))
    224  1.1  christos       lf_printf(file, "&&");
    225  1.1  christos     lf_printf(file, "%s_illegal },\n",
    226  1.1  christos 	      ((code & generate_with_icache) ? "icache" : "semantic"));
    227  1.1  christos   }
    228  1.1  christos }
    229  1.1  christos 
    230  1.1  christos 
    231  1.1  christos /****************************************************************/
    232  1.1  christos 
    233  1.1  christos 
    234  1.1  christos static void
    235  1.1  christos print_goto_switch_name(lf *file,
    236  1.1  christos 		       insn_table *entry)
    237  1.1  christos {
    238  1.1  christos   lf_printf(file, "case_");
    239  1.1  christos   if (entry->opcode == NULL)
    240  1.1  christos     print_function_name(file,
    241  1.1  christos 			entry->insns->file_entry->fields[insn_name],
    242  1.1  christos 			entry->expanded_bits,
    243  1.1  christos 			((code & generate_with_icache)
    244  1.1  christos 			 ? function_name_prefix_icache
    245  1.1  christos 			 : function_name_prefix_semantics));
    246  1.1  christos   else
    247  1.1  christos     lf_print_table_name(file, entry);
    248  1.1  christos }
    249  1.1  christos 
    250  1.1  christos static void
    251  1.1  christos print_goto_switch_table_leaf(insn_table *entry,
    252  1.1  christos 			     lf *file,
    253  1.1  christos 			     void *data,
    254  1.1  christos 			     insn *instruction,
    255  1.1  christos 			     int depth)
    256  1.1  christos {
    257  1.1  christos   ASSERT(entry->parent != NULL);
    258  1.1  christos   ASSERT(depth == 0);
    259  1.1  christos   ASSERT(entry->parent->opcode_rule->gen == goto_switch_gen);
    260  1.1  christos   ASSERT(entry->parent->opcode);
    261  1.1  christos 
    262  1.1  christos   lf_printf(file, "&&");
    263  1.1  christos   print_goto_switch_name(file, entry);
    264  1.1  christos   lf_printf(file, ",\n");
    265  1.1  christos }
    266  1.1  christos 
    267  1.1  christos static void
    268  1.1  christos print_goto_switch_table_padding(insn_table *table,
    269  1.1  christos 				lf *file,
    270  1.1  christos 				void *data,
    271  1.1  christos 				int depth,
    272  1.1  christos 				int opcode_nr)
    273  1.1  christos {
    274  1.1  christos   ASSERT(depth == 0);
    275  1.1  christos   ASSERT(table->opcode_rule->gen == goto_switch_gen);
    276  1.1  christos 
    277  1.1  christos   lf_printf(file, "&&illegal_");
    278  1.1  christos   lf_print_table_name(file, table);
    279  1.1  christos   lf_printf(file, ",\n");
    280  1.1  christos }
    281  1.1  christos 
    282  1.1  christos static void
    283  1.1  christos print_goto_switch_break(lf *file,
    284  1.1  christos 			insn_table *entry)
    285  1.1  christos {
    286  1.1  christos   lf_printf(file, "goto break_");
    287  1.1  christos   lf_print_table_name(file, entry->parent);
    288  1.1  christos   lf_printf(file, ";\n");
    289  1.1  christos }
    290  1.1  christos 
    291  1.1  christos 
    292  1.1  christos static void
    293  1.1  christos print_goto_switch_table(lf *file,
    294  1.1  christos 			insn_table *table)
    295  1.1  christos {
    296  1.1  christos   lf_printf(file, "const static void *");
    297  1.1  christos   lf_print_table_name(file, table);
    298  1.1  christos   lf_printf(file, "[] = {\n");
    299  1.1  christos   lf_indent(file, +2);
    300  1.1  christos   insn_table_traverse_tree(table,
    301  1.1  christos 			   file, NULL/*data*/,
    302  1.1  christos 			   0,
    303  1.1  christos 			   NULL/*start*/,
    304  1.1  christos 			   print_goto_switch_table_leaf,
    305  1.1  christos 			   NULL/*end*/,
    306  1.1  christos 			   print_goto_switch_table_padding);
    307  1.1  christos   lf_indent(file, -2);
    308  1.1  christos   lf_printf(file, "};\n");
    309  1.1  christos }
    310  1.1  christos 
    311  1.1  christos 
    312  1.1  christos void print_idecode_switch
    313  1.1  christos (lf *file,
    314  1.1  christos  insn_table *table,
    315  1.1  christos  const char *result);
    316  1.1  christos 
    317  1.1  christos static void
    318  1.1  christos idecode_switch_start(insn_table *table,
    319  1.1  christos 		     lf *file,
    320  1.1  christos 		     void *data,
    321  1.1  christos 		     int depth)
    322  1.1  christos {
    323  1.1  christos   /* const char *result = data; */
    324  1.1  christos   ASSERT(depth == 0);
    325  1.1  christos   ASSERT(table->opcode_rule->gen == switch_gen
    326  1.1  christos 	 || table->opcode_rule->gen == goto_switch_gen
    327  1.1  christos 	 || table->opcode_rule->gen == padded_switch_gen);
    328  1.1  christos 
    329  1.1  christos   if (table->opcode->is_boolean
    330  1.1  christos       || table->opcode_rule->gen == switch_gen
    331  1.1  christos 	 || table->opcode_rule->gen == padded_switch_gen) {
    332  1.1  christos     lf_printf(file, "switch (EXTRACTED32(instruction, %d, %d)) {\n",
    333  1.1  christos 	      i2target(hi_bit_nr, table->opcode->first),
    334  1.1  christos 	      i2target(hi_bit_nr, table->opcode->last));
    335  1.1  christos   }
    336  1.1  christos   else if (table->opcode_rule->gen == goto_switch_gen) {
    337  1.1  christos     if (table->parent != NULL
    338  1.1  christos 	&& (table->parent->opcode_rule->gen == switch_gen
    339  1.1  christos 	    || table->parent->opcode_rule->gen == goto_switch_gen
    340  1.1  christos 	    || table->parent->opcode_rule->gen == padded_switch_gen)) {
    341  1.1  christos       lf_printf(file, "{\n");
    342  1.1  christos       lf_indent(file, +2);
    343  1.1  christos     }
    344  1.1  christos     print_goto_switch_table(file, table);
    345  1.1  christos     lf_printf(file, "ASSERT(EXTRACTED32(instruction, %d, %d)\n",
    346  1.1  christos 	      i2target(hi_bit_nr, table->opcode->first),
    347  1.1  christos 	      i2target(hi_bit_nr, table->opcode->last));
    348  1.1  christos     lf_printf(file, "       < (sizeof(");
    349  1.1  christos     lf_print_table_name(file, table);
    350  1.1  christos     lf_printf(file, ") / sizeof(void*)));\n");
    351  1.1  christos     lf_printf(file, "goto *");
    352  1.1  christos     lf_print_table_name(file, table);
    353  1.1  christos     lf_printf(file, "[EXTRACTED32(instruction, %d, %d)];\n",
    354  1.1  christos 	      i2target(hi_bit_nr, table->opcode->first),
    355  1.1  christos 	      i2target(hi_bit_nr, table->opcode->last));
    356  1.1  christos   }
    357  1.1  christos   else {
    358  1.1  christos     ASSERT("bad switch" == NULL);
    359  1.1  christos   }
    360  1.1  christos }
    361  1.1  christos 
    362  1.1  christos 
    363  1.1  christos static void
    364  1.1  christos idecode_switch_leaf(insn_table *entry,
    365  1.1  christos 		    lf *file,
    366  1.1  christos 		    void *data,
    367  1.1  christos 		    insn *instruction,
    368  1.1  christos 		    int depth)
    369  1.1  christos {
    370  1.1  christos   const char *result = data;
    371  1.1  christos   ASSERT(entry->parent != NULL);
    372  1.1  christos   ASSERT(depth == 0);
    373  1.1  christos   ASSERT(entry->parent->opcode_rule->gen == switch_gen
    374  1.1  christos 	 || entry->parent->opcode_rule->gen == goto_switch_gen
    375  1.1  christos 	 || entry->parent->opcode_rule->gen == padded_switch_gen);
    376  1.1  christos   ASSERT(entry->parent->opcode);
    377  1.1  christos 
    378  1.1  christos   if (entry->parent->opcode->is_boolean
    379  1.1  christos       && entry->opcode_nr == 0) {
    380  1.1  christos     /* boolean false target */
    381  1.1  christos     lf_printf(file, "case %d:\n", entry->parent->opcode->boolean_constant);
    382  1.1  christos   }
    383  1.1  christos   else if (entry->parent->opcode->is_boolean
    384  1.1  christos 	   && entry->opcode_nr != 0) {
    385  1.1  christos     /* boolean true case */
    386  1.1  christos     lf_printf(file, "default:\n");
    387  1.1  christos   }
    388  1.1  christos   else if (entry->parent->opcode_rule->gen == switch_gen
    389  1.1  christos 	   || entry->parent->opcode_rule->gen == padded_switch_gen) {
    390  1.1  christos     /* normal goto */
    391  1.1  christos     lf_printf(file, "case %d:\n", entry->opcode_nr);
    392  1.1  christos   }
    393  1.1  christos   else if (entry->parent->opcode_rule->gen == goto_switch_gen) {
    394  1.1  christos     /* lf_indent(file, -1); */
    395  1.1  christos     print_goto_switch_name(file, entry);
    396  1.1  christos     lf_printf(file, ":\n");
    397  1.1  christos     /* lf_indent(file, +1); */
    398  1.1  christos   }
    399  1.1  christos   else {
    400  1.1  christos     ASSERT("bad switch" == NULL);
    401  1.1  christos   }
    402  1.1  christos   lf_indent(file, +2);
    403  1.1  christos   {
    404  1.1  christos     if (entry->opcode == NULL) {
    405  1.1  christos       /* switch calling leaf */
    406  1.1  christos       if ((code & generate_jumps))
    407  1.1  christos 	lf_printf(file, "goto ");
    408  1.1  christos       if ((code & generate_calls))
    409  1.1  christos 	lf_printf(file, "%s ", result);
    410  1.1  christos       print_function_name(file,
    411  1.1  christos 			  entry->insns->file_entry->fields[insn_name],
    412  1.1  christos 			  entry->expanded_bits,
    413  1.1  christos 			  ((code & generate_with_icache)
    414  1.1  christos 			   ? function_name_prefix_icache
    415  1.1  christos 			   : function_name_prefix_semantics));
    416  1.1  christos       if ((code & generate_calls))
    417  1.1  christos 	lf_printf(file, "(%s)", SEMANTIC_FUNCTION_ACTUAL);
    418  1.1  christos       lf_printf(file, ";\n");
    419  1.1  christos     }
    420  1.1  christos     else if (entry->opcode_rule->gen == switch_gen
    421  1.1  christos 	     || entry->opcode_rule->gen == goto_switch_gen
    422  1.1  christos 	     || entry->opcode_rule->gen == padded_switch_gen) {
    423  1.1  christos       /* switch calling switch */
    424  1.1  christos       print_idecode_switch(file, entry, result);
    425  1.1  christos     }
    426  1.1  christos     else {
    427  1.1  christos       /* switch looking up a table */
    428  1.1  christos       lf_printf(file, "{\n");
    429  1.1  christos       lf_indent(file, -2);
    430  1.1  christos       print_idecode_table(file, entry, result);
    431  1.1  christos       lf_indent(file, -2);
    432  1.1  christos       lf_printf(file, "}\n");
    433  1.1  christos     }
    434  1.1  christos     if (entry->parent->opcode->is_boolean
    435  1.1  christos 	|| entry->parent->opcode_rule->gen == switch_gen
    436  1.1  christos 	|| entry->parent->opcode_rule->gen == padded_switch_gen) {
    437  1.1  christos       lf_printf(file, "break;\n");
    438  1.1  christos     }
    439  1.1  christos     else if (entry->parent->opcode_rule->gen == goto_switch_gen) {
    440  1.1  christos       print_goto_switch_break(file, entry);
    441  1.1  christos     }
    442  1.1  christos     else {
    443  1.1  christos       ASSERT("bad switch" == NULL);
    444  1.1  christos     }
    445  1.1  christos   }
    446  1.1  christos   lf_indent(file, -2);
    447  1.1  christos }
    448  1.1  christos 
    449  1.1  christos 
    450  1.1  christos static void
    451  1.1  christos print_idecode_switch_illegal(lf *file,
    452  1.1  christos 			     const char *result)
    453  1.1  christos {
    454  1.1  christos   lf_indent(file, +2);
    455  1.1  christos   print_idecode_illegal(file, result);
    456  1.1  christos   lf_printf(file, "break;\n");
    457  1.1  christos   lf_indent(file, -2);
    458  1.1  christos }
    459  1.1  christos 
    460  1.1  christos static void
    461  1.1  christos idecode_switch_end(insn_table *table,
    462  1.1  christos 		   lf *file,
    463  1.1  christos 		   void *data,
    464  1.1  christos 		   int depth)
    465  1.1  christos {
    466  1.1  christos   const char *result = data;
    467  1.1  christos   ASSERT(depth == 0);
    468  1.1  christos   ASSERT(table->opcode_rule->gen == switch_gen
    469  1.1  christos 	 || table->opcode_rule->gen == goto_switch_gen
    470  1.1  christos 	 || table->opcode_rule->gen == padded_switch_gen);
    471  1.1  christos   ASSERT(table->opcode);
    472  1.1  christos 
    473  1.1  christos   if (table->opcode->is_boolean) {
    474  1.1  christos     lf_printf(file, "}\n");
    475  1.1  christos   }
    476  1.1  christos   else if (table->opcode_rule->gen == switch_gen
    477  1.1  christos 	   || table->opcode_rule->gen == padded_switch_gen) {
    478  1.1  christos     lf_printf(file, "default:\n");
    479  1.1  christos     switch (table->opcode_rule->gen) {
    480  1.1  christos     case switch_gen:
    481  1.1  christos       print_idecode_switch_illegal(file, result);
    482  1.1  christos       break;
    483  1.1  christos     case padded_switch_gen:
    484  1.1  christos       lf_printf(file, "  error(\"Internal error - bad switch generated\\n\");\n");
    485  1.1  christos       lf_printf(file, "  break;\n");
    486  1.1  christos       break;
    487  1.1  christos     default:
    488  1.1  christos       ASSERT("bad switch" == NULL);
    489  1.1  christos     }
    490  1.1  christos     lf_printf(file, "}\n");
    491  1.1  christos   }
    492  1.1  christos   else if (table->opcode_rule->gen == goto_switch_gen) {
    493  1.1  christos     lf_printf(file, "illegal_");
    494  1.1  christos     lf_print_table_name(file, table);
    495  1.1  christos     lf_printf(file, ":\n");
    496  1.1  christos     print_idecode_illegal(file, result);
    497  1.1  christos     lf_printf(file, "break_");
    498  1.1  christos     lf_print_table_name(file, table);
    499  1.1  christos     lf_printf(file, ":;\n");
    500  1.1  christos     if (table->parent != NULL
    501  1.1  christos 	&& (table->parent->opcode_rule->gen == switch_gen
    502  1.1  christos 	    || table->parent->opcode_rule->gen == goto_switch_gen
    503  1.1  christos 	    || table->parent->opcode_rule->gen == padded_switch_gen)) {
    504  1.1  christos       lf_indent(file, -2);
    505  1.1  christos       lf_printf(file, "}\n");
    506  1.1  christos     }
    507  1.1  christos   }
    508  1.1  christos   else {
    509  1.1  christos     ASSERT("bad switch" == NULL);
    510  1.1  christos   }
    511  1.1  christos }
    512  1.1  christos 
    513  1.1  christos static void
    514  1.1  christos idecode_switch_padding(insn_table *table,
    515  1.1  christos 		       lf *file,
    516  1.1  christos 		       void *data,
    517  1.1  christos 		       int depth,
    518  1.1  christos 		       int opcode_nr)
    519  1.1  christos {
    520  1.1  christos   const char *result = data;
    521  1.1  christos   ASSERT(depth == 0);
    522  1.1  christos   ASSERT(table->opcode_rule->gen == switch_gen
    523  1.1  christos 	 || table->opcode_rule->gen == goto_switch_gen
    524  1.1  christos 	 || table->opcode_rule->gen == padded_switch_gen);
    525  1.1  christos 
    526  1.1  christos   switch (table->opcode_rule->gen) {
    527  1.1  christos   case switch_gen:
    528  1.1  christos     break;
    529  1.1  christos   case padded_switch_gen:
    530  1.1  christos     lf_printf(file, "case %d:\n", opcode_nr);
    531  1.1  christos     print_idecode_switch_illegal(file, result);
    532  1.1  christos     break;
    533  1.1  christos   case goto_switch_gen:
    534  1.1  christos     /* no padding needed */
    535  1.1  christos     break;
    536  1.1  christos   default:
    537  1.1  christos     ASSERT("bad switch" != NULL);
    538  1.1  christos   }
    539  1.1  christos }
    540  1.1  christos 
    541  1.1  christos 
    542  1.1  christos void
    543  1.1  christos print_idecode_switch(lf *file,
    544  1.1  christos 		     insn_table *table,
    545  1.1  christos 		     const char *result)
    546  1.1  christos {
    547  1.1  christos   insn_table_traverse_tree(table,
    548  1.1  christos 			   file, (void*)result,
    549  1.1  christos 			   0,
    550  1.1  christos 			   idecode_switch_start,
    551  1.1  christos 			   idecode_switch_leaf,
    552  1.1  christos 			   idecode_switch_end,
    553  1.1  christos 			   idecode_switch_padding);
    554  1.1  christos }
    555  1.1  christos 
    556  1.1  christos 
    557  1.1  christos static void
    558  1.1  christos print_idecode_switch_function_header(lf *file,
    559  1.1  christos 				     insn_table *table,
    560  1.1  christos 				     int is_function_definition)
    561  1.1  christos {
    562  1.1  christos   lf_printf(file, "\n");
    563  1.1  christos   if ((code & generate_calls)) {
    564  1.1  christos     lf_printf(file, "static ");
    565  1.1  christos     if ((code & generate_with_icache))
    566  1.1  christos       lf_printf(file, "idecode_semantic *");
    567  1.1  christos     else
    568  1.1  christos       lf_printf(file, "unsigned_word");
    569  1.1  christos     if (is_function_definition)
    570  1.1  christos       lf_printf(file, "\n");
    571  1.1  christos     else
    572  1.1  christos       lf_printf(file, " ");
    573  1.1  christos     lf_print_table_name(file, table);
    574  1.1  christos     lf_printf(file, "\n(%s)", ICACHE_FUNCTION_FORMAL);
    575  1.1  christos     if (!is_function_definition)
    576  1.1  christos       lf_printf(file, ";");
    577  1.1  christos     lf_printf(file, "\n");
    578  1.1  christos   }
    579  1.1  christos   if ((code & generate_jumps) && is_function_definition) {
    580  1.1  christos     lf_indent(file, -1);
    581  1.1  christos     lf_print_table_name(file, table);
    582  1.1  christos     lf_printf(file, ":\n");
    583  1.1  christos     lf_indent(file, +1);
    584  1.1  christos   }
    585  1.1  christos }
    586  1.1  christos 
    587  1.1  christos 
    588  1.1  christos static void
    589  1.1  christos idecode_declare_if_switch(insn_table *table,
    590  1.1  christos 			  lf *file,
    591  1.1  christos 			  void *data,
    592  1.1  christos 			  int depth)
    593  1.1  christos {
    594  1.1  christos   if ((table->opcode_rule->gen == switch_gen
    595  1.1  christos        || table->opcode_rule->gen == goto_switch_gen
    596  1.1  christos        || table->opcode_rule->gen == padded_switch_gen)
    597  1.1  christos       && table->parent != NULL /* don't declare the top one yet */
    598  1.1  christos       && table->parent->opcode_rule->gen == array_gen) {
    599  1.1  christos     print_idecode_switch_function_header(file,
    600  1.1  christos 					 table,
    601  1.1  christos 					 0/*isnt function definition*/);
    602  1.1  christos   }
    603  1.1  christos }
    604  1.1  christos 
    605  1.1  christos 
    606  1.1  christos static void
    607  1.1  christos idecode_expand_if_switch(insn_table *table,
    608  1.1  christos 			 lf *file,
    609  1.1  christos 			 void *data,
    610  1.1  christos 			 int depth)
    611  1.1  christos {
    612  1.1  christos   if ((table->opcode_rule->gen == switch_gen
    613  1.1  christos        || table->opcode_rule->gen == goto_switch_gen
    614  1.1  christos        || table->opcode_rule->gen == padded_switch_gen)
    615  1.1  christos       && table->parent != NULL /* don't expand the top one yet */
    616  1.1  christos       && table->parent->opcode_rule->gen == array_gen) {
    617  1.1  christos     print_idecode_switch_function_header(file,
    618  1.1  christos 					    table,
    619  1.1  christos 					    1/*is function definition*/);
    620  1.1  christos     if ((code & generate_calls)) {
    621  1.1  christos       lf_printf(file, "{\n");
    622  1.1  christos       lf_indent(file, +2);
    623  1.1  christos     }
    624  1.1  christos     print_idecode_switch(file, table, "return");
    625  1.1  christos     if ((code & generate_calls)) {
    626  1.1  christos       lf_indent(file, -2);
    627  1.1  christos       lf_printf(file, "}\n");
    628  1.1  christos     }
    629  1.1  christos   }
    630  1.1  christos }
    631  1.1  christos 
    632  1.1  christos 
    633  1.1  christos /****************************************************************/
    634  1.1  christos 
    635  1.1  christos 
    636  1.1  christos static void
    637  1.1  christos print_idecode_lookups(lf *file,
    638  1.1  christos 		      insn_table *table,
    639  1.1  christos 		      cache_table *cache_rules)
    640  1.1  christos {
    641  1.1  christos   int depth;
    642  1.1  christos 
    643  1.1  christos   /* output switch function declarations where needed by tables */
    644  1.1  christos   insn_table_traverse_tree(table,
    645  1.1  christos 			   file, NULL,
    646  1.1  christos 			   1,
    647  1.1  christos 			   idecode_declare_if_switch, /* START */
    648  1.1  christos 			   NULL, NULL, NULL);
    649  1.1  christos 
    650  1.1  christos   /* output tables where needed */
    651  1.1  christos   for (depth = insn_table_depth(table);
    652  1.1  christos        depth > 0;
    653  1.1  christos        depth--) {
    654  1.1  christos     insn_table_traverse_tree(table,
    655  1.1  christos 			     file, NULL,
    656  1.1  christos 			     1-depth,
    657  1.1  christos 			     print_idecode_table_start,
    658  1.1  christos 			     print_idecode_table_leaf,
    659  1.1  christos 			     print_idecode_table_end,
    660  1.1  christos 			     print_idecode_table_padding);
    661  1.1  christos   }
    662  1.1  christos 
    663  1.1  christos   /* output switch functions where needed */
    664  1.1  christos   insn_table_traverse_tree(table,
    665  1.1  christos 			   file, NULL,
    666  1.1  christos 			   1,
    667  1.1  christos 			   idecode_expand_if_switch, /* START */
    668  1.1  christos 			   NULL, NULL, NULL);
    669  1.1  christos }
    670  1.1  christos 
    671  1.1  christos 
    672  1.1  christos static void
    673  1.1  christos print_idecode_body(lf *file,
    674  1.1  christos 		   insn_table *table,
    675  1.1  christos 		   const char *result)
    676  1.1  christos {
    677  1.1  christos   if (table->opcode_rule->gen == switch_gen
    678  1.1  christos       || table->opcode_rule->gen == goto_switch_gen
    679  1.1  christos       || table->opcode_rule->gen == padded_switch_gen)
    680  1.1  christos     print_idecode_switch(file, table, result);
    681  1.1  christos   else
    682  1.1  christos     print_idecode_table(file, table, result);
    683  1.1  christos }
    684  1.1  christos 
    685  1.1  christos 
    686  1.1  christos /****************************************************************/
    687  1.1  christos 
    688  1.1  christos 
    689  1.1  christos static void
    690  1.1  christos print_run_until_stop_body(lf *file,
    691  1.1  christos 			  insn_table *table,
    692  1.1  christos 			  int can_stop)
    693  1.1  christos {
    694  1.1  christos   /* Output the function to execute real code:
    695  1.1  christos 
    696  1.1  christos      Unfortunatly, there are multiple cases to consider vis:
    697  1.1  christos 
    698  1.1  christos      <icache> X <smp> X <events> X <keep-running-flag> X ...
    699  1.1  christos 
    700  1.1  christos      Consequently this function is written in multiple different ways */
    701  1.1  christos 
    702  1.1  christos   lf_putstr(file, "{\n");
    703  1.1  christos   lf_indent(file, +2);
    704  1.1  christos   lf_putstr(file, "jmp_buf halt;\n");
    705  1.1  christos   lf_putstr(file, "jmp_buf restart;\n");
    706  1.1  christos   if (!generate_smp) {
    707  1.1  christos     lf_putstr(file, "cpu *processor = NULL;\n");
    708  1.1  christos     lf_putstr(file, "unsigned_word cia = -1;\n");
    709  1.1  christos   }
    710  1.1  christos   lf_putstr(file, "int last_cpu;\n");
    711  1.1  christos   if (generate_smp) {
    712  1.1  christos     lf_putstr(file, "int current_cpu;\n");
    713  1.1  christos   }
    714  1.1  christos 
    715  1.1  christos   if ((code & generate_with_icache)) {
    716  1.1  christos     lf_putstr(file, "int cpu_nr;\n");
    717  1.1  christos     lf_putstr(file, "\n");
    718  1.1  christos     lf_putstr(file, "/* flush the icache of a possible break insn */\n");
    719  1.1  christos     lf_putstr(file, "for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
    720  1.1  christos     lf_putstr(file, "  cpu_flush_icache(processors[cpu_nr]);\n");
    721  1.1  christos   }
    722  1.1  christos 
    723  1.1  christos   lf_putstr(file, "\n");
    724  1.1  christos   lf_putstr(file, "/* set the halt target initially */\n");
    725  1.1  christos   lf_putstr(file, "psim_set_halt_and_restart(system, &halt, NULL);\n");
    726  1.1  christos   lf_putstr(file, "if (setjmp(halt))\n");
    727  1.1  christos   lf_putstr(file, "  return;\n");
    728  1.1  christos 
    729  1.1  christos   lf_putstr(file, "\n");
    730  1.1  christos   lf_putstr(file, "/* where were we before the halt? */\n");
    731  1.1  christos   lf_putstr(file, "last_cpu = psim_last_cpu(system);\n");
    732  1.1  christos 
    733  1.1  christos   lf_putstr(file, "\n");
    734  1.1  christos   lf_putstr(file, "/* check for need to force event processing first */\n");
    735  1.1  christos   lf_putstr(file, "if (WITH_EVENTS) {\n");
    736  1.1  christos   lf_putstr(file, "  if (last_cpu == nr_cpus) {\n");
    737  1.1  christos   lf_putstr(file, "    /* halted during event processing */\n");
    738  1.1  christos   lf_putstr(file, "    event_queue_process(events);\n");
    739  1.1  christos   lf_putstr(file, "    last_cpu = -1;\n");
    740  1.1  christos   lf_putstr(file, "  }\n");
    741  1.1  christos   lf_putstr(file, "  else if (last_cpu == nr_cpus - 1) {\n");
    742  1.1  christos   lf_putstr(file, "    /* last cpu did halt */\n");
    743  1.1  christos   lf_putstr(file, "    if (event_queue_tick(events)) {\n");
    744  1.1  christos   lf_putstr(file, "      event_queue_process(events);\n");
    745  1.1  christos   lf_putstr(file, "    }\n");
    746  1.1  christos   lf_putstr(file, "    last_cpu = -1;\n");
    747  1.1  christos   lf_putstr(file, "  }\n");
    748  1.1  christos   lf_putstr(file, "}\n");
    749  1.1  christos   lf_putstr(file, "else {\n");
    750  1.1  christos   lf_putstr(file, " if (last_cpu == nr_cpus - 1)\n");
    751  1.1  christos   lf_putstr(file, "   /* cpu zero is next */\n");
    752  1.1  christos   lf_putstr(file, "   last_cpu = -1;\n");
    753  1.1  christos   lf_putstr(file, "}\n");
    754  1.1  christos 
    755  1.1  christos   lf_putstr(file, "\n");
    756  1.1  christos   lf_putstr(file, "/* have ensured that the event queue can not be first */\n");
    757  1.1  christos   lf_putstr(file, "ASSERT(last_cpu >= -1 && last_cpu < nr_cpus - 1);\n");
    758  1.1  christos 
    759  1.1  christos   if (!generate_smp) {
    760  1.1  christos 
    761  1.1  christos     lf_putstr(file, "\n\
    762  1.1  christos /* CASE 1: NO SMP (with or with out instruction cache).\n\
    763  1.1  christos \n\
    764  1.1  christos    In this case, we can take advantage of the fact that the current\n\
    765  1.1  christos    instruction address does not need to be returned to the cpu object\n\
    766  1.1  christos    after every execution of an instruction.  Instead it only needs to\n\
    767  1.1  christos    be saved when either A. the main loop exits or B. A cpu-halt or\n\
    768  1.1  christos    cpu-restart call forces the loop to be re-enered.  The later\n\
    769  1.1  christos    functions always save the current cpu instruction address.\n\
    770  1.1  christos \n\
    771  1.1  christos    Two subcases also exist that with and that without an instruction\n\
    772  1.1  christos    cache.\n\
    773  1.1  christos \n\
    774  1.1  christos    An additional complexity is the need to ensure that a 1:1 ratio\n\
    775  1.1  christos    is maintained between the execution of an instruction and the\n\
    776  1.1  christos    incrementing of the simulation clock */");
    777  1.1  christos 
    778  1.1  christos     lf_putstr(file, "\n");
    779  1.1  christos 
    780  1.1  christos     lf_putstr(file, "\n");
    781  1.1  christos     lf_putstr(file, "/* now add restart target as ready to run */\n");
    782  1.1  christos     lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
    783  1.1  christos     lf_putstr(file, "if (setjmp(restart)) {\n");
    784  1.1  christos     lf_putstr(file, "  if (WITH_EVENTS) {\n");
    785  1.1  christos     lf_putstr(file, "    /* when restart, cpu must have been last, clock next */\n");
    786  1.1  christos     lf_putstr(file, "    if (event_queue_tick(events)) {\n");
    787  1.1  christos     lf_putstr(file, "      event_queue_process(events);\n");
    788  1.1  christos     lf_putstr(file, "    }\n");
    789  1.1  christos     lf_putstr(file, "  }\n");
    790  1.1  christos     lf_putstr(file, "}\n");
    791  1.1  christos 
    792  1.1  christos     lf_putstr(file, "\n");
    793  1.1  christos     lf_putstr(file, "/* prime the main loop */\n");
    794  1.1  christos     lf_putstr(file, "processor = processors[0];\n");
    795  1.1  christos     lf_putstr(file, "cia = cpu_get_program_counter(processor);\n");
    796  1.1  christos 
    797  1.1  christos     lf_putstr(file, "\n");
    798  1.1  christos     lf_putstr(file, "while (1) {\n");
    799  1.1  christos     lf_indent(file, +2);
    800  1.1  christos 
    801  1.1  christos     if (!(code & generate_with_icache)) {
    802  1.1  christos       lf_putstr(file, "instruction_word instruction =\n");
    803  1.1  christos       lf_putstr(file, "  vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
    804  1.1  christos       lf_putstr(file, "\n");
    805  1.1  christos       print_idecode_body(file, table, "cia =");;
    806  1.1  christos     }
    807  1.1  christos 
    808  1.1  christos     if ((code & generate_with_icache)) {
    809  1.1  christos       lf_putstr(file, "idecode_cache *cache_entry =\n");
    810  1.1  christos       lf_putstr(file, "  cpu_icache_entry(processor, cia);\n");
    811  1.1  christos       lf_putstr(file, "if (cache_entry->address == cia) {\n");
    812  1.1  christos       lf_putstr(file, "  /* cache hit */\n");
    813  1.1  christos       lf_putstr(file, "  idecode_semantic *const semantic = cache_entry->semantic;\n");
    814  1.1  christos       lf_putstr(file, "  cia = semantic(processor, cache_entry, cia);\n");
    815  1.1  christos       /* tail */
    816  1.1  christos       if (can_stop) {
    817  1.1  christos 	lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
    818  1.1  christos 	lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
    819  1.1  christos       }
    820  1.1  christos       lf_putstr(file, "}\n");
    821  1.1  christos       lf_putstr(file, "else {\n");
    822  1.1  christos       lf_putstr(file, "  /* cache miss */\n");
    823  1.1  christos       if (!(code & generate_with_semantic_icache)) {
    824  1.1  christos 	lf_indent(file, +2);
    825  1.1  christos 	lf_putstr(file, "idecode_semantic *semantic;\n");
    826  1.1  christos 	lf_indent(file, -2);
    827  1.1  christos       }
    828  1.1  christos       lf_putstr(file, "  instruction_word instruction =\n");
    829  1.1  christos       lf_putstr(file, "    vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
    830  1.1  christos       lf_putstr(file, "  if (WITH_MON != 0)\n");
    831  1.1  christos       lf_putstr(file, "    mon_event(mon_event_icache_miss, processor, cia);\n");
    832  1.1  christos       if ((code & generate_with_semantic_icache)) {
    833  1.1  christos 	lf_putstr(file, "{\n");
    834  1.1  christos 	lf_indent(file, +2);
    835  1.1  christos 	print_idecode_body(file, table, "cia =");
    836  1.1  christos 	lf_indent(file, -2);
    837  1.1  christos 	lf_putstr(file, "}\n");
    838  1.1  christos       }
    839  1.1  christos       else {
    840  1.1  christos 	print_idecode_body(file, table, "semantic =");
    841  1.1  christos 	lf_putstr(file, "  cia = semantic(processor, cache_entry, cia);\n");
    842  1.1  christos       }
    843  1.1  christos       lf_putstr(file, "}\n");
    844  1.1  christos     }
    845  1.1  christos 
    846  1.1  christos     /* events */
    847  1.1  christos     lf_putstr(file, "\n");
    848  1.1  christos     lf_putstr(file, "/* process any events */\n");
    849  1.1  christos     lf_putstr(file, "if (WITH_EVENTS) {\n");
    850  1.1  christos     lf_putstr(file, "  if (event_queue_tick(events)) {\n");
    851  1.1  christos     lf_putstr(file, "    cpu_set_program_counter(processor, cia);\n");
    852  1.1  christos     lf_putstr(file, "    event_queue_process(events);\n");
    853  1.1  christos     lf_putstr(file, "    cia = cpu_get_program_counter(processor);\n");
    854  1.1  christos     lf_putstr(file, "  }\n");
    855  1.1  christos     lf_putstr(file, "}\n");
    856  1.1  christos 
    857  1.1  christos     /* tail */
    858  1.1  christos     if (can_stop) {
    859  1.1  christos       lf_putstr(file, "\n");
    860  1.1  christos       lf_putstr(file, "/* abort if necessary */\n");
    861  1.1  christos       lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
    862  1.1  christos       lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*not important*/);\n");
    863  1.1  christos     }
    864  1.1  christos 
    865  1.1  christos     lf_indent(file, -2);
    866  1.1  christos     lf_putstr(file, "}\n");
    867  1.1  christos   }
    868  1.1  christos 
    869  1.1  christos   if (generate_smp) {
    870  1.1  christos 
    871  1.1  christos     lf_putstr(file, "\n\
    872  1.1  christos /* CASE 2: SMP (With or without ICACHE)\n\
    873  1.1  christos \n\
    874  1.1  christos    The complexity here comes from needing to correctly restart the\n\
    875  1.1  christos    system when it is aborted.  In particular if cpu0 requests a\n\
    876  1.1  christos    restart, the next cpu is still cpu1.  Cpu0 being restarted after\n\
    877  1.1  christos    all the other CPU's and the event queue have been processed */");
    878  1.1  christos 
    879  1.1  christos     lf_putstr(file, "\n");
    880  1.1  christos 
    881  1.1  christos     lf_putstr(file, "\n");
    882  1.1  christos     lf_putstr(file, "/* now establish the restart target */\n");
    883  1.1  christos     lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
    884  1.1  christos     lf_putstr(file, "if (setjmp(restart)) {\n");
    885  1.1  christos     lf_putstr(file, "  current_cpu = psim_last_cpu(system);\n");
    886  1.1  christos     lf_putstr(file, "  ASSERT(current_cpu >= 0 && current_cpu < nr_cpus);\n");
    887  1.1  christos     lf_putstr(file, "}\n");
    888  1.1  christos     lf_putstr(file, "else {\n");
    889  1.1  christos     lf_putstr(file, "  current_cpu = last_cpu;\n");
    890  1.1  christos     lf_putstr(file, "  ASSERT(current_cpu >= -1 && current_cpu < nr_cpus);\n");
    891  1.1  christos     lf_putstr(file, "}\n");
    892  1.1  christos 
    893  1.1  christos 
    894  1.1  christos     lf_putstr(file, "\n");
    895  1.1  christos     lf_putstr(file, "while (1) {\n");
    896  1.1  christos     lf_indent(file, +2);
    897  1.1  christos 
    898  1.1  christos     lf_putstr(file, "\n");
    899  1.1  christos     lf_putstr(file, "if (WITH_EVENTS) {\n");
    900  1.1  christos     lf_putstr(file, "  current_cpu += 1;\n");
    901  1.1  christos     lf_putstr(file, "  if (current_cpu == nr_cpus) {\n");
    902  1.1  christos     lf_putstr(file, "    if (event_queue_tick(events)) {\n");
    903  1.1  christos     lf_putstr(file, "      event_queue_process(events);\n");
    904  1.1  christos     lf_putstr(file, "    }\n");
    905  1.1  christos     lf_putstr(file, "    current_cpu = 0;\n");
    906  1.1  christos     lf_putstr(file, "  }\n");
    907  1.1  christos     lf_putstr(file, "}\n");
    908  1.1  christos     lf_putstr(file, "else {\n");
    909  1.1  christos     lf_putstr(file, "  current_cpu = (current_cpu + 1) % nr_cpus;\n");
    910  1.1  christos     lf_putstr(file, "}\n");
    911  1.1  christos 
    912  1.1  christos     lf_putstr(file, "\n");
    913  1.1  christos     lf_putstr(file, "{\n");
    914  1.1  christos     lf_indent(file, +2);
    915  1.1  christos     lf_putstr(file, "cpu *processor = processors[current_cpu];\n");
    916  1.1  christos     lf_putstr(file, "unsigned_word cia =\n");
    917  1.1  christos     lf_putstr(file, "  cpu_get_program_counter(processor);\n");
    918  1.1  christos 
    919  1.1  christos     if (!(code & generate_with_icache)) {
    920  1.1  christos       lf_putstr(file, "instruction_word instruction =\n");
    921  1.1  christos       lf_putstr(file, "  vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
    922  1.1  christos       print_idecode_body(file, table, "cia =");
    923  1.1  christos       if (can_stop) {
    924  1.1  christos 	lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
    925  1.1  christos 	lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore*/);\n");
    926  1.1  christos       }
    927  1.1  christos       lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
    928  1.1  christos     }
    929  1.1  christos 
    930  1.1  christos     if ((code & generate_with_icache)) {
    931  1.1  christos       lf_putstr(file, "idecode_cache *cache_entry =\n");
    932  1.1  christos       lf_putstr(file, "  cpu_icache_entry(processor, cia);\n");
    933  1.1  christos       lf_putstr(file, "\n");
    934  1.1  christos       lf_putstr(file, "if (cache_entry->address == cia) {\n");
    935  1.1  christos       {
    936  1.1  christos 	lf_indent(file, +2);
    937  1.1  christos 	lf_putstr(file, "\n");
    938  1.1  christos 	lf_putstr(file, "/* cache hit */\n");
    939  1.1  christos 	lf_putstr(file, "idecode_semantic *semantic = cache_entry->semantic;\n");
    940  1.1  christos 	lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n");
    941  1.1  christos 	/* tail */
    942  1.1  christos 	if (can_stop) {
    943  1.1  christos 	  lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
    944  1.1  christos 	  lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore-signal*/);\n");
    945  1.1  christos 	}
    946  1.1  christos 	lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
    947  1.1  christos 	lf_putstr(file, "\n");
    948  1.1  christos 	lf_indent(file, -2);
    949  1.1  christos       }
    950  1.1  christos       lf_putstr(file, "}\n");
    951  1.1  christos       lf_putstr(file, "else {\n");
    952  1.1  christos       {
    953  1.1  christos 	lf_indent(file, +2);
    954  1.1  christos 	lf_putstr(file, "\n");
    955  1.1  christos 	lf_putstr(file, "/* cache miss */\n");
    956  1.1  christos 	if (!(code & generate_with_semantic_icache)) {
    957  1.1  christos 	  lf_putstr(file, "idecode_semantic *semantic;\n");
    958  1.1  christos 	}
    959  1.1  christos 	lf_putstr(file, "instruction_word instruction =\n");
    960  1.1  christos 	lf_putstr(file, "  vm_instruction_map_read(cpu_instruction_map(processor), processor, cia);\n");
    961  1.1  christos 	lf_putstr(file, "if (WITH_MON != 0)\n");
    962  1.1  christos 	lf_putstr(file, "  mon_event(mon_event_icache_miss, processors[current_cpu], cia);\n");
    963  1.1  christos 	if ((code & generate_with_semantic_icache)) {
    964  1.1  christos 	  lf_putstr(file, "{\n");
    965  1.1  christos 	  lf_indent(file, +2);
    966  1.1  christos 	  print_idecode_body(file, table, "cia =");
    967  1.1  christos 	  lf_indent(file, -2);
    968  1.1  christos 	  lf_putstr(file, "}\n");
    969  1.1  christos 	}
    970  1.1  christos 	else {
    971  1.1  christos 	  print_idecode_body(file, table, "semantic = ");
    972  1.1  christos 	  lf_putstr(file, "cia = semantic(processor, cache_entry, cia);\n");
    973  1.1  christos 	}
    974  1.1  christos 	/* tail */
    975  1.1  christos 	if (can_stop) {
    976  1.1  christos 	  lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
    977  1.1  christos 	  lf_putstr(file, "  cpu_halt(processor, cia, was_continuing, 0/*ignore-signal*/);\n");
    978  1.1  christos 	}
    979  1.1  christos 	lf_putstr(file, "cpu_set_program_counter(processor, cia);\n");
    980  1.1  christos 	lf_putstr(file, "\n");
    981  1.1  christos 	lf_indent(file, -2);
    982  1.1  christos       }
    983  1.1  christos       lf_putstr(file, "}\n");
    984  1.1  christos     }
    985  1.1  christos 
    986  1.1  christos     /* close */
    987  1.1  christos     lf_indent(file, -2);
    988  1.1  christos     lf_putstr(file, "}\n");
    989  1.1  christos 
    990  1.1  christos     /* tail */
    991  1.1  christos     lf_indent(file, -2);
    992  1.1  christos     lf_putstr(file, "}\n");
    993  1.1  christos   }
    994  1.1  christos 
    995  1.1  christos 
    996  1.1  christos   lf_indent(file, -2);
    997  1.1  christos   lf_putstr(file, "}\n");
    998  1.1  christos }
    999  1.1  christos 
   1000  1.1  christos 
   1001  1.1  christos /****************************************************************/
   1002  1.1  christos 
   1003  1.1  christos static void
   1004  1.1  christos print_jump(lf *file,
   1005  1.1  christos 	   int is_tail)
   1006  1.1  christos {
   1007  1.1  christos   if (is_tail) {
   1008  1.1  christos     lf_putstr(file, "if (keep_running != NULL && !*keep_running)\n");
   1009  1.1  christos     lf_putstr(file, "  cpu_halt(processor, nia, was_continuing, 0/*na*/);\n");
   1010  1.1  christos   }
   1011  1.1  christos 
   1012  1.1  christos   if (!generate_smp) {
   1013  1.1  christos     lf_putstr(file, "if (WITH_EVENTS) {\n");
   1014  1.1  christos     lf_putstr(file, "  if (event_queue_tick(events)) {\n");
   1015  1.1  christos     lf_putstr(file, "    cpu_set_program_counter(processor, nia);\n");
   1016  1.1  christos     lf_putstr(file, "    event_queue_process(events);\n");
   1017  1.1  christos     lf_putstr(file, "    nia = cpu_get_program_counter(processor);\n");
   1018  1.1  christos     lf_putstr(file, "  }\n");
   1019  1.1  christos     lf_putstr(file, "}\n");
   1020  1.1  christos   }
   1021  1.1  christos 
   1022  1.1  christos   if (generate_smp) {
   1023  1.1  christos     if (is_tail)
   1024  1.1  christos       lf_putstr(file, "cpu_set_program_counter(processor, nia);\n");
   1025  1.1  christos     lf_putstr(file, "if (WITH_EVENTS) {\n");
   1026  1.1  christos     lf_putstr(file, "  current_cpu += 1;\n");
   1027  1.1  christos     lf_putstr(file, "  if (current_cpu >= nr_cpus) {\n");
   1028  1.1  christos     lf_putstr(file, "    if (event_queue_tick(events)) {\n");
   1029  1.1  christos     lf_putstr(file, "      event_queue_process(events);\n");
   1030  1.1  christos     lf_putstr(file, "    }\n");
   1031  1.1  christos     lf_putstr(file, "    current_cpu = 0;\n");
   1032  1.1  christos     lf_putstr(file, "  }\n");
   1033  1.1  christos     lf_putstr(file, "}\n");
   1034  1.1  christos     lf_putstr(file, "else {\n");
   1035  1.1  christos     lf_putstr(file, "  current_cpu = (current_cpu + 1) % nr_cpus;\n");
   1036  1.1  christos     lf_putstr(file, "}\n");
   1037  1.1  christos     lf_putstr(file, "processor = processors[current_cpu];\n");
   1038  1.1  christos     lf_putstr(file, "nia = cpu_get_program_counter(processor);\n");
   1039  1.1  christos   }
   1040  1.1  christos 
   1041  1.1  christos   if ((code & generate_with_icache)) {
   1042  1.1  christos     lf_putstr(file, "cache_entry = cpu_icache_entry(processor, nia);\n");
   1043  1.1  christos     lf_putstr(file, "if (cache_entry->address == nia) {\n");
   1044  1.1  christos     lf_putstr(file, "  /* cache hit */\n");
   1045  1.1  christos     lf_putstr(file, "  goto *cache_entry->semantic;\n");
   1046  1.1  christos     lf_putstr(file, "}\n");
   1047  1.1  christos     if (is_tail) {
   1048  1.1  christos       lf_putstr(file, "goto cache_miss;\n");
   1049  1.1  christos     }
   1050  1.1  christos   }
   1051  1.1  christos 
   1052  1.1  christos   if (!(code & generate_with_icache) && is_tail) {
   1053  1.1  christos     lf_printf(file, "goto idecode;\n");
   1054  1.1  christos   }
   1055  1.1  christos 
   1056  1.1  christos }
   1057  1.1  christos 
   1058  1.1  christos 
   1059  1.1  christos 
   1060  1.1  christos 
   1061  1.1  christos 
   1062  1.1  christos static void
   1063  1.1  christos print_jump_insn(lf *file,
   1064  1.1  christos 		insn *instruction,
   1065  1.1  christos 		insn_bits *expanded_bits,
   1066  1.1  christos 		opcode_field *opcodes,
   1067  1.1  christos 		cache_table *cache_rules)
   1068  1.1  christos {
   1069  1.1  christos 
   1070  1.1  christos   /* what we are for the moment */
   1071  1.1  christos   lf_printf(file, "\n");
   1072  1.1  christos   print_my_defines(file, expanded_bits, instruction->file_entry);
   1073  1.1  christos 
   1074  1.1  christos   /* output the icache entry */
   1075  1.1  christos   if ((code & generate_with_icache)) {
   1076  1.1  christos     lf_printf(file, "\n");
   1077  1.1  christos     lf_indent(file, -1);
   1078  1.1  christos     print_function_name(file,
   1079  1.1  christos 			instruction->file_entry->fields[insn_name],
   1080  1.1  christos 			expanded_bits,
   1081  1.1  christos 			function_name_prefix_icache);
   1082  1.1  christos     lf_printf(file, ":\n");
   1083  1.1  christos     lf_indent(file, +1);
   1084  1.1  christos     lf_printf(file, "{\n");
   1085  1.1  christos     lf_indent(file, +2);
   1086  1.1  christos     lf_putstr(file, "const unsigned_word cia = nia;\n");
   1087  1.1  christos     print_itrace(file, instruction->file_entry, 1/*putting-value-in-cache*/);
   1088  1.1  christos     print_idecode_validate(file, instruction, opcodes);
   1089  1.1  christos     lf_printf(file, "\n");
   1090  1.1  christos     lf_printf(file, "{\n");
   1091  1.1  christos     lf_indent(file, +2);
   1092  1.1  christos     print_icache_body(file,
   1093  1.1  christos 		      instruction,
   1094  1.1  christos 		      expanded_bits,
   1095  1.1  christos 		      cache_rules,
   1096  1.1  christos 		      0, /*use_defines*/
   1097  1.1  christos 		      put_values_in_icache);
   1098  1.1  christos     lf_printf(file, "cache_entry->address = nia;\n");
   1099  1.1  christos     lf_printf(file, "cache_entry->semantic = &&");
   1100  1.1  christos     print_function_name(file,
   1101  1.1  christos 			instruction->file_entry->fields[insn_name],
   1102  1.1  christos 			expanded_bits,
   1103  1.1  christos 			function_name_prefix_semantics);
   1104  1.1  christos     lf_printf(file, ";\n");
   1105  1.1  christos     if ((code & generate_with_semantic_icache)) {
   1106  1.1  christos       print_semantic_body(file,
   1107  1.1  christos 			  instruction,
   1108  1.1  christos 			  expanded_bits,
   1109  1.1  christos 			  opcodes);
   1110  1.1  christos       print_jump(file, 1/*is-tail*/);
   1111  1.1  christos     }
   1112  1.1  christos     else {
   1113  1.1  christos       lf_printf(file, "/* goto ");
   1114  1.1  christos       print_function_name(file,
   1115  1.1  christos 			  instruction->file_entry->fields[insn_name],
   1116  1.1  christos 			  expanded_bits,
   1117  1.1  christos 			  function_name_prefix_semantics);
   1118  1.1  christos       lf_printf(file, "; */\n");
   1119  1.1  christos     }
   1120  1.1  christos     lf_indent(file, -2);
   1121  1.1  christos     lf_putstr(file, "}\n");
   1122  1.1  christos     lf_indent(file, -2);
   1123  1.1  christos     lf_printf(file, "}\n");
   1124  1.1  christos   }
   1125  1.1  christos 
   1126  1.1  christos   /* print the semantics */
   1127  1.1  christos   lf_printf(file, "\n");
   1128  1.1  christos   lf_indent(file, -1);
   1129  1.1  christos   print_function_name(file,
   1130  1.1  christos 		      instruction->file_entry->fields[insn_name],
   1131  1.1  christos 		      expanded_bits,
   1132  1.1  christos 		      function_name_prefix_semantics);
   1133  1.1  christos   lf_printf(file, ":\n");
   1134  1.1  christos   lf_indent(file, +1);
   1135  1.1  christos   lf_printf(file, "{\n");
   1136  1.1  christos   lf_indent(file, +2);
   1137  1.1  christos   lf_putstr(file, "const unsigned_word cia = nia;\n");
   1138  1.1  christos   print_icache_body(file,
   1139  1.1  christos 		    instruction,
   1140  1.1  christos 		    expanded_bits,
   1141  1.1  christos 		    cache_rules,
   1142  1.1  christos 		    ((code & generate_with_direct_access)
   1143  1.1  christos 		     ? define_variables
   1144  1.1  christos 		     : declare_variables),
   1145  1.1  christos 		    ((code & generate_with_icache)
   1146  1.1  christos 		     ? get_values_from_icache
   1147  1.1  christos 		     : do_not_use_icache));
   1148  1.1  christos   print_semantic_body(file,
   1149  1.1  christos 		      instruction,
   1150  1.1  christos 		      expanded_bits,
   1151  1.1  christos 		      opcodes);
   1152  1.1  christos   if (code & generate_with_direct_access)
   1153  1.1  christos     print_icache_body(file,
   1154  1.1  christos 		      instruction,
   1155  1.1  christos 		      expanded_bits,
   1156  1.1  christos 		      cache_rules,
   1157  1.1  christos 		      undef_variables,
   1158  1.1  christos 		      ((code & generate_with_icache)
   1159  1.1  christos 		       ? get_values_from_icache
   1160  1.1  christos 		       : do_not_use_icache));
   1161  1.1  christos   print_jump(file, 1/*is tail*/);
   1162  1.1  christos   lf_indent(file, -2);
   1163  1.1  christos   lf_printf(file, "}\n");
   1164  1.1  christos }
   1165  1.1  christos 
   1166  1.1  christos static void
   1167  1.1  christos print_jump_definition(insn_table *entry,
   1168  1.1  christos 		      lf *file,
   1169  1.1  christos 		      void *data,
   1170  1.1  christos 		      insn *instruction,
   1171  1.1  christos 		      int depth)
   1172  1.1  christos {
   1173  1.1  christos   cache_table *cache_rules = (cache_table*)data;
   1174  1.1  christos   if (generate_expanded_instructions) {
   1175  1.1  christos     ASSERT(entry->nr_insn == 1
   1176  1.1  christos 	   && entry->opcode == NULL
   1177  1.1  christos 	   && entry->parent != NULL
   1178  1.1  christos 	   && entry->parent->opcode != NULL);
   1179  1.1  christos     ASSERT(entry->nr_insn == 1
   1180  1.1  christos 	   && entry->opcode == NULL
   1181  1.1  christos 	   && entry->parent != NULL
   1182  1.1  christos 	   && entry->parent->opcode != NULL
   1183  1.1  christos 	   && entry->parent->opcode_rule != NULL);
   1184  1.1  christos     print_jump_insn(file,
   1185  1.1  christos 		    entry->insns,
   1186  1.1  christos 		    entry->expanded_bits,
   1187  1.1  christos 		    entry->opcode,
   1188  1.1  christos 		    cache_rules);
   1189  1.1  christos   }
   1190  1.1  christos   else {
   1191  1.1  christos     print_jump_insn(file,
   1192  1.1  christos 		    instruction,
   1193  1.1  christos 		    NULL,
   1194  1.1  christos 		    NULL,
   1195  1.1  christos 		    cache_rules);
   1196  1.1  christos   }
   1197  1.1  christos }
   1198  1.1  christos 
   1199  1.1  christos 
   1200  1.1  christos static void
   1201  1.1  christos print_jump_internal_function(insn_table *table,
   1202  1.1  christos 			     lf *file,
   1203  1.1  christos 			     void *data,
   1204  1.1  christos 			     table_entry *function)
   1205  1.1  christos {
   1206  1.1  christos   if (it_is("internal", function->fields[insn_flags])) {
   1207  1.1  christos     lf_printf(file, "\n");
   1208  1.1  christos     table_entry_print_cpp_line_nr(file, function);
   1209  1.1  christos     lf_indent(file, -1);
   1210  1.1  christos     print_function_name(file,
   1211  1.1  christos 			function->fields[insn_name],
   1212  1.1  christos 			NULL,
   1213  1.1  christos 			((code & generate_with_icache)
   1214  1.1  christos 			 ? function_name_prefix_icache
   1215  1.1  christos 			 : function_name_prefix_semantics));
   1216  1.1  christos     lf_printf(file, ":\n");
   1217  1.1  christos     lf_indent(file, +1);
   1218  1.1  christos     lf_printf(file, "{\n");
   1219  1.1  christos     lf_indent(file, +2);
   1220  1.1  christos     lf_printf(file, "const unsigned_word cia = nia;\n");
   1221  1.1  christos     lf_print__c_code(file, function->annex);
   1222  1.6  christos     lf_print__internal_ref(file);
   1223  1.1  christos     lf_printf(file, "error(\"Internal function must longjump\\n\");\n");
   1224  1.1  christos     lf_indent(file, -2);
   1225  1.1  christos     lf_printf(file, "}\n");
   1226  1.1  christos   }
   1227  1.1  christos }
   1228  1.1  christos 
   1229  1.1  christos static void
   1230  1.1  christos print_jump_until_stop_body(lf *file,
   1231  1.1  christos 			   insn_table *table,
   1232  1.1  christos 			   cache_table *cache_rules,
   1233  1.1  christos 			   int can_stop)
   1234  1.1  christos {
   1235  1.1  christos   lf_printf(file, "{\n");
   1236  1.1  christos   lf_indent(file, +2);
   1237  1.1  christos   if (!can_stop)
   1238  1.1  christos     lf_printf(file, "int *keep_running = NULL;\n");
   1239  1.1  christos   lf_putstr(file, "jmp_buf halt;\n");
   1240  1.1  christos   lf_putstr(file, "jmp_buf restart;\n");
   1241  1.1  christos   lf_putstr(file, "cpu *processor = NULL;\n");
   1242  1.1  christos   lf_putstr(file, "unsigned_word nia = -1;\n");
   1243  1.1  christos   lf_putstr(file, "instruction_word instruction = 0;\n");
   1244  1.1  christos   if ((code & generate_with_icache)) {
   1245  1.1  christos     lf_putstr(file, "idecode_cache *cache_entry = NULL;\n");
   1246  1.1  christos   }
   1247  1.1  christos   if (generate_smp) {
   1248  1.1  christos     lf_putstr(file, "int current_cpu = -1;\n");
   1249  1.1  christos   }
   1250  1.1  christos 
   1251  1.1  christos   /* all the switches and tables - they know about jumping */
   1252  1.1  christos   print_idecode_lookups(file, table, cache_rules);
   1253  1.1  christos 
   1254  1.1  christos   /* start the simulation up */
   1255  1.1  christos   if ((code & generate_with_icache)) {
   1256  1.1  christos     lf_putstr(file, "\n");
   1257  1.1  christos     lf_putstr(file, "{\n");
   1258  1.1  christos     lf_putstr(file, "  int cpu_nr;\n");
   1259  1.1  christos     lf_putstr(file, "  for (cpu_nr = 0; cpu_nr < nr_cpus; cpu_nr++)\n");
   1260  1.1  christos     lf_putstr(file, "    cpu_flush_icache(processors[cpu_nr]);\n");
   1261  1.1  christos     lf_putstr(file, "}\n");
   1262  1.1  christos   }
   1263  1.1  christos 
   1264  1.1  christos   lf_putstr(file, "\n");
   1265  1.1  christos   lf_putstr(file, "psim_set_halt_and_restart(system, &halt, &restart);\n");
   1266  1.1  christos 
   1267  1.1  christos   lf_putstr(file, "\n");
   1268  1.1  christos   lf_putstr(file, "if (setjmp(halt))\n");
   1269  1.1  christos   lf_putstr(file, "  return;\n");
   1270  1.1  christos 
   1271  1.1  christos   lf_putstr(file, "\n");
   1272  1.1  christos   lf_putstr(file, "setjmp(restart);\n");
   1273  1.1  christos 
   1274  1.1  christos   lf_putstr(file, "\n");
   1275  1.1  christos   if (!generate_smp) {
   1276  1.1  christos     lf_putstr(file, "processor = processors[0];\n");
   1277  1.1  christos     lf_putstr(file, "nia = cpu_get_program_counter(processor);\n");
   1278  1.1  christos   }
   1279  1.1  christos   else {
   1280  1.1  christos     lf_putstr(file, "current_cpu = psim_last_cpu(system);\n");
   1281  1.1  christos   }
   1282  1.1  christos 
   1283  1.1  christos   if (!(code & generate_with_icache)) {
   1284  1.1  christos     lf_printf(file, "\n");
   1285  1.1  christos     lf_indent(file, -1);
   1286  1.1  christos     lf_printf(file, "idecode:\n");
   1287  1.1  christos     lf_indent(file, +1);
   1288  1.1  christos   }
   1289  1.1  christos 
   1290  1.1  christos   print_jump(file, 0/*is_tail*/);
   1291  1.1  christos 
   1292  1.1  christos   if ((code & generate_with_icache)) {
   1293  1.1  christos     lf_indent(file, -1);
   1294  1.1  christos     lf_printf(file, "cache_miss:\n");
   1295  1.1  christos     lf_indent(file, +1);
   1296  1.1  christos   }
   1297  1.1  christos 
   1298  1.1  christos   lf_putstr(file, "instruction\n");
   1299  1.1  christos   lf_putstr(file, "  = vm_instruction_map_read(cpu_instruction_map(processor),\n");
   1300  1.1  christos   lf_putstr(file, "                            processor, nia);\n");
   1301  1.1  christos   print_idecode_body(file, table, "/*IGORE*/");
   1302  1.1  christos 
   1303  1.1  christos   /* print out a table of all the internals functions */
   1304  1.1  christos   insn_table_traverse_function(table,
   1305  1.1  christos 			       file, NULL,
   1306  1.1  christos 			       print_jump_internal_function);
   1307  1.1  christos 
   1308  1.1  christos  /* print out a table of all the instructions */
   1309  1.1  christos   if (generate_expanded_instructions)
   1310  1.1  christos     insn_table_traverse_tree(table,
   1311  1.1  christos 			     file, cache_rules,
   1312  1.1  christos 			     1,
   1313  1.1  christos 			     NULL, /* start */
   1314  1.1  christos 			     print_jump_definition, /* leaf */
   1315  1.1  christos 			     NULL, /* end */
   1316  1.1  christos 			     NULL); /* padding */
   1317  1.1  christos   else
   1318  1.1  christos     insn_table_traverse_insn(table,
   1319  1.1  christos 			     file, cache_rules,
   1320  1.1  christos 			     print_jump_definition);
   1321  1.1  christos   lf_indent(file, -2);
   1322  1.1  christos   lf_printf(file, "}\n");
   1323  1.1  christos }
   1324  1.1  christos 
   1325  1.1  christos 
   1326  1.1  christos /****************************************************************/
   1327  1.1  christos 
   1328  1.1  christos 
   1329  1.1  christos 
   1330  1.1  christos static void
   1331  1.1  christos print_idecode_floating_point_unavailable(lf *file)
   1332  1.1  christos {
   1333  1.1  christos   if ((code & generate_jumps))
   1334  1.1  christos     lf_printf(file, "goto %s_floating_point_unavailable;\n", (code & generate_with_icache) ? "icache" : "semantic");
   1335  1.1  christos   else if ((code & generate_with_icache))
   1336  1.1  christos     lf_printf(file, "return icache_floating_point_unavailable(%s);\n",
   1337  1.1  christos 	      ICACHE_FUNCTION_ACTUAL);
   1338  1.1  christos   else
   1339  1.1  christos     lf_printf(file, "return semantic_floating_point_unavailable(%s);\n",
   1340  1.1  christos 	      SEMANTIC_FUNCTION_ACTUAL);
   1341  1.1  christos }
   1342  1.1  christos 
   1343  1.1  christos 
   1344  1.1  christos /* Output code to do any final checks on the decoded instruction.
   1345  1.1  christos    This includes things like verifying any on decoded fields have the
   1346  1.1  christos    correct value and checking that (for floating point) floating point
   1347  1.1  christos    hardware isn't disabled */
   1348  1.1  christos 
   1349  1.1  christos void
   1350  1.1  christos print_idecode_validate(lf *file,
   1351  1.1  christos 		       insn *instruction,
   1352  1.1  christos 		       opcode_field *opcodes)
   1353  1.1  christos {
   1354  1.1  christos   /* Validate: unchecked instruction fields
   1355  1.1  christos 
   1356  1.1  christos      If any constant fields in the instruction were not checked by the
   1357  1.1  christos      idecode tables, output code to check that they have the correct
   1358  1.1  christos      value here */
   1359  1.1  christos   {
   1360  1.1  christos     unsigned check_mask = 0;
   1361  1.1  christos     unsigned check_val = 0;
   1362  1.1  christos     insn_field *field;
   1363  1.1  christos     opcode_field *opcode;
   1364  1.1  christos 
   1365  1.1  christos     /* form check_mask/check_val containing what needs to be checked
   1366  1.1  christos        in the instruction */
   1367  1.1  christos     for (field = instruction->fields->first;
   1368  1.1  christos 	 field->first < insn_bit_size;
   1369  1.1  christos 	 field = field->next) {
   1370  1.1  christos 
   1371  1.1  christos       check_mask <<= field->width;
   1372  1.1  christos       check_val <<= field->width;
   1373  1.1  christos 
   1374  1.1  christos       /* is it a constant that could need validating? */
   1375  1.1  christos       if (!field->is_int && !field->is_slash)
   1376  1.1  christos 	continue;
   1377  1.1  christos 
   1378  1.1  christos       /* has it been checked by a table? */
   1379  1.1  christos       for (opcode = opcodes; opcode != NULL; opcode = opcode->parent) {
   1380  1.1  christos 	if (field->first >= opcode->first
   1381  1.1  christos 	    && field->last <= opcode->last)
   1382  1.1  christos 	  break;
   1383  1.1  christos       }
   1384  1.1  christos       if (opcode != NULL)
   1385  1.1  christos 	continue;
   1386  1.1  christos 
   1387  1.1  christos       check_mask |= (1 << field->width)-1;
   1388  1.1  christos       check_val |= field->val_int;
   1389  1.1  christos     }
   1390  1.1  christos 
   1391  1.1  christos     /* if any bits not checked by opcode tables, output code to check them */
   1392  1.1  christos     if (check_mask) {
   1393  1.1  christos       lf_printf(file, "\n");
   1394  1.1  christos       lf_printf(file, "/* validate: %s */\n",
   1395  1.1  christos 		instruction->file_entry->fields[insn_format]);
   1396  1.1  christos       lf_printf(file, "if (WITH_RESERVED_BITS && (instruction & 0x%x) != 0x%x)\n",
   1397  1.1  christos 		check_mask, check_val);
   1398  1.1  christos       lf_indent(file, +2);
   1399  1.1  christos       print_idecode_illegal(file, "return");
   1400  1.1  christos       lf_indent(file, -2);
   1401  1.1  christos     }
   1402  1.1  christos   }
   1403  1.1  christos 
   1404  1.1  christos   /* Validate floating point hardware
   1405  1.1  christos 
   1406  1.1  christos      If the simulator is being built with out floating point hardware
   1407  1.1  christos      (different to it being disabled in the MSR) then floating point
   1408  1.1  christos      instructions are invalid */
   1409  1.1  christos   {
   1410  1.1  christos     if (it_is("f", instruction->file_entry->fields[insn_flags])) {
   1411  1.1  christos       lf_printf(file, "\n");
   1412  1.1  christos       lf_printf(file, "/* Validate: FP hardware exists */\n");
   1413  1.1  christos       lf_printf(file, "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT)\n");
   1414  1.1  christos       lf_indent(file, +2);
   1415  1.1  christos       print_idecode_illegal(file, "return");
   1416  1.1  christos       lf_indent(file, -2);
   1417  1.1  christos     }
   1418  1.1  christos   }
   1419  1.1  christos 
   1420  1.1  christos   /* Validate: Floating Point available
   1421  1.1  christos 
   1422  1.1  christos      If floating point is not available, we enter a floating point
   1423  1.1  christos      unavailable interrupt into the cache instead of the instruction
   1424  1.1  christos      proper.
   1425  1.1  christos 
   1426  1.1  christos      The PowerPC spec requires a CSI after MSR[FP] is changed and when
   1427  1.1  christos      ever a CSI occures we flush the instruction cache. */
   1428  1.1  christos 
   1429  1.1  christos   {
   1430  1.1  christos     if (it_is("f", instruction->file_entry->fields[insn_flags])) {
   1431  1.1  christos       lf_printf(file, "\n");
   1432  1.1  christos       lf_printf(file, "/* Validate: FP available according to MSR[FP] */\n");
   1433  1.1  christos       lf_printf(file, "if (!IS_FP_AVAILABLE(processor))\n");
   1434  1.1  christos       lf_indent(file, +2);
   1435  1.1  christos       print_idecode_floating_point_unavailable(file);
   1436  1.1  christos       lf_indent(file, -2);
   1437  1.1  christos     }
   1438  1.1  christos   }
   1439  1.1  christos }
   1440  1.1  christos 
   1441  1.1  christos 
   1442  1.1  christos /****************************************************************/
   1443  1.1  christos 
   1444  1.1  christos 
   1445  1.1  christos static void
   1446  1.1  christos print_idecode_run_function_header(lf *file,
   1447  1.1  christos 				  int can_stop,
   1448  1.1  christos 				  int is_definition)
   1449  1.1  christos {
   1450  1.1  christos   int indent;
   1451  1.1  christos   lf_printf(file, "\n");
   1452  1.6  christos   lf_print__function_type(file, "void", "PSIM_INLINE_IDECODE", (is_definition ? " " : "\n"));
   1453  1.1  christos   indent = lf_putstr(file, (can_stop ? "idecode_run_until_stop" : "idecode_run"));
   1454  1.1  christos   if (is_definition)
   1455  1.1  christos     lf_putstr(file, "\n");
   1456  1.1  christos   else
   1457  1.1  christos     lf_indent(file, +indent);
   1458  1.1  christos   lf_putstr(file, "(psim *system,\n");
   1459  1.1  christos   if (can_stop)
   1460  1.1  christos     lf_putstr(file, " volatile int *keep_running,\n");
   1461  1.1  christos   lf_printf(file, " event_queue *events,\n");
   1462  1.1  christos   lf_putstr(file, " cpu *const processors[],\n");
   1463  1.1  christos   lf_putstr(file, " const int nr_cpus)");
   1464  1.1  christos   if (is_definition)
   1465  1.1  christos     lf_putstr(file, ";");
   1466  1.1  christos   else
   1467  1.1  christos     lf_indent(file, -indent);
   1468  1.1  christos   lf_putstr(file, "\n");
   1469  1.1  christos }
   1470  1.1  christos 
   1471  1.1  christos 
   1472  1.1  christos void
   1473  1.1  christos gen_idecode_h(lf *file,
   1474  1.1  christos 	      insn_table *table,
   1475  1.1  christos 	      cache_table *cache_rules)
   1476  1.1  christos {
   1477  1.1  christos   lf_printf(file, "/* The idecode_*.h functions shall move to support */\n");
   1478  1.1  christos   lf_printf(file, "#include \"idecode_expression.h\"\n");
   1479  1.1  christos   lf_printf(file, "#include \"idecode_fields.h\"\n");
   1480  1.1  christos   lf_printf(file, "#include \"idecode_branch.h\"\n");
   1481  1.1  christos   lf_printf(file, "\n");
   1482  1.1  christos   print_icache_struct(table, cache_rules, file);
   1483  1.1  christos   lf_printf(file, "\n");
   1484  1.1  christos   lf_printf(file, "#define WITH_IDECODE_SMP %d\n", generate_smp);
   1485  1.1  christos   lf_printf(file, "\n");
   1486  1.1  christos   print_idecode_run_function_header(file, 0/*can stop*/, 1/*is definition*/);
   1487  1.1  christos   print_idecode_run_function_header(file, 1/*can stop*/, 1/*is definition*/);
   1488  1.1  christos }
   1489  1.1  christos 
   1490  1.1  christos 
   1491  1.1  christos void
   1492  1.1  christos gen_idecode_c(lf *file,
   1493  1.1  christos 	      insn_table *table,
   1494  1.1  christos 	      cache_table *cache_rules)
   1495  1.1  christos {
   1496  1.1  christos   /* the intro */
   1497  1.1  christos   lf_printf(file, "#include \"inline.c\"\n");
   1498  1.1  christos   lf_printf(file, "\n");
   1499  1.1  christos   lf_printf(file, "#include \"cpu.h\"\n");
   1500  1.1  christos   lf_printf(file, "#include \"idecode.h\"\n");
   1501  1.1  christos   lf_printf(file, "#include \"semantics.h\"\n");
   1502  1.1  christos   lf_printf(file, "#include \"icache.h\"\n");
   1503  1.1  christos   lf_printf(file, "#ifdef HAVE_COMMON_FPU\n");
   1504  1.1  christos   lf_printf(file, "#include \"sim-inline.h\"\n");
   1505  1.1  christos   lf_printf(file, "#include \"sim-fpu.h\"\n");
   1506  1.1  christos   lf_printf(file, "#endif\n");
   1507  1.1  christos   lf_printf(file, "#include \"support.h\"\n");
   1508  1.1  christos   lf_printf(file, "\n");
   1509  1.1  christos   lf_printf(file, "#include <setjmp.h>\n");
   1510  1.1  christos   lf_printf(file, "\n");
   1511  1.1  christos   lf_printf(file, "enum {\n");
   1512  1.1  christos   lf_printf(file, "  /* greater or equal to zero => table */\n");
   1513  1.1  christos   lf_printf(file, "  function_entry = -1,\n");
   1514  1.1  christos   lf_printf(file, "  boolean_entry = -2,\n");
   1515  1.1  christos   lf_printf(file, "};\n");
   1516  1.1  christos   lf_printf(file, "\n");
   1517  1.1  christos   lf_printf(file, "typedef struct _idecode_table_entry {\n");
   1518  1.1  christos   lf_printf(file, "  int shift;\n");
   1519  1.1  christos   lf_printf(file, "  instruction_word mask;\n");
   1520  1.1  christos   lf_printf(file, "  instruction_word value;");
   1521  1.1  christos   lf_printf(file, "  void *function_or_table;\n");
   1522  1.1  christos   lf_printf(file, "} idecode_table_entry;\n");
   1523  1.1  christos   lf_printf(file, "\n");
   1524  1.1  christos   lf_printf(file, "\n");
   1525  1.1  christos 
   1526  1.1  christos   if ((code & generate_calls)) {
   1527  1.1  christos 
   1528  1.1  christos     print_idecode_lookups(file, table, cache_rules);
   1529  1.1  christos 
   1530  1.1  christos     /* output the main idecode routine */
   1531  1.1  christos     print_idecode_run_function_header(file, 0/*can stop*/, 0/*is definition*/);
   1532  1.1  christos     print_run_until_stop_body(file, table, 0/* have stop argument */);
   1533  1.1  christos 
   1534  1.1  christos     print_idecode_run_function_header(file, 1/*can stop*/, 0/*is definition*/);
   1535  1.1  christos     print_run_until_stop_body(file, table, 1/* no stop argument */);
   1536  1.1  christos 
   1537  1.1  christos   }
   1538  1.1  christos   else if ((code & generate_jumps)) {
   1539  1.1  christos 
   1540  1.1  christos     print_idecode_run_function_header(file, 0/*can stop*/, 0/*is definition*/);
   1541  1.1  christos     print_jump_until_stop_body(file, table, cache_rules, 0 /* have stop argument */);
   1542  1.1  christos 
   1543  1.1  christos     print_idecode_run_function_header(file, 1/*can stop*/, 0/*is definition*/);
   1544  1.1  christos     print_jump_until_stop_body(file, table, cache_rules, 1/* have stop argument */);
   1545  1.1  christos 
   1546  1.1  christos   }
   1547  1.1  christos   else {
   1548  1.6  christos     ERROR("Something is wrong!\n");
   1549  1.1  christos   }
   1550  1.1  christos }
   1551