early-access version 2360
This commit is contained in:
parent
a0076b154a
commit
72a49d1800
95 changed files with 3430 additions and 125 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 2359.
|
This is the source code for early-access 2360.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
29
externals/dynarmic/CMakeLists.txt
vendored
29
externals/dynarmic/CMakeLists.txt
vendored
|
@ -171,3 +171,32 @@ add_subdirectory(src/dynarmic)
|
||||||
if (DYNARMIC_TESTS)
|
if (DYNARMIC_TESTS)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
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()
|
||||||
|
|
5
externals/dynarmic/CMakeModules/dynarmicConfig.cmake.in
vendored
Executable file
5
externals/dynarmic/CMakeModules/dynarmicConfig.cmake.in
vendored
Executable file
|
@ -0,0 +1,5 @@
|
||||||
|
@PACKAGE_INIT@
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||||
|
|
||||||
|
check_required_components(@PROJECT_NAME@)
|
4
externals/dynarmic/externals/CMakeLists.txt
vendored
4
externals/dynarmic/externals/CMakeLists.txt
vendored
|
@ -24,9 +24,7 @@ target_include_directories(mp INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE
|
||||||
# robin-map
|
# robin-map
|
||||||
|
|
||||||
if (NOT TARGET tsl::robin_map)
|
if (NOT TARGET tsl::robin_map)
|
||||||
add_library(robin_map INTERFACE)
|
add_subdirectory(robin-map)
|
||||||
add_library(tsl::robin_map ALIAS robin_map)
|
|
||||||
target_include_directories(robin_map SYSTEM INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/robin-map/include>")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# vixl
|
# vixl
|
||||||
|
|
66
externals/dynarmic/src/dynarmic/CMakeLists.txt
vendored
66
externals/dynarmic/src/dynarmic/CMakeLists.txt
vendored
|
@ -64,10 +64,10 @@ add_library(dynarmic
|
||||||
common/variant_util.h
|
common/variant_util.h
|
||||||
common/x64_disassemble.cpp
|
common/x64_disassemble.cpp
|
||||||
common/x64_disassemble.h
|
common/x64_disassemble.h
|
||||||
frontend/A32/types.cpp
|
frontend/A32/a32_types.cpp
|
||||||
frontend/A32/types.h
|
frontend/A32/a32_types.h
|
||||||
frontend/A64/types.cpp
|
frontend/A64/a64_types.cpp
|
||||||
frontend/A64/types.h
|
frontend/A64/a64_types.h
|
||||||
frontend/decoder/decoder_detail.h
|
frontend/decoder/decoder_detail.h
|
||||||
frontend/decoder/matcher.h
|
frontend/decoder/matcher.h
|
||||||
frontend/imm.cpp
|
frontend/imm.cpp
|
||||||
|
@ -115,12 +115,19 @@ if ("A32" IN_LIST DYNARMIC_FRONTENDS)
|
||||||
frontend/A32/disassembler/disassembler_arm.cpp
|
frontend/A32/disassembler/disassembler_arm.cpp
|
||||||
frontend/A32/disassembler/disassembler_thumb.cpp
|
frontend/A32/disassembler/disassembler_thumb.cpp
|
||||||
frontend/A32/FPSCR.h
|
frontend/A32/FPSCR.h
|
||||||
frontend/A32/ir_emitter.cpp
|
frontend/A32/a32_ir_emitter.cpp
|
||||||
frontend/A32/ir_emitter.h
|
frontend/A32/a32_ir_emitter.h
|
||||||
|
frontend/A32/a32_location_descriptor.cpp
|
||||||
|
frontend/A32/a32_location_descriptor.h
|
||||||
frontend/A32/ITState.h
|
frontend/A32/ITState.h
|
||||||
frontend/A32/location_descriptor.cpp
|
|
||||||
frontend/A32/location_descriptor.h
|
|
||||||
frontend/A32/PSR.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.cpp
|
||||||
frontend/A32/translate/conditional_state.h
|
frontend/A32/translate/conditional_state.h
|
||||||
frontend/A32/translate/impl/asimd_load_store_structures.cpp
|
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_scalar.cpp
|
||||||
frontend/A32/translate/impl/asimd_two_regs_shift.cpp
|
frontend/A32/translate/impl/asimd_two_regs_shift.cpp
|
||||||
frontend/A32/translate/impl/barrier.cpp
|
frontend/A32/translate/impl/barrier.cpp
|
||||||
frontend/A32/translate/impl/branch.cpp
|
|
||||||
frontend/A32/translate/impl/coprocessor.cpp
|
frontend/A32/translate/impl/coprocessor.cpp
|
||||||
frontend/A32/translate/impl/crc32.cpp
|
|
||||||
frontend/A32/translate/impl/data_processing.cpp
|
frontend/A32/translate/impl/data_processing.cpp
|
||||||
frontend/A32/translate/impl/divide.cpp
|
frontend/A32/translate/impl/divide.cpp
|
||||||
frontend/A32/translate/impl/exception_generating.cpp
|
|
||||||
frontend/A32/translate/impl/extension.cpp
|
frontend/A32/translate/impl/extension.cpp
|
||||||
frontend/A32/translate/impl/hint.cpp
|
frontend/A32/translate/impl/hint.cpp
|
||||||
frontend/A32/translate/impl/load_store.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_multiply.cpp
|
||||||
frontend/A32/translate/impl/thumb32_parallel.cpp
|
frontend/A32/translate/impl/thumb32_parallel.cpp
|
||||||
frontend/A32/translate/impl/thumb32_store_single_data_item.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/impl/vfp.cpp
|
||||||
frontend/A32/translate/translate.cpp
|
|
||||||
frontend/A32/translate/translate.h
|
|
||||||
frontend/A32/translate/translate_arm.cpp
|
frontend/A32/translate/translate_arm.cpp
|
||||||
frontend/A32/translate/translate_thumb.cpp
|
frontend/A32/translate/translate_thumb.cpp
|
||||||
interface/A32/a32.h
|
interface/A32/a32.h
|
||||||
|
@ -186,13 +186,16 @@ endif()
|
||||||
|
|
||||||
if ("A64" IN_LIST DYNARMIC_FRONTENDS)
|
if ("A64" IN_LIST DYNARMIC_FRONTENDS)
|
||||||
target_sources(dynarmic PRIVATE
|
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.h
|
||||||
frontend/A64/decoder/a64.inc
|
frontend/A64/decoder/a64.inc
|
||||||
frontend/A64/ir_emitter.cpp
|
frontend/A64/translate/a64_translate.cpp
|
||||||
frontend/A64/ir_emitter.h
|
frontend/A64/translate/a64_translate.h
|
||||||
frontend/A64/location_descriptor.cpp
|
frontend/A64/translate/impl/a64_branch.cpp
|
||||||
frontend/A64/location_descriptor.h
|
frontend/A64/translate/impl/a64_exception_generating.cpp
|
||||||
frontend/A64/translate/impl/branch.cpp
|
|
||||||
frontend/A64/translate/impl/data_processing_addsub.cpp
|
frontend/A64/translate/impl/data_processing_addsub.cpp
|
||||||
frontend/A64/translate/impl/data_processing_bitfield.cpp
|
frontend/A64/translate/impl/data_processing_bitfield.cpp
|
||||||
frontend/A64/translate/impl/data_processing_conditional_compare.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_pcrel.cpp
|
||||||
frontend/A64/translate/impl/data_processing_register.cpp
|
frontend/A64/translate/impl/data_processing_register.cpp
|
||||||
frontend/A64/translate/impl/data_processing_shift.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_compare.cpp
|
||||||
frontend/A64/translate/impl/floating_point_conditional_compare.cpp
|
frontend/A64/translate/impl/floating_point_conditional_compare.cpp
|
||||||
frontend/A64/translate/impl/floating_point_conditional_select.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.cpp
|
||||||
frontend/A64/translate/impl/system_flag_format.cpp
|
frontend/A64/translate/impl/system_flag_format.cpp
|
||||||
frontend/A64/translate/impl/system_flag_manipulation.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/a64.h
|
||||||
interface/A64/config.h
|
interface/A64/config.h
|
||||||
ir/opt/a64_callback_config_pass.cpp
|
ir/opt/a64_callback_config_pass.cpp
|
||||||
|
@ -350,7 +350,7 @@ if (ARCHITECTURE STREQUAL "x86_64")
|
||||||
endif()
|
endif()
|
||||||
elseif (UNIX)
|
elseif (UNIX)
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
target_link_libraries(dynarmic PUBLIC rt)
|
target_link_libraries(dynarmic PRIVATE rt)
|
||||||
endif()
|
endif()
|
||||||
target_sources(dynarmic PRIVATE backend/x64/exception_handler_posix.cpp)
|
target_sources(dynarmic PRIVATE backend/x64/exception_handler_posix.cpp)
|
||||||
else()
|
else()
|
||||||
|
@ -363,20 +363,24 @@ endif()
|
||||||
include(CreateDirectoryGroups)
|
include(CreateDirectoryGroups)
|
||||||
create_target_directory_groups(dynarmic)
|
create_target_directory_groups(dynarmic)
|
||||||
|
|
||||||
target_include_directories(dynarmic PUBLIC ..)
|
target_include_directories(dynarmic PUBLIC
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
|
)
|
||||||
set_target_properties(dynarmic PROPERTIES
|
set_target_properties(dynarmic PROPERTIES
|
||||||
VERSION ${dynarmic_VERSION}
|
VERSION ${dynarmic_VERSION}
|
||||||
SOVERSION ${dynarmic_VERSION_MAJOR}
|
SOVERSION ${dynarmic_VERSION_MAJOR}
|
||||||
)
|
)
|
||||||
target_compile_options(dynarmic PRIVATE ${DYNARMIC_CXX_FLAGS})
|
target_compile_options(dynarmic PRIVATE ${DYNARMIC_CXX_FLAGS})
|
||||||
|
# $<BUILD_INTERFACE:> required because of https://gitlab.kitware.com/cmake/cmake/-/issues/15415
|
||||||
target_link_libraries(dynarmic
|
target_link_libraries(dynarmic
|
||||||
PUBLIC
|
PRIVATE
|
||||||
boost
|
$<BUILD_INTERFACE:boost>
|
||||||
fmt::fmt
|
$<BUILD_INTERFACE:fmt::fmt>
|
||||||
mp
|
$<BUILD_INTERFACE:mp>
|
||||||
tsl::robin_map
|
tsl::robin_map
|
||||||
xbyak
|
$<BUILD_INTERFACE:xbyak>
|
||||||
Zydis
|
$<BUILD_INTERFACE:Zydis>
|
||||||
$<$<BOOL:DYNARMIC_USE_LLVM>:${llvm_libs}>
|
$<$<BOOL:DYNARMIC_USE_LLVM>:${llvm_libs}>
|
||||||
)
|
)
|
||||||
if (DYNARMIC_ENABLE_CPU_FEATURE_DETECTION)
|
if (DYNARMIC_ENABLE_CPU_FEATURE_DETECTION)
|
||||||
|
|
|
@ -27,8 +27,8 @@
|
||||||
#include "dynarmic/common/scope_exit.h"
|
#include "dynarmic/common/scope_exit.h"
|
||||||
#include "dynarmic/common/variant_util.h"
|
#include "dynarmic/common/variant_util.h"
|
||||||
#include "dynarmic/common/x64_disassemble.h"
|
#include "dynarmic/common/x64_disassemble.h"
|
||||||
#include "dynarmic/frontend/A32/location_descriptor.h"
|
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||||
#include "dynarmic/frontend/A32/types.h"
|
#include "dynarmic/frontend/A32/a32_types.h"
|
||||||
#include "dynarmic/interface/A32/coprocessor.h"
|
#include "dynarmic/interface/A32/coprocessor.h"
|
||||||
#include "dynarmic/interface/exclusive_monitor.h"
|
#include "dynarmic/interface/exclusive_monitor.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include "dynarmic/backend/x64/a32_jitstate.h"
|
#include "dynarmic/backend/x64/a32_jitstate.h"
|
||||||
#include "dynarmic/backend/x64/block_range_information.h"
|
#include "dynarmic/backend/x64/block_range_information.h"
|
||||||
#include "dynarmic/backend/x64/emit_x64.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/a32.h"
|
||||||
#include "dynarmic/interface/A32/config.h"
|
#include "dynarmic/interface/A32/config.h"
|
||||||
#include "dynarmic/ir/terminal.h"
|
#include "dynarmic/ir/terminal.h"
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/common/scope_exit.h"
|
#include "dynarmic/common/scope_exit.h"
|
||||||
#include "dynarmic/common/x64_disassemble.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/a32.h"
|
||||||
#include "dynarmic/interface/A32/context.h"
|
#include "dynarmic/interface/A32/context.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/common/common_types.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 {
|
namespace Dynarmic::Backend::X64 {
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/common/scope_exit.h"
|
#include "dynarmic/common/scope_exit.h"
|
||||||
#include "dynarmic/common/x64_disassemble.h"
|
#include "dynarmic/common/x64_disassemble.h"
|
||||||
#include "dynarmic/frontend/A64/location_descriptor.h"
|
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
||||||
#include "dynarmic/frontend/A64/types.h"
|
#include "dynarmic/frontend/A64/a64_types.h"
|
||||||
#include "dynarmic/interface/exclusive_monitor.h"
|
#include "dynarmic/interface/exclusive_monitor.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/cond.h"
|
#include "dynarmic/ir/cond.h"
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "dynarmic/backend/x64/a64_jitstate.h"
|
#include "dynarmic/backend/x64/a64_jitstate.h"
|
||||||
#include "dynarmic/backend/x64/block_range_information.h"
|
#include "dynarmic/backend/x64/block_range_information.h"
|
||||||
#include "dynarmic/backend/x64/emit_x64.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/a64.h"
|
||||||
#include "dynarmic/interface/A64/config.h"
|
#include "dynarmic/interface/A64/config.h"
|
||||||
#include "dynarmic/ir/terminal.h"
|
#include "dynarmic/ir/terminal.h"
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/scope_exit.h"
|
#include "dynarmic/common/scope_exit.h"
|
||||||
#include "dynarmic/common/x64_disassemble.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/interface/A64/a64.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/opt/passes.h"
|
#include "dynarmic/ir/opt/passes.h"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include "dynarmic/backend/x64/a64_jitstate.h"
|
#include "dynarmic/backend/x64/a64_jitstate.h"
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.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 {
|
namespace Dynarmic::Backend::X64 {
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include "dynarmic/backend/x64/nzcv_util.h"
|
#include "dynarmic/backend/x64/nzcv_util.h"
|
||||||
#include "dynarmic/common/common_types.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 {
|
namespace Dynarmic::Backend::X64 {
|
||||||
|
|
||||||
|
|
441
externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.cpp
vendored
Executable file
441
externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.cpp
vendored
Executable file
|
@ -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<u32>(pc - pc % alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::GetRegister(Reg reg) {
|
||||||
|
if (reg == A32::Reg::PC) {
|
||||||
|
return Imm32(PC());
|
||||||
|
}
|
||||||
|
return Inst<IR::U32>(Opcode::A32GetRegister, IR::Value(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32U64 IREmitter::GetExtendedRegister(ExtReg reg) {
|
||||||
|
if (A32::IsSingleExtReg(reg)) {
|
||||||
|
return Inst<IR::U32U64>(Opcode::A32GetExtendedRegister32, IR::Value(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (A32::IsDoubleExtReg(reg)) {
|
||||||
|
return Inst<IR::U32U64>(Opcode::A32GetExtendedRegister64, IR::Value(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_FALSE("Invalid reg.");
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U128 IREmitter::GetVector(ExtReg reg) {
|
||||||
|
ASSERT(A32::IsDoubleExtReg(reg) || A32::IsQuadExtReg(reg));
|
||||||
|
return Inst<IR::U128>(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<u64>(exception)));
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::GetCpsr() {
|
||||||
|
return Inst<IR::U32>(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<IR::U1>(Opcode::GetOverflowFromOp, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U1 IREmitter::GetCFlag() {
|
||||||
|
return Inst<IR::U1>(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<IR::U32>(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<IR::U32>(Opcode::A32GetFpscr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetFpscr(const IR::U32& new_fpscr) {
|
||||||
|
Inst(Opcode::A32SetFpscr, new_fpscr);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::GetFpscrNZCV() {
|
||||||
|
return Inst<IR::U32>(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<IR::U8>(Opcode::A32ReadMemory8, vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U16 IREmitter::ReadMemory16(const IR::U32& vaddr) {
|
||||||
|
const auto value = Inst<IR::U16>(Opcode::A32ReadMemory16, vaddr);
|
||||||
|
return current_location.EFlag() ? ByteReverseHalf(value) : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::ReadMemory32(const IR::U32& vaddr) {
|
||||||
|
const auto value = Inst<IR::U32>(Opcode::A32ReadMemory32, vaddr);
|
||||||
|
return current_location.EFlag() ? ByteReverseWord(value) : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 IREmitter::ReadMemory64(const IR::U32& vaddr) {
|
||||||
|
const auto value = Inst<IR::U64>(Opcode::A32ReadMemory64, vaddr);
|
||||||
|
return current_location.EFlag() ? ByteReverseDual(value) : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U8 IREmitter::ExclusiveReadMemory8(const IR::U32& vaddr) {
|
||||||
|
return Inst<IR::U8>(Opcode::A32ExclusiveReadMemory8, vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U16 IREmitter::ExclusiveReadMemory16(const IR::U32& vaddr) {
|
||||||
|
const auto value = Inst<IR::U16>(Opcode::A32ExclusiveReadMemory16, vaddr);
|
||||||
|
return current_location.EFlag() ? ByteReverseHalf(value) : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::ExclusiveReadMemory32(const IR::U32& vaddr) {
|
||||||
|
const auto value = Inst<IR::U32>(Opcode::A32ExclusiveReadMemory32, vaddr);
|
||||||
|
return current_location.EFlag() ? ByteReverseWord(value) : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<IR::U32, IR::U32> IREmitter::ExclusiveReadMemory64(const IR::U32& vaddr) {
|
||||||
|
const auto value = Inst<IR::U64>(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<IR::U32>(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<IR::U32>(Opcode::A32ExclusiveWriteMemory16, vaddr, v);
|
||||||
|
} else {
|
||||||
|
return Inst<IR::U32>(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<IR::U32>(Opcode::A32ExclusiveWriteMemory32, vaddr, v);
|
||||||
|
} else {
|
||||||
|
return Inst<IR::U32>(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<IR::U32>(Opcode::A32ExclusiveWriteMemory64, vaddr, Pack2x32To1x64(vlo, vhi));
|
||||||
|
} else {
|
||||||
|
return Inst<IR::U32>(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<u8>(coproc_no),
|
||||||
|
static_cast<u8>(two ? 1 : 0),
|
||||||
|
static_cast<u8>(opc1),
|
||||||
|
static_cast<u8>(CRd),
|
||||||
|
static_cast<u8>(CRn),
|
||||||
|
static_cast<u8>(CRm),
|
||||||
|
static_cast<u8>(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<u8>(coproc_no),
|
||||||
|
static_cast<u8>(two ? 1 : 0),
|
||||||
|
static_cast<u8>(opc1),
|
||||||
|
static_cast<u8>(CRn),
|
||||||
|
static_cast<u8>(CRm),
|
||||||
|
static_cast<u8>(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<u8>(coproc_no),
|
||||||
|
static_cast<u8>(two ? 1 : 0),
|
||||||
|
static_cast<u8>(opc),
|
||||||
|
static_cast<u8>(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<u8>(coproc_no),
|
||||||
|
static_cast<u8>(two ? 1 : 0),
|
||||||
|
static_cast<u8>(opc1),
|
||||||
|
static_cast<u8>(CRn),
|
||||||
|
static_cast<u8>(CRm),
|
||||||
|
static_cast<u8>(opc2)};
|
||||||
|
return Inst<IR::U32>(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<u8>(coproc_no),
|
||||||
|
static_cast<u8>(two ? 1 : 0),
|
||||||
|
static_cast<u8>(opc),
|
||||||
|
static_cast<u8>(CRm)};
|
||||||
|
return Inst<IR::U64>(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<u8>(coproc_no),
|
||||||
|
static_cast<u8>(two ? 1 : 0),
|
||||||
|
static_cast<u8>(long_transfer ? 1 : 0),
|
||||||
|
static_cast<u8>(CRd),
|
||||||
|
static_cast<u8>(has_option ? 1 : 0),
|
||||||
|
static_cast<u8>(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<u8>(coproc_no),
|
||||||
|
static_cast<u8>(two ? 1 : 0),
|
||||||
|
static_cast<u8>(long_transfer ? 1 : 0),
|
||||||
|
static_cast<u8>(CRd),
|
||||||
|
static_cast<u8>(has_option ? 1 : 0),
|
||||||
|
static_cast<u8>(option)};
|
||||||
|
Inst(Opcode::A32CoprocStoreWords, IR::Value(coproc_info), address);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Dynarmic::A32
|
114
externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h
vendored
Executable file
114
externals/dynarmic/src/dynarmic/frontend/A32/a32_ir_emitter.h
vendored
Executable file
|
@ -0,0 +1,114 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#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<IR::U32, IR::U32> 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
|
24
externals/dynarmic/src/dynarmic/frontend/A32/a32_location_descriptor.cpp
vendored
Executable file
24
externals/dynarmic/src/dynarmic/frontend/A32/a32_location_descriptor.cpp
vendored
Executable file
|
@ -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 <ostream>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
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
|
153
externals/dynarmic/src/dynarmic/frontend/A32/a32_location_descriptor.h
vendored
Executable file
153
externals/dynarmic/src/dynarmic/frontend/A32/a32_location_descriptor.h
vendored
Executable file
|
@ -0,0 +1,153 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#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<u32>(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<u8>(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<u32>(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<Dynarmic::A32::LocationDescriptor> {
|
||||||
|
bool operator()(const Dynarmic::A32::LocationDescriptor& x, const Dynarmic::A32::LocationDescriptor& y) const noexcept {
|
||||||
|
return x.UniqueHash() < y.UniqueHash();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct hash<Dynarmic::A32::LocationDescriptor> {
|
||||||
|
size_t operator()(const Dynarmic::A32::LocationDescriptor& x) const noexcept {
|
||||||
|
return std::hash<u64>()(x.UniqueHash());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace std
|
80
externals/dynarmic/src/dynarmic/frontend/A32/a32_types.cpp
vendored
Executable file
80
externals/dynarmic/src/dynarmic/frontend/A32/a32_types.cpp
vendored
Executable file
|
@ -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 <array>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
#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<size_t>(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<size_t>(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<size_t>(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<size_t>(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<Reg>(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
|
149
externals/dynarmic/src/dynarmic/frontend/A32/a32_types.h
vendored
Executable file
149
externals/dynarmic/src/dynarmic/frontend/A32/a32_types.h
vendored
Executable file
|
@ -0,0 +1,149 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#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<size_t>(reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t RegNumber(ExtReg reg) {
|
||||||
|
if (IsSingleExtReg(reg)) {
|
||||||
|
return static_cast<size_t>(reg) - static_cast<size_t>(ExtReg::S0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsDoubleExtReg(reg)) {
|
||||||
|
return static_cast<size_t>(reg) - static_cast<size_t>(ExtReg::D0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsQuadExtReg(reg)) {
|
||||||
|
return static_cast<size_t>(reg) - static_cast<size_t>(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<Reg>(new_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ExtReg operator+(ExtReg reg, size_t number) {
|
||||||
|
const auto new_reg = static_cast<ExtReg>(static_cast<size_t>(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
|
|
@ -11,10 +11,10 @@
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/common/string_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/arm.h"
|
||||||
#include "dynarmic/frontend/A32/decoder/vfp.h"
|
#include "dynarmic/frontend/A32/decoder/vfp.h"
|
||||||
#include "dynarmic/frontend/A32/disassembler/disassembler.h"
|
#include "dynarmic/frontend/A32/disassembler/disassembler.h"
|
||||||
#include "dynarmic/frontend/A32/types.h"
|
|
||||||
#include "dynarmic/frontend/imm.h"
|
#include "dynarmic/frontend/imm.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/common/string_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/decoder/thumb16.h"
|
||||||
#include "dynarmic/frontend/A32/disassembler/disassembler.h"
|
#include "dynarmic/frontend/A32/disassembler/disassembler.h"
|
||||||
#include "dynarmic/frontend/A32/types.h"
|
|
||||||
#include "dynarmic/frontend/imm.h"
|
#include "dynarmic/frontend/imm.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
27
externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.cpp
vendored
Executable file
27
externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.cpp
vendored
Executable file
|
@ -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
|
51
externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.h
vendored
Executable file
51
externals/dynarmic/src/dynarmic/frontend/A32/translate/a32_translate.h
vendored
Executable file
|
@ -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
|
|
@ -9,8 +9,8 @@
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/frontend/A32/ir_emitter.h"
|
#include "dynarmic/frontend/A32/a32_ir_emitter.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
#include "dynarmic/interface/A32/config.h"
|
#include "dynarmic/interface/A32/config.h"
|
||||||
#include "dynarmic/ir/cond.h"
|
#include "dynarmic/ir/cond.h"
|
||||||
|
|
||||||
|
|
87
externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_branch.cpp
vendored
Executable file
87
externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_branch.cpp
vendored
Executable file
|
@ -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 <label>
|
||||||
|
bool TranslatorVisitor::arm_B(Cond cond, Imm<24> imm24) {
|
||||||
|
if (!ArmConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 imm32 = Common::SignExtend<26, u32>(imm24.ZeroExtend() << 2) + 8;
|
||||||
|
const auto new_location = ir.current_location.AdvancePC(imm32);
|
||||||
|
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BL <label>
|
||||||
|
bool TranslatorVisitor::arm_BL(Cond cond, Imm<24> imm24) {
|
||||||
|
if (!ArmConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.PushRSB(ir.current_location.AdvancePC(4));
|
||||||
|
ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4));
|
||||||
|
|
||||||
|
const u32 imm32 = Common::SignExtend<26, u32>(imm24.ZeroExtend() << 2) + 8;
|
||||||
|
const auto new_location = ir.current_location.AdvancePC(imm32);
|
||||||
|
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BLX <label>
|
||||||
|
bool TranslatorVisitor::arm_BLX_imm(bool H, Imm<24> imm24) {
|
||||||
|
ir.PushRSB(ir.current_location.AdvancePC(4));
|
||||||
|
ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4));
|
||||||
|
|
||||||
|
const u32 imm32 = Common::SignExtend<26, u32>((imm24.ZeroExtend() << 2)) + (H ? 2 : 0) + 8;
|
||||||
|
const auto new_location = ir.current_location.AdvancePC(imm32).SetTFlag(true);
|
||||||
|
ir.SetTerm(IR::Term::LinkBlock{new_location});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BLX <Rm>
|
||||||
|
bool TranslatorVisitor::arm_BLX_reg(Cond cond, Reg m) {
|
||||||
|
if (m == Reg::PC) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ArmConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.PushRSB(ir.current_location.AdvancePC(4));
|
||||||
|
ir.BXWritePC(ir.GetRegister(m));
|
||||||
|
ir.SetRegister(Reg::LR, ir.Imm32(ir.current_location.PC() + 4));
|
||||||
|
ir.SetTerm(IR::Term::FastDispatchHint{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BX <Rm>
|
||||||
|
bool TranslatorVisitor::arm_BX(Cond cond, Reg m) {
|
||||||
|
if (!ArmConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ir.BXWritePC(ir.GetRegister(m));
|
||||||
|
if (m == Reg::R14) {
|
||||||
|
ir.SetTerm(IR::Term::PopRSBHint{});
|
||||||
|
} else {
|
||||||
|
ir.SetTerm(IR::Term::FastDispatchHint{});
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::arm_BXJ(Cond cond, Reg m) {
|
||||||
|
// Jazelle not supported
|
||||||
|
return arm_BX(cond, m);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Dynarmic::A32
|
95
externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_crc32.cpp
vendored
Executable file
95
externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_crc32.cpp
vendored
Executable file
|
@ -0,0 +1,95 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2019 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
// It's considered constrained UNPREDICTABLE behavior if either
|
||||||
|
// CRC32 instruction variant is executed with a condition code
|
||||||
|
// that is *not* 0xE (Always execute). ARM defines one of the following
|
||||||
|
// as being a requirement in this case. Either:
|
||||||
|
//
|
||||||
|
// 1. The instruction is undefined.
|
||||||
|
// 2. The instruction executes as a NOP.
|
||||||
|
// 3. The instruction executes unconditionally.
|
||||||
|
// 4. The instruction executes conditionally.
|
||||||
|
//
|
||||||
|
// It's also considered constrained UNPREDICTABLE behavior if
|
||||||
|
// either CRC32 instruction variant is executed with a size specifier
|
||||||
|
// of 64-bit (sz -> 0b11)
|
||||||
|
//
|
||||||
|
// In this case, either:
|
||||||
|
//
|
||||||
|
// 1. The instruction is undefined
|
||||||
|
// 2. The instruction executes as a NOP.
|
||||||
|
// 3. The instruction executes with the additional decode: size = 32.
|
||||||
|
//
|
||||||
|
// In both cases, we treat as unpredictable, to allow
|
||||||
|
// library users to provide their own intended behavior
|
||||||
|
// in the unpredictable exception handler.
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
enum class CRCType {
|
||||||
|
Castagnoli,
|
||||||
|
ISO,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool CRC32Variant(TranslatorVisitor& v, Cond cond, Imm<2> sz, Reg n, Reg d, Reg m, CRCType type) {
|
||||||
|
if (d == Reg::PC || n == Reg::PC || m == Reg::PC) {
|
||||||
|
return v.UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sz == 0b11) {
|
||||||
|
return v.UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cond != Cond::AL) {
|
||||||
|
return v.UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
const IR::U32 result = [m, n, sz, type, &v] {
|
||||||
|
const IR::U32 accumulator = v.ir.GetRegister(n);
|
||||||
|
const IR::U32 data = v.ir.GetRegister(m);
|
||||||
|
|
||||||
|
if (type == CRCType::ISO) {
|
||||||
|
switch (sz.ZeroExtend()) {
|
||||||
|
case 0b00:
|
||||||
|
return v.ir.CRC32ISO8(accumulator, data);
|
||||||
|
case 0b01:
|
||||||
|
return v.ir.CRC32ISO16(accumulator, data);
|
||||||
|
case 0b10:
|
||||||
|
return v.ir.CRC32ISO32(accumulator, data);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (sz.ZeroExtend()) {
|
||||||
|
case 0b00:
|
||||||
|
return v.ir.CRC32Castagnoli8(accumulator, data);
|
||||||
|
case 0b01:
|
||||||
|
return v.ir.CRC32Castagnoli16(accumulator, data);
|
||||||
|
case 0b10:
|
||||||
|
return v.ir.CRC32Castagnoli32(accumulator, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UNREACHABLE();
|
||||||
|
}();
|
||||||
|
|
||||||
|
v.ir.SetRegister(d, result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
// CRC32{B,H,W}{<q>} <Rd>, <Rn>, <Rm>
|
||||||
|
bool TranslatorVisitor::arm_CRC32(Cond cond, Imm<2> sz, Reg n, Reg d, Reg m) {
|
||||||
|
return CRC32Variant(*this, cond, sz, n, d, m, CRCType::ISO);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CRC32C{B,H,W}{<q>} <Rd>, <Rn>, <Rm>
|
||||||
|
bool TranslatorVisitor::arm_CRC32C(Cond cond, Imm<2> sz, Reg n, Reg d, Reg m) {
|
||||||
|
return CRC32Variant(*this, cond, sz, n, d, m, CRCType::Castagnoli);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Dynarmic::A32
|
44
externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_exception_generating.cpp
vendored
Executable file
44
externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_exception_generating.cpp
vendored
Executable file
|
@ -0,0 +1,44 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
#include "dynarmic/interface/A32/config.h"
|
||||||
|
|
||||||
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
// BKPT #<imm16>
|
||||||
|
bool TranslatorVisitor::arm_BKPT(Cond cond, Imm<12> /*imm12*/, Imm<4> /*imm4*/) {
|
||||||
|
if (cond != Cond::AL && !options.define_unpredictable_behaviour) {
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
}
|
||||||
|
// UNPREDICTABLE: The instruction executes conditionally.
|
||||||
|
|
||||||
|
if (!ArmConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RaiseException(Exception::Breakpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SVC<c> #<imm24>
|
||||||
|
bool TranslatorVisitor::arm_SVC(Cond cond, Imm<24> imm24) {
|
||||||
|
if (!ArmConditionPassed(cond)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 imm32 = imm24.ZeroExtend();
|
||||||
|
ir.PushRSB(ir.current_location.AdvancePC(4));
|
||||||
|
ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 4));
|
||||||
|
ir.CallSupervisor(ir.Imm32(imm32));
|
||||||
|
ir.SetTerm(IR::Term::CheckHalt{IR::Term::PopRSBHint{}});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDF<c> #<imm16>
|
||||||
|
bool TranslatorVisitor::arm_UDF() {
|
||||||
|
return UndefinedInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Dynarmic::A32
|
109
externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.cpp
vendored
Executable file
109
externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.cpp
vendored
Executable file
|
@ -0,0 +1,109 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
|
#include "dynarmic/common/assert.h"
|
||||||
|
#include "dynarmic/interface/A32/config.h"
|
||||||
|
|
||||||
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
bool TranslatorVisitor::ArmConditionPassed(Cond cond) {
|
||||||
|
return IsConditionPassed(*this, cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::ThumbConditionPassed() {
|
||||||
|
const Cond cond = ir.current_location.IT().Cond();
|
||||||
|
return IsConditionPassed(*this, cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::VFPConditionPassed(Cond cond) {
|
||||||
|
if (ir.current_location.TFlag()) {
|
||||||
|
ASSERT(cond == Cond::AL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return ArmConditionPassed(cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::InterpretThisInstruction() {
|
||||||
|
ir.SetTerm(IR::Term::Interpret(ir.current_location));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::UnpredictableInstruction() {
|
||||||
|
return RaiseException(Exception::UnpredictableInstruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::UndefinedInstruction() {
|
||||||
|
return RaiseException(Exception::UndefinedInstruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::DecodeError() {
|
||||||
|
return RaiseException(Exception::DecodeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::RaiseException(Exception exception) {
|
||||||
|
ir.UpdateUpperLocationDescriptor();
|
||||||
|
ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + static_cast<u32>(current_instruction_size)));
|
||||||
|
ir.ExceptionRaised(exception);
|
||||||
|
ir.SetTerm(IR::Term::CheckHalt{IR::Term::ReturnToDispatch{}});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::UAny TranslatorVisitor::I(size_t bitsize, u64 value) {
|
||||||
|
switch (bitsize) {
|
||||||
|
case 8:
|
||||||
|
return ir.Imm8(static_cast<u8>(value));
|
||||||
|
case 16:
|
||||||
|
return ir.Imm16(static_cast<u16>(value));
|
||||||
|
case 32:
|
||||||
|
return ir.Imm32(static_cast<u32>(value));
|
||||||
|
case 64:
|
||||||
|
return ir.Imm64(value);
|
||||||
|
default:
|
||||||
|
ASSERT_FALSE("Imm - get: Invalid bitsize");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::ResultAndCarry<IR::U32> TranslatorVisitor::EmitImmShift(IR::U32 value, ShiftType type, Imm<3> imm3, Imm<2> imm2, IR::U1 carry_in) {
|
||||||
|
return EmitImmShift(value, type, concatenate(imm3, imm2), carry_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::ResultAndCarry<IR::U32> TranslatorVisitor::EmitImmShift(IR::U32 value, ShiftType type, Imm<5> imm5, IR::U1 carry_in) {
|
||||||
|
u8 imm5_value = imm5.ZeroExtend<u8>();
|
||||||
|
switch (type) {
|
||||||
|
case ShiftType::LSL:
|
||||||
|
return ir.LogicalShiftLeft(value, ir.Imm8(imm5_value), carry_in);
|
||||||
|
case ShiftType::LSR:
|
||||||
|
imm5_value = imm5_value ? imm5_value : 32;
|
||||||
|
return ir.LogicalShiftRight(value, ir.Imm8(imm5_value), carry_in);
|
||||||
|
case ShiftType::ASR:
|
||||||
|
imm5_value = imm5_value ? imm5_value : 32;
|
||||||
|
return ir.ArithmeticShiftRight(value, ir.Imm8(imm5_value), carry_in);
|
||||||
|
case ShiftType::ROR:
|
||||||
|
if (imm5_value) {
|
||||||
|
return ir.RotateRight(value, ir.Imm8(imm5_value), carry_in);
|
||||||
|
} else {
|
||||||
|
return ir.RotateRightExtended(value, carry_in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::ResultAndCarry<IR::U32> TranslatorVisitor::EmitRegShift(IR::U32 value, ShiftType type, IR::U8 amount, IR::U1 carry_in) {
|
||||||
|
switch (type) {
|
||||||
|
case ShiftType::LSL:
|
||||||
|
return ir.LogicalShiftLeft(value, amount, carry_in);
|
||||||
|
case ShiftType::LSR:
|
||||||
|
return ir.LogicalShiftRight(value, amount, carry_in);
|
||||||
|
case ShiftType::ASR:
|
||||||
|
return ir.ArithmeticShiftRight(value, amount, carry_in);
|
||||||
|
case ShiftType::ROR:
|
||||||
|
return ir.RotateRight(value, amount, carry_in);
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Dynarmic::A32
|
962
externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h
vendored
Executable file
962
externals/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h
vendored
Executable file
|
@ -0,0 +1,962 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dynarmic/common/assert.h"
|
||||||
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/a32_ir_emitter.h"
|
||||||
|
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||||
|
#include "dynarmic/frontend/A32/a32_types.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/a32_translate.h"
|
||||||
|
#include "dynarmic/frontend/A32/translate/conditional_state.h"
|
||||||
|
#include "dynarmic/frontend/imm.h"
|
||||||
|
|
||||||
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
enum class Exception;
|
||||||
|
|
||||||
|
struct TranslatorVisitor final {
|
||||||
|
using instruction_return_type = bool;
|
||||||
|
|
||||||
|
explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor, const TranslationOptions& options)
|
||||||
|
: ir(block, descriptor, options.arch_version), options(options) {}
|
||||||
|
|
||||||
|
A32::IREmitter ir;
|
||||||
|
ConditionalState cond_state = ConditionalState::None;
|
||||||
|
TranslationOptions options;
|
||||||
|
|
||||||
|
size_t current_instruction_size;
|
||||||
|
|
||||||
|
bool ArmConditionPassed(Cond cond);
|
||||||
|
bool ThumbConditionPassed();
|
||||||
|
bool VFPConditionPassed(Cond cond);
|
||||||
|
|
||||||
|
bool InterpretThisInstruction();
|
||||||
|
bool UnpredictableInstruction();
|
||||||
|
bool UndefinedInstruction();
|
||||||
|
bool DecodeError();
|
||||||
|
bool RaiseException(Exception exception);
|
||||||
|
|
||||||
|
struct ImmAndCarry {
|
||||||
|
u32 imm32;
|
||||||
|
IR::U1 carry;
|
||||||
|
};
|
||||||
|
|
||||||
|
ImmAndCarry ArmExpandImm_C(int rotate, Imm<8> imm8, IR::U1 carry_in) {
|
||||||
|
u32 imm32 = imm8.ZeroExtend();
|
||||||
|
auto carry_out = carry_in;
|
||||||
|
if (rotate) {
|
||||||
|
imm32 = Common::RotateRight<u32>(imm8.ZeroExtend(), rotate * 2);
|
||||||
|
carry_out = ir.Imm1(Common::Bit<31>(imm32));
|
||||||
|
}
|
||||||
|
return {imm32, carry_out};
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ArmExpandImm(int rotate, Imm<8> imm8) {
|
||||||
|
return ArmExpandImm_C(rotate, imm8, ir.Imm1(0)).imm32;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmAndCarry ThumbExpandImm_C(Imm<1> i, Imm<3> imm3, Imm<8> imm8, IR::U1 carry_in) {
|
||||||
|
const Imm<12> imm12 = concatenate(i, imm3, imm8);
|
||||||
|
if (imm12.Bits<10, 11>() == 0) {
|
||||||
|
const u32 imm32 = [&] {
|
||||||
|
const u32 imm8 = imm12.Bits<0, 7>();
|
||||||
|
switch (imm12.Bits<8, 9>()) {
|
||||||
|
case 0b00:
|
||||||
|
return imm8;
|
||||||
|
case 0b01:
|
||||||
|
return Common::Replicate(imm8, 16);
|
||||||
|
case 0b10:
|
||||||
|
return Common::Replicate(imm8 << 8, 16);
|
||||||
|
case 0b11:
|
||||||
|
return Common::Replicate(imm8, 8);
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
}();
|
||||||
|
return {imm32, carry_in};
|
||||||
|
}
|
||||||
|
const u32 imm32 = Common::RotateRight<u32>((1 << 7) | imm12.Bits<0, 6>(), imm12.Bits<7, 11>());
|
||||||
|
return {imm32, ir.Imm1(Common::Bit<31>(imm32))};
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ThumbExpandImm(Imm<1> i, Imm<3> imm3, Imm<8> imm8) {
|
||||||
|
return ThumbExpandImm_C(i, imm3, imm8, ir.Imm1(0)).imm32;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates an immediate of the given value
|
||||||
|
IR::UAny I(size_t bitsize, u64 value);
|
||||||
|
|
||||||
|
IR::ResultAndCarry<IR::U32> EmitImmShift(IR::U32 value, ShiftType type, Imm<3> imm3, Imm<2> imm2, IR::U1 carry_in);
|
||||||
|
IR::ResultAndCarry<IR::U32> EmitImmShift(IR::U32 value, ShiftType type, Imm<5> imm5, IR::U1 carry_in);
|
||||||
|
IR::ResultAndCarry<IR::U32> EmitRegShift(IR::U32 value, ShiftType type, IR::U8 amount, IR::U1 carry_in);
|
||||||
|
template<typename FnT>
|
||||||
|
bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg n, ExtReg m, const FnT& fn);
|
||||||
|
template<typename FnT>
|
||||||
|
bool EmitVfpVectorOperation(bool sz, ExtReg d, ExtReg m, const FnT& fn);
|
||||||
|
|
||||||
|
// Barrier instructions
|
||||||
|
bool arm_DMB(Imm<4> option);
|
||||||
|
bool arm_DSB(Imm<4> option);
|
||||||
|
bool arm_ISB(Imm<4> option);
|
||||||
|
|
||||||
|
// Branch instructions
|
||||||
|
bool arm_B(Cond cond, Imm<24> imm24);
|
||||||
|
bool arm_BL(Cond cond, Imm<24> imm24);
|
||||||
|
bool arm_BLX_imm(bool H, Imm<24> imm24);
|
||||||
|
bool arm_BLX_reg(Cond cond, Reg m);
|
||||||
|
bool arm_BX(Cond cond, Reg m);
|
||||||
|
bool arm_BXJ(Cond cond, Reg m);
|
||||||
|
|
||||||
|
// Coprocessor instructions
|
||||||
|
bool arm_CDP(Cond cond, size_t opc1, CoprocReg CRn, CoprocReg CRd, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
||||||
|
bool arm_LDC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8);
|
||||||
|
bool arm_MCR(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
||||||
|
bool arm_MCRR(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm);
|
||||||
|
bool arm_MRC(Cond cond, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
||||||
|
bool arm_MRRC(Cond cond, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm);
|
||||||
|
bool arm_STC(Cond cond, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8);
|
||||||
|
|
||||||
|
// CRC32 instructions
|
||||||
|
bool arm_CRC32(Cond cond, Imm<2> sz, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_CRC32C(Cond cond, Imm<2> sz, Reg n, Reg d, Reg m);
|
||||||
|
|
||||||
|
// Data processing instructions
|
||||||
|
bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_CMN_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_CMN_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_CMP_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_CMP_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_MOV_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_MVN_reg(Cond cond, bool S, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_TEQ_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
|
||||||
|
bool arm_TST_imm(Cond cond, Reg n, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_TST_reg(Cond cond, Reg n, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m);
|
||||||
|
|
||||||
|
// Exception generating instructions
|
||||||
|
bool arm_BKPT(Cond cond, Imm<12> imm12, Imm<4> imm4);
|
||||||
|
bool arm_SVC(Cond cond, Imm<24> imm24);
|
||||||
|
bool arm_UDF();
|
||||||
|
|
||||||
|
// Extension instructions
|
||||||
|
bool arm_SXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool arm_SXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool arm_SXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool arm_SXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool arm_SXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool arm_SXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool arm_UXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool arm_UXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool arm_UXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool arm_UXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool arm_UXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
|
||||||
|
// Hint instructions
|
||||||
|
bool arm_PLD_imm(bool add, bool R, Reg n, Imm<12> imm12);
|
||||||
|
bool arm_PLD_reg(bool add, bool R, Reg n, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_SEV();
|
||||||
|
bool arm_SEVL();
|
||||||
|
bool arm_WFE();
|
||||||
|
bool arm_WFI();
|
||||||
|
bool arm_YIELD();
|
||||||
|
|
||||||
|
// Load/Store
|
||||||
|
bool arm_LDRBT();
|
||||||
|
bool arm_LDRHT();
|
||||||
|
bool arm_LDRSBT();
|
||||||
|
bool arm_LDRSHT();
|
||||||
|
bool arm_LDRT();
|
||||||
|
bool arm_STRBT();
|
||||||
|
bool arm_STRHT();
|
||||||
|
bool arm_STRT();
|
||||||
|
bool arm_LDR_lit(Cond cond, bool U, Reg t, Imm<12> imm12);
|
||||||
|
bool arm_LDR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm<12> imm12);
|
||||||
|
bool arm_LDR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_LDRB_lit(Cond cond, bool U, Reg t, Imm<12> imm12);
|
||||||
|
bool arm_LDRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12);
|
||||||
|
bool arm_LDRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_LDRD_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
|
bool arm_LDRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
|
bool arm_LDRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_LDRH_lit(Cond cond, bool P, bool U, bool W, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
|
bool arm_LDRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
|
bool arm_LDRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_LDRSB_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
|
bool arm_LDRSB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
|
bool arm_LDRSB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
|
||||||
|
bool arm_LDRSH_lit(Cond cond, bool U, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
|
bool arm_LDRSH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
|
bool arm_LDRSH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
|
||||||
|
bool arm_STR_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12);
|
||||||
|
bool arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<12> imm12);
|
||||||
|
bool arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<5> imm5, ShiftType shift, Reg m);
|
||||||
|
bool arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
|
bool arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
|
||||||
|
bool arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm<4> imm8a, Imm<4> imm8b);
|
||||||
|
bool arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m);
|
||||||
|
|
||||||
|
// Load/Store multiple instructions
|
||||||
|
bool arm_LDM(Cond cond, bool W, Reg n, RegList list);
|
||||||
|
bool arm_LDMDA(Cond cond, bool W, Reg n, RegList list);
|
||||||
|
bool arm_LDMDB(Cond cond, bool W, Reg n, RegList list);
|
||||||
|
bool arm_LDMIB(Cond cond, bool W, Reg n, RegList list);
|
||||||
|
bool arm_LDM_usr();
|
||||||
|
bool arm_LDM_eret();
|
||||||
|
bool arm_STM(Cond cond, bool W, Reg n, RegList list);
|
||||||
|
bool arm_STMDA(Cond cond, bool W, Reg n, RegList list);
|
||||||
|
bool arm_STMDB(Cond cond, bool W, Reg n, RegList list);
|
||||||
|
bool arm_STMIB(Cond cond, bool W, Reg n, RegList list);
|
||||||
|
bool arm_STM_usr();
|
||||||
|
|
||||||
|
// Miscellaneous instructions
|
||||||
|
bool arm_BFC(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb);
|
||||||
|
bool arm_BFI(Cond cond, Imm<5> msb, Reg d, Imm<5> lsb, Reg n);
|
||||||
|
bool arm_CLZ(Cond cond, Reg d, Reg m);
|
||||||
|
bool arm_MOVT(Cond cond, Imm<4> imm4, Reg d, Imm<12> imm12);
|
||||||
|
bool arm_MOVW(Cond cond, Imm<4> imm4, Reg d, Imm<12> imm12);
|
||||||
|
bool arm_NOP() { return true; }
|
||||||
|
bool arm_RBIT(Cond cond, Reg d, Reg m);
|
||||||
|
bool arm_SBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n);
|
||||||
|
bool arm_SEL(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UBFX(Cond cond, Imm<5> widthm1, Reg d, Imm<5> lsb, Reg n);
|
||||||
|
|
||||||
|
// Unsigned sum of absolute difference functions
|
||||||
|
bool arm_USAD8(Cond cond, Reg d, Reg m, Reg n);
|
||||||
|
bool arm_USADA8(Cond cond, Reg d, Reg a, Reg m, Reg n);
|
||||||
|
|
||||||
|
// Packing instructions
|
||||||
|
bool arm_PKHBT(Cond cond, Reg n, Reg d, Imm<5> imm5, Reg m);
|
||||||
|
bool arm_PKHTB(Cond cond, Reg n, Reg d, Imm<5> imm5, Reg m);
|
||||||
|
|
||||||
|
// Reversal instructions
|
||||||
|
bool arm_REV(Cond cond, Reg d, Reg m);
|
||||||
|
bool arm_REV16(Cond cond, Reg d, Reg m);
|
||||||
|
bool arm_REVSH(Cond cond, Reg d, Reg m);
|
||||||
|
|
||||||
|
// Saturation instructions
|
||||||
|
bool arm_SSAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n);
|
||||||
|
bool arm_SSAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n);
|
||||||
|
bool arm_USAT(Cond cond, Imm<5> sat_imm, Reg d, Imm<5> imm5, bool sh, Reg n);
|
||||||
|
bool arm_USAT16(Cond cond, Imm<4> sat_imm, Reg d, Reg n);
|
||||||
|
|
||||||
|
// Divide instructions
|
||||||
|
bool arm_SDIV(Cond cond, Reg d, Reg m, Reg n);
|
||||||
|
bool arm_UDIV(Cond cond, Reg d, Reg m, Reg n);
|
||||||
|
|
||||||
|
// Multiply (Normal) instructions
|
||||||
|
bool arm_MLA(Cond cond, bool S, Reg d, Reg a, Reg m, Reg n);
|
||||||
|
bool arm_MLS(Cond cond, Reg d, Reg a, Reg m, Reg n);
|
||||||
|
bool arm_MUL(Cond cond, bool S, Reg d, Reg m, Reg n);
|
||||||
|
|
||||||
|
// Multiply (Long) instructions
|
||||||
|
bool arm_SMLAL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n);
|
||||||
|
bool arm_SMULL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n);
|
||||||
|
bool arm_UMAAL(Cond cond, Reg dHi, Reg dLo, Reg m, Reg n);
|
||||||
|
bool arm_UMLAL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n);
|
||||||
|
bool arm_UMULL(Cond cond, bool S, Reg dHi, Reg dLo, Reg m, Reg n);
|
||||||
|
|
||||||
|
// Multiply (Halfword) instructions
|
||||||
|
bool arm_SMLALxy(Cond cond, Reg dHi, Reg dLo, Reg m, bool M, bool N, Reg n);
|
||||||
|
bool arm_SMLAxy(Cond cond, Reg d, Reg a, Reg m, bool M, bool N, Reg n);
|
||||||
|
bool arm_SMULxy(Cond cond, Reg d, Reg m, bool M, bool N, Reg n);
|
||||||
|
|
||||||
|
// Multiply (word by halfword) instructions
|
||||||
|
bool arm_SMLAWy(Cond cond, Reg d, Reg a, Reg m, bool M, Reg n);
|
||||||
|
bool arm_SMULWy(Cond cond, Reg d, Reg m, bool M, Reg n);
|
||||||
|
|
||||||
|
// Multiply (Most significant word) instructions
|
||||||
|
bool arm_SMMLA(Cond cond, Reg d, Reg a, Reg m, bool R, Reg n);
|
||||||
|
bool arm_SMMLS(Cond cond, Reg d, Reg a, Reg m, bool R, Reg n);
|
||||||
|
bool arm_SMMUL(Cond cond, Reg d, Reg m, bool R, Reg n);
|
||||||
|
|
||||||
|
// Multiply (Dual) instructions
|
||||||
|
bool arm_SMLAD(Cond cond, Reg d, Reg a, Reg m, bool M, Reg n);
|
||||||
|
bool arm_SMLALD(Cond cond, Reg dHi, Reg dLo, Reg m, bool M, Reg n);
|
||||||
|
bool arm_SMLSD(Cond cond, Reg d, Reg a, Reg m, bool M, Reg n);
|
||||||
|
bool arm_SMLSLD(Cond cond, Reg dHi, Reg dLo, Reg m, bool M, Reg n);
|
||||||
|
bool arm_SMUAD(Cond cond, Reg d, Reg m, bool M, Reg n);
|
||||||
|
bool arm_SMUSD(Cond cond, Reg d, Reg m, bool M, Reg n);
|
||||||
|
|
||||||
|
// Parallel Add/Subtract (Modulo arithmetic) instructions
|
||||||
|
bool arm_SADD8(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_SADD16(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_SASX(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_SSAX(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_SSUB8(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_SSUB16(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UADD8(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UADD16(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UASX(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_USAX(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_USUB8(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_USUB16(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
|
||||||
|
// Parallel Add/Subtract (Saturating) instructions
|
||||||
|
bool arm_QADD8(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_QADD16(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_QASX(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_QSAX(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_QSUB8(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_QSUB16(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UQADD8(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UQADD16(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UQASX(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UQSAX(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UQSUB8(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UQSUB16(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
|
||||||
|
// Parallel Add/Subtract (Halving) instructions
|
||||||
|
bool arm_SHADD8(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_SHADD16(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_SHASX(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_SHSAX(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_SHSUB8(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_SHSUB16(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UHADD8(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UHADD16(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UHASX(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UHSAX(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UHSUB8(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_UHSUB16(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
|
||||||
|
// Saturated Add/Subtract instructions
|
||||||
|
bool arm_QADD(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_QSUB(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_QDADD(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
bool arm_QDSUB(Cond cond, Reg n, Reg d, Reg m);
|
||||||
|
|
||||||
|
// Synchronization Primitive instructions
|
||||||
|
bool arm_CLREX();
|
||||||
|
bool arm_SWP(Cond cond, Reg n, Reg t, Reg t2);
|
||||||
|
bool arm_SWPB(Cond cond, Reg n, Reg t, Reg t2);
|
||||||
|
bool arm_STL(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_STLEX(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_STREX(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_LDA(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_LDAEX(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_LDREX(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_STLEXD(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_STREXD(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_LDAEXD(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_LDREXD(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_STLB(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_STLEXB(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_STREXB(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_LDAB(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_LDAEXB(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_LDREXB(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_STLH(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_STLEXH(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_STREXH(Cond cond, Reg n, Reg d, Reg t);
|
||||||
|
bool arm_LDAH(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_LDAEXH(Cond cond, Reg n, Reg t);
|
||||||
|
bool arm_LDREXH(Cond cond, Reg n, Reg t);
|
||||||
|
|
||||||
|
// Status register access instructions
|
||||||
|
bool arm_CPS();
|
||||||
|
bool arm_MRS(Cond cond, Reg d);
|
||||||
|
bool arm_MSR_imm(Cond cond, int mask, int rotate, Imm<8> imm8);
|
||||||
|
bool arm_MSR_reg(Cond cond, int mask, Reg n);
|
||||||
|
bool arm_RFE();
|
||||||
|
bool arm_SETEND(bool E);
|
||||||
|
bool arm_SRS();
|
||||||
|
|
||||||
|
// thumb16
|
||||||
|
bool thumb16_LSL_imm(Imm<5> imm5, Reg m, Reg d);
|
||||||
|
bool thumb16_LSR_imm(Imm<5> imm5, Reg m, Reg d);
|
||||||
|
bool thumb16_ASR_imm(Imm<5> imm5, Reg m, Reg d);
|
||||||
|
bool thumb16_ADD_reg_t1(Reg m, Reg n, Reg d);
|
||||||
|
bool thumb16_SUB_reg(Reg m, Reg n, Reg d);
|
||||||
|
bool thumb16_ADD_imm_t1(Imm<3> imm3, Reg n, Reg d);
|
||||||
|
bool thumb16_SUB_imm_t1(Imm<3> imm3, Reg n, Reg d);
|
||||||
|
bool thumb16_MOV_imm(Reg d, Imm<8> imm8);
|
||||||
|
bool thumb16_CMP_imm(Reg n, Imm<8> imm8);
|
||||||
|
bool thumb16_ADD_imm_t2(Reg d_n, Imm<8> imm8);
|
||||||
|
bool thumb16_SUB_imm_t2(Reg d_n, Imm<8> imm8);
|
||||||
|
bool thumb16_AND_reg(Reg m, Reg d_n);
|
||||||
|
bool thumb16_EOR_reg(Reg m, Reg d_n);
|
||||||
|
bool thumb16_LSL_reg(Reg m, Reg d_n);
|
||||||
|
bool thumb16_LSR_reg(Reg m, Reg d_n);
|
||||||
|
bool thumb16_ASR_reg(Reg m, Reg d_n);
|
||||||
|
bool thumb16_ADC_reg(Reg m, Reg d_n);
|
||||||
|
bool thumb16_SBC_reg(Reg m, Reg d_n);
|
||||||
|
bool thumb16_ROR_reg(Reg m, Reg d_n);
|
||||||
|
bool thumb16_TST_reg(Reg m, Reg n);
|
||||||
|
bool thumb16_RSB_imm(Reg n, Reg d);
|
||||||
|
bool thumb16_CMP_reg_t1(Reg m, Reg n);
|
||||||
|
bool thumb16_CMN_reg(Reg m, Reg n);
|
||||||
|
bool thumb16_ORR_reg(Reg m, Reg d_n);
|
||||||
|
bool thumb16_MUL_reg(Reg n, Reg d_m);
|
||||||
|
bool thumb16_BIC_reg(Reg m, Reg d_n);
|
||||||
|
bool thumb16_MVN_reg(Reg m, Reg d);
|
||||||
|
bool thumb16_ADD_reg_t2(bool d_n_hi, Reg m, Reg d_n_lo);
|
||||||
|
bool thumb16_CMP_reg_t2(bool n_hi, Reg m, Reg n_lo);
|
||||||
|
bool thumb16_MOV_reg(bool d_hi, Reg m, Reg d_lo);
|
||||||
|
bool thumb16_LDR_literal(Reg t, Imm<8> imm8);
|
||||||
|
bool thumb16_STR_reg(Reg m, Reg n, Reg t);
|
||||||
|
bool thumb16_STRH_reg(Reg m, Reg n, Reg t);
|
||||||
|
bool thumb16_STRB_reg(Reg m, Reg n, Reg t);
|
||||||
|
bool thumb16_LDRSB_reg(Reg m, Reg n, Reg t);
|
||||||
|
bool thumb16_LDR_reg(Reg m, Reg n, Reg t);
|
||||||
|
bool thumb16_LDRH_reg(Reg m, Reg n, Reg t);
|
||||||
|
bool thumb16_LDRB_reg(Reg m, Reg n, Reg t);
|
||||||
|
bool thumb16_LDRSH_reg(Reg m, Reg n, Reg t);
|
||||||
|
bool thumb16_STR_imm_t1(Imm<5> imm5, Reg n, Reg t);
|
||||||
|
bool thumb16_LDR_imm_t1(Imm<5> imm5, Reg n, Reg t);
|
||||||
|
bool thumb16_STRB_imm(Imm<5> imm5, Reg n, Reg t);
|
||||||
|
bool thumb16_LDRB_imm(Imm<5> imm5, Reg n, Reg t);
|
||||||
|
bool thumb16_STRH_imm(Imm<5> imm5, Reg n, Reg t);
|
||||||
|
bool thumb16_LDRH_imm(Imm<5> imm5, Reg n, Reg t);
|
||||||
|
bool thumb16_STR_imm_t2(Reg t, Imm<8> imm8);
|
||||||
|
bool thumb16_LDR_imm_t2(Reg t, Imm<8> imm8);
|
||||||
|
bool thumb16_ADR(Reg d, Imm<8> imm8);
|
||||||
|
bool thumb16_ADD_sp_t1(Reg d, Imm<8> imm8);
|
||||||
|
bool thumb16_ADD_sp_t2(Imm<7> imm7);
|
||||||
|
bool thumb16_SUB_sp(Imm<7> imm7);
|
||||||
|
bool thumb16_SEV();
|
||||||
|
bool thumb16_SEVL();
|
||||||
|
bool thumb16_WFE();
|
||||||
|
bool thumb16_WFI();
|
||||||
|
bool thumb16_YIELD();
|
||||||
|
bool thumb16_NOP();
|
||||||
|
bool thumb16_IT(Imm<8> imm8);
|
||||||
|
bool thumb16_SXTH(Reg m, Reg d);
|
||||||
|
bool thumb16_SXTB(Reg m, Reg d);
|
||||||
|
bool thumb16_UXTH(Reg m, Reg d);
|
||||||
|
bool thumb16_UXTB(Reg m, Reg d);
|
||||||
|
bool thumb16_PUSH(bool M, RegList reg_list);
|
||||||
|
bool thumb16_POP(bool P, RegList reg_list);
|
||||||
|
bool thumb16_SETEND(bool E);
|
||||||
|
bool thumb16_CPS(bool, bool, bool, bool);
|
||||||
|
bool thumb16_REV(Reg m, Reg d);
|
||||||
|
bool thumb16_REV16(Reg m, Reg d);
|
||||||
|
bool thumb16_REVSH(Reg m, Reg d);
|
||||||
|
bool thumb16_BKPT(Imm<8> imm8);
|
||||||
|
bool thumb16_STMIA(Reg n, RegList reg_list);
|
||||||
|
bool thumb16_LDMIA(Reg n, RegList reg_list);
|
||||||
|
bool thumb16_CBZ_CBNZ(bool nonzero, Imm<1> i, Imm<5> imm5, Reg n);
|
||||||
|
bool thumb16_UDF();
|
||||||
|
bool thumb16_BX(Reg m);
|
||||||
|
bool thumb16_BLX_reg(Reg m);
|
||||||
|
bool thumb16_SVC(Imm<8> imm8);
|
||||||
|
bool thumb16_B_t1(Cond cond, Imm<8> imm8);
|
||||||
|
bool thumb16_B_t2(Imm<11> imm11);
|
||||||
|
|
||||||
|
// thumb32 load/store multiple instructions
|
||||||
|
bool thumb32_LDMDB(bool W, Reg n, Imm<16> reg_list);
|
||||||
|
bool thumb32_LDMIA(bool W, Reg n, Imm<16> reg_list);
|
||||||
|
bool thumb32_POP(Imm<16> reg_list);
|
||||||
|
bool thumb32_PUSH(Imm<15> reg_list);
|
||||||
|
bool thumb32_STMIA(bool W, Reg n, Imm<15> reg_list);
|
||||||
|
bool thumb32_STMDB(bool W, Reg n, Imm<15> reg_list);
|
||||||
|
|
||||||
|
// thumb32 load/store dual, load/store exclusive, table branch instructions
|
||||||
|
bool thumb32_LDRD_imm_1(bool U, Reg n, Reg t, Reg t2, Imm<8> imm8);
|
||||||
|
bool thumb32_LDRD_imm_2(bool U, bool W, Reg n, Reg t, Reg t2, Imm<8> imm8);
|
||||||
|
bool thumb32_LDRD_lit_1(bool U, Reg t, Reg t2, Imm<8> imm8);
|
||||||
|
bool thumb32_LDRD_lit_2(bool U, bool W, Reg t, Reg t2, Imm<8> imm8);
|
||||||
|
bool thumb32_STRD_imm_1(bool U, Reg n, Reg t, Reg t2, Imm<8> imm8);
|
||||||
|
bool thumb32_STRD_imm_2(bool U, bool W, Reg n, Reg t, Reg t2, Imm<8> imm8);
|
||||||
|
bool thumb32_LDREX(Reg n, Reg t, Imm<8> imm8);
|
||||||
|
bool thumb32_LDREXD(Reg n, Reg t, Reg t2);
|
||||||
|
bool thumb32_LDREXB(Reg n, Reg t);
|
||||||
|
bool thumb32_LDREXH(Reg n, Reg t);
|
||||||
|
bool thumb32_STREX(Reg n, Reg t, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_STREXB(Reg n, Reg t, Reg d);
|
||||||
|
bool thumb32_STREXD(Reg n, Reg t, Reg t2, Reg d);
|
||||||
|
bool thumb32_STREXH(Reg n, Reg t, Reg d);
|
||||||
|
bool thumb32_TBB(Reg n, Reg m);
|
||||||
|
bool thumb32_TBH(Reg n, Reg m);
|
||||||
|
|
||||||
|
// thumb32 data processing (shifted register) instructions
|
||||||
|
bool thumb32_TST_reg(Reg n, Imm<3> imm3, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_AND_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_BIC_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_MOV_reg(bool S, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_ORR_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_MVN_reg(bool S, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_ORN_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_TEQ_reg(Reg n, Imm<3> imm3, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_EOR_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_PKH(Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, Imm<1> tb, Reg m);
|
||||||
|
bool thumb32_CMN_reg(Reg n, Imm<3> imm3, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_ADD_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_ADC_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_SBC_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_CMP_reg(Reg n, Imm<3> imm3, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_SUB_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
bool thumb32_RSB_reg(bool S, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, ShiftType type, Reg m);
|
||||||
|
|
||||||
|
// thumb32 data processing (modified immediate) instructions
|
||||||
|
bool thumb32_TST_imm(Imm<1> i, Reg n, Imm<3> imm3, Imm<8> imm8);
|
||||||
|
bool thumb32_AND_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_BIC_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_MOV_imm(Imm<1> i, bool S, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_ORR_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_MVN_imm(Imm<1> i, bool S, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_ORN_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_TEQ_imm(Imm<1> i, Reg n, Imm<3> imm3, Imm<8> imm8);
|
||||||
|
bool thumb32_EOR_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_CMN_imm(Imm<1> i, Reg n, Imm<3> imm3, Imm<8> imm8);
|
||||||
|
bool thumb32_ADD_imm_1(Imm<1> i, bool S, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_ADC_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_SBC_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_CMP_imm(Imm<1> i, Reg n, Imm<3> imm3, Imm<8> imm8);
|
||||||
|
bool thumb32_SUB_imm_1(Imm<1> i, bool S, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_RSB_imm(Imm<1> i, bool S, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
|
||||||
|
// thumb32 data processing (plain binary immediate) instructions.
|
||||||
|
bool thumb32_ADR_t2(Imm<1> imm1, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_ADR_t3(Imm<1> imm1, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_ADD_imm_2(Imm<1> imm1, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_BFC(Imm<3> imm3, Reg d, Imm<2> imm2, Imm<5> msb);
|
||||||
|
bool thumb32_BFI(Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, Imm<5> msb);
|
||||||
|
bool thumb32_MOVT(Imm<1> imm1, Imm<4> imm4, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_MOVW_imm(Imm<1> imm1, Imm<4> imm4, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_SBFX(Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, Imm<5> widthm1);
|
||||||
|
bool thumb32_SSAT(bool sh, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, Imm<5> sat_imm);
|
||||||
|
bool thumb32_SSAT16(Reg n, Reg d, Imm<4> sat_imm);
|
||||||
|
bool thumb32_SUB_imm_2(Imm<1> imm1, Reg n, Imm<3> imm3, Reg d, Imm<8> imm8);
|
||||||
|
bool thumb32_UBFX(Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, Imm<5> widthm1);
|
||||||
|
bool thumb32_USAT(bool sh, Reg n, Imm<3> imm3, Reg d, Imm<2> imm2, Imm<5> sat_imm);
|
||||||
|
bool thumb32_USAT16(Reg n, Reg d, Imm<4> sat_imm);
|
||||||
|
|
||||||
|
// thumb32 miscellaneous control instructions
|
||||||
|
bool thumb32_BXJ(Reg m);
|
||||||
|
bool thumb32_CLREX();
|
||||||
|
bool thumb32_DMB(Imm<4> option);
|
||||||
|
bool thumb32_DSB(Imm<4> option);
|
||||||
|
bool thumb32_ISB(Imm<4> option);
|
||||||
|
bool thumb32_NOP();
|
||||||
|
bool thumb32_SEV();
|
||||||
|
bool thumb32_SEVL();
|
||||||
|
bool thumb32_UDF();
|
||||||
|
bool thumb32_WFE();
|
||||||
|
bool thumb32_WFI();
|
||||||
|
bool thumb32_YIELD();
|
||||||
|
bool thumb32_MSR_reg(bool R, Reg n, Imm<4> mask);
|
||||||
|
bool thumb32_MRS_reg(bool R, Reg d);
|
||||||
|
|
||||||
|
// thumb32 branch instructions
|
||||||
|
bool thumb32_BL_imm(Imm<1> S, Imm<10> hi, Imm<1> j1, Imm<1> j2, Imm<11> lo);
|
||||||
|
bool thumb32_BLX_imm(Imm<1> S, Imm<10> hi, Imm<1> j1, Imm<1> j2, Imm<11> lo);
|
||||||
|
bool thumb32_B(Imm<1> S, Imm<10> hi, Imm<1> j1, Imm<1> j2, Imm<11> lo);
|
||||||
|
bool thumb32_B_cond(Imm<1> S, Cond cond, Imm<6> hi, Imm<1> j1, Imm<1> j2, Imm<11> lo);
|
||||||
|
|
||||||
|
// thumb32 store single data item instructions
|
||||||
|
bool thumb32_STRB_imm_1(Reg n, Reg t, bool P, bool U, Imm<8> imm8);
|
||||||
|
bool thumb32_STRB_imm_2(Reg n, Reg t, Imm<8> imm8);
|
||||||
|
bool thumb32_STRB_imm_3(Reg n, Reg t, Imm<12> imm12);
|
||||||
|
bool thumb32_STRBT(Reg n, Reg t, Imm<8> imm8);
|
||||||
|
bool thumb32_STRB(Reg n, Reg t, Imm<2> imm2, Reg m);
|
||||||
|
bool thumb32_STRH_imm_1(Reg n, Reg t, bool P, bool U, Imm<8> imm8);
|
||||||
|
bool thumb32_STRH_imm_2(Reg n, Reg t, Imm<8> imm8);
|
||||||
|
bool thumb32_STRH_imm_3(Reg n, Reg t, Imm<12> imm12);
|
||||||
|
bool thumb32_STRHT(Reg n, Reg t, Imm<8> imm8);
|
||||||
|
bool thumb32_STRH(Reg n, Reg t, Imm<2> imm2, Reg m);
|
||||||
|
bool thumb32_STR_imm_1(Reg n, Reg t, bool P, bool U, Imm<8> imm8);
|
||||||
|
bool thumb32_STR_imm_2(Reg n, Reg t, Imm<8> imm8);
|
||||||
|
bool thumb32_STR_imm_3(Reg n, Reg t, Imm<12> imm12);
|
||||||
|
bool thumb32_STRT(Reg n, Reg t, Imm<8> imm8);
|
||||||
|
bool thumb32_STR_reg(Reg n, Reg t, Imm<2> imm2, Reg m);
|
||||||
|
|
||||||
|
// thumb32 load byte and memory hints
|
||||||
|
bool thumb32_PLD_lit(bool U, Imm<12> imm12);
|
||||||
|
bool thumb32_PLD_imm8(bool W, Reg n, Imm<8> imm8);
|
||||||
|
bool thumb32_PLD_imm12(bool W, Reg n, Imm<12> imm12);
|
||||||
|
bool thumb32_PLD_reg(bool W, Reg n, Imm<2> imm2, Reg m);
|
||||||
|
bool thumb32_PLI_lit(bool U, Imm<12> imm12);
|
||||||
|
bool thumb32_PLI_imm8(Reg n, Imm<8> imm8);
|
||||||
|
bool thumb32_PLI_imm12(Reg n, Imm<12> imm12);
|
||||||
|
bool thumb32_PLI_reg(Reg n, Imm<2> imm2, Reg m);
|
||||||
|
bool thumb32_LDRB_lit(bool U, Reg t, Imm<12> imm12);
|
||||||
|
bool thumb32_LDRB_reg(Reg n, Reg t, Imm<2> imm2, Reg m);
|
||||||
|
bool thumb32_LDRB_imm8(Reg n, Reg t, bool P, bool U, bool W, Imm<8> imm8);
|
||||||
|
bool thumb32_LDRB_imm12(Reg n, Reg t, Imm<12> imm12);
|
||||||
|
bool thumb32_LDRBT(Reg n, Reg t, Imm<8> imm8);
|
||||||
|
bool thumb32_LDRSB_lit(bool U, Reg t, Imm<12> imm12);
|
||||||
|
bool thumb32_LDRSB_reg(Reg n, Reg t, Imm<2> imm2, Reg m);
|
||||||
|
bool thumb32_LDRSB_imm8(Reg n, Reg t, bool P, bool U, bool W, Imm<8> imm8);
|
||||||
|
bool thumb32_LDRSB_imm12(Reg n, Reg t, Imm<12> imm12);
|
||||||
|
bool thumb32_LDRSBT(Reg n, Reg t, Imm<8> imm8);
|
||||||
|
|
||||||
|
// thumb32 load halfword instructions
|
||||||
|
bool thumb32_LDRH_lit(bool U, Reg t, Imm<12> imm12);
|
||||||
|
bool thumb32_LDRH_reg(Reg n, Reg t, Imm<2> imm2, Reg m);
|
||||||
|
bool thumb32_LDRH_imm8(Reg n, Reg t, bool P, bool U, bool W, Imm<8> imm8);
|
||||||
|
bool thumb32_LDRH_imm12(Reg n, Reg t, Imm<12> imm12);
|
||||||
|
bool thumb32_LDRHT(Reg n, Reg t, Imm<8> imm8);
|
||||||
|
bool thumb32_LDRSH_lit(bool U, Reg t, Imm<12> imm12);
|
||||||
|
bool thumb32_LDRSH_reg(Reg n, Reg t, Imm<2> imm2, Reg m);
|
||||||
|
bool thumb32_LDRSH_imm8(Reg n, Reg t, bool P, bool U, bool W, Imm<8> imm8);
|
||||||
|
bool thumb32_LDRSH_imm12(Reg n, Reg t, Imm<12> imm12);
|
||||||
|
bool thumb32_LDRSHT(Reg n, Reg t, Imm<8> imm8);
|
||||||
|
|
||||||
|
// thumb32 load word instructions
|
||||||
|
bool thumb32_LDR_lit(bool U, Reg t, Imm<12> imm12);
|
||||||
|
bool thumb32_LDR_reg(Reg n, Reg t, Imm<2> imm2, Reg m);
|
||||||
|
bool thumb32_LDR_imm8(Reg n, Reg t, bool P, bool U, bool W, Imm<8> imm8);
|
||||||
|
bool thumb32_LDR_imm12(Reg n, Reg t, Imm<12> imm12);
|
||||||
|
bool thumb32_LDRT(Reg n, Reg t, Imm<8> imm8);
|
||||||
|
|
||||||
|
// thumb32 data processing (register) instructions
|
||||||
|
bool thumb32_ASR_reg(bool S, Reg m, Reg d, Reg s);
|
||||||
|
bool thumb32_LSL_reg(bool S, Reg m, Reg d, Reg s);
|
||||||
|
bool thumb32_LSR_reg(bool S, Reg m, Reg d, Reg s);
|
||||||
|
bool thumb32_ROR_reg(bool S, Reg m, Reg d, Reg s);
|
||||||
|
bool thumb32_SXTB(Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool thumb32_SXTB16(Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool thumb32_SXTAB(Reg n, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool thumb32_SXTAB16(Reg n, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool thumb32_SXTH(Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool thumb32_SXTAH(Reg n, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool thumb32_UXTB(Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool thumb32_UXTB16(Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool thumb32_UXTAB(Reg n, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool thumb32_UXTAB16(Reg n, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool thumb32_UXTH(Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
bool thumb32_UXTAH(Reg n, Reg d, SignExtendRotation rotate, Reg m);
|
||||||
|
|
||||||
|
// thumb32 long multiply, long multiply accumulate, and divide instructions
|
||||||
|
bool thumb32_SDIV(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_SMLAL(Reg n, Reg dLo, Reg dHi, Reg m);
|
||||||
|
bool thumb32_SMLALD(Reg n, Reg dLo, Reg dHi, bool M, Reg m);
|
||||||
|
bool thumb32_SMLALXY(Reg n, Reg dLo, Reg dHi, bool N, bool M, Reg m);
|
||||||
|
bool thumb32_SMLSLD(Reg n, Reg dLo, Reg dHi, bool M, Reg m);
|
||||||
|
bool thumb32_SMULL(Reg n, Reg dLo, Reg dHi, Reg m);
|
||||||
|
bool thumb32_UDIV(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UMAAL(Reg n, Reg dLo, Reg dHi, Reg m);
|
||||||
|
bool thumb32_UMLAL(Reg n, Reg dLo, Reg dHi, Reg m);
|
||||||
|
bool thumb32_UMULL(Reg n, Reg dLo, Reg dHi, Reg m);
|
||||||
|
|
||||||
|
// thumb32 miscellaneous instructions
|
||||||
|
bool thumb32_CLZ(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_QADD(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_QDADD(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_QDSUB(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_QSUB(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_RBIT(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_REV(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_REV16(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_REVSH(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_SEL(Reg n, Reg d, Reg m);
|
||||||
|
|
||||||
|
// thumb32 multiply instructions
|
||||||
|
bool thumb32_MLA(Reg n, Reg a, Reg d, Reg m);
|
||||||
|
bool thumb32_MLS(Reg n, Reg a, Reg d, Reg m);
|
||||||
|
bool thumb32_MUL(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_SMLAD(Reg n, Reg a, Reg d, bool X, Reg m);
|
||||||
|
bool thumb32_SMLAXY(Reg n, Reg a, Reg d, bool N, bool M, Reg m);
|
||||||
|
bool thumb32_SMLAWY(Reg n, Reg a, Reg d, bool M, Reg m);
|
||||||
|
bool thumb32_SMLSD(Reg n, Reg a, Reg d, bool X, Reg m);
|
||||||
|
bool thumb32_SMMLA(Reg n, Reg a, Reg d, bool R, Reg m);
|
||||||
|
bool thumb32_SMMLS(Reg n, Reg a, Reg d, bool R, Reg m);
|
||||||
|
bool thumb32_SMMUL(Reg n, Reg d, bool R, Reg m);
|
||||||
|
bool thumb32_SMUAD(Reg n, Reg d, bool M, Reg m);
|
||||||
|
bool thumb32_SMUSD(Reg n, Reg d, bool M, Reg m);
|
||||||
|
bool thumb32_SMULXY(Reg n, Reg d, bool N, bool M, Reg m);
|
||||||
|
bool thumb32_SMULWY(Reg n, Reg d, bool M, Reg m);
|
||||||
|
bool thumb32_USAD8(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_USADA8(Reg n, Reg a, Reg d, Reg m);
|
||||||
|
|
||||||
|
// thumb32 parallel add/sub instructions
|
||||||
|
bool thumb32_SADD8(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_SADD16(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_SASX(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_SSAX(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_SSUB8(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_SSUB16(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UADD8(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UADD16(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UASX(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_USAX(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_USUB8(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_USUB16(Reg n, Reg d, Reg m);
|
||||||
|
|
||||||
|
bool thumb32_QADD8(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_QADD16(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_QASX(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_QSAX(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_QSUB8(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_QSUB16(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UQADD8(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UQADD16(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UQASX(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UQSAX(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UQSUB8(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UQSUB16(Reg n, Reg d, Reg m);
|
||||||
|
|
||||||
|
bool thumb32_SHADD8(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_SHADD16(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_SHASX(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_SHSAX(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_SHSUB8(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_SHSUB16(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UHADD8(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UHADD16(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UHASX(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UHSAX(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UHSUB8(Reg n, Reg d, Reg m);
|
||||||
|
bool thumb32_UHSUB16(Reg n, Reg d, Reg m);
|
||||||
|
|
||||||
|
// thumb32 coprocessor insturctions
|
||||||
|
bool thumb32_MCRR(bool two, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm);
|
||||||
|
bool thumb32_MRRC(bool two, Reg t2, Reg t, size_t coproc_no, size_t opc, CoprocReg CRm);
|
||||||
|
bool thumb32_STC(bool two, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8);
|
||||||
|
bool thumb32_LDC(bool two, bool p, bool u, bool d, bool w, Reg n, CoprocReg CRd, size_t coproc_no, Imm<8> imm8);
|
||||||
|
bool thumb32_CDP(bool two, size_t opc1, CoprocReg CRn, CoprocReg CRd, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
||||||
|
bool thumb32_MCR(bool two, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
||||||
|
bool thumb32_MRC(bool two, size_t opc1, CoprocReg CRn, Reg t, size_t coproc_no, size_t opc2, CoprocReg CRm);
|
||||||
|
|
||||||
|
// Floating-point three-register data processing instructions
|
||||||
|
bool vfp_VADD(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VSUB(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VMUL(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VMLA(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VMLS(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VNMUL(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VNMLA(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VNMLS(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VDIV(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VFNMS(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VFNMA(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VFMA(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VFMS(Cond cond, bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VSEL(bool D, Imm<2> cc, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VMAXNM(bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
bool vfp_VMINNM(bool D, size_t Vn, size_t Vd, bool sz, bool N, bool M, size_t Vm);
|
||||||
|
|
||||||
|
// Floating-point move instructions
|
||||||
|
bool vfp_VMOV_u32_f64(Cond cond, size_t Vd, Reg t, bool D);
|
||||||
|
bool vfp_VMOV_f64_u32(Cond cond, size_t Vn, Reg t, bool N);
|
||||||
|
bool vfp_VMOV_u32_f32(Cond cond, size_t Vn, Reg t, bool N);
|
||||||
|
bool vfp_VMOV_f32_u32(Cond cond, size_t Vn, Reg t, bool N);
|
||||||
|
bool vfp_VMOV_2u32_2f32(Cond cond, Reg t2, Reg t, bool M, size_t Vm);
|
||||||
|
bool vfp_VMOV_2f32_2u32(Cond cond, Reg t2, Reg t, bool M, size_t Vm);
|
||||||
|
bool vfp_VMOV_2u32_f64(Cond cond, Reg t2, Reg t, bool M, size_t Vm);
|
||||||
|
bool vfp_VMOV_f64_2u32(Cond cond, Reg t2, Reg t, bool M, size_t Vm);
|
||||||
|
bool vfp_VMOV_from_i32(Cond cond, Imm<1> i, size_t Vd, Reg t, bool D);
|
||||||
|
bool vfp_VMOV_from_i16(Cond cond, Imm<1> i1, size_t Vd, Reg t, bool D, Imm<1> i2);
|
||||||
|
bool vfp_VMOV_from_i8(Cond cond, Imm<1> i1, size_t Vd, Reg t, bool D, Imm<2> i2);
|
||||||
|
bool vfp_VMOV_to_i32(Cond cond, Imm<1> i, size_t Vn, Reg t, bool N);
|
||||||
|
bool vfp_VMOV_to_i16(Cond cond, bool U, Imm<1> i1, size_t Vn, Reg t, bool N, Imm<1> i2);
|
||||||
|
bool vfp_VMOV_to_i8(Cond cond, bool U, Imm<1> i1, size_t Vn, Reg t, bool N, Imm<2> i2);
|
||||||
|
bool vfp_VDUP(Cond cond, Imm<1> B, bool Q, size_t Vd, Reg t, bool D, Imm<1> E);
|
||||||
|
bool vfp_VMOV_imm(Cond cond, bool D, Imm<4> imm4H, size_t Vd, bool sz, Imm<4> imm4L);
|
||||||
|
bool vfp_VMOV_reg(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
|
||||||
|
|
||||||
|
// Floating-point misc instructions
|
||||||
|
bool vfp_VABS(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
|
||||||
|
bool vfp_VNEG(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
|
||||||
|
bool vfp_VSQRT(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
|
||||||
|
bool vfp_VCVTB(Cond cond, bool D, bool op, size_t Vd, bool sz, bool M, size_t Vm);
|
||||||
|
bool vfp_VCVTT(Cond cond, bool D, bool op, size_t Vd, bool sz, bool M, size_t Vm);
|
||||||
|
bool vfp_VCMP(Cond cond, bool D, size_t Vd, bool sz, bool E, bool M, size_t Vm);
|
||||||
|
bool vfp_VCMP_zero(Cond cond, bool D, size_t Vd, bool sz, bool E);
|
||||||
|
bool vfp_VRINTR(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
|
||||||
|
bool vfp_VRINTZ(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
|
||||||
|
bool vfp_VRINTX(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
|
||||||
|
bool vfp_VCVT_f_to_f(Cond cond, bool D, size_t Vd, bool sz, bool M, size_t Vm);
|
||||||
|
bool vfp_VCVT_from_int(Cond cond, bool D, size_t Vd, bool sz, bool is_signed, bool M, size_t Vm);
|
||||||
|
bool vfp_VCVT_from_fixed(Cond cond, bool D, bool U, size_t Vd, bool sz, bool sx, Imm<1> i, Imm<4> imm4);
|
||||||
|
bool vfp_VCVT_to_u32(Cond cond, bool D, size_t Vd, bool sz, bool round_towards_zero, bool M, size_t Vm);
|
||||||
|
bool vfp_VCVT_to_s32(Cond cond, bool D, size_t Vd, bool sz, bool round_towards_zero, bool M, size_t Vm);
|
||||||
|
bool vfp_VCVT_to_fixed(Cond cond, bool D, bool U, size_t Vd, bool sz, bool sx, Imm<1> i, Imm<4> imm4);
|
||||||
|
bool vfp_VRINT_rm(bool D, size_t rm, size_t Vd, bool sz, bool M, size_t Vm);
|
||||||
|
bool vfp_VCVT_rm(bool D, size_t rm, size_t Vd, bool sz, bool U, bool M, size_t Vm);
|
||||||
|
|
||||||
|
// Floating-point system register access
|
||||||
|
bool vfp_VMSR(Cond cond, Reg t);
|
||||||
|
bool vfp_VMRS(Cond cond, Reg t);
|
||||||
|
|
||||||
|
// Floating-point load-store instructions
|
||||||
|
bool vfp_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8);
|
||||||
|
bool vfp_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd, bool sz, Imm<8> imm8);
|
||||||
|
bool vfp_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm<8> imm8);
|
||||||
|
bool vfp_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm<8> imm8);
|
||||||
|
bool vfp_VSTM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8);
|
||||||
|
bool vfp_VSTM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8);
|
||||||
|
bool vfp_VLDM_a1(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8);
|
||||||
|
bool vfp_VLDM_a2(Cond cond, bool p, bool u, bool D, bool w, Reg n, size_t Vd, Imm<8> imm8);
|
||||||
|
|
||||||
|
// Advanced SIMD one register, modified immediate
|
||||||
|
bool asimd_VMOV_imm(Imm<1> a, bool D, Imm<1> b, Imm<1> c, Imm<1> d, size_t Vd, Imm<4> cmode, bool Q, bool op, Imm<1> e, Imm<1> f, Imm<1> g, Imm<1> h);
|
||||||
|
|
||||||
|
// Advanced SIMD three register with same length
|
||||||
|
bool asimd_VHADD(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VQADD(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VRHADD(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VAND_reg(bool D, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VBIC_reg(bool D, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VORR_reg(bool D, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VORN_reg(bool D, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VEOR_reg(bool D, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VBSL(bool D, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VBIT(bool D, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VBIF(bool D, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VHSUB(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VQSUB(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VCGT_reg(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VCGE_reg(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VABD(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VABA(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VADD_int(bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VSUB_int(bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VSHL_reg(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VQSHL_reg(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VRSHL(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VMAX(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, bool op, size_t Vm);
|
||||||
|
bool asimd_VTST(bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VCEQ_reg(bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VMLA(bool op, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VMUL(bool P, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VPMAX_int(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, bool op, size_t Vm);
|
||||||
|
bool asimd_VQDMULH(bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VQRDMULH(bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VPADD(bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VFMA(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VFMS(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VADD_float(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VSUB_float(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VPADD_float(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VABD_float(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VMLA_float(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VMLS_float(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VMUL_float(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VCEQ_reg_float(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VCGE_reg_float(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VCGT_reg_float(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VACGE(bool D, bool op, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VMAX_float(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VMIN_float(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VPMAX_float(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VPMIN_float(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VRECPS(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VRSQRTS(bool D, bool sz, size_t Vn, size_t Vd, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
|
||||||
|
// Advanced SIMD three registers with different lengths
|
||||||
|
bool asimd_VADDL(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool op, bool N, bool M, size_t Vm);
|
||||||
|
bool asimd_VSUBL(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool op, bool N, bool M, size_t Vm);
|
||||||
|
bool asimd_VABAL(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool M, size_t Vm);
|
||||||
|
bool asimd_VABDL(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool M, size_t Vm);
|
||||||
|
bool asimd_VMLAL(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool op, bool N, bool M, size_t Vm);
|
||||||
|
bool asimd_VMULL(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool P, bool N, bool M, size_t Vm);
|
||||||
|
|
||||||
|
// Advanced SIMD two registers and a scalar
|
||||||
|
bool asimd_VMLA_scalar(bool Q, bool D, size_t sz, size_t Vn, size_t Vd, bool op, bool F, bool N, bool M, size_t Vm);
|
||||||
|
bool asimd_VMLAL_scalar(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool op, bool N, bool M, size_t Vm);
|
||||||
|
bool asimd_VMUL_scalar(bool Q, bool D, size_t sz, size_t Vn, size_t Vd, bool F, bool N, bool M, size_t Vm);
|
||||||
|
bool asimd_VMULL_scalar(bool U, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool M, size_t Vm);
|
||||||
|
bool asimd_VQDMULL_scalar(bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool M, size_t Vm);
|
||||||
|
bool asimd_VQDMULH_scalar(bool Q, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool M, size_t Vm);
|
||||||
|
bool asimd_VQRDMULH_scalar(bool Q, bool D, size_t sz, size_t Vn, size_t Vd, bool N, bool M, size_t Vm);
|
||||||
|
|
||||||
|
// Two registers and a shift amount
|
||||||
|
bool asimd_SHR(bool U, bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_SRA(bool U, bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VRSHR(bool U, bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VRSRA(bool U, bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VSRI(bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VSHL(bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VSLI(bool D, size_t imm6, size_t Vd, bool L, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VQSHL(bool U, bool D, size_t imm6, size_t Vd, bool op, bool L, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VSHRN(bool D, size_t imm6, size_t Vd, bool M, size_t Vm);
|
||||||
|
bool asimd_VRSHRN(bool D, size_t imm6, size_t Vd, bool M, size_t Vm);
|
||||||
|
bool asimd_VQSHRUN(bool D, size_t imm6, size_t Vd, bool M, size_t Vm);
|
||||||
|
bool asimd_VQRSHRUN(bool D, size_t imm6, size_t Vd, bool M, size_t Vm);
|
||||||
|
bool asimd_VQSHRN(bool U, bool D, size_t imm6, size_t Vd, bool M, size_t Vm);
|
||||||
|
bool asimd_VQRSHRN(bool U, bool D, size_t imm6, size_t Vd, bool M, size_t Vm);
|
||||||
|
bool asimd_VSHLL(bool U, bool D, size_t imm6, size_t Vd, bool M, size_t Vm);
|
||||||
|
bool asimd_VCVT_fixed(bool U, bool D, size_t imm6, size_t Vd, bool to_fixed, bool Q, bool M, size_t Vm);
|
||||||
|
|
||||||
|
// Advanced SIMD two register, miscellaneous
|
||||||
|
bool asimd_VREV(bool D, size_t sz, size_t Vd, size_t op, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VPADDL(bool D, size_t sz, size_t Vd, bool op, bool Q, bool M, size_t Vm);
|
||||||
|
bool v8_AESD(bool D, size_t sz, size_t Vd, bool M, size_t Vm);
|
||||||
|
bool v8_AESE(bool D, size_t sz, size_t Vd, bool M, size_t Vm);
|
||||||
|
bool v8_AESIMC(bool D, size_t sz, size_t Vd, bool M, size_t Vm);
|
||||||
|
bool v8_AESMC(bool D, size_t sz, size_t Vd, bool M, size_t Vm);
|
||||||
|
bool asimd_VCLS(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VCLZ(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VCNT(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VMVN_reg(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VPADAL(bool D, size_t sz, size_t Vd, bool op, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VQABS(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VQNEG(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VCGT_zero(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VCGE_zero(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VCEQ_zero(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VCLE_zero(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VCLT_zero(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VABS(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VNEG(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VSWP(bool D, size_t Vd, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VTRN(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VUZP(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VZIP(bool D, size_t sz, size_t Vd, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VMOVN(bool D, size_t sz, size_t Vd, bool M, size_t Vm);
|
||||||
|
bool asimd_VQMOVUN(bool D, size_t sz, size_t Vd, bool M, size_t Vm);
|
||||||
|
bool asimd_VQMOVN(bool D, size_t sz, size_t Vd, bool op, bool M, size_t Vm);
|
||||||
|
bool asimd_VSHLL_max(bool D, size_t sz, size_t Vd, bool M, size_t Vm);
|
||||||
|
bool asimd_VCVT_half(bool D, size_t sz, size_t Vd, bool op, bool M, size_t Vm);
|
||||||
|
bool asimd_VRECPE(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VRSQRTE(bool D, size_t sz, size_t Vd, bool F, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VCVT_integer(bool D, size_t sz, size_t Vd, bool op, bool U, bool Q, bool M, size_t Vm);
|
||||||
|
|
||||||
|
// Advanced SIMD miscellaneous
|
||||||
|
bool asimd_VEXT(bool D, size_t Vn, size_t Vd, Imm<4> imm4, bool N, bool Q, bool M, size_t Vm);
|
||||||
|
bool asimd_VTBL(bool D, size_t Vn, size_t Vd, size_t len, bool N, bool M, size_t Vm);
|
||||||
|
bool asimd_VTBX(bool D, size_t Vn, size_t Vd, size_t len, bool N, bool M, size_t Vm);
|
||||||
|
bool asimd_VDUP_scalar(bool D, Imm<4> imm4, size_t Vd, bool Q, bool M, size_t Vm);
|
||||||
|
|
||||||
|
// Advanced SIMD load/store structures
|
||||||
|
bool v8_VST_multiple(bool D, Reg n, size_t Vd, Imm<4> type, size_t sz, size_t align, Reg m);
|
||||||
|
bool v8_VLD_multiple(bool D, Reg n, size_t Vd, Imm<4> type, size_t sz, size_t align, Reg m);
|
||||||
|
bool v8_VLD_all_lanes(bool D, Reg n, size_t Vd, size_t nn, size_t sz, bool T, bool a, Reg m);
|
||||||
|
bool v8_VST_single(bool D, Reg n, size_t Vd, size_t sz, size_t nn, size_t index_align, Reg m);
|
||||||
|
bool v8_VLD_single(bool D, Reg n, size_t Vd, size_t sz, size_t nn, size_t index_align, Reg m);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Dynarmic::A32
|
|
@ -7,7 +7,7 @@
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
#include "dynarmic/interface/A32/config.h"
|
#include "dynarmic/interface/A32/config.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
#include "dynarmic/interface/A32/config.h"
|
#include "dynarmic/interface/A32/config.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
static IR::U32 Pack2x16To1x32(A32::IREmitter& ir, IR::U32 lo, IR::U32 hi) {
|
static IR::U32 Pack2x16To1x32(A32::IREmitter& ir, IR::U32 lo, IR::U32 hi) {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
#include "dynarmic/interface/A32/config.h"
|
#include "dynarmic/interface/A32/config.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
static bool ITBlockCheck(const A32::IREmitter& ir) {
|
static bool ITBlockCheck(const A32::IREmitter& ir) {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
static bool ITBlockCheck(const A32::IREmitter& ir) {
|
static bool ITBlockCheck(const A32::IREmitter& ir) {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
static bool ITBlockCheck(const A32::IREmitter& ir) {
|
static bool ITBlockCheck(const A32::IREmitter& ir) {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
static IR::U32 Pack2x16To1x32(A32::IREmitter& ir, IR::U32 lo, IR::U32 hi) {
|
static IR::U32 Pack2x16To1x32(A32::IREmitter& ir, IR::U32 lo, IR::U32 hi) {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
|
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||||
|
#include "dynarmic/frontend/A32/a32_types.h"
|
||||||
#include "dynarmic/frontend/A32/decoder/arm.h"
|
#include "dynarmic/frontend/A32/decoder/arm.h"
|
||||||
#include "dynarmic/frontend/A32/decoder/asimd.h"
|
#include "dynarmic/frontend/A32/decoder/asimd.h"
|
||||||
#include "dynarmic/frontend/A32/decoder/vfp.h"
|
#include "dynarmic/frontend/A32/decoder/vfp.h"
|
||||||
#include "dynarmic/frontend/A32/location_descriptor.h"
|
#include "dynarmic/frontend/A32/translate/a32_translate.h"
|
||||||
#include "dynarmic/frontend/A32/translate/conditional_state.h"
|
#include "dynarmic/frontend/A32/translate/conditional_state.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
#include "dynarmic/frontend/A32/translate/translate.h"
|
|
||||||
#include "dynarmic/frontend/A32/translate/translate_callbacks.h"
|
#include "dynarmic/frontend/A32/translate/translate_callbacks.h"
|
||||||
#include "dynarmic/frontend/A32/types.h"
|
|
||||||
#include "dynarmic/interface/A32/config.h"
|
#include "dynarmic/interface/A32/config.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,15 @@
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/frontend/A32/a32_ir_emitter.h"
|
||||||
|
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||||
#include "dynarmic/frontend/A32/decoder/asimd.h"
|
#include "dynarmic/frontend/A32/decoder/asimd.h"
|
||||||
#include "dynarmic/frontend/A32/decoder/thumb16.h"
|
#include "dynarmic/frontend/A32/decoder/thumb16.h"
|
||||||
#include "dynarmic/frontend/A32/decoder/thumb32.h"
|
#include "dynarmic/frontend/A32/decoder/thumb32.h"
|
||||||
#include "dynarmic/frontend/A32/decoder/vfp.h"
|
#include "dynarmic/frontend/A32/decoder/vfp.h"
|
||||||
#include "dynarmic/frontend/A32/ir_emitter.h"
|
#include "dynarmic/frontend/A32/translate/a32_translate.h"
|
||||||
#include "dynarmic/frontend/A32/location_descriptor.h"
|
|
||||||
#include "dynarmic/frontend/A32/translate/conditional_state.h"
|
#include "dynarmic/frontend/A32/translate/conditional_state.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
#include "dynarmic/frontend/A32/translate/translate.h"
|
|
||||||
#include "dynarmic/frontend/A32/translate/translate_callbacks.h"
|
#include "dynarmic/frontend/A32/translate/translate_callbacks.h"
|
||||||
#include "dynarmic/frontend/imm.h"
|
#include "dynarmic/frontend/imm.h"
|
||||||
#include "dynarmic/interface/A32/config.h"
|
#include "dynarmic/interface/A32/config.h"
|
||||||
|
|
264
externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.cpp
vendored
Executable file
264
externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.cpp
vendored
Executable file
|
@ -0,0 +1,264 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/frontend/A64/a64_ir_emitter.h"
|
||||||
|
|
||||||
|
#include "dynarmic/common/assert.h"
|
||||||
|
#include "dynarmic/ir/opcodes.h"
|
||||||
|
|
||||||
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
|
using Opcode = IR::Opcode;
|
||||||
|
|
||||||
|
u64 IREmitter::PC() const {
|
||||||
|
return current_location->PC();
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 IREmitter::AlignPC(size_t alignment) const {
|
||||||
|
const u64 pc = PC();
|
||||||
|
return static_cast<u64>(pc - pc % alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetCheckBit(const IR::U1& value) {
|
||||||
|
Inst(Opcode::A64SetCheckBit, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U1 IREmitter::GetCFlag() {
|
||||||
|
return Inst<IR::U1>(Opcode::A64GetCFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::GetNZCVRaw() {
|
||||||
|
return Inst<IR::U32>(Opcode::A64GetNZCVRaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetNZCVRaw(IR::U32 value) {
|
||||||
|
Inst(Opcode::A64SetNZCVRaw, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetNZCV(const IR::NZCV& nzcv) {
|
||||||
|
Inst(Opcode::A64SetNZCV, nzcv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::OrQC(const IR::U1& value) {
|
||||||
|
Inst(Opcode::A64OrQC, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::CallSupervisor(u32 imm) {
|
||||||
|
Inst(Opcode::A64CallSupervisor, Imm32(imm));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::ExceptionRaised(Exception exception) {
|
||||||
|
Inst(Opcode::A64ExceptionRaised, Imm64(PC()), Imm64(static_cast<u64>(exception)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::DataCacheOperationRaised(DataCacheOperation op, const IR::U64& value) {
|
||||||
|
Inst(Opcode::A64DataCacheOperationRaised, Imm64(static_cast<u64>(op)), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::InstructionCacheOperationRaised(InstructionCacheOperation op, const IR::U64& value) {
|
||||||
|
Inst(Opcode::A64InstructionCacheOperationRaised, Imm64(static_cast<u64>(op)), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::DataSynchronizationBarrier() {
|
||||||
|
Inst(Opcode::A64DataSynchronizationBarrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::DataMemoryBarrier() {
|
||||||
|
Inst(Opcode::A64DataMemoryBarrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::InstructionSynchronizationBarrier() {
|
||||||
|
Inst(Opcode::A64InstructionSynchronizationBarrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::GetCNTFRQ() {
|
||||||
|
return Inst<IR::U32>(Opcode::A64GetCNTFRQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 IREmitter::GetCNTPCT() {
|
||||||
|
return Inst<IR::U64>(Opcode::A64GetCNTPCT);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::GetCTR() {
|
||||||
|
return Inst<IR::U32>(Opcode::A64GetCTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::GetDCZID() {
|
||||||
|
return Inst<IR::U32>(Opcode::A64GetDCZID);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 IREmitter::GetTPIDR() {
|
||||||
|
return Inst<IR::U64>(Opcode::A64GetTPIDR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetTPIDR(const IR::U64& value) {
|
||||||
|
Inst(Opcode::A64SetTPIDR, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 IREmitter::GetTPIDRRO() {
|
||||||
|
return Inst<IR::U64>(Opcode::A64GetTPIDRRO);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::ClearExclusive() {
|
||||||
|
Inst(Opcode::A64ClearExclusive);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U8 IREmitter::ReadMemory8(const IR::U64& vaddr) {
|
||||||
|
return Inst<IR::U8>(Opcode::A64ReadMemory8, vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U16 IREmitter::ReadMemory16(const IR::U64& vaddr) {
|
||||||
|
return Inst<IR::U16>(Opcode::A64ReadMemory16, vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::ReadMemory32(const IR::U64& vaddr) {
|
||||||
|
return Inst<IR::U32>(Opcode::A64ReadMemory32, vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 IREmitter::ReadMemory64(const IR::U64& vaddr) {
|
||||||
|
return Inst<IR::U64>(Opcode::A64ReadMemory64, vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U128 IREmitter::ReadMemory128(const IR::U64& vaddr) {
|
||||||
|
return Inst<IR::U128>(Opcode::A64ReadMemory128, vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U8 IREmitter::ExclusiveReadMemory8(const IR::U64& vaddr) {
|
||||||
|
return Inst<IR::U8>(Opcode::A64ExclusiveReadMemory8, vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U16 IREmitter::ExclusiveReadMemory16(const IR::U64& vaddr) {
|
||||||
|
return Inst<IR::U16>(Opcode::A64ExclusiveReadMemory16, vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::ExclusiveReadMemory32(const IR::U64& vaddr) {
|
||||||
|
return Inst<IR::U32>(Opcode::A64ExclusiveReadMemory32, vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 IREmitter::ExclusiveReadMemory64(const IR::U64& vaddr) {
|
||||||
|
return Inst<IR::U64>(Opcode::A64ExclusiveReadMemory64, vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U128 IREmitter::ExclusiveReadMemory128(const IR::U64& vaddr) {
|
||||||
|
return Inst<IR::U128>(Opcode::A64ExclusiveReadMemory128, vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::WriteMemory8(const IR::U64& vaddr, const IR::U8& value) {
|
||||||
|
Inst(Opcode::A64WriteMemory8, vaddr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::WriteMemory16(const IR::U64& vaddr, const IR::U16& value) {
|
||||||
|
Inst(Opcode::A64WriteMemory16, vaddr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::WriteMemory32(const IR::U64& vaddr, const IR::U32& value) {
|
||||||
|
Inst(Opcode::A64WriteMemory32, vaddr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::WriteMemory64(const IR::U64& vaddr, const IR::U64& value) {
|
||||||
|
Inst(Opcode::A64WriteMemory64, vaddr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::WriteMemory128(const IR::U64& vaddr, const IR::U128& value) {
|
||||||
|
Inst(Opcode::A64WriteMemory128, vaddr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::ExclusiveWriteMemory8(const IR::U64& vaddr, const IR::U8& value) {
|
||||||
|
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory8, vaddr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::ExclusiveWriteMemory16(const IR::U64& vaddr, const IR::U16& value) {
|
||||||
|
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory16, vaddr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::ExclusiveWriteMemory32(const IR::U64& vaddr, const IR::U32& value) {
|
||||||
|
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory32, vaddr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::ExclusiveWriteMemory64(const IR::U64& vaddr, const IR::U64& value) {
|
||||||
|
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory64, vaddr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::ExclusiveWriteMemory128(const IR::U64& vaddr, const IR::U128& value) {
|
||||||
|
return Inst<IR::U32>(Opcode::A64ExclusiveWriteMemory128, vaddr, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::GetW(Reg reg) {
|
||||||
|
if (reg == Reg::ZR)
|
||||||
|
return Imm32(0);
|
||||||
|
return Inst<IR::U32>(Opcode::A64GetW, IR::Value(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 IREmitter::GetX(Reg reg) {
|
||||||
|
if (reg == Reg::ZR)
|
||||||
|
return Imm64(0);
|
||||||
|
return Inst<IR::U64>(Opcode::A64GetX, IR::Value(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U128 IREmitter::GetS(Vec vec) {
|
||||||
|
return Inst<IR::U128>(Opcode::A64GetS, IR::Value(vec));
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U128 IREmitter::GetD(Vec vec) {
|
||||||
|
return Inst<IR::U128>(Opcode::A64GetD, IR::Value(vec));
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U128 IREmitter::GetQ(Vec vec) {
|
||||||
|
return Inst<IR::U128>(Opcode::A64GetQ, IR::Value(vec));
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U64 IREmitter::GetSP() {
|
||||||
|
return Inst<IR::U64>(Opcode::A64GetSP);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::GetFPCR() {
|
||||||
|
return Inst<IR::U32>(Opcode::A64GetFPCR);
|
||||||
|
}
|
||||||
|
|
||||||
|
IR::U32 IREmitter::GetFPSR() {
|
||||||
|
return Inst<IR::U32>(Opcode::A64GetFPSR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetW(const Reg reg, const IR::U32& value) {
|
||||||
|
if (reg == Reg::ZR)
|
||||||
|
return;
|
||||||
|
Inst(Opcode::A64SetW, IR::Value(reg), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetX(const Reg reg, const IR::U64& value) {
|
||||||
|
if (reg == Reg::ZR)
|
||||||
|
return;
|
||||||
|
Inst(Opcode::A64SetX, IR::Value(reg), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetS(const Vec vec, const IR::U128& value) {
|
||||||
|
Inst(Opcode::A64SetS, IR::Value(vec), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetD(const Vec vec, const IR::U128& value) {
|
||||||
|
Inst(Opcode::A64SetD, IR::Value(vec), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetQ(const Vec vec, const IR::U128& value) {
|
||||||
|
Inst(Opcode::A64SetQ, IR::Value(vec), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetSP(const IR::U64& value) {
|
||||||
|
Inst(Opcode::A64SetSP, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetFPCR(const IR::U32& value) {
|
||||||
|
Inst(Opcode::A64SetFPCR, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetFPSR(const IR::U32& value) {
|
||||||
|
Inst(Opcode::A64SetFPSR, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetPC(const IR::U64& value) {
|
||||||
|
Inst(Opcode::A64SetPC, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Dynarmic::A64
|
99
externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.h
vendored
Executable file
99
externals/dynarmic/src/dynarmic/frontend/A64/a64_ir_emitter.h
vendored
Executable file
|
@ -0,0 +1,99 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include "dynarmic/common/common_types.h"
|
||||||
|
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
||||||
|
#include "dynarmic/frontend/A64/a64_types.h"
|
||||||
|
#include "dynarmic/interface/A64/config.h"
|
||||||
|
#include "dynarmic/ir/ir_emitter.h"
|
||||||
|
#include "dynarmic/ir/value.h"
|
||||||
|
|
||||||
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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:
|
||||||
|
explicit IREmitter(IR::Block& block)
|
||||||
|
: IR::IREmitter(block) {}
|
||||||
|
explicit IREmitter(IR::Block& block, LocationDescriptor descriptor)
|
||||||
|
: IR::IREmitter(block), current_location(descriptor) {}
|
||||||
|
|
||||||
|
std::optional<LocationDescriptor> current_location;
|
||||||
|
|
||||||
|
u64 PC() const;
|
||||||
|
u64 AlignPC(size_t alignment) const;
|
||||||
|
|
||||||
|
void SetCheckBit(const IR::U1& value);
|
||||||
|
IR::U1 GetCFlag();
|
||||||
|
IR::U32 GetNZCVRaw();
|
||||||
|
void SetNZCVRaw(IR::U32 value);
|
||||||
|
void SetNZCV(const IR::NZCV& nzcv);
|
||||||
|
void OrQC(const IR::U1& value);
|
||||||
|
|
||||||
|
void CallSupervisor(u32 imm);
|
||||||
|
void ExceptionRaised(Exception exception);
|
||||||
|
void DataCacheOperationRaised(DataCacheOperation op, const IR::U64& value);
|
||||||
|
void InstructionCacheOperationRaised(InstructionCacheOperation op, const IR::U64& value);
|
||||||
|
void DataSynchronizationBarrier();
|
||||||
|
void DataMemoryBarrier();
|
||||||
|
void InstructionSynchronizationBarrier();
|
||||||
|
IR::U32 GetCNTFRQ();
|
||||||
|
IR::U64 GetCNTPCT(); // TODO: Ensure sub-basic-block cycle counts are updated before this.
|
||||||
|
IR::U32 GetCTR();
|
||||||
|
IR::U32 GetDCZID();
|
||||||
|
IR::U64 GetTPIDR();
|
||||||
|
IR::U64 GetTPIDRRO();
|
||||||
|
void SetTPIDR(const IR::U64& value);
|
||||||
|
|
||||||
|
void ClearExclusive();
|
||||||
|
IR::U8 ReadMemory8(const IR::U64& vaddr);
|
||||||
|
IR::U16 ReadMemory16(const IR::U64& vaddr);
|
||||||
|
IR::U32 ReadMemory32(const IR::U64& vaddr);
|
||||||
|
IR::U64 ReadMemory64(const IR::U64& vaddr);
|
||||||
|
IR::U128 ReadMemory128(const IR::U64& vaddr);
|
||||||
|
IR::U8 ExclusiveReadMemory8(const IR::U64& vaddr);
|
||||||
|
IR::U16 ExclusiveReadMemory16(const IR::U64& vaddr);
|
||||||
|
IR::U32 ExclusiveReadMemory32(const IR::U64& vaddr);
|
||||||
|
IR::U64 ExclusiveReadMemory64(const IR::U64& vaddr);
|
||||||
|
IR::U128 ExclusiveReadMemory128(const IR::U64& vaddr);
|
||||||
|
void WriteMemory8(const IR::U64& vaddr, const IR::U8& value);
|
||||||
|
void WriteMemory16(const IR::U64& vaddr, const IR::U16& value);
|
||||||
|
void WriteMemory32(const IR::U64& vaddr, const IR::U32& value);
|
||||||
|
void WriteMemory64(const IR::U64& vaddr, const IR::U64& value);
|
||||||
|
void WriteMemory128(const IR::U64& vaddr, const IR::U128& value);
|
||||||
|
IR::U32 ExclusiveWriteMemory8(const IR::U64& vaddr, const IR::U8& value);
|
||||||
|
IR::U32 ExclusiveWriteMemory16(const IR::U64& vaddr, const IR::U16& value);
|
||||||
|
IR::U32 ExclusiveWriteMemory32(const IR::U64& vaddr, const IR::U32& value);
|
||||||
|
IR::U32 ExclusiveWriteMemory64(const IR::U64& vaddr, const IR::U64& value);
|
||||||
|
IR::U32 ExclusiveWriteMemory128(const IR::U64& vaddr, const IR::U128& value);
|
||||||
|
|
||||||
|
IR::U32 GetW(Reg source_reg);
|
||||||
|
IR::U64 GetX(Reg source_reg);
|
||||||
|
IR::U128 GetS(Vec source_vec);
|
||||||
|
IR::U128 GetD(Vec source_vec);
|
||||||
|
IR::U128 GetQ(Vec source_vec);
|
||||||
|
IR::U64 GetSP();
|
||||||
|
IR::U32 GetFPCR();
|
||||||
|
IR::U32 GetFPSR();
|
||||||
|
void SetW(Reg dest_reg, const IR::U32& value);
|
||||||
|
void SetX(Reg dest_reg, const IR::U64& value);
|
||||||
|
void SetS(Vec dest_vec, const IR::U128& value);
|
||||||
|
void SetD(Vec dest_vec, const IR::U128& value);
|
||||||
|
void SetQ(Vec dest_vec, const IR::U128& value);
|
||||||
|
void SetSP(const IR::U64& value);
|
||||||
|
void SetFPCR(const IR::U32& value);
|
||||||
|
void SetFPSR(const IR::U32& value);
|
||||||
|
void SetPC(const IR::U64& value);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Dynarmic::A64
|
19
externals/dynarmic/src/dynarmic/frontend/A64/a64_location_descriptor.cpp
vendored
Executable file
19
externals/dynarmic/src/dynarmic/frontend/A64/a64_location_descriptor.cpp
vendored
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& o, const LocationDescriptor& descriptor) {
|
||||||
|
o << fmt::format("{{{}, {}{}}}", descriptor.PC(), descriptor.FPCR().Value(), descriptor.SingleStepping() ? ", step" : "");
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Dynarmic::A64
|
106
externals/dynarmic/src/dynarmic/frontend/A64/a64_location_descriptor.h
vendored
Executable file
106
externals/dynarmic/src/dynarmic/frontend/A64/a64_location_descriptor.h
vendored
Executable file
|
@ -0,0 +1,106 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2016 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "dynarmic/common/bit_util.h"
|
||||||
|
#include "dynarmic/common/common_types.h"
|
||||||
|
#include "dynarmic/common/fp/fpcr.h"
|
||||||
|
#include "dynarmic/ir/location_descriptor.h"
|
||||||
|
|
||||||
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
class LocationDescriptor {
|
||||||
|
public:
|
||||||
|
static constexpr size_t pc_bit_count = 56;
|
||||||
|
static constexpr u64 pc_mask = Common::Ones<u64>(pc_bit_count);
|
||||||
|
static constexpr u32 fpcr_mask = 0x07C8'0000;
|
||||||
|
static constexpr size_t fpcr_shift = 37;
|
||||||
|
static constexpr size_t single_stepping_bit = 57;
|
||||||
|
static_assert((pc_mask & (u64(fpcr_mask) << fpcr_shift) & (u64(1) << single_stepping_bit)) == 0);
|
||||||
|
|
||||||
|
LocationDescriptor(u64 pc, FP::FPCR fpcr, bool single_stepping = false)
|
||||||
|
: pc(pc & pc_mask), fpcr(fpcr.Value() & fpcr_mask), single_stepping(single_stepping) {}
|
||||||
|
|
||||||
|
explicit LocationDescriptor(const IR::LocationDescriptor& o)
|
||||||
|
: pc(o.Value() & pc_mask)
|
||||||
|
, fpcr((o.Value() >> fpcr_shift) & fpcr_mask)
|
||||||
|
, single_stepping(Common::Bit<single_stepping_bit>(o.Value())) {}
|
||||||
|
|
||||||
|
u64 PC() const { return Common::SignExtend<pc_bit_count>(pc); }
|
||||||
|
FP::FPCR FPCR() const { return fpcr; }
|
||||||
|
bool SingleStepping() const { return single_stepping; }
|
||||||
|
|
||||||
|
bool operator==(const LocationDescriptor& o) const {
|
||||||
|
return std::tie(pc, fpcr, single_stepping) == std::tie(o.pc, o.fpcr, o.single_stepping);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const LocationDescriptor& o) const {
|
||||||
|
return !operator==(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocationDescriptor SetPC(u64 new_pc) const {
|
||||||
|
return LocationDescriptor(new_pc, fpcr, single_stepping);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocationDescriptor AdvancePC(int amount) const {
|
||||||
|
return LocationDescriptor(static_cast<u64>(pc + amount), fpcr, single_stepping);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocationDescriptor SetSingleStepping(bool new_single_stepping) const {
|
||||||
|
return LocationDescriptor(pc, fpcr, new_single_stepping);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 UniqueHash() const noexcept {
|
||||||
|
// This value MUST BE UNIQUE.
|
||||||
|
// This calculation has to match up with EmitTerminalPopRSBHint
|
||||||
|
const u64 fpcr_u64 = static_cast<u64>(fpcr.Value()) << fpcr_shift;
|
||||||
|
const u64 single_stepping_u64 = static_cast<u64>(single_stepping) << single_stepping_bit;
|
||||||
|
return pc | fpcr_u64 | single_stepping_u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator IR::LocationDescriptor() const {
|
||||||
|
return IR::LocationDescriptor{UniqueHash()};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
u64 pc; ///< Current program counter value.
|
||||||
|
FP::FPCR fpcr; ///< Floating point 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::A64
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template<>
|
||||||
|
struct less<Dynarmic::A64::LocationDescriptor> {
|
||||||
|
bool operator()(const Dynarmic::A64::LocationDescriptor& x, const Dynarmic::A64::LocationDescriptor& y) const noexcept {
|
||||||
|
return x.UniqueHash() < y.UniqueHash();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct hash<Dynarmic::A64::LocationDescriptor> {
|
||||||
|
size_t operator()(const Dynarmic::A64::LocationDescriptor& x) const noexcept {
|
||||||
|
return std::hash<u64>()(x.UniqueHash());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace std
|
43
externals/dynarmic/src/dynarmic/frontend/A64/a64_types.cpp
vendored
Executable file
43
externals/dynarmic/src/dynarmic/frontend/A64/a64_types.cpp
vendored
Executable file
|
@ -0,0 +1,43 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2018 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/frontend/A64/a64_types.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
|
const char* CondToString(Cond cond) {
|
||||||
|
static constexpr std::array cond_strs = {
|
||||||
|
"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
|
||||||
|
"hi", "ls", "ge", "lt", "gt", "le", "al", "nv"};
|
||||||
|
return cond_strs.at(static_cast<size_t>(cond));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string RegToString(Reg reg) {
|
||||||
|
if (reg == Reg::R31) {
|
||||||
|
return "sp|zr";
|
||||||
|
}
|
||||||
|
return fmt::format("r{}", static_cast<size_t>(reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string VecToString(Vec vec) {
|
||||||
|
return fmt::format("v{}", static_cast<size_t>(vec));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& o, Reg reg) {
|
||||||
|
o << RegToString(reg);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& o, Vec vec) {
|
||||||
|
o << VecToString(vec);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Dynarmic::A64
|
128
externals/dynarmic/src/dynarmic/frontend/A64/a64_types.h
vendored
Executable file
128
externals/dynarmic/src/dynarmic/frontend/A64/a64_types.h
vendored
Executable file
|
@ -0,0 +1,128 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2018 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "dynarmic/common/assert.h"
|
||||||
|
#include "dynarmic/common/common_types.h"
|
||||||
|
#include "dynarmic/ir/cond.h"
|
||||||
|
|
||||||
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
|
using Cond = IR::Cond;
|
||||||
|
|
||||||
|
enum class Reg {
|
||||||
|
R0,
|
||||||
|
R1,
|
||||||
|
R2,
|
||||||
|
R3,
|
||||||
|
R4,
|
||||||
|
R5,
|
||||||
|
R6,
|
||||||
|
R7,
|
||||||
|
R8,
|
||||||
|
R9,
|
||||||
|
R10,
|
||||||
|
R11,
|
||||||
|
R12,
|
||||||
|
R13,
|
||||||
|
R14,
|
||||||
|
R15,
|
||||||
|
R16,
|
||||||
|
R17,
|
||||||
|
R18,
|
||||||
|
R19,
|
||||||
|
R20,
|
||||||
|
R21,
|
||||||
|
R22,
|
||||||
|
R23,
|
||||||
|
R24,
|
||||||
|
R25,
|
||||||
|
R26,
|
||||||
|
R27,
|
||||||
|
R28,
|
||||||
|
R29,
|
||||||
|
R30,
|
||||||
|
R31,
|
||||||
|
LR = R30,
|
||||||
|
SP = R31,
|
||||||
|
ZR = R31,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Vec {
|
||||||
|
V0,
|
||||||
|
V1,
|
||||||
|
V2,
|
||||||
|
V3,
|
||||||
|
V4,
|
||||||
|
V5,
|
||||||
|
V6,
|
||||||
|
V7,
|
||||||
|
V8,
|
||||||
|
V9,
|
||||||
|
V10,
|
||||||
|
V11,
|
||||||
|
V12,
|
||||||
|
V13,
|
||||||
|
V14,
|
||||||
|
V15,
|
||||||
|
V16,
|
||||||
|
V17,
|
||||||
|
V18,
|
||||||
|
V19,
|
||||||
|
V20,
|
||||||
|
V21,
|
||||||
|
V22,
|
||||||
|
V23,
|
||||||
|
V24,
|
||||||
|
V25,
|
||||||
|
V26,
|
||||||
|
V27,
|
||||||
|
V28,
|
||||||
|
V29,
|
||||||
|
V30,
|
||||||
|
V31,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ShiftType {
|
||||||
|
LSL,
|
||||||
|
LSR,
|
||||||
|
ASR,
|
||||||
|
ROR,
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* CondToString(Cond cond);
|
||||||
|
std::string RegToString(Reg reg);
|
||||||
|
std::string VecToString(Vec vec);
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& o, Reg reg);
|
||||||
|
std::ostream& operator<<(std::ostream& o, Vec vec);
|
||||||
|
|
||||||
|
constexpr size_t RegNumber(Reg reg) {
|
||||||
|
return static_cast<size_t>(reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t VecNumber(Vec vec) {
|
||||||
|
return static_cast<size_t>(vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Reg operator+(Reg reg, size_t number) {
|
||||||
|
const size_t new_reg = RegNumber(reg) + number;
|
||||||
|
ASSERT(new_reg <= 31);
|
||||||
|
|
||||||
|
return static_cast<Reg>(new_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Vec operator+(Vec vec, size_t number) {
|
||||||
|
const size_t new_vec = VecNumber(vec) + number;
|
||||||
|
ASSERT(new_vec <= 31);
|
||||||
|
|
||||||
|
return static_cast<Vec>(new_vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Dynarmic::A64
|
66
externals/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp
vendored
Executable file
66
externals/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.cpp
vendored
Executable file
|
@ -0,0 +1,66 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2018 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/frontend/A64/translate/a64_translate.h"
|
||||||
|
|
||||||
|
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
||||||
|
#include "dynarmic/frontend/A64/decoder/a64.h"
|
||||||
|
#include "dynarmic/frontend/A64/translate/impl/impl.h"
|
||||||
|
#include "dynarmic/ir/basic_block.h"
|
||||||
|
#include "dynarmic/ir/terminal.h"
|
||||||
|
|
||||||
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
|
IR::Block Translate(LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, TranslationOptions options) {
|
||||||
|
const bool single_step = descriptor.SingleStepping();
|
||||||
|
|
||||||
|
IR::Block block{descriptor};
|
||||||
|
TranslatorVisitor visitor{block, descriptor, std::move(options)};
|
||||||
|
|
||||||
|
bool should_continue = true;
|
||||||
|
do {
|
||||||
|
const u64 pc = visitor.ir.current_location->PC();
|
||||||
|
const u32 instruction = memory_read_code(pc);
|
||||||
|
|
||||||
|
if (auto decoder = Decode<TranslatorVisitor>(instruction)) {
|
||||||
|
should_continue = decoder->get().call(visitor, instruction);
|
||||||
|
} else {
|
||||||
|
should_continue = visitor.InterpretThisInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
visitor.ir.current_location = visitor.ir.current_location->AdvancePC(4);
|
||||||
|
block.CycleCount()++;
|
||||||
|
} while (should_continue && !single_step);
|
||||||
|
|
||||||
|
if (single_step && should_continue) {
|
||||||
|
visitor.ir.SetTerm(IR::Term::LinkBlock{*visitor.ir.current_location});
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_MSG(block.HasTerminal(), "Terminal has not been set");
|
||||||
|
|
||||||
|
block.SetEndLocation(*visitor.ir.current_location);
|
||||||
|
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslateSingleInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction) {
|
||||||
|
TranslatorVisitor visitor{block, descriptor, {}};
|
||||||
|
|
||||||
|
bool should_continue = true;
|
||||||
|
if (auto decoder = Decode<TranslatorVisitor>(instruction)) {
|
||||||
|
should_continue = decoder->get().call(visitor, instruction);
|
||||||
|
} else {
|
||||||
|
should_continue = visitor.InterpretThisInstruction();
|
||||||
|
}
|
||||||
|
|
||||||
|
visitor.ir.current_location = visitor.ir.current_location->AdvancePC(4);
|
||||||
|
block.CycleCount()++;
|
||||||
|
|
||||||
|
block.SetEndLocation(*visitor.ir.current_location);
|
||||||
|
|
||||||
|
return should_continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Dynarmic::A64
|
58
externals/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.h
vendored
Executable file
58
externals/dynarmic/src/dynarmic/frontend/A64/translate/a64_translate.h
vendored
Executable file
|
@ -0,0 +1,58 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2018 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "dynarmic/common/common_types.h"
|
||||||
|
|
||||||
|
namespace Dynarmic {
|
||||||
|
|
||||||
|
namespace IR {
|
||||||
|
class Block;
|
||||||
|
} // namespace IR
|
||||||
|
|
||||||
|
namespace A64 {
|
||||||
|
|
||||||
|
class LocationDescriptor;
|
||||||
|
|
||||||
|
using MemoryReadCodeFuncType = std::function<u32(u64 vaddr)>;
|
||||||
|
|
||||||
|
struct TranslationOptions {
|
||||||
|
/// 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 tells the translator a wall clock will be used, thus allowing it
|
||||||
|
/// to avoid writting certain unnecessary code only needed for cycle timers.
|
||||||
|
bool wall_clock_cntpct = 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, FPCR state, &c.
|
||||||
|
* @param memory_read_code The function 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, MemoryReadCodeFuncType memory_read_code, 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, FPCR 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 A64
|
||||||
|
} // namespace Dynarmic
|
128
externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/a64_branch.cpp
vendored
Executable file
128
externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/a64_branch.cpp
vendored
Executable file
|
@ -0,0 +1,128 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2018 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/frontend/A64/translate/impl/impl.h"
|
||||||
|
|
||||||
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
|
bool TranslatorVisitor::B_cond(Imm<19> imm19, Cond cond) {
|
||||||
|
const s64 offset = concatenate(imm19, Imm<2>{0}).SignExtend<s64>();
|
||||||
|
const u64 target = ir.PC() + offset;
|
||||||
|
|
||||||
|
const auto cond_pass = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
|
||||||
|
const auto cond_fail = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
|
||||||
|
ir.SetTerm(IR::Term::If{cond, cond_pass, cond_fail});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::B_uncond(Imm<26> imm26) {
|
||||||
|
const s64 offset = concatenate(imm26, Imm<2>{0}).SignExtend<s64>();
|
||||||
|
const u64 target = ir.PC() + offset;
|
||||||
|
|
||||||
|
ir.SetTerm(IR::Term::LinkBlock{ir.current_location->SetPC(target)});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::BL(Imm<26> imm26) {
|
||||||
|
const s64 offset = concatenate(imm26, Imm<2>{0}).SignExtend<s64>();
|
||||||
|
|
||||||
|
X(64, Reg::R30, ir.Imm64(ir.PC() + 4));
|
||||||
|
ir.PushRSB(ir.current_location->AdvancePC(4));
|
||||||
|
|
||||||
|
const u64 target = ir.PC() + offset;
|
||||||
|
ir.SetTerm(IR::Term::LinkBlock{ir.current_location->SetPC(target)});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::BLR(Reg Rn) {
|
||||||
|
const auto target = X(64, Rn);
|
||||||
|
|
||||||
|
X(64, Reg::R30, ir.Imm64(ir.PC() + 4));
|
||||||
|
ir.PushRSB(ir.current_location->AdvancePC(4));
|
||||||
|
|
||||||
|
ir.SetPC(target);
|
||||||
|
ir.SetTerm(IR::Term::FastDispatchHint{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::BR(Reg Rn) {
|
||||||
|
const auto target = X(64, Rn);
|
||||||
|
|
||||||
|
ir.SetPC(target);
|
||||||
|
ir.SetTerm(IR::Term::FastDispatchHint{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::RET(Reg Rn) {
|
||||||
|
const auto target = X(64, Rn);
|
||||||
|
|
||||||
|
ir.SetPC(target);
|
||||||
|
ir.SetTerm(IR::Term::PopRSBHint{});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::CBZ(bool sf, Imm<19> imm19, Reg Rt) {
|
||||||
|
const size_t datasize = sf ? 64 : 32;
|
||||||
|
const s64 offset = concatenate(imm19, Imm<2>{0}).SignExtend<s64>();
|
||||||
|
|
||||||
|
const IR::U32U64 operand1 = X(datasize, Rt);
|
||||||
|
|
||||||
|
ir.SetCheckBit(ir.IsZero(operand1));
|
||||||
|
|
||||||
|
const u64 target = ir.PC() + offset;
|
||||||
|
const auto cond_pass = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
|
||||||
|
const auto cond_fail = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
|
||||||
|
ir.SetTerm(IR::Term::CheckBit{cond_pass, cond_fail});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::CBNZ(bool sf, Imm<19> imm19, Reg Rt) {
|
||||||
|
const size_t datasize = sf ? 64 : 32;
|
||||||
|
const s64 offset = concatenate(imm19, Imm<2>{0}).SignExtend<s64>();
|
||||||
|
|
||||||
|
const IR::U32U64 operand1 = X(datasize, Rt);
|
||||||
|
|
||||||
|
ir.SetCheckBit(ir.IsZero(operand1));
|
||||||
|
|
||||||
|
const u64 target = ir.PC() + offset;
|
||||||
|
const auto cond_pass = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
|
||||||
|
const auto cond_fail = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
|
||||||
|
ir.SetTerm(IR::Term::CheckBit{cond_pass, cond_fail});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::TBZ(Imm<1> b5, Imm<5> b40, Imm<14> imm14, Reg Rt) {
|
||||||
|
const size_t datasize = b5 == 1 ? 64 : 32;
|
||||||
|
const u8 bit_pos = concatenate(b5, b40).ZeroExtend<u8>();
|
||||||
|
const s64 offset = concatenate(imm14, Imm<2>{0}).SignExtend<s64>();
|
||||||
|
|
||||||
|
const auto operand = X(datasize, Rt);
|
||||||
|
|
||||||
|
ir.SetCheckBit(ir.TestBit(operand, ir.Imm8(bit_pos)));
|
||||||
|
|
||||||
|
const u64 target = ir.PC() + offset;
|
||||||
|
const auto cond_1 = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
|
||||||
|
const auto cond_0 = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
|
||||||
|
ir.SetTerm(IR::Term::CheckBit{cond_1, cond_0});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::TBNZ(Imm<1> b5, Imm<5> b40, Imm<14> imm14, Reg Rt) {
|
||||||
|
const size_t datasize = b5 == 1 ? 64 : 32;
|
||||||
|
const u8 bit_pos = concatenate(b5, b40).ZeroExtend<u8>();
|
||||||
|
const s64 offset = concatenate(imm14, Imm<2>{0}).SignExtend<s64>();
|
||||||
|
|
||||||
|
const auto operand = X(datasize, Rt);
|
||||||
|
|
||||||
|
ir.SetCheckBit(ir.TestBit(operand, ir.Imm8(bit_pos)));
|
||||||
|
|
||||||
|
const u64 target = ir.PC() + offset;
|
||||||
|
const auto cond_1 = IR::Term::LinkBlock{ir.current_location->SetPC(target)};
|
||||||
|
const auto cond_0 = IR::Term::LinkBlock{ir.current_location->AdvancePC(4)};
|
||||||
|
ir.SetTerm(IR::Term::CheckBit{cond_1, cond_0});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Dynarmic::A64
|
22
externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/a64_exception_generating.cpp
vendored
Executable file
22
externals/dynarmic/src/dynarmic/frontend/A64/translate/impl/a64_exception_generating.cpp
vendored
Executable file
|
@ -0,0 +1,22 @@
|
||||||
|
/* This file is part of the dynarmic project.
|
||||||
|
* Copyright (c) 2018 MerryMage
|
||||||
|
* SPDX-License-Identifier: 0BSD
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dynarmic/frontend/A64/translate/impl/impl.h"
|
||||||
|
|
||||||
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
|
bool TranslatorVisitor::BRK(Imm<16> /*imm16*/) {
|
||||||
|
return RaiseException(Exception::Breakpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TranslatorVisitor::SVC(Imm<16> imm16) {
|
||||||
|
ir.PushRSB(ir.current_location->AdvancePC(4));
|
||||||
|
ir.SetPC(ir.Imm64(ir.current_location->PC() + 4));
|
||||||
|
ir.CallSupervisor(imm16.ZeroExtend());
|
||||||
|
ir.SetTerm(IR::Term::CheckHalt{IR::Term::PopRSBHint{}});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Dynarmic::A64
|
|
@ -7,10 +7,10 @@
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#include "dynarmic/frontend/A64/ir_emitter.h"
|
#include "dynarmic/frontend/A64/a64_ir_emitter.h"
|
||||||
#include "dynarmic/frontend/A64/location_descriptor.h"
|
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
||||||
#include "dynarmic/frontend/A64/translate/translate.h"
|
#include "dynarmic/frontend/A64/a64_types.h"
|
||||||
#include "dynarmic/frontend/A64/types.h"
|
#include "dynarmic/frontend/A64/translate/a64_translate.h"
|
||||||
#include "dynarmic/frontend/imm.h"
|
#include "dynarmic/frontend/imm.h"
|
||||||
|
|
||||||
namespace Dynarmic::A64 {
|
namespace Dynarmic::A64 {
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/memory_pool.h"
|
#include "dynarmic/common/memory_pool.h"
|
||||||
#include "dynarmic/frontend/A32/types.h"
|
#include "dynarmic/frontend/A32/a32_types.h"
|
||||||
#include "dynarmic/frontend/A64/types.h"
|
#include "dynarmic/frontend/A64/a64_types.h"
|
||||||
#include "dynarmic/ir/cond.h"
|
#include "dynarmic/ir/cond.h"
|
||||||
#include "dynarmic/ir/opcodes.h"
|
#include "dynarmic/ir/opcodes.h"
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/frontend/A32/types.h"
|
#include "dynarmic/frontend/A32/a32_types.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/opcodes.h"
|
#include "dynarmic/ir/opcodes.h"
|
||||||
#include "dynarmic/ir/opt/passes.h"
|
#include "dynarmic/ir/opt/passes.h"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dynarmic/frontend/A64/ir_emitter.h"
|
#include "dynarmic/frontend/A64/a64_ir_emitter.h"
|
||||||
#include "dynarmic/interface/A64/config.h"
|
#include "dynarmic/interface/A64/config.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/microinstruction.h"
|
#include "dynarmic/ir/microinstruction.h"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/frontend/A64/types.h"
|
#include "dynarmic/frontend/A64/a64_types.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/opcodes.h"
|
#include "dynarmic/ir/opcodes.h"
|
||||||
#include "dynarmic/ir/opt/passes.h"
|
#include "dynarmic/ir/opt/passes.h"
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
#include <boost/variant/get.hpp>
|
#include <boost/variant/get.hpp>
|
||||||
|
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/frontend/A64/location_descriptor.h"
|
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
||||||
#include "dynarmic/frontend/A64/translate/translate.h"
|
#include "dynarmic/frontend/A64/translate/a64_translate.h"
|
||||||
#include "dynarmic/interface/A64/config.h"
|
#include "dynarmic/interface/A64/config.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/opt/passes.h"
|
#include "dynarmic/ir/opt/passes.h"
|
||||||
|
|
6
externals/dynarmic/tests/A32/fuzz_arm.cpp
vendored
6
externals/dynarmic/tests/A32/fuzz_arm.cpp
vendored
|
@ -22,9 +22,9 @@
|
||||||
#include "dynarmic/common/llvm_disassemble.h"
|
#include "dynarmic/common/llvm_disassemble.h"
|
||||||
#include "dynarmic/common/scope_exit.h"
|
#include "dynarmic/common/scope_exit.h"
|
||||||
#include "dynarmic/frontend/A32/ITState.h"
|
#include "dynarmic/frontend/A32/ITState.h"
|
||||||
#include "dynarmic/frontend/A32/location_descriptor.h"
|
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||||
#include "dynarmic/frontend/A32/translate/translate.h"
|
#include "dynarmic/frontend/A32/a32_types.h"
|
||||||
#include "dynarmic/frontend/A32/types.h"
|
#include "dynarmic/frontend/A32/translate/a32_translate.h"
|
||||||
#include "dynarmic/interface/A32/a32.h"
|
#include "dynarmic/interface/A32/a32.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/location_descriptor.h"
|
#include "dynarmic/ir/location_descriptor.h"
|
||||||
|
|
4
externals/dynarmic/tests/A32/fuzz_thumb.cpp
vendored
4
externals/dynarmic/tests/A32/fuzz_thumb.cpp
vendored
|
@ -21,9 +21,9 @@
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/frontend/A32/FPSCR.h"
|
#include "dynarmic/frontend/A32/FPSCR.h"
|
||||||
#include "dynarmic/frontend/A32/PSR.h"
|
#include "dynarmic/frontend/A32/PSR.h"
|
||||||
|
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||||
#include "dynarmic/frontend/A32/disassembler/disassembler.h"
|
#include "dynarmic/frontend/A32/disassembler/disassembler.h"
|
||||||
#include "dynarmic/frontend/A32/location_descriptor.h"
|
#include "dynarmic/frontend/A32/translate/a32_translate.h"
|
||||||
#include "dynarmic/frontend/A32/translate/translate.h"
|
|
||||||
#include "dynarmic/interface/A32/a32.h"
|
#include "dynarmic/interface/A32/a32.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/opt/passes.h"
|
#include "dynarmic/ir/opt/passes.h"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <catch2/catch.hpp>
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
#include "./testenv.h"
|
#include "./testenv.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/a32.h"
|
||||||
|
|
||||||
using namespace Dynarmic;
|
using namespace Dynarmic;
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
#include "dynarmic/common/fp/fpsr.h"
|
#include "dynarmic/common/fp/fpsr.h"
|
||||||
#include "dynarmic/common/llvm_disassemble.h"
|
#include "dynarmic/common/llvm_disassemble.h"
|
||||||
#include "dynarmic/common/scope_exit.h"
|
#include "dynarmic/common/scope_exit.h"
|
||||||
|
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
||||||
|
#include "dynarmic/frontend/A64/a64_types.h"
|
||||||
#include "dynarmic/frontend/A64/decoder/a64.h"
|
#include "dynarmic/frontend/A64/decoder/a64.h"
|
||||||
#include "dynarmic/frontend/A64/location_descriptor.h"
|
#include "dynarmic/frontend/A64/translate/a64_translate.h"
|
||||||
#include "dynarmic/frontend/A64/translate/translate.h"
|
|
||||||
#include "dynarmic/frontend/A64/types.h"
|
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/opcodes.h"
|
#include "dynarmic/ir/opcodes.h"
|
||||||
#include "dynarmic/ir/opt/passes.h"
|
#include "dynarmic/ir/opt/passes.h"
|
||||||
|
|
2
externals/dynarmic/tests/decoder_tests.cpp
vendored
2
externals/dynarmic/tests/decoder_tests.cpp
vendored
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
#include "dynarmic/common/assert.h"
|
#include "dynarmic/common/assert.h"
|
||||||
#include "dynarmic/frontend/A32/decoder/asimd.h"
|
#include "dynarmic/frontend/A32/decoder/asimd.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
#include "dynarmic/interface/A32/config.h"
|
#include "dynarmic/interface/A32/config.h"
|
||||||
#include "dynarmic/ir/opcodes.h"
|
#include "dynarmic/ir/opcodes.h"
|
||||||
|
|
||||||
|
|
10
externals/dynarmic/tests/print_info.cpp
vendored
10
externals/dynarmic/tests/print_info.cpp
vendored
|
@ -18,16 +18,16 @@
|
||||||
#include "dynarmic/common/bit_util.h"
|
#include "dynarmic/common/bit_util.h"
|
||||||
#include "dynarmic/common/common_types.h"
|
#include "dynarmic/common/common_types.h"
|
||||||
#include "dynarmic/common/llvm_disassemble.h"
|
#include "dynarmic/common/llvm_disassemble.h"
|
||||||
|
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||||
#include "dynarmic/frontend/A32/decoder/arm.h"
|
#include "dynarmic/frontend/A32/decoder/arm.h"
|
||||||
#include "dynarmic/frontend/A32/decoder/asimd.h"
|
#include "dynarmic/frontend/A32/decoder/asimd.h"
|
||||||
#include "dynarmic/frontend/A32/decoder/vfp.h"
|
#include "dynarmic/frontend/A32/decoder/vfp.h"
|
||||||
#include "dynarmic/frontend/A32/location_descriptor.h"
|
#include "dynarmic/frontend/A32/translate/a32_translate.h"
|
||||||
#include "dynarmic/frontend/A32/translate/impl/translate.h"
|
#include "dynarmic/frontend/A32/translate/impl/a32_translate_impl.h"
|
||||||
#include "dynarmic/frontend/A32/translate/translate.h"
|
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
||||||
#include "dynarmic/frontend/A64/decoder/a64.h"
|
#include "dynarmic/frontend/A64/decoder/a64.h"
|
||||||
#include "dynarmic/frontend/A64/location_descriptor.h"
|
#include "dynarmic/frontend/A64/translate/a64_translate.h"
|
||||||
#include "dynarmic/frontend/A64/translate/impl/impl.h"
|
#include "dynarmic/frontend/A64/translate/impl/impl.h"
|
||||||
#include "dynarmic/frontend/A64/translate/translate.h"
|
|
||||||
#include "dynarmic/interface/A32/a32.h"
|
#include "dynarmic/interface/A32/a32.h"
|
||||||
#include "dynarmic/interface/A32/disassembler.h"
|
#include "dynarmic/interface/A32/disassembler.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
|
|
Loading…
Reference in a new issue