| 1 | /* This file is part of the program psim. |
| 2 | |
| 3 | Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au> |
| 4 | |
| 5 | This program is free software; you can redistribute it and/or modify |
| 6 | it under the terms of the GNU General Public License as published by |
| 7 | the Free Software Foundation; either version 2 of the License, or |
| 8 | (at your option) any later version. |
| 9 | |
| 10 | This program is distributed in the hope that it will be useful, |
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | GNU General Public License for more details. |
| 14 | |
| 15 | You should have received a copy of the GNU General Public License |
| 16 | along with this program; if not, write to the Free Software |
| 17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 18 | |
| 19 | */ |
| 20 | |
| 21 | |
| 22 | |
| 23 | #include "misc.h" |
| 24 | #include "lf.h" |
| 25 | #include "table.h" |
| 26 | #include "filter.h" |
| 27 | |
| 28 | #include "ld-decode.h" |
| 29 | #include "ld-cache.h" |
| 30 | #include "ld-insn.h" |
| 31 | |
| 32 | #include "igen.h" |
| 33 | |
| 34 | #include "gen-semantics.h" |
| 35 | #include "gen-icache.h" |
| 36 | #include "gen-idecode.h" |
| 37 | |
| 38 | |
| 39 | static void |
| 40 | print_semantic_function_header(lf *file, |
| 41 | const char *basename, |
| 42 | insn_bits *expanded_bits, |
| 43 | int is_function_definition) |
| 44 | { |
| 45 | int indent; |
| 46 | lf_printf(file, "\n"); |
| 47 | lf_print_function_type(file, SEMANTIC_FUNCTION_TYPE, "PSIM_EXTERN_SEMANTICS", |
| 48 | (is_function_definition ? "\n" : " ")); |
| 49 | indent = print_function_name(file, |
| 50 | basename, |
| 51 | expanded_bits, |
| 52 | function_name_prefix_semantics); |
| 53 | if (is_function_definition) |
| 54 | lf_indent(file, +indent); |
| 55 | else |
| 56 | lf_printf(file, "\n"); |
| 57 | lf_printf(file, "(%s)", SEMANTIC_FUNCTION_FORMAL); |
| 58 | if (is_function_definition) |
| 59 | lf_indent(file, -indent); |
| 60 | else |
| 61 | lf_printf(file, ";"); |
| 62 | lf_printf(file, "\n"); |
| 63 | } |
| 64 | |
| 65 | void |
| 66 | print_semantic_declaration(insn_table *entry, |
| 67 | lf *file, |
| 68 | void *data, |
| 69 | insn *instruction, |
| 70 | int depth) |
| 71 | { |
| 72 | if (generate_expanded_instructions) { |
| 73 | ASSERT(entry->nr_insn == 1); |
| 74 | print_semantic_function_header(file, |
| 75 | instruction->file_entry->fields[insn_name], |
| 76 | entry->expanded_bits, |
| 77 | 0/* is not function definition*/); |
| 78 | } |
| 79 | else { |
| 80 | print_semantic_function_header(file, |
| 81 | instruction->file_entry->fields[insn_name], |
| 82 | NULL, |
| 83 | 0/* is not function definition*/); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | |
| 88 | \f |
| 89 | /* generate the semantics.c file */ |
| 90 | |
| 91 | |
| 92 | void |
| 93 | print_idecode_illegal(lf *file, |
| 94 | const char *result) |
| 95 | { |
| 96 | if ((code & generate_jumps)) |
| 97 | lf_printf(file, "goto %s_illegal;\n", (code & generate_with_icache) ? "icache" : "semantic"); |
| 98 | else if ((code & generate_with_icache)) |
| 99 | lf_printf(file, "%s icache_illegal(%s);\n", result, ICACHE_FUNCTION_ACTUAL); |
| 100 | else |
| 101 | lf_printf(file, "%s semantic_illegal(%s);\n", result, SEMANTIC_FUNCTION_ACTUAL); |
| 102 | } |
| 103 | |
| 104 | |
| 105 | void |
| 106 | print_semantic_body(lf *file, |
| 107 | insn *instruction, |
| 108 | insn_bits *expanded_bits, |
| 109 | opcode_field *opcodes) |
| 110 | { |
| 111 | print_itrace(file, instruction->file_entry, 0/*put_value_in_cache*/); |
| 112 | |
| 113 | /* validate the instruction, if a cache this has already been done */ |
| 114 | if (!(code & generate_with_icache)) |
| 115 | print_idecode_validate(file, instruction, opcodes); |
| 116 | |
| 117 | /* generate the profiling call - this is delayed until after the |
| 118 | instruction has been verified */ |
| 119 | lf_printf(file, "\n"); |
| 120 | lf_printf(file, "/* monitoring: */\n"); |
| 121 | lf_printf(file, "if (WITH_MON & MONITOR_INSTRUCTION_ISSUE) {\n"); |
| 122 | lf_printf(file, " mon_issue("); |
| 123 | print_function_name(file, |
| 124 | instruction->file_entry->fields[insn_name], |
| 125 | NULL, |
| 126 | function_name_prefix_itable); |
| 127 | lf_printf(file, ", processor, cia);\n"); |
| 128 | lf_printf(file, "}\n"); |
| 129 | |
| 130 | /* generate the code (or at least something */ |
| 131 | lf_printf(file, "\n"); |
| 132 | lf_printf(file, "/* semantics: */\n"); |
| 133 | lf_printf(file, "nia = cia + %d;\n", insn_bit_size / 8); |
| 134 | if (instruction->file_entry->annex != NULL) { |
| 135 | /* true code */ |
| 136 | table_entry_print_cpp_line_nr(file, instruction->file_entry); |
| 137 | lf_printf(file, "{\n"); |
| 138 | lf_indent(file, +2); |
| 139 | lf_print__c_code(file, instruction->file_entry->annex); |
| 140 | lf_indent(file, -2); |
| 141 | lf_printf(file, "}\n"); |
| 142 | lf_print__internal_reference(file); |
| 143 | } |
| 144 | else if (it_is("nop", instruction->file_entry->fields[insn_flags])) { |
| 145 | lf_print__internal_reference(file); |
| 146 | } |
| 147 | else { |
| 148 | /* abort so it is implemented now */ |
| 149 | table_entry_print_cpp_line_nr(file, instruction->file_entry); |
| 150 | lf_putstr(file, "error(\"%s:%d:0x%08lx:%s unimplemented\\n\",\n"); |
| 151 | lf_printf(file, " itable[MY_INDEX].file, itable[MY_INDEX].line_nr, (long)cia, itable[MY_INDEX].name);\n"); |
| 152 | lf_print__internal_reference(file); |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | static void |
| 157 | print_c_semantic(lf *file, |
| 158 | insn *instruction, |
| 159 | insn_bits *expanded_bits, |
| 160 | opcode_field *opcodes, |
| 161 | cache_table *cache_rules) |
| 162 | { |
| 163 | |
| 164 | lf_printf(file, "{\n"); |
| 165 | lf_indent(file, +2); |
| 166 | |
| 167 | print_my_defines(file, expanded_bits, instruction->file_entry); |
| 168 | lf_printf(file, "\n"); |
| 169 | print_icache_body(file, |
| 170 | instruction, |
| 171 | expanded_bits, |
| 172 | cache_rules, |
| 173 | ((code & generate_with_direct_access) |
| 174 | ? define_variables |
| 175 | : declare_variables), |
| 176 | ((code & generate_with_icache) |
| 177 | ? get_values_from_icache |
| 178 | : do_not_use_icache)); |
| 179 | |
| 180 | lf_printf(file, "unsigned_word nia;\n"); |
| 181 | print_semantic_body(file, |
| 182 | instruction, |
| 183 | expanded_bits, |
| 184 | opcodes); |
| 185 | lf_printf(file, "return nia;\n"); |
| 186 | |
| 187 | /* generate something to clean up any #defines created for the cache */ |
| 188 | if (code & generate_with_direct_access) |
| 189 | print_icache_body(file, |
| 190 | instruction, |
| 191 | expanded_bits, |
| 192 | cache_rules, |
| 193 | undef_variables, |
| 194 | ((code & generate_with_icache) |
| 195 | ? get_values_from_icache |
| 196 | : do_not_use_icache)); |
| 197 | |
| 198 | lf_indent(file, -2); |
| 199 | lf_printf(file, "}\n"); |
| 200 | } |
| 201 | |
| 202 | static void |
| 203 | print_c_semantic_function(lf *file, |
| 204 | insn *instruction, |
| 205 | insn_bits *expanded_bits, |
| 206 | opcode_field *opcodes, |
| 207 | cache_table *cache_rules) |
| 208 | { |
| 209 | /* build the semantic routine to execute the instruction */ |
| 210 | print_semantic_function_header(file, |
| 211 | instruction->file_entry->fields[insn_name], |
| 212 | expanded_bits, |
| 213 | 1/*is-function-definition*/); |
| 214 | print_c_semantic(file, |
| 215 | instruction, |
| 216 | expanded_bits, |
| 217 | opcodes, |
| 218 | cache_rules); |
| 219 | } |
| 220 | |
| 221 | void |
| 222 | print_semantic_definition(insn_table *entry, |
| 223 | lf *file, |
| 224 | void *data, |
| 225 | insn *instruction, |
| 226 | int depth) |
| 227 | { |
| 228 | cache_table *cache_rules = (cache_table*)data; |
| 229 | if (generate_expanded_instructions) { |
| 230 | ASSERT(entry->nr_insn == 1 |
| 231 | && entry->opcode == NULL |
| 232 | && entry->parent != NULL |
| 233 | && entry->parent->opcode != NULL); |
| 234 | ASSERT(entry->nr_insn == 1 |
| 235 | && entry->opcode == NULL |
| 236 | && entry->parent != NULL |
| 237 | && entry->parent->opcode != NULL |
| 238 | && entry->parent->opcode_rule != NULL); |
| 239 | print_c_semantic_function(file, |
| 240 | entry->insns, |
| 241 | entry->expanded_bits, |
| 242 | entry->parent->opcode, |
| 243 | cache_rules); |
| 244 | } |
| 245 | else { |
| 246 | print_c_semantic_function(file, instruction, |
| 247 | NULL, NULL, |
| 248 | cache_rules); |
| 249 | } |
| 250 | } |