From 72a49d180057731beff280273118c62a2d3992c4 Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Fri, 31 Dec 2021 09:50:27 +0100 Subject: [PATCH] early-access version 2360 --- README.md | 2 +- externals/dynarmic/CMakeLists.txt | 29 + .../CMakeModules/dynarmicConfig.cmake.in | 5 + externals/dynarmic/externals/CMakeLists.txt | 4 +- .../dynarmic/src/dynarmic/CMakeLists.txt | 66 +- .../src/dynarmic/backend/x64/a32_emit_x64.cpp | 4 +- .../src/dynarmic/backend/x64/a32_emit_x64.h | 2 +- .../dynarmic/backend/x64/a32_interface.cpp | 2 +- .../src/dynarmic/backend/x64/a32_jitstate.cpp | 2 +- .../src/dynarmic/backend/x64/a64_emit_x64.cpp | 4 +- .../src/dynarmic/backend/x64/a64_emit_x64.h | 2 +- .../dynarmic/backend/x64/a64_interface.cpp | 2 +- .../src/dynarmic/backend/x64/a64_jitstate.cpp | 2 +- .../src/dynarmic/backend/x64/a64_jitstate.h | 2 +- .../dynarmic/frontend/A32/a32_ir_emitter.cpp | 441 ++++++++ .../dynarmic/frontend/A32/a32_ir_emitter.h | 114 +++ .../frontend/A32/a32_location_descriptor.cpp | 24 + .../frontend/A32/a32_location_descriptor.h | 153 +++ .../src/dynarmic/frontend/A32/a32_types.cpp | 80 ++ .../src/dynarmic/frontend/A32/a32_types.h | 149 +++ .../A32/disassembler/disassembler_arm.cpp | 2 +- .../A32/disassembler/disassembler_thumb.cpp | 2 +- .../frontend/A32/translate/a32_translate.cpp | 27 + .../frontend/A32/translate/a32_translate.h | 51 + .../A32/translate/conditional_state.cpp | 4 +- .../A32/translate/impl/a32_branch.cpp | 87 ++ .../frontend/A32/translate/impl/a32_crc32.cpp | 95 ++ .../impl/a32_exception_generating.cpp | 44 + .../A32/translate/impl/a32_translate_impl.cpp | 109 ++ .../A32/translate/impl/a32_translate_impl.h | 962 ++++++++++++++++++ .../impl/asimd_load_store_structures.cpp | 2 +- .../A32/translate/impl/asimd_misc.cpp | 2 +- .../impl/asimd_one_reg_modified_immediate.cpp | 2 +- .../A32/translate/impl/asimd_three_regs.cpp | 2 +- .../translate/impl/asimd_two_regs_misc.cpp | 2 +- .../translate/impl/asimd_two_regs_scalar.cpp | 2 +- .../translate/impl/asimd_two_regs_shift.cpp | 2 +- .../frontend/A32/translate/impl/barrier.cpp | 2 +- .../A32/translate/impl/coprocessor.cpp | 2 +- .../A32/translate/impl/data_processing.cpp | 2 +- .../frontend/A32/translate/impl/divide.cpp | 2 +- .../frontend/A32/translate/impl/extension.cpp | 2 +- .../frontend/A32/translate/impl/hint.cpp | 2 +- .../A32/translate/impl/load_store.cpp | 2 +- .../frontend/A32/translate/impl/misc.cpp | 2 +- .../frontend/A32/translate/impl/multiply.cpp | 2 +- .../frontend/A32/translate/impl/packing.cpp | 2 +- .../frontend/A32/translate/impl/parallel.cpp | 2 +- .../frontend/A32/translate/impl/reversal.cpp | 2 +- .../frontend/A32/translate/impl/saturated.cpp | 2 +- .../translate/impl/status_register_access.cpp | 2 +- .../A32/translate/impl/synchronization.cpp | 2 +- .../frontend/A32/translate/impl/thumb16.cpp | 2 +- .../A32/translate/impl/thumb32_branch.cpp | 2 +- .../A32/translate/impl/thumb32_control.cpp | 2 +- .../translate/impl/thumb32_coprocessor.cpp | 2 +- ...b32_data_processing_modified_immediate.cpp | 2 +- ...data_processing_plain_binary_immediate.cpp | 2 +- .../impl/thumb32_data_processing_register.cpp | 2 +- ...umb32_data_processing_shifted_register.cpp | 2 +- .../A32/translate/impl/thumb32_load_byte.cpp | 2 +- .../translate/impl/thumb32_load_halfword.cpp | 2 +- .../impl/thumb32_load_store_dual.cpp | 2 +- .../impl/thumb32_load_store_multiple.cpp | 2 +- .../A32/translate/impl/thumb32_load_word.cpp | 2 +- .../translate/impl/thumb32_long_multiply.cpp | 2 +- .../A32/translate/impl/thumb32_misc.cpp | 2 +- .../A32/translate/impl/thumb32_multiply.cpp | 2 +- .../A32/translate/impl/thumb32_parallel.cpp | 2 +- .../impl/thumb32_store_single_data_item.cpp | 2 +- .../frontend/A32/translate/impl/vfp.cpp | 2 +- .../frontend/A32/translate/translate_arm.cpp | 8 +- .../A32/translate/translate_thumb.cpp | 8 +- .../dynarmic/frontend/A64/a64_ir_emitter.cpp | 264 +++++ .../dynarmic/frontend/A64/a64_ir_emitter.h | 99 ++ .../frontend/A64/a64_location_descriptor.cpp | 19 + .../frontend/A64/a64_location_descriptor.h | 106 ++ .../src/dynarmic/frontend/A64/a64_types.cpp | 43 + .../src/dynarmic/frontend/A64/a64_types.h | 128 +++ .../frontend/A64/translate/a64_translate.cpp | 66 ++ .../frontend/A64/translate/a64_translate.h | 58 ++ .../A64/translate/impl/a64_branch.cpp | 128 +++ .../impl/a64_exception_generating.cpp | 22 + .../frontend/A64/translate/impl/impl.h | 8 +- .../dynarmic/src/dynarmic/ir/basic_block.cpp | 4 +- .../ir/opt/a32_get_set_elimination_pass.cpp | 2 +- .../ir/opt/a64_callback_config_pass.cpp | 2 +- .../ir/opt/a64_get_set_elimination_pass.cpp | 2 +- .../ir/opt/a64_merge_interpret_blocks.cpp | 4 +- externals/dynarmic/tests/A32/fuzz_arm.cpp | 6 +- externals/dynarmic/tests/A32/fuzz_thumb.cpp | 4 +- .../tests/A32/test_arm_instructions.cpp | 2 +- .../dynarmic/tests/A64/fuzz_with_unicorn.cpp | 6 +- externals/dynarmic/tests/decoder_tests.cpp | 2 +- externals/dynarmic/tests/print_info.cpp | 10 +- 95 files changed, 3430 insertions(+), 125 deletions(-) create mode 100755 externals/dynarmic/CMakeModules/dynarmicConfig.cmake.in create mode 100755 externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.cpp create mode 100755 externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h create mode 100755 externals/dynarmic/src/dynarmic/frontend/A32/a32_location_descriptor.cpp create mode 100755 externals/dynarmic/src/dynarmic/frontend/A32/a32_location_descriptor.h create mode 100755 externals/dynarmic/src/dynarmic/frontend/A32/a32_types.cpp create mode 100755 externals/dynarmic/src/dynarmic/frontend/A32/a32_types.h create mode 100755 externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.cpp create mode 100755 externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.h create mode 100755 externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_branch.cpp create mode 100755 externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_crc32.cpp create mode 100755 externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_exception_generating.cpp create mode 100755 externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.cpp create mode 100755 externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h create mode 100755 externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.cpp create mode 100755 externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.h create mode 100755 externals/dynarmic/src/dynarmic/frontend/A64/a64_location_descriptor.cpp create mode 100755 externals/dynarmic/src/dynarmic/frontend/A64/a64_location_descriptor.h create mode 100755 externals/dynarmic/src/dynarmic/frontend/A64/a64_types.cpp create mode 100755 externals/dynarmic/src/dynarmic/frontend/A64/a64_types.h create mode 100755 externals/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp create mode 100755 externals/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.h create mode 100755 externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/a64_branch.cpp create mode 100755 externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/a64_exception_generating.cpp diff --git a/README.md b/README.md index 962c1ed55..6b6985a19 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 2359. +This is the source code for early-access 2360. ## Legal Notice diff --git a/externals/dynarmic/CMakeLists.txt b/externals/dynarmic/CMakeLists.txt index ff98e034e..56b7f122d 100755 --- a/externals/dynarmic/CMakeLists.txt +++ b/externals/dynarmic/CMakeLists.txt @@ -171,3 +171,32 @@ add_subdirectory(src/dynarmic) if (DYNARMIC_TESTS) add_subdirectory(tests) endif() + +# +# Install +# +if (MASTER_PROJECT) + include(GNUInstallDirs) + include(CMakePackageConfigHelpers) + + install(TARGETS dynarmic EXPORT dynarmicTargets) + install(EXPORT dynarmicTargets + NAMESPACE dynarmic:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/dynarmic" + ) + + configure_package_config_file(CMakeModules/dynarmicConfig.cmake.in + dynarmicConfig.cmake + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/dynarmic" + ) + write_basic_package_version_file(dynarmicConfigVersion.cmake + COMPATIBILITY SameMajorVersion + ) + install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/dynarmicConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/dynarmicConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/dynarmic" + ) + + install(DIRECTORY src/dynarmic TYPE INCLUDE FILES_MATCHING PATTERN "*.h") +endif() diff --git a/externals/dynarmic/CMakeModules/dynarmicConfig.cmake.in b/externals/dynarmic/CMakeModules/dynarmicConfig.cmake.in new file mode 100755 index 000000000..8c9ad12aa --- /dev/null +++ b/externals/dynarmic/CMakeModules/dynarmicConfig.cmake.in @@ -0,0 +1,5 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") + +check_required_components(@PROJECT_NAME@) diff --git a/externals/dynarmic/externals/CMakeLists.txt b/externals/dynarmic/externals/CMakeLists.txt index 21ace6fb3..e20b5d026 100755 --- a/externals/dynarmic/externals/CMakeLists.txt +++ b/externals/dynarmic/externals/CMakeLists.txt @@ -24,9 +24,7 @@ target_include_directories(mp INTERFACE $") + add_subdirectory(robin-map) endif() # vixl diff --git a/externals/dynarmic/src/dynarmic/CMakeLists.txt b/externals/dynarmic/src/dynarmic/CMakeLists.txt index 902ac6145..b5f9b1762 100755 --- a/externals/dynarmic/src/dynarmic/CMakeLists.txt +++ b/externals/dynarmic/src/dynarmic/CMakeLists.txt @@ -64,10 +64,10 @@ add_library(dynarmic common/variant_util.h common/x64_disassemble.cpp common/x64_disassemble.h - frontend/A32/types.cpp - frontend/A32/types.h - frontend/A64/types.cpp - frontend/A64/types.h + frontend/A32/a32_types.cpp + frontend/A32/a32_types.h + frontend/A64/a64_types.cpp + frontend/A64/a64_types.h frontend/decoder/decoder_detail.h frontend/decoder/matcher.h frontend/imm.cpp @@ -115,12 +115,19 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS) frontend/A32/disassembler/disassembler_arm.cpp frontend/A32/disassembler/disassembler_thumb.cpp frontend/A32/FPSCR.h - frontend/A32/ir_emitter.cpp - frontend/A32/ir_emitter.h + frontend/A32/a32_ir_emitter.cpp + frontend/A32/a32_ir_emitter.h + frontend/A32/a32_location_descriptor.cpp + frontend/A32/a32_location_descriptor.h frontend/A32/ITState.h - frontend/A32/location_descriptor.cpp - frontend/A32/location_descriptor.h frontend/A32/PSR.h + frontend/A32/translate/a32_translate.cpp + frontend/A32/translate/a32_translate.h + frontend/A32/translate/impl/a32_branch.cpp + frontend/A32/translate/impl/a32_crc32.cpp + frontend/A32/translate/impl/a32_exception_generating.cpp + frontend/A32/translate/impl/a32_translate_impl.cpp + frontend/A32/translate/impl/a32_translate_impl.h frontend/A32/translate/conditional_state.cpp frontend/A32/translate/conditional_state.h frontend/A32/translate/impl/asimd_load_store_structures.cpp @@ -131,12 +138,9 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS) frontend/A32/translate/impl/asimd_two_regs_scalar.cpp frontend/A32/translate/impl/asimd_two_regs_shift.cpp frontend/A32/translate/impl/barrier.cpp - frontend/A32/translate/impl/branch.cpp frontend/A32/translate/impl/coprocessor.cpp - frontend/A32/translate/impl/crc32.cpp frontend/A32/translate/impl/data_processing.cpp frontend/A32/translate/impl/divide.cpp - frontend/A32/translate/impl/exception_generating.cpp frontend/A32/translate/impl/extension.cpp frontend/A32/translate/impl/hint.cpp frontend/A32/translate/impl/load_store.cpp @@ -166,11 +170,7 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS) frontend/A32/translate/impl/thumb32_multiply.cpp frontend/A32/translate/impl/thumb32_parallel.cpp frontend/A32/translate/impl/thumb32_store_single_data_item.cpp - frontend/A32/translate/impl/translate.cpp - frontend/A32/translate/impl/translate.h frontend/A32/translate/impl/vfp.cpp - frontend/A32/translate/translate.cpp - frontend/A32/translate/translate.h frontend/A32/translate/translate_arm.cpp frontend/A32/translate/translate_thumb.cpp interface/A32/a32.h @@ -186,13 +186,16 @@ endif() if ("A64" IN_LIST DYNARMIC_FRONTENDS) target_sources(dynarmic PRIVATE + frontend/A64/a64_ir_emitter.cpp + frontend/A64/a64_ir_emitter.h + frontend/A64/a64_location_descriptor.cpp + frontend/A64/a64_location_descriptor.h frontend/A64/decoder/a64.h frontend/A64/decoder/a64.inc - frontend/A64/ir_emitter.cpp - frontend/A64/ir_emitter.h - frontend/A64/location_descriptor.cpp - frontend/A64/location_descriptor.h - frontend/A64/translate/impl/branch.cpp + frontend/A64/translate/a64_translate.cpp + frontend/A64/translate/a64_translate.h + frontend/A64/translate/impl/a64_branch.cpp + frontend/A64/translate/impl/a64_exception_generating.cpp frontend/A64/translate/impl/data_processing_addsub.cpp frontend/A64/translate/impl/data_processing_bitfield.cpp frontend/A64/translate/impl/data_processing_conditional_compare.cpp @@ -203,7 +206,6 @@ if ("A64" IN_LIST DYNARMIC_FRONTENDS) frontend/A64/translate/impl/data_processing_pcrel.cpp frontend/A64/translate/impl/data_processing_register.cpp frontend/A64/translate/impl/data_processing_shift.cpp - frontend/A64/translate/impl/exception_generating.cpp frontend/A64/translate/impl/floating_point_compare.cpp frontend/A64/translate/impl/floating_point_conditional_compare.cpp frontend/A64/translate/impl/floating_point_conditional_select.cpp @@ -251,8 +253,6 @@ if ("A64" IN_LIST DYNARMIC_FRONTENDS) frontend/A64/translate/impl/system.cpp frontend/A64/translate/impl/system_flag_format.cpp frontend/A64/translate/impl/system_flag_manipulation.cpp - frontend/A64/translate/translate.cpp - frontend/A64/translate/translate.h interface/A64/a64.h interface/A64/config.h ir/opt/a64_callback_config_pass.cpp @@ -350,7 +350,7 @@ if (ARCHITECTURE STREQUAL "x86_64") endif() elseif (UNIX) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - target_link_libraries(dynarmic PUBLIC rt) + target_link_libraries(dynarmic PRIVATE rt) endif() target_sources(dynarmic PRIVATE backend/x64/exception_handler_posix.cpp) else() @@ -363,20 +363,24 @@ endif() include(CreateDirectoryGroups) create_target_directory_groups(dynarmic) -target_include_directories(dynarmic PUBLIC ..) +target_include_directories(dynarmic PUBLIC + $ + $ +) set_target_properties(dynarmic PROPERTIES VERSION ${dynarmic_VERSION} SOVERSION ${dynarmic_VERSION_MAJOR} ) target_compile_options(dynarmic PRIVATE ${DYNARMIC_CXX_FLAGS}) +# $ required because of https://gitlab.kitware.com/cmake/cmake/-/issues/15415 target_link_libraries(dynarmic - PUBLIC - boost - fmt::fmt - mp + PRIVATE + $ + $ + $ tsl::robin_map - xbyak - Zydis + $ + $ $<$:${llvm_libs}> ) if (DYNARMIC_ENABLE_CPU_FEATURE_DETECTION) diff --git a/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp b/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp index 4c09621d8..e8ddbce6d 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp +++ b/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp @@ -27,8 +27,8 @@ #include "dynarmic/common/scope_exit.h" #include "dynarmic/common/variant_util.h" #include "dynarmic/common/x64_disassemble.h" -#include "dynarmic/frontend/A32/location_descriptor.h" -#include "dynarmic/frontend/A32/types.h" +#include "dynarmic/frontend/A32/a32_location_descriptor.h" +#include "dynarmic/frontend/A32/a32_types.h" #include "dynarmic/interface/A32/coprocessor.h" #include "dynarmic/interface/exclusive_monitor.h" #include "dynarmic/ir/basic_block.h" diff --git a/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.h b/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.h index 93ab4b871..6684835f7 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.h +++ b/externals/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.h @@ -15,7 +15,7 @@ #include "dynarmic/backend/x64/a32_jitstate.h" #include "dynarmic/backend/x64/block_range_information.h" #include "dynarmic/backend/x64/emit_x64.h" -#include "dynarmic/frontend/A32/location_descriptor.h" +#include "dynarmic/frontend/A32/a32_location_descriptor.h" #include "dynarmic/interface/A32/a32.h" #include "dynarmic/interface/A32/config.h" #include "dynarmic/ir/terminal.h" diff --git a/externals/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp b/externals/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp index 24b48c038..49c7e8d0f 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp +++ b/externals/dynarmic/src/dynarmic/backend/x64/a32_interface.cpp @@ -20,7 +20,7 @@ #include "dynarmic/common/common_types.h" #include "dynarmic/common/scope_exit.h" #include "dynarmic/common/x64_disassemble.h" -#include "dynarmic/frontend/A32/translate/translate.h" +#include "dynarmic/frontend/A32/translate/a32_translate.h" #include "dynarmic/interface/A32/a32.h" #include "dynarmic/interface/A32/context.h" #include "dynarmic/ir/basic_block.h" diff --git a/externals/dynarmic/src/dynarmic/backend/x64/a32_jitstate.cpp b/externals/dynarmic/src/dynarmic/backend/x64/a32_jitstate.cpp index 4d9cf07b7..2d8447808 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/a32_jitstate.cpp +++ b/externals/dynarmic/src/dynarmic/backend/x64/a32_jitstate.cpp @@ -10,7 +10,7 @@ #include "dynarmic/common/assert.h" #include "dynarmic/common/bit_util.h" #include "dynarmic/common/common_types.h" -#include "dynarmic/frontend/A32/location_descriptor.h" +#include "dynarmic/frontend/A32/a32_location_descriptor.h" namespace Dynarmic::Backend::X64 { diff --git a/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp b/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp index 6690e68e5..de54a4445 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp +++ b/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp @@ -24,8 +24,8 @@ #include "dynarmic/common/common_types.h" #include "dynarmic/common/scope_exit.h" #include "dynarmic/common/x64_disassemble.h" -#include "dynarmic/frontend/A64/location_descriptor.h" -#include "dynarmic/frontend/A64/types.h" +#include "dynarmic/frontend/A64/a64_location_descriptor.h" +#include "dynarmic/frontend/A64/a64_types.h" #include "dynarmic/interface/exclusive_monitor.h" #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/cond.h" diff --git a/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.h b/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.h index 32c14a6b9..32ab24e85 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.h +++ b/externals/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.h @@ -12,7 +12,7 @@ #include "dynarmic/backend/x64/a64_jitstate.h" #include "dynarmic/backend/x64/block_range_information.h" #include "dynarmic/backend/x64/emit_x64.h" -#include "dynarmic/frontend/A64/location_descriptor.h" +#include "dynarmic/frontend/A64/a64_location_descriptor.h" #include "dynarmic/interface/A64/a64.h" #include "dynarmic/interface/A64/config.h" #include "dynarmic/ir/terminal.h" diff --git a/externals/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp b/externals/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp index cb4ed12a3..c19c4939b 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp +++ b/externals/dynarmic/src/dynarmic/backend/x64/a64_interface.cpp @@ -17,7 +17,7 @@ #include "dynarmic/common/assert.h" #include "dynarmic/common/scope_exit.h" #include "dynarmic/common/x64_disassemble.h" -#include "dynarmic/frontend/A64/translate/translate.h" +#include "dynarmic/frontend/A64/translate/a64_translate.h" #include "dynarmic/interface/A64/a64.h" #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/opt/passes.h" diff --git a/externals/dynarmic/src/dynarmic/backend/x64/a64_jitstate.cpp b/externals/dynarmic/src/dynarmic/backend/x64/a64_jitstate.cpp index c0e7a1c6a..c7d0e5970 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/a64_jitstate.cpp +++ b/externals/dynarmic/src/dynarmic/backend/x64/a64_jitstate.cpp @@ -6,7 +6,7 @@ #include "dynarmic/backend/x64/a64_jitstate.h" #include "dynarmic/common/bit_util.h" -#include "dynarmic/frontend/A64/location_descriptor.h" +#include "dynarmic/frontend/A64/a64_location_descriptor.h" namespace Dynarmic::Backend::X64 { diff --git a/externals/dynarmic/src/dynarmic/backend/x64/a64_jitstate.h b/externals/dynarmic/src/dynarmic/backend/x64/a64_jitstate.h index bd3d8989a..a0e20cff2 100755 --- a/externals/dynarmic/src/dynarmic/backend/x64/a64_jitstate.h +++ b/externals/dynarmic/src/dynarmic/backend/x64/a64_jitstate.h @@ -9,7 +9,7 @@ #include "dynarmic/backend/x64/nzcv_util.h" #include "dynarmic/common/common_types.h" -#include "dynarmic/frontend/A64/location_descriptor.h" +#include "dynarmic/frontend/A64/a64_location_descriptor.h" namespace Dynarmic::Backend::X64 { diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.cpp new file mode 100755 index 000000000..8363f81f6 --- /dev/null +++ b/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.cpp @@ -0,0 +1,441 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include "dynarmic/frontend/A32/a32_ir_emitter.h" + +#include "dynarmic/common/assert.h" +#include "dynarmic/frontend/A32/a32_types.h" +#include "dynarmic/interface/A32/arch_version.h" +#include "dynarmic/ir/opcodes.h" + +namespace Dynarmic::A32 { + +using Opcode = IR::Opcode; + +size_t IREmitter::ArchVersion() const { + switch (arch_version) { + case ArchVersion::v3: + return 3; + case ArchVersion::v4: + case ArchVersion::v4T: + return 4; + case ArchVersion::v5TE: + return 5; + case ArchVersion::v6K: + case ArchVersion::v6T2: + return 6; + case ArchVersion::v7: + return 7; + case ArchVersion::v8: + return 8; + } + UNREACHABLE(); +} + +u32 IREmitter::PC() const { + const u32 offset = current_location.TFlag() ? 4 : 8; + return current_location.PC() + offset; +} + +u32 IREmitter::AlignPC(size_t alignment) const { + const u32 pc = PC(); + return static_cast(pc - pc % alignment); +} + +IR::U32 IREmitter::GetRegister(Reg reg) { + if (reg == A32::Reg::PC) { + return Imm32(PC()); + } + return Inst(Opcode::A32GetRegister, IR::Value(reg)); +} + +IR::U32U64 IREmitter::GetExtendedRegister(ExtReg reg) { + if (A32::IsSingleExtReg(reg)) { + return Inst(Opcode::A32GetExtendedRegister32, IR::Value(reg)); + } + + if (A32::IsDoubleExtReg(reg)) { + return Inst(Opcode::A32GetExtendedRegister64, IR::Value(reg)); + } + + ASSERT_FALSE("Invalid reg."); +} + +IR::U128 IREmitter::GetVector(ExtReg reg) { + ASSERT(A32::IsDoubleExtReg(reg) || A32::IsQuadExtReg(reg)); + return Inst(Opcode::A32GetVector, IR::Value(reg)); +} + +void IREmitter::SetRegister(const Reg reg, const IR::U32& value) { + ASSERT(reg != A32::Reg::PC); + Inst(Opcode::A32SetRegister, IR::Value(reg), value); +} + +void IREmitter::SetExtendedRegister(const ExtReg reg, const IR::U32U64& value) { + if (A32::IsSingleExtReg(reg)) { + Inst(Opcode::A32SetExtendedRegister32, IR::Value(reg), value); + } else if (A32::IsDoubleExtReg(reg)) { + Inst(Opcode::A32SetExtendedRegister64, IR::Value(reg), value); + } else { + ASSERT_FALSE("Invalid reg."); + } +} + +void IREmitter::SetVector(ExtReg reg, const IR::U128& value) { + ASSERT(A32::IsDoubleExtReg(reg) || A32::IsQuadExtReg(reg)); + Inst(Opcode::A32SetVector, IR::Value(reg), value); +} + +void IREmitter::ALUWritePC(const IR::U32& value) { + // This behaviour is ARM version-dependent. + if (ArchVersion() >= 7 && !current_location.TFlag()) { + BXWritePC(value); + } else { + BranchWritePC(value); + } +} + +void IREmitter::BranchWritePC(const IR::U32& value) { + if (!current_location.TFlag()) { + // Note that for ArchVersion() < 6, this is UNPREDICTABLE when value<1:0> != 0b00 + const auto new_pc = And(value, Imm32(0xFFFFFFFC)); + Inst(Opcode::A32SetRegister, IR::Value(A32::Reg::PC), new_pc); + } else { + const auto new_pc = And(value, Imm32(0xFFFFFFFE)); + Inst(Opcode::A32SetRegister, IR::Value(A32::Reg::PC), new_pc); + } +} + +void IREmitter::BXWritePC(const IR::U32& value) { + Inst(Opcode::A32BXWritePC, value); +} + +void IREmitter::LoadWritePC(const IR::U32& value) { + // This behaviour is ARM version-dependent. + if (ArchVersion() >= 5) { + BXWritePC(value); + } else { + BranchWritePC(value); + } +} + +void IREmitter::UpdateUpperLocationDescriptor() { + Inst(Opcode::A32UpdateUpperLocationDescriptor); +} + +void IREmitter::CallSupervisor(const IR::U32& value) { + Inst(Opcode::A32CallSupervisor, value); +} + +void IREmitter::ExceptionRaised(const Exception exception) { + Inst(Opcode::A32ExceptionRaised, Imm32(current_location.PC()), Imm64(static_cast(exception))); +} + +IR::U32 IREmitter::GetCpsr() { + return Inst(Opcode::A32GetCpsr); +} + +void IREmitter::SetCpsr(const IR::U32& value) { + Inst(Opcode::A32SetCpsr, value); +} + +void IREmitter::SetCpsrNZCV(const IR::NZCV& value) { + Inst(Opcode::A32SetCpsrNZCV, value); +} + +void IREmitter::SetCpsrNZCVRaw(const IR::U32& value) { + Inst(Opcode::A32SetCpsrNZCVRaw, value); +} + +void IREmitter::SetCpsrNZCVQ(const IR::U32& value) { + Inst(Opcode::A32SetCpsrNZCVQ, value); +} + +void IREmitter::SetCheckBit(const IR::U1& value) { + Inst(Opcode::A32SetCheckBit, value); +} + +IR::U1 IREmitter::GetOverflowFrom(const IR::Value& value) { + return Inst(Opcode::GetOverflowFromOp, value); +} + +IR::U1 IREmitter::GetCFlag() { + return Inst(Opcode::A32GetCFlag); +} + +void IREmitter::SetNFlag(const IR::U1& value) { + Inst(Opcode::A32SetNFlag, value); +} + +void IREmitter::SetZFlag(const IR::U1& value) { + Inst(Opcode::A32SetZFlag, value); +} + +void IREmitter::SetCFlag(const IR::U1& value) { + Inst(Opcode::A32SetCFlag, value); +} + +void IREmitter::SetVFlag(const IR::U1& value) { + Inst(Opcode::A32SetVFlag, value); +} + +void IREmitter::OrQFlag(const IR::U1& value) { + Inst(Opcode::A32OrQFlag, value); +} + +IR::U32 IREmitter::GetGEFlags() { + return Inst(Opcode::A32GetGEFlags); +} + +void IREmitter::SetGEFlags(const IR::U32& value) { + Inst(Opcode::A32SetGEFlags, value); +} + +void IREmitter::SetGEFlagsCompressed(const IR::U32& value) { + Inst(Opcode::A32SetGEFlagsCompressed, value); +} + +void IREmitter::DataSynchronizationBarrier() { + Inst(Opcode::A32DataSynchronizationBarrier); +} + +void IREmitter::DataMemoryBarrier() { + Inst(Opcode::A32DataMemoryBarrier); +} + +void IREmitter::InstructionSynchronizationBarrier() { + Inst(Opcode::A32InstructionSynchronizationBarrier); +} + +IR::U32 IREmitter::GetFpscr() { + return Inst(Opcode::A32GetFpscr); +} + +void IREmitter::SetFpscr(const IR::U32& new_fpscr) { + Inst(Opcode::A32SetFpscr, new_fpscr); +} + +IR::U32 IREmitter::GetFpscrNZCV() { + return Inst(Opcode::A32GetFpscrNZCV); +} + +void IREmitter::SetFpscrNZCV(const IR::NZCV& new_fpscr_nzcv) { + Inst(Opcode::A32SetFpscrNZCV, new_fpscr_nzcv); +} + +void IREmitter::ClearExclusive() { + Inst(Opcode::A32ClearExclusive); +} + +IR::UAny IREmitter::ReadMemory(size_t bitsize, const IR::U32& vaddr) { + switch (bitsize) { + case 8: + return ReadMemory8(vaddr); + case 16: + return ReadMemory16(vaddr); + case 32: + return ReadMemory32(vaddr); + case 64: + return ReadMemory64(vaddr); + } + ASSERT_FALSE("Invalid bitsize"); +} + +IR::U8 IREmitter::ReadMemory8(const IR::U32& vaddr) { + return Inst(Opcode::A32ReadMemory8, vaddr); +} + +IR::U16 IREmitter::ReadMemory16(const IR::U32& vaddr) { + const auto value = Inst(Opcode::A32ReadMemory16, vaddr); + return current_location.EFlag() ? ByteReverseHalf(value) : value; +} + +IR::U32 IREmitter::ReadMemory32(const IR::U32& vaddr) { + const auto value = Inst(Opcode::A32ReadMemory32, vaddr); + return current_location.EFlag() ? ByteReverseWord(value) : value; +} + +IR::U64 IREmitter::ReadMemory64(const IR::U32& vaddr) { + const auto value = Inst(Opcode::A32ReadMemory64, vaddr); + return current_location.EFlag() ? ByteReverseDual(value) : value; +} + +IR::U8 IREmitter::ExclusiveReadMemory8(const IR::U32& vaddr) { + return Inst(Opcode::A32ExclusiveReadMemory8, vaddr); +} + +IR::U16 IREmitter::ExclusiveReadMemory16(const IR::U32& vaddr) { + const auto value = Inst(Opcode::A32ExclusiveReadMemory16, vaddr); + return current_location.EFlag() ? ByteReverseHalf(value) : value; +} + +IR::U32 IREmitter::ExclusiveReadMemory32(const IR::U32& vaddr) { + const auto value = Inst(Opcode::A32ExclusiveReadMemory32, vaddr); + return current_location.EFlag() ? ByteReverseWord(value) : value; +} + +std::pair IREmitter::ExclusiveReadMemory64(const IR::U32& vaddr) { + const auto value = Inst(Opcode::A32ExclusiveReadMemory64, vaddr); + const auto lo = LeastSignificantWord(value); + const auto hi = MostSignificantWord(value).result; + if (current_location.EFlag()) { + // DO NOT SWAP hi AND lo IN BIG ENDIAN MODE, THIS IS CORRECT BEHAVIOUR + return std::make_pair(ByteReverseWord(lo), ByteReverseWord(hi)); + } + return std::make_pair(lo, hi); +} + +void IREmitter::WriteMemory(size_t bitsize, const IR::U32& vaddr, const IR::UAny& value) { + switch (bitsize) { + case 8: + return WriteMemory8(vaddr, value); + case 16: + return WriteMemory16(vaddr, value); + case 32: + return WriteMemory32(vaddr, value); + case 64: + return WriteMemory64(vaddr, value); + } + ASSERT_FALSE("Invalid bitsize"); +} + +void IREmitter::WriteMemory8(const IR::U32& vaddr, const IR::U8& value) { + Inst(Opcode::A32WriteMemory8, vaddr, value); +} + +void IREmitter::WriteMemory16(const IR::U32& vaddr, const IR::U16& value) { + if (current_location.EFlag()) { + const auto v = ByteReverseHalf(value); + Inst(Opcode::A32WriteMemory16, vaddr, v); + } else { + Inst(Opcode::A32WriteMemory16, vaddr, value); + } +} + +void IREmitter::WriteMemory32(const IR::U32& vaddr, const IR::U32& value) { + if (current_location.EFlag()) { + const auto v = ByteReverseWord(value); + Inst(Opcode::A32WriteMemory32, vaddr, v); + } else { + Inst(Opcode::A32WriteMemory32, vaddr, value); + } +} + +void IREmitter::WriteMemory64(const IR::U32& vaddr, const IR::U64& value) { + if (current_location.EFlag()) { + const auto v = ByteReverseDual(value); + Inst(Opcode::A32WriteMemory64, vaddr, v); + } else { + Inst(Opcode::A32WriteMemory64, vaddr, value); + } +} + +IR::U32 IREmitter::ExclusiveWriteMemory8(const IR::U32& vaddr, const IR::U8& value) { + return Inst(Opcode::A32ExclusiveWriteMemory8, vaddr, value); +} + +IR::U32 IREmitter::ExclusiveWriteMemory16(const IR::U32& vaddr, const IR::U16& value) { + if (current_location.EFlag()) { + const auto v = ByteReverseHalf(value); + return Inst(Opcode::A32ExclusiveWriteMemory16, vaddr, v); + } else { + return Inst(Opcode::A32ExclusiveWriteMemory16, vaddr, value); + } +} + +IR::U32 IREmitter::ExclusiveWriteMemory32(const IR::U32& vaddr, const IR::U32& value) { + if (current_location.EFlag()) { + const auto v = ByteReverseWord(value); + return Inst(Opcode::A32ExclusiveWriteMemory32, vaddr, v); + } else { + return Inst(Opcode::A32ExclusiveWriteMemory32, vaddr, value); + } +} + +IR::U32 IREmitter::ExclusiveWriteMemory64(const IR::U32& vaddr, const IR::U32& value_lo, const IR::U32& value_hi) { + if (current_location.EFlag()) { + const auto vlo = ByteReverseWord(value_lo); + const auto vhi = ByteReverseWord(value_hi); + return Inst(Opcode::A32ExclusiveWriteMemory64, vaddr, Pack2x32To1x64(vlo, vhi)); + } else { + return Inst(Opcode::A32ExclusiveWriteMemory64, vaddr, Pack2x32To1x64(value_lo, value_hi)); + } +} + +void IREmitter::CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, CoprocReg CRd, CoprocReg CRn, CoprocReg CRm, size_t opc2) { + ASSERT(coproc_no <= 15); + const IR::Value::CoprocessorInfo coproc_info{static_cast(coproc_no), + static_cast(two ? 1 : 0), + static_cast(opc1), + static_cast(CRd), + static_cast(CRn), + static_cast(CRm), + static_cast(opc2)}; + Inst(Opcode::A32CoprocInternalOperation, IR::Value(coproc_info)); +} + +void IREmitter::CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, CoprocReg CRn, CoprocReg CRm, size_t opc2, const IR::U32& word) { + ASSERT(coproc_no <= 15); + const IR::Value::CoprocessorInfo coproc_info{static_cast(coproc_no), + static_cast(two ? 1 : 0), + static_cast(opc1), + static_cast(CRn), + static_cast(CRm), + static_cast(opc2)}; + Inst(Opcode::A32CoprocSendOneWord, IR::Value(coproc_info), word); +} + +void IREmitter::CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, CoprocReg CRm, const IR::U32& word1, const IR::U32& word2) { + ASSERT(coproc_no <= 15); + const IR::Value::CoprocessorInfo coproc_info{static_cast(coproc_no), + static_cast(two ? 1 : 0), + static_cast(opc), + static_cast(CRm)}; + Inst(Opcode::A32CoprocSendTwoWords, IR::Value(coproc_info), word1, word2); +} + +IR::U32 IREmitter::CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, CoprocReg CRn, CoprocReg CRm, size_t opc2) { + ASSERT(coproc_no <= 15); + const IR::Value::CoprocessorInfo coproc_info{static_cast(coproc_no), + static_cast(two ? 1 : 0), + static_cast(opc1), + static_cast(CRn), + static_cast(CRm), + static_cast(opc2)}; + return Inst(Opcode::A32CoprocGetOneWord, IR::Value(coproc_info)); +} + +IR::U64 IREmitter::CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, CoprocReg CRm) { + ASSERT(coproc_no <= 15); + const IR::Value::CoprocessorInfo coproc_info{static_cast(coproc_no), + static_cast(two ? 1 : 0), + static_cast(opc), + static_cast(CRm)}; + return Inst(Opcode::A32CoprocGetTwoWords, IR::Value(coproc_info)); +} + +void IREmitter::CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, CoprocReg CRd, const IR::U32& address, bool has_option, u8 option) { + ASSERT(coproc_no <= 15); + const IR::Value::CoprocessorInfo coproc_info{static_cast(coproc_no), + static_cast(two ? 1 : 0), + static_cast(long_transfer ? 1 : 0), + static_cast(CRd), + static_cast(has_option ? 1 : 0), + static_cast(option)}; + Inst(Opcode::A32CoprocLoadWords, IR::Value(coproc_info), address); +} + +void IREmitter::CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, CoprocReg CRd, const IR::U32& address, bool has_option, u8 option) { + ASSERT(coproc_no <= 15); + const IR::Value::CoprocessorInfo coproc_info{static_cast(coproc_no), + static_cast(two ? 1 : 0), + static_cast(long_transfer ? 1 : 0), + static_cast(CRd), + static_cast(has_option ? 1 : 0), + static_cast(option)}; + Inst(Opcode::A32CoprocStoreWords, IR::Value(coproc_info), address); +} + +} // namespace Dynarmic::A32 diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h b/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h new file mode 100755 index 000000000..7b6b1b03a --- /dev/null +++ b/externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h @@ -0,0 +1,114 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +#include + +#include "dynarmic/common/common_types.h" +#include "dynarmic/frontend/A32/a32_location_descriptor.h" +#include "dynarmic/ir/ir_emitter.h" +#include "dynarmic/ir/value.h" + +namespace Dynarmic::A32 { + +enum class ArchVersion; +enum class CoprocReg; +enum class Exception; +enum class ExtReg; +enum class Reg; + +/** + * Convenience class to construct a basic block of the intermediate representation. + * `block` is the resulting block. + * The user of this class updates `current_location` as appropriate. + */ +class IREmitter : public IR::IREmitter { +public: + IREmitter(IR::Block& block, LocationDescriptor descriptor, ArchVersion arch_version) + : IR::IREmitter(block), current_location(descriptor), arch_version(arch_version) {} + + LocationDescriptor current_location; + + size_t ArchVersion() const; + + u32 PC() const; + u32 AlignPC(size_t alignment) const; + + IR::U32 GetRegister(Reg source_reg); + IR::U32U64 GetExtendedRegister(ExtReg source_reg); + IR::U128 GetVector(ExtReg source_reg); + void SetRegister(Reg dest_reg, const IR::U32& value); + void SetExtendedRegister(ExtReg dest_reg, const IR::U32U64& value); + void SetVector(ExtReg dest_reg, const IR::U128& value); + + void ALUWritePC(const IR::U32& value); + void BranchWritePC(const IR::U32& value); + void BXWritePC(const IR::U32& value); + void LoadWritePC(const IR::U32& value); + void UpdateUpperLocationDescriptor(); + + void CallSupervisor(const IR::U32& value); + void ExceptionRaised(Exception exception); + + IR::U32 GetCpsr(); + void SetCpsr(const IR::U32& value); + void SetCpsrNZCV(const IR::NZCV& value); + void SetCpsrNZCVRaw(const IR::U32& value); + void SetCpsrNZCVQ(const IR::U32& value); + void SetCheckBit(const IR::U1& value); + IR::U1 GetOverflowFrom(const IR::Value& value); + IR::U1 GetCFlag(); + void SetNFlag(const IR::U1& value); + void SetZFlag(const IR::U1& value); + void SetCFlag(const IR::U1& value); + void SetVFlag(const IR::U1& value); + void OrQFlag(const IR::U1& value); + IR::U32 GetGEFlags(); + void SetGEFlags(const IR::U32& value); + void SetGEFlagsCompressed(const IR::U32& value); + + void DataSynchronizationBarrier(); + void DataMemoryBarrier(); + void InstructionSynchronizationBarrier(); + + IR::U32 GetFpscr(); + void SetFpscr(const IR::U32& new_fpscr); + IR::U32 GetFpscrNZCV(); + void SetFpscrNZCV(const IR::NZCV& new_fpscr_nzcv); + + void ClearExclusive(); + IR::UAny ReadMemory(size_t bitsize, const IR::U32& vaddr); + IR::U8 ReadMemory8(const IR::U32& vaddr); + IR::U16 ReadMemory16(const IR::U32& vaddr); + IR::U32 ReadMemory32(const IR::U32& vaddr); + IR::U64 ReadMemory64(const IR::U32& vaddr); + IR::U8 ExclusiveReadMemory8(const IR::U32& vaddr); + IR::U16 ExclusiveReadMemory16(const IR::U32& vaddr); + IR::U32 ExclusiveReadMemory32(const IR::U32& vaddr); + std::pair ExclusiveReadMemory64(const IR::U32& vaddr); + void WriteMemory(size_t bitsize, const IR::U32& vaddr, const IR::UAny& value); + void WriteMemory8(const IR::U32& vaddr, const IR::U8& value); + void WriteMemory16(const IR::U32& vaddr, const IR::U16& value); + void WriteMemory32(const IR::U32& vaddr, const IR::U32& value); + void WriteMemory64(const IR::U32& vaddr, const IR::U64& value); + IR::U32 ExclusiveWriteMemory8(const IR::U32& vaddr, const IR::U8& value); + IR::U32 ExclusiveWriteMemory16(const IR::U32& vaddr, const IR::U16& value); + IR::U32 ExclusiveWriteMemory32(const IR::U32& vaddr, const IR::U32& value); + IR::U32 ExclusiveWriteMemory64(const IR::U32& vaddr, const IR::U32& value_lo, const IR::U32& value_hi); + + void CoprocInternalOperation(size_t coproc_no, bool two, size_t opc1, CoprocReg CRd, CoprocReg CRn, CoprocReg CRm, size_t opc2); + void CoprocSendOneWord(size_t coproc_no, bool two, size_t opc1, CoprocReg CRn, CoprocReg CRm, size_t opc2, const IR::U32& word); + void CoprocSendTwoWords(size_t coproc_no, bool two, size_t opc, CoprocReg CRm, const IR::U32& word1, const IR::U32& word2); + IR::U32 CoprocGetOneWord(size_t coproc_no, bool two, size_t opc1, CoprocReg CRn, CoprocReg CRm, size_t opc2); + IR::U64 CoprocGetTwoWords(size_t coproc_no, bool two, size_t opc, CoprocReg CRm); + void CoprocLoadWords(size_t coproc_no, bool two, bool long_transfer, CoprocReg CRd, const IR::U32& address, bool has_option, u8 option); + void CoprocStoreWords(size_t coproc_no, bool two, bool long_transfer, CoprocReg CRd, const IR::U32& address, bool has_option, u8 option); + +private: + enum ArchVersion arch_version; +}; + +} // namespace Dynarmic::A32 diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/a32_location_descriptor.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/a32_location_descriptor.cpp new file mode 100755 index 000000000..62a94113f --- /dev/null +++ b/externals/dynarmic/src/dynarmic/frontend/A32/a32_location_descriptor.cpp @@ -0,0 +1,24 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include "dynarmic/frontend/A32/a32_location_descriptor.h" + +#include + +#include + +namespace Dynarmic::A32 { + +std::ostream& operator<<(std::ostream& o, const LocationDescriptor& descriptor) { + o << fmt::format("{{{:08x},{},{},{:08x}{}}}", + descriptor.PC(), + descriptor.TFlag() ? "T" : "!T", + descriptor.EFlag() ? "E" : "!E", + descriptor.FPSCR().Value(), + descriptor.SingleStepping() ? ",step" : ""); + return o; +} + +} // namespace Dynarmic::A32 diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/a32_location_descriptor.h b/externals/dynarmic/src/dynarmic/frontend/A32/a32_location_descriptor.h new file mode 100755 index 000000000..4b68d2def --- /dev/null +++ b/externals/dynarmic/src/dynarmic/frontend/A32/a32_location_descriptor.h @@ -0,0 +1,153 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +#include +#include +#include + +#include "dynarmic/common/common_types.h" +#include "dynarmic/frontend/A32/FPSCR.h" +#include "dynarmic/frontend/A32/ITState.h" +#include "dynarmic/frontend/A32/PSR.h" +#include "dynarmic/ir/location_descriptor.h" + +namespace Dynarmic::A32 { + +/** + * LocationDescriptor describes the location of a basic block. + * The location is not solely based on the PC because other flags influence the way + * instructions should be translated. The CPSR.T flag is most notable since it + * tells us if the processor is in Thumb or Arm mode. + */ +class LocationDescriptor { +public: + // Indicates bits that should be preserved within descriptors. + static constexpr u32 CPSR_MODE_MASK = 0x0600FE20; + static constexpr u32 FPSCR_MODE_MASK = 0x07F70000; + + LocationDescriptor(u32 arm_pc, PSR cpsr, FPSCR fpscr, bool single_stepping = false) + : arm_pc(arm_pc) + , cpsr(cpsr.Value() & CPSR_MODE_MASK) + , fpscr(fpscr.Value() & FPSCR_MODE_MASK) + , single_stepping(single_stepping) {} + + explicit LocationDescriptor(const IR::LocationDescriptor& o) { + arm_pc = static_cast(o.Value()); + cpsr.T((o.Value() >> 32) & 1); + cpsr.E((o.Value() >> 32) & 2); + fpscr = (o.Value() >> 32) & FPSCR_MODE_MASK; + cpsr.IT(ITState{static_cast(o.Value() >> 40)}); + single_stepping = (o.Value() >> 32) & 4; + } + + u32 PC() const { return arm_pc; } + bool TFlag() const { return cpsr.T(); } + bool EFlag() const { return cpsr.E(); } + ITState IT() const { return cpsr.IT(); } + + A32::PSR CPSR() const { return cpsr; } + A32::FPSCR FPSCR() const { return fpscr; } + + bool SingleStepping() const { return single_stepping; } + + bool operator==(const LocationDescriptor& o) const { + return std::tie(arm_pc, cpsr, fpscr, single_stepping) == std::tie(o.arm_pc, o.cpsr, o.fpscr, o.single_stepping); + } + + bool operator!=(const LocationDescriptor& o) const { + return !operator==(o); + } + + LocationDescriptor SetPC(u32 new_arm_pc) const { + return LocationDescriptor(new_arm_pc, cpsr, fpscr, single_stepping); + } + + LocationDescriptor AdvancePC(int amount) const { + return LocationDescriptor(static_cast(arm_pc + amount), cpsr, fpscr, single_stepping); + } + + LocationDescriptor SetTFlag(bool new_tflag) const { + PSR new_cpsr = cpsr; + new_cpsr.T(new_tflag); + + return LocationDescriptor(arm_pc, new_cpsr, fpscr, single_stepping); + } + + LocationDescriptor SetEFlag(bool new_eflag) const { + PSR new_cpsr = cpsr; + new_cpsr.E(new_eflag); + + return LocationDescriptor(arm_pc, new_cpsr, fpscr, single_stepping); + } + + LocationDescriptor SetFPSCR(u32 new_fpscr) const { + return LocationDescriptor(arm_pc, cpsr, A32::FPSCR{new_fpscr & FPSCR_MODE_MASK}, single_stepping); + } + + LocationDescriptor SetIT(ITState new_it) const { + PSR new_cpsr = cpsr; + new_cpsr.IT(new_it); + + return LocationDescriptor(arm_pc, new_cpsr, fpscr, single_stepping); + } + + LocationDescriptor AdvanceIT() const { + return SetIT(IT().Advance()); + } + + LocationDescriptor SetSingleStepping(bool new_single_stepping) const { + return LocationDescriptor(arm_pc, cpsr, fpscr, new_single_stepping); + } + + u64 UniqueHash() const noexcept { + // This value MUST BE UNIQUE. + // This calculation has to match up with EmitX64::EmitTerminalPopRSBHint + const u64 pc_u64 = arm_pc; + const u64 fpscr_u64 = fpscr.Value(); + const u64 t_u64 = cpsr.T() ? 1 : 0; + const u64 e_u64 = cpsr.E() ? 2 : 0; + const u64 single_stepping_u64 = single_stepping ? 4 : 0; + const u64 it_u64 = u64(cpsr.IT().Value()) << 8; + const u64 upper = (fpscr_u64 | t_u64 | e_u64 | single_stepping_u64 | it_u64) << 32; + return pc_u64 | upper; + } + + operator IR::LocationDescriptor() const { + return IR::LocationDescriptor{UniqueHash()}; + } + +private: + u32 arm_pc; ///< Current program counter value. + PSR cpsr; ///< Current program status register. + A32::FPSCR fpscr; ///< Floating point status control register. + bool single_stepping; +}; + +/** + * Provides a string representation of a LocationDescriptor. + * + * @param o Output stream + * @param descriptor The descriptor to get a string representation of + */ +std::ostream& operator<<(std::ostream& o, const LocationDescriptor& descriptor); + +} // namespace Dynarmic::A32 + +namespace std { +template<> +struct less { + bool operator()(const Dynarmic::A32::LocationDescriptor& x, const Dynarmic::A32::LocationDescriptor& y) const noexcept { + return x.UniqueHash() < y.UniqueHash(); + } +}; +template<> +struct hash { + size_t operator()(const Dynarmic::A32::LocationDescriptor& x) const noexcept { + return std::hash()(x.UniqueHash()); + } +}; +} // namespace std diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/a32_types.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/a32_types.cpp new file mode 100755 index 000000000..046286270 --- /dev/null +++ b/externals/dynarmic/src/dynarmic/frontend/A32/a32_types.cpp @@ -0,0 +1,80 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include "dynarmic/frontend/A32/a32_types.h" + +#include +#include + +#include "dynarmic/common/bit_util.h" + +namespace Dynarmic::A32 { + +const char* CondToString(Cond cond, bool explicit_al) { + static constexpr std::array cond_strs = {"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"}; + return (!explicit_al && cond == Cond::AL) ? "" : cond_strs.at(static_cast(cond)); +} + +const char* RegToString(Reg reg) { + static constexpr std::array reg_strs = {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc"}; + return reg_strs.at(static_cast(reg)); +} + +const char* ExtRegToString(ExtReg reg) { + static constexpr std::array reg_strs = { + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", "s16", + "s17", "s18", "s19", "s20", "s21", "s22", "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", + + "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", "d16", + "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", + + "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", "q16"}; + return reg_strs.at(static_cast(reg)); +} + +const char* CoprocRegToString(CoprocReg reg) { + static constexpr std::array reg_strs = { + "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", + "c9", "c10", "c11", "c12", "c13", "c14", "c15"}; + return reg_strs.at(static_cast(reg)); +} + +std::string RegListToString(RegList reg_list) { + std::string ret; + bool first_reg = true; + for (size_t i = 0; i < 16; i++) { + if (Common::Bit(i, reg_list)) { + if (!first_reg) { + ret += ", "; + } + ret += RegToString(static_cast(i)); + first_reg = false; + } + } + return ret; +} + +std::ostream& operator<<(std::ostream& o, Reg reg) { + o << RegToString(reg); + return o; +} + +std::ostream& operator<<(std::ostream& o, ExtReg reg) { + o << ExtRegToString(reg); + return o; +} + +std::ostream& operator<<(std::ostream& o, CoprocReg reg) { + o << CoprocRegToString(reg); + return o; +} + +std::ostream& operator<<(std::ostream& o, RegList reg_list) { + o << RegListToString(reg_list); + return o; +} + +} // namespace Dynarmic::A32 diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/a32_types.h b/externals/dynarmic/src/dynarmic/frontend/A32/a32_types.h new file mode 100755 index 000000000..ff30cc760 --- /dev/null +++ b/externals/dynarmic/src/dynarmic/frontend/A32/a32_types.h @@ -0,0 +1,149 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#pragma once + +#include +#include +#include + +#include "dynarmic/common/assert.h" +#include "dynarmic/common/common_types.h" +#include "dynarmic/interface/A32/coprocessor_util.h" +#include "dynarmic/ir/cond.h" + +namespace Dynarmic::A32 { + +using Cond = IR::Cond; + +enum class Reg { + R0, + R1, + R2, + R3, + R4, + R5, + R6, + R7, + R8, + R9, + R10, + R11, + R12, + R13, + R14, + R15, + SP = R13, + LR = R14, + PC = R15, + INVALID_REG = 99 +}; + +enum class ExtReg { + // clang-format off + S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15, S16, S17, S18, S19, S20, S21, S22, S23, S24, S25, S26, S27, S28, S29, S30, S31, + D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31, + Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15 + // clang-format on +}; + +using RegList = u16; + +enum class ShiftType { + LSL, + LSR, + ASR, + ROR ///< RRX falls under this too +}; + +enum class SignExtendRotation { + ROR_0, ///< ROR #0 or omitted + ROR_8, ///< ROR #8 + ROR_16, ///< ROR #16 + ROR_24 ///< ROR #24 +}; + +const char* CondToString(Cond cond, bool explicit_al = false); +const char* RegToString(Reg reg); +const char* ExtRegToString(ExtReg reg); +const char* CoprocRegToString(CoprocReg reg); +std::string RegListToString(RegList reg_list); + +std::ostream& operator<<(std::ostream& o, Reg reg); +std::ostream& operator<<(std::ostream& o, ExtReg reg); +std::ostream& operator<<(std::ostream& o, CoprocReg reg); +std::ostream& operator<<(std::ostream& o, RegList reg_list); + +constexpr bool IsSingleExtReg(ExtReg reg) { + return reg >= ExtReg::S0 && reg <= ExtReg::S31; +} + +constexpr bool IsDoubleExtReg(ExtReg reg) { + return reg >= ExtReg::D0 && reg <= ExtReg::D31; +} + +constexpr bool IsQuadExtReg(ExtReg reg) { + return reg >= ExtReg::Q0 && reg <= ExtReg::Q15; +} + +inline size_t RegNumber(Reg reg) { + ASSERT(reg != Reg::INVALID_REG); + return static_cast(reg); +} + +inline size_t RegNumber(ExtReg reg) { + if (IsSingleExtReg(reg)) { + return static_cast(reg) - static_cast(ExtReg::S0); + } + + if (IsDoubleExtReg(reg)) { + return static_cast(reg) - static_cast(ExtReg::D0); + } + + if (IsQuadExtReg(reg)) { + return static_cast(reg) - static_cast(ExtReg::Q0); + } + + ASSERT_FALSE("Invalid extended register"); +} + +inline Reg operator+(Reg reg, size_t number) { + const size_t new_reg = RegNumber(reg) + number; + ASSERT(new_reg <= 15); + + return static_cast(new_reg); +} + +inline ExtReg operator+(ExtReg reg, size_t number) { + const auto new_reg = static_cast(static_cast(reg) + number); + + ASSERT((IsSingleExtReg(reg) && IsSingleExtReg(new_reg)) + || (IsDoubleExtReg(reg) && IsDoubleExtReg(new_reg)) + || (IsQuadExtReg(reg) && IsQuadExtReg(new_reg))); + + return new_reg; +} + +inline ExtReg ToExtRegQ(size_t base, bool bit) { + return ExtReg::Q0 + ((base >> 1) + (bit ? 8 : 0)); +} + +inline ExtReg ToExtRegD(size_t base, bool bit) { + return ExtReg::D0 + (base + (bit ? 16 : 0)); +} + +inline ExtReg ToExtRegS(size_t base, bool bit) { + return ExtReg::S0 + ((base << 1) + (bit ? 1 : 0)); +} + +inline ExtReg ToExtReg(bool sz, size_t base, bool bit) { + return sz ? ToExtRegD(base, bit) : ToExtRegS(base, bit); +} + +inline ExtReg ToVector(bool Q, size_t base, bool bit) { + return Q ? ToExtRegQ(base, bit) : ToExtRegD(base, bit); +} + +} // namespace Dynarmic::A32 diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/disassembler/disassembler_arm.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/disassembler/disassembler_arm.cpp index 9b0157a84..b42600dcd 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/disassembler/disassembler_arm.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/disassembler/disassembler_arm.cpp @@ -11,10 +11,10 @@ #include "dynarmic/common/bit_util.h" #include "dynarmic/common/string_util.h" +#include "dynarmic/frontend/A32/a32_types.h" #include "dynarmic/frontend/A32/decoder/arm.h" #include "dynarmic/frontend/A32/decoder/vfp.h" #include "dynarmic/frontend/A32/disassembler/disassembler.h" -#include "dynarmic/frontend/A32/types.h" #include "dynarmic/frontend/imm.h" namespace Dynarmic::A32 { diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/disassembler/disassembler_thumb.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/disassembler/disassembler_thumb.cpp index b22255139..d5f43cb85 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/disassembler/disassembler_thumb.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/disassembler/disassembler_thumb.cpp @@ -11,9 +11,9 @@ #include "dynarmic/common/bit_util.h" #include "dynarmic/common/string_util.h" +#include "dynarmic/frontend/A32/a32_types.h" #include "dynarmic/frontend/A32/decoder/thumb16.h" #include "dynarmic/frontend/A32/disassembler/disassembler.h" -#include "dynarmic/frontend/A32/types.h" #include "dynarmic/frontend/imm.h" namespace Dynarmic::A32 { diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.cpp new file mode 100755 index 000000000..97a7f11ad --- /dev/null +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.cpp @@ -0,0 +1,27 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include "dynarmic/frontend/A32/translate/a32_translate.h" + +#include "dynarmic/frontend/A32/a32_location_descriptor.h" +#include "dynarmic/ir/basic_block.h" + +namespace Dynarmic::A32 { + +IR::Block TranslateArm(LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options); +IR::Block TranslateThumb(LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options); + +IR::Block Translate(LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options) { + return (descriptor.TFlag() ? TranslateThumb : TranslateArm)(descriptor, tcb, options); +} + +bool TranslateSingleArmInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction); +bool TranslateSingleThumbInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction); + +bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction) { + return (descriptor.TFlag() ? TranslateSingleThumbInstruction : TranslateSingleArmInstruction)(block, descriptor, instruction); +} + +} // namespace Dynarmic::A32 diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.h b/externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.h new file mode 100755 index 000000000..9af458e62 --- /dev/null +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.h @@ -0,0 +1,51 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * SPDX-License-Identifier: 0BSD + */ +#pragma once + +#include "dynarmic/common/common_types.h" +#include "dynarmic/interface/A32/arch_version.h" + +namespace Dynarmic::IR { +class Block; +} // namespace Dynarmic::IR + +namespace Dynarmic::A32 { + +class LocationDescriptor; +struct TranslateCallbacks; + +struct TranslationOptions { + ArchVersion arch_version; + + /// This changes what IR we emit when we translate an unpredictable instruction. + /// If this is false, the ExceptionRaised IR instruction is emitted. + /// If this is true, we define some behaviour for some instructions. + bool define_unpredictable_behaviour = false; + + /// This changes what IR we emit when we translate a hint instruction. + /// If this is false, we treat the instruction as a NOP. + /// If this is true, we emit an ExceptionRaised instruction. + bool hook_hint_instructions = true; +}; + +/** + * This function translates instructions in memory into our intermediate representation. + * @param descriptor The starting location of the basic block. Includes information like PC, Thumb state, &c. + * @param tcb The callbacks we should use to read emulated memory. + * @param options Configures how certain instructions are translated. + * @return A translated basic block in the intermediate representation. + */ +IR::Block Translate(LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options); + +/** + * This function translates a single provided instruction into our intermediate representation. + * @param block The block to append the IR for the instruction to. + * @param descriptor The location of the instruction. Includes information like PC, Thumb state, &c. + * @param instruction The instruction to translate. + * @return The translated instruction translated to the intermediate representation. + */ +bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction); + +} // namespace Dynarmic::A32 diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp index 916e756b4..9488e628e 100755 --- a/externals/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/conditional_state.cpp @@ -9,8 +9,8 @@ #include "dynarmic/common/assert.h" #include "dynarmic/common/common_types.h" -#include "dynarmic/frontend/A32/ir_emitter.h" -#include "dynarmic/frontend/A32/translate/impl/translate.h" +#include "dynarmic/frontend/A32/a32_ir_emitter.h" +#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" #include "dynarmic/interface/A32/config.h" #include "dynarmic/ir/cond.h" diff --git a/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_branch.cpp b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_branch.cpp new file mode 100755 index 000000000..41beea7bb --- /dev/null +++ b/externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_branch.cpp @@ -0,0 +1,87 @@ +/* This file is part of the dynarmic project. + * Copyright (c) 2016 MerryMage + * SPDX-License-Identifier: 0BSD + */ + +#include "dynarmic/common/bit_util.h" +#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h" + +namespace Dynarmic::A32 { + +// B