| 1 | ## |
| 2 | ## Copyright(c) 2020-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. |
| 3 | ## |
| 4 | ## This program is free software; you can redistribute it and/or modify |
| 5 | ## it under the terms of the GNU General Public License as published by |
| 6 | ## the Free Software Foundation; either version 2 of the License, or |
| 7 | ## (at your option) any later version. |
| 8 | ## |
| 9 | ## This program is distributed in the hope that it will be useful, |
| 10 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | ## GNU General Public License for more details. |
| 13 | ## |
| 14 | ## You should have received a copy of the GNU General Public License |
| 15 | ## along with this program; if not, see <http://www.gnu.org/licenses/>. |
| 16 | ## |
| 17 | |
| 18 | hexagon_ss = ss.source_set() |
| 19 | |
| 20 | hex_common_py = 'hex_common.py' |
| 21 | gen_tcg_h = meson.current_source_dir() / 'gen_tcg.h' |
| 22 | gen_tcg_hvx_h = meson.current_source_dir() / 'gen_tcg_hvx.h' |
| 23 | gen_tcg_sys_h = meson.current_source_dir() / 'gen_tcg_sys.h' |
| 24 | idef_parser_dir = meson.current_source_dir() / 'idef-parser' |
| 25 | |
| 26 | # |
| 27 | # Step 1 |
| 28 | # We use a C program to create semantics_generated.pyinc |
| 29 | # |
| 30 | gen_semantics = executable( |
| 31 | 'gen_semantics', |
| 32 | 'gen_semantics.c', |
| 33 | native: true, build_by_default: false) |
| 34 | |
| 35 | semantics_generated = custom_target( |
| 36 | 'semantics_generated.pyinc', |
| 37 | output: 'semantics_generated.pyinc', |
| 38 | command: [gen_semantics, '@OUTPUT@'], |
| 39 | ) |
| 40 | hexagon_ss.add(semantics_generated) |
| 41 | |
| 42 | # |
| 43 | # Step 2 |
| 44 | # We use Python scripts to generate the following files |
| 45 | # printinsn_generated.h.inc |
| 46 | # op_attribs_generated.h.inc |
| 47 | # opcodes_def_generated.h.inc |
| 48 | # |
| 49 | printinsn_generated = custom_target( |
| 50 | 'printinsn_generated.h.inc', |
| 51 | output: 'printinsn_generated.h.inc', |
| 52 | depends: [semantics_generated], |
| 53 | depend_files: [hex_common_py], |
| 54 | command: [python, files('gen_printinsn.py'), semantics_generated, '@OUTPUT@'], |
| 55 | ) |
| 56 | hexagon_ss.add(printinsn_generated) |
| 57 | |
| 58 | op_attribs_generated = custom_target( |
| 59 | 'op_attribs_generated.h.inc', |
| 60 | output: 'op_attribs_generated.h.inc', |
| 61 | depends: [semantics_generated], |
| 62 | depend_files: [hex_common_py], |
| 63 | command: [python, files('gen_op_attribs.py'), semantics_generated, '@OUTPUT@'], |
| 64 | ) |
| 65 | hexagon_ss.add(op_attribs_generated) |
| 66 | |
| 67 | opcodes_def_generated = custom_target( |
| 68 | 'opcodes_def_generated.h.inc', |
| 69 | output: 'opcodes_def_generated.h.inc', |
| 70 | depends: [semantics_generated], |
| 71 | depend_files: [hex_common_py], |
| 72 | command: [python, files('gen_opcodes_def.py'), semantics_generated, '@OUTPUT@'], |
| 73 | ) |
| 74 | hexagon_ss.add(opcodes_def_generated) |
| 75 | |
| 76 | # |
| 77 | # Step 3 |
| 78 | # We use a C program to create iset.py which is imported into dectree.py |
| 79 | # to create the decode tree |
| 80 | # |
| 81 | gen_dectree_import = executable( |
| 82 | 'gen_dectree_import', |
| 83 | 'gen_dectree_import.c', opcodes_def_generated, |
| 84 | native: true, build_by_default: false) |
| 85 | |
| 86 | iset_py = custom_target( |
| 87 | 'iset.py', |
| 88 | output: 'iset.py', |
| 89 | command: [gen_dectree_import, '@OUTPUT@'], |
| 90 | ) |
| 91 | hexagon_ss.add(iset_py) |
| 92 | |
| 93 | # |
| 94 | # Step 4 |
| 95 | # Generate the input to the QEMU decodetree.py script |
| 96 | # |
| 97 | normal_decode_generated = custom_target( |
| 98 | 'normal_decode_generated', |
| 99 | output: 'normal_decode_generated', |
| 100 | depends: [iset_py, semantics_generated], |
| 101 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 102 | command: [python, files('gen_decodetree.py'), semantics_generated, 'NORMAL', '@OUTPUT@'], |
| 103 | ) |
| 104 | hexagon_ss.add(normal_decode_generated) |
| 105 | |
| 106 | hvx_decode_generated = custom_target( |
| 107 | 'hvx_decode_generated', |
| 108 | output: 'hvx_decode_generated', |
| 109 | depends: [iset_py, semantics_generated], |
| 110 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 111 | command: [python, files('gen_decodetree.py'), semantics_generated, 'EXT_mmvec', '@OUTPUT@'], |
| 112 | ) |
| 113 | hexagon_ss.add(hvx_decode_generated) |
| 114 | |
| 115 | subinsn_a_decode_generated = custom_target( |
| 116 | 'subinsn_a_decode_generated', |
| 117 | output: 'subinsn_a_decode_generated', |
| 118 | depends: [iset_py, semantics_generated], |
| 119 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 120 | command: [python, files('gen_decodetree.py'), semantics_generated, 'SUBINSN_A', '@OUTPUT@'], |
| 121 | ) |
| 122 | hexagon_ss.add(subinsn_a_decode_generated) |
| 123 | |
| 124 | subinsn_l1_decode_generated = custom_target( |
| 125 | 'subinsn_l1_decode_generated', |
| 126 | output: 'subinsn_l1_decode_generated', |
| 127 | depends: [iset_py, semantics_generated], |
| 128 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 129 | command: [python, files('gen_decodetree.py'), semantics_generated, 'SUBINSN_L1', '@OUTPUT@'], |
| 130 | ) |
| 131 | hexagon_ss.add(subinsn_l1_decode_generated) |
| 132 | |
| 133 | subinsn_l2_decode_generated = custom_target( |
| 134 | 'subinsn_l2_decode_generated', |
| 135 | output: 'subinsn_l2_decode_generated', |
| 136 | depends: [iset_py, semantics_generated], |
| 137 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 138 | command: [python, files('gen_decodetree.py'), semantics_generated, 'SUBINSN_L2', '@OUTPUT@'], |
| 139 | ) |
| 140 | hexagon_ss.add(subinsn_l2_decode_generated) |
| 141 | |
| 142 | subinsn_s1_decode_generated = custom_target( |
| 143 | 'subinsn_s1_decode_generated', |
| 144 | output: 'subinsn_s1_decode_generated', |
| 145 | depends: [iset_py, semantics_generated], |
| 146 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 147 | command: [python, files('gen_decodetree.py'), semantics_generated, 'SUBINSN_S1', '@OUTPUT@'], |
| 148 | ) |
| 149 | hexagon_ss.add(subinsn_s1_decode_generated) |
| 150 | |
| 151 | subinsn_s2_decode_generated = custom_target( |
| 152 | 'subinsn_s2_decode_generated', |
| 153 | output: 'subinsn_s2_decode_generated', |
| 154 | depends: [iset_py, semantics_generated], |
| 155 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 156 | command: [python, files('gen_decodetree.py'), semantics_generated, 'SUBINSN_S2', '@OUTPUT@'], |
| 157 | ) |
| 158 | hexagon_ss.add(subinsn_s2_decode_generated) |
| 159 | |
| 160 | # |
| 161 | # Run the QEMU decodetree.py script to produce the instruction decoder |
| 162 | # |
| 163 | decodetree_py = meson.current_source_dir() / '../../scripts/decodetree.py' |
| 164 | decode_normal_generated = custom_target( |
| 165 | 'decode_normal_generated.c.inc', |
| 166 | output: 'decode_normal_generated.c.inc', |
| 167 | input: normal_decode_generated, |
| 168 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 169 | command: [python, files(decodetree_py), normal_decode_generated, '--static-decode=decode_normal', '-o', '@OUTPUT@'], |
| 170 | ) |
| 171 | hexagon_ss.add(decode_normal_generated) |
| 172 | |
| 173 | decode_hvx_generated = custom_target( |
| 174 | 'decode_hvx_generated.c.inc', |
| 175 | output: 'decode_hvx_generated.c.inc', |
| 176 | input: hvx_decode_generated, |
| 177 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 178 | command: [python, files(decodetree_py), hvx_decode_generated, '--static-decode=decode_hvx', '-o', '@OUTPUT@'], |
| 179 | ) |
| 180 | hexagon_ss.add(decode_hvx_generated) |
| 181 | |
| 182 | decode_subinsn_a_generated = custom_target( |
| 183 | 'decode_subinsn_a_generated.c.inc', |
| 184 | output: 'decode_subinsn_a_generated.c.inc', |
| 185 | input: subinsn_a_decode_generated, |
| 186 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 187 | command: [python, files(decodetree_py), subinsn_a_decode_generated, ['--static-decode=decode_subinsn_a', '--insnwidth=16'], '-o', '@OUTPUT@'], |
| 188 | ) |
| 189 | hexagon_ss.add(decode_subinsn_a_generated) |
| 190 | |
| 191 | decode_subinsn_l1_generated = custom_target( |
| 192 | 'decode_subinsn_l1_generated.c.inc', |
| 193 | output: 'decode_subinsn_l1_generated.c.inc', |
| 194 | input: subinsn_l1_decode_generated, |
| 195 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 196 | command: [python, files(decodetree_py), subinsn_l1_decode_generated, ['--static-decode=decode_subinsn_l1', '--insnwidth=16'], '-o', '@OUTPUT@'], |
| 197 | ) |
| 198 | hexagon_ss.add(decode_subinsn_l1_generated) |
| 199 | |
| 200 | decode_subinsn_l2_generated = custom_target( |
| 201 | 'decode_subinsn_l2_generated.c.inc', |
| 202 | output: 'decode_subinsn_l2_generated.c.inc', |
| 203 | input: subinsn_l2_decode_generated, |
| 204 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 205 | command: [python, files(decodetree_py), subinsn_l2_decode_generated, ['--static-decode=decode_subinsn_l2', '--insnwidth=16'], '-o', '@OUTPUT@'], |
| 206 | ) |
| 207 | hexagon_ss.add(decode_subinsn_l2_generated) |
| 208 | |
| 209 | decode_subinsn_s1_generated = custom_target( |
| 210 | 'decode_subinsn_s1_generated.c.inc', |
| 211 | output: 'decode_subinsn_s1_generated.c.inc', |
| 212 | input: subinsn_s1_decode_generated, |
| 213 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 214 | command: [python, files(decodetree_py), subinsn_s1_decode_generated, ['--static-decode=decode_subinsn_s1', '--insnwidth=16'], '-o', '@OUTPUT@'], |
| 215 | ) |
| 216 | hexagon_ss.add(decode_subinsn_s1_generated) |
| 217 | |
| 218 | decode_subinsn_s2_generated = custom_target( |
| 219 | 'decode_subinsn_s2_generated.c.inc', |
| 220 | output: 'decode_subinsn_s2_generated.c.inc', |
| 221 | input: subinsn_s2_decode_generated, |
| 222 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 223 | command: [python, files(decodetree_py), subinsn_s2_decode_generated, ['--static-decode=decode_subinsn_s2', '--insnwidth=16'], '-o', '@OUTPUT@'], |
| 224 | ) |
| 225 | hexagon_ss.add(decode_subinsn_s2_generated) |
| 226 | |
| 227 | # |
| 228 | # Generate the trans_* functions that the decoder will use |
| 229 | # |
| 230 | decodetree_trans_funcs_generated = custom_target( |
| 231 | 'decodetree_trans_funcs_generated.c.inc', |
| 232 | output: 'decodetree_trans_funcs_generated.c.inc', |
| 233 | depends: [iset_py, semantics_generated], |
| 234 | env: {'PYTHONPATH': meson.current_build_dir()}, |
| 235 | command: [python, files('gen_trans_funcs.py'), semantics_generated, '@OUTPUT@'], |
| 236 | ) |
| 237 | hexagon_ss.add(decodetree_trans_funcs_generated) |
| 238 | hexagon_softmmu_ss = ss.source_set() |
| 239 | |
| 240 | hexagon_ss.add(files( |
| 241 | 'cpu.c', |
| 242 | 'translate.c', |
| 243 | 'op_helper.c', |
| 244 | 'gdbstub.c', |
| 245 | 'genptr.c', |
| 246 | 'reg_fields.c', |
| 247 | 'decode.c', |
| 248 | 'iclass.c', |
| 249 | 'opcodes.c', |
| 250 | 'printinsn.c', |
| 251 | 'arch.c', |
| 252 | 'fma_emu.c', |
| 253 | 'mmvec/decode_ext_mmvec.c', |
| 254 | 'mmvec/system_ext_mmvec.c', |
| 255 | 'mmvec/hvx_ieee_fp.c', |
| 256 | )) |
| 257 | |
| 258 | hexagon_softmmu_ss.add(files( |
| 259 | 'cpu_helper.c', |
| 260 | 'hex_mmu.c', |
| 261 | 'hex_interrupts.c', |
| 262 | 'hexswi.c', |
| 263 | 'machine.c', |
| 264 | )) |
| 265 | |
| 266 | # |
| 267 | # Step 4.5 |
| 268 | # We use flex/bison based idef-parser to generate TCG code for a lot |
| 269 | # of instructions. idef-parser outputs |
| 270 | # idef-generated-emitter.c |
| 271 | # idef-generated-emitter.h.inc |
| 272 | # idef-generated-enabled-instructions |
| 273 | # |
| 274 | idef_parser_enabled = get_option('hexagon_idef_parser') |
| 275 | if idef_parser_enabled and ('hexagon-linux-user' in target_dirs or |
| 276 | 'hexagon-softmmu' in target_dirs) |
| 277 | idef_parser_input_generated = custom_target( |
| 278 | 'idef_parser_input.h.inc', |
| 279 | output: 'idef_parser_input.h.inc', |
| 280 | depends: [semantics_generated], |
| 281 | depend_files: [hex_common_py], |
| 282 | command: [python, files('gen_idef_parser_funcs.py'), semantics_generated, '@OUTPUT@'], |
| 283 | ) |
| 284 | |
| 285 | compiler = meson.get_compiler('c').cmd_array() |
| 286 | preprocessed_idef_parser_input_generated = custom_target( |
| 287 | 'idef_parser_input.preprocessed.h.inc', |
| 288 | output: 'idef_parser_input.preprocessed.h.inc', |
| 289 | input: idef_parser_input_generated, |
| 290 | depend_files: [idef_parser_dir / 'macros.h.inc'], |
| 291 | command: compiler + ['-x', 'c', '-E', '-I', idef_parser_dir, '-o', '@OUTPUT@', '@INPUT@'], |
| 292 | ) |
| 293 | |
| 294 | flex = generator( |
| 295 | find_program('flex'), |
| 296 | output: ['@BASENAME@.yy.c', '@BASENAME@.yy.h'], |
| 297 | arguments: ['-o', '@OUTPUT0@', '--header-file=@OUTPUT1@', '@INPUT@'] |
| 298 | ) |
| 299 | |
| 300 | bison = generator( |
| 301 | find_program('bison', version: '>=3.0'), |
| 302 | output: ['@BASENAME@.tab.c', '@BASENAME@.tab.h'], |
| 303 | arguments: ['@INPUT@', '--defines=@OUTPUT1@', '--output=@OUTPUT0@'] |
| 304 | ) |
| 305 | |
| 306 | glib_dep = dependency('glib-2.0', native: true, static: false) |
| 307 | |
| 308 | idef_parser = executable( |
| 309 | 'idef-parser', |
| 310 | [flex.process(idef_parser_dir / 'idef-parser.lex'), |
| 311 | bison.process(idef_parser_dir / 'idef-parser.y'), |
| 312 | idef_parser_dir / 'parser-helpers.c'], |
| 313 | include_directories: ['idef-parser', '../../include/'], |
| 314 | dependencies: [glib_dep], |
| 315 | native: true |
| 316 | ) |
| 317 | |
| 318 | idef_generated_tcg = custom_target( |
| 319 | 'idef-generated-tcg', |
| 320 | output: ['idef-generated-emitter.c', |
| 321 | 'idef-generated-emitter.h.inc', |
| 322 | 'idef-generated-enabled-instructions'], |
| 323 | input: preprocessed_idef_parser_input_generated, |
| 324 | depend_files: [hex_common_py], |
| 325 | command: [idef_parser, '@INPUT@', '@OUTPUT0@', '@OUTPUT1@', '@OUTPUT2@'] |
| 326 | ) |
| 327 | |
| 328 | indent = find_program('indent', required: false) |
| 329 | if indent.found() and host_os == 'linux' |
| 330 | idef_generated_tcg_c = custom_target( |
| 331 | 'indent', |
| 332 | input: idef_generated_tcg[0], |
| 333 | output: 'idef-generated-emitter.indented.c', |
| 334 | command: [indent, '-linux', '@INPUT@', '-o', '@OUTPUT@'] |
| 335 | ) |
| 336 | else |
| 337 | idef_generated_tcg_c = custom_target( |
| 338 | 'copy', |
| 339 | input: idef_generated_tcg[0], |
| 340 | output: 'idef-generated-emitter.indented.c', |
| 341 | command: ['cp', '@INPUT@', '@OUTPUT@'] |
| 342 | ) |
| 343 | endif |
| 344 | |
| 345 | idef_generated_list = idef_generated_tcg[2].full_path() |
| 346 | |
| 347 | hexagon_ss.add(idef_generated_tcg_c) |
| 348 | |
| 349 | # Setup input and dependencies for the next step, this depends on whether or |
| 350 | # not idef-parser is enabled |
| 351 | helper_dep = [semantics_generated, idef_generated_tcg_c, idef_generated_tcg] |
| 352 | helper_in = [semantics_generated, gen_tcg_h, gen_tcg_hvx_h, gen_tcg_sys_h, '--idef-parser', idef_generated_list] |
| 353 | else |
| 354 | # Setup input and dependencies for the next step, this depends on whether or |
| 355 | # not idef-parser is enabled |
| 356 | helper_dep = [semantics_generated] |
| 357 | helper_in = [semantics_generated, gen_tcg_h, gen_tcg_hvx_h, gen_tcg_sys_h] |
| 358 | endif |
| 359 | |
| 360 | # |
| 361 | # Step 5 |
| 362 | # We use Python scripts to generate the following files |
| 363 | # helper_protos_generated.h.inc |
| 364 | # helper_funcs_generated.c.inc |
| 365 | # tcg_funcs_generated.c.inc |
| 366 | # |
| 367 | helper_protos_generated = custom_target( |
| 368 | 'helper_protos_generated.h.inc', |
| 369 | output: 'helper_protos_generated.h.inc', |
| 370 | depends: helper_dep, |
| 371 | depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h, gen_tcg_sys_h], |
| 372 | command: [python, files('gen_helper_protos.py'), helper_in, '@OUTPUT@'], |
| 373 | ) |
| 374 | hexagon_ss.add(helper_protos_generated) |
| 375 | |
| 376 | helper_funcs_generated = custom_target( |
| 377 | 'helper_funcs_generated.c.inc', |
| 378 | output: 'helper_funcs_generated.c.inc', |
| 379 | depends: helper_dep, |
| 380 | depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h, gen_tcg_sys_h], |
| 381 | command: [python, files('gen_helper_funcs.py'), helper_in, '@OUTPUT@'], |
| 382 | ) |
| 383 | hexagon_ss.add(helper_funcs_generated) |
| 384 | |
| 385 | tcg_funcs_generated = custom_target( |
| 386 | 'tcg_funcs_generated.c.inc', |
| 387 | output: 'tcg_funcs_generated.c.inc', |
| 388 | depends: helper_dep, |
| 389 | depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h, gen_tcg_sys_h], |
| 390 | command: [python, files('gen_tcg_funcs.py'), helper_in, '@OUTPUT@'], |
| 391 | ) |
| 392 | hexagon_ss.add(tcg_funcs_generated) |
| 393 | |
| 394 | analyze_funcs_generated = custom_target( |
| 395 | 'analyze_funcs_generated.c.inc', |
| 396 | output: 'analyze_funcs_generated.c.inc', |
| 397 | depends: helper_dep, |
| 398 | depend_files: [hex_common_py, gen_tcg_h, gen_tcg_hvx_h, gen_tcg_sys_h], |
| 399 | command: [python, files('gen_analyze_funcs.py'), helper_in, '@OUTPUT@'], |
| 400 | ) |
| 401 | hexagon_ss.add(analyze_funcs_generated) |
| 402 | |
| 403 | target_arch += {'hexagon': hexagon_ss} |
| 404 | target_system_arch += {'hexagon': hexagon_softmmu_ss} |