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