1 1.1 christos /* The IGEN simulator generator for GDB, the GNU Debugger. 2 1.1 christos 3 1.11 christos Copyright 2002-2024 Free Software Foundation, Inc. 4 1.1 christos 5 1.1 christos Contributed by Andrew Cagney. 6 1.1 christos 7 1.1 christos This file is part of GDB. 8 1.1 christos 9 1.1 christos This program is free software; you can redistribute it and/or modify 10 1.1 christos it under the terms of the GNU General Public License as published by 11 1.1 christos the Free Software Foundation; either version 3 of the License, or 12 1.1 christos (at your option) any later version. 13 1.1 christos 14 1.1 christos This program is distributed in the hope that it will be useful, 15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 1.1 christos GNU General Public License for more details. 18 1.1 christos 19 1.1 christos You should have received a copy of the GNU General Public License 20 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 21 1.1 christos 22 1.1 christos 23 1.1 christos #include "misc.h" 24 1.1 christos #include "lf.h" 25 1.1 christos #include "table.h" 26 1.1 christos #include "filter.h" 27 1.1 christos #include "igen.h" 28 1.1 christos 29 1.1 christos #include "ld-insn.h" 30 1.1 christos #include "ld-decode.h" 31 1.1 christos 32 1.1 christos #include "gen.h" 33 1.1 christos 34 1.1 christos #include "gen-idecode.h" 35 1.1 christos #include "gen-icache.h" 36 1.1 christos #include "gen-semantics.h" 37 1.1 christos 38 1.1 christos 39 1.1 christos 40 1.1 christos static void 41 1.10 christos lf_print_opcodes (lf *file, const gen_entry *table) 42 1.1 christos { 43 1.1 christos if (table !=NULL) 44 1.1 christos { 45 1.1 christos while (1) 46 1.1 christos { 47 1.1 christos ASSERT (table->opcode != NULL); 48 1.1 christos lf_printf (file, "_%d_%d", 49 1.1 christos table->opcode->first, table->opcode->last); 50 1.1 christos if (table->parent == NULL) 51 1.1 christos break; 52 1.1 christos lf_printf (file, "__%d", table->opcode_nr); 53 1.1 christos table = table->parent; 54 1.1 christos } 55 1.1 christos } 56 1.1 christos } 57 1.1 christos 58 1.1 christos 59 1.1 christos 60 1.1 christos 61 1.1 christos static void 62 1.1 christos print_idecode_ifetch (lf *file, 63 1.1 christos int previous_nr_prefetched_words, 64 1.1 christos int current_nr_prefetched_words) 65 1.1 christos { 66 1.1 christos int word_nr; 67 1.1 christos for (word_nr = previous_nr_prefetched_words; 68 1.1 christos word_nr < current_nr_prefetched_words; word_nr++) 69 1.1 christos { 70 1.1 christos lf_printf (file, 71 1.1 christos "instruction_word instruction_%d = IMEM%d_IMMED (cia, %d);\n", 72 1.1 christos word_nr, options.insn_bit_size, word_nr); 73 1.1 christos 74 1.1 christos } 75 1.1 christos } 76 1.1 christos 77 1.1 christos 78 1.1 christos 79 1.1 christos /****************************************************************/ 80 1.1 christos 81 1.1 christos 82 1.1 christos static void 83 1.10 christos lf_print_table_name (lf *file, const gen_entry *table) 84 1.1 christos { 85 1.1 christos lf_printf (file, "idecode_table"); 86 1.1 christos lf_print_opcodes (file, table); 87 1.1 christos } 88 1.1 christos 89 1.1 christos 90 1.1 christos 91 1.1 christos static void 92 1.10 christos print_idecode_table (lf *file, const gen_entry *entry, const char *result) 93 1.1 christos { 94 1.1 christos lf_printf (file, "/* prime the search */\n"); 95 1.1 christos lf_printf (file, "idecode_table_entry *table = "); 96 1.1 christos lf_print_table_name (file, entry); 97 1.1 christos lf_printf (file, ";\n"); 98 1.1 christos lf_printf (file, "int opcode = EXTRACTED%d (instruction, %d, %d);\n", 99 1.1 christos options.insn_bit_size, 100 1.1 christos i2target (options.hi_bit_nr, entry->opcode->first), 101 1.1 christos i2target (options.hi_bit_nr, entry->opcode->last)); 102 1.1 christos lf_printf (file, "idecode_table_entry *table_entry = table + opcode;\n"); 103 1.1 christos 104 1.1 christos lf_printf (file, "\n"); 105 1.1 christos lf_printf (file, "/* iterate until a leaf */\n"); 106 1.1 christos lf_printf (file, "while (1) {\n"); 107 1.1 christos lf_printf (file, " signed shift = table_entry->shift;\n"); 108 1.1 christos lf_printf (file, "if (shift == function_entry) break;\n"); 109 1.1 christos lf_printf (file, " if (shift >= 0) {\n"); 110 1.1 christos lf_printf (file, " table = ((idecode_table_entry*)\n"); 111 1.1 christos lf_printf (file, " table_entry->function_or_table);\n"); 112 1.1 christos lf_printf (file, " opcode = ((instruction & table_entry->mask)\n"); 113 1.1 christos lf_printf (file, " >> shift);\n"); 114 1.1 christos lf_printf (file, " table_entry = table + opcode;\n"); 115 1.1 christos lf_printf (file, " }\n"); 116 1.1 christos lf_printf (file, " else {\n"); 117 1.1 christos lf_printf (file, " /* must be a boolean */\n"); 118 1.1 christos lf_printf (file, " ASSERT(table_entry->shift == boolean_entry);\n"); 119 1.1 christos lf_printf (file, " opcode = ((instruction & table_entry->mask)\n"); 120 1.1 christos lf_printf (file, " != table_entry->value);\n"); 121 1.1 christos lf_printf (file, " table = ((idecode_table_entry*)\n"); 122 1.1 christos lf_printf (file, " table_entry->function_or_table);\n"); 123 1.1 christos lf_printf (file, " table_entry = table + opcode;\n"); 124 1.1 christos lf_printf (file, " }\n"); 125 1.1 christos lf_printf (file, "}\n"); 126 1.1 christos 127 1.1 christos lf_printf (file, "\n"); 128 1.1 christos lf_printf (file, "/* call the leaf code */\n"); 129 1.1 christos if (options.gen.code == generate_jumps) 130 1.1 christos { 131 1.1 christos lf_printf (file, "goto *table_entry->function_or_table;\n"); 132 1.1 christos } 133 1.1 christos else 134 1.1 christos { 135 1.1 christos lf_printf (file, "%s ", result); 136 1.1 christos if (options.gen.icache) 137 1.1 christos { 138 1.1 christos lf_printf (file, 139 1.1 christos "(((idecode_icache*)table_entry->function_or_table)\n"); 140 1.1 christos lf_printf (file, " ("); 141 1.1 christos print_icache_function_actual (file, 1); 142 1.1 christos lf_printf (file, "));\n"); 143 1.1 christos } 144 1.1 christos else 145 1.1 christos { 146 1.1 christos lf_printf (file, 147 1.1 christos "((idecode_semantic*)table_entry->function_or_table)\n"); 148 1.1 christos lf_printf (file, " ("); 149 1.1 christos print_semantic_function_actual (file, 1); 150 1.1 christos lf_printf (file, ");\n"); 151 1.1 christos } 152 1.1 christos } 153 1.1 christos } 154 1.1 christos 155 1.1 christos 156 1.1 christos static void 157 1.10 christos print_idecode_table_start (lf *file, 158 1.10 christos const gen_entry *table, int depth, void *data) 159 1.1 christos { 160 1.1 christos ASSERT (depth == 0); 161 1.1 christos /* start of the table */ 162 1.1 christos if (table->opcode_rule->gen == array_gen) 163 1.1 christos { 164 1.1 christos lf_printf (file, "\n"); 165 1.1 christos lf_printf (file, "static idecode_table_entry "); 166 1.1 christos lf_print_table_name (file, table); 167 1.1 christos lf_printf (file, "[] = {\n"); 168 1.1 christos } 169 1.1 christos } 170 1.1 christos 171 1.1 christos static void 172 1.10 christos print_idecode_table_leaf (lf *file, 173 1.10 christos const gen_entry *entry, int depth, void *data) 174 1.1 christos { 175 1.10 christos const gen_entry *master_entry; 176 1.1 christos ASSERT (entry->parent != NULL); 177 1.1 christos ASSERT (depth == 0); 178 1.1 christos if (entry->combined_parent == NULL) 179 1.1 christos master_entry = entry; 180 1.1 christos else 181 1.1 christos master_entry = entry->combined_parent; 182 1.1 christos 183 1.1 christos /* add an entry to the table */ 184 1.1 christos if (entry->parent->opcode_rule->gen == array_gen) 185 1.1 christos { 186 1.1 christos lf_printf (file, " /*%d*/ { ", entry->opcode_nr); 187 1.1 christos if (entry->opcode == NULL) 188 1.1 christos { 189 1.1 christos ASSERT (entry->nr_insns == 1); 190 1.1 christos /* table leaf entry */ 191 1.1 christos lf_printf (file, "function_entry, 0, 0, "); 192 1.1 christos if (options.gen.code == generate_jumps) 193 1.1 christos { 194 1.1 christos lf_printf (file, "&&"); 195 1.1 christos } 196 1.1 christos print_function_name (file, 197 1.1 christos entry->insns->insn->name, 198 1.1 christos entry->insns->insn->format_name, 199 1.1 christos NULL, 200 1.1 christos master_entry->expanded_bits, 201 1.1 christos (options.gen.icache 202 1.1 christos ? function_name_prefix_icache 203 1.1 christos : function_name_prefix_semantics)); 204 1.1 christos } 205 1.1 christos else if (entry->opcode_rule->gen == switch_gen 206 1.1 christos || entry->opcode_rule->gen == goto_switch_gen 207 1.1 christos || entry->opcode_rule->gen == padded_switch_gen) 208 1.1 christos { 209 1.1 christos /* table calling switch statement */ 210 1.1 christos lf_printf (file, "function_entry, 0, 0, "); 211 1.1 christos if (options.gen.code == generate_jumps) 212 1.1 christos { 213 1.1 christos lf_printf (file, "&&"); 214 1.1 christos } 215 1.1 christos lf_print_table_name (file, entry); 216 1.1 christos } 217 1.1 christos else if (entry->opcode->is_boolean) 218 1.1 christos { 219 1.1 christos /* table `calling' boolean table */ 220 1.1 christos lf_printf (file, "boolean_entry, "); 221 1.1 christos lf_printf (file, "MASK32(%d, %d), ", 222 1.1 christos i2target (options.hi_bit_nr, entry->opcode->first), 223 1.1 christos i2target (options.hi_bit_nr, entry->opcode->last)); 224 1.1 christos lf_printf (file, "INSERTED32(%d, %d, %d), ", 225 1.1 christos entry->opcode->boolean_constant, 226 1.1 christos i2target (options.hi_bit_nr, entry->opcode->first), 227 1.1 christos i2target (options.hi_bit_nr, entry->opcode->last)); 228 1.1 christos lf_print_table_name (file, entry); 229 1.1 christos } 230 1.1 christos else 231 1.1 christos { 232 1.1 christos /* table `calling' another table */ 233 1.1 christos lf_printf (file, "%d, ", 234 1.1 christos options.insn_bit_size - entry->opcode->last - 1); 235 1.1 christos lf_printf (file, "MASK%d(%d,%d), ", options.insn_bit_size, 236 1.1 christos i2target (options.hi_bit_nr, entry->opcode->first), 237 1.1 christos i2target (options.hi_bit_nr, entry->opcode->last)); 238 1.1 christos lf_printf (file, "0, "); 239 1.1 christos lf_print_table_name (file, entry); 240 1.1 christos } 241 1.1 christos lf_printf (file, " },\n"); 242 1.1 christos } 243 1.1 christos } 244 1.1 christos 245 1.1 christos static void 246 1.10 christos print_idecode_table_end (lf *file, 247 1.10 christos const gen_entry *table, int depth, void *data) 248 1.1 christos { 249 1.1 christos ASSERT (depth == 0); 250 1.1 christos if (table->opcode_rule->gen == array_gen) 251 1.1 christos { 252 1.1 christos lf_printf (file, "};\n"); 253 1.1 christos } 254 1.1 christos } 255 1.1 christos 256 1.1 christos /****************************************************************/ 257 1.1 christos 258 1.1 christos 259 1.1 christos static void 260 1.10 christos print_goto_switch_name (lf *file, const gen_entry *entry) 261 1.1 christos { 262 1.1 christos lf_printf (file, "case_"); 263 1.1 christos if (entry->opcode == NULL) 264 1.1 christos { 265 1.1 christos print_function_name (file, 266 1.1 christos entry->insns->insn->name, 267 1.1 christos entry->insns->insn->format_name, 268 1.1 christos NULL, 269 1.1 christos entry->expanded_bits, 270 1.1 christos (options.gen.icache 271 1.1 christos ? function_name_prefix_icache 272 1.1 christos : function_name_prefix_semantics)); 273 1.1 christos } 274 1.1 christos else 275 1.1 christos { 276 1.1 christos lf_print_table_name (file, entry); 277 1.1 christos } 278 1.1 christos } 279 1.1 christos 280 1.1 christos static void 281 1.1 christos print_goto_switch_table_leaf (lf *file, 282 1.10 christos const gen_entry *entry, int depth, void *data) 283 1.1 christos { 284 1.1 christos ASSERT (entry->parent != NULL); 285 1.1 christos ASSERT (depth == 0); 286 1.1 christos ASSERT (entry->parent->opcode_rule->gen == goto_switch_gen); 287 1.1 christos ASSERT (entry->parent->opcode); 288 1.1 christos 289 1.1 christos lf_printf (file, "/* %d */ &&", entry->opcode_nr); 290 1.1 christos if (entry->combined_parent != NULL) 291 1.1 christos print_goto_switch_name (file, entry->combined_parent); 292 1.1 christos else 293 1.1 christos print_goto_switch_name (file, entry); 294 1.1 christos lf_printf (file, ",\n"); 295 1.1 christos } 296 1.1 christos 297 1.1 christos static void 298 1.10 christos print_goto_switch_break (lf *file, const gen_entry *entry) 299 1.1 christos { 300 1.1 christos lf_printf (file, "goto break_"); 301 1.1 christos lf_print_table_name (file, entry->parent); 302 1.1 christos lf_printf (file, ";\n"); 303 1.1 christos } 304 1.1 christos 305 1.1 christos 306 1.1 christos static void 307 1.10 christos print_goto_switch_table (lf *file, const gen_entry *table) 308 1.1 christos { 309 1.1 christos lf_printf (file, "const static void *"); 310 1.1 christos lf_print_table_name (file, table); 311 1.1 christos lf_printf (file, "[] = {\n"); 312 1.1 christos lf_indent (file, +2); 313 1.1 christos gen_entry_traverse_tree (file, table, 0, NULL /*start */ , 314 1.1 christos print_goto_switch_table_leaf, NULL /*end */ , 315 1.1 christos NULL /*data */ ); 316 1.1 christos lf_indent (file, -2); 317 1.1 christos lf_printf (file, "};\n"); 318 1.1 christos } 319 1.1 christos 320 1.1 christos 321 1.10 christos void print_idecode_switch 322 1.10 christos (lf *file, const gen_entry *table, const char *result); 323 1.1 christos 324 1.1 christos static void 325 1.10 christos print_idecode_switch_start (lf *file, 326 1.10 christos const gen_entry *table, int depth, void *data) 327 1.1 christos { 328 1.1 christos /* const char *result = data; */ 329 1.1 christos ASSERT (depth == 0); 330 1.1 christos ASSERT (table->opcode_rule->gen == switch_gen 331 1.1 christos || table->opcode_rule->gen == goto_switch_gen 332 1.1 christos || table->opcode_rule->gen == padded_switch_gen); 333 1.1 christos 334 1.1 christos if (table->opcode->is_boolean 335 1.1 christos || table->opcode_rule->gen == switch_gen 336 1.1 christos || table->opcode_rule->gen == padded_switch_gen) 337 1.1 christos { 338 1.1 christos lf_printf (file, "switch (EXTRACTED%d (instruction_%d, %d, %d))\n", 339 1.1 christos options.insn_bit_size, 340 1.1 christos table->opcode_rule->word_nr, 341 1.1 christos i2target (options.hi_bit_nr, table->opcode->first), 342 1.1 christos i2target (options.hi_bit_nr, table->opcode->last)); 343 1.1 christos lf_indent (file, +2); 344 1.1 christos lf_printf (file, "{\n"); 345 1.1 christos } 346 1.1 christos else if (table->opcode_rule->gen == goto_switch_gen) 347 1.1 christos { 348 1.1 christos if (table->parent != NULL 349 1.1 christos && (table->parent->opcode_rule->gen == switch_gen 350 1.1 christos || table->parent->opcode_rule->gen == goto_switch_gen 351 1.1 christos || table->parent->opcode_rule->gen == padded_switch_gen)) 352 1.1 christos { 353 1.1 christos lf_printf (file, "{\n"); 354 1.1 christos lf_indent (file, +2); 355 1.1 christos } 356 1.1 christos print_goto_switch_table (file, table); 357 1.1 christos lf_printf (file, "ASSERT (EXTRACTED%d (instruction_%d, %d, %d)\n", 358 1.1 christos options.insn_bit_size, 359 1.1 christos table->opcode->word_nr, 360 1.1 christos i2target (options.hi_bit_nr, table->opcode->first), 361 1.1 christos i2target (options.hi_bit_nr, table->opcode->last)); 362 1.1 christos lf_printf (file, " < (sizeof ("); 363 1.1 christos lf_print_table_name (file, table); 364 1.1 christos lf_printf (file, ") / sizeof(void*)));\n"); 365 1.1 christos lf_printf (file, "goto *"); 366 1.1 christos lf_print_table_name (file, table); 367 1.1 christos lf_printf (file, "[EXTRACTED%d (instruction_%d, %d, %d)];\n", 368 1.1 christos options.insn_bit_size, 369 1.1 christos table->opcode->word_nr, 370 1.1 christos i2target (options.hi_bit_nr, table->opcode->first), 371 1.1 christos i2target (options.hi_bit_nr, table->opcode->last)); 372 1.1 christos } 373 1.1 christos else 374 1.1 christos { 375 1.1 christos ASSERT ("bad switch" == NULL); 376 1.1 christos } 377 1.1 christos } 378 1.1 christos 379 1.1 christos 380 1.1 christos static void 381 1.10 christos print_idecode_switch_leaf (lf *file, 382 1.10 christos const gen_entry *entry, int depth, void *data) 383 1.1 christos { 384 1.1 christos const char *result = data; 385 1.1 christos ASSERT (entry->parent != NULL); 386 1.1 christos ASSERT (depth == 0); 387 1.1 christos ASSERT (entry->parent->opcode_rule->gen == switch_gen 388 1.1 christos || entry->parent->opcode_rule->gen == goto_switch_gen 389 1.1 christos || entry->parent->opcode_rule->gen == padded_switch_gen); 390 1.1 christos ASSERT (entry->parent->opcode); 391 1.1 christos 392 1.1 christos /* skip over any instructions combined into another entry */ 393 1.1 christos if (entry->combined_parent != NULL) 394 1.1 christos return; 395 1.1 christos 396 1.1 christos if (entry->parent->opcode->is_boolean && entry->opcode_nr == 0) 397 1.1 christos { 398 1.1 christos /* case: boolean false target */ 399 1.1 christos lf_printf (file, "case %d:\n", entry->parent->opcode->boolean_constant); 400 1.1 christos } 401 1.1 christos else if (entry->parent->opcode->is_boolean && entry->opcode_nr != 0) 402 1.1 christos { 403 1.1 christos /* case: boolean true case */ 404 1.1 christos lf_printf (file, "default:\n"); 405 1.1 christos } 406 1.1 christos else if (entry->parent->opcode_rule->gen == switch_gen 407 1.1 christos || entry->parent->opcode_rule->gen == padded_switch_gen) 408 1.1 christos { 409 1.1 christos /* case: <opcode-nr> - switch */ 410 1.10 christos const gen_entry *cob; 411 1.1 christos for (cob = entry; cob != NULL; cob = cob->combined_next) 412 1.1 christos lf_printf (file, "case %d:\n", cob->opcode_nr); 413 1.1 christos } 414 1.1 christos else if (entry->parent->opcode_rule->gen == goto_switch_gen) 415 1.1 christos { 416 1.1 christos /* case: <opcode-nr> - goto-switch */ 417 1.1 christos print_goto_switch_name (file, entry); 418 1.1 christos lf_printf (file, ":\n"); 419 1.1 christos } 420 1.1 christos else 421 1.1 christos { 422 1.1 christos ERROR ("bad switch"); 423 1.1 christos } 424 1.1 christos lf_printf (file, " {\n"); 425 1.1 christos lf_indent (file, +4); 426 1.1 christos { 427 1.1 christos if (entry->opcode == NULL) 428 1.1 christos { 429 1.1 christos /* switch calling leaf */ 430 1.1 christos ASSERT (entry->nr_insns == 1); 431 1.1 christos print_idecode_ifetch (file, entry->nr_prefetched_words, 432 1.1 christos entry->insns->semantic->nr_prefetched_words); 433 1.1 christos switch (options.gen.code) 434 1.1 christos { 435 1.1 christos case generate_jumps: 436 1.1 christos lf_printf (file, "goto "); 437 1.1 christos break; 438 1.1 christos case generate_calls: 439 1.1 christos lf_printf (file, "%s", result); 440 1.1 christos break; 441 1.1 christos } 442 1.1 christos print_function_name (file, 443 1.1 christos entry->insns->insn->name, 444 1.1 christos entry->insns->insn->format_name, 445 1.1 christos NULL, 446 1.1 christos entry->expanded_bits, 447 1.1 christos (options.gen.icache 448 1.1 christos ? function_name_prefix_icache 449 1.1 christos : function_name_prefix_semantics)); 450 1.1 christos if (options.gen.code == generate_calls) 451 1.1 christos { 452 1.1 christos lf_printf (file, " ("); 453 1.1 christos print_semantic_function_actual (file, 454 1.1 christos entry->insns->semantic-> 455 1.1 christos nr_prefetched_words); 456 1.1 christos lf_printf (file, ")"); 457 1.1 christos } 458 1.1 christos lf_printf (file, ";\n"); 459 1.1 christos } 460 1.1 christos else if (entry->opcode_rule->gen == switch_gen 461 1.1 christos || entry->opcode_rule->gen == goto_switch_gen 462 1.1 christos || entry->opcode_rule->gen == padded_switch_gen) 463 1.1 christos { 464 1.1 christos /* switch calling switch */ 465 1.1 christos lf_printf (file, "{\n"); 466 1.1 christos lf_indent (file, +2); 467 1.1 christos print_idecode_ifetch (file, entry->parent->nr_prefetched_words, 468 1.1 christos entry->nr_prefetched_words); 469 1.1 christos print_idecode_switch (file, entry, result); 470 1.1 christos lf_indent (file, -2); 471 1.1 christos lf_printf (file, "}\n"); 472 1.1 christos } 473 1.1 christos else 474 1.1 christos { 475 1.1 christos /* switch looking up a table */ 476 1.1 christos lf_printf (file, "{\n"); 477 1.1 christos lf_indent (file, +2); 478 1.1 christos print_idecode_ifetch (file, entry->parent->nr_prefetched_words, 479 1.1 christos entry->nr_prefetched_words); 480 1.1 christos print_idecode_table (file, entry, result); 481 1.1 christos lf_indent (file, -2); 482 1.1 christos lf_printf (file, "}\n"); 483 1.1 christos } 484 1.1 christos if (entry->parent->opcode->is_boolean 485 1.1 christos || entry->parent->opcode_rule->gen == switch_gen 486 1.1 christos || entry->parent->opcode_rule->gen == padded_switch_gen) 487 1.1 christos { 488 1.1 christos lf_printf (file, "break;\n"); 489 1.1 christos } 490 1.1 christos else if (entry->parent->opcode_rule->gen == goto_switch_gen) 491 1.1 christos { 492 1.1 christos print_goto_switch_break (file, entry); 493 1.1 christos } 494 1.1 christos else 495 1.1 christos { 496 1.1 christos ERROR ("bad switch"); 497 1.1 christos } 498 1.1 christos } 499 1.1 christos lf_indent (file, -4); 500 1.1 christos lf_printf (file, " }\n"); 501 1.1 christos } 502 1.1 christos 503 1.1 christos 504 1.1 christos static void 505 1.1 christos print_idecode_switch_illegal (lf *file, const char *result) 506 1.1 christos { 507 1.1 christos lf_indent (file, +2); 508 1.1 christos print_idecode_invalid (file, result, invalid_illegal); 509 1.1 christos lf_printf (file, "break;\n"); 510 1.1 christos lf_indent (file, -2); 511 1.1 christos } 512 1.1 christos 513 1.1 christos static void 514 1.10 christos print_idecode_switch_end (lf *file, 515 1.10 christos const gen_entry *table, int depth, void *data) 516 1.1 christos { 517 1.1 christos const char *result = data; 518 1.1 christos ASSERT (depth == 0); 519 1.1 christos ASSERT (table->opcode_rule->gen == switch_gen 520 1.1 christos || table->opcode_rule->gen == goto_switch_gen 521 1.1 christos || table->opcode_rule->gen == padded_switch_gen); 522 1.1 christos ASSERT (table->opcode); 523 1.1 christos 524 1.1 christos if (table->opcode->is_boolean) 525 1.1 christos { 526 1.1 christos lf_printf (file, "}\n"); 527 1.1 christos lf_indent (file, -2); 528 1.1 christos } 529 1.1 christos else if (table->opcode_rule->gen == switch_gen 530 1.1 christos || table->opcode_rule->gen == padded_switch_gen) 531 1.1 christos { 532 1.1 christos lf_printf (file, "default:\n"); 533 1.1 christos lf_indent (file, +2); 534 1.1 christos if (table->nr_entries == table->opcode->nr_opcodes) 535 1.1 christos { 536 1.1 christos print_sim_engine_abort (file, 537 1.1 christos "Internal error - bad switch generated"); 538 1.1 christos lf_printf (file, "%sNULL_CIA;\n", result); 539 1.1 christos lf_printf (file, "break;\n"); 540 1.1 christos } 541 1.1 christos else 542 1.1 christos { 543 1.1 christos print_idecode_switch_illegal (file, result); 544 1.1 christos } 545 1.1 christos lf_indent (file, -2); 546 1.1 christos lf_printf (file, "}\n"); 547 1.1 christos lf_indent (file, -2); 548 1.1 christos } 549 1.1 christos else if (table->opcode_rule->gen == goto_switch_gen) 550 1.1 christos { 551 1.1 christos lf_printf (file, "illegal_"); 552 1.1 christos lf_print_table_name (file, table); 553 1.1 christos lf_printf (file, ":\n"); 554 1.1 christos print_idecode_invalid (file, result, invalid_illegal); 555 1.1 christos lf_printf (file, "break_"); 556 1.1 christos lf_print_table_name (file, table); 557 1.1 christos lf_printf (file, ":;\n"); 558 1.1 christos if (table->parent != NULL 559 1.1 christos && (table->parent->opcode_rule->gen == switch_gen 560 1.1 christos || table->parent->opcode_rule->gen == goto_switch_gen 561 1.1 christos || table->parent->opcode_rule->gen == padded_switch_gen)) 562 1.1 christos { 563 1.1 christos lf_indent (file, -2); 564 1.1 christos lf_printf (file, "}\n"); 565 1.1 christos } 566 1.1 christos } 567 1.1 christos else 568 1.1 christos { 569 1.1 christos ERROR ("bad switch"); 570 1.1 christos } 571 1.1 christos } 572 1.1 christos 573 1.1 christos 574 1.1 christos void 575 1.10 christos print_idecode_switch (lf *file, const gen_entry *table, const char *result) 576 1.1 christos { 577 1.1 christos gen_entry_traverse_tree (file, table, 578 1.1 christos 0, 579 1.1 christos print_idecode_switch_start, 580 1.1 christos print_idecode_switch_leaf, 581 1.1 christos print_idecode_switch_end, (void *) result); 582 1.1 christos } 583 1.1 christos 584 1.1 christos 585 1.1 christos static void 586 1.1 christos print_idecode_switch_function_header (lf *file, 587 1.10 christos const gen_entry *table, 588 1.1 christos int is_function_definition, 589 1.1 christos int nr_prefetched_words) 590 1.1 christos { 591 1.1 christos lf_printf (file, "\n"); 592 1.1 christos if (options.gen.code == generate_calls) 593 1.1 christos { 594 1.1 christos lf_printf (file, "static "); 595 1.1 christos if (options.gen.icache) 596 1.1 christos { 597 1.1 christos lf_printf (file, "idecode_semantic *"); 598 1.1 christos } 599 1.1 christos else 600 1.1 christos { 601 1.1 christos lf_printf (file, "unsigned_word"); 602 1.1 christos } 603 1.1 christos if (is_function_definition) 604 1.1 christos { 605 1.1 christos lf_printf (file, "\n"); 606 1.1 christos } 607 1.1 christos else 608 1.1 christos { 609 1.1 christos lf_printf (file, " "); 610 1.1 christos } 611 1.1 christos lf_print_table_name (file, table); 612 1.1 christos lf_printf (file, "\n("); 613 1.1 christos print_icache_function_formal (file, nr_prefetched_words); 614 1.1 christos lf_printf (file, ")"); 615 1.1 christos if (!is_function_definition) 616 1.1 christos { 617 1.1 christos lf_printf (file, ";"); 618 1.1 christos } 619 1.1 christos lf_printf (file, "\n"); 620 1.1 christos } 621 1.1 christos if (options.gen.code == generate_jumps && is_function_definition) 622 1.1 christos { 623 1.1 christos lf_indent (file, -1); 624 1.1 christos lf_print_table_name (file, table); 625 1.1 christos lf_printf (file, ":\n"); 626 1.1 christos lf_indent (file, +1); 627 1.1 christos } 628 1.1 christos } 629 1.1 christos 630 1.1 christos 631 1.1 christos static void 632 1.10 christos idecode_declare_if_switch (lf *file, 633 1.10 christos const gen_entry *table, int depth, void *data) 634 1.1 christos { 635 1.1 christos 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 */ 636 1.1 christos && table->parent->opcode_rule->gen == array_gen) 637 1.1 christos { 638 1.1 christos print_idecode_switch_function_header (file, 639 1.1 christos table, 640 1.1 christos 0 /*isnt function definition */ , 641 1.1 christos 0); 642 1.1 christos } 643 1.1 christos } 644 1.1 christos 645 1.1 christos 646 1.1 christos static void 647 1.10 christos idecode_expand_if_switch (lf *file, 648 1.10 christos const gen_entry *table, int depth, void *data) 649 1.1 christos { 650 1.1 christos 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 */ 651 1.1 christos && table->parent->opcode_rule->gen == array_gen) 652 1.1 christos { 653 1.1 christos print_idecode_switch_function_header (file, 654 1.1 christos table, 655 1.1 christos 1 /*is function definition */ , 656 1.1 christos 0); 657 1.1 christos if (options.gen.code == generate_calls) 658 1.1 christos { 659 1.1 christos lf_printf (file, "{\n"); 660 1.1 christos lf_indent (file, +2); 661 1.1 christos } 662 1.1 christos print_idecode_switch (file, table, "return"); 663 1.1 christos if (options.gen.code == generate_calls) 664 1.1 christos { 665 1.1 christos lf_indent (file, -2); 666 1.1 christos lf_printf (file, "}\n"); 667 1.1 christos } 668 1.1 christos } 669 1.1 christos } 670 1.1 christos 671 1.1 christos 672 1.1 christos /****************************************************************/ 673 1.1 christos 674 1.1 christos 675 1.1 christos void 676 1.10 christos print_idecode_lookups (lf *file, 677 1.10 christos const gen_entry *table, 678 1.10 christos cache_entry *cache_rules) 679 1.1 christos { 680 1.1 christos int depth; 681 1.1 christos 682 1.1 christos /* output switch function declarations where needed by tables */ 683 1.1 christos gen_entry_traverse_tree (file, table, 1, idecode_declare_if_switch, /* START */ 684 1.1 christos NULL, NULL, NULL); 685 1.1 christos 686 1.1 christos /* output tables where needed */ 687 1.1 christos for (depth = gen_entry_depth (table); depth > 0; depth--) 688 1.1 christos { 689 1.1 christos gen_entry_traverse_tree (file, table, 690 1.1 christos 1 - depth, 691 1.1 christos print_idecode_table_start, 692 1.1 christos print_idecode_table_leaf, 693 1.1 christos print_idecode_table_end, NULL); 694 1.1 christos } 695 1.1 christos 696 1.1 christos /* output switch functions where needed */ 697 1.1 christos gen_entry_traverse_tree (file, table, 1, idecode_expand_if_switch, /* START */ 698 1.1 christos NULL, NULL, NULL); 699 1.1 christos } 700 1.1 christos 701 1.1 christos 702 1.1 christos void 703 1.10 christos print_idecode_body (lf *file, const gen_entry *table, const char *result) 704 1.1 christos { 705 1.1 christos if (table->opcode_rule->gen == switch_gen 706 1.1 christos || table->opcode_rule->gen == goto_switch_gen 707 1.1 christos || table->opcode_rule->gen == padded_switch_gen) 708 1.1 christos { 709 1.1 christos print_idecode_switch (file, table, result); 710 1.1 christos } 711 1.1 christos else 712 1.1 christos { 713 1.1 christos print_idecode_table (file, table, result); 714 1.1 christos } 715 1.1 christos } 716 1.1 christos 717 1.1 christos 718 1.1 christos /****************************************************************/ 719 1.1 christos 720 1.1 christos /* Output code to do any final checks on the decoded instruction. 721 1.1 christos This includes things like verifying any on decoded fields have the 722 1.1 christos correct value and checking that (for floating point) floating point 723 1.1 christos hardware isn't disabled */ 724 1.1 christos 725 1.1 christos void 726 1.1 christos print_idecode_validate (lf *file, 727 1.10 christos const insn_entry *instruction, 728 1.10 christos const insn_opcodes *opcode_paths) 729 1.1 christos { 730 1.1 christos /* Validate: unchecked instruction fields 731 1.1 christos 732 1.1 christos If any constant fields in the instruction were not checked by the 733 1.1 christos idecode tables, output code to check that they have the correct 734 1.1 christos value here */ 735 1.1 christos { 736 1.1 christos int nr_checks = 0; 737 1.1 christos int word_nr; 738 1.1 christos lf_printf (file, "\n"); 739 1.1 christos lf_indent_suppress (file); 740 1.1 christos lf_printf (file, "#if defined (WITH_RESERVED_BITS)\n"); 741 1.1 christos lf_printf (file, "/* validate: "); 742 1.1 christos print_insn_words (file, instruction); 743 1.1 christos lf_printf (file, " */\n"); 744 1.1 christos for (word_nr = 0; word_nr < instruction->nr_words; word_nr++) 745 1.1 christos { 746 1.1 christos insn_uint check_mask = 0; 747 1.1 christos insn_uint check_val = 0; 748 1.1 christos insn_word_entry *word = instruction->word[word_nr]; 749 1.1 christos int bit_nr; 750 1.1 christos 751 1.1 christos /* form check_mask/check_val containing what needs to be checked 752 1.1 christos in the instruction */ 753 1.1 christos for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++) 754 1.1 christos { 755 1.1 christos insn_bit_entry *bit = word->bit[bit_nr]; 756 1.1 christos insn_field_entry *field = bit->field; 757 1.1 christos 758 1.1 christos /* Make space for the next bit */ 759 1.1 christos check_mask <<= 1; 760 1.1 christos check_val <<= 1; 761 1.1 christos 762 1.1 christos /* Only need to validate constant (and reserved) 763 1.1 christos bits. Skip any others */ 764 1.1 christos if (field->type != insn_field_int 765 1.1 christos && field->type != insn_field_reserved 766 1.1 christos /* Consider a named field equal to a value to be just as 767 1.1 christos constant as an integer field. */ 768 1.1 christos && (field->type != insn_field_string 769 1.1 christos || field->conditions == NULL 770 1.1 christos || field->conditions->test != insn_field_cond_eq 771 1.1 christos || field->conditions->type != insn_field_cond_value)) 772 1.1 christos continue; 773 1.1 christos 774 1.1 christos /* Look through the list of opcode paths that lead to this 775 1.1 christos instruction. See if any have failed to check the 776 1.1 christos relevant bit */ 777 1.1 christos if (opcode_paths != NULL) 778 1.1 christos { 779 1.10 christos const insn_opcodes *entry; 780 1.1 christos for (entry = opcode_paths; entry != NULL; entry = entry->next) 781 1.1 christos { 782 1.1 christos opcode_field *opcode; 783 1.1 christos for (opcode = entry->opcode; 784 1.1 christos opcode != NULL; opcode = opcode->parent) 785 1.1 christos { 786 1.1 christos if (opcode->word_nr == word_nr 787 1.1 christos && opcode->first <= bit_nr 788 1.1 christos && opcode->last >= bit_nr) 789 1.1 christos /* we've decoded on this bit */ 790 1.1 christos break; 791 1.1 christos } 792 1.1 christos if (opcode == NULL) 793 1.1 christos /* the bit wasn't decoded on */ 794 1.1 christos break; 795 1.1 christos } 796 1.1 christos if (entry == NULL) 797 1.1 christos /* all the opcode paths decoded on BIT_NR, no need 798 1.1 christos to check it */ 799 1.1 christos continue; 800 1.1 christos } 801 1.1 christos 802 1.1 christos check_mask |= 1; 803 1.1 christos check_val |= bit->value; 804 1.1 christos } 805 1.1 christos 806 1.1 christos /* if any bits not checked by opcode tables, output code to check them */ 807 1.1 christos if (check_mask) 808 1.1 christos { 809 1.1 christos if (nr_checks == 0) 810 1.1 christos { 811 1.1 christos lf_printf (file, "if (WITH_RESERVED_BITS)\n"); 812 1.1 christos lf_printf (file, " {\n"); 813 1.1 christos lf_indent (file, +4); 814 1.1 christos } 815 1.1 christos nr_checks++; 816 1.1 christos if (options.insn_bit_size > 32) 817 1.1 christos { 818 1.1 christos lf_printf (file, "if ((instruction_%d\n", word_nr); 819 1.1 christos lf_printf (file, " & UNSIGNED64 (0x%08lx%08lx))\n", 820 1.1 christos (unsigned long) (check_mask >> 32), 821 1.1 christos (unsigned long) (check_mask)); 822 1.1 christos lf_printf (file, " != UNSIGNED64 (0x%08lx%08lx))\n", 823 1.1 christos (unsigned long) (check_val >> 32), 824 1.1 christos (unsigned long) (check_val)); 825 1.1 christos } 826 1.1 christos else 827 1.1 christos { 828 1.1 christos lf_printf (file, 829 1.1 christos "if ((instruction_%d & 0x%08lx) != 0x%08lx)\n", 830 1.1 christos word_nr, (unsigned long) (check_mask), 831 1.1 christos (unsigned long) (check_val)); 832 1.1 christos } 833 1.1 christos lf_indent (file, +2); 834 1.1 christos print_idecode_invalid (file, "return", invalid_illegal); 835 1.1 christos lf_indent (file, -2); 836 1.1 christos } 837 1.1 christos } 838 1.1 christos if (nr_checks > 0) 839 1.1 christos { 840 1.1 christos lf_indent (file, -4); 841 1.1 christos lf_printf (file, " }\n"); 842 1.1 christos } 843 1.1 christos lf_indent_suppress (file); 844 1.1 christos lf_printf (file, "#endif\n"); 845 1.1 christos } 846 1.1 christos 847 1.1 christos /* Validate: Floating Point hardware 848 1.1 christos 849 1.1 christos If the simulator is being built with out floating point hardware 850 1.1 christos (different to it being disabled in the MSR) then floating point 851 1.1 christos instructions are invalid */ 852 1.1 christos { 853 1.1 christos if (filter_is_member (instruction->flags, "f")) 854 1.1 christos { 855 1.1 christos lf_printf (file, "\n"); 856 1.1 christos lf_indent_suppress (file); 857 1.1 christos lf_printf (file, "#if defined(CURRENT_FLOATING_POINT)\n"); 858 1.1 christos lf_printf (file, "/* Validate: FP hardware exists */\n"); 859 1.1 christos lf_printf (file, 860 1.1 christos "if (CURRENT_FLOATING_POINT != HARD_FLOATING_POINT) {\n"); 861 1.1 christos lf_indent (file, +2); 862 1.1 christos print_idecode_invalid (file, "return", invalid_illegal); 863 1.1 christos lf_indent (file, -2); 864 1.1 christos lf_printf (file, "}\n"); 865 1.1 christos lf_indent_suppress (file); 866 1.1 christos lf_printf (file, "#endif\n"); 867 1.1 christos } 868 1.1 christos } 869 1.1 christos 870 1.1 christos /* Validate: Floating Point available 871 1.1 christos 872 1.1 christos If floating point is not available, we enter a floating point 873 1.1 christos unavailable interrupt into the cache instead of the instruction 874 1.1 christos proper. 875 1.1 christos 876 1.1 christos The PowerPC spec requires a CSI after MSR[FP] is changed and when 877 1.1 christos ever a CSI occures we flush the instruction cache. */ 878 1.1 christos 879 1.1 christos { 880 1.1 christos if (filter_is_member (instruction->flags, "f")) 881 1.1 christos { 882 1.1 christos lf_printf (file, "\n"); 883 1.1 christos lf_indent_suppress (file); 884 1.1 christos lf_printf (file, "#if defined(IS_FP_AVAILABLE)\n"); 885 1.1 christos lf_printf (file, "/* Validate: FP available according to cpu */\n"); 886 1.1 christos lf_printf (file, "if (!IS_FP_AVAILABLE) {\n"); 887 1.1 christos lf_indent (file, +2); 888 1.1 christos print_idecode_invalid (file, "return", invalid_fp_unavailable); 889 1.1 christos lf_indent (file, -2); 890 1.1 christos lf_printf (file, "}\n"); 891 1.1 christos lf_indent_suppress (file); 892 1.1 christos lf_printf (file, "#endif\n"); 893 1.1 christos } 894 1.1 christos } 895 1.1 christos 896 1.1 christos /* Validate: Validate Instruction in correct slot 897 1.1 christos 898 1.1 christos Some architectures place restrictions on the slot that an 899 1.1 christos instruction can be issued in */ 900 1.1 christos 901 1.1 christos { 902 1.1 christos if (filter_is_member (instruction->options, "s") 903 1.1 christos || options.gen.slot_verification) 904 1.1 christos { 905 1.1 christos lf_printf (file, "\n"); 906 1.1 christos lf_indent_suppress (file); 907 1.1 christos lf_printf (file, "#if defined(IS_WRONG_SLOT)\n"); 908 1.1 christos lf_printf (file, 909 1.1 christos "/* Validate: Instruction issued in correct slot */\n"); 910 1.1 christos lf_printf (file, "if (IS_WRONG_SLOT) {\n"); 911 1.1 christos lf_indent (file, +2); 912 1.1 christos print_idecode_invalid (file, "return", invalid_wrong_slot); 913 1.1 christos lf_indent (file, -2); 914 1.1 christos lf_printf (file, "}\n"); 915 1.1 christos lf_indent_suppress (file); 916 1.1 christos lf_printf (file, "#endif\n"); 917 1.1 christos } 918 1.1 christos } 919 1.1 christos 920 1.1 christos } 921 1.1 christos 922 1.1 christos 923 1.1 christos /****************************************************************/ 924 1.1 christos 925 1.1 christos 926 1.1 christos void 927 1.1 christos print_idecode_issue_function_header (lf *file, 928 1.1 christos const char *processor, 929 1.1 christos function_decl_type decl_type, 930 1.1 christos int nr_prefetched_words) 931 1.1 christos { 932 1.1 christos int indent; 933 1.1 christos lf_printf (file, "\n"); 934 1.1 christos switch (decl_type) 935 1.1 christos { 936 1.1 christos case is_function_declaration: 937 1.1 christos lf_print__function_type_function (file, print_semantic_function_type, 938 1.1 christos "INLINE_IDECODE", " "); 939 1.1 christos break; 940 1.1 christos case is_function_definition: 941 1.1 christos lf_print__function_type_function (file, print_semantic_function_type, 942 1.1 christos "INLINE_IDECODE", "\n"); 943 1.1 christos break; 944 1.1 christos case is_function_variable: 945 1.9 christos if (lf_get_file_type (file) == lf_is_h) 946 1.9 christos lf_printf (file, "extern "); 947 1.1 christos print_semantic_function_type (file); 948 1.1 christos lf_printf (file, " (*"); 949 1.1 christos break; 950 1.1 christos } 951 1.1 christos indent = print_function_name (file, 952 1.1 christos "issue", 953 1.1 christos NULL, 954 1.1 christos processor, 955 1.1 christos NULL, function_name_prefix_idecode); 956 1.1 christos switch (decl_type) 957 1.1 christos { 958 1.1 christos case is_function_definition: 959 1.1 christos indent += lf_printf (file, " ("); 960 1.1 christos break; 961 1.1 christos case is_function_declaration: 962 1.1 christos lf_putstr (file, "\n("); 963 1.1 christos indent = 1; 964 1.1 christos break; 965 1.1 christos case is_function_variable: 966 1.1 christos lf_putstr (file, ")\n("); 967 1.1 christos indent = 1; 968 1.1 christos break; 969 1.1 christos } 970 1.1 christos lf_indent (file, +indent); 971 1.1 christos print_semantic_function_formal (file, nr_prefetched_words); 972 1.1 christos lf_putstr (file, ")"); 973 1.1 christos lf_indent (file, -indent); 974 1.1 christos switch (decl_type) 975 1.1 christos { 976 1.1 christos case is_function_definition: 977 1.1 christos lf_printf (file, "\n"); 978 1.1 christos break; 979 1.1 christos case is_function_declaration: 980 1.1 christos case is_function_variable: 981 1.1 christos lf_putstr (file, ";\n"); 982 1.1 christos break; 983 1.1 christos } 984 1.1 christos } 985 1.1 christos 986 1.1 christos 987 1.1 christos 988 1.1 christos void 989 1.1 christos print_idecode_globals (lf *file) 990 1.1 christos { 991 1.1 christos lf_printf (file, "enum {\n"); 992 1.1 christos lf_printf (file, " /* greater or equal to zero => table */\n"); 993 1.1 christos lf_printf (file, " function_entry = -1,\n"); 994 1.1 christos lf_printf (file, " boolean_entry = -2,\n"); 995 1.1 christos lf_printf (file, "};\n"); 996 1.1 christos lf_printf (file, "\n"); 997 1.1 christos lf_printf (file, "typedef struct _idecode_table_entry {\n"); 998 1.1 christos lf_printf (file, " int shift;\n"); 999 1.10 christos lf_printf (file, " uint%d_t mask;\n", options.insn_bit_size); 1000 1.10 christos lf_printf (file, " uint%d_t value;\n", options.insn_bit_size); 1001 1.1 christos lf_printf (file, " void *function_or_table;\n"); 1002 1.1 christos lf_printf (file, "} idecode_table_entry;\n"); 1003 1.1 christos } 1004