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 244e98e3e1Schristos #include "misc.h" 254e98e3e1Schristos #include "lf.h" 264e98e3e1Schristos #include "table.h" 274e98e3e1Schristos #include "filter.h" 284e98e3e1Schristos #include "igen.h" 294e98e3e1Schristos 304e98e3e1Schristos #include "ld-insn.h" 314e98e3e1Schristos #include "ld-decode.h" 324e98e3e1Schristos 334e98e3e1Schristos #include "gen.h" 344e98e3e1Schristos 354e98e3e1Schristos #include "gen-semantics.h" 364e98e3e1Schristos #include "gen-icache.h" 374e98e3e1Schristos #include "gen-idecode.h" 384e98e3e1Schristos 394e98e3e1Schristos 404e98e3e1Schristos static void 414e98e3e1Schristos print_semantic_function_header (lf *file, 424e98e3e1Schristos const char *basename, 434e98e3e1Schristos const char *format_name, 444b169a6bSchristos const opcode_bits *expanded_bits, 454e98e3e1Schristos int is_function_definition, 464e98e3e1Schristos int nr_prefetched_words) 474e98e3e1Schristos { 484e98e3e1Schristos int indent; 494e98e3e1Schristos lf_printf (file, "\n"); 504e98e3e1Schristos lf_print__function_type_function (file, print_semantic_function_type, 514e98e3e1Schristos "EXTERN_SEMANTICS", 524e98e3e1Schristos (is_function_definition ? "\n" : " ")); 534e98e3e1Schristos indent = print_function_name (file, 544e98e3e1Schristos basename, 554e98e3e1Schristos format_name, 564e98e3e1Schristos NULL, 574e98e3e1Schristos expanded_bits, 584e98e3e1Schristos function_name_prefix_semantics); 594e98e3e1Schristos if (is_function_definition) 604e98e3e1Schristos { 614e98e3e1Schristos indent += lf_printf (file, " "); 624e98e3e1Schristos lf_indent (file, +indent); 634e98e3e1Schristos } 644e98e3e1Schristos else 654e98e3e1Schristos { 664e98e3e1Schristos lf_printf (file, "\n"); 674e98e3e1Schristos } 684e98e3e1Schristos lf_printf (file, "("); 694e98e3e1Schristos lf_indent (file, +1); 704e98e3e1Schristos print_semantic_function_formal (file, nr_prefetched_words); 714e98e3e1Schristos lf_indent (file, -1); 724e98e3e1Schristos lf_printf (file, ")"); 734e98e3e1Schristos if (is_function_definition) 744e98e3e1Schristos { 754e98e3e1Schristos lf_indent (file, -indent); 764e98e3e1Schristos } 774e98e3e1Schristos else 784e98e3e1Schristos { 794e98e3e1Schristos lf_printf (file, ";"); 804e98e3e1Schristos } 814e98e3e1Schristos lf_printf (file, "\n"); 824e98e3e1Schristos } 834e98e3e1Schristos 844e98e3e1Schristos void 854e98e3e1Schristos print_semantic_declaration (lf *file, 864b169a6bSchristos const insn_entry *insn, 874b169a6bSchristos const opcode_bits *expanded_bits, 884b169a6bSchristos const insn_opcodes *opcodes, 894b169a6bSchristos int nr_prefetched_words) 904e98e3e1Schristos { 914e98e3e1Schristos print_semantic_function_header (file, 924e98e3e1Schristos insn->name, 934e98e3e1Schristos insn->format_name, 944e98e3e1Schristos expanded_bits, 954e98e3e1Schristos 0 /* is not function definition */ , 964e98e3e1Schristos nr_prefetched_words); 974e98e3e1Schristos } 984e98e3e1Schristos 994e98e3e1Schristos 1004e98e3e1Schristos 1014e98e3e1Schristos /* generate the semantics.c file */ 1024e98e3e1Schristos 1034e98e3e1Schristos 1044e98e3e1Schristos void 1054e98e3e1Schristos print_idecode_invalid (lf *file, const char *result, invalid_type type) 1064e98e3e1Schristos { 1074e98e3e1Schristos const char *name; 1084e98e3e1Schristos switch (type) 1094e98e3e1Schristos { 1104e98e3e1Schristos default: 1114e98e3e1Schristos name = "unknown"; 1124e98e3e1Schristos break; 1134e98e3e1Schristos case invalid_illegal: 1144e98e3e1Schristos name = "illegal"; 1154e98e3e1Schristos break; 1164e98e3e1Schristos case invalid_fp_unavailable: 1174e98e3e1Schristos name = "fp_unavailable"; 1184e98e3e1Schristos break; 1194e98e3e1Schristos case invalid_wrong_slot: 1204e98e3e1Schristos name = "wrong_slot"; 1214e98e3e1Schristos break; 1224e98e3e1Schristos } 1234e98e3e1Schristos if (options.gen.code == generate_jumps) 1244e98e3e1Schristos { 1254e98e3e1Schristos lf_printf (file, "goto %s_%s;\n", 1264e98e3e1Schristos (options.gen.icache ? "icache" : "semantic"), name); 1274e98e3e1Schristos } 1284e98e3e1Schristos else if (options.gen.icache) 1294e98e3e1Schristos { 1304e98e3e1Schristos lf_printf (file, "%s %sicache_%s (", result, 1314e98e3e1Schristos options.module.global.prefix.l, name); 1324e98e3e1Schristos print_icache_function_actual (file, 0); 1334e98e3e1Schristos lf_printf (file, ");\n"); 1344e98e3e1Schristos } 1354e98e3e1Schristos else 1364e98e3e1Schristos { 1374e98e3e1Schristos lf_printf (file, "%s %ssemantic_%s (", result, 1384e98e3e1Schristos options.module.global.prefix.l, name); 1394e98e3e1Schristos print_semantic_function_actual (file, 0); 1404e98e3e1Schristos lf_printf (file, ");\n"); 1414e98e3e1Schristos } 1424e98e3e1Schristos } 1434e98e3e1Schristos 1444e98e3e1Schristos 1454e98e3e1Schristos void 1464e98e3e1Schristos print_semantic_body (lf *file, 1474b169a6bSchristos const insn_entry *instruction, 1484b169a6bSchristos const opcode_bits *expanded_bits, 1494b169a6bSchristos const insn_opcodes *opcodes) 1504e98e3e1Schristos { 1514e98e3e1Schristos /* validate the instruction, if a cache this has already been done */ 1524e98e3e1Schristos if (!options.gen.icache) 1534e98e3e1Schristos { 1544e98e3e1Schristos print_idecode_validate (file, instruction, opcodes); 1554e98e3e1Schristos } 1564e98e3e1Schristos 1574e98e3e1Schristos print_itrace (file, instruction, 0 /*put_value_in_cache */ ); 1584e98e3e1Schristos 1594e98e3e1Schristos /* generate the instruction profile call - this is delayed until 1604e98e3e1Schristos after the instruction has been verified. The count macro 1614e98e3e1Schristos generated is prefixed by ITABLE_PREFIX */ 1624e98e3e1Schristos { 1634e98e3e1Schristos lf_printf (file, "\n"); 1644e98e3e1Schristos lf_indent_suppress (file); 1654e98e3e1Schristos lf_printf (file, "#if defined (%sPROFILE_COUNT_INSN)\n", 1664e98e3e1Schristos options.module.itable.prefix.u); 1674e98e3e1Schristos lf_printf (file, "%sPROFILE_COUNT_INSN (CPU, CIA, MY_INDEX);\n", 1684e98e3e1Schristos options.module.itable.prefix.u); 1694e98e3e1Schristos lf_indent_suppress (file); 1704e98e3e1Schristos lf_printf (file, "#endif\n"); 1714e98e3e1Schristos } 1724e98e3e1Schristos 1734e98e3e1Schristos /* generate the model call - this is delayed until after the 1744e98e3e1Schristos instruction has been verified */ 1754e98e3e1Schristos { 1764e98e3e1Schristos lf_printf (file, "\n"); 1774e98e3e1Schristos lf_indent_suppress (file); 1784e98e3e1Schristos lf_printf (file, "#if defined (WITH_MON)\n"); 1794e98e3e1Schristos lf_printf (file, "/* monitoring: */\n"); 1804e98e3e1Schristos lf_printf (file, "if (WITH_MON & MONITOR_INSTRUCTION_ISSUE)\n"); 1814e98e3e1Schristos lf_printf (file, " mon_issue ("); 1824e98e3e1Schristos print_function_name (file, 1834e98e3e1Schristos instruction->name, 1844e98e3e1Schristos instruction->format_name, 1854e98e3e1Schristos NULL, NULL, function_name_prefix_itable); 1864e98e3e1Schristos lf_printf (file, ", cpu, cia);\n"); 1874e98e3e1Schristos lf_indent_suppress (file); 1884e98e3e1Schristos lf_printf (file, "#endif\n"); 1894e98e3e1Schristos lf_printf (file, "\n"); 1904e98e3e1Schristos } 1914e98e3e1Schristos 1924e98e3e1Schristos /* determine the new instruction address */ 1934e98e3e1Schristos { 1944e98e3e1Schristos lf_printf (file, "/* keep the next instruction address handy */\n"); 1954e98e3e1Schristos if (options.gen.nia == nia_is_invalid) 1964e98e3e1Schristos { 1974e98e3e1Schristos lf_printf (file, "nia = %sINVALID_INSTRUCTION_ADDRESS;\n", 1984e98e3e1Schristos options.module.global.prefix.u); 1994e98e3e1Schristos } 2004e98e3e1Schristos else 2014e98e3e1Schristos { 2024e98e3e1Schristos int nr_immeds = instruction->nr_words - 1; 2034e98e3e1Schristos if (options.gen.delayed_branch) 2044e98e3e1Schristos { 2054e98e3e1Schristos if (nr_immeds > 0) 2064e98e3e1Schristos { 2074e98e3e1Schristos lf_printf (file, "cia.dp += %d * %d; %s\n", 2084e98e3e1Schristos options.insn_bit_size / 8, nr_immeds, 2094e98e3e1Schristos "/* skip dp immeds */"); 2104e98e3e1Schristos } 2114e98e3e1Schristos lf_printf (file, "nia.ip = cia.dp; %s\n", 2124e98e3e1Schristos "/* instruction pointer */"); 2134e98e3e1Schristos lf_printf (file, "nia.dp = cia.dp + %d; %s\n", 2144e98e3e1Schristos options.insn_bit_size / 8, 2154e98e3e1Schristos "/* delayed-slot pointer */"); 2164e98e3e1Schristos } 2174e98e3e1Schristos else 2184e98e3e1Schristos { 2194e98e3e1Schristos if (nr_immeds > 0) 2204e98e3e1Schristos { 2214e98e3e1Schristos lf_printf (file, "nia = cia + %d * (%d + 1); %s\n", 2224e98e3e1Schristos options.insn_bit_size / 8, nr_immeds, 2234e98e3e1Schristos "/* skip immeds as well */"); 2244e98e3e1Schristos 2254e98e3e1Schristos } 2264e98e3e1Schristos else 2274e98e3e1Schristos { 2284e98e3e1Schristos lf_printf (file, "nia = cia + %d;\n", 2294e98e3e1Schristos options.insn_bit_size / 8); 2304e98e3e1Schristos } 2314e98e3e1Schristos } 2324e98e3e1Schristos } 2334e98e3e1Schristos } 2344e98e3e1Schristos 2354e98e3e1Schristos /* if conditional, generate code to verify that the instruction 2364e98e3e1Schristos should be issued */ 2374e98e3e1Schristos if (filter_is_member (instruction->options, "c") 2384e98e3e1Schristos || options.gen.conditional_issue) 2394e98e3e1Schristos { 2404e98e3e1Schristos lf_printf (file, "\n"); 2414e98e3e1Schristos lf_printf (file, "/* execute only if conditional passes */\n"); 2424e98e3e1Schristos lf_printf (file, "if (IS_CONDITION_OK)\n"); 2434e98e3e1Schristos lf_printf (file, " {\n"); 2444e98e3e1Schristos lf_indent (file, +4); 2454e98e3e1Schristos /* FIXME - need to log a conditional failure */ 2464e98e3e1Schristos } 2474e98e3e1Schristos 2484e98e3e1Schristos /* Architecture expects a REG to be zero. Instead of having to 2494e98e3e1Schristos check every read to see if it is refering to that REG just zap it 2504e98e3e1Schristos at the start of every instruction */ 2514e98e3e1Schristos if (options.gen.zero_reg) 2524e98e3e1Schristos { 2534e98e3e1Schristos lf_printf (file, "\n"); 2544e98e3e1Schristos lf_printf (file, "/* Architecture expects REG to be zero */\n"); 2554e98e3e1Schristos lf_printf (file, "GPR_CLEAR(%d);\n", options.gen.zero_reg_nr); 2564e98e3e1Schristos } 2574e98e3e1Schristos 2584e98e3e1Schristos /* generate the code (or at least something */ 2594e98e3e1Schristos lf_printf (file, "\n"); 2604e98e3e1Schristos lf_printf (file, "/* semantics: */\n"); 2614e98e3e1Schristos if (instruction->code != NULL) 2624e98e3e1Schristos { 2634e98e3e1Schristos /* true code */ 2644e98e3e1Schristos lf_printf (file, "{\n"); 265*71f62182Schristos /* NB: Do not indent the code. If the .igen source files cause a compiler 266*71f62182Schristos warning, the diagnostics can read the line from the original source, 267*71f62182Schristos but use column offsets from the generated files, causing columns to be 268*71f62182Schristos misaligned. It makes the generated code slightly more difficult to 269*71f62182Schristos read, but accurate compiler diagnostics relative to the original source 270*71f62182Schristos are more important here. 271*71f62182Schristos lf_indent (file, +2); */ 2724e98e3e1Schristos lf_print__line_ref (file, instruction->code->line); 2734e98e3e1Schristos table_print_code (file, instruction->code); 274*71f62182Schristos /* NB: Disabled -- see above. 275*71f62182Schristos lf_indent (file, -2); */ 2764e98e3e1Schristos lf_printf (file, "}\n"); 2774e98e3e1Schristos lf_print__internal_ref (file); 2784e98e3e1Schristos } 2794e98e3e1Schristos else if (filter_is_member (instruction->options, "nop")) 2804e98e3e1Schristos { 2814e98e3e1Schristos lf_print__internal_ref (file); 2824e98e3e1Schristos } 2834e98e3e1Schristos else 2844e98e3e1Schristos { 2854e98e3e1Schristos const char *prefix = "sim_engine_abort ("; 2864e98e3e1Schristos int indent = strlen (prefix); 2874e98e3e1Schristos /* abort so it is implemented now */ 2884e98e3e1Schristos lf_print__line_ref (file, instruction->line); 2894e98e3e1Schristos lf_printf (file, "%sSD, CPU, cia, \\\n", prefix); 2904e98e3e1Schristos lf_indent (file, +indent); 2914e98e3e1Schristos lf_printf (file, "\"%s:%d:0x%%08lx:%%s unimplemented\\n\", \\\n", 2924e98e3e1Schristos filter_filename (instruction->line->file_name), 2934e98e3e1Schristos instruction->line->line_nr); 2944e98e3e1Schristos lf_printf (file, "(long) CIA, \\\n"); 2954e98e3e1Schristos lf_printf (file, "%sitable[MY_INDEX].name);\n", 2964e98e3e1Schristos options.module.itable.prefix.l); 2974e98e3e1Schristos lf_indent (file, -indent); 2984e98e3e1Schristos lf_print__internal_ref (file); 2994e98e3e1Schristos } 3004e98e3e1Schristos 3014e98e3e1Schristos /* Close off the conditional execution */ 3024e98e3e1Schristos if (filter_is_member (instruction->options, "c") 3034e98e3e1Schristos || options.gen.conditional_issue) 3044e98e3e1Schristos { 3054e98e3e1Schristos lf_indent (file, -4); 3064e98e3e1Schristos lf_printf (file, " }\n"); 3074e98e3e1Schristos } 3084e98e3e1Schristos } 3094e98e3e1Schristos 3104e98e3e1Schristos static void 3114e98e3e1Schristos print_c_semantic (lf *file, 3124b169a6bSchristos const insn_entry *instruction, 3134b169a6bSchristos const opcode_bits *expanded_bits, 3144b169a6bSchristos const insn_opcodes *opcodes, 3154b169a6bSchristos cache_entry *cache_rules, 3164b169a6bSchristos int nr_prefetched_words) 3174e98e3e1Schristos { 3184e98e3e1Schristos 3194e98e3e1Schristos lf_printf (file, "{\n"); 3204e98e3e1Schristos lf_indent (file, +2); 3214e98e3e1Schristos 3224e98e3e1Schristos print_my_defines (file, 3234e98e3e1Schristos instruction->name, 3244e98e3e1Schristos instruction->format_name, expanded_bits); 3254e98e3e1Schristos lf_printf (file, "\n"); 3264e98e3e1Schristos print_icache_body (file, 3274e98e3e1Schristos instruction, 3284e98e3e1Schristos expanded_bits, 3294e98e3e1Schristos cache_rules, 3304e98e3e1Schristos (options.gen.direct_access 3314e98e3e1Schristos ? define_variables 3324e98e3e1Schristos : declare_variables), 3334e98e3e1Schristos (options.gen.icache 3344e98e3e1Schristos ? get_values_from_icache 3354e98e3e1Schristos : do_not_use_icache), nr_prefetched_words); 3364e98e3e1Schristos 3374e98e3e1Schristos lf_printf (file, "%sinstruction_address nia;\n", 3384e98e3e1Schristos options.module.global.prefix.l); 3394e98e3e1Schristos print_semantic_body (file, instruction, expanded_bits, opcodes); 3404e98e3e1Schristos lf_printf (file, "return nia;\n"); 3414e98e3e1Schristos 3424e98e3e1Schristos /* generate something to clean up any #defines created for the cache */ 3434e98e3e1Schristos if (options.gen.direct_access) 3444e98e3e1Schristos { 3454e98e3e1Schristos print_icache_body (file, 3464e98e3e1Schristos instruction, 3474e98e3e1Schristos expanded_bits, 3484e98e3e1Schristos cache_rules, 3494e98e3e1Schristos undef_variables, 3504e98e3e1Schristos (options.gen.icache 3514e98e3e1Schristos ? get_values_from_icache 3524e98e3e1Schristos : do_not_use_icache), nr_prefetched_words); 3534e98e3e1Schristos } 3544e98e3e1Schristos 3554e98e3e1Schristos lf_indent (file, -2); 3564e98e3e1Schristos lf_printf (file, "}\n"); 3574e98e3e1Schristos } 3584e98e3e1Schristos 3594e98e3e1Schristos static void 3604e98e3e1Schristos print_c_semantic_function (lf *file, 3614b169a6bSchristos const insn_entry *instruction, 3624b169a6bSchristos const opcode_bits *expanded_bits, 3634b169a6bSchristos const insn_opcodes *opcodes, 3644b169a6bSchristos cache_entry *cache_rules, 3654b169a6bSchristos int nr_prefetched_words) 3664e98e3e1Schristos { 3674e98e3e1Schristos /* build the semantic routine to execute the instruction */ 3684e98e3e1Schristos print_semantic_function_header (file, 3694e98e3e1Schristos instruction->name, 3704e98e3e1Schristos instruction->format_name, 3714e98e3e1Schristos expanded_bits, 3724e98e3e1Schristos 1 /*is-function-definition */ , 3734e98e3e1Schristos nr_prefetched_words); 3744e98e3e1Schristos print_c_semantic (file, 3754e98e3e1Schristos instruction, 3764e98e3e1Schristos expanded_bits, opcodes, cache_rules, nr_prefetched_words); 3774e98e3e1Schristos } 3784e98e3e1Schristos 3794e98e3e1Schristos void 3804e98e3e1Schristos print_semantic_definition (lf *file, 3814b169a6bSchristos const insn_entry *insn, 3824b169a6bSchristos const opcode_bits *expanded_bits, 3834b169a6bSchristos const insn_opcodes *opcodes, 3844b169a6bSchristos cache_entry *cache_rules, 3854b169a6bSchristos int nr_prefetched_words) 3864e98e3e1Schristos { 3874e98e3e1Schristos print_c_semantic_function (file, 3884e98e3e1Schristos insn, 3894e98e3e1Schristos expanded_bits, 3904e98e3e1Schristos opcodes, cache_rules, nr_prefetched_words); 3914e98e3e1Schristos } 392