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