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