Merge branch 'dev'
This commit is contained in:
commit
6c1cbef6ac
12
.github/workflows/PyPI-publishing.yml
vendored
12
.github/workflows/PyPI-publishing.yml
vendored
@ -71,6 +71,18 @@ jobs:
|
||||
uses: microsoft/setup-msbuild@v1.0.3
|
||||
with:
|
||||
vs-version: '16.5'
|
||||
|
||||
- name: '🛠️ Win MSVC 32 dev cmd setup'
|
||||
if: contains(matrix.config.name, 'win32')
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: x86
|
||||
|
||||
- name: '🛠️ Win MSVC 64 dev cmd setup'
|
||||
if: contains(matrix.config.name, 'win_amd64')
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: x64
|
||||
|
||||
- name: '🛠️ Win build dependencies'
|
||||
if: contains(matrix.config.name, 'win')
|
||||
|
51
.github/workflows/build-uc2.yml
vendored
51
.github/workflows/build-uc2.yml
vendored
@ -31,7 +31,8 @@ jobs:
|
||||
arch: x64,
|
||||
python-arch: x64,
|
||||
python-ver: '3.8',
|
||||
name: 'windows-x64 MINGW64',
|
||||
name: 'windows-x64 MINGW64 shared',
|
||||
shared: 'yes',
|
||||
mingw: MINGW64,
|
||||
mingw-arch: x86_64,
|
||||
artifact: 'windows_mingw64.7z',
|
||||
@ -44,7 +45,36 @@ jobs:
|
||||
arch: x64,
|
||||
python-arch: x64,
|
||||
python-ver: '3.8',
|
||||
name: 'windows-x64 MINGW32',
|
||||
name: 'windows-x64 MINGW64 static',
|
||||
shared: 'no',
|
||||
mingw: MINGW64,
|
||||
mingw-arch: x86_64,
|
||||
artifact: 'windows_mingw64.7z',
|
||||
build_type: 'Debug',
|
||||
archiver: '7z a',
|
||||
generators: 'Ninja'
|
||||
}
|
||||
- {
|
||||
os: windows-2019,
|
||||
arch: x64,
|
||||
python-arch: x64,
|
||||
python-ver: '3.8',
|
||||
name: 'windows-x64 MINGW32 shared',
|
||||
shared: "yes",
|
||||
mingw: MINGW32,
|
||||
mingw-arch: i686,
|
||||
artifact: 'windows_mingw32.7z',
|
||||
build_type: 'Debug',
|
||||
archiver: '7z a',
|
||||
generators: 'Ninja'
|
||||
}
|
||||
- {
|
||||
os: windows-2019,
|
||||
arch: x64,
|
||||
python-arch: x64,
|
||||
python-ver: '3.8',
|
||||
name: 'windows-x64 MINGW32 static',
|
||||
shared: "no",
|
||||
mingw: MINGW32,
|
||||
mingw-arch: i686,
|
||||
artifact: 'windows_mingw32.7z',
|
||||
@ -124,6 +154,12 @@ jobs:
|
||||
- name: '🛠️ Win MSVC 64 setup'
|
||||
if: contains(matrix.config.name, 'MSVC 64')
|
||||
uses: microsoft/setup-msbuild@v1
|
||||
|
||||
- name: '🛠️ Win MSVC 64 dev cmd setup'
|
||||
if: contains(matrix.config.name, 'MSVC 64')
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
with:
|
||||
arch: x64
|
||||
|
||||
- name: '🚧 Win MSVC 64 build'
|
||||
if: contains(matrix.config.name, 'MSVC 64')
|
||||
@ -138,7 +174,8 @@ jobs:
|
||||
-B . \
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
|
||||
-G "${{ matrix.config.generators }}" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=instdir
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=instdir \
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.config.shared }}
|
||||
cmake --build . --config ${{ matrix.config.build_type }}
|
||||
cmake --install . --strip --config ${{ matrix.config.build_type }}
|
||||
ctest -VV -C ${{ matrix.config.build_type }}
|
||||
@ -164,7 +201,8 @@ jobs:
|
||||
-A "win32" \
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
|
||||
-G "${{ matrix.config.generators }}" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=instdir
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=instdir \
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.config.shared }}
|
||||
cmake --build . --config ${{ matrix.config.build_type }}
|
||||
cmake --install . --strip --config ${{ matrix.config.build_type }}
|
||||
ctest -VV -C ${{ matrix.config.build_type }}
|
||||
@ -191,7 +229,8 @@ jobs:
|
||||
-B . \
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
|
||||
-G "${{ matrix.config.generators }}" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=instdir
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=instdir \
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.config.shared }}
|
||||
cmake --build . --config ${{ matrix.config.build_type }}
|
||||
cmake --install . --strip
|
||||
ctest -VV -C ${{ matrix.config.build_type }}
|
||||
@ -277,7 +316,7 @@ jobs:
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} \
|
||||
-G "${{ matrix.config.generators }}" \
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=instdir \
|
||||
-DBUILD_SHARED_LIB= ${{ matrix.config.shared }}
|
||||
-DBUILD_SHARED_LIBS=${{ matrix.config.shared }}
|
||||
cmake --build . --config ${{ matrix.config.build_type }}
|
||||
cmake --install . --strip
|
||||
ctest -VV -C ${{ matrix.config.build_type }}
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -10,6 +10,7 @@
|
||||
*.dll
|
||||
*.class
|
||||
*.jar
|
||||
*.gem
|
||||
*~
|
||||
|
||||
qemu/*-softmmu/
|
||||
@ -52,7 +53,7 @@ bindings/python/unicorn.egg-info/
|
||||
bindings/python/unicorn/lib/
|
||||
bindings/python/unicorn/include/
|
||||
bindings/python/MANIFEST
|
||||
target/
|
||||
/target/
|
||||
Cargo.lock
|
||||
config.log
|
||||
|
||||
|
135
CMakeLists.txt
135
CMakeLists.txt
@ -40,11 +40,16 @@ set(UNICORN_VERSION_PATCH 0)
|
||||
|
||||
include(bundle_static.cmake)
|
||||
|
||||
# Even though we generate shared lib and static archive at the same time, we still support
|
||||
# using unicorn as a subdirectory so we have to respect BUILD_SHARED_LIBS.
|
||||
#
|
||||
# Also we would like users to link a native cmake target, instead of a custom target for better
|
||||
# compatability.
|
||||
option(BUILD_SHARED_LIBS "Build shared instead of static library" ${PROJECT_IS_TOP_LEVEL})
|
||||
option(UNICORN_FUZZ "Enable fuzzing" OFF)
|
||||
option(UNICORN_BUILD_TESTS "Build unicorn tests" ${PROJECT_IS_TOP_LEVEL})
|
||||
option(UNICORN_INSTALL "Enable unicorn installation" ${PROJECT_IS_TOP_LEVEL})
|
||||
set(UNICORN_ARCH "x86;arm;aarch64;riscv;mips;sparc;m68k;ppc;s390x" CACHE STRING "Enabled unicorn architectures")
|
||||
set(UNICORN_ARCH "x86;arm;aarch64;riscv;mips;sparc;m68k;ppc;s390x;tricore" CACHE STRING "Enabled unicorn architectures")
|
||||
option(UNICORN_TRACER "Trace unicorn execution" OFF)
|
||||
|
||||
foreach(ARCH_LOOP ${UNICORN_ARCH})
|
||||
@ -119,7 +124,7 @@ else()
|
||||
string(FIND "${UC_COMPILER_VERSION}" "i686" UC_RET)
|
||||
if(${UC_RET} GREATER_EQUAL "0")
|
||||
set(UNICORN_TARGET_ARCH "i386")
|
||||
set(UNICORN_CFLAGS -m32)
|
||||
set(UNICORN_CFLAGS -m32 -static-libgcc) # Workaround for github action bugs
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32")
|
||||
else()
|
||||
@ -209,6 +214,11 @@ else()
|
||||
set(UNICORN_TARGET_ARCH "s390")
|
||||
break()
|
||||
endif()
|
||||
string(FIND ${UC_COMPILER_MACRO} "__tricore__" UC_RET)
|
||||
if (${UC_RET} GREATER_EQUAL "0")
|
||||
set(UNICORN_TARGET_ARCH "tricore")
|
||||
break()
|
||||
endif()
|
||||
message(FATAL_ERROR "Unknown host compiler: ${CMAKE_C_COMPILER}.")
|
||||
endwhile(TRUE)
|
||||
endif()
|
||||
@ -241,6 +251,9 @@ else()
|
||||
if (UNICORN_HAS_S390X)
|
||||
set (EXTRA_CFLAGS "${EXTRA_CFLAGS}-DUNICORN_HAS_S390X ")
|
||||
endif()
|
||||
if (UNICORN_HAS_TRICORE)
|
||||
set (EXTRA_CFLAGS "${EXTRA_CFLAGS}-DUNICORN_HAS_TRICORE ")
|
||||
endif()
|
||||
|
||||
set(EXTRA_CFLAGS "${EXTRA_CFLAGS}-fPIC")
|
||||
if(ANDROID_ABI)
|
||||
@ -282,6 +295,9 @@ else()
|
||||
if(UNICORN_HAS_S390X)
|
||||
set(TARGET_LIST "${TARGET_LIST}s390x-softmmu, ")
|
||||
endif()
|
||||
if (UNICORN_HAS_TRICORE)
|
||||
set (TARGET_LIST "${TARGET_LIST}tricore-softmmu, ")
|
||||
endif()
|
||||
set(TARGET_LIST "${TARGET_LIST} ")
|
||||
|
||||
# GEN config-host.mak & target directories
|
||||
@ -373,6 +389,12 @@ else()
|
||||
OUTPUT_FILE ${CMAKE_BINARY_DIR}/s390x-softmmu/config-target.h
|
||||
)
|
||||
endif()
|
||||
if (UNICORN_HAS_TRICORE)
|
||||
execute_process(COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/qemu/scripts/create_config
|
||||
INPUT_FILE ${CMAKE_BINARY_DIR}/tricore-softmmu/config-target.mak
|
||||
OUTPUT_FILE ${CMAKE_BINARY_DIR}/tricore-softmmu/config-target.h
|
||||
)
|
||||
endif()
|
||||
add_compile_options(
|
||||
${UNICORN_CFLAGS}
|
||||
-I${CMAKE_CURRENT_SOURCE_DIR}/qemu/tcg/${UNICORN_TARGET_ARCH}
|
||||
@ -1034,6 +1056,36 @@ endif()
|
||||
endif()
|
||||
|
||||
|
||||
if (UNICORN_HAS_TRICORE)
|
||||
add_library(tricore-softmmu STATIC
|
||||
${UNICORN_ARCH_COMMON}
|
||||
|
||||
qemu/target/tricore/cpu.c
|
||||
qemu/target/tricore/fpu_helper.c
|
||||
qemu/target/tricore/helper.c
|
||||
qemu/target/tricore/op_helper.c
|
||||
qemu/target/tricore/translate.c
|
||||
qemu/target/tricore/unicorn.c
|
||||
)
|
||||
|
||||
if(MSVC)
|
||||
target_compile_options(tricore-softmmu PRIVATE
|
||||
-DNEED_CPU_H
|
||||
/FItricore.h
|
||||
/I${CMAKE_CURRENT_SOURCE_DIR}/msvc/tricore-softmmu
|
||||
/I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/tricore
|
||||
)
|
||||
else()
|
||||
target_compile_options(tricore-softmmu PRIVATE
|
||||
-DNEED_CPU_H
|
||||
-include tricore.h
|
||||
-I${CMAKE_BINARY_DIR}/tricore-softmmu
|
||||
-I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/tricore
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
set(UNICORN_SRCS
|
||||
uc.c
|
||||
|
||||
@ -1093,6 +1145,7 @@ if(MSVC)
|
||||
enable_language(ASM_MASM)
|
||||
endif()
|
||||
set(UNICORN_COMMON_SRCS ${UNICORN_COMMON_SRCS} qemu/util/setjmp-wrapper-win32.asm)
|
||||
set_property(SOURCE qemu/util/setjmp-wrapper-win32.asm PROPERTY LANGUAGE ASM_MASM)
|
||||
endif()
|
||||
else()
|
||||
set(UNICORN_COMMON_SRCS
|
||||
@ -1110,14 +1163,12 @@ if(NOT MSVC AND NOT ANDROID_ABI)
|
||||
target_link_libraries(unicorn-common PRIVATE pthread)
|
||||
endif()
|
||||
|
||||
add_library(unicorn ${UNICORN_SRCS})
|
||||
# For static archive
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set(UNICORN_LIB_NAME "unicorn")
|
||||
else()
|
||||
set(UNICORN_LIB_NAME "unicorn-static") # This static lib is useless and it's just an intermediate target
|
||||
add_library(unicorn_static STATIC ${UNICORN_SRCS})
|
||||
endif()
|
||||
|
||||
add_library(${UNICORN_LIB_NAME} ${UNICORN_SRCS})
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
if(ANDROID_ABI)
|
||||
file(APPEND ${CMAKE_BINARY_DIR}/adb.sh "adb push ./libunicorn.so /data/local/tmp/build/\n")
|
||||
@ -1194,6 +1245,13 @@ if (UNICORN_HAS_S390X)
|
||||
target_link_libraries(s390x-softmmu PRIVATE unicorn-common)
|
||||
set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_s390x)
|
||||
endif()
|
||||
if (UNICORN_HAS_TRICORE)
|
||||
set(UNICORN_COMPILE_OPTIONS ${UNICORN_COMPILE_OPTIONS} -DUNICORN_HAS_TRICORE)
|
||||
set(UNICORN_LINK_LIBRARIES ${UNICORN_LINK_LIBRARIES} tricore-softmmu)
|
||||
set(UNICORN_SAMPLE_FILE ${UNICORN_SAMPLE_FILE} sample_tricore)
|
||||
target_link_libraries(tricore-softmmu unicorn-common)
|
||||
set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_tricore)
|
||||
endif()
|
||||
|
||||
# Extra tests
|
||||
set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_mem)
|
||||
@ -1209,10 +1267,17 @@ target_compile_options(unicorn-common PRIVATE
|
||||
${UNICORN_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
target_compile_options(${UNICORN_LIB_NAME} PRIVATE
|
||||
target_compile_options(unicorn PRIVATE
|
||||
${UNICORN_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
# For static archive
|
||||
if (BUILD_SHARED_LIBS)
|
||||
target_compile_options(unicorn_static PRIVATE
|
||||
${UNICORN_COMPILE_OPTIONS}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(MINGW)
|
||||
set(UNICORN_LINK_LIBRARIES ${UNICORN_LINK_LIBRARIES} pthread)
|
||||
endif()
|
||||
@ -1223,29 +1288,46 @@ endif()
|
||||
|
||||
if(MSVC)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_compile_options(${UNICORN_LIB_NAME} PRIVATE
|
||||
target_compile_options(unicorn PRIVATE
|
||||
-DUNICORN_SHARED
|
||||
)
|
||||
|
||||
# For static archive
|
||||
target_link_libraries(unicorn_static PRIVATE
|
||||
${UNICORN_LINK_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${UNICORN_LIB_NAME} PRIVATE
|
||||
target_link_libraries(unicorn PRIVATE
|
||||
${UNICORN_LINK_LIBRARIES}
|
||||
)
|
||||
|
||||
set_target_properties(${UNICORN_LIB_NAME} PROPERTIES
|
||||
set_target_properties(unicorn PROPERTIES
|
||||
VERSION "${UNICORN_VERSION_MAJOR}.${UNICORN_VERSION_MINOR}"
|
||||
)
|
||||
else()
|
||||
target_link_libraries(${UNICORN_LIB_NAME} PRIVATE
|
||||
target_link_libraries(unicorn PRIVATE
|
||||
${UNICORN_LINK_LIBRARIES}
|
||||
m
|
||||
)
|
||||
|
||||
target_link_libraries(${UNICORN_LIB_NAME} PUBLIC
|
||||
target_link_libraries(unicorn PUBLIC
|
||||
m
|
||||
)
|
||||
|
||||
set_target_properties(${UNICORN_LIB_NAME} PROPERTIES
|
||||
# For static archive
|
||||
if (BUILD_SHARED_LIBS)
|
||||
target_link_libraries(unicorn_static PUBLIC
|
||||
m
|
||||
)
|
||||
|
||||
target_link_libraries(unicorn_static PRIVATE
|
||||
${UNICORN_LINK_LIBRARIES}
|
||||
m
|
||||
)
|
||||
endif()
|
||||
|
||||
set_target_properties(unicorn PROPERTIES
|
||||
VERSION ${UNICORN_VERSION_MAJOR}
|
||||
SOVERSION ${UNICORN_VERSION_MAJOR}
|
||||
)
|
||||
@ -1266,12 +1348,28 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
target_include_directories(${UNICORN_LIB_NAME} PUBLIC
|
||||
target_include_directories(unicorn PUBLIC
|
||||
include
|
||||
)
|
||||
|
||||
if (NOT BUILD_SHARED_LIBS)
|
||||
bundle_static_library(${UNICORN_LIB_NAME} unicorn) # Bundle our real unicorn static lib
|
||||
# For static archive
|
||||
if (BUILD_SHARED_LIBS)
|
||||
target_include_directories(unicorn_static PUBLIC
|
||||
include
|
||||
)
|
||||
endif()
|
||||
|
||||
# Black magic for generating static archives...
|
||||
if (BUILD_SHARED_LIBS)
|
||||
if (MSVC)
|
||||
# Avoid the import lib built by MVSC clash with our archive.
|
||||
set_target_properties(unicorn PROPERTIES ARCHIVE_OUTPUT_NAME "unicorn-import")
|
||||
endif()
|
||||
bundle_static_library(unicorn_static unicorn_archive unicorn)
|
||||
else()
|
||||
# Rename the "static" lib to avoid filename clash.
|
||||
set_target_properties(unicorn PROPERTIES OUTPUT_NAME "unicorn-static")
|
||||
bundle_static_library(unicorn unicorn_archive unicorn)
|
||||
endif()
|
||||
|
||||
if(UNICORN_FUZZ)
|
||||
@ -1327,9 +1425,8 @@ if(UNICORN_INSTALL AND NOT MSVC)
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
else()
|
||||
install(FILES $<TARGET_FILE:unicorn> DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
install(FILES $<TARGET_FILE:unicorn_archive> DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(FILES ${UNICORN_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/unicorn)
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/unicorn.pc "Name: unicorn\n\
|
||||
Description: Unicorn emulator engine\n\
|
||||
|
13
Cargo.toml
13
Cargo.toml
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "unicorn-engine"
|
||||
version = "2.0.0-rc7"
|
||||
version = "2.0.0"
|
||||
authors = ["Ziqiao Kong", "Lukas Seidel"]
|
||||
documentation = "https://github.com/unicorn-engine/unicorn/wiki"
|
||||
edition = "2021"
|
||||
@ -34,11 +34,10 @@ bitflags = "1.3"
|
||||
libc = "0.2"
|
||||
|
||||
[build-dependencies]
|
||||
cc = { optional = true, version = "1.0" }
|
||||
cmake = { optional = true, version = "0.1" }
|
||||
pkg-config = { optional = true, version = "0.3" }
|
||||
cc = { version = "1.0" }
|
||||
cmake = { version = "0.1" }
|
||||
pkg-config = { version = "0.3" }
|
||||
|
||||
[features]
|
||||
default = ["build_unicorn_cmake"]
|
||||
build_unicorn_cmake = ["cc", "cmake"]
|
||||
use_system_unicorn = ["pkg-config"]
|
||||
default = []
|
||||
dynamic_linkage = []
|
31
ChangeLog
31
ChangeLog
@ -1,5 +1,36 @@
|
||||
This file details the changelog of Unicorn Engine.
|
||||
|
||||
-------------------------------
|
||||
[Version 2.0.0]: July 7th, 2022
|
||||
|
||||
Features:
|
||||
|
||||
- TriCore Support (#1568)
|
||||
|
||||
Fixes/Improvements:
|
||||
|
||||
- Build both shared library and static archive as unicorn1 does.
|
||||
- Misc bindings improvements. #1569 #1600 #1609 #1613 #1616
|
||||
- Make sure setjmp-setjmp-wrapper-win32 participates in the build. #1604
|
||||
- Improve Rust bindings build logic.
|
||||
- Fix wrong python binding for UC_CTL_TB_REMOVE_CACHE
|
||||
- Flush translation blocks when the count hook is removed.
|
||||
- Fix unicorn crash when nested `uc_emu_start` deletes a hook
|
||||
- Fix CPU not fully resumed when writing PC.
|
||||
- Don't quit TB if `uc_mem_protect` doesn't change the protection of current TB memory.
|
||||
- Add type annotations for python bindings.
|
||||
- Add CPUID hook for python bindings. #1618
|
||||
- Don't repeat memory hooks if there is already an unhandled error. #1618
|
||||
- Support reads and writes over all Arm SIMD registers #1621
|
||||
- Fix wrong registers range in python bindings.
|
||||
- Fix uc_mem_protect on mmio regions
|
||||
- Fix a UAF caused by hook cache.
|
||||
- Fix the value collision between UC_MODE_ARMBE8 and UC_MODE_ARM926
|
||||
|
||||
Thanks:
|
||||
|
||||
@AfoHT @mrexodia @bet4it @lowlyw @ekilmer @ondryaso @QDucasse @PalumboN @uberwoozle
|
||||
|
||||
----------------------------------
|
||||
[Version 2.0.0 rc7]: April 17, 2022
|
||||
|
||||
|
@ -6,7 +6,7 @@ import sys, re, os
|
||||
|
||||
INCL_DIR = os.path.join('..', 'include', 'unicorn')
|
||||
|
||||
include = [ 'arm.h', 'arm64.h', 'mips.h', 'x86.h', 'sparc.h', 'm68k.h', 'ppc.h', 'riscv.h', 's390x.h', 'unicorn.h' ]
|
||||
include = [ 'arm.h', 'arm64.h', 'mips.h', 'x86.h', 'sparc.h', 'm68k.h', 'ppc.h', 'riscv.h', 's390x.h', 'tricore.h', 'unicorn.h' ]
|
||||
|
||||
template = {
|
||||
'python': {
|
||||
@ -24,6 +24,7 @@ template = {
|
||||
'ppc.h': 'ppc',
|
||||
'riscv.h': 'riscv',
|
||||
's390x.h' : 's390x',
|
||||
'tricore.h' : 'tricore',
|
||||
'unicorn.h': 'unicorn',
|
||||
'comment_open': '#',
|
||||
'comment_close': '',
|
||||
@ -43,6 +44,7 @@ template = {
|
||||
'ppc.h': 'ppc',
|
||||
'riscv.h': 'riscv',
|
||||
's390x.h' : 's390x',
|
||||
'tricore.h' : 'tricore',
|
||||
'unicorn.h': 'unicorn',
|
||||
'comment_open': '#',
|
||||
'comment_close': '',
|
||||
@ -62,6 +64,7 @@ template = {
|
||||
'ppc.h': 'ppc',
|
||||
'riscv.h': 'riscv',
|
||||
's390x.h' : 's390x',
|
||||
'tricore.h' : 'tricore',
|
||||
'unicorn.h': 'unicorn',
|
||||
'comment_open': '//',
|
||||
'comment_close': '',
|
||||
@ -81,6 +84,7 @@ template = {
|
||||
'ppc.h': 'Ppc',
|
||||
'riscv.h': 'Riscv',
|
||||
's390x.h' : 'S390x',
|
||||
'tricore.h' : 'TriCore',
|
||||
'unicorn.h': 'Unicorn',
|
||||
'comment_open': '//',
|
||||
'comment_close': '',
|
||||
@ -100,6 +104,7 @@ template = {
|
||||
'ppc.h': 'Ppc',
|
||||
'riscv.h': 'Riscv',
|
||||
's390x.h' : 'S390x',
|
||||
'tricore.h' : 'TriCore',
|
||||
'unicorn.h': 'Common',
|
||||
'comment_open': ' //',
|
||||
'comment_close': '',
|
||||
@ -119,6 +124,7 @@ template = {
|
||||
'ppc.h': 'Ppc',
|
||||
'riscv.h': 'Riscv',
|
||||
's390x.h' : 'S390x',
|
||||
'tricore.h' : 'TriCore',
|
||||
'unicorn.h': 'Unicorn',
|
||||
'comment_open': '//',
|
||||
'comment_close': '',
|
||||
|
@ -11,13 +11,13 @@ module Common =
|
||||
let UC_API_MINOR = 0
|
||||
|
||||
let UC_API_PATCH = 0
|
||||
let UC_API_EXTRA = 7
|
||||
let UC_API_EXTRA = 255
|
||||
let UC_VERSION_MAJOR = 2
|
||||
|
||||
let UC_VERSION_MINOR = 0
|
||||
|
||||
let UC_VERSION_PATCH = 0
|
||||
let UC_VERSION_EXTRA = 7
|
||||
let UC_VERSION_EXTRA = 255
|
||||
let UC_SECOND_SCALE = 1000000
|
||||
let UC_MILISECOND_SCALE = 1000
|
||||
let UC_ARCH_ARM = 1
|
||||
@ -29,7 +29,8 @@ module Common =
|
||||
let UC_ARCH_M68K = 7
|
||||
let UC_ARCH_RISCV = 8
|
||||
let UC_ARCH_S390X = 9
|
||||
let UC_ARCH_MAX = 10
|
||||
let UC_ARCH_TRICORE = 10
|
||||
let UC_ARCH_MAX = 11
|
||||
|
||||
let UC_MODE_LITTLE_ENDIAN = 0
|
||||
let UC_MODE_BIG_ENDIAN = 1073741824
|
||||
@ -38,7 +39,7 @@ module Common =
|
||||
let UC_MODE_THUMB = 16
|
||||
let UC_MODE_MCLASS = 32
|
||||
let UC_MODE_V8 = 64
|
||||
let UC_MODE_ARMBE8 = 128
|
||||
let UC_MODE_ARMBE8 = 1024
|
||||
let UC_MODE_ARM926 = 128
|
||||
let UC_MODE_ARM946 = 256
|
||||
let UC_MODE_ARM1176 = 512
|
||||
@ -139,6 +140,7 @@ module Common =
|
||||
let UC_CTL_CPU_MODEL = 7
|
||||
let UC_CTL_TB_REQUEST_CACHE = 8
|
||||
let UC_CTL_TB_REMOVE_CACHE = 9
|
||||
let UC_CTL_TB_FLUSH = 10
|
||||
|
||||
let UC_PROT_NONE = 0
|
||||
let UC_PROT_READ = 1
|
||||
|
132
bindings/dotnet/UnicornManaged/Const/TriCore.fs
Normal file
132
bindings/dotnet/UnicornManaged/Const/TriCore.fs
Normal file
@ -0,0 +1,132 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
namespace UnicornManaged.Const
|
||||
|
||||
open System
|
||||
|
||||
[<AutoOpen>]
|
||||
module TriCore =
|
||||
|
||||
// TRICORE CPU
|
||||
|
||||
let UC_CPU_TRICORE_TC1796 = 0
|
||||
let UC_CPU_TRICORE_TC1797 = 1
|
||||
let UC_CPU_TRICORE_TC27X = 2
|
||||
let UC_CPU_TRICORE_ENDING = 3
|
||||
|
||||
// TRICORE registers
|
||||
|
||||
let UC_TRICORE_REG_INVALID = 0
|
||||
let UC_TRICORE_REG_A0 = 1
|
||||
let UC_TRICORE_REG_A1 = 2
|
||||
let UC_TRICORE_REG_A2 = 3
|
||||
let UC_TRICORE_REG_A3 = 4
|
||||
let UC_TRICORE_REG_A4 = 5
|
||||
let UC_TRICORE_REG_A5 = 6
|
||||
let UC_TRICORE_REG_A6 = 7
|
||||
let UC_TRICORE_REG_A7 = 8
|
||||
let UC_TRICORE_REG_A8 = 9
|
||||
let UC_TRICORE_REG_A9 = 10
|
||||
let UC_TRICORE_REG_A10 = 11
|
||||
let UC_TRICORE_REG_A11 = 12
|
||||
let UC_TRICORE_REG_A12 = 13
|
||||
let UC_TRICORE_REG_A13 = 14
|
||||
let UC_TRICORE_REG_A14 = 15
|
||||
let UC_TRICORE_REG_A15 = 16
|
||||
let UC_TRICORE_REG_D0 = 17
|
||||
let UC_TRICORE_REG_D1 = 18
|
||||
let UC_TRICORE_REG_D2 = 19
|
||||
let UC_TRICORE_REG_D3 = 20
|
||||
let UC_TRICORE_REG_D4 = 21
|
||||
let UC_TRICORE_REG_D5 = 22
|
||||
let UC_TRICORE_REG_D6 = 23
|
||||
let UC_TRICORE_REG_D7 = 24
|
||||
let UC_TRICORE_REG_D8 = 25
|
||||
let UC_TRICORE_REG_D9 = 26
|
||||
let UC_TRICORE_REG_D10 = 27
|
||||
let UC_TRICORE_REG_D11 = 28
|
||||
let UC_TRICORE_REG_D12 = 29
|
||||
let UC_TRICORE_REG_D13 = 30
|
||||
let UC_TRICORE_REG_D14 = 31
|
||||
let UC_TRICORE_REG_D15 = 32
|
||||
let UC_TRICORE_REG_PCXI = 33
|
||||
let UC_TRICORE_REG_PSW = 34
|
||||
let UC_TRICORE_REG_PSW_USB_C = 35
|
||||
let UC_TRICORE_REG_PSW_USB_V = 36
|
||||
let UC_TRICORE_REG_PSW_USB_SV = 37
|
||||
let UC_TRICORE_REG_PSW_USB_AV = 38
|
||||
let UC_TRICORE_REG_PSW_USB_SAV = 39
|
||||
let UC_TRICORE_REG_PC = 40
|
||||
let UC_TRICORE_REG_SYSCON = 41
|
||||
let UC_TRICORE_REG_CPU_ID = 42
|
||||
let UC_TRICORE_REG_BIV = 43
|
||||
let UC_TRICORE_REG_BTV = 44
|
||||
let UC_TRICORE_REG_ISP = 45
|
||||
let UC_TRICORE_REG_ICR = 46
|
||||
let UC_TRICORE_REG_FCX = 47
|
||||
let UC_TRICORE_REG_LCX = 48
|
||||
let UC_TRICORE_REG_COMPAT = 49
|
||||
let UC_TRICORE_REG_DPR0_U = 50
|
||||
let UC_TRICORE_REG_DPR1_U = 51
|
||||
let UC_TRICORE_REG_DPR2_U = 52
|
||||
let UC_TRICORE_REG_DPR3_U = 53
|
||||
let UC_TRICORE_REG_DPR0_L = 54
|
||||
let UC_TRICORE_REG_DPR1_L = 55
|
||||
let UC_TRICORE_REG_DPR2_L = 56
|
||||
let UC_TRICORE_REG_DPR3_L = 57
|
||||
let UC_TRICORE_REG_CPR0_U = 58
|
||||
let UC_TRICORE_REG_CPR1_U = 59
|
||||
let UC_TRICORE_REG_CPR2_U = 60
|
||||
let UC_TRICORE_REG_CPR3_U = 61
|
||||
let UC_TRICORE_REG_CPR0_L = 62
|
||||
let UC_TRICORE_REG_CPR1_L = 63
|
||||
let UC_TRICORE_REG_CPR2_L = 64
|
||||
let UC_TRICORE_REG_CPR3_L = 65
|
||||
let UC_TRICORE_REG_DPM0 = 66
|
||||
let UC_TRICORE_REG_DPM1 = 67
|
||||
let UC_TRICORE_REG_DPM2 = 68
|
||||
let UC_TRICORE_REG_DPM3 = 69
|
||||
let UC_TRICORE_REG_CPM0 = 70
|
||||
let UC_TRICORE_REG_CPM1 = 71
|
||||
let UC_TRICORE_REG_CPM2 = 72
|
||||
let UC_TRICORE_REG_CPM3 = 73
|
||||
let UC_TRICORE_REG_MMU_CON = 74
|
||||
let UC_TRICORE_REG_MMU_ASI = 75
|
||||
let UC_TRICORE_REG_MMU_TVA = 76
|
||||
let UC_TRICORE_REG_MMU_TPA = 77
|
||||
let UC_TRICORE_REG_MMU_TPX = 78
|
||||
let UC_TRICORE_REG_MMU_TFA = 79
|
||||
let UC_TRICORE_REG_BMACON = 80
|
||||
let UC_TRICORE_REG_SMACON = 81
|
||||
let UC_TRICORE_REG_DIEAR = 82
|
||||
let UC_TRICORE_REG_DIETR = 83
|
||||
let UC_TRICORE_REG_CCDIER = 84
|
||||
let UC_TRICORE_REG_MIECON = 85
|
||||
let UC_TRICORE_REG_PIEAR = 86
|
||||
let UC_TRICORE_REG_PIETR = 87
|
||||
let UC_TRICORE_REG_CCPIER = 88
|
||||
let UC_TRICORE_REG_DBGSR = 89
|
||||
let UC_TRICORE_REG_EXEVT = 90
|
||||
let UC_TRICORE_REG_CREVT = 91
|
||||
let UC_TRICORE_REG_SWEVT = 92
|
||||
let UC_TRICORE_REG_TR0EVT = 93
|
||||
let UC_TRICORE_REG_TR1EVT = 94
|
||||
let UC_TRICORE_REG_DMS = 95
|
||||
let UC_TRICORE_REG_DCX = 96
|
||||
let UC_TRICORE_REG_DBGTCR = 97
|
||||
let UC_TRICORE_REG_CCTRL = 98
|
||||
let UC_TRICORE_REG_CCNT = 99
|
||||
let UC_TRICORE_REG_ICNT = 100
|
||||
let UC_TRICORE_REG_M1CNT = 101
|
||||
let UC_TRICORE_REG_M2CNT = 102
|
||||
let UC_TRICORE_REG_M3CNT = 103
|
||||
let UC_TRICORE_REG_ENDING = 104
|
||||
let UC_TRICORE_REG_GA0 = 1
|
||||
let UC_TRICORE_REG_GA1 = 2
|
||||
let UC_TRICORE_REG_GA8 = 9
|
||||
let UC_TRICORE_REG_GA9 = 10
|
||||
let UC_TRICORE_REG_SP = 11
|
||||
let UC_TRICORE_REG_LR = 12
|
||||
let UC_TRICORE_REG_IA = 16
|
||||
let UC_TRICORE_REG_ID = 32
|
||||
|
127
bindings/go/unicorn/tricore_const.go
Normal file
127
bindings/go/unicorn/tricore_const.go
Normal file
@ -0,0 +1,127 @@
|
||||
package unicorn
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [tricore_const.go]
|
||||
const (
|
||||
|
||||
// TRICORE CPU
|
||||
|
||||
CPU_TRICORE_TC1796 = 0
|
||||
CPU_TRICORE_TC1797 = 1
|
||||
CPU_TRICORE_TC27X = 2
|
||||
CPU_TRICORE_ENDING = 3
|
||||
|
||||
// TRICORE registers
|
||||
|
||||
TRICORE_REG_INVALID = 0
|
||||
TRICORE_REG_A0 = 1
|
||||
TRICORE_REG_A1 = 2
|
||||
TRICORE_REG_A2 = 3
|
||||
TRICORE_REG_A3 = 4
|
||||
TRICORE_REG_A4 = 5
|
||||
TRICORE_REG_A5 = 6
|
||||
TRICORE_REG_A6 = 7
|
||||
TRICORE_REG_A7 = 8
|
||||
TRICORE_REG_A8 = 9
|
||||
TRICORE_REG_A9 = 10
|
||||
TRICORE_REG_A10 = 11
|
||||
TRICORE_REG_A11 = 12
|
||||
TRICORE_REG_A12 = 13
|
||||
TRICORE_REG_A13 = 14
|
||||
TRICORE_REG_A14 = 15
|
||||
TRICORE_REG_A15 = 16
|
||||
TRICORE_REG_D0 = 17
|
||||
TRICORE_REG_D1 = 18
|
||||
TRICORE_REG_D2 = 19
|
||||
TRICORE_REG_D3 = 20
|
||||
TRICORE_REG_D4 = 21
|
||||
TRICORE_REG_D5 = 22
|
||||
TRICORE_REG_D6 = 23
|
||||
TRICORE_REG_D7 = 24
|
||||
TRICORE_REG_D8 = 25
|
||||
TRICORE_REG_D9 = 26
|
||||
TRICORE_REG_D10 = 27
|
||||
TRICORE_REG_D11 = 28
|
||||
TRICORE_REG_D12 = 29
|
||||
TRICORE_REG_D13 = 30
|
||||
TRICORE_REG_D14 = 31
|
||||
TRICORE_REG_D15 = 32
|
||||
TRICORE_REG_PCXI = 33
|
||||
TRICORE_REG_PSW = 34
|
||||
TRICORE_REG_PSW_USB_C = 35
|
||||
TRICORE_REG_PSW_USB_V = 36
|
||||
TRICORE_REG_PSW_USB_SV = 37
|
||||
TRICORE_REG_PSW_USB_AV = 38
|
||||
TRICORE_REG_PSW_USB_SAV = 39
|
||||
TRICORE_REG_PC = 40
|
||||
TRICORE_REG_SYSCON = 41
|
||||
TRICORE_REG_CPU_ID = 42
|
||||
TRICORE_REG_BIV = 43
|
||||
TRICORE_REG_BTV = 44
|
||||
TRICORE_REG_ISP = 45
|
||||
TRICORE_REG_ICR = 46
|
||||
TRICORE_REG_FCX = 47
|
||||
TRICORE_REG_LCX = 48
|
||||
TRICORE_REG_COMPAT = 49
|
||||
TRICORE_REG_DPR0_U = 50
|
||||
TRICORE_REG_DPR1_U = 51
|
||||
TRICORE_REG_DPR2_U = 52
|
||||
TRICORE_REG_DPR3_U = 53
|
||||
TRICORE_REG_DPR0_L = 54
|
||||
TRICORE_REG_DPR1_L = 55
|
||||
TRICORE_REG_DPR2_L = 56
|
||||
TRICORE_REG_DPR3_L = 57
|
||||
TRICORE_REG_CPR0_U = 58
|
||||
TRICORE_REG_CPR1_U = 59
|
||||
TRICORE_REG_CPR2_U = 60
|
||||
TRICORE_REG_CPR3_U = 61
|
||||
TRICORE_REG_CPR0_L = 62
|
||||
TRICORE_REG_CPR1_L = 63
|
||||
TRICORE_REG_CPR2_L = 64
|
||||
TRICORE_REG_CPR3_L = 65
|
||||
TRICORE_REG_DPM0 = 66
|
||||
TRICORE_REG_DPM1 = 67
|
||||
TRICORE_REG_DPM2 = 68
|
||||
TRICORE_REG_DPM3 = 69
|
||||
TRICORE_REG_CPM0 = 70
|
||||
TRICORE_REG_CPM1 = 71
|
||||
TRICORE_REG_CPM2 = 72
|
||||
TRICORE_REG_CPM3 = 73
|
||||
TRICORE_REG_MMU_CON = 74
|
||||
TRICORE_REG_MMU_ASI = 75
|
||||
TRICORE_REG_MMU_TVA = 76
|
||||
TRICORE_REG_MMU_TPA = 77
|
||||
TRICORE_REG_MMU_TPX = 78
|
||||
TRICORE_REG_MMU_TFA = 79
|
||||
TRICORE_REG_BMACON = 80
|
||||
TRICORE_REG_SMACON = 81
|
||||
TRICORE_REG_DIEAR = 82
|
||||
TRICORE_REG_DIETR = 83
|
||||
TRICORE_REG_CCDIER = 84
|
||||
TRICORE_REG_MIECON = 85
|
||||
TRICORE_REG_PIEAR = 86
|
||||
TRICORE_REG_PIETR = 87
|
||||
TRICORE_REG_CCPIER = 88
|
||||
TRICORE_REG_DBGSR = 89
|
||||
TRICORE_REG_EXEVT = 90
|
||||
TRICORE_REG_CREVT = 91
|
||||
TRICORE_REG_SWEVT = 92
|
||||
TRICORE_REG_TR0EVT = 93
|
||||
TRICORE_REG_TR1EVT = 94
|
||||
TRICORE_REG_DMS = 95
|
||||
TRICORE_REG_DCX = 96
|
||||
TRICORE_REG_DBGTCR = 97
|
||||
TRICORE_REG_CCTRL = 98
|
||||
TRICORE_REG_CCNT = 99
|
||||
TRICORE_REG_ICNT = 100
|
||||
TRICORE_REG_M1CNT = 101
|
||||
TRICORE_REG_M2CNT = 102
|
||||
TRICORE_REG_M3CNT = 103
|
||||
TRICORE_REG_ENDING = 104
|
||||
TRICORE_REG_GA0 = 1
|
||||
TRICORE_REG_GA1 = 2
|
||||
TRICORE_REG_GA8 = 9
|
||||
TRICORE_REG_GA9 = 10
|
||||
TRICORE_REG_SP = 11
|
||||
TRICORE_REG_LR = 12
|
||||
TRICORE_REG_IA = 16
|
||||
TRICORE_REG_ID = 32
|
||||
)
|
@ -6,13 +6,13 @@ const (
|
||||
API_MINOR = 0
|
||||
|
||||
API_PATCH = 0
|
||||
API_EXTRA = 7
|
||||
API_EXTRA = 255
|
||||
VERSION_MAJOR = 2
|
||||
|
||||
VERSION_MINOR = 0
|
||||
|
||||
VERSION_PATCH = 0
|
||||
VERSION_EXTRA = 7
|
||||
VERSION_EXTRA = 255
|
||||
SECOND_SCALE = 1000000
|
||||
MILISECOND_SCALE = 1000
|
||||
ARCH_ARM = 1
|
||||
@ -24,7 +24,8 @@ const (
|
||||
ARCH_M68K = 7
|
||||
ARCH_RISCV = 8
|
||||
ARCH_S390X = 9
|
||||
ARCH_MAX = 10
|
||||
ARCH_TRICORE = 10
|
||||
ARCH_MAX = 11
|
||||
|
||||
MODE_LITTLE_ENDIAN = 0
|
||||
MODE_BIG_ENDIAN = 1073741824
|
||||
@ -33,7 +34,7 @@ const (
|
||||
MODE_THUMB = 16
|
||||
MODE_MCLASS = 32
|
||||
MODE_V8 = 64
|
||||
MODE_ARMBE8 = 128
|
||||
MODE_ARMBE8 = 1024
|
||||
MODE_ARM926 = 128
|
||||
MODE_ARM946 = 256
|
||||
MODE_ARM1176 = 512
|
||||
@ -134,6 +135,7 @@ const (
|
||||
CTL_CPU_MODEL = 7
|
||||
CTL_TB_REQUEST_CACHE = 8
|
||||
CTL_TB_REMOVE_CACHE = 9
|
||||
CTL_TB_FLUSH = 10
|
||||
|
||||
PROT_NONE = 0
|
||||
PROT_READ = 1
|
||||
|
130
bindings/java/unicorn/TriCoreConst.java
Normal file
130
bindings/java/unicorn/TriCoreConst.java
Normal file
@ -0,0 +1,130 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
package unicorn;
|
||||
|
||||
public interface TriCoreConst {
|
||||
|
||||
// TRICORE CPU
|
||||
|
||||
public static final int UC_CPU_TRICORE_TC1796 = 0;
|
||||
public static final int UC_CPU_TRICORE_TC1797 = 1;
|
||||
public static final int UC_CPU_TRICORE_TC27X = 2;
|
||||
public static final int UC_CPU_TRICORE_ENDING = 3;
|
||||
|
||||
// TRICORE registers
|
||||
|
||||
public static final int UC_TRICORE_REG_INVALID = 0;
|
||||
public static final int UC_TRICORE_REG_A0 = 1;
|
||||
public static final int UC_TRICORE_REG_A1 = 2;
|
||||
public static final int UC_TRICORE_REG_A2 = 3;
|
||||
public static final int UC_TRICORE_REG_A3 = 4;
|
||||
public static final int UC_TRICORE_REG_A4 = 5;
|
||||
public static final int UC_TRICORE_REG_A5 = 6;
|
||||
public static final int UC_TRICORE_REG_A6 = 7;
|
||||
public static final int UC_TRICORE_REG_A7 = 8;
|
||||
public static final int UC_TRICORE_REG_A8 = 9;
|
||||
public static final int UC_TRICORE_REG_A9 = 10;
|
||||
public static final int UC_TRICORE_REG_A10 = 11;
|
||||
public static final int UC_TRICORE_REG_A11 = 12;
|
||||
public static final int UC_TRICORE_REG_A12 = 13;
|
||||
public static final int UC_TRICORE_REG_A13 = 14;
|
||||
public static final int UC_TRICORE_REG_A14 = 15;
|
||||
public static final int UC_TRICORE_REG_A15 = 16;
|
||||
public static final int UC_TRICORE_REG_D0 = 17;
|
||||
public static final int UC_TRICORE_REG_D1 = 18;
|
||||
public static final int UC_TRICORE_REG_D2 = 19;
|
||||
public static final int UC_TRICORE_REG_D3 = 20;
|
||||
public static final int UC_TRICORE_REG_D4 = 21;
|
||||
public static final int UC_TRICORE_REG_D5 = 22;
|
||||
public static final int UC_TRICORE_REG_D6 = 23;
|
||||
public static final int UC_TRICORE_REG_D7 = 24;
|
||||
public static final int UC_TRICORE_REG_D8 = 25;
|
||||
public static final int UC_TRICORE_REG_D9 = 26;
|
||||
public static final int UC_TRICORE_REG_D10 = 27;
|
||||
public static final int UC_TRICORE_REG_D11 = 28;
|
||||
public static final int UC_TRICORE_REG_D12 = 29;
|
||||
public static final int UC_TRICORE_REG_D13 = 30;
|
||||
public static final int UC_TRICORE_REG_D14 = 31;
|
||||
public static final int UC_TRICORE_REG_D15 = 32;
|
||||
public static final int UC_TRICORE_REG_PCXI = 33;
|
||||
public static final int UC_TRICORE_REG_PSW = 34;
|
||||
public static final int UC_TRICORE_REG_PSW_USB_C = 35;
|
||||
public static final int UC_TRICORE_REG_PSW_USB_V = 36;
|
||||
public static final int UC_TRICORE_REG_PSW_USB_SV = 37;
|
||||
public static final int UC_TRICORE_REG_PSW_USB_AV = 38;
|
||||
public static final int UC_TRICORE_REG_PSW_USB_SAV = 39;
|
||||
public static final int UC_TRICORE_REG_PC = 40;
|
||||
public static final int UC_TRICORE_REG_SYSCON = 41;
|
||||
public static final int UC_TRICORE_REG_CPU_ID = 42;
|
||||
public static final int UC_TRICORE_REG_BIV = 43;
|
||||
public static final int UC_TRICORE_REG_BTV = 44;
|
||||
public static final int UC_TRICORE_REG_ISP = 45;
|
||||
public static final int UC_TRICORE_REG_ICR = 46;
|
||||
public static final int UC_TRICORE_REG_FCX = 47;
|
||||
public static final int UC_TRICORE_REG_LCX = 48;
|
||||
public static final int UC_TRICORE_REG_COMPAT = 49;
|
||||
public static final int UC_TRICORE_REG_DPR0_U = 50;
|
||||
public static final int UC_TRICORE_REG_DPR1_U = 51;
|
||||
public static final int UC_TRICORE_REG_DPR2_U = 52;
|
||||
public static final int UC_TRICORE_REG_DPR3_U = 53;
|
||||
public static final int UC_TRICORE_REG_DPR0_L = 54;
|
||||
public static final int UC_TRICORE_REG_DPR1_L = 55;
|
||||
public static final int UC_TRICORE_REG_DPR2_L = 56;
|
||||
public static final int UC_TRICORE_REG_DPR3_L = 57;
|
||||
public static final int UC_TRICORE_REG_CPR0_U = 58;
|
||||
public static final int UC_TRICORE_REG_CPR1_U = 59;
|
||||
public static final int UC_TRICORE_REG_CPR2_U = 60;
|
||||
public static final int UC_TRICORE_REG_CPR3_U = 61;
|
||||
public static final int UC_TRICORE_REG_CPR0_L = 62;
|
||||
public static final int UC_TRICORE_REG_CPR1_L = 63;
|
||||
public static final int UC_TRICORE_REG_CPR2_L = 64;
|
||||
public static final int UC_TRICORE_REG_CPR3_L = 65;
|
||||
public static final int UC_TRICORE_REG_DPM0 = 66;
|
||||
public static final int UC_TRICORE_REG_DPM1 = 67;
|
||||
public static final int UC_TRICORE_REG_DPM2 = 68;
|
||||
public static final int UC_TRICORE_REG_DPM3 = 69;
|
||||
public static final int UC_TRICORE_REG_CPM0 = 70;
|
||||
public static final int UC_TRICORE_REG_CPM1 = 71;
|
||||
public static final int UC_TRICORE_REG_CPM2 = 72;
|
||||
public static final int UC_TRICORE_REG_CPM3 = 73;
|
||||
public static final int UC_TRICORE_REG_MMU_CON = 74;
|
||||
public static final int UC_TRICORE_REG_MMU_ASI = 75;
|
||||
public static final int UC_TRICORE_REG_MMU_TVA = 76;
|
||||
public static final int UC_TRICORE_REG_MMU_TPA = 77;
|
||||
public static final int UC_TRICORE_REG_MMU_TPX = 78;
|
||||
public static final int UC_TRICORE_REG_MMU_TFA = 79;
|
||||
public static final int UC_TRICORE_REG_BMACON = 80;
|
||||
public static final int UC_TRICORE_REG_SMACON = 81;
|
||||
public static final int UC_TRICORE_REG_DIEAR = 82;
|
||||
public static final int UC_TRICORE_REG_DIETR = 83;
|
||||
public static final int UC_TRICORE_REG_CCDIER = 84;
|
||||
public static final int UC_TRICORE_REG_MIECON = 85;
|
||||
public static final int UC_TRICORE_REG_PIEAR = 86;
|
||||
public static final int UC_TRICORE_REG_PIETR = 87;
|
||||
public static final int UC_TRICORE_REG_CCPIER = 88;
|
||||
public static final int UC_TRICORE_REG_DBGSR = 89;
|
||||
public static final int UC_TRICORE_REG_EXEVT = 90;
|
||||
public static final int UC_TRICORE_REG_CREVT = 91;
|
||||
public static final int UC_TRICORE_REG_SWEVT = 92;
|
||||
public static final int UC_TRICORE_REG_TR0EVT = 93;
|
||||
public static final int UC_TRICORE_REG_TR1EVT = 94;
|
||||
public static final int UC_TRICORE_REG_DMS = 95;
|
||||
public static final int UC_TRICORE_REG_DCX = 96;
|
||||
public static final int UC_TRICORE_REG_DBGTCR = 97;
|
||||
public static final int UC_TRICORE_REG_CCTRL = 98;
|
||||
public static final int UC_TRICORE_REG_CCNT = 99;
|
||||
public static final int UC_TRICORE_REG_ICNT = 100;
|
||||
public static final int UC_TRICORE_REG_M1CNT = 101;
|
||||
public static final int UC_TRICORE_REG_M2CNT = 102;
|
||||
public static final int UC_TRICORE_REG_M3CNT = 103;
|
||||
public static final int UC_TRICORE_REG_ENDING = 104;
|
||||
public static final int UC_TRICORE_REG_GA0 = 1;
|
||||
public static final int UC_TRICORE_REG_GA1 = 2;
|
||||
public static final int UC_TRICORE_REG_GA8 = 9;
|
||||
public static final int UC_TRICORE_REG_GA9 = 10;
|
||||
public static final int UC_TRICORE_REG_SP = 11;
|
||||
public static final int UC_TRICORE_REG_LR = 12;
|
||||
public static final int UC_TRICORE_REG_IA = 16;
|
||||
public static final int UC_TRICORE_REG_ID = 32;
|
||||
|
||||
}
|
@ -821,5 +821,11 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
|
||||
*/
|
||||
public native void context_restore(long context);
|
||||
|
||||
/**
|
||||
* Set the emulated cpu model.
|
||||
*
|
||||
* @param cpu_model CPU model type (see UC_CPU_*).
|
||||
*/
|
||||
public native void ctl_set_cpu_model(int cpu_model);
|
||||
}
|
||||
|
||||
|
@ -8,13 +8,13 @@ public interface UnicornConst {
|
||||
public static final int UC_API_MINOR = 0;
|
||||
|
||||
public static final int UC_API_PATCH = 0;
|
||||
public static final int UC_API_EXTRA = 7;
|
||||
public static final int UC_API_EXTRA = 255;
|
||||
public static final int UC_VERSION_MAJOR = 2;
|
||||
|
||||
public static final int UC_VERSION_MINOR = 0;
|
||||
|
||||
public static final int UC_VERSION_PATCH = 0;
|
||||
public static final int UC_VERSION_EXTRA = 7;
|
||||
public static final int UC_VERSION_EXTRA = 255;
|
||||
public static final int UC_SECOND_SCALE = 1000000;
|
||||
public static final int UC_MILISECOND_SCALE = 1000;
|
||||
public static final int UC_ARCH_ARM = 1;
|
||||
@ -26,7 +26,8 @@ public interface UnicornConst {
|
||||
public static final int UC_ARCH_M68K = 7;
|
||||
public static final int UC_ARCH_RISCV = 8;
|
||||
public static final int UC_ARCH_S390X = 9;
|
||||
public static final int UC_ARCH_MAX = 10;
|
||||
public static final int UC_ARCH_TRICORE = 10;
|
||||
public static final int UC_ARCH_MAX = 11;
|
||||
|
||||
public static final int UC_MODE_LITTLE_ENDIAN = 0;
|
||||
public static final int UC_MODE_BIG_ENDIAN = 1073741824;
|
||||
@ -35,7 +36,7 @@ public interface UnicornConst {
|
||||
public static final int UC_MODE_THUMB = 16;
|
||||
public static final int UC_MODE_MCLASS = 32;
|
||||
public static final int UC_MODE_V8 = 64;
|
||||
public static final int UC_MODE_ARMBE8 = 128;
|
||||
public static final int UC_MODE_ARMBE8 = 1024;
|
||||
public static final int UC_MODE_ARM926 = 128;
|
||||
public static final int UC_MODE_ARM946 = 256;
|
||||
public static final int UC_MODE_ARM1176 = 512;
|
||||
@ -136,6 +137,7 @@ public interface UnicornConst {
|
||||
public static final int UC_CTL_CPU_MODEL = 7;
|
||||
public static final int UC_CTL_TB_REQUEST_CACHE = 8;
|
||||
public static final int UC_CTL_TB_REMOVE_CACHE = 9;
|
||||
public static final int UC_CTL_TB_FLUSH = 10;
|
||||
|
||||
public static final int UC_PROT_NONE = 0;
|
||||
public static final int UC_PROT_READ = 1;
|
||||
|
@ -779,3 +779,17 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_context_1restore
|
||||
throwException(env, err);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: unicorn_Unicorn
|
||||
* Method: ctl_set_cpu_model
|
||||
* Signature: (I)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_unicorn_Unicorn_ctl_1set_1cpu_1model
|
||||
(JNIEnv *env, jobject self, jint cpu_model) {
|
||||
uc_engine *eng = getEngine(env, self);
|
||||
uc_err err = uc_ctl_set_cpu_model(eng, cpu_model);
|
||||
if (err != UC_ERR_OK) {
|
||||
throwException(env, err);
|
||||
}
|
||||
}
|
||||
|
132
bindings/pascal/unicorn/TriCoreConst.pas
Normal file
132
bindings/pascal/unicorn/TriCoreConst.pas
Normal file
@ -0,0 +1,132 @@
|
||||
// For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT
|
||||
|
||||
unit TriCoreConst;
|
||||
|
||||
interface
|
||||
|
||||
const
|
||||
// TRICORE CPU
|
||||
|
||||
UC_CPU_TRICORE_TC1796 = 0;
|
||||
UC_CPU_TRICORE_TC1797 = 1;
|
||||
UC_CPU_TRICORE_TC27X = 2;
|
||||
UC_CPU_TRICORE_ENDING = 3;
|
||||
|
||||
// TRICORE registers
|
||||
|
||||
UC_TRICORE_REG_INVALID = 0;
|
||||
UC_TRICORE_REG_A0 = 1;
|
||||
UC_TRICORE_REG_A1 = 2;
|
||||
UC_TRICORE_REG_A2 = 3;
|
||||
UC_TRICORE_REG_A3 = 4;
|
||||
UC_TRICORE_REG_A4 = 5;
|
||||
UC_TRICORE_REG_A5 = 6;
|
||||
UC_TRICORE_REG_A6 = 7;
|
||||
UC_TRICORE_REG_A7 = 8;
|
||||
UC_TRICORE_REG_A8 = 9;
|
||||
UC_TRICORE_REG_A9 = 10;
|
||||
UC_TRICORE_REG_A10 = 11;
|
||||
UC_TRICORE_REG_A11 = 12;
|
||||
UC_TRICORE_REG_A12 = 13;
|
||||
UC_TRICORE_REG_A13 = 14;
|
||||
UC_TRICORE_REG_A14 = 15;
|
||||
UC_TRICORE_REG_A15 = 16;
|
||||
UC_TRICORE_REG_D0 = 17;
|
||||
UC_TRICORE_REG_D1 = 18;
|
||||
UC_TRICORE_REG_D2 = 19;
|
||||
UC_TRICORE_REG_D3 = 20;
|
||||
UC_TRICORE_REG_D4 = 21;
|
||||
UC_TRICORE_REG_D5 = 22;
|
||||
UC_TRICORE_REG_D6 = 23;
|
||||
UC_TRICORE_REG_D7 = 24;
|
||||
UC_TRICORE_REG_D8 = 25;
|
||||
UC_TRICORE_REG_D9 = 26;
|
||||
UC_TRICORE_REG_D10 = 27;
|
||||
UC_TRICORE_REG_D11 = 28;
|
||||
UC_TRICORE_REG_D12 = 29;
|
||||
UC_TRICORE_REG_D13 = 30;
|
||||
UC_TRICORE_REG_D14 = 31;
|
||||
UC_TRICORE_REG_D15 = 32;
|
||||
UC_TRICORE_REG_PCXI = 33;
|
||||
UC_TRICORE_REG_PSW = 34;
|
||||
UC_TRICORE_REG_PSW_USB_C = 35;
|
||||
UC_TRICORE_REG_PSW_USB_V = 36;
|
||||
UC_TRICORE_REG_PSW_USB_SV = 37;
|
||||
UC_TRICORE_REG_PSW_USB_AV = 38;
|
||||
UC_TRICORE_REG_PSW_USB_SAV = 39;
|
||||
UC_TRICORE_REG_PC = 40;
|
||||
UC_TRICORE_REG_SYSCON = 41;
|
||||
UC_TRICORE_REG_CPU_ID = 42;
|
||||
UC_TRICORE_REG_BIV = 43;
|
||||
UC_TRICORE_REG_BTV = 44;
|
||||
UC_TRICORE_REG_ISP = 45;
|
||||
UC_TRICORE_REG_ICR = 46;
|
||||
UC_TRICORE_REG_FCX = 47;
|
||||
UC_TRICORE_REG_LCX = 48;
|
||||
UC_TRICORE_REG_COMPAT = 49;
|
||||
UC_TRICORE_REG_DPR0_U = 50;
|
||||
UC_TRICORE_REG_DPR1_U = 51;
|
||||
UC_TRICORE_REG_DPR2_U = 52;
|
||||
UC_TRICORE_REG_DPR3_U = 53;
|
||||
UC_TRICORE_REG_DPR0_L = 54;
|
||||
UC_TRICORE_REG_DPR1_L = 55;
|
||||
UC_TRICORE_REG_DPR2_L = 56;
|
||||
UC_TRICORE_REG_DPR3_L = 57;
|
||||
UC_TRICORE_REG_CPR0_U = 58;
|
||||
UC_TRICORE_REG_CPR1_U = 59;
|
||||
UC_TRICORE_REG_CPR2_U = 60;
|
||||
UC_TRICORE_REG_CPR3_U = 61;
|
||||
UC_TRICORE_REG_CPR0_L = 62;
|
||||
UC_TRICORE_REG_CPR1_L = 63;
|
||||
UC_TRICORE_REG_CPR2_L = 64;
|
||||
UC_TRICORE_REG_CPR3_L = 65;
|
||||
UC_TRICORE_REG_DPM0 = 66;
|
||||
UC_TRICORE_REG_DPM1 = 67;
|
||||
UC_TRICORE_REG_DPM2 = 68;
|
||||
UC_TRICORE_REG_DPM3 = 69;
|
||||
UC_TRICORE_REG_CPM0 = 70;
|
||||
UC_TRICORE_REG_CPM1 = 71;
|
||||
UC_TRICORE_REG_CPM2 = 72;
|
||||
UC_TRICORE_REG_CPM3 = 73;
|
||||
UC_TRICORE_REG_MMU_CON = 74;
|
||||
UC_TRICORE_REG_MMU_ASI = 75;
|
||||
UC_TRICORE_REG_MMU_TVA = 76;
|
||||
UC_TRICORE_REG_MMU_TPA = 77;
|
||||
UC_TRICORE_REG_MMU_TPX = 78;
|
||||
UC_TRICORE_REG_MMU_TFA = 79;
|
||||
UC_TRICORE_REG_BMACON = 80;
|
||||
UC_TRICORE_REG_SMACON = 81;
|
||||
UC_TRICORE_REG_DIEAR = 82;
|
||||
UC_TRICORE_REG_DIETR = 83;
|
||||
UC_TRICORE_REG_CCDIER = 84;
|
||||
UC_TRICORE_REG_MIECON = 85;
|
||||
UC_TRICORE_REG_PIEAR = 86;
|
||||
UC_TRICORE_REG_PIETR = 87;
|
||||
UC_TRICORE_REG_CCPIER = 88;
|
||||
UC_TRICORE_REG_DBGSR = 89;
|
||||
UC_TRICORE_REG_EXEVT = 90;
|
||||
UC_TRICORE_REG_CREVT = 91;
|
||||
UC_TRICORE_REG_SWEVT = 92;
|
||||
UC_TRICORE_REG_TR0EVT = 93;
|
||||
UC_TRICORE_REG_TR1EVT = 94;
|
||||
UC_TRICORE_REG_DMS = 95;
|
||||
UC_TRICORE_REG_DCX = 96;
|
||||
UC_TRICORE_REG_DBGTCR = 97;
|
||||
UC_TRICORE_REG_CCTRL = 98;
|
||||
UC_TRICORE_REG_CCNT = 99;
|
||||
UC_TRICORE_REG_ICNT = 100;
|
||||
UC_TRICORE_REG_M1CNT = 101;
|
||||
UC_TRICORE_REG_M2CNT = 102;
|
||||
UC_TRICORE_REG_M3CNT = 103;
|
||||
UC_TRICORE_REG_ENDING = 104;
|
||||
UC_TRICORE_REG_GA0 = 1;
|
||||
UC_TRICORE_REG_GA1 = 2;
|
||||
UC_TRICORE_REG_GA8 = 9;
|
||||
UC_TRICORE_REG_GA9 = 10;
|
||||
UC_TRICORE_REG_SP = 11;
|
||||
UC_TRICORE_REG_LR = 12;
|
||||
UC_TRICORE_REG_IA = 16;
|
||||
UC_TRICORE_REG_ID = 32;
|
||||
|
||||
implementation
|
||||
end.
|
@ -9,13 +9,13 @@ const UC_API_MAJOR = 2;
|
||||
UC_API_MINOR = 0;
|
||||
|
||||
UC_API_PATCH = 0;
|
||||
UC_API_EXTRA = 7;
|
||||
UC_API_EXTRA = 255;
|
||||
UC_VERSION_MAJOR = 2;
|
||||
|
||||
UC_VERSION_MINOR = 0;
|
||||
|
||||
UC_VERSION_PATCH = 0;
|
||||
UC_VERSION_EXTRA = 7;
|
||||
UC_VERSION_EXTRA = 255;
|
||||
UC_SECOND_SCALE = 1000000;
|
||||
UC_MILISECOND_SCALE = 1000;
|
||||
UC_ARCH_ARM = 1;
|
||||
@ -27,7 +27,8 @@ const UC_API_MAJOR = 2;
|
||||
UC_ARCH_M68K = 7;
|
||||
UC_ARCH_RISCV = 8;
|
||||
UC_ARCH_S390X = 9;
|
||||
UC_ARCH_MAX = 10;
|
||||
UC_ARCH_TRICORE = 10;
|
||||
UC_ARCH_MAX = 11;
|
||||
|
||||
UC_MODE_LITTLE_ENDIAN = 0;
|
||||
UC_MODE_BIG_ENDIAN = 1073741824;
|
||||
@ -36,7 +37,7 @@ const UC_API_MAJOR = 2;
|
||||
UC_MODE_THUMB = 16;
|
||||
UC_MODE_MCLASS = 32;
|
||||
UC_MODE_V8 = 64;
|
||||
UC_MODE_ARMBE8 = 128;
|
||||
UC_MODE_ARMBE8 = 1024;
|
||||
UC_MODE_ARM926 = 128;
|
||||
UC_MODE_ARM946 = 256;
|
||||
UC_MODE_ARM1176 = 512;
|
||||
@ -137,6 +138,7 @@ const UC_API_MAJOR = 2;
|
||||
UC_CTL_CPU_MODEL = 7;
|
||||
UC_CTL_TB_REQUEST_CACHE = 8;
|
||||
UC_CTL_TB_REMOVE_CACHE = 9;
|
||||
UC_CTL_TB_FLUSH = 10;
|
||||
|
||||
UC_PROT_NONE = 0;
|
||||
UC_PROT_READ = 1;
|
||||
|
57
bindings/python/sample_tricore.py
Executable file
57
bindings/python/sample_tricore.py
Executable file
@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
'''
|
||||
Created for Unicorn Engine by Eric Poole <eric.poole@aptiv.com>, 2022
|
||||
Copyright 2022 Aptiv
|
||||
'''
|
||||
|
||||
from __future__ import print_function
|
||||
from unicorn import *
|
||||
from unicorn.tricore_const import *
|
||||
|
||||
# code to be emulated
|
||||
TRICORE_CODE = b"\x82\x11\xbb\x00\x00\x08" # mov d0, #0x1; mov.u d0, #0x8000
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x10000
|
||||
|
||||
# callback for tracing basic blocks
|
||||
def hook_block(uc, address, size, user_data):
|
||||
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
|
||||
|
||||
# callback for tracing instructions
|
||||
def hook_code(uc, address, size, user_data):
|
||||
print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" %(address, size))
|
||||
|
||||
# Test TriCore
|
||||
def test_tricore():
|
||||
print("Emulate TriCore code")
|
||||
try:
|
||||
# Initialize emulator in TriCore mode
|
||||
mu = Uc(UC_ARCH_TRICORE, UC_MODE_LITTLE_ENDIAN)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, TRICORE_CODE)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing one instruction at ADDRESS with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(TRICORE_CODE))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
r0 = mu.reg_read(UC_TRICORE_REG_D0)
|
||||
print(">>> D0 = 0x%x" %r0)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_tricore()
|
@ -29,17 +29,17 @@ SRC_DIR = os.path.join(ROOT_DIR, 'src')
|
||||
UC_DIR = os.path.join(ROOT_DIR, '../..')
|
||||
BUILD_DIR = os.path.join(UC_DIR, 'build_python')
|
||||
|
||||
VERSION = "2.0.0rc7"
|
||||
VERSION = "2.0.0"
|
||||
|
||||
if SYSTEM == 'darwin':
|
||||
LIBRARY_FILE = "libunicorn.dylib"
|
||||
STATIC_LIBRARY_FILE = None
|
||||
LIBRARY_FILE = "libunicorn.2.dylib"
|
||||
STATIC_LIBRARY_FILE = "libunicorn.a"
|
||||
elif SYSTEM in ('win32', 'cygwin'):
|
||||
LIBRARY_FILE = "unicorn.dll"
|
||||
STATIC_LIBRARY_FILE = "unicorn.lib"
|
||||
else:
|
||||
LIBRARY_FILE = "libunicorn.so"
|
||||
STATIC_LIBRARY_FILE = None
|
||||
LIBRARY_FILE = "libunicorn.so.2"
|
||||
STATIC_LIBRARY_FILE = "libunicorn.a"
|
||||
|
||||
def clean_bins():
|
||||
shutil.rmtree(LIBS_DIR, ignore_errors=True)
|
||||
@ -124,7 +124,7 @@ def build_libraries():
|
||||
|
||||
obj_dir = os.path.join(BUILD_DIR, conf)
|
||||
shutil.copy(os.path.join(obj_dir, LIBRARY_FILE), LIBS_DIR)
|
||||
shutil.copy(os.path.join(obj_dir, STATIC_LIBRARY_FILE), LIBS_DIR)
|
||||
shutil.copy(os.path.join(BUILD_DIR, STATIC_LIBRARY_FILE), LIBS_DIR)
|
||||
else:
|
||||
# platform description refs at https://docs.python.org/2/library/sys.html#sys.platform
|
||||
if not os.path.exists(BUILD_DIR):
|
||||
@ -140,15 +140,8 @@ def build_libraries():
|
||||
subprocess.check_call(["cmake", "--build", ".", "-j" + threads])
|
||||
|
||||
shutil.copy(LIBRARY_FILE, LIBS_DIR)
|
||||
try:
|
||||
# static library may fail to build on windows if user doesn't have visual studio installed. this is fine.
|
||||
if STATIC_LIBRARY_FILE is not None:
|
||||
shutil.copy(STATIC_LIBRARY_FILE, LIBS_DIR)
|
||||
except FileNotFoundError:
|
||||
print('Warning: Could not build static library file! This build is not appropriate for a binary distribution')
|
||||
# enforce this
|
||||
if 'upload' in sys.argv:
|
||||
sys.exit(1)
|
||||
shutil.copy(STATIC_LIBRARY_FILE, LIBS_DIR)
|
||||
|
||||
os.chdir(cwd)
|
||||
|
||||
|
||||
|
124
bindings/python/unicorn/tricore_const.py
Normal file
124
bindings/python/unicorn/tricore_const.py
Normal file
@ -0,0 +1,124 @@
|
||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [tricore_const.py]
|
||||
|
||||
# TRICORE CPU
|
||||
|
||||
UC_CPU_TRICORE_TC1796 = 0
|
||||
UC_CPU_TRICORE_TC1797 = 1
|
||||
UC_CPU_TRICORE_TC27X = 2
|
||||
UC_CPU_TRICORE_ENDING = 3
|
||||
|
||||
# TRICORE registers
|
||||
|
||||
UC_TRICORE_REG_INVALID = 0
|
||||
UC_TRICORE_REG_A0 = 1
|
||||
UC_TRICORE_REG_A1 = 2
|
||||
UC_TRICORE_REG_A2 = 3
|
||||
UC_TRICORE_REG_A3 = 4
|
||||
UC_TRICORE_REG_A4 = 5
|
||||
UC_TRICORE_REG_A5 = 6
|
||||
UC_TRICORE_REG_A6 = 7
|
||||
UC_TRICORE_REG_A7 = 8
|
||||
UC_TRICORE_REG_A8 = 9
|
||||
UC_TRICORE_REG_A9 = 10
|
||||
UC_TRICORE_REG_A10 = 11
|
||||
UC_TRICORE_REG_A11 = 12
|
||||
UC_TRICORE_REG_A12 = 13
|
||||
UC_TRICORE_REG_A13 = 14
|
||||
UC_TRICORE_REG_A14 = 15
|
||||
UC_TRICORE_REG_A15 = 16
|
||||
UC_TRICORE_REG_D0 = 17
|
||||
UC_TRICORE_REG_D1 = 18
|
||||
UC_TRICORE_REG_D2 = 19
|
||||
UC_TRICORE_REG_D3 = 20
|
||||
UC_TRICORE_REG_D4 = 21
|
||||
UC_TRICORE_REG_D5 = 22
|
||||
UC_TRICORE_REG_D6 = 23
|
||||
UC_TRICORE_REG_D7 = 24
|
||||
UC_TRICORE_REG_D8 = 25
|
||||
UC_TRICORE_REG_D9 = 26
|
||||
UC_TRICORE_REG_D10 = 27
|
||||
UC_TRICORE_REG_D11 = 28
|
||||
UC_TRICORE_REG_D12 = 29
|
||||
UC_TRICORE_REG_D13 = 30
|
||||
UC_TRICORE_REG_D14 = 31
|
||||
UC_TRICORE_REG_D15 = 32
|
||||
UC_TRICORE_REG_PCXI = 33
|
||||
UC_TRICORE_REG_PSW = 34
|
||||
UC_TRICORE_REG_PSW_USB_C = 35
|
||||
UC_TRICORE_REG_PSW_USB_V = 36
|
||||
UC_TRICORE_REG_PSW_USB_SV = 37
|
||||
UC_TRICORE_REG_PSW_USB_AV = 38
|
||||
UC_TRICORE_REG_PSW_USB_SAV = 39
|
||||
UC_TRICORE_REG_PC = 40
|
||||
UC_TRICORE_REG_SYSCON = 41
|
||||
UC_TRICORE_REG_CPU_ID = 42
|
||||
UC_TRICORE_REG_BIV = 43
|
||||
UC_TRICORE_REG_BTV = 44
|
||||
UC_TRICORE_REG_ISP = 45
|
||||
UC_TRICORE_REG_ICR = 46
|
||||
UC_TRICORE_REG_FCX = 47
|
||||
UC_TRICORE_REG_LCX = 48
|
||||
UC_TRICORE_REG_COMPAT = 49
|
||||
UC_TRICORE_REG_DPR0_U = 50
|
||||
UC_TRICORE_REG_DPR1_U = 51
|
||||
UC_TRICORE_REG_DPR2_U = 52
|
||||
UC_TRICORE_REG_DPR3_U = 53
|
||||
UC_TRICORE_REG_DPR0_L = 54
|
||||
UC_TRICORE_REG_DPR1_L = 55
|
||||
UC_TRICORE_REG_DPR2_L = 56
|
||||
UC_TRICORE_REG_DPR3_L = 57
|
||||
UC_TRICORE_REG_CPR0_U = 58
|
||||
UC_TRICORE_REG_CPR1_U = 59
|
||||
UC_TRICORE_REG_CPR2_U = 60
|
||||
UC_TRICORE_REG_CPR3_U = 61
|
||||
UC_TRICORE_REG_CPR0_L = 62
|
||||
UC_TRICORE_REG_CPR1_L = 63
|
||||
UC_TRICORE_REG_CPR2_L = 64
|
||||
UC_TRICORE_REG_CPR3_L = 65
|
||||
UC_TRICORE_REG_DPM0 = 66
|
||||
UC_TRICORE_REG_DPM1 = 67
|
||||
UC_TRICORE_REG_DPM2 = 68
|
||||
UC_TRICORE_REG_DPM3 = 69
|
||||
UC_TRICORE_REG_CPM0 = 70
|
||||
UC_TRICORE_REG_CPM1 = 71
|
||||
UC_TRICORE_REG_CPM2 = 72
|
||||
UC_TRICORE_REG_CPM3 = 73
|
||||
UC_TRICORE_REG_MMU_CON = 74
|
||||
UC_TRICORE_REG_MMU_ASI = 75
|
||||
UC_TRICORE_REG_MMU_TVA = 76
|
||||
UC_TRICORE_REG_MMU_TPA = 77
|
||||
UC_TRICORE_REG_MMU_TPX = 78
|
||||
UC_TRICORE_REG_MMU_TFA = 79
|
||||
UC_TRICORE_REG_BMACON = 80
|
||||
UC_TRICORE_REG_SMACON = 81
|
||||
UC_TRICORE_REG_DIEAR = 82
|
||||
UC_TRICORE_REG_DIETR = 83
|
||||
UC_TRICORE_REG_CCDIER = 84
|
||||
UC_TRICORE_REG_MIECON = 85
|
||||
UC_TRICORE_REG_PIEAR = 86
|
||||
UC_TRICORE_REG_PIETR = 87
|
||||
UC_TRICORE_REG_CCPIER = 88
|
||||
UC_TRICORE_REG_DBGSR = 89
|
||||
UC_TRICORE_REG_EXEVT = 90
|
||||
UC_TRICORE_REG_CREVT = 91
|
||||
UC_TRICORE_REG_SWEVT = 92
|
||||
UC_TRICORE_REG_TR0EVT = 93
|
||||
UC_TRICORE_REG_TR1EVT = 94
|
||||
UC_TRICORE_REG_DMS = 95
|
||||
UC_TRICORE_REG_DCX = 96
|
||||
UC_TRICORE_REG_DBGTCR = 97
|
||||
UC_TRICORE_REG_CCTRL = 98
|
||||
UC_TRICORE_REG_CCNT = 99
|
||||
UC_TRICORE_REG_ICNT = 100
|
||||
UC_TRICORE_REG_M1CNT = 101
|
||||
UC_TRICORE_REG_M2CNT = 102
|
||||
UC_TRICORE_REG_M3CNT = 103
|
||||
UC_TRICORE_REG_ENDING = 104
|
||||
UC_TRICORE_REG_GA0 = 1
|
||||
UC_TRICORE_REG_GA1 = 2
|
||||
UC_TRICORE_REG_GA8 = 9
|
||||
UC_TRICORE_REG_GA9 = 10
|
||||
UC_TRICORE_REG_SP = 11
|
||||
UC_TRICORE_REG_LR = 12
|
||||
UC_TRICORE_REG_IA = 16
|
||||
UC_TRICORE_REG_ID = 32
|
@ -1,9 +1,10 @@
|
||||
# Unicorn Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
|
||||
|
||||
from __future__ import annotations
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
import distutils.sysconfig
|
||||
from functools import wraps
|
||||
from typing import Any, Callable, List, Tuple, Union
|
||||
import pkg_resources
|
||||
import inspect
|
||||
import os.path
|
||||
@ -21,11 +22,11 @@ _python2 = sys.version_info[0] < 3
|
||||
if _python2:
|
||||
range = xrange
|
||||
|
||||
_lib = { 'darwin': 'libunicorn.dylib',
|
||||
_lib = { 'darwin': 'libunicorn.2.dylib',
|
||||
'win32': 'unicorn.dll',
|
||||
'cygwin': 'cygunicorn.dll',
|
||||
'linux': 'libunicorn.so',
|
||||
'linux2': 'libunicorn.so' }
|
||||
'linux': 'libunicorn.so.2',
|
||||
'linux2': 'libunicorn.so.2' }
|
||||
|
||||
|
||||
# Windows DLL in dependency order
|
||||
@ -57,12 +58,12 @@ def _load_win_support(path):
|
||||
if sys.platform in ('win32', 'cygwin'):
|
||||
_load_win_support('')
|
||||
|
||||
def _load_lib(path):
|
||||
def _load_lib(path, lib_name):
|
||||
try:
|
||||
if sys.platform in ('win32', 'cygwin'):
|
||||
_load_win_support(path)
|
||||
|
||||
lib_file = os.path.join(path, _lib.get(sys.platform, 'libunicorn.so'))
|
||||
lib_file = os.path.join(path, lib_name)
|
||||
dll = ctypes.cdll.LoadLibrary(lib_file)
|
||||
#print('SUCCESS')
|
||||
return dll
|
||||
@ -93,12 +94,26 @@ _path_list = [os.getenv('LIBUNICORN_PATH', None),
|
||||
|
||||
for _path in _path_list:
|
||||
if _path is None: continue
|
||||
_uc = _load_lib(_path)
|
||||
if _uc is not None: break
|
||||
else:
|
||||
_uc = _load_lib(_path, _lib.get(sys.platform, "libunicorn.so"))
|
||||
if _uc is not None:
|
||||
break
|
||||
|
||||
# Try to search old unicorn1 library without SONAME
|
||||
if _uc is None:
|
||||
for _path in _path_list:
|
||||
if _path is None:
|
||||
continue
|
||||
|
||||
_uc = _load_lib(_path, "libunicorn.so")
|
||||
if _uc is not None:
|
||||
# In this case, show a warning for users
|
||||
print("Found an old style dynamic library libunicorn.so, consider checking your installation", file=sys.stderr)
|
||||
break
|
||||
|
||||
if _uc is None:
|
||||
raise ImportError("ERROR: fail to load the dynamic library.")
|
||||
|
||||
__version__ = "%u.%u.%u" % (uc.UC_VERSION_MAJOR, uc.UC_VERSION_MINOR, uc.UC_VERSION_EXTRA)
|
||||
__version__ = "%u.%u.%u" % (uc.UC_VERSION_MAJOR, uc.UC_VERSION_MINOR, uc.UC_VERSION_PATCH)
|
||||
|
||||
# setup all the function prototype
|
||||
def _setup_prototype(lib, fname, restype, *argtypes):
|
||||
@ -184,6 +199,7 @@ UC_HOOK_INSN_OUT_CB = ctypes.CFUNCTYPE(
|
||||
)
|
||||
UC_HOOK_INSN_SYSCALL_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_void_p)
|
||||
UC_HOOK_INSN_SYS_CB = ctypes.CFUNCTYPE(ctypes.c_uint32, uc_engine, ctypes.c_uint32, ctypes.c_void_p, ctypes.c_void_p)
|
||||
UC_HOOK_INSN_CPUID_CB = ctypes.CFUNCTYPE(ctypes.c_uint32, uc_engine, ctypes.c_void_p)
|
||||
UC_MMIO_READ_CB = ctypes.CFUNCTYPE(
|
||||
ctypes.c_uint64, uc_engine, ctypes.c_uint64, ctypes.c_int, ctypes.c_void_p
|
||||
)
|
||||
@ -226,6 +242,13 @@ def version_bind():
|
||||
def uc_arch_supported(query):
|
||||
return _uc.uc_arch_supported(query)
|
||||
|
||||
ARMCPReg = Tuple[int, int, int, int, int, int, int]
|
||||
ARM64CPReg = Tuple[int, int, int, int, int]
|
||||
ARMCPRegValue = Tuple[int, int, int, int, int, int, int, int]
|
||||
ARM64CPRegValue = Tuple[int, int, int, int, int, int]
|
||||
X86MMRReg = Tuple[int, int, int, int]
|
||||
X86FPReg = Tuple[int, int]
|
||||
|
||||
# uc_reg_read/write and uc_context_reg_read/write.
|
||||
def reg_read(reg_read_func, arch, reg_id, opt=None):
|
||||
if arch == uc.UC_ARCH_X86:
|
||||
@ -285,7 +308,7 @@ def reg_read(reg_read_func, arch, reg_id, opt=None):
|
||||
raise UcError(status)
|
||||
return reg.val
|
||||
|
||||
elif reg_id in range(arm64_const.UC_ARM64_REG_Q0, arm64_const.UC_ARM64_REG_Q31+1) or range(arm64_const.UC_ARM64_REG_V0, arm64_const.UC_ARM64_REG_V31+1):
|
||||
elif reg_id in range(arm64_const.UC_ARM64_REG_Q0, arm64_const.UC_ARM64_REG_Q31+1) or reg_id in range(arm64_const.UC_ARM64_REG_V0, arm64_const.UC_ARM64_REG_V31+1):
|
||||
reg = uc_arm64_neon128()
|
||||
status = reg_read_func(reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
@ -330,7 +353,7 @@ def reg_write(reg_write_func, arch, reg_id, value):
|
||||
reg.value = value[1]
|
||||
|
||||
if arch == uc.UC_ARCH_ARM64:
|
||||
if reg_id in range(arm64_const.UC_ARM64_REG_Q0, arm64_const.UC_ARM64_REG_Q31+1) or range(arm64_const.UC_ARM64_REG_V0, arm64_const.UC_ARM64_REG_V31+1):
|
||||
if reg_id in range(arm64_const.UC_ARM64_REG_Q0, arm64_const.UC_ARM64_REG_Q31+1) or reg_id in range(arm64_const.UC_ARM64_REG_V0, arm64_const.UC_ARM64_REG_V31+1):
|
||||
reg = uc_arm64_neon128()
|
||||
reg.low_qword = value & 0xffffffffffffffff
|
||||
reg.high_qword = value >> 64
|
||||
@ -484,7 +507,7 @@ class UcCleanupManager(object):
|
||||
class Uc(object):
|
||||
_cleanup = UcCleanupManager()
|
||||
|
||||
def __init__(self, arch, mode):
|
||||
def __init__(self, arch: int, mode: int):
|
||||
# verify version compatibility with the core before doing anything
|
||||
(major, minor, _combined) = uc_version()
|
||||
# print("core version =", uc_version())
|
||||
@ -508,7 +531,7 @@ class Uc(object):
|
||||
self._hook_exception = None # The exception raised in a hook
|
||||
|
||||
@staticmethod
|
||||
def release_handle(uch):
|
||||
def release_handle(uch: ctypes.CDLL):
|
||||
if uch:
|
||||
try:
|
||||
status = _uc.uc_close(uch)
|
||||
@ -518,7 +541,7 @@ class Uc(object):
|
||||
pass
|
||||
|
||||
# emulate from @begin, and stop when reaching address @until
|
||||
def emu_start(self, begin, until, timeout=0, count=0):
|
||||
def emu_start(self, begin: int, until: int, timeout: int=0, count: int=0) -> None:
|
||||
self._hook_exception = None
|
||||
status = _uc.uc_emu_start(self._uch, begin, until, timeout, count)
|
||||
if status != uc.UC_ERR_OK:
|
||||
@ -528,29 +551,29 @@ class Uc(object):
|
||||
raise self._hook_exception
|
||||
|
||||
# stop emulation
|
||||
def emu_stop(self):
|
||||
def emu_stop(self) -> None:
|
||||
status = _uc.uc_emu_stop(self._uch)
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
# return the value of a register
|
||||
def reg_read(self, reg_id, opt=None):
|
||||
# return the value of a register, for @opt parameter, specify int for x86 msr, tuple for arm cp/neon regs.
|
||||
def reg_read(self, reg_id: int, opt: Union[None, int, ARMCPReg, ARM64CPReg]=None) -> Union[int, X86MMRReg, X86FPReg]:
|
||||
return reg_read(functools.partial(_uc.uc_reg_read, self._uch), self._arch, reg_id, opt)
|
||||
|
||||
# write to a register
|
||||
def reg_write(self, reg_id, value):
|
||||
# write to a register, tuple for arm cp regs.
|
||||
def reg_write(self, reg_id: Union[int, ARMCPRegValue, ARM64CPRegValue, X86MMRReg, X86FPReg], value: int):
|
||||
return reg_write(functools.partial(_uc.uc_reg_write, self._uch), self._arch, reg_id, value)
|
||||
|
||||
# read from MSR - X86 only
|
||||
def msr_read(self, msr_id):
|
||||
def msr_read(self, msr_id: int):
|
||||
return self.reg_read(x86_const.UC_X86_REG_MSR, msr_id)
|
||||
|
||||
# write to MSR - X86 only
|
||||
def msr_write(self, msr_id, value):
|
||||
def msr_write(self, msr_id, value: int):
|
||||
return self.reg_write(x86_const.UC_X86_REG_MSR, (msr_id, value))
|
||||
|
||||
# read data from memory
|
||||
def mem_read(self, address, size):
|
||||
def mem_read(self, address: int, size: int):
|
||||
data = ctypes.create_string_buffer(size)
|
||||
status = _uc.uc_mem_read(self._uch, address, data, size)
|
||||
if status != uc.UC_ERR_OK:
|
||||
@ -558,7 +581,7 @@ class Uc(object):
|
||||
return bytearray(data)
|
||||
|
||||
# write to memory
|
||||
def mem_write(self, address, data):
|
||||
def mem_write(self, address: int, data: bytes):
|
||||
status = _uc.uc_mem_write(self._uch, address, data, len(data))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
@ -571,7 +594,9 @@ class Uc(object):
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
cb(self, offset, size, value, data)
|
||||
|
||||
def mmio_map(self, address, size, read_cb, user_data_read, write_cb, user_data_write):
|
||||
def mmio_map(self, address: int, size: int,
|
||||
read_cb: UC_MMIO_READ_TYPE, user_data_read: Any,
|
||||
write_cb: UC_MMIO_WRITE_TYPE, user_data_write: Any):
|
||||
internal_read_cb = ctypes.cast(UC_MMIO_READ_CB(self._mmio_map_read_cb), UC_MMIO_READ_CB)
|
||||
internal_write_cb = ctypes.cast(UC_MMIO_WRITE_CB(self._mmio_map_write_cb), UC_MMIO_WRITE_CB)
|
||||
|
||||
@ -591,31 +616,31 @@ class Uc(object):
|
||||
self._ctype_cbs.append(internal_write_cb)
|
||||
|
||||
# map a range of memory
|
||||
def mem_map(self, address, size, perms=uc.UC_PROT_ALL):
|
||||
def mem_map(self, address: int, size: int, perms: int=uc.UC_PROT_ALL):
|
||||
status = _uc.uc_mem_map(self._uch, address, size, perms)
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
# map a range of memory from a raw host memory address
|
||||
def mem_map_ptr(self, address, size, perms, ptr):
|
||||
def mem_map_ptr(self, address: int, size: int, perms: int, ptr: int):
|
||||
status = _uc.uc_mem_map_ptr(self._uch, address, size, perms, ptr)
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
# unmap a range of memory
|
||||
def mem_unmap(self, address, size):
|
||||
def mem_unmap(self, address: int, size: int):
|
||||
status = _uc.uc_mem_unmap(self._uch, address, size)
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
# protect a range of memory
|
||||
def mem_protect(self, address, size, perms=uc.UC_PROT_ALL):
|
||||
def mem_protect(self, address: int, size: int, perms: int=uc.UC_PROT_ALL):
|
||||
status = _uc.uc_mem_protect(self._uch, address, size, perms)
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
# return CPU mode at runtime
|
||||
def query(self, query_mode):
|
||||
def query(self, query_mode: int):
|
||||
result = ctypes.c_size_t(0)
|
||||
status = _uc.uc_query(self._uch, query_mode, ctypes.byref(result))
|
||||
if status != uc.UC_ERR_OK:
|
||||
@ -690,7 +715,13 @@ class Uc(object):
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
cb(self, data)
|
||||
|
||||
def ctl(self, control, *args):
|
||||
@_catch_hook_exception
|
||||
def _hook_insn_cpuid_cb(self, handle: int, user_data: int) -> int:
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
return cb(self, data)
|
||||
|
||||
def ctl(self, control: int, *args):
|
||||
status = _uc.uc_ctl(self._uch, control, *args)
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
@ -717,6 +748,11 @@ class Uc(object):
|
||||
arg = ctp(val)
|
||||
self.ctl(self.__ctl_w(ctl, 1), arg)
|
||||
|
||||
def __ctl_w_2_arg(self, ctl, val1, val2, ctp1, ctp2):
|
||||
arg1 = ctp1(val1)
|
||||
arg2 = ctp2(val2)
|
||||
self.ctl(self.__ctl_w(ctl, 2), arg1, arg2)
|
||||
|
||||
def __ctl_rw_1_1_arg(self, ctl, val, ctp1, ctp2):
|
||||
arg1 = ctp1(val)
|
||||
arg2 = ctp2()
|
||||
@ -729,7 +765,7 @@ class Uc(object):
|
||||
def ctl_get_page_size(self):
|
||||
return self.__ctl_r_1_arg(uc.UC_CTL_UC_PAGE_SIZE, ctypes.c_uint32)
|
||||
|
||||
def ctl_set_page_size(self, val):
|
||||
def ctl_set_page_size(self, val: int):
|
||||
self.__ctl_w_1_arg(uc.UC_CTL_UC_PAGE_SIZE, val, ctypes.c_uint32)
|
||||
|
||||
def ctl_get_arch(self):
|
||||
@ -738,7 +774,7 @@ class Uc(object):
|
||||
def ctl_get_timeout(self):
|
||||
return self.__ctl_r_1_arg(uc.UC_CTL_UC_TIMEOUT, ctypes.c_uint64)
|
||||
|
||||
def ctl_exits_enabled(self, val):
|
||||
def ctl_exits_enabled(self, val: bool):
|
||||
self.__ctl_w_1_arg(uc.UC_CTL_UC_USE_EXITS, val, ctypes.c_int)
|
||||
|
||||
def ctl_get_exits_cnt(self):
|
||||
@ -750,7 +786,7 @@ class Uc(object):
|
||||
self.ctl(self.__ctl_r(uc.UC_CTL_UC_EXITS, 2), ctypes.cast(arr, ctypes.c_void_p), ctypes.c_size_t(l))
|
||||
return [i for i in arr]
|
||||
|
||||
def ctl_set_exits(self, exits):
|
||||
def ctl_set_exits(self, exits: List[int]):
|
||||
arr = (ctypes.c_uint64 * len(exits))()
|
||||
for idx, exit in enumerate(exits):
|
||||
arr[idx] = exit
|
||||
@ -759,17 +795,20 @@ class Uc(object):
|
||||
def ctl_get_cpu_model(self):
|
||||
return self.__ctl_r_1_arg(uc.UC_CTL_CPU_MODEL, ctypes.c_int)
|
||||
|
||||
def ctl_set_cpu_model(self, val):
|
||||
def ctl_set_cpu_model(self, val: int):
|
||||
self.__ctl_w_1_arg(uc.UC_CTL_CPU_MODEL, val, ctypes.c_int)
|
||||
|
||||
def ctl_remove_cache(self, addr):
|
||||
self.__ctl_w_1_arg(uc.UC_CTL_TB_REMOVE_CACHE, addr, ctypes.c_uint64)
|
||||
def ctl_remove_cache(self, addr: int, end: int):
|
||||
self.__ctl_w_2_arg(uc.UC_CTL_TB_REMOVE_CACHE, addr, end, ctypes.c_uint64, ctypes.c_uint64)
|
||||
|
||||
def ctl_request_cache(self, addr):
|
||||
def ctl_request_cache(self, addr: int):
|
||||
return self.__ctl_rw_1_1_arg(uc.UC_CTL_TB_REQUEST_CACHE, addr, ctypes.c_uint64, uc_tb)
|
||||
|
||||
def ctl_flush_tb(self):
|
||||
self.ctl(self.__ctl_w(uc.UC_CTL_TB_FLUSH, 0))
|
||||
|
||||
# add a hook
|
||||
def hook_add(self, htype, callback, user_data=None, begin=1, end=0, arg1=0, arg2=0):
|
||||
def hook_add(self, htype: int, callback: UC_HOOK_CALLBACK_TYPE , user_data: Any=None, begin: int=1, end: int=0, arg1: int=0, arg2: int=0):
|
||||
_h2 = uc_hook_h()
|
||||
|
||||
# save callback & user_data
|
||||
@ -785,6 +824,8 @@ class Uc(object):
|
||||
cb = ctypes.cast(UC_HOOK_INSN_OUT_CB(self._hook_insn_out_cb), UC_HOOK_INSN_OUT_CB)
|
||||
if arg1 in (x86_const.UC_X86_INS_SYSCALL, x86_const.UC_X86_INS_SYSENTER): # SYSCALL/SYSENTER instruction
|
||||
cb = ctypes.cast(UC_HOOK_INSN_SYSCALL_CB(self._hook_insn_syscall_cb), UC_HOOK_INSN_SYSCALL_CB)
|
||||
if arg1 == x86_const.UC_X86_INS_CPUID: # CPUID instruction
|
||||
cb = ctypes.cast(UC_HOOK_INSN_CPUID_CB(self._hook_insn_cpuid_cb), UC_HOOK_INSN_CPUID_CB)
|
||||
if arg1 in (arm64_const.UC_ARM64_INS_MRS, arm64_const.UC_ARM64_INS_MSR, arm64_const.UC_ARM64_INS_SYS, arm64_const.UC_ARM64_INS_SYSL):
|
||||
cb = ctypes.cast(UC_HOOK_INSN_SYS_CB(self._hook_insn_sys_cb), UC_HOOK_INSN_SYS_CB)
|
||||
status = _uc.uc_hook_add(
|
||||
@ -861,7 +902,7 @@ class Uc(object):
|
||||
return _h2.value
|
||||
|
||||
# delete a hook
|
||||
def hook_del(self, h):
|
||||
def hook_del(self, h: int):
|
||||
_h = uc_hook_h(h)
|
||||
status = _uc.uc_hook_del(self._uch, _h)
|
||||
if status != uc.UC_ERR_OK:
|
||||
@ -876,12 +917,12 @@ class Uc(object):
|
||||
|
||||
return context
|
||||
|
||||
def context_update(self, context):
|
||||
def context_update(self, context: UcContext):
|
||||
status = _uc.uc_context_save(self._uch, context.context)
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
def context_restore(self, context):
|
||||
def context_restore(self, context: UcContext):
|
||||
status = _uc.uc_context_restore(self._uch, context.context)
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
@ -956,6 +997,34 @@ class UcContext:
|
||||
if self._to_free:
|
||||
_uc.uc_context_free(self._context)
|
||||
|
||||
UC_HOOK_CODE_TYPE = Callable[[Uc, int, int, Any], None]
|
||||
UC_HOOK_INSN_INVALID_TYPE = Callable[[Uc, Any], bool]
|
||||
UC_HOOK_MEM_INVALID_TYPE = Callable[[Uc, int, int, int, int, Any], bool]
|
||||
UC_HOOK_MEM_ACCESS_TYPE = Callable[[Uc, int, int, int, int, Any], None]
|
||||
UC_HOOK_INTR_TYPE = Callable[[Uc, int, Any], None]
|
||||
UC_HOOK_INSN_IN_TYPE = Callable[[Uc, int, int, Any], int]
|
||||
UC_HOOK_INSN_OUT_TYPE = Callable[[Uc, int, int, int, Any], None]
|
||||
UC_HOOK_INSN_SYSCALL_TYPE = Callable[[Uc, Any], None]
|
||||
UC_HOOK_INSN_SYS_TYPE = Callable[[Uc, int, Tuple[int, int, int, int, int, int], Any], int]
|
||||
UC_HOOK_INSN_CPUID_TYPE = Callable[[Uc, Any], int]
|
||||
UC_MMIO_READ_TYPE = Callable[[Uc, int, int, Any], int]
|
||||
UC_MMIO_WRITE_TYPE = Callable[[Uc, int, int, int, Any], None]
|
||||
UC_HOOK_EDGE_GEN_TYPE = Callable[[Uc, uc_tb, uc_tb, Any], None]
|
||||
UC_HOOK_TCG_OPCODE_TYPE = Callable[[Uc, int, int, int, Any], None]
|
||||
|
||||
UC_HOOK_CALLBACK_TYPE = Union[
|
||||
UC_HOOK_CODE_TYPE,
|
||||
UC_HOOK_INSN_INVALID_TYPE,
|
||||
UC_HOOK_MEM_INVALID_TYPE,
|
||||
UC_HOOK_MEM_ACCESS_TYPE,
|
||||
UC_HOOK_INSN_IN_TYPE,
|
||||
UC_HOOK_INSN_OUT_TYPE,
|
||||
UC_HOOK_INSN_SYSCALL_TYPE,
|
||||
UC_HOOK_INSN_SYS_TYPE,
|
||||
UC_HOOK_INSN_CPUID_TYPE,
|
||||
UC_HOOK_EDGE_GEN_TYPE,
|
||||
UC_HOOK_TCG_OPCODE_TYPE
|
||||
]
|
||||
|
||||
# print out debugging info
|
||||
def debug():
|
||||
|
@ -4,13 +4,13 @@ UC_API_MAJOR = 2
|
||||
UC_API_MINOR = 0
|
||||
|
||||
UC_API_PATCH = 0
|
||||
UC_API_EXTRA = 7
|
||||
UC_API_EXTRA = 255
|
||||
UC_VERSION_MAJOR = 2
|
||||
|
||||
UC_VERSION_MINOR = 0
|
||||
|
||||
UC_VERSION_PATCH = 0
|
||||
UC_VERSION_EXTRA = 7
|
||||
UC_VERSION_EXTRA = 255
|
||||
UC_SECOND_SCALE = 1000000
|
||||
UC_MILISECOND_SCALE = 1000
|
||||
UC_ARCH_ARM = 1
|
||||
@ -22,7 +22,8 @@ UC_ARCH_SPARC = 6
|
||||
UC_ARCH_M68K = 7
|
||||
UC_ARCH_RISCV = 8
|
||||
UC_ARCH_S390X = 9
|
||||
UC_ARCH_MAX = 10
|
||||
UC_ARCH_TRICORE = 10
|
||||
UC_ARCH_MAX = 11
|
||||
|
||||
UC_MODE_LITTLE_ENDIAN = 0
|
||||
UC_MODE_BIG_ENDIAN = 1073741824
|
||||
@ -31,7 +32,7 @@ UC_MODE_ARM = 0
|
||||
UC_MODE_THUMB = 16
|
||||
UC_MODE_MCLASS = 32
|
||||
UC_MODE_V8 = 64
|
||||
UC_MODE_ARMBE8 = 128
|
||||
UC_MODE_ARMBE8 = 1024
|
||||
UC_MODE_ARM926 = 128
|
||||
UC_MODE_ARM946 = 256
|
||||
UC_MODE_ARM1176 = 512
|
||||
@ -132,6 +133,7 @@ UC_CTL_UC_EXITS = 6
|
||||
UC_CTL_CPU_MODEL = 7
|
||||
UC_CTL_TB_REQUEST_CACHE = 8
|
||||
UC_CTL_TB_REMOVE_CACHE = 9
|
||||
UC_CTL_TB_FLUSH = 10
|
||||
|
||||
UC_PROT_NONE = 0
|
||||
UC_PROT_READ = 1
|
||||
|
@ -5,7 +5,7 @@
|
||||
# Use bundle install && rake to install gem and test
|
||||
install: gen_const
|
||||
cd unicorn_gem && rake build
|
||||
cd unicorn_gem && gem install --local pkg/unicorn-engine-1.0.1.gem
|
||||
cd unicorn_gem && gem install --local pkg/unicorn-engine-2.0.0.gem
|
||||
|
||||
gen_const:
|
||||
cd .. && python3 const_generator.py ruby
|
||||
|
@ -3,6 +3,7 @@ require 'mkmf'
|
||||
extension_name = 'unicorn_engine'
|
||||
|
||||
dir_config(extension_name)
|
||||
pkg_config('unicorn')
|
||||
have_library('unicorn')
|
||||
|
||||
create_makefile(extension_name)
|
||||
|
127
bindings/ruby/unicorn_gem/lib/unicorn_engine/tricore_const.rb
Normal file
127
bindings/ruby/unicorn_gem/lib/unicorn_engine/tricore_const.rb
Normal file
@ -0,0 +1,127 @@
|
||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [tricore_const.rb]
|
||||
|
||||
module UnicornEngine
|
||||
|
||||
# TRICORE CPU
|
||||
|
||||
UC_CPU_TRICORE_TC1796 = 0
|
||||
UC_CPU_TRICORE_TC1797 = 1
|
||||
UC_CPU_TRICORE_TC27X = 2
|
||||
UC_CPU_TRICORE_ENDING = 3
|
||||
|
||||
# TRICORE registers
|
||||
|
||||
UC_TRICORE_REG_INVALID = 0
|
||||
UC_TRICORE_REG_A0 = 1
|
||||
UC_TRICORE_REG_A1 = 2
|
||||
UC_TRICORE_REG_A2 = 3
|
||||
UC_TRICORE_REG_A3 = 4
|
||||
UC_TRICORE_REG_A4 = 5
|
||||
UC_TRICORE_REG_A5 = 6
|
||||
UC_TRICORE_REG_A6 = 7
|
||||
UC_TRICORE_REG_A7 = 8
|
||||
UC_TRICORE_REG_A8 = 9
|
||||
UC_TRICORE_REG_A9 = 10
|
||||
UC_TRICORE_REG_A10 = 11
|
||||
UC_TRICORE_REG_A11 = 12
|
||||
UC_TRICORE_REG_A12 = 13
|
||||
UC_TRICORE_REG_A13 = 14
|
||||
UC_TRICORE_REG_A14 = 15
|
||||
UC_TRICORE_REG_A15 = 16
|
||||
UC_TRICORE_REG_D0 = 17
|
||||
UC_TRICORE_REG_D1 = 18
|
||||
UC_TRICORE_REG_D2 = 19
|
||||
UC_TRICORE_REG_D3 = 20
|
||||
UC_TRICORE_REG_D4 = 21
|
||||
UC_TRICORE_REG_D5 = 22
|
||||
UC_TRICORE_REG_D6 = 23
|
||||
UC_TRICORE_REG_D7 = 24
|
||||
UC_TRICORE_REG_D8 = 25
|
||||
UC_TRICORE_REG_D9 = 26
|
||||
UC_TRICORE_REG_D10 = 27
|
||||
UC_TRICORE_REG_D11 = 28
|
||||
UC_TRICORE_REG_D12 = 29
|
||||
UC_TRICORE_REG_D13 = 30
|
||||
UC_TRICORE_REG_D14 = 31
|
||||
UC_TRICORE_REG_D15 = 32
|
||||
UC_TRICORE_REG_PCXI = 33
|
||||
UC_TRICORE_REG_PSW = 34
|
||||
UC_TRICORE_REG_PSW_USB_C = 35
|
||||
UC_TRICORE_REG_PSW_USB_V = 36
|
||||
UC_TRICORE_REG_PSW_USB_SV = 37
|
||||
UC_TRICORE_REG_PSW_USB_AV = 38
|
||||
UC_TRICORE_REG_PSW_USB_SAV = 39
|
||||
UC_TRICORE_REG_PC = 40
|
||||
UC_TRICORE_REG_SYSCON = 41
|
||||
UC_TRICORE_REG_CPU_ID = 42
|
||||
UC_TRICORE_REG_BIV = 43
|
||||
UC_TRICORE_REG_BTV = 44
|
||||
UC_TRICORE_REG_ISP = 45
|
||||
UC_TRICORE_REG_ICR = 46
|
||||
UC_TRICORE_REG_FCX = 47
|
||||
UC_TRICORE_REG_LCX = 48
|
||||
UC_TRICORE_REG_COMPAT = 49
|
||||
UC_TRICORE_REG_DPR0_U = 50
|
||||
UC_TRICORE_REG_DPR1_U = 51
|
||||
UC_TRICORE_REG_DPR2_U = 52
|
||||
UC_TRICORE_REG_DPR3_U = 53
|
||||
UC_TRICORE_REG_DPR0_L = 54
|
||||
UC_TRICORE_REG_DPR1_L = 55
|
||||
UC_TRICORE_REG_DPR2_L = 56
|
||||
UC_TRICORE_REG_DPR3_L = 57
|
||||
UC_TRICORE_REG_CPR0_U = 58
|
||||
UC_TRICORE_REG_CPR1_U = 59
|
||||
UC_TRICORE_REG_CPR2_U = 60
|
||||
UC_TRICORE_REG_CPR3_U = 61
|
||||
UC_TRICORE_REG_CPR0_L = 62
|
||||
UC_TRICORE_REG_CPR1_L = 63
|
||||
UC_TRICORE_REG_CPR2_L = 64
|
||||
UC_TRICORE_REG_CPR3_L = 65
|
||||
UC_TRICORE_REG_DPM0 = 66
|
||||
UC_TRICORE_REG_DPM1 = 67
|
||||
UC_TRICORE_REG_DPM2 = 68
|
||||
UC_TRICORE_REG_DPM3 = 69
|
||||
UC_TRICORE_REG_CPM0 = 70
|
||||
UC_TRICORE_REG_CPM1 = 71
|
||||
UC_TRICORE_REG_CPM2 = 72
|
||||
UC_TRICORE_REG_CPM3 = 73
|
||||
UC_TRICORE_REG_MMU_CON = 74
|
||||
UC_TRICORE_REG_MMU_ASI = 75
|
||||
UC_TRICORE_REG_MMU_TVA = 76
|
||||
UC_TRICORE_REG_MMU_TPA = 77
|
||||
UC_TRICORE_REG_MMU_TPX = 78
|
||||
UC_TRICORE_REG_MMU_TFA = 79
|
||||
UC_TRICORE_REG_BMACON = 80
|
||||
UC_TRICORE_REG_SMACON = 81
|
||||
UC_TRICORE_REG_DIEAR = 82
|
||||
UC_TRICORE_REG_DIETR = 83
|
||||
UC_TRICORE_REG_CCDIER = 84
|
||||
UC_TRICORE_REG_MIECON = 85
|
||||
UC_TRICORE_REG_PIEAR = 86
|
||||
UC_TRICORE_REG_PIETR = 87
|
||||
UC_TRICORE_REG_CCPIER = 88
|
||||
UC_TRICORE_REG_DBGSR = 89
|
||||
UC_TRICORE_REG_EXEVT = 90
|
||||
UC_TRICORE_REG_CREVT = 91
|
||||
UC_TRICORE_REG_SWEVT = 92
|
||||
UC_TRICORE_REG_TR0EVT = 93
|
||||
UC_TRICORE_REG_TR1EVT = 94
|
||||
UC_TRICORE_REG_DMS = 95
|
||||
UC_TRICORE_REG_DCX = 96
|
||||
UC_TRICORE_REG_DBGTCR = 97
|
||||
UC_TRICORE_REG_CCTRL = 98
|
||||
UC_TRICORE_REG_CCNT = 99
|
||||
UC_TRICORE_REG_ICNT = 100
|
||||
UC_TRICORE_REG_M1CNT = 101
|
||||
UC_TRICORE_REG_M2CNT = 102
|
||||
UC_TRICORE_REG_M3CNT = 103
|
||||
UC_TRICORE_REG_ENDING = 104
|
||||
UC_TRICORE_REG_GA0 = 1
|
||||
UC_TRICORE_REG_GA1 = 2
|
||||
UC_TRICORE_REG_GA8 = 9
|
||||
UC_TRICORE_REG_GA9 = 10
|
||||
UC_TRICORE_REG_SP = 11
|
||||
UC_TRICORE_REG_LR = 12
|
||||
UC_TRICORE_REG_IA = 16
|
||||
UC_TRICORE_REG_ID = 32
|
||||
end
|
@ -6,13 +6,13 @@ module UnicornEngine
|
||||
UC_API_MINOR = 0
|
||||
|
||||
UC_API_PATCH = 0
|
||||
UC_API_EXTRA = 7
|
||||
UC_API_EXTRA = 255
|
||||
UC_VERSION_MAJOR = 2
|
||||
|
||||
UC_VERSION_MINOR = 0
|
||||
|
||||
UC_VERSION_PATCH = 0
|
||||
UC_VERSION_EXTRA = 7
|
||||
UC_VERSION_EXTRA = 255
|
||||
UC_SECOND_SCALE = 1000000
|
||||
UC_MILISECOND_SCALE = 1000
|
||||
UC_ARCH_ARM = 1
|
||||
@ -24,7 +24,8 @@ module UnicornEngine
|
||||
UC_ARCH_M68K = 7
|
||||
UC_ARCH_RISCV = 8
|
||||
UC_ARCH_S390X = 9
|
||||
UC_ARCH_MAX = 10
|
||||
UC_ARCH_TRICORE = 10
|
||||
UC_ARCH_MAX = 11
|
||||
|
||||
UC_MODE_LITTLE_ENDIAN = 0
|
||||
UC_MODE_BIG_ENDIAN = 1073741824
|
||||
@ -33,7 +34,7 @@ module UnicornEngine
|
||||
UC_MODE_THUMB = 16
|
||||
UC_MODE_MCLASS = 32
|
||||
UC_MODE_V8 = 64
|
||||
UC_MODE_ARMBE8 = 128
|
||||
UC_MODE_ARMBE8 = 1024
|
||||
UC_MODE_ARM926 = 128
|
||||
UC_MODE_ARM946 = 256
|
||||
UC_MODE_ARM1176 = 512
|
||||
@ -134,6 +135,7 @@ module UnicornEngine
|
||||
UC_CTL_CPU_MODEL = 7
|
||||
UC_CTL_TB_REQUEST_CACHE = 8
|
||||
UC_CTL_TB_REMOVE_CACHE = 9
|
||||
UC_CTL_TB_FLUSH = 10
|
||||
|
||||
UC_PROT_NONE = 0
|
||||
UC_PROT_READ = 1
|
||||
|
@ -1,3 +1,3 @@
|
||||
module Unicorn
|
||||
VERSION = "1.0.1"
|
||||
VERSION = "2.0.0"
|
||||
end
|
||||
|
@ -12,7 +12,7 @@ fn main() {
|
||||
let arm_code32: Vec<u8> = vec![0x17, 0x00, 0x40, 0xe2]; // sub r0, #23
|
||||
|
||||
let mut unicorn = Unicorn::new(Arch::ARM, Mode::LITTLE_ENDIAN).expect("failed to initialize Unicorn instance");
|
||||
let mut emu = unicorn.borrow();
|
||||
let emu = &mut unicorn;
|
||||
emu.mem_map(0x1000, 0x4000, Permission::ALL).expect("failed to map code page");
|
||||
emu.mem_write(0x1000, &arm_code32).expect("failed to write instructions");
|
||||
|
||||
@ -20,11 +20,11 @@ fn main() {
|
||||
emu.reg_write(RegisterARM::R5, 1337).expect("failed write R5");
|
||||
|
||||
let _ = emu.emu_start(0x1000, (0x1000 + arm_code32.len()) as u64, 10 * SECOND_SCALE, 1000);
|
||||
assert_eq!(emu.reg_read(RegisterARM::R0, Ok(100));
|
||||
assert_eq!(emu.reg_read(RegisterARM::R5, Ok(1337));
|
||||
assert_eq!(emu.reg_read(RegisterARM::R0), Ok(100));
|
||||
assert_eq!(emu.reg_read(RegisterARM::R5), Ok(1337));
|
||||
}
|
||||
```
|
||||
Further sample code can be found in ```tests/unicorn.rs```.
|
||||
Further sample code can be found in [tests](../../tests/rust-tests/main.rs).
|
||||
|
||||
## Usage
|
||||
|
||||
@ -32,7 +32,7 @@ Add this to your `Cargo.toml`:
|
||||
|
||||
```
|
||||
[dependencies]
|
||||
unicorn-engine = "2.0.0-rc3"
|
||||
unicorn-engine = "2.0.0"
|
||||
```
|
||||
|
||||
## Acknowledgements
|
||||
|
@ -1,23 +1,16 @@
|
||||
#[cfg(feature = "use_system_unicorn")]
|
||||
use pkg_config;
|
||||
#[cfg(feature = "build_unicorn_cmake")]
|
||||
use std::env;
|
||||
#[cfg(feature = "build_unicorn_cmake")]
|
||||
use std::path::PathBuf;
|
||||
#[cfg(feature = "build_unicorn_cmake")]
|
||||
use std::process::Command;
|
||||
|
||||
#[cfg(all(feature = "build_unicorn_cmake"))]
|
||||
fn ninja_available() -> bool {
|
||||
Command::new("ninja").arg("--version").spawn().is_ok()
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "build_unicorn_cmake"))]
|
||||
fn msvc_cmake_tools_available() -> bool {
|
||||
Command::new("cmake").arg("--version").spawn().is_ok() && ninja_available()
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "build_unicorn_cmake"))]
|
||||
fn setup_env_msvc(compiler: &cc::Tool) {
|
||||
// If PATH already contains what we need, skip this
|
||||
if msvc_cmake_tools_available() {
|
||||
@ -27,20 +20,24 @@ fn setup_env_msvc(compiler: &cc::Tool) {
|
||||
let target = env::var("TARGET").unwrap();
|
||||
let devenv = cc::windows_registry::find_tool(target.as_str(), "devenv");
|
||||
let tool_root: PathBuf = match devenv {
|
||||
Some(devenv_tool) => {
|
||||
devenv_tool.path().parent().unwrap().to_path_buf()
|
||||
},
|
||||
Some(devenv_tool) => devenv_tool.path().parent().unwrap().to_path_buf(),
|
||||
None => {
|
||||
// if devenv (i.e. Visual Studio) was not found, assume compiler is
|
||||
// from standalone Build Tools and look there instead.
|
||||
// this should be done properly in cc crate, but for now it's not.
|
||||
let tools_name = std::ffi::OsStr::new("BuildTools");
|
||||
let compiler_path = compiler.path().to_path_buf();
|
||||
compiler_path.iter().find(|x| *x == tools_name)
|
||||
compiler_path
|
||||
.iter()
|
||||
.find(|x| *x == tools_name)
|
||||
.expect("Failed to find devenv or Build Tools");
|
||||
compiler_path.iter().take_while(|x| *x != tools_name)
|
||||
.collect::<PathBuf>().join(tools_name).join(r"Common7\IDE")
|
||||
},
|
||||
compiler_path
|
||||
.iter()
|
||||
.take_while(|x| *x != tools_name)
|
||||
.collect::<PathBuf>()
|
||||
.join(tools_name)
|
||||
.join(r"Common7\IDE")
|
||||
}
|
||||
};
|
||||
let cmake_pkg_dir = tool_root.join(r"CommonExtensions\Microsoft\CMake");
|
||||
let cmake_path = cmake_pkg_dir.join(r"CMake\bin\cmake.exe");
|
||||
@ -63,7 +60,6 @@ fn setup_env_msvc(compiler: &cc::Tool) {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "build_unicorn_cmake")]
|
||||
fn build_with_cmake() {
|
||||
let uc_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||
let compiler = cc::Build::new().get_compiler();
|
||||
@ -92,14 +88,22 @@ fn build_with_cmake() {
|
||||
// unicorn's CMakeLists.txt doesn't properly support 'install', so we use
|
||||
// the build artifacts from the build directory, which cmake crate sets
|
||||
// to "<out_dir>/build/"
|
||||
let dst = config.define("BUILD_SHARED_LIBS", "OFF")
|
||||
let dst = config
|
||||
.define("UNICORN_BUILD_TESTS", "OFF")
|
||||
.define("UNICORN_INSTALL", "OFF")
|
||||
.no_build_target(true).build();
|
||||
println!("cargo:rustc-link-search=native={}", dst.join("build").display());
|
||||
.no_build_target(true)
|
||||
.build();
|
||||
println!(
|
||||
"cargo:rustc-link-search=native={}",
|
||||
dst.join("build").display()
|
||||
);
|
||||
|
||||
// Lazymio(@wtdcode): Why do I stick to static link? See: https://github.com/rust-lang/cargo/issues/5077
|
||||
println!("cargo:rustc-link-lib=static=unicorn");
|
||||
// Lazymio(@wtdcode): Dynamic link may break. See: https://github.com/rust-lang/cargo/issues/5077
|
||||
if cfg!(feature = "dynamic_linkage") {
|
||||
println!("cargo:rustc-link-lib=dylib=unicorn");
|
||||
} else {
|
||||
println!("cargo:rustc-link-lib=static=unicorn");
|
||||
}
|
||||
if !compiler.is_like_msvc() {
|
||||
println!("cargo:rustc-link-lib=pthread");
|
||||
println!("cargo:rustc-link-lib=m");
|
||||
@ -107,14 +111,26 @@ fn build_with_cmake() {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if cfg!(feature = "use_system_unicorn") {
|
||||
#[cfg(feature = "use_system_unicorn")]
|
||||
pkg_config::Config::new()
|
||||
.atleast_version("2")
|
||||
.probe("unicorn")
|
||||
.expect("Could not find system unicorn2");
|
||||
} else {
|
||||
#[cfg(feature = "build_unicorn_cmake")]
|
||||
build_with_cmake();
|
||||
}
|
||||
match pkg_config::Config::new()
|
||||
.atleast_version("2")
|
||||
.cargo_metadata(false)
|
||||
.probe("unicorn")
|
||||
{
|
||||
Ok(lib) => {
|
||||
for dir in lib.link_paths {
|
||||
println!("cargo:rustc-link-search=native={}", dir.to_str().unwrap());
|
||||
}
|
||||
if cfg!(feature = "dynamic_linkage") {
|
||||
println!("cargo:rustc-link-lib=dylib=unicorn");
|
||||
} else {
|
||||
println!("cargo:rustc-link-arg=-Wl,-allow-multiple-definition");
|
||||
println!("cargo:rustc-link-lib=static=unicorn");
|
||||
println!("cargo:rustc-link-lib=pthread");
|
||||
println!("cargo:rustc-link-lib=m");
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
build_with_cmake();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -305,14 +305,14 @@ pub enum RegisterARM64 {
|
||||
VBAR_EL3 = 289,
|
||||
CP_REG = 290,
|
||||
ENDING = 291,
|
||||
}
|
||||
|
||||
impl RegisterARM64 {
|
||||
// alias registers
|
||||
// (assoc) IP0 = 215,
|
||||
// (assoc) IP1 = 216,
|
||||
// (assoc) FP = 1,
|
||||
// (assoc) LR = 2,
|
||||
}
|
||||
|
||||
impl RegisterARM64 {
|
||||
pub const IP0: RegisterARM64 = RegisterARM64::X16;
|
||||
pub const IP1: RegisterARM64 = RegisterARM64::X17;
|
||||
pub const FP: RegisterARM64 = RegisterARM64::X29;
|
||||
|
@ -188,10 +188,7 @@ pub extern "C" fn insn_in_hook_proxy<D, F>(
|
||||
(user_data.callback)(&mut user_data.uc, port, size);
|
||||
}
|
||||
|
||||
pub extern "C" fn insn_invalid_hook_proxy<D, F>(
|
||||
uc: uc_handle,
|
||||
user_data: *mut UcHook<D, F>,
|
||||
) -> bool
|
||||
pub extern "C" fn insn_invalid_hook_proxy<D, F>(uc: uc_handle, user_data: *mut UcHook<D, F>) -> bool
|
||||
where
|
||||
F: FnMut(&mut crate::Unicorn<D>) -> bool,
|
||||
{
|
||||
|
@ -42,11 +42,12 @@ mod ppc;
|
||||
mod riscv;
|
||||
mod s390x;
|
||||
mod sparc;
|
||||
mod tricore;
|
||||
mod x86;
|
||||
|
||||
pub use crate::{
|
||||
arm::*, arm64::*, m68k::*, mips::*, ppc::*, riscv::*, s390x::*, sparc::*, unicorn_const::*,
|
||||
x86::*,
|
||||
arm::*, arm64::*, m68k::*, mips::*, ppc::*, riscv::*, s390x::*, sparc::*, tricore::*,
|
||||
unicorn_const::*, x86::*,
|
||||
};
|
||||
|
||||
use alloc::{boxed::Box, rc::Rc, vec::Vec};
|
||||
@ -544,7 +545,6 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
///
|
||||
/// This adds safe support for registers >64 bit (GDTR/IDTR, XMM, YMM, ZMM, ST (x86); Q, V (arm64)).
|
||||
pub fn reg_read_long<T: Into<i32>>(&self, regid: T) -> Result<Box<[u8]>, uc_error> {
|
||||
let err: uc_error;
|
||||
let boxed: Box<[u8]>;
|
||||
let mut value: Vec<u8>;
|
||||
let curr_reg_id = regid.into();
|
||||
@ -586,7 +586,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
return Err(uc_error::ARCH);
|
||||
}
|
||||
|
||||
err = unsafe { ffi::uc_reg_read(self.get_handle(), curr_reg_id, value.as_mut_ptr() as _) };
|
||||
let err: uc_error = unsafe { ffi::uc_reg_read(self.get_handle(), curr_reg_id, value.as_mut_ptr() as _) };
|
||||
|
||||
if err == uc_error::OK {
|
||||
boxed = value.into_boxed_slice();
|
||||
@ -900,15 +900,13 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
///
|
||||
/// `hook` is the value returned by `add_*_hook` functions.
|
||||
pub fn remove_hook(&mut self, hook: ffi::uc_hook) -> Result<(), uc_error> {
|
||||
let err: uc_error;
|
||||
|
||||
// drop the hook
|
||||
let inner = self.inner_mut();
|
||||
inner
|
||||
.hooks
|
||||
.retain(|(hook_ptr, _hook_impl)| hook_ptr != &hook);
|
||||
|
||||
err = unsafe { ffi::uc_hook_del(inner.handle, hook) };
|
||||
let err: uc_error = unsafe { ffi::uc_hook_del(inner.handle, hook) };
|
||||
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
@ -1041,6 +1039,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
Arch::PPC => RegisterPPC::PC as i32,
|
||||
Arch::RISCV => RegisterRISCV::PC as i32,
|
||||
Arch::S390X => RegisterS390X::PC as i32,
|
||||
Arch::TRICORE => RegisterTRICORE::PC as i32,
|
||||
Arch::MAX => panic!("Illegal Arch specified"),
|
||||
};
|
||||
self.reg_read(reg)
|
||||
@ -1060,6 +1059,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
Arch::PPC => RegisterPPC::PC as i32,
|
||||
Arch::RISCV => RegisterRISCV::PC as i32,
|
||||
Arch::S390X => RegisterS390X::PC as i32,
|
||||
Arch::TRICORE => RegisterTRICORE::PC as i32,
|
||||
Arch::MAX => panic!("Illegal Arch specified"),
|
||||
};
|
||||
self.reg_write(reg, value)
|
||||
|
137
bindings/rust/src/tricore.rs
Normal file
137
bindings/rust/src/tricore.rs
Normal file
@ -0,0 +1,137 @@
|
||||
// TRICORE registers
|
||||
#[repr(C)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum RegisterTRICORE {
|
||||
INVALID = 0,
|
||||
A0 = 1,
|
||||
A1 = 2,
|
||||
A2 = 3,
|
||||
A3 = 4,
|
||||
A4 = 5,
|
||||
A5 = 6,
|
||||
A6 = 7,
|
||||
A7 = 8,
|
||||
A8 = 9,
|
||||
A9 = 10,
|
||||
A10 = 11,
|
||||
A11 = 12,
|
||||
A12 = 13,
|
||||
A13 = 14,
|
||||
A14 = 15,
|
||||
A15 = 16,
|
||||
D0 = 17,
|
||||
D1 = 18,
|
||||
D2 = 19,
|
||||
D3 = 20,
|
||||
D4 = 21,
|
||||
D5 = 22,
|
||||
D6 = 23,
|
||||
D7 = 24,
|
||||
D8 = 25,
|
||||
D9 = 26,
|
||||
D10 = 27,
|
||||
D11 = 28,
|
||||
D12 = 29,
|
||||
D13 = 30,
|
||||
D14 = 31,
|
||||
D15 = 32,
|
||||
PCXI = 33,
|
||||
PSW = 34,
|
||||
PSW_USB_C = 35,
|
||||
PSW_USB_V = 36,
|
||||
PSW_USB_SV = 37,
|
||||
PSW_USB_AV = 38,
|
||||
PSW_USB_SAV = 39,
|
||||
PC = 40,
|
||||
SYSCON = 41,
|
||||
CPU_ID = 42,
|
||||
BIV = 43,
|
||||
BTV = 44,
|
||||
ISP = 45,
|
||||
ICR = 46,
|
||||
FCX = 47,
|
||||
LCX = 48,
|
||||
COMPAT = 49,
|
||||
DPR0_U = 50,
|
||||
DPR1_U = 51,
|
||||
DPR2_U = 52,
|
||||
DPR3_U = 53,
|
||||
DPR0_L = 54,
|
||||
DPR1_L = 55,
|
||||
DPR2_L = 56,
|
||||
DPR3_L = 57,
|
||||
CPR0_U = 58,
|
||||
CPR1_U = 59,
|
||||
CPR2_U = 60,
|
||||
CPR3_U = 61,
|
||||
CPR0_L = 62,
|
||||
CPR1_L = 63,
|
||||
CPR2_L = 64,
|
||||
CPR3_L = 65,
|
||||
DPM0 = 66,
|
||||
DPM1 = 67,
|
||||
DPM2 = 68,
|
||||
DPM3 = 69,
|
||||
CPM0 = 70,
|
||||
CPM1 = 71,
|
||||
CPM2 = 72,
|
||||
CPM3 = 73,
|
||||
MMU_CON = 74,
|
||||
MMU_ASI = 75,
|
||||
MMU_TVA = 76,
|
||||
MMU_TPA = 77,
|
||||
MMU_TPX = 78,
|
||||
MMU_TFA = 79,
|
||||
BMACON = 80,
|
||||
SMACON = 81,
|
||||
DIEAR = 82,
|
||||
DIETR = 83,
|
||||
CCDIER = 84,
|
||||
MIECON = 85,
|
||||
PIEAR = 86,
|
||||
PIETR = 87,
|
||||
CCPIER = 88,
|
||||
DBGSR = 89,
|
||||
EXEVT = 90,
|
||||
CREVT = 91,
|
||||
SWEVT = 92,
|
||||
TR0EVT = 93,
|
||||
TR1EVT = 94,
|
||||
DMS = 95,
|
||||
DCX = 96,
|
||||
DBGTCR = 97,
|
||||
CCTRL = 98,
|
||||
CCNT = 99,
|
||||
ICNT = 100,
|
||||
M1CNT = 101,
|
||||
M2CNT = 102,
|
||||
M3CNT = 103,
|
||||
ENDING = 104,
|
||||
}
|
||||
|
||||
impl RegisterTRICORE {
|
||||
// alias registers
|
||||
// (assoc) GA0 = 1,
|
||||
// (assoc) GA1 = 2,
|
||||
// (assoc) GA8 = 9,
|
||||
// (assoc) GA9 = 10,
|
||||
// (assoc) SP = 11,
|
||||
// (assoc) LR = 12,
|
||||
// (assoc) IA = 16,
|
||||
// (assoc) ID = 32,
|
||||
pub const GA0: RegisterTRICORE = RegisterTRICORE::A0;
|
||||
pub const GA1: RegisterTRICORE = RegisterTRICORE::A1;
|
||||
pub const GA8: RegisterTRICORE = RegisterTRICORE::A8;
|
||||
pub const GA9: RegisterTRICORE = RegisterTRICORE::A9;
|
||||
pub const SP: RegisterTRICORE = RegisterTRICORE::A10;
|
||||
pub const LR: RegisterTRICORE = RegisterTRICORE::A11;
|
||||
pub const IA: RegisterTRICORE = RegisterTRICORE::A15;
|
||||
pub const ID: RegisterTRICORE = RegisterTRICORE::D15;
|
||||
}
|
||||
|
||||
impl From<RegisterTRICORE> for i32 {
|
||||
fn from(r: RegisterTRICORE) -> Self {
|
||||
r as i32
|
||||
}
|
||||
}
|
@ -5,7 +5,8 @@ pub const API_MAJOR: u64 = 2;
|
||||
pub const API_MINOR: u64 = 0;
|
||||
pub const VERSION_MAJOR: u64 = 2;
|
||||
pub const VERSION_MINOR: u64 = 0;
|
||||
pub const VERSION_EXTRA: u64 = 6;
|
||||
pub const VERSION_PATCH: u64 = 0;
|
||||
pub const VERSION_EXTRA: u64 = 7;
|
||||
pub const SECOND_SCALE: u64 = 1_000_000;
|
||||
pub const MILISECOND_SCALE: u64 = 1_000;
|
||||
|
||||
@ -129,7 +130,8 @@ pub enum Arch {
|
||||
M68K = 7,
|
||||
RISCV = 8,
|
||||
S390X = 9,
|
||||
MAX = 10,
|
||||
TRICORE = 10,
|
||||
MAX = 11,
|
||||
}
|
||||
|
||||
impl TryFrom<usize> for Arch {
|
||||
@ -146,6 +148,7 @@ impl TryFrom<usize> for Arch {
|
||||
x if x == Self::M68K as usize => Ok(Self::M68K),
|
||||
x if x == Self::RISCV as usize => Ok(Self::RISCV),
|
||||
x if x == Self::S390X as usize => Ok(Self::S390X),
|
||||
x if x == Self::TRICORE as usize => Ok(Self::TRICORE),
|
||||
x if x == Self::MAX as usize => Ok(Self::MAX),
|
||||
_ => Err(uc_error::ARCH),
|
||||
}
|
||||
@ -162,8 +165,8 @@ bitflags! {
|
||||
const THUMB = 0x10;
|
||||
const MCLASS = 0x20;
|
||||
const V8 = 0x40;
|
||||
const ARMBE8 = 0x80;
|
||||
const ARM926 = Self::ARMBE8.bits;
|
||||
const ARMBE8 = 0x400;
|
||||
const ARM926 = 0x80;
|
||||
const ARM946 = 0x100;
|
||||
const ARM1176 = 0x200;
|
||||
const MICRO = Self::THUMB.bits;
|
||||
|
@ -1,5 +1,5 @@
|
||||
# https://cristianadam.eu/20190501/bundling-together-static-libraries-with-cmake/
|
||||
function(bundle_static_library tgt_name bundled_tgt_name)
|
||||
function(bundle_static_library tgt_name bundled_tgt_name library_name)
|
||||
list(APPEND static_libs ${tgt_name})
|
||||
set(dep_libs "")
|
||||
|
||||
@ -41,10 +41,10 @@ function(bundle_static_library tgt_name bundled_tgt_name)
|
||||
list(REMOVE_DUPLICATES dep_libs)
|
||||
|
||||
set(bundled_tgt_full_name
|
||||
${CMAKE_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${bundled_tgt_name}${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
${CMAKE_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${library_name}${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
|
||||
if (APPLE)
|
||||
find_program(lib_tool libtool)
|
||||
find_program(lib_tool libtool REQUIRED)
|
||||
|
||||
foreach(tgt IN LISTS static_libs)
|
||||
list(APPEND static_libs_full_names $<TARGET_FILE:${tgt}>)
|
||||
@ -55,7 +55,7 @@ function(bundle_static_library tgt_name bundled_tgt_name)
|
||||
OUTPUT ${bundled_tgt_full_name}
|
||||
COMMENT "Bundling ${bundled_tgt_name}"
|
||||
VERBATIM)
|
||||
elseif(UNIX)
|
||||
elseif(UNIX OR MINGW)
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/${bundled_tgt_name}.ar.in
|
||||
"CREATE ${bundled_tgt_full_name}\n" )
|
||||
|
||||
@ -82,7 +82,10 @@ function(bundle_static_library tgt_name bundled_tgt_name)
|
||||
COMMENT "Bundling ${bundled_tgt_name}"
|
||||
VERBATIM)
|
||||
elseif(WIN32)
|
||||
find_program(lib_tool lib)
|
||||
# https://stackoverflow.com/a/38096930/1806760
|
||||
get_filename_component(vs_bin_path "${CMAKE_LINKER}" DIRECTORY)
|
||||
|
||||
find_program(lib_tool lib HINTS "${vs_bin_path}" REQUIRED)
|
||||
|
||||
foreach(tgt IN LISTS static_libs)
|
||||
list(APPEND static_libs_full_names $<TARGET_FILE:${tgt}>)
|
||||
|
@ -1,6 +1,6 @@
|
||||
This HOWTO introduces how to build Unicorn2 natively on Linux/Mac/Windows or cross-build to Windows from Linux host.
|
||||
|
||||
Note: Please run `make clean` before you switch to `dev` branch.
|
||||
Note: By default, CMake will build both the shared and static libraries while only static libraries are built if unicorn is used as a Cmake subdirectory. In most cases, you don't need to care about which kind of library to build. ONLY use `BUILD_SHARED_LIBS=no`if you know what you are doing.
|
||||
|
||||
## Native build on Linux/macOS
|
||||
|
||||
|
26
docs/FAQ.md
26
docs/FAQ.md
@ -5,7 +5,7 @@ Typically, it’s due to
|
||||
- Instrumenting every instruction executed.
|
||||
- Instrumenting every memory access.
|
||||
|
||||
Optimize your program with less instrumentation.
|
||||
Optimize your program with less instrumentation, e.g. by using `UC_HOOK_BLOCK` instead of `UC_HOOK_CODE`
|
||||
|
||||
## Why do I get a wrong PC after emulation stops?
|
||||
|
||||
@ -26,6 +26,7 @@ On x86, all available instructions are: `in` `out` `syscall` `sysenter` `cpuid`.
|
||||
1. Some instructions are not enabled by default on some architectures. For example, you have to setup CSR on RISC-V or VFP on ARM before emulating floating-point instructions. Refer to the corresponding manual to check if you leave out possible switches in special registers.
|
||||
2. If you are on ARM, please check whether you are emulating a THUMB instruction. If so, please use `UC_MODE_THUMB` and make sure the starting address is odd.
|
||||
3. If either is not the case, it might be some newer instruction sets that qemu5 doesn’t support.
|
||||
4. Note some instruction sets are not implemented by QEMU.
|
||||
|
||||
If you are still using Unicorn1, please upgrade to Unicorn2 for better support.
|
||||
|
||||
@ -37,6 +38,29 @@ It is due to the fact that, if users return `true` without memory mapping set up
|
||||
|
||||
See the [sample](https://github.com/unicorn-engine/unicorn/blob/c05fbb7e63aed0b60fc2888e08beceb17bce8ac4/samples/sample_x86.c#L1379-L1393) for details.
|
||||
|
||||
## My MIPS emulation gets weird read/write error and CPU exceptions.
|
||||
|
||||
Note you might have an address that falls in MIPS `kseg` segments. In that case, MMU is bypassed and you have to make sure the corresponding physical memory is mapped. See [#217](https://github.com/unicorn-engine/unicorn/issues/217), [#1371](https://github.com/unicorn-engine/unicorn/issues/1371), [#1550](https://github.com/unicorn-engine/unicorn/issues/1371).
|
||||
|
||||
## KeyboardInterrupt is not raised during `uc.emu_start`
|
||||
|
||||
This is intended as python [signal module](https://docs.python.org/3.10/library/signal.html) states:
|
||||
|
||||
> A long-running calculation implemented purely in C (such as regular expression matching on a large body of text) may run uninterrupted for an arbitrary amount of time, regardless of any signals received. The Python signal handlers will be called when the calculation finishes.
|
||||
|
||||
A workaround is to start emulation in another thread.
|
||||
|
||||
## Editing an instruction doesn't take effect/Hooks added during emulation are not called.
|
||||
|
||||
Unicorn is a fork of QEMU and inherits most QEMU internal mechanisms, one of which is called TB chaining. In short, every block (in most cases, a `basic block`) is translated, executed and __cached__. Therefore, any operation on cached addresses won't immediately take effect without a call to `uc_ctl_remove_cache`. Check a more detailed discussion here: [#1561](https://github.com/unicorn-engine/unicorn/issues/1561)
|
||||
|
||||
Note, this doesn't mean you have to care about Self Modifying Code because the read/write happens within emulation (TB execution) and QEMU would handle such special cases. For technical details, refer to the [QEMU paper](https://www.usenix.org/legacy/event/usenix05/tech/freenix/full_papers/bellard/bellard.pdf).
|
||||
|
||||
TLDR: To ensure any modification to an address will take effect:
|
||||
|
||||
1. Call `uc_ctl_remove_cache` on the target address.
|
||||
2. Call `uc_reg_write` to write current PC to the PC register, if the modification happens during emulation. It restarts emulation (but doesn't quit `uc_emu_start`) on current address to re-translate the block.
|
||||
|
||||
## How to emulate interrupts (or ticks) with Unicorn?
|
||||
|
||||
As stated, Unicorn is a pure CPU emulator. For such emulation, you have two choices:
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "qemu.h"
|
||||
#include "qemu/xxhash.h"
|
||||
#include "unicorn/unicorn.h"
|
||||
#include "list.h"
|
||||
|
||||
@ -33,6 +34,7 @@
|
||||
#define UC_MODE_RISCV_MASK \
|
||||
(UC_MODE_RISCV32 | UC_MODE_RISCV64 | UC_MODE_LITTLE_ENDIAN)
|
||||
#define UC_MODE_S390X_MASK (UC_MODE_BIG_ENDIAN)
|
||||
#define UC_MODE_TRICORE_MASK (UC_MODE_LITTLE_ENDIAN)
|
||||
|
||||
#define ARR_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
@ -92,6 +94,8 @@ typedef void (*uc_args_uc_long_t)(struct uc_struct *, unsigned long);
|
||||
|
||||
typedef void (*uc_args_uc_u64_t)(struct uc_struct *, uint64_t addr);
|
||||
|
||||
typedef uint64_t (*uc_get_pc_t)(struct uc_struct *);
|
||||
|
||||
typedef MemoryRegion *(*uc_args_uc_ram_size_t)(struct uc_struct *, hwaddr begin,
|
||||
size_t size, uint32_t perms);
|
||||
|
||||
@ -139,6 +143,9 @@ typedef void (*uc_invalidate_tb_t)(struct uc_struct *uc, uint64_t start,
|
||||
// Request generating TB at given address
|
||||
typedef uc_err (*uc_gen_tb_t)(struct uc_struct *uc, uint64_t pc, uc_tb *out_tb);
|
||||
|
||||
// tb flush
|
||||
typedef uc_tcg_flush_tlb uc_tb_flush_t;
|
||||
|
||||
struct hook {
|
||||
int type; // UC_HOOK_*
|
||||
int insn; // instruction for HOOK_INSN
|
||||
@ -151,6 +158,7 @@ struct hook {
|
||||
// address (depends on hook type)
|
||||
void *callback; // a uc_cb_* type
|
||||
void *user_data;
|
||||
GHashTable *hooked_regions; // The regions this hook instrumented on
|
||||
};
|
||||
|
||||
// Add an inline hook to helper_table
|
||||
@ -254,6 +262,7 @@ struct uc_struct {
|
||||
uc_read_mem_t read_mem;
|
||||
uc_args_void_t release; // release resource when uc_close()
|
||||
uc_args_uc_u64_t set_pc; // set PC for tracecode
|
||||
uc_get_pc_t get_pc;
|
||||
uc_args_int_t
|
||||
stop_interrupt; // check if the interrupt should stop emulation
|
||||
uc_memory_map_io_t memory_map_io;
|
||||
@ -272,6 +281,7 @@ struct uc_struct {
|
||||
uc_tcg_flush_tlb tcg_flush_tlb;
|
||||
uc_invalidate_tb_t uc_invalidate_tb;
|
||||
uc_gen_tb_t uc_gen_tb;
|
||||
uc_tb_flush_t tb_flush;
|
||||
uc_add_inline_hook_t add_inline_hook;
|
||||
uc_del_inline_hook_t del_inline_hook;
|
||||
|
||||
@ -406,6 +416,62 @@ static inline int uc_addr_is_exit(uc_engine *uc, uint64_t addr)
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct HookedRegion {
|
||||
uint64_t start;
|
||||
uint64_t length;
|
||||
} HookedRegion;
|
||||
|
||||
// hooked_regions related functions
|
||||
static inline guint hooked_regions_hash(const void *p)
|
||||
{
|
||||
HookedRegion *region = (HookedRegion *)p;
|
||||
|
||||
return qemu_xxhash4(region->start, region->length);
|
||||
}
|
||||
|
||||
static inline gboolean hooked_regions_equal(const void *lhs, const void *rhs)
|
||||
{
|
||||
HookedRegion *l = (HookedRegion *)lhs;
|
||||
HookedRegion *r = (HookedRegion *)rhs;
|
||||
|
||||
return l->start == r->start && l->length == r->length;
|
||||
}
|
||||
|
||||
static inline void hooked_regions_add(struct hook *h, uint64_t start,
|
||||
uint64_t length)
|
||||
{
|
||||
HookedRegion tmp;
|
||||
tmp.start = start;
|
||||
tmp.length = length;
|
||||
|
||||
if (!g_hash_table_lookup(h->hooked_regions, (void *)&tmp)) {
|
||||
HookedRegion *r = malloc(sizeof(HookedRegion));
|
||||
r->start = start;
|
||||
r->length = length;
|
||||
g_hash_table_insert(h->hooked_regions, (void *)r, (void *)1);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void hooked_regions_check_single(struct list_item *cur,
|
||||
uint64_t start, uint64_t length)
|
||||
{
|
||||
while (cur != NULL) {
|
||||
if (HOOK_BOUND_CHECK((struct hook *)cur->data, start)) {
|
||||
hooked_regions_add((struct hook *)cur->data, start, length);
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void hooked_regions_check(uc_engine *uc, uint64_t start,
|
||||
uint64_t length)
|
||||
{
|
||||
// Only UC_HOOK_BLOCK and UC_HOOK_CODE might be wrongle cached!
|
||||
hooked_regions_check_single(uc->hook[UC_HOOK_CODE_IDX].head, start, length);
|
||||
hooked_regions_check_single(uc->hook[UC_HOOK_BLOCK_IDX].head, start,
|
||||
length);
|
||||
}
|
||||
|
||||
#ifdef UNICORN_TRACER
|
||||
#define UC_TRACE_START(loc) trace_start(get_tracer(), loc)
|
||||
#define UC_TRACE_END(loc, fmt, ...) \
|
||||
|
174
include/unicorn/tricore.h
Normal file
174
include/unicorn/tricore.h
Normal file
@ -0,0 +1,174 @@
|
||||
/* This file is released under LGPL2.
|
||||
See COPYING.LGPL2 in root directory for more details
|
||||
*/
|
||||
|
||||
/*
|
||||
Created for Unicorn Engine by Eric Poole <eric.poole@aptiv.com>, 2022
|
||||
Copyright 2022 Aptiv
|
||||
*/
|
||||
|
||||
#ifndef UNICORN_TRICORE_H
|
||||
#define UNICORN_TRICORE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4201)
|
||||
#endif
|
||||
|
||||
//> TRICORE CPU
|
||||
typedef enum uc_cpu_tricore {
|
||||
UC_CPU_TRICORE_TC1796,
|
||||
UC_CPU_TRICORE_TC1797,
|
||||
UC_CPU_TRICORE_TC27X,
|
||||
|
||||
UC_CPU_TRICORE_ENDING
|
||||
} uc_cpu_tricore;
|
||||
|
||||
//> TRICORE registers
|
||||
typedef enum uc_tricore_reg {
|
||||
UC_TRICORE_REG_INVALID = 0,
|
||||
|
||||
// General purpose registers (GPR)
|
||||
// Address GPR
|
||||
UC_TRICORE_REG_A0,
|
||||
UC_TRICORE_REG_A1,
|
||||
UC_TRICORE_REG_A2,
|
||||
UC_TRICORE_REG_A3,
|
||||
UC_TRICORE_REG_A4,
|
||||
UC_TRICORE_REG_A5,
|
||||
UC_TRICORE_REG_A6,
|
||||
UC_TRICORE_REG_A7,
|
||||
UC_TRICORE_REG_A8,
|
||||
UC_TRICORE_REG_A9,
|
||||
UC_TRICORE_REG_A10,
|
||||
UC_TRICORE_REG_A11,
|
||||
UC_TRICORE_REG_A12,
|
||||
UC_TRICORE_REG_A13,
|
||||
UC_TRICORE_REG_A14,
|
||||
UC_TRICORE_REG_A15,
|
||||
// Data GPR
|
||||
UC_TRICORE_REG_D0,
|
||||
UC_TRICORE_REG_D1,
|
||||
UC_TRICORE_REG_D2,
|
||||
UC_TRICORE_REG_D3,
|
||||
UC_TRICORE_REG_D4,
|
||||
UC_TRICORE_REG_D5,
|
||||
UC_TRICORE_REG_D6,
|
||||
UC_TRICORE_REG_D7,
|
||||
UC_TRICORE_REG_D8,
|
||||
UC_TRICORE_REG_D9,
|
||||
UC_TRICORE_REG_D10,
|
||||
UC_TRICORE_REG_D11,
|
||||
UC_TRICORE_REG_D12,
|
||||
UC_TRICORE_REG_D13,
|
||||
UC_TRICORE_REG_D14,
|
||||
UC_TRICORE_REG_D15,
|
||||
|
||||
/* CSFR Register */
|
||||
UC_TRICORE_REG_PCXI,
|
||||
|
||||
UC_TRICORE_REG_PSW,
|
||||
|
||||
/* PSW flag cache for faster execution */
|
||||
UC_TRICORE_REG_PSW_USB_C,
|
||||
UC_TRICORE_REG_PSW_USB_V,
|
||||
UC_TRICORE_REG_PSW_USB_SV,
|
||||
UC_TRICORE_REG_PSW_USB_AV,
|
||||
UC_TRICORE_REG_PSW_USB_SAV,
|
||||
|
||||
UC_TRICORE_REG_PC,
|
||||
UC_TRICORE_REG_SYSCON,
|
||||
UC_TRICORE_REG_CPU_ID,
|
||||
UC_TRICORE_REG_BIV,
|
||||
UC_TRICORE_REG_BTV,
|
||||
UC_TRICORE_REG_ISP,
|
||||
UC_TRICORE_REG_ICR,
|
||||
UC_TRICORE_REG_FCX,
|
||||
UC_TRICORE_REG_LCX,
|
||||
UC_TRICORE_REG_COMPAT,
|
||||
|
||||
UC_TRICORE_REG_DPR0_U,
|
||||
UC_TRICORE_REG_DPR1_U,
|
||||
UC_TRICORE_REG_DPR2_U,
|
||||
UC_TRICORE_REG_DPR3_U,
|
||||
UC_TRICORE_REG_DPR0_L,
|
||||
UC_TRICORE_REG_DPR1_L,
|
||||
UC_TRICORE_REG_DPR2_L,
|
||||
UC_TRICORE_REG_DPR3_L,
|
||||
|
||||
UC_TRICORE_REG_CPR0_U,
|
||||
UC_TRICORE_REG_CPR1_U,
|
||||
UC_TRICORE_REG_CPR2_U,
|
||||
UC_TRICORE_REG_CPR3_U,
|
||||
UC_TRICORE_REG_CPR0_L,
|
||||
UC_TRICORE_REG_CPR1_L,
|
||||
UC_TRICORE_REG_CPR2_L,
|
||||
UC_TRICORE_REG_CPR3_L,
|
||||
|
||||
UC_TRICORE_REG_DPM0,
|
||||
UC_TRICORE_REG_DPM1,
|
||||
UC_TRICORE_REG_DPM2,
|
||||
UC_TRICORE_REG_DPM3,
|
||||
|
||||
UC_TRICORE_REG_CPM0,
|
||||
UC_TRICORE_REG_CPM1,
|
||||
UC_TRICORE_REG_CPM2,
|
||||
UC_TRICORE_REG_CPM3,
|
||||
|
||||
/* Memory Management Registers */
|
||||
UC_TRICORE_REG_MMU_CON,
|
||||
UC_TRICORE_REG_MMU_ASI,
|
||||
UC_TRICORE_REG_MMU_TVA,
|
||||
UC_TRICORE_REG_MMU_TPA,
|
||||
UC_TRICORE_REG_MMU_TPX,
|
||||
UC_TRICORE_REG_MMU_TFA,
|
||||
|
||||
// 1.3.1 Only
|
||||
UC_TRICORE_REG_BMACON,
|
||||
UC_TRICORE_REG_SMACON,
|
||||
UC_TRICORE_REG_DIEAR,
|
||||
UC_TRICORE_REG_DIETR,
|
||||
UC_TRICORE_REG_CCDIER,
|
||||
UC_TRICORE_REG_MIECON,
|
||||
UC_TRICORE_REG_PIEAR,
|
||||
UC_TRICORE_REG_PIETR,
|
||||
UC_TRICORE_REG_CCPIER,
|
||||
|
||||
/* Debug Registers */
|
||||
UC_TRICORE_REG_DBGSR,
|
||||
UC_TRICORE_REG_EXEVT,
|
||||
UC_TRICORE_REG_CREVT,
|
||||
UC_TRICORE_REG_SWEVT,
|
||||
UC_TRICORE_REG_TR0EVT,
|
||||
UC_TRICORE_REG_TR1EVT,
|
||||
UC_TRICORE_REG_DMS,
|
||||
UC_TRICORE_REG_DCX,
|
||||
UC_TRICORE_REG_DBGTCR,
|
||||
UC_TRICORE_REG_CCTRL,
|
||||
UC_TRICORE_REG_CCNT,
|
||||
UC_TRICORE_REG_ICNT,
|
||||
UC_TRICORE_REG_M1CNT,
|
||||
UC_TRICORE_REG_M2CNT,
|
||||
UC_TRICORE_REG_M3CNT,
|
||||
|
||||
UC_TRICORE_REG_ENDING, // <-- mark the end of the list of registers
|
||||
|
||||
// alias registers
|
||||
UC_TRICORE_REG_GA0 = UC_TRICORE_REG_A0,
|
||||
UC_TRICORE_REG_GA1 = UC_TRICORE_REG_A1,
|
||||
UC_TRICORE_REG_GA8 = UC_TRICORE_REG_A8,
|
||||
UC_TRICORE_REG_GA9 = UC_TRICORE_REG_A9,
|
||||
UC_TRICORE_REG_SP = UC_TRICORE_REG_A10,
|
||||
UC_TRICORE_REG_LR = UC_TRICORE_REG_A11,
|
||||
UC_TRICORE_REG_IA = UC_TRICORE_REG_A15,
|
||||
UC_TRICORE_REG_ID = UC_TRICORE_REG_D15,
|
||||
} uc_tricore_reg;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -35,6 +35,7 @@ typedef size_t uc_hook;
|
||||
#include "ppc.h"
|
||||
#include "riscv.h"
|
||||
#include "s390x.h"
|
||||
#include "tricore.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define DEFAULT_VISIBILITY __attribute__((visibility("default")))
|
||||
@ -72,7 +73,8 @@ typedef size_t uc_hook;
|
||||
#define UC_API_MAJOR 2
|
||||
#define UC_API_MINOR 0
|
||||
#define UC_API_PATCH 0
|
||||
#define UC_API_EXTRA 7
|
||||
// Release candidate version, 255 means the official release.
|
||||
#define UC_API_EXTRA 255
|
||||
|
||||
// Unicorn package version
|
||||
#define UC_VERSION_MAJOR UC_API_MAJOR
|
||||
@ -103,6 +105,7 @@ typedef enum uc_arch {
|
||||
UC_ARCH_M68K, // M68K architecture
|
||||
UC_ARCH_RISCV, // RISCV architecture
|
||||
UC_ARCH_S390X, // S390X architecture
|
||||
UC_ARCH_TRICORE, // TriCore architecture
|
||||
UC_ARCH_MAX,
|
||||
} uc_arch;
|
||||
|
||||
@ -117,8 +120,8 @@ typedef enum uc_mode {
|
||||
// Depreciated, use UC_ARM_CPU_* with uc_ctl instead.
|
||||
UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series.
|
||||
UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM
|
||||
UC_MODE_ARMBE8 = 1 << 7, // Big-endian data and Little-endian code.
|
||||
// Legacy support for UC1 only.
|
||||
UC_MODE_ARMBE8 = 1 << 10, // Big-endian data and Little-endian code.
|
||||
// Legacy support for UC1 only.
|
||||
|
||||
// arm (32bit) cpu types
|
||||
// Depreciated, use UC_ARM_CPU_* with uc_ctl instead.
|
||||
@ -530,7 +533,10 @@ typedef enum uc_control_type {
|
||||
UC_CTL_TB_REQUEST_CACHE,
|
||||
// Invalidate a tb cache at a specific address
|
||||
// Write: @args = (uint64_t, uint64_t)
|
||||
UC_CTL_TB_REMOVE_CACHE
|
||||
UC_CTL_TB_REMOVE_CACHE,
|
||||
// Invalidate all translation blocks.
|
||||
// No arguments.
|
||||
UC_CTL_TB_FLUSH
|
||||
|
||||
} uc_control_type;
|
||||
|
||||
@ -605,7 +611,7 @@ See sample_ctl.c for a detailed example.
|
||||
uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TB_REMOVE_CACHE, 2), (address), (end))
|
||||
#define uc_ctl_request_cache(uc, address, tb) \
|
||||
uc_ctl(uc, UC_CTL_READ_WRITE(UC_CTL_TB_REQUEST_CACHE, 2), (address), (tb))
|
||||
|
||||
#define uc_ctl_flush_tlb(uc) uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TB_FLUSH, 0))
|
||||
// Opaque storage for CPU context, used with uc_context_*()
|
||||
struct uc_context;
|
||||
typedef struct uc_context uc_context;
|
||||
|
5
msvc/tricore-softmmu/config-target.h
Normal file
5
msvc/tricore-softmmu/config-target.h
Normal file
@ -0,0 +1,5 @@
|
||||
/* Automatically generated by create_config - do not modify */
|
||||
#define TARGET_TRICORE 1
|
||||
#define TARGET_NAME "tricore"
|
||||
#define TARGET_TRICORE 1
|
||||
#define CONFIG_SOFTMMU 1
|
@ -1441,36 +1441,41 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
|
||||
// memory might be still unmapped while reading or fetching
|
||||
if (mr == NULL) {
|
||||
handled = false;
|
||||
if (code_read) {
|
||||
// code fetching
|
||||
error_code = UC_ERR_FETCH_UNMAPPED;
|
||||
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_FETCH_UNMAPPED) {
|
||||
if (hook->to_delete)
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, addr))
|
||||
continue;
|
||||
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, addr, size - uc->size_recur_mem, 0, hook->user_data)))
|
||||
break;
|
||||
// if there is already an unhandled eror, skip callbacks.
|
||||
if (uc->invalid_error == UC_ERR_OK) {
|
||||
if (code_read) {
|
||||
// code fetching
|
||||
error_code = UC_ERR_FETCH_UNMAPPED;
|
||||
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_FETCH_UNMAPPED) {
|
||||
if (hook->to_delete)
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, addr))
|
||||
continue;
|
||||
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, addr, size - uc->size_recur_mem, 0, hook->user_data)))
|
||||
break;
|
||||
|
||||
// the last callback may already asked to stop emulation
|
||||
if (uc->stop_request)
|
||||
break;
|
||||
// the last callback may already asked to stop emulation
|
||||
if (uc->stop_request)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// data reading
|
||||
error_code = UC_ERR_READ_UNMAPPED;
|
||||
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_UNMAPPED) {
|
||||
if (hook->to_delete)
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, addr))
|
||||
continue;
|
||||
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, addr, size - uc->size_recur_mem, 0, hook->user_data)))
|
||||
break;
|
||||
|
||||
// the last callback may already asked to stop emulation
|
||||
if (uc->stop_request)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// data reading
|
||||
error_code = UC_ERR_READ_UNMAPPED;
|
||||
HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_UNMAPPED) {
|
||||
if (hook->to_delete)
|
||||
continue;
|
||||
if (!HOOK_BOUND_CHECK(hook, addr))
|
||||
continue;
|
||||
if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, addr, size - uc->size_recur_mem, 0, hook->user_data)))
|
||||
break;
|
||||
|
||||
// the last callback may already asked to stop emulation
|
||||
if (uc->stop_request)
|
||||
break;
|
||||
}
|
||||
error_code = uc->invalid_error;
|
||||
}
|
||||
|
||||
if (handled) {
|
||||
|
@ -985,6 +985,10 @@ static void tb_htable_init(struct uc_struct *uc)
|
||||
}
|
||||
|
||||
|
||||
static void uc_tb_flush(struct uc_struct *uc) {
|
||||
tb_flush(uc->cpu);
|
||||
}
|
||||
|
||||
static void uc_invalidate_tb(struct uc_struct *uc, uint64_t start_addr, size_t len)
|
||||
{
|
||||
tb_page_addr_t start, end;
|
||||
@ -1095,6 +1099,7 @@ void tcg_exec_init(struct uc_struct *uc, unsigned long tb_size)
|
||||
/* Invalidate / Cache TBs */
|
||||
uc->uc_invalidate_tb = uc_invalidate_tb;
|
||||
uc->uc_gen_tb = uc_gen_tb;
|
||||
uc->tb_flush = uc_tb_flush;
|
||||
|
||||
/* Inline hooks optimization */
|
||||
uc->add_inline_hook = uc_add_inline_hook;
|
||||
|
@ -147,6 +147,8 @@ _end_loop:
|
||||
db->tb->size = db->pc_next - db->pc_first;
|
||||
db->tb->icount = db->num_insns;
|
||||
|
||||
hooked_regions_check(uc, db->tb->pc, db->tb->size);
|
||||
|
||||
if (block_hook) {
|
||||
TCGOp *tcg_op;
|
||||
|
||||
|
11
qemu/configure
vendored
11
qemu/configure
vendored
@ -489,6 +489,8 @@ elif check_define __arm__ ; then
|
||||
cpu="arm"
|
||||
elif check_define __aarch64__ ; then
|
||||
cpu="aarch64"
|
||||
elif check_define __tricore__ ; then
|
||||
cpu="tricore"
|
||||
else
|
||||
cpu=$(uname -m)
|
||||
fi
|
||||
@ -528,6 +530,10 @@ case "$cpu" in
|
||||
cpu="sparc"
|
||||
supported_cpu="yes"
|
||||
;;
|
||||
tricore)
|
||||
cpu="tricore"
|
||||
supported_cpu="yes"
|
||||
;;
|
||||
*)
|
||||
# This will result in either an error or falling back to TCI later
|
||||
ARCH=unknown
|
||||
@ -852,7 +858,8 @@ QEMU_CFLAGS="$CPU_CFLAGS $QEMU_CFLAGS"
|
||||
default_target_list="aarch64-softmmu \
|
||||
arm-softmmu m68k-softmmu mips64el-softmmu mips64-softmmu mipsel-softmmu \
|
||||
mips-softmmu ppc64-softmmu ppc-softmmu sparc64-softmmu sparc-softmmu \
|
||||
x86_64-softmmu riscv32-softmmu riscv64-softmmu s390x-softmmu"
|
||||
x86_64-softmmu riscv32-softmmu riscv64-softmmu s390x-softmmu \
|
||||
tricore-softmmu"
|
||||
|
||||
if test x"$show_help" = x"yes" ; then
|
||||
cat << EOF
|
||||
@ -2747,6 +2754,8 @@ case "$target_name" in
|
||||
tilegx)
|
||||
;;
|
||||
tricore)
|
||||
TARGET_ARCH=tricore
|
||||
TARGET_BASE_ARCH=tricore
|
||||
;;
|
||||
unicore32)
|
||||
;;
|
||||
|
@ -794,6 +794,12 @@ struct TCGContext {
|
||||
TCGv NULL_QREG;
|
||||
/* Used to distinguish stores from bad addressing modes. */
|
||||
TCGv store_dummy;
|
||||
|
||||
// target/tricore/translate.c
|
||||
TCGv_i32 cpu_gpr_a[16];
|
||||
TCGv_i32 cpu_gpr_d[16];
|
||||
TCGv_i32 cpu_PSW_C, cpu_PSW_V, cpu_PSW_SV, cpu_PSW_AV, cpu_PSW_SAV;
|
||||
TCGv_i32 cpu_PC, cpu_PCXI, cpu_PSW, cpu_ICR;
|
||||
|
||||
// Used to store the start of current instrution.
|
||||
uint64_t pc_start;
|
||||
|
@ -99,6 +99,12 @@ static int tcg_cpu_exec(struct uc_struct *uc)
|
||||
if (uc->quit_request) {
|
||||
// reset stop_request
|
||||
uc->stop_request = false;
|
||||
|
||||
// resume cpu
|
||||
cpu->halted = 0;
|
||||
cpu->exit_request = 0;
|
||||
cpu->exception_index = -1;
|
||||
cpu_resume(cpu);
|
||||
} else if (uc->stop_request) {
|
||||
//printf(">>> got STOP request!!!\n");
|
||||
finish = true;
|
||||
|
@ -82,7 +82,7 @@ MemoryRegion *memory_map_ptr(struct uc_struct *uc, hwaddr begin, size_t size, ui
|
||||
static uint64_t mmio_read_wrapper(struct uc_struct *uc, void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
mmio_cbs* cbs = (mmio_cbs*)opaque;
|
||||
|
||||
|
||||
// We have to care about 32bit target.
|
||||
addr = addr & ( (target_ulong)(-1) );
|
||||
if (cbs->read) {
|
||||
@ -123,7 +123,9 @@ MemoryRegion *memory_map_io(struct uc_struct *uc, ram_addr_t begin, size_t size,
|
||||
memset(ops, 0, sizeof(*ops));
|
||||
|
||||
ops->read = mmio_read_wrapper;
|
||||
ops->read_with_attrs = NULL;
|
||||
ops->write = mmio_write_wrapper;
|
||||
ops->write_with_attrs = NULL;
|
||||
ops->endianness = DEVICE_NATIVE_ENDIAN;
|
||||
|
||||
memory_region_init_io(uc, mmio, ops, opaques, size);
|
||||
|
@ -18,6 +18,11 @@ static void arm64_set_pc(struct uc_struct *uc, uint64_t address)
|
||||
((CPUARMState *)uc->cpu->env_ptr)->pc = address;
|
||||
}
|
||||
|
||||
static uint64_t arm64_get_pc(struct uc_struct *uc)
|
||||
{
|
||||
return ((CPUARMState *)uc->cpu->env_ptr)->pc;
|
||||
}
|
||||
|
||||
static void arm64_release(void *ctx)
|
||||
{
|
||||
int i;
|
||||
@ -431,6 +436,7 @@ void arm64_uc_init(struct uc_struct *uc)
|
||||
uc->reg_write = arm64_reg_write;
|
||||
uc->reg_reset = arm64_reg_reset;
|
||||
uc->set_pc = arm64_set_pc;
|
||||
uc->get_pc = arm64_get_pc;
|
||||
uc->release = arm64_release;
|
||||
uc->cpus_init = arm64_cpus_init;
|
||||
uc->cpu_context_size = offsetof(CPUARMState, cpu_watchpoint);
|
||||
|
@ -16,7 +16,14 @@ ARMCPU *cpu_arm_init(struct uc_struct *uc);
|
||||
static void arm_set_pc(struct uc_struct *uc, uint64_t address)
|
||||
{
|
||||
((CPUARMState *)uc->cpu->env_ptr)->pc = address;
|
||||
((CPUARMState *)uc->cpu->env_ptr)->regs[15] = address;
|
||||
((CPUARMState *)uc->cpu->env_ptr)->regs[15] = address & ~1;
|
||||
((CPUARMState *)uc->cpu->env_ptr)->thumb = address & 1;
|
||||
}
|
||||
|
||||
static uint64_t arm_get_pc(struct uc_struct *uc)
|
||||
{
|
||||
return ((CPUARMState *)uc->cpu->env_ptr)->regs[15] |
|
||||
((CPUARMState *)uc->cpu->env_ptr)->thumb;
|
||||
}
|
||||
|
||||
static void arm_release(void *ctx)
|
||||
@ -204,10 +211,23 @@ static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value)
|
||||
uc_err ret = UC_ERR_OK;
|
||||
|
||||
if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) {
|
||||
*(int32_t *)value = env->regs[regid - UC_ARM_REG_R0];
|
||||
*(uint32_t *)value = env->regs[regid - UC_ARM_REG_R0];
|
||||
} else if (regid >= UC_ARM_REG_Q0 && regid <= UC_ARM_REG_Q15) {
|
||||
uint32_t reg_index = regid - UC_ARM_REG_Q0;
|
||||
*(uint64_t *)value = env->vfp.zregs[reg_index].d[0];
|
||||
*(((uint64_t *)value) + 1) = env->vfp.zregs[reg_index].d[1];
|
||||
} else if (regid >= UC_ARM_REG_D0 && regid <= UC_ARM_REG_D31) {
|
||||
uint32_t reg_index = regid - UC_ARM_REG_D0;
|
||||
*(float64 *)value = env->vfp.zregs[reg_index / 2].d[reg_index & 1];
|
||||
*(uint64_t *)value = env->vfp.zregs[reg_index / 2].d[reg_index & 1];
|
||||
} else if (regid >= UC_ARM_REG_S0 && regid <= UC_ARM_REG_S31) {
|
||||
uint32_t reg_index = regid - UC_ARM_REG_S0;
|
||||
uint64_t reg_value = env->vfp.zregs[reg_index / 4].d[reg_index % 4 / 2];
|
||||
|
||||
if (reg_index % 2 == 0) {
|
||||
*(uint32_t *)value = (uint32_t)(reg_value & 0xffffffff);
|
||||
} else {
|
||||
*(uint32_t *)value = (uint32_t)(reg_value >> 32);
|
||||
}
|
||||
} else {
|
||||
switch (regid) {
|
||||
case UC_ARM_REG_APSR:
|
||||
@ -308,9 +328,25 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value)
|
||||
|
||||
if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) {
|
||||
env->regs[regid - UC_ARM_REG_R0] = *(uint32_t *)value;
|
||||
} else if (regid >= UC_ARM_REG_Q0 && regid <= UC_ARM_REG_Q15) {
|
||||
uint32_t reg_index = regid - UC_ARM_REG_Q0;
|
||||
env->vfp.zregs[reg_index].d[0] = *(uint64_t *)value;
|
||||
env->vfp.zregs[reg_index].d[1] = *(((uint64_t *)value) + 1);
|
||||
} else if (regid >= UC_ARM_REG_D0 && regid <= UC_ARM_REG_D31) {
|
||||
uint32_t reg_index = regid - UC_ARM_REG_D0;
|
||||
env->vfp.zregs[reg_index / 2].d[reg_index & 1] = *(float64 *)value;
|
||||
env->vfp.zregs[reg_index / 2].d[reg_index & 1] = *(uint64_t *)value;
|
||||
} else if (regid >= UC_ARM_REG_S0 && regid <= UC_ARM_REG_S31) {
|
||||
uint32_t reg_index = regid - UC_ARM_REG_S0;
|
||||
uint64_t *p_reg_value =
|
||||
&env->vfp.zregs[reg_index / 4].d[reg_index % 4 / 2];
|
||||
uint64_t in_value = *((uint32_t *)value);
|
||||
if (reg_index % 2 == 0) {
|
||||
in_value |= *p_reg_value & 0xffffffff00000000ul;
|
||||
} else {
|
||||
in_value = (in_value << 32) | (*p_reg_value & 0xfffffffful);
|
||||
}
|
||||
|
||||
*p_reg_value = in_value;
|
||||
} else {
|
||||
switch (regid) {
|
||||
case UC_ARM_REG_APSR:
|
||||
@ -591,6 +627,7 @@ void arm_uc_init(struct uc_struct *uc)
|
||||
uc->reg_write = arm_reg_write;
|
||||
uc->reg_reset = arm_reg_reset;
|
||||
uc->set_pc = arm_set_pc;
|
||||
uc->get_pc = arm_get_pc;
|
||||
uc->stop_interrupt = arm_stop_interrupt;
|
||||
uc->release = arm_release;
|
||||
uc->query = arm_query;
|
||||
|
@ -33,6 +33,16 @@ static void x86_set_pc(struct uc_struct *uc, uint64_t address)
|
||||
((CPUX86State *)uc->cpu->env_ptr)->eip = address;
|
||||
}
|
||||
|
||||
static uint64_t x86_get_pc(struct uc_struct *uc)
|
||||
{
|
||||
if (uc->mode == UC_MODE_16) {
|
||||
return X86_CPU(uc->cpu)->env.segs[R_CS].selector * 16 +
|
||||
((CPUX86State *)uc->cpu->env_ptr)->eip;
|
||||
} else {
|
||||
return ((CPUX86State *)uc->cpu->env_ptr)->eip;
|
||||
}
|
||||
}
|
||||
|
||||
static void x86_release(void *ctx)
|
||||
{
|
||||
int i;
|
||||
@ -1644,6 +1654,7 @@ void x86_uc_init(struct uc_struct *uc)
|
||||
uc->reg_reset = x86_reg_reset;
|
||||
uc->release = x86_release;
|
||||
uc->set_pc = x86_set_pc;
|
||||
uc->get_pc = x86_get_pc;
|
||||
uc->stop_interrupt = x86_stop_interrupt;
|
||||
uc->insn_hook_validate = x86_insn_hook_validate;
|
||||
uc->opcode_hook_invalidate = x86_opcode_hook_invalidate;
|
||||
|
@ -15,6 +15,11 @@ static void m68k_set_pc(struct uc_struct *uc, uint64_t address)
|
||||
((CPUM68KState *)uc->cpu->env_ptr)->pc = address;
|
||||
}
|
||||
|
||||
static uint64_t m68k_get_pc(struct uc_struct *uc)
|
||||
{
|
||||
return ((CPUM68KState *)uc->cpu->env_ptr)->pc;
|
||||
}
|
||||
|
||||
static void m68k_release(void *ctx)
|
||||
{
|
||||
int i;
|
||||
@ -170,6 +175,7 @@ void m68k_uc_init(struct uc_struct *uc)
|
||||
uc->reg_write = m68k_reg_write;
|
||||
uc->reg_reset = m68k_reg_reset;
|
||||
uc->set_pc = m68k_set_pc;
|
||||
uc->get_pc = m68k_get_pc;
|
||||
uc->cpus_init = m68k_cpus_init;
|
||||
uc->cpu_context_size = offsetof(CPUM68KState, end_reset_fields);
|
||||
uc_common_init(uc);
|
||||
|
@ -37,6 +37,11 @@ static void mips_set_pc(struct uc_struct *uc, uint64_t address)
|
||||
((CPUMIPSState *)uc->cpu->env_ptr)->active_tc.PC = address;
|
||||
}
|
||||
|
||||
static uint64_t mips_get_pc(struct uc_struct *uc)
|
||||
{
|
||||
return ((CPUMIPSState *)uc->cpu->env_ptr)->active_tc.PC;
|
||||
}
|
||||
|
||||
static void mips_release(void *ctx)
|
||||
{
|
||||
int i;
|
||||
@ -266,6 +271,7 @@ void mipsel_uc_init(struct uc_struct *uc)
|
||||
uc->reg_reset = mips_reg_reset;
|
||||
uc->release = mips_release;
|
||||
uc->set_pc = mips_set_pc;
|
||||
uc->get_pc = mips_get_pc;
|
||||
uc->mem_redirect = mips_mem_redirect;
|
||||
uc->cpus_init = mips_cpus_init;
|
||||
uc->cpu_context_size = offsetof(CPUMIPSState, end_reset_fields);
|
||||
|
@ -97,6 +97,11 @@ static void ppc_set_pc(struct uc_struct *uc, uint64_t address)
|
||||
((CPUPPCState *)uc->cpu->env_ptr)->nip = address;
|
||||
}
|
||||
|
||||
static uint64_t ppc_get_pc(struct uc_struct *uc)
|
||||
{
|
||||
return ((CPUPPCState *)uc->cpu->env_ptr)->nip;
|
||||
}
|
||||
|
||||
void ppc_cpu_instance_finalize(CPUState *obj);
|
||||
void ppc_cpu_unrealize(CPUState *dev);
|
||||
static void ppc_release(void *ctx)
|
||||
@ -414,6 +419,7 @@ void ppc_uc_init(struct uc_struct *uc)
|
||||
uc->reg_reset = ppc_reg_reset;
|
||||
uc->release = ppc_release;
|
||||
uc->set_pc = ppc_set_pc;
|
||||
uc->get_pc = ppc_get_pc;
|
||||
uc->mem_redirect = ppc_mem_redirect;
|
||||
uc->cpus_init = ppc_cpus_init;
|
||||
uc->cpu_context_size = offsetof(CPUPPCState, uc);
|
||||
|
@ -52,6 +52,11 @@ static void riscv_set_pc(struct uc_struct *uc, uint64_t address)
|
||||
RISCV_CPU(uc->cpu)->env.pc = address;
|
||||
}
|
||||
|
||||
static uint64_t riscv_get_pc(struct uc_struct *uc)
|
||||
{
|
||||
return RISCV_CPU(uc->cpu)->env.pc;
|
||||
}
|
||||
|
||||
static void riscv_release(void *ctx)
|
||||
{
|
||||
int i;
|
||||
@ -651,6 +656,7 @@ void riscv64_uc_init(struct uc_struct *uc)
|
||||
uc->reg_reset = riscv_reg_reset;
|
||||
uc->release = riscv_release;
|
||||
uc->set_pc = riscv_set_pc;
|
||||
uc->get_pc = riscv_get_pc;
|
||||
uc->stop_interrupt = riscv_stop_interrupt;
|
||||
uc->insn_hook_validate = riscv_insn_hook_validate;
|
||||
uc->cpus_init = riscv_cpus_init;
|
||||
|
@ -21,50 +21,50 @@ typedef struct SigpInfo {
|
||||
uint64_t *status_reg;
|
||||
} SigpInfo;
|
||||
|
||||
static void set_sigp_status(SigpInfo *si, uint64_t status)
|
||||
{
|
||||
*si->status_reg &= 0xffffffff00000000ULL;
|
||||
*si->status_reg |= status;
|
||||
si->cc = SIGP_CC_STATUS_STORED;
|
||||
}
|
||||
// static void set_sigp_status(SigpInfo *si, uint64_t status)
|
||||
// {
|
||||
// *si->status_reg &= 0xffffffff00000000ULL;
|
||||
// *si->status_reg |= status;
|
||||
// si->cc = SIGP_CC_STATUS_STORED;
|
||||
// }
|
||||
|
||||
static void sigp_sense(S390CPU *dst_cpu, SigpInfo *si)
|
||||
{
|
||||
uint8_t state = s390_cpu_get_state(dst_cpu);
|
||||
bool ext_call = dst_cpu->env.pending_int & INTERRUPT_EXTERNAL_CALL;
|
||||
uint64_t status = 0;
|
||||
// static void sigp_sense(S390CPU *dst_cpu, SigpInfo *si)
|
||||
// {
|
||||
// uint8_t state = s390_cpu_get_state(dst_cpu);
|
||||
// bool ext_call = dst_cpu->env.pending_int & INTERRUPT_EXTERNAL_CALL;
|
||||
// uint64_t status = 0;
|
||||
|
||||
/* sensing without locks is racy, but it's the same for real hw */
|
||||
if (state != S390_CPU_STATE_STOPPED && !ext_call) {
|
||||
si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
|
||||
} else {
|
||||
if (ext_call) {
|
||||
status |= SIGP_STAT_EXT_CALL_PENDING;
|
||||
}
|
||||
if (state == S390_CPU_STATE_STOPPED) {
|
||||
status |= SIGP_STAT_STOPPED;
|
||||
}
|
||||
set_sigp_status(si, status);
|
||||
}
|
||||
}
|
||||
// /* sensing without locks is racy, but it's the same for real hw */
|
||||
// if (state != S390_CPU_STATE_STOPPED && !ext_call) {
|
||||
// si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
|
||||
// } else {
|
||||
// if (ext_call) {
|
||||
// status |= SIGP_STAT_EXT_CALL_PENDING;
|
||||
// }
|
||||
// if (state == S390_CPU_STATE_STOPPED) {
|
||||
// status |= SIGP_STAT_STOPPED;
|
||||
// }
|
||||
// set_sigp_status(si, status);
|
||||
// }
|
||||
// }
|
||||
|
||||
static void sigp_external_call(S390CPU *src_cpu, S390CPU *dst_cpu, SigpInfo *si)
|
||||
{
|
||||
int ret;
|
||||
// static void sigp_external_call(S390CPU *src_cpu, S390CPU *dst_cpu, SigpInfo *si)
|
||||
// {
|
||||
// int ret;
|
||||
|
||||
ret = cpu_inject_external_call(dst_cpu, src_cpu->env.core_id);
|
||||
if (!ret) {
|
||||
si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
|
||||
} else {
|
||||
set_sigp_status(si, SIGP_STAT_EXT_CALL_PENDING);
|
||||
}
|
||||
}
|
||||
// ret = cpu_inject_external_call(dst_cpu, src_cpu->env.core_id);
|
||||
// if (!ret) {
|
||||
// si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
|
||||
// } else {
|
||||
// set_sigp_status(si, SIGP_STAT_EXT_CALL_PENDING);
|
||||
// }
|
||||
// }
|
||||
|
||||
static void sigp_emergency(S390CPU *src_cpu, S390CPU *dst_cpu, SigpInfo *si)
|
||||
{
|
||||
cpu_inject_emergency_signal(dst_cpu, src_cpu->env.core_id);
|
||||
si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
|
||||
}
|
||||
// static void sigp_emergency(S390CPU *src_cpu, S390CPU *dst_cpu, SigpInfo *si)
|
||||
// {
|
||||
// cpu_inject_emergency_signal(dst_cpu, src_cpu->env.core_id);
|
||||
// si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
|
||||
// }
|
||||
|
||||
#if 0
|
||||
static void sigp_start(CPUState *cs, run_on_cpu_data arg)
|
||||
@ -277,146 +277,146 @@ static void sigp_set_prefix(CPUState *cs, run_on_cpu_data arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void sigp_cond_emergency(S390CPU *src_cpu, S390CPU *dst_cpu,
|
||||
SigpInfo *si)
|
||||
{
|
||||
const uint64_t psw_int_mask = PSW_MASK_IO | PSW_MASK_EXT;
|
||||
uint16_t p_asn, s_asn, asn;
|
||||
uint64_t psw_addr, psw_mask;
|
||||
bool idle;
|
||||
// static void sigp_cond_emergency(S390CPU *src_cpu, S390CPU *dst_cpu,
|
||||
// SigpInfo *si)
|
||||
// {
|
||||
// const uint64_t psw_int_mask = PSW_MASK_IO | PSW_MASK_EXT;
|
||||
// uint16_t p_asn, s_asn, asn;
|
||||
// uint64_t psw_addr, psw_mask;
|
||||
// bool idle;
|
||||
|
||||
/* this looks racy, but these values are only used when STOPPED */
|
||||
idle = CPU(dst_cpu)->halted;
|
||||
psw_addr = dst_cpu->env.psw.addr;
|
||||
psw_mask = dst_cpu->env.psw.mask;
|
||||
asn = si->param;
|
||||
p_asn = dst_cpu->env.cregs[4] & 0xffff; /* Primary ASN */
|
||||
s_asn = dst_cpu->env.cregs[3] & 0xffff; /* Secondary ASN */
|
||||
// /* this looks racy, but these values are only used when STOPPED */
|
||||
// idle = CPU(dst_cpu)->halted;
|
||||
// psw_addr = dst_cpu->env.psw.addr;
|
||||
// psw_mask = dst_cpu->env.psw.mask;
|
||||
// asn = si->param;
|
||||
// p_asn = dst_cpu->env.cregs[4] & 0xffff; /* Primary ASN */
|
||||
// s_asn = dst_cpu->env.cregs[3] & 0xffff; /* Secondary ASN */
|
||||
|
||||
if (s390_cpu_get_state(dst_cpu) != S390_CPU_STATE_STOPPED ||
|
||||
(psw_mask & psw_int_mask) != psw_int_mask ||
|
||||
(idle && psw_addr != 0) ||
|
||||
(!idle && (asn == p_asn || asn == s_asn))) {
|
||||
cpu_inject_emergency_signal(dst_cpu, src_cpu->env.core_id);
|
||||
} else {
|
||||
set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
|
||||
}
|
||||
// if (s390_cpu_get_state(dst_cpu) != S390_CPU_STATE_STOPPED ||
|
||||
// (psw_mask & psw_int_mask) != psw_int_mask ||
|
||||
// (idle && psw_addr != 0) ||
|
||||
// (!idle && (asn == p_asn || asn == s_asn))) {
|
||||
// cpu_inject_emergency_signal(dst_cpu, src_cpu->env.core_id);
|
||||
// } else {
|
||||
// set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
|
||||
// }
|
||||
|
||||
si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
|
||||
}
|
||||
// si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
|
||||
// }
|
||||
|
||||
static void sigp_sense_running(S390CPU *dst_cpu, SigpInfo *si)
|
||||
{
|
||||
/* sensing without locks is racy, but it's the same for real hw */
|
||||
//if (!s390_has_feat(S390_FEAT_SENSE_RUNNING_STATUS)) {
|
||||
// set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
|
||||
// return;
|
||||
//}
|
||||
// static void sigp_sense_running(S390CPU *dst_cpu, SigpInfo *si)
|
||||
// {
|
||||
// /* sensing without locks is racy, but it's the same for real hw */
|
||||
// //if (!s390_has_feat(S390_FEAT_SENSE_RUNNING_STATUS)) {
|
||||
// // set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
|
||||
// // return;
|
||||
// //}
|
||||
|
||||
/* If halted (which includes also STOPPED), it is not running */
|
||||
if (CPU(dst_cpu)->halted) {
|
||||
set_sigp_status(si, SIGP_STAT_NOT_RUNNING);
|
||||
} else {
|
||||
si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
|
||||
}
|
||||
}
|
||||
// /* If halted (which includes also STOPPED), it is not running */
|
||||
// if (CPU(dst_cpu)->halted) {
|
||||
// set_sigp_status(si, SIGP_STAT_NOT_RUNNING);
|
||||
// } else {
|
||||
// si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
|
||||
// }
|
||||
// }
|
||||
|
||||
static int handle_sigp_single_dst(S390CPU *cpu, S390CPU *dst_cpu, uint8_t order,
|
||||
uint64_t param, uint64_t *status_reg)
|
||||
{
|
||||
SigpInfo si = {
|
||||
.param = param,
|
||||
.status_reg = status_reg,
|
||||
};
|
||||
// static int handle_sigp_single_dst(S390CPU *cpu, S390CPU *dst_cpu, uint8_t order,
|
||||
// uint64_t param, uint64_t *status_reg)
|
||||
// {
|
||||
// SigpInfo si = {
|
||||
// .param = param,
|
||||
// .status_reg = status_reg,
|
||||
// };
|
||||
|
||||
/* cpu available? */
|
||||
if (dst_cpu == NULL) {
|
||||
return SIGP_CC_NOT_OPERATIONAL;
|
||||
}
|
||||
// /* cpu available? */
|
||||
// if (dst_cpu == NULL) {
|
||||
// return SIGP_CC_NOT_OPERATIONAL;
|
||||
// }
|
||||
|
||||
/* only resets can break pending orders */
|
||||
if (dst_cpu->env.sigp_order != 0 &&
|
||||
order != SIGP_CPU_RESET &&
|
||||
order != SIGP_INITIAL_CPU_RESET) {
|
||||
return SIGP_CC_BUSY;
|
||||
}
|
||||
// /* only resets can break pending orders */
|
||||
// if (dst_cpu->env.sigp_order != 0 &&
|
||||
// order != SIGP_CPU_RESET &&
|
||||
// order != SIGP_INITIAL_CPU_RESET) {
|
||||
// return SIGP_CC_BUSY;
|
||||
// }
|
||||
|
||||
switch (order) {
|
||||
case SIGP_SENSE:
|
||||
sigp_sense(dst_cpu, &si);
|
||||
break;
|
||||
case SIGP_EXTERNAL_CALL:
|
||||
sigp_external_call(cpu, dst_cpu, &si);
|
||||
break;
|
||||
case SIGP_EMERGENCY:
|
||||
sigp_emergency(cpu, dst_cpu, &si);
|
||||
break;
|
||||
case SIGP_START:
|
||||
//run_on_cpu(CPU(dst_cpu), sigp_start, RUN_ON_CPU_HOST_PTR(&si));
|
||||
break;
|
||||
case SIGP_STOP:
|
||||
//run_on_cpu(CPU(dst_cpu), sigp_stop, RUN_ON_CPU_HOST_PTR(&si));
|
||||
break;
|
||||
case SIGP_RESTART:
|
||||
//run_on_cpu(CPU(dst_cpu), sigp_restart, RUN_ON_CPU_HOST_PTR(&si));
|
||||
break;
|
||||
case SIGP_STOP_STORE_STATUS:
|
||||
//run_on_cpu(CPU(dst_cpu), sigp_stop_and_store_status, RUN_ON_CPU_HOST_PTR(&si));
|
||||
break;
|
||||
case SIGP_STORE_STATUS_ADDR:
|
||||
//run_on_cpu(CPU(dst_cpu), sigp_store_status_at_address, RUN_ON_CPU_HOST_PTR(&si));
|
||||
break;
|
||||
case SIGP_STORE_ADTL_STATUS:
|
||||
//run_on_cpu(CPU(dst_cpu), sigp_store_adtl_status, RUN_ON_CPU_HOST_PTR(&si));
|
||||
break;
|
||||
case SIGP_SET_PREFIX:
|
||||
//run_on_cpu(CPU(dst_cpu), sigp_set_prefix, RUN_ON_CPU_HOST_PTR(&si));
|
||||
break;
|
||||
case SIGP_INITIAL_CPU_RESET:
|
||||
//run_on_cpu(CPU(dst_cpu), sigp_initial_cpu_reset, RUN_ON_CPU_HOST_PTR(&si));
|
||||
break;
|
||||
case SIGP_CPU_RESET:
|
||||
//run_on_cpu(CPU(dst_cpu), sigp_cpu_reset, RUN_ON_CPU_HOST_PTR(&si));
|
||||
break;
|
||||
case SIGP_COND_EMERGENCY:
|
||||
sigp_cond_emergency(cpu, dst_cpu, &si);
|
||||
break;
|
||||
case SIGP_SENSE_RUNNING:
|
||||
sigp_sense_running(dst_cpu, &si);
|
||||
break;
|
||||
default:
|
||||
set_sigp_status(&si, SIGP_STAT_INVALID_ORDER);
|
||||
}
|
||||
// switch (order) {
|
||||
// case SIGP_SENSE:
|
||||
// sigp_sense(dst_cpu, &si);
|
||||
// break;
|
||||
// case SIGP_EXTERNAL_CALL:
|
||||
// sigp_external_call(cpu, dst_cpu, &si);
|
||||
// break;
|
||||
// case SIGP_EMERGENCY:
|
||||
// sigp_emergency(cpu, dst_cpu, &si);
|
||||
// break;
|
||||
// case SIGP_START:
|
||||
// //run_on_cpu(CPU(dst_cpu), sigp_start, RUN_ON_CPU_HOST_PTR(&si));
|
||||
// break;
|
||||
// case SIGP_STOP:
|
||||
// //run_on_cpu(CPU(dst_cpu), sigp_stop, RUN_ON_CPU_HOST_PTR(&si));
|
||||
// break;
|
||||
// case SIGP_RESTART:
|
||||
// //run_on_cpu(CPU(dst_cpu), sigp_restart, RUN_ON_CPU_HOST_PTR(&si));
|
||||
// break;
|
||||
// case SIGP_STOP_STORE_STATUS:
|
||||
// //run_on_cpu(CPU(dst_cpu), sigp_stop_and_store_status, RUN_ON_CPU_HOST_PTR(&si));
|
||||
// break;
|
||||
// case SIGP_STORE_STATUS_ADDR:
|
||||
// //run_on_cpu(CPU(dst_cpu), sigp_store_status_at_address, RUN_ON_CPU_HOST_PTR(&si));
|
||||
// break;
|
||||
// case SIGP_STORE_ADTL_STATUS:
|
||||
// //run_on_cpu(CPU(dst_cpu), sigp_store_adtl_status, RUN_ON_CPU_HOST_PTR(&si));
|
||||
// break;
|
||||
// case SIGP_SET_PREFIX:
|
||||
// //run_on_cpu(CPU(dst_cpu), sigp_set_prefix, RUN_ON_CPU_HOST_PTR(&si));
|
||||
// break;
|
||||
// case SIGP_INITIAL_CPU_RESET:
|
||||
// //run_on_cpu(CPU(dst_cpu), sigp_initial_cpu_reset, RUN_ON_CPU_HOST_PTR(&si));
|
||||
// break;
|
||||
// case SIGP_CPU_RESET:
|
||||
// //run_on_cpu(CPU(dst_cpu), sigp_cpu_reset, RUN_ON_CPU_HOST_PTR(&si));
|
||||
// break;
|
||||
// case SIGP_COND_EMERGENCY:
|
||||
// sigp_cond_emergency(cpu, dst_cpu, &si);
|
||||
// break;
|
||||
// case SIGP_SENSE_RUNNING:
|
||||
// sigp_sense_running(dst_cpu, &si);
|
||||
// break;
|
||||
// default:
|
||||
// set_sigp_status(&si, SIGP_STAT_INVALID_ORDER);
|
||||
// }
|
||||
|
||||
return si.cc;
|
||||
}
|
||||
// return si.cc;
|
||||
// }
|
||||
|
||||
static int sigp_set_architecture(S390CPU *cpu, uint32_t param,
|
||||
uint64_t *status_reg)
|
||||
{
|
||||
bool all_stopped = true;
|
||||
// static int sigp_set_architecture(S390CPU *cpu, uint32_t param,
|
||||
// uint64_t *status_reg)
|
||||
// {
|
||||
// bool all_stopped = true;
|
||||
|
||||
#if 0
|
||||
CPU_FOREACH(cur_cs) {
|
||||
cur_cpu = S390_CPU(cur_cs);
|
||||
// #if 0
|
||||
// CPU_FOREACH(cur_cs) {
|
||||
// cur_cpu = S390_CPU(cur_cs);
|
||||
|
||||
if (cur_cpu == cpu) {
|
||||
continue;
|
||||
}
|
||||
if (s390_cpu_get_state(cur_cpu) != S390_CPU_STATE_STOPPED) {
|
||||
all_stopped = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// if (cur_cpu == cpu) {
|
||||
// continue;
|
||||
// }
|
||||
// if (s390_cpu_get_state(cur_cpu) != S390_CPU_STATE_STOPPED) {
|
||||
// all_stopped = false;
|
||||
// }
|
||||
// }
|
||||
// #endif
|
||||
|
||||
all_stopped = false;
|
||||
*status_reg &= 0xffffffff00000000ULL;
|
||||
// all_stopped = false;
|
||||
// *status_reg &= 0xffffffff00000000ULL;
|
||||
|
||||
/* Reject set arch order, with czam we're always in z/Arch mode. */
|
||||
*status_reg |= (all_stopped ? SIGP_STAT_INVALID_PARAMETER :
|
||||
SIGP_STAT_INCORRECT_STATE);
|
||||
return SIGP_CC_STATUS_STORED;
|
||||
}
|
||||
// /* Reject set arch order, with czam we're always in z/Arch mode. */
|
||||
// *status_reg |= (all_stopped ? SIGP_STAT_INVALID_PARAMETER :
|
||||
// SIGP_STAT_INCORRECT_STATE);
|
||||
// return SIGP_CC_STATUS_STORED;
|
||||
// }
|
||||
|
||||
#if 0
|
||||
int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3)
|
||||
|
@ -12,7 +12,12 @@ S390CPU *cpu_s390_init(struct uc_struct *uc, const char *cpu_model);
|
||||
|
||||
static void s390_set_pc(struct uc_struct *uc, uint64_t address)
|
||||
{
|
||||
// ((CPUS390XState *)uc->cpu->env_ptr)->pc = address;
|
||||
((CPUS390XState *)uc->cpu->env_ptr)->psw.addr = address;
|
||||
}
|
||||
|
||||
static uint64_t s390_get_pc(struct uc_struct *uc)
|
||||
{
|
||||
return ((CPUS390XState *)uc->cpu->env_ptr)->psw.addr;
|
||||
}
|
||||
|
||||
static void s390_release(void *ctx)
|
||||
@ -183,6 +188,7 @@ void s390_uc_init(struct uc_struct *uc)
|
||||
uc->reg_write = s390_reg_write;
|
||||
uc->reg_reset = s390_reg_reset;
|
||||
uc->set_pc = s390_set_pc;
|
||||
uc->get_pc = s390_get_pc;
|
||||
uc->cpus_init = s390_cpus_init;
|
||||
uc->cpu_context_size = offsetof(CPUS390XState, end_reset_fields);
|
||||
uc_common_init(uc);
|
||||
|
@ -24,6 +24,11 @@ static void sparc_set_pc(struct uc_struct *uc, uint64_t address)
|
||||
((CPUSPARCState *)uc->cpu->env_ptr)->npc = address + 4;
|
||||
}
|
||||
|
||||
static uint64_t sparc_get_pc(struct uc_struct *uc)
|
||||
{
|
||||
return ((CPUSPARCState *)uc->cpu->env_ptr)->pc;
|
||||
}
|
||||
|
||||
static void sparc_release(void *ctx)
|
||||
{
|
||||
int i;
|
||||
@ -190,6 +195,7 @@ void sparc_uc_init(struct uc_struct *uc)
|
||||
uc->reg_write = sparc_reg_write;
|
||||
uc->reg_reset = sparc_reg_reset;
|
||||
uc->set_pc = sparc_set_pc;
|
||||
uc->get_pc = sparc_get_pc;
|
||||
uc->stop_interrupt = sparc_stop_interrupt;
|
||||
uc->cpus_init = sparc_cpus_init;
|
||||
uc->cpu_context_size = offsetof(CPUSPARCState, irq_manager);
|
||||
|
@ -26,6 +26,11 @@ static void sparc_set_pc(struct uc_struct *uc, uint64_t address)
|
||||
((CPUSPARCState *)uc->cpu->env_ptr)->npc = address + 4;
|
||||
}
|
||||
|
||||
static uint64_t sparc_get_pc(struct uc_struct *uc)
|
||||
{
|
||||
return ((CPUSPARCState *)uc->cpu->env_ptr)->pc;
|
||||
}
|
||||
|
||||
static void sparc_release(void *ctx)
|
||||
{
|
||||
release_common(ctx);
|
||||
@ -196,6 +201,7 @@ void sparc64_uc_init(struct uc_struct* uc)
|
||||
uc->reg_write = sparc_reg_write;
|
||||
uc->reg_reset = sparc_reg_reset;
|
||||
uc->set_pc = sparc_set_pc;
|
||||
uc->get_pc = sparc_get_pc;
|
||||
uc->stop_interrupt = sparc_stop_interrupt;
|
||||
uc->cpus_init = sparc_cpus_init;
|
||||
uc_common_init(uc);
|
||||
|
17
qemu/target/tricore/cpu-param.h
Normal file
17
qemu/target/tricore/cpu-param.h
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* TriCore cpu parameters for qemu.
|
||||
*
|
||||
* Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#ifndef TRICORE_CPU_PARAM_H
|
||||
#define TRICORE_CPU_PARAM_H 1
|
||||
|
||||
#define TARGET_LONG_BITS 32
|
||||
#define TARGET_PAGE_BITS 14
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 32
|
||||
#define TARGET_VIRT_ADDR_SPACE_BITS 32
|
||||
#define NB_MMU_MODES 3
|
||||
|
||||
#endif
|
43
qemu/target/tricore/cpu-qom.h
Normal file
43
qemu/target/tricore/cpu-qom.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Modified for Unicorn Engine by Eric Poole <eric.poole@aptiv.com>, 2022
|
||||
Copyright 2022 Aptiv
|
||||
*/
|
||||
|
||||
#ifndef QEMU_TRICORE_CPU_QOM_H
|
||||
#define QEMU_TRICORE_CPU_QOM_H
|
||||
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
#define TYPE_TRICORE_CPU "tricore-cpu"
|
||||
|
||||
#define TRICORE_CPU(obj) ((TriCoreCPU *)obj)
|
||||
#define TRICORE_CPU_CLASS(klass) ((TriCoreCPUClass *)klass)
|
||||
#define TRICORE_CPU_GET_CLASS(obj) (&((TriCoreCPU *)obj)->cc)
|
||||
|
||||
typedef struct TriCoreCPUClass {
|
||||
/*< private >*/
|
||||
CPUClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
void (*parent_reset)(CPUState *cpu);
|
||||
} TriCoreCPUClass;
|
||||
|
||||
|
||||
#endif /* QEMU_TRICORE_CPU_QOM_H */
|
205
qemu/target/tricore/cpu.c
Normal file
205
qemu/target/tricore/cpu.c
Normal file
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* TriCore emulation for qemu: main translation routines.
|
||||
*
|
||||
* Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Modified for Unicorn Engine by Eric Poole <eric.poole@aptiv.com>, 2022
|
||||
Copyright 2022 Aptiv
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "cpu-qom.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
#include <uc_priv.h>
|
||||
|
||||
static inline void set_feature(CPUTriCoreState *env, int feature)
|
||||
{
|
||||
env->features |= 1ULL << feature;
|
||||
}
|
||||
|
||||
static void tricore_cpu_set_pc(CPUState *cs, vaddr value)
|
||||
{
|
||||
TriCoreCPU *cpu = TRICORE_CPU(cs);
|
||||
CPUTriCoreState *env = &cpu->env;
|
||||
|
||||
env->PC = value & ~(target_ulong)1;
|
||||
}
|
||||
|
||||
static void tricore_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
|
||||
{
|
||||
TriCoreCPU *cpu = TRICORE_CPU(cs);
|
||||
CPUTriCoreState *env = &cpu->env;
|
||||
|
||||
env->PC = tb->pc;
|
||||
}
|
||||
|
||||
static void tricore_cpu_reset(CPUState *dev)
|
||||
{
|
||||
CPUState *s = CPU(dev);
|
||||
TriCoreCPU *cpu = TRICORE_CPU(s);
|
||||
TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(cpu);
|
||||
CPUTriCoreState *env = &cpu->env;
|
||||
|
||||
tcc->parent_reset(dev);
|
||||
|
||||
memset(env, 0, offsetof(CPUTriCoreState, end_reset_fields));
|
||||
|
||||
cpu_state_reset(env);
|
||||
}
|
||||
|
||||
static bool tricore_cpu_has_work(CPUState *cs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void tricore_cpu_realizefn(CPUState *dev)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
TriCoreCPU *cpu = TRICORE_CPU(dev);
|
||||
CPUTriCoreState *env = &cpu->env;
|
||||
|
||||
cpu_exec_realizefn(cs);
|
||||
|
||||
/* Some features automatically imply others */
|
||||
if (tricore_feature(env, TRICORE_FEATURE_161)) {
|
||||
set_feature(env, TRICORE_FEATURE_16);
|
||||
}
|
||||
|
||||
if (tricore_feature(env, TRICORE_FEATURE_16)) {
|
||||
set_feature(env, TRICORE_FEATURE_131);
|
||||
}
|
||||
if (tricore_feature(env, TRICORE_FEATURE_131)) {
|
||||
set_feature(env, TRICORE_FEATURE_13);
|
||||
}
|
||||
cpu_reset(cs);
|
||||
}
|
||||
|
||||
|
||||
static void tricore_cpu_initfn(struct uc_struct *uc, CPUState *obj)
|
||||
{
|
||||
TriCoreCPU *cpu = TRICORE_CPU(obj);
|
||||
CPUTriCoreState *env = &cpu->env;
|
||||
|
||||
env->uc = uc;
|
||||
cpu_set_cpustate_pointers(cpu);
|
||||
}
|
||||
|
||||
static void tc1796_initfn(CPUState *obj)
|
||||
{
|
||||
TriCoreCPU *cpu = TRICORE_CPU(obj);
|
||||
|
||||
set_feature(&cpu->env, TRICORE_FEATURE_13);
|
||||
}
|
||||
|
||||
static void tc1797_initfn(CPUState *obj)
|
||||
{
|
||||
TriCoreCPU *cpu = TRICORE_CPU(obj);
|
||||
|
||||
set_feature(&cpu->env, TRICORE_FEATURE_131);
|
||||
}
|
||||
|
||||
static void tc27x_initfn(CPUState *obj)
|
||||
{
|
||||
TriCoreCPU *cpu = TRICORE_CPU(obj);
|
||||
|
||||
set_feature(&cpu->env, TRICORE_FEATURE_161);
|
||||
}
|
||||
|
||||
static void tricore_cpu_class_init(CPUClass *c)
|
||||
{
|
||||
TriCoreCPUClass *mcc = TRICORE_CPU_CLASS(c);
|
||||
CPUClass *cc = CPU_CLASS(c);
|
||||
|
||||
/* parent class is CPUClass, parent_reset() is cpu_common_reset(). */
|
||||
mcc->parent_reset = cc->reset;
|
||||
|
||||
cc->reset = tricore_cpu_reset;
|
||||
cc->has_work = tricore_cpu_has_work;
|
||||
cc->set_pc = tricore_cpu_set_pc;
|
||||
|
||||
cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb;
|
||||
cc->get_phys_page_debug = tricore_cpu_get_phys_page_debug;
|
||||
|
||||
cc->tlb_fill = tricore_cpu_tlb_fill;
|
||||
cc->tcg_initialize = tricore_tcg_init;
|
||||
}
|
||||
|
||||
#define DEFINE_TRICORE_CPU_TYPE(cpu_model, initfn) \
|
||||
{ \
|
||||
.parent = TYPE_TRICORE_CPU, \
|
||||
.initfn = initfn, \
|
||||
.name = TRICORE_CPU_TYPE_NAME(cpu_model), \
|
||||
}
|
||||
|
||||
struct TriCoreCPUInfo {
|
||||
const char *name;
|
||||
void (*initfn)(CPUState *obj);
|
||||
};
|
||||
|
||||
static struct TriCoreCPUInfo tricore_cpus_type_infos[] = {
|
||||
{ "tc1796", tc1796_initfn },
|
||||
{ "tc1797", tc1797_initfn },
|
||||
{ "tc27x", tc27x_initfn },
|
||||
};
|
||||
|
||||
TriCoreCPU *cpu_tricore_init(struct uc_struct *uc)
|
||||
{
|
||||
TriCoreCPU *cpu;
|
||||
CPUState *cs;
|
||||
CPUClass *cc;
|
||||
|
||||
cpu = calloc(1, sizeof(*cpu));
|
||||
if (cpu == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uc->cpu_model == INT_MAX) {
|
||||
uc->cpu_model = 2; // tc27x
|
||||
} else if (uc->cpu_model >= ARRAY_SIZE(tricore_cpus_type_infos)) {
|
||||
free(cpu);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cs = (CPUState *)cpu;
|
||||
cc = (CPUClass *)&cpu->cc;
|
||||
cs->cc = cc;
|
||||
cs->uc = uc;
|
||||
uc->cpu = cs;
|
||||
|
||||
cpu_class_init(uc, cc);
|
||||
|
||||
tricore_cpu_class_init(cc);
|
||||
|
||||
cpu_common_initfn(uc, cs);
|
||||
|
||||
tricore_cpu_initfn(uc, cs);
|
||||
|
||||
tricore_cpus_type_infos[uc->cpu_model].initfn(cs);
|
||||
|
||||
tricore_cpu_realizefn(cs);
|
||||
|
||||
// init address space
|
||||
cpu_address_space_init(cs, 0, cs->memory);
|
||||
|
||||
qemu_init_vcpu(cs);
|
||||
|
||||
return cpu;
|
||||
}
|
||||
|
410
qemu/target/tricore/cpu.h
Normal file
410
qemu/target/tricore/cpu.h
Normal file
@ -0,0 +1,410 @@
|
||||
/*
|
||||
* TriCore emulation for qemu: main CPU struct.
|
||||
*
|
||||
* Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Modified for Unicorn Engine by Eric Poole <eric.poole@aptiv.com>, 2022
|
||||
Copyright 2022 Aptiv
|
||||
*/
|
||||
|
||||
#ifndef TRICORE_CPU_H
|
||||
#define TRICORE_CPU_H
|
||||
|
||||
#include "cpu-qom.h"
|
||||
#include "exec/cpu-defs.h"
|
||||
#include "tricore-defs.h"
|
||||
|
||||
struct tricore_boot_info;
|
||||
|
||||
typedef struct tricore_def_t tricore_def_t;
|
||||
|
||||
// struct CPUTriCoreState {
|
||||
typedef struct CPUTriCoreState {
|
||||
/* GPR Register */
|
||||
uint32_t gpr_a[16];
|
||||
uint32_t gpr_d[16];
|
||||
/* CSFR Register */
|
||||
uint32_t PCXI;
|
||||
/* Frequently accessed PSW_USB bits are stored separately for efficiency.
|
||||
This contains all the other bits. Use psw_{read,write} to access
|
||||
the whole PSW. */
|
||||
uint32_t PSW;
|
||||
|
||||
/* PSW flag cache for faster execution
|
||||
*/
|
||||
uint32_t PSW_USB_C;
|
||||
uint32_t PSW_USB_V; /* Only if bit 31 set, then flag is set */
|
||||
uint32_t PSW_USB_SV; /* Only if bit 31 set, then flag is set */
|
||||
uint32_t PSW_USB_AV; /* Only if bit 31 set, then flag is set. */
|
||||
uint32_t PSW_USB_SAV; /* Only if bit 31 set, then flag is set. */
|
||||
|
||||
uint32_t PC;
|
||||
uint32_t SYSCON;
|
||||
uint32_t CPU_ID;
|
||||
uint32_t CORE_ID;
|
||||
uint32_t BIV;
|
||||
uint32_t BTV;
|
||||
uint32_t ISP;
|
||||
uint32_t ICR;
|
||||
uint32_t FCX;
|
||||
uint32_t LCX;
|
||||
uint32_t COMPAT;
|
||||
|
||||
/* Mem Protection Register */
|
||||
uint32_t DPR0_0L;
|
||||
uint32_t DPR0_0U;
|
||||
uint32_t DPR0_1L;
|
||||
uint32_t DPR0_1U;
|
||||
uint32_t DPR0_2L;
|
||||
uint32_t DPR0_2U;
|
||||
uint32_t DPR0_3L;
|
||||
uint32_t DPR0_3U;
|
||||
|
||||
uint32_t DPR1_0L;
|
||||
uint32_t DPR1_0U;
|
||||
uint32_t DPR1_1L;
|
||||
uint32_t DPR1_1U;
|
||||
uint32_t DPR1_2L;
|
||||
uint32_t DPR1_2U;
|
||||
uint32_t DPR1_3L;
|
||||
uint32_t DPR1_3U;
|
||||
|
||||
uint32_t DPR2_0L;
|
||||
uint32_t DPR2_0U;
|
||||
uint32_t DPR2_1L;
|
||||
uint32_t DPR2_1U;
|
||||
uint32_t DPR2_2L;
|
||||
uint32_t DPR2_2U;
|
||||
uint32_t DPR2_3L;
|
||||
uint32_t DPR2_3U;
|
||||
|
||||
uint32_t DPR3_0L;
|
||||
uint32_t DPR3_0U;
|
||||
uint32_t DPR3_1L;
|
||||
uint32_t DPR3_1U;
|
||||
uint32_t DPR3_2L;
|
||||
uint32_t DPR3_2U;
|
||||
uint32_t DPR3_3L;
|
||||
uint32_t DPR3_3U;
|
||||
|
||||
uint32_t CPR0_0L;
|
||||
uint32_t CPR0_0U;
|
||||
uint32_t CPR0_1L;
|
||||
uint32_t CPR0_1U;
|
||||
uint32_t CPR0_2L;
|
||||
uint32_t CPR0_2U;
|
||||
uint32_t CPR0_3L;
|
||||
uint32_t CPR0_3U;
|
||||
|
||||
uint32_t CPR1_0L;
|
||||
uint32_t CPR1_0U;
|
||||
uint32_t CPR1_1L;
|
||||
uint32_t CPR1_1U;
|
||||
uint32_t CPR1_2L;
|
||||
uint32_t CPR1_2U;
|
||||
uint32_t CPR1_3L;
|
||||
uint32_t CPR1_3U;
|
||||
|
||||
uint32_t CPR2_0L;
|
||||
uint32_t CPR2_0U;
|
||||
uint32_t CPR2_1L;
|
||||
uint32_t CPR2_1U;
|
||||
uint32_t CPR2_2L;
|
||||
uint32_t CPR2_2U;
|
||||
uint32_t CPR2_3L;
|
||||
uint32_t CPR2_3U;
|
||||
|
||||
uint32_t CPR3_0L;
|
||||
uint32_t CPR3_0U;
|
||||
uint32_t CPR3_1L;
|
||||
uint32_t CPR3_1U;
|
||||
uint32_t CPR3_2L;
|
||||
uint32_t CPR3_2U;
|
||||
uint32_t CPR3_3L;
|
||||
uint32_t CPR3_3U;
|
||||
|
||||
uint32_t DPM0;
|
||||
uint32_t DPM1;
|
||||
uint32_t DPM2;
|
||||
uint32_t DPM3;
|
||||
|
||||
uint32_t CPM0;
|
||||
uint32_t CPM1;
|
||||
uint32_t CPM2;
|
||||
uint32_t CPM3;
|
||||
|
||||
/* Memory Management Registers */
|
||||
uint32_t MMU_CON;
|
||||
uint32_t MMU_ASI;
|
||||
uint32_t MMU_TVA;
|
||||
uint32_t MMU_TPA;
|
||||
uint32_t MMU_TPX;
|
||||
uint32_t MMU_TFA;
|
||||
/* {1.3.1 only */
|
||||
uint32_t BMACON;
|
||||
uint32_t SMACON;
|
||||
uint32_t DIEAR;
|
||||
uint32_t DIETR;
|
||||
uint32_t CCDIER;
|
||||
uint32_t MIECON;
|
||||
uint32_t PIEAR;
|
||||
uint32_t PIETR;
|
||||
uint32_t CCPIER;
|
||||
/*} */
|
||||
/* Debug Registers */
|
||||
uint32_t DBGSR;
|
||||
uint32_t EXEVT;
|
||||
uint32_t CREVT;
|
||||
uint32_t SWEVT;
|
||||
uint32_t TR0EVT;
|
||||
uint32_t TR1EVT;
|
||||
uint32_t DMS;
|
||||
uint32_t DCX;
|
||||
uint32_t DBGTCR;
|
||||
uint32_t CCTRL;
|
||||
uint32_t CCNT;
|
||||
uint32_t ICNT;
|
||||
uint32_t M1CNT;
|
||||
uint32_t M2CNT;
|
||||
uint32_t M3CNT;
|
||||
/* Floating Point Registers */
|
||||
float_status fp_status;
|
||||
/* QEMU */
|
||||
int error_code;
|
||||
uint32_t hflags; /* CPU State */
|
||||
|
||||
const tricore_def_t *cpu_model;
|
||||
void *irq[8];
|
||||
struct QEMUTimer *timer; /* Internal timer */
|
||||
|
||||
/* Fields up to this point are cleared by a CPU reset */
|
||||
int end_reset_fields;
|
||||
|
||||
/* Fields from here on are preserved across CPU reset. */
|
||||
uint32_t features;
|
||||
|
||||
// Unicorn engine
|
||||
struct uc_struct *uc;
|
||||
} CPUTriCoreState;
|
||||
|
||||
/**
|
||||
* TriCoreCPU:
|
||||
* @env: #CPUTriCoreState
|
||||
*
|
||||
* A TriCore CPU.
|
||||
*/
|
||||
// TODO: Why is the type def needed? Without it the later typedef fails to find this... ?
|
||||
typedef struct TriCoreCPU {
|
||||
/*< private >*/
|
||||
CPUState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
CPUNegativeOffsetState neg;
|
||||
CPUTriCoreState env;
|
||||
|
||||
struct TriCoreCPUClass cc;
|
||||
} TriCoreCPU;
|
||||
|
||||
hwaddr tricore_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
||||
void tricore_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
|
||||
|
||||
|
||||
#define MASK_PCXI_PCPN 0xff000000
|
||||
#define MASK_PCXI_PIE_1_3 0x00800000
|
||||
#define MASK_PCXI_PIE_1_6 0x00200000
|
||||
#define MASK_PCXI_UL 0x00400000
|
||||
#define MASK_PCXI_PCXS 0x000f0000
|
||||
#define MASK_PCXI_PCXO 0x0000ffff
|
||||
|
||||
#define MASK_PSW_USB 0xff000000
|
||||
#define MASK_USB_C 0x80000000
|
||||
#define MASK_USB_V 0x40000000
|
||||
#define MASK_USB_SV 0x20000000
|
||||
#define MASK_USB_AV 0x10000000
|
||||
#define MASK_USB_SAV 0x08000000
|
||||
#define MASK_PSW_PRS 0x00003000
|
||||
#define MASK_PSW_IO 0x00000c00
|
||||
#define MASK_PSW_IS 0x00000200
|
||||
#define MASK_PSW_GW 0x00000100
|
||||
#define MASK_PSW_CDE 0x00000080
|
||||
#define MASK_PSW_CDC 0x0000007f
|
||||
#define MASK_PSW_FPU_RM 0x3000000
|
||||
|
||||
#define MASK_SYSCON_PRO_TEN 0x2
|
||||
#define MASK_SYSCON_FCD_SF 0x1
|
||||
|
||||
#define MASK_CPUID_MOD 0xffff0000
|
||||
#define MASK_CPUID_MOD_32B 0x0000ff00
|
||||
#define MASK_CPUID_REV 0x000000ff
|
||||
|
||||
#define MASK_ICR_PIPN 0x00ff0000
|
||||
#define MASK_ICR_IE_1_3 0x00000100
|
||||
#define MASK_ICR_IE_1_6 0x00008000
|
||||
#define MASK_ICR_CCPN 0x000000ff
|
||||
|
||||
#define MASK_FCX_FCXS 0x000f0000
|
||||
#define MASK_FCX_FCXO 0x0000ffff
|
||||
|
||||
#define MASK_LCX_LCXS 0x000f0000
|
||||
#define MASK_LCX_LCX0 0x0000ffff
|
||||
|
||||
#define MASK_DBGSR_DE 0x1
|
||||
#define MASK_DBGSR_HALT 0x6
|
||||
#define MASK_DBGSR_SUSP 0x10
|
||||
#define MASK_DBGSR_PREVSUSP 0x20
|
||||
#define MASK_DBGSR_PEVT 0x40
|
||||
#define MASK_DBGSR_EVTSRC 0x1f00
|
||||
|
||||
#define TRICORE_HFLAG_KUU 0x3
|
||||
#define TRICORE_HFLAG_UM0 0x00002 /* user mode-0 flag */
|
||||
#define TRICORE_HFLAG_UM1 0x00001 /* user mode-1 flag */
|
||||
#define TRICORE_HFLAG_SM 0x00000 /* kernel mode flag */
|
||||
|
||||
enum tricore_features {
|
||||
TRICORE_FEATURE_13,
|
||||
TRICORE_FEATURE_131,
|
||||
TRICORE_FEATURE_16,
|
||||
TRICORE_FEATURE_161,
|
||||
};
|
||||
|
||||
static inline int tricore_feature(CPUTriCoreState *env, int feature)
|
||||
{
|
||||
return (env->features & (1ULL << feature)) != 0;
|
||||
}
|
||||
|
||||
/* TriCore Traps Classes*/
|
||||
enum {
|
||||
TRAPC_NONE = -1,
|
||||
TRAPC_MMU = 0,
|
||||
TRAPC_PROT = 1,
|
||||
TRAPC_INSN_ERR = 2,
|
||||
TRAPC_CTX_MNG = 3,
|
||||
TRAPC_SYSBUS = 4,
|
||||
TRAPC_ASSERT = 5,
|
||||
TRAPC_SYSCALL = 6,
|
||||
TRAPC_NMI = 7,
|
||||
TRAPC_IRQ = 8
|
||||
};
|
||||
|
||||
/* Class 0 TIN */
|
||||
enum {
|
||||
TIN0_VAF = 0,
|
||||
TIN0_VAP = 1,
|
||||
};
|
||||
|
||||
/* Class 1 TIN */
|
||||
enum {
|
||||
TIN1_PRIV = 1,
|
||||
TIN1_MPR = 2,
|
||||
TIN1_MPW = 3,
|
||||
TIN1_MPX = 4,
|
||||
TIN1_MPP = 5,
|
||||
TIN1_MPN = 6,
|
||||
TIN1_GRWP = 7,
|
||||
};
|
||||
|
||||
/* Class 2 TIN */
|
||||
enum {
|
||||
TIN2_IOPC = 1,
|
||||
TIN2_UOPC = 2,
|
||||
TIN2_OPD = 3,
|
||||
TIN2_ALN = 4,
|
||||
TIN2_MEM = 5,
|
||||
};
|
||||
|
||||
/* Class 3 TIN */
|
||||
enum {
|
||||
TIN3_FCD = 1,
|
||||
TIN3_CDO = 2,
|
||||
TIN3_CDU = 3,
|
||||
TIN3_FCU = 4,
|
||||
TIN3_CSU = 5,
|
||||
TIN3_CTYP = 6,
|
||||
TIN3_NEST = 7,
|
||||
};
|
||||
|
||||
/* Class 4 TIN */
|
||||
enum {
|
||||
TIN4_PSE = 1,
|
||||
TIN4_DSE = 2,
|
||||
TIN4_DAE = 3,
|
||||
TIN4_CAE = 4,
|
||||
TIN4_PIE = 5,
|
||||
TIN4_DIE = 6,
|
||||
};
|
||||
|
||||
/* Class 5 TIN */
|
||||
enum {
|
||||
TIN5_OVF = 1,
|
||||
TIN5_SOVF = 1,
|
||||
};
|
||||
|
||||
/* Class 6 TIN
|
||||
*
|
||||
* Is always TIN6_SYS
|
||||
*/
|
||||
|
||||
/* Class 7 TIN */
|
||||
enum {
|
||||
TIN7_NMI = 0,
|
||||
};
|
||||
|
||||
uint32_t psw_read(CPUTriCoreState *env);
|
||||
void psw_write(CPUTriCoreState *env, uint32_t val);
|
||||
int tricore_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n);
|
||||
int tricore_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n);
|
||||
|
||||
void fpu_set_state(CPUTriCoreState *env);
|
||||
|
||||
#define MMU_USER_IDX 2
|
||||
|
||||
void tricore_cpu_list(void);
|
||||
|
||||
#define cpu_list tricore_cpu_list
|
||||
|
||||
static inline int cpu_mmu_index(CPUTriCoreState *env, bool ifetch)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef CPUTriCoreState CPUArchState;
|
||||
typedef TriCoreCPU ArchCPU;
|
||||
|
||||
#include "exec/cpu-all.h"
|
||||
|
||||
void cpu_state_reset(CPUTriCoreState *s);
|
||||
void tricore_tcg_init(struct uc_struct *uc);
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUTriCoreState *env, target_ulong *pc,
|
||||
target_ulong *cs_base, uint32_t *flags)
|
||||
{
|
||||
*pc = env->PC;
|
||||
*cs_base = 0;
|
||||
*flags = 0;
|
||||
}
|
||||
|
||||
#define TRICORE_CPU_TYPE_SUFFIX "-" TYPE_TRICORE_CPU
|
||||
#define TRICORE_CPU_TYPE_NAME(model) model TRICORE_CPU_TYPE_SUFFIX
|
||||
#define CPU_RESOLVING_TYPE TYPE_TRICORE_CPU
|
||||
|
||||
/* helpers.c */
|
||||
bool tricore_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool probe, uintptr_t retaddr);
|
||||
|
||||
#endif /* TRICORE_CPU_H */
|
125
qemu/target/tricore/csfr.def
Normal file
125
qemu/target/tricore/csfr.def
Normal file
@ -0,0 +1,125 @@
|
||||
/* A(ll) access permited
|
||||
R(ead only) access
|
||||
E(nd init protected) access
|
||||
|
||||
A|R|E(offset, register, feature introducing reg)
|
||||
|
||||
NOTE: PSW is handled as a special case in gen_mtcr/mfcr */
|
||||
|
||||
A(0xfe00, PCXI, TRICORE_FEATURE_13)
|
||||
A(0xfe08, PC, TRICORE_FEATURE_13)
|
||||
A(0xfe14, SYSCON, TRICORE_FEATURE_13)
|
||||
R(0xfe18, CPU_ID, TRICORE_FEATURE_13)
|
||||
R(0xfe1c, CORE_ID, TRICORE_FEATURE_161)
|
||||
E(0xfe20, BIV, TRICORE_FEATURE_13)
|
||||
E(0xfe24, BTV, TRICORE_FEATURE_13)
|
||||
E(0xfe28, ISP, TRICORE_FEATURE_13)
|
||||
A(0xfe2c, ICR, TRICORE_FEATURE_13)
|
||||
A(0xfe38, FCX, TRICORE_FEATURE_13)
|
||||
A(0xfe3c, LCX, TRICORE_FEATURE_13)
|
||||
E(0x9400, COMPAT, TRICORE_FEATURE_131)
|
||||
/* memory protection register */
|
||||
A(0xC000, DPR0_0L, TRICORE_FEATURE_13)
|
||||
A(0xC004, DPR0_0U, TRICORE_FEATURE_13)
|
||||
A(0xC008, DPR0_1L, TRICORE_FEATURE_13)
|
||||
A(0xC00C, DPR0_1U, TRICORE_FEATURE_13)
|
||||
A(0xC010, DPR0_2L, TRICORE_FEATURE_13)
|
||||
A(0xC014, DPR0_2U, TRICORE_FEATURE_13)
|
||||
A(0xC018, DPR0_3L, TRICORE_FEATURE_13)
|
||||
A(0xC01C, DPR0_3U, TRICORE_FEATURE_13)
|
||||
A(0xC400, DPR1_0L, TRICORE_FEATURE_13)
|
||||
A(0xC404, DPR1_0U, TRICORE_FEATURE_13)
|
||||
A(0xC408, DPR1_1L, TRICORE_FEATURE_13)
|
||||
A(0xC40C, DPR1_1U, TRICORE_FEATURE_13)
|
||||
A(0xC410, DPR1_2L, TRICORE_FEATURE_13)
|
||||
A(0xC414, DPR1_2U, TRICORE_FEATURE_13)
|
||||
A(0xC418, DPR1_3L, TRICORE_FEATURE_13)
|
||||
A(0xC41C, DPR1_3U, TRICORE_FEATURE_13)
|
||||
A(0xC800, DPR2_0L, TRICORE_FEATURE_13)
|
||||
A(0xC804, DPR2_0U, TRICORE_FEATURE_13)
|
||||
A(0xC808, DPR2_1L, TRICORE_FEATURE_13)
|
||||
A(0xC80C, DPR2_1U, TRICORE_FEATURE_13)
|
||||
A(0xC810, DPR2_2L, TRICORE_FEATURE_13)
|
||||
A(0xC814, DPR2_2U, TRICORE_FEATURE_13)
|
||||
A(0xC818, DPR2_3L, TRICORE_FEATURE_13)
|
||||
A(0xC81C, DPR2_3U, TRICORE_FEATURE_13)
|
||||
A(0xCC00, DPR3_0L, TRICORE_FEATURE_13)
|
||||
A(0xCC04, DPR3_0U, TRICORE_FEATURE_13)
|
||||
A(0xCC08, DPR3_1L, TRICORE_FEATURE_13)
|
||||
A(0xCC0C, DPR3_1U, TRICORE_FEATURE_13)
|
||||
A(0xCC10, DPR3_2L, TRICORE_FEATURE_13)
|
||||
A(0xCC14, DPR3_2U, TRICORE_FEATURE_13)
|
||||
A(0xCC18, DPR3_3L, TRICORE_FEATURE_13)
|
||||
A(0xCC1C, DPR3_3U, TRICORE_FEATURE_13)
|
||||
A(0xD000, CPR0_0L, TRICORE_FEATURE_13)
|
||||
A(0xD004, CPR0_0U, TRICORE_FEATURE_13)
|
||||
A(0xD008, CPR0_1L, TRICORE_FEATURE_13)
|
||||
A(0xD00C, CPR0_1U, TRICORE_FEATURE_13)
|
||||
A(0xD010, CPR0_2L, TRICORE_FEATURE_13)
|
||||
A(0xD014, CPR0_2U, TRICORE_FEATURE_13)
|
||||
A(0xD018, CPR0_3L, TRICORE_FEATURE_13)
|
||||
A(0xD01C, CPR0_3U, TRICORE_FEATURE_13)
|
||||
A(0xD400, CPR1_0L, TRICORE_FEATURE_13)
|
||||
A(0xD404, CPR1_0U, TRICORE_FEATURE_13)
|
||||
A(0xD408, CPR1_1L, TRICORE_FEATURE_13)
|
||||
A(0xD40C, CPR1_1U, TRICORE_FEATURE_13)
|
||||
A(0xD410, CPR1_2L, TRICORE_FEATURE_13)
|
||||
A(0xD414, CPR1_2U, TRICORE_FEATURE_13)
|
||||
A(0xD418, CPR1_3L, TRICORE_FEATURE_13)
|
||||
A(0xD41C, CPR1_3U, TRICORE_FEATURE_13)
|
||||
A(0xD800, CPR2_0L, TRICORE_FEATURE_13)
|
||||
A(0xD804, CPR2_0U, TRICORE_FEATURE_13)
|
||||
A(0xD808, CPR2_1L, TRICORE_FEATURE_13)
|
||||
A(0xD80C, CPR2_1U, TRICORE_FEATURE_13)
|
||||
A(0xD810, CPR2_2L, TRICORE_FEATURE_13)
|
||||
A(0xD814, CPR2_2U, TRICORE_FEATURE_13)
|
||||
A(0xD818, CPR2_3L, TRICORE_FEATURE_13)
|
||||
A(0xD81C, CPR2_3U, TRICORE_FEATURE_13)
|
||||
A(0xDC00, CPR3_0L, TRICORE_FEATURE_13)
|
||||
A(0xDC04, CPR3_0U, TRICORE_FEATURE_13)
|
||||
A(0xDC08, CPR3_1L, TRICORE_FEATURE_13)
|
||||
A(0xDC0C, CPR3_1U, TRICORE_FEATURE_13)
|
||||
A(0xDC10, CPR3_2L, TRICORE_FEATURE_13)
|
||||
A(0xDC14, CPR3_2U, TRICORE_FEATURE_13)
|
||||
A(0xDC18, CPR3_3L, TRICORE_FEATURE_13)
|
||||
A(0xDC1C, CPR3_3U, TRICORE_FEATURE_13)
|
||||
A(0xE000, DPM0, TRICORE_FEATURE_13)
|
||||
A(0xE080, DPM1, TRICORE_FEATURE_13)
|
||||
A(0xE100, DPM2, TRICORE_FEATURE_13)
|
||||
A(0xE180, DPM3, TRICORE_FEATURE_13)
|
||||
A(0xE200, CPM0, TRICORE_FEATURE_13)
|
||||
A(0xE280, CPM1, TRICORE_FEATURE_13)
|
||||
A(0xE300, CPM2, TRICORE_FEATURE_13)
|
||||
A(0xE380, CPM3, TRICORE_FEATURE_13)
|
||||
/* memory management registers */
|
||||
A(0x8000, MMU_CON, TRICORE_FEATURE_13)
|
||||
A(0x8004, MMU_ASI, TRICORE_FEATURE_13)
|
||||
A(0x800C, MMU_TVA, TRICORE_FEATURE_13)
|
||||
A(0x8010, MMU_TPA, TRICORE_FEATURE_13)
|
||||
A(0x8014, MMU_TPX, TRICORE_FEATURE_13)
|
||||
A(0x8018, MMU_TFA, TRICORE_FEATURE_13)
|
||||
E(0x9004, BMACON, TRICORE_FEATURE_131)
|
||||
E(0x900C, SMACON, TRICORE_FEATURE_131)
|
||||
A(0x9020, DIEAR, TRICORE_FEATURE_131)
|
||||
A(0x9024, DIETR, TRICORE_FEATURE_131)
|
||||
A(0x9028, CCDIER, TRICORE_FEATURE_131)
|
||||
E(0x9044, MIECON, TRICORE_FEATURE_131)
|
||||
A(0x9210, PIEAR, TRICORE_FEATURE_131)
|
||||
A(0x9214, PIETR, TRICORE_FEATURE_131)
|
||||
A(0x9218, CCPIER, TRICORE_FEATURE_131)
|
||||
/* debug registers */
|
||||
A(0xFD00, DBGSR, TRICORE_FEATURE_13)
|
||||
A(0xFD08, EXEVT, TRICORE_FEATURE_13)
|
||||
A(0xFD0C, CREVT, TRICORE_FEATURE_13)
|
||||
A(0xFD10, SWEVT, TRICORE_FEATURE_13)
|
||||
A(0xFD20, TR0EVT, TRICORE_FEATURE_13)
|
||||
A(0xFD24, TR1EVT, TRICORE_FEATURE_13)
|
||||
A(0xFD40, DMS, TRICORE_FEATURE_13)
|
||||
A(0xFD44, DCX, TRICORE_FEATURE_13)
|
||||
A(0xFD48, DBGTCR, TRICORE_FEATURE_131)
|
||||
A(0xFC00, CCTRL, TRICORE_FEATURE_131)
|
||||
A(0xFC04, CCNT, TRICORE_FEATURE_131)
|
||||
A(0xFC08, ICNT, TRICORE_FEATURE_131)
|
||||
A(0xFC0C, M1CNT, TRICORE_FEATURE_131)
|
||||
A(0xFC10, M2CNT, TRICORE_FEATURE_131)
|
||||
A(0xFC14, M3CNT, TRICORE_FEATURE_131)
|
478
qemu/target/tricore/fpu_helper.c
Normal file
478
qemu/target/tricore/fpu_helper.c
Normal file
@ -0,0 +1,478 @@
|
||||
/*
|
||||
* TriCore emulation for qemu: fpu helper.
|
||||
*
|
||||
* Copyright (c) 2016 Bastian Koppelmann University of Paderborn
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Modified for Unicorn Engine by Eric Poole <eric.poole@aptiv.com>, 2022
|
||||
Copyright 2022 Aptiv
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "fpu/softfloat.h"
|
||||
|
||||
#define QUIET_NAN 0x7fc00000
|
||||
#define ADD_NAN 0x7fc00001
|
||||
#define SQRT_NAN 0x7fc00004
|
||||
#define DIV_NAN 0x7fc00008
|
||||
#define MUL_NAN 0x7fc00002
|
||||
#define FPU_FS PSW_USB_C
|
||||
#define FPU_FI PSW_USB_V
|
||||
#define FPU_FV PSW_USB_SV
|
||||
#define FPU_FZ PSW_USB_AV
|
||||
#define FPU_FU PSW_USB_SAV
|
||||
|
||||
#define float32_sqrt_nan make_float32(SQRT_NAN)
|
||||
#define float32_quiet_nan make_float32(QUIET_NAN)
|
||||
|
||||
/* we don't care about input_denormal */
|
||||
static inline uint8_t f_get_excp_flags(CPUTriCoreState *env)
|
||||
{
|
||||
return get_float_exception_flags(&env->fp_status)
|
||||
& (float_flag_invalid
|
||||
| float_flag_overflow
|
||||
| float_flag_underflow
|
||||
| float_flag_output_denormal
|
||||
| float_flag_divbyzero
|
||||
| float_flag_inexact);
|
||||
}
|
||||
|
||||
static inline float32 f_maddsub_nan_result(float32 arg1, float32 arg2,
|
||||
float32 arg3, float32 result,
|
||||
uint32_t muladd_negate_c)
|
||||
{
|
||||
uint32_t aSign, bSign, cSign;
|
||||
uint32_t aExp, bExp, cExp;
|
||||
|
||||
if (float32_is_any_nan(arg1) || float32_is_any_nan(arg2) ||
|
||||
float32_is_any_nan(arg3)) {
|
||||
return QUIET_NAN;
|
||||
} else if (float32_is_infinity(arg1) && float32_is_zero(arg2)) {
|
||||
return MUL_NAN;
|
||||
} else if (float32_is_zero(arg1) && float32_is_infinity(arg2)) {
|
||||
return MUL_NAN;
|
||||
} else {
|
||||
aSign = arg1 >> 31;
|
||||
bSign = arg2 >> 31;
|
||||
cSign = arg3 >> 31;
|
||||
|
||||
aExp = (arg1 >> 23) & 0xff;
|
||||
bExp = (arg2 >> 23) & 0xff;
|
||||
cExp = (arg3 >> 23) & 0xff;
|
||||
|
||||
if (muladd_negate_c) {
|
||||
cSign ^= 1;
|
||||
}
|
||||
if (((aExp == 0xff) || (bExp == 0xff)) && (cExp == 0xff)) {
|
||||
if (aSign ^ bSign ^ cSign) {
|
||||
return ADD_NAN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void f_update_psw_flags(CPUTriCoreState *env, uint8_t flags)
|
||||
{
|
||||
uint8_t some_excp = 0;
|
||||
set_float_exception_flags(0, &env->fp_status);
|
||||
|
||||
if (flags & float_flag_invalid) {
|
||||
env->FPU_FI = 1 << 31;
|
||||
some_excp = 1;
|
||||
}
|
||||
|
||||
if (flags & float_flag_overflow) {
|
||||
env->FPU_FV = 1 << 31;
|
||||
some_excp = 1;
|
||||
}
|
||||
|
||||
if (flags & float_flag_underflow || flags & float_flag_output_denormal) {
|
||||
env->FPU_FU = 1 << 31;
|
||||
some_excp = 1;
|
||||
}
|
||||
|
||||
if (flags & float_flag_divbyzero) {
|
||||
env->FPU_FZ = 1 << 31;
|
||||
some_excp = 1;
|
||||
}
|
||||
|
||||
if (flags & float_flag_inexact || flags & float_flag_output_denormal) {
|
||||
env->PSW |= 1 << 26;
|
||||
some_excp = 1;
|
||||
}
|
||||
|
||||
env->FPU_FS = some_excp;
|
||||
}
|
||||
|
||||
#define FADD_SUB(op) \
|
||||
uint32_t helper_f##op(CPUTriCoreState *env, uint32_t r1, uint32_t r2) \
|
||||
{ \
|
||||
float32 arg1 = make_float32(r1); \
|
||||
float32 arg2 = make_float32(r2); \
|
||||
uint32_t flags; \
|
||||
float32 f_result; \
|
||||
\
|
||||
f_result = float32_##op(arg2, arg1, &env->fp_status); \
|
||||
flags = f_get_excp_flags(env); \
|
||||
if (flags) { \
|
||||
/* If the output is a NaN, but the inputs aren't, \
|
||||
we return a unique value. */ \
|
||||
if ((flags & float_flag_invalid) \
|
||||
&& !float32_is_any_nan(arg1) \
|
||||
&& !float32_is_any_nan(arg2)) { \
|
||||
f_result = ADD_NAN; \
|
||||
} \
|
||||
f_update_psw_flags(env, flags); \
|
||||
} else { \
|
||||
env->FPU_FS = 0; \
|
||||
} \
|
||||
return (uint32_t)f_result; \
|
||||
}
|
||||
FADD_SUB(add)
|
||||
FADD_SUB(sub)
|
||||
|
||||
uint32_t helper_fmul(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
|
||||
{
|
||||
uint32_t flags;
|
||||
float32 arg1 = make_float32(r1);
|
||||
float32 arg2 = make_float32(r2);
|
||||
float32 f_result;
|
||||
|
||||
f_result = float32_mul(arg1, arg2, &env->fp_status);
|
||||
|
||||
flags = f_get_excp_flags(env);
|
||||
if (flags) {
|
||||
/* If the output is a NaN, but the inputs aren't,
|
||||
we return a unique value. */
|
||||
if ((flags & float_flag_invalid)
|
||||
&& !float32_is_any_nan(arg1)
|
||||
&& !float32_is_any_nan(arg2)) {
|
||||
f_result = MUL_NAN;
|
||||
}
|
||||
f_update_psw_flags(env, flags);
|
||||
} else {
|
||||
env->FPU_FS = 0;
|
||||
}
|
||||
return (uint32_t)f_result;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Target TriCore QSEED.F significand Lookup Table
|
||||
*
|
||||
* The QSEED.F output significand depends on the least-significant
|
||||
* exponent bit and the 6 most-significant significand bits.
|
||||
*
|
||||
* IEEE 754 float datatype
|
||||
* partitioned into Sign (S), Exponent (E) and Significand (M):
|
||||
*
|
||||
* S E E E E E E E E M M M M M M ...
|
||||
* | | |
|
||||
* +------+------+-------+-------+
|
||||
* | |
|
||||
* for lookup table
|
||||
* calculating index for
|
||||
* output E output M
|
||||
*
|
||||
* This lookup table was extracted by analyzing QSEED output
|
||||
* from the real hardware
|
||||
*/
|
||||
static const uint8_t target_qseed_significand_table[128] = {
|
||||
253, 252, 245, 244, 239, 238, 231, 230, 225, 224, 217, 216,
|
||||
211, 210, 205, 204, 201, 200, 195, 194, 189, 188, 185, 184,
|
||||
179, 178, 175, 174, 169, 168, 165, 164, 161, 160, 157, 156,
|
||||
153, 152, 149, 148, 145, 144, 141, 140, 137, 136, 133, 132,
|
||||
131, 130, 127, 126, 123, 122, 121, 120, 117, 116, 115, 114,
|
||||
111, 110, 109, 108, 103, 102, 99, 98, 93, 92, 89, 88, 83,
|
||||
82, 79, 78, 75, 74, 71, 70, 67, 66, 63, 62, 59, 58, 55,
|
||||
54, 53, 52, 49, 48, 45, 44, 43, 42, 39, 38, 37, 36, 33,
|
||||
32, 31, 30, 27, 26, 25, 24, 23, 22, 19, 18, 17, 16, 15,
|
||||
14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2
|
||||
};
|
||||
|
||||
uint32_t helper_qseed(CPUTriCoreState *env, uint32_t r1)
|
||||
{
|
||||
uint32_t arg1, S, E, M, E_minus_one, m_idx;
|
||||
uint32_t new_E, new_M, new_S, result;
|
||||
|
||||
arg1 = make_float32(r1);
|
||||
|
||||
/* fetch IEEE-754 fields S, E and the uppermost 6-bit of M */
|
||||
S = extract32(arg1, 31, 1);
|
||||
E = extract32(arg1, 23, 8);
|
||||
M = extract32(arg1, 17, 6);
|
||||
|
||||
if (float32_is_any_nan(arg1)) {
|
||||
result = float32_quiet_nan;
|
||||
} else if (float32_is_zero_or_denormal(arg1)) {
|
||||
if (float32_is_neg(arg1)) {
|
||||
result = float32_infinity | (1 << 31);
|
||||
} else {
|
||||
result = float32_infinity;
|
||||
}
|
||||
} else if (float32_is_neg(arg1)) {
|
||||
result = float32_sqrt_nan;
|
||||
} else if (float32_is_infinity(arg1)) {
|
||||
result = float32_zero;
|
||||
} else {
|
||||
E_minus_one = E - 1;
|
||||
m_idx = ((E_minus_one & 1) << 6) | M;
|
||||
new_S = S;
|
||||
new_E = 0xBD - E_minus_one / 2;
|
||||
new_M = target_qseed_significand_table[m_idx];
|
||||
|
||||
result = 0;
|
||||
result = deposit32(result, 31, 1, new_S);
|
||||
result = deposit32(result, 23, 8, new_E);
|
||||
result = deposit32(result, 15, 8, new_M);
|
||||
}
|
||||
|
||||
if (float32_is_signaling_nan(arg1, &env->fp_status)
|
||||
|| result == float32_sqrt_nan) {
|
||||
env->FPU_FI = 1 << 31;
|
||||
env->FPU_FS = 1;
|
||||
} else {
|
||||
env->FPU_FS = 0;
|
||||
}
|
||||
|
||||
return (uint32_t) result;
|
||||
}
|
||||
|
||||
uint32_t helper_fdiv(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
|
||||
{
|
||||
uint32_t flags;
|
||||
float32 arg1 = make_float32(r1);
|
||||
float32 arg2 = make_float32(r2);
|
||||
float32 f_result;
|
||||
|
||||
f_result = float32_div(arg1, arg2 , &env->fp_status);
|
||||
|
||||
flags = f_get_excp_flags(env);
|
||||
if (flags) {
|
||||
/* If the output is a NaN, but the inputs aren't,
|
||||
we return a unique value. */
|
||||
if ((flags & float_flag_invalid)
|
||||
&& !float32_is_any_nan(arg1)
|
||||
&& !float32_is_any_nan(arg2)) {
|
||||
f_result = DIV_NAN;
|
||||
}
|
||||
f_update_psw_flags(env, flags);
|
||||
} else {
|
||||
env->FPU_FS = 0;
|
||||
}
|
||||
|
||||
return (uint32_t)f_result;
|
||||
}
|
||||
|
||||
uint32_t helper_fmadd(CPUTriCoreState *env, uint32_t r1,
|
||||
uint32_t r2, uint32_t r3)
|
||||
{
|
||||
uint32_t flags;
|
||||
float32 arg1 = make_float32(r1);
|
||||
float32 arg2 = make_float32(r2);
|
||||
float32 arg3 = make_float32(r3);
|
||||
float32 f_result;
|
||||
|
||||
f_result = float32_muladd(arg1, arg2, arg3, 0, &env->fp_status);
|
||||
|
||||
flags = f_get_excp_flags(env);
|
||||
if (flags) {
|
||||
if (flags & float_flag_invalid) {
|
||||
arg1 = float32_squash_input_denormal(arg1, &env->fp_status);
|
||||
arg2 = float32_squash_input_denormal(arg2, &env->fp_status);
|
||||
arg3 = float32_squash_input_denormal(arg3, &env->fp_status);
|
||||
f_result = f_maddsub_nan_result(arg1, arg2, arg3, f_result, 0);
|
||||
}
|
||||
f_update_psw_flags(env, flags);
|
||||
} else {
|
||||
env->FPU_FS = 0;
|
||||
}
|
||||
return (uint32_t)f_result;
|
||||
}
|
||||
|
||||
uint32_t helper_fmsub(CPUTriCoreState *env, uint32_t r1,
|
||||
uint32_t r2, uint32_t r3)
|
||||
{
|
||||
uint32_t flags;
|
||||
float32 arg1 = make_float32(r1);
|
||||
float32 arg2 = make_float32(r2);
|
||||
float32 arg3 = make_float32(r3);
|
||||
float32 f_result;
|
||||
|
||||
f_result = float32_muladd(arg1, arg2, arg3, float_muladd_negate_product,
|
||||
&env->fp_status);
|
||||
|
||||
flags = f_get_excp_flags(env);
|
||||
if (flags) {
|
||||
if (flags & float_flag_invalid) {
|
||||
arg1 = float32_squash_input_denormal(arg1, &env->fp_status);
|
||||
arg2 = float32_squash_input_denormal(arg2, &env->fp_status);
|
||||
arg3 = float32_squash_input_denormal(arg3, &env->fp_status);
|
||||
|
||||
f_result = f_maddsub_nan_result(arg1, arg2, arg3, f_result, 1);
|
||||
}
|
||||
f_update_psw_flags(env, flags);
|
||||
} else {
|
||||
env->FPU_FS = 0;
|
||||
}
|
||||
return (uint32_t)f_result;
|
||||
}
|
||||
|
||||
uint32_t helper_fcmp(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
|
||||
{
|
||||
uint32_t result, flags;
|
||||
float32 arg1 = make_float32(r1);
|
||||
float32 arg2 = make_float32(r2);
|
||||
|
||||
set_flush_inputs_to_zero(0, &env->fp_status);
|
||||
|
||||
result = 1 << (float32_compare_quiet(arg1, arg2, &env->fp_status) + 1);
|
||||
result |= float32_is_denormal(arg1) << 4;
|
||||
result |= float32_is_denormal(arg2) << 5;
|
||||
|
||||
flags = f_get_excp_flags(env);
|
||||
if (flags) {
|
||||
f_update_psw_flags(env, flags);
|
||||
} else {
|
||||
env->FPU_FS = 0;
|
||||
}
|
||||
|
||||
set_flush_inputs_to_zero(1, &env->fp_status);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t helper_ftoi(CPUTriCoreState *env, uint32_t arg)
|
||||
{
|
||||
float32 f_arg = make_float32(arg);
|
||||
int32_t result, flags;
|
||||
|
||||
result = float32_to_int32(f_arg, &env->fp_status);
|
||||
|
||||
flags = f_get_excp_flags(env);
|
||||
if (flags) {
|
||||
if (float32_is_any_nan(f_arg)) {
|
||||
result = 0;
|
||||
}
|
||||
f_update_psw_flags(env, flags);
|
||||
} else {
|
||||
env->FPU_FS = 0;
|
||||
}
|
||||
return (uint32_t)result;
|
||||
}
|
||||
|
||||
uint32_t helper_itof(CPUTriCoreState *env, uint32_t arg)
|
||||
{
|
||||
float32 f_result;
|
||||
uint32_t flags;
|
||||
f_result = int32_to_float32(arg, &env->fp_status);
|
||||
|
||||
flags = f_get_excp_flags(env);
|
||||
if (flags) {
|
||||
f_update_psw_flags(env, flags);
|
||||
} else {
|
||||
env->FPU_FS = 0;
|
||||
}
|
||||
return (uint32_t)f_result;
|
||||
}
|
||||
|
||||
uint32_t helper_utof(CPUTriCoreState *env, uint32_t arg)
|
||||
{
|
||||
float32 f_result;
|
||||
uint32_t flags;
|
||||
|
||||
f_result = uint32_to_float32(arg, &env->fp_status);
|
||||
|
||||
flags = f_get_excp_flags(env);
|
||||
if (flags) {
|
||||
f_update_psw_flags(env, flags);
|
||||
} else {
|
||||
env->FPU_FS = 0;
|
||||
}
|
||||
return (uint32_t)f_result;
|
||||
}
|
||||
|
||||
uint32_t helper_ftoiz(CPUTriCoreState *env, uint32_t arg)
|
||||
{
|
||||
float32 f_arg = make_float32(arg);
|
||||
uint32_t result;
|
||||
int32_t flags;
|
||||
|
||||
result = float32_to_int32_round_to_zero(f_arg, &env->fp_status);
|
||||
|
||||
flags = f_get_excp_flags(env);
|
||||
if (flags & float_flag_invalid) {
|
||||
flags &= ~float_flag_inexact;
|
||||
if (float32_is_any_nan(f_arg)) {
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags) {
|
||||
f_update_psw_flags(env, flags);
|
||||
} else {
|
||||
env->FPU_FS = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t helper_ftouz(CPUTriCoreState *env, uint32_t arg)
|
||||
{
|
||||
float32 f_arg = make_float32(arg);
|
||||
uint32_t result;
|
||||
int32_t flags;
|
||||
|
||||
result = float32_to_uint32_round_to_zero(f_arg, &env->fp_status);
|
||||
|
||||
flags = f_get_excp_flags(env);
|
||||
if (flags & float_flag_invalid) {
|
||||
flags &= ~float_flag_inexact;
|
||||
if (float32_is_any_nan(f_arg)) {
|
||||
result = 0;
|
||||
}
|
||||
} else if (float32_lt_quiet(f_arg, 0, &env->fp_status)) {
|
||||
flags = float_flag_invalid;
|
||||
result = 0;
|
||||
}
|
||||
|
||||
if (flags) {
|
||||
f_update_psw_flags(env, flags);
|
||||
} else {
|
||||
env->FPU_FS = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void helper_updfl(CPUTriCoreState *env, uint32_t arg)
|
||||
{
|
||||
env->FPU_FS = extract32(arg, 7, 1) & extract32(arg, 15, 1);
|
||||
env->FPU_FI = (extract32(arg, 6, 1) & extract32(arg, 14, 1)) << 31;
|
||||
env->FPU_FV = (extract32(arg, 5, 1) & extract32(arg, 13, 1)) << 31;
|
||||
env->FPU_FZ = (extract32(arg, 4, 1) & extract32(arg, 12, 1)) << 31;
|
||||
env->FPU_FU = (extract32(arg, 3, 1) & extract32(arg, 11, 1)) << 31;
|
||||
/* clear FX and RM */
|
||||
env->PSW &= ~(extract32(arg, 10, 1) << 26);
|
||||
env->PSW |= (extract32(arg, 2, 1) & extract32(arg, 10, 1)) << 26;
|
||||
|
||||
fpu_set_state(env);
|
||||
}
|
162
qemu/target/tricore/helper.c
Normal file
162
qemu/target/tricore/helper.c
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Modified for Unicorn Engine by Eric Poole <eric.poole@aptiv.com>, 2022
|
||||
Copyright 2022 Aptiv
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "fpu/softfloat-helpers.h"
|
||||
|
||||
enum {
|
||||
TLBRET_DIRTY = -4,
|
||||
TLBRET_INVALID = -3,
|
||||
TLBRET_NOMATCH = -2,
|
||||
TLBRET_BADADDR = -1,
|
||||
TLBRET_MATCH = 0
|
||||
};
|
||||
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
static int get_physical_address(CPUTriCoreState *env, hwaddr *physical,
|
||||
int *prot, target_ulong address,
|
||||
MMUAccessType access_type, int mmu_idx)
|
||||
{
|
||||
int ret = TLBRET_MATCH;
|
||||
|
||||
*physical = address & 0xFFFFFFFF;
|
||||
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
hwaddr tricore_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
|
||||
{
|
||||
TriCoreCPU *cpu = TRICORE_CPU(cs);
|
||||
hwaddr phys_addr;
|
||||
int prot;
|
||||
int mmu_idx = cpu_mmu_index(&cpu->env, false);
|
||||
|
||||
if (get_physical_address(&cpu->env, &phys_addr, &prot, addr,
|
||||
MMU_DATA_LOAD, mmu_idx)) {
|
||||
return -1;
|
||||
}
|
||||
return phys_addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* TODO: Add exeption support*/
|
||||
static void raise_mmu_exception(CPUTriCoreState *env, target_ulong address,
|
||||
int rw, int tlb_error)
|
||||
{
|
||||
}
|
||||
|
||||
bool tricore_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
MMUAccessType rw, int mmu_idx,
|
||||
bool probe, uintptr_t retaddr)
|
||||
{
|
||||
TriCoreCPU *cpu = TRICORE_CPU(cs);
|
||||
CPUTriCoreState *env = &cpu->env;
|
||||
hwaddr physical;
|
||||
int prot;
|
||||
int ret = 0;
|
||||
|
||||
rw &= 1;
|
||||
ret = get_physical_address(env, &physical, &prot,
|
||||
address, rw, mmu_idx);
|
||||
|
||||
// qemu_log_mask(CPU_LOG_MMU, "%s address=" TARGET_FMT_lx " ret %d physical "
|
||||
// TARGET_FMT_plx " prot %d\n",
|
||||
// __func__, (target_ulong)address, ret, physical, prot);
|
||||
|
||||
if (ret == TLBRET_MATCH) {
|
||||
tlb_set_page(cs, address & TARGET_PAGE_MASK,
|
||||
physical & TARGET_PAGE_MASK, prot | PAGE_EXEC,
|
||||
mmu_idx, TARGET_PAGE_SIZE);
|
||||
return true;
|
||||
} else {
|
||||
assert(ret < 0);
|
||||
if (probe) {
|
||||
return false;
|
||||
}
|
||||
raise_mmu_exception(env, address, rw, ret);
|
||||
cpu_loop_exit_restore(cs, retaddr);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void tricore_cpu_list_entry(gpointer data, gpointer user_data)
|
||||
{
|
||||
ObjectClass *oc = data;
|
||||
const char *typename;
|
||||
char *name;
|
||||
|
||||
typename = object_class_get_name(oc);
|
||||
name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_TRICORE_CPU));
|
||||
qemu_printf(" %s\n", name);
|
||||
g_free(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void tricore_cpu_list(void)
|
||||
{
|
||||
GSList *list;
|
||||
|
||||
list = object_class_get_list_sorted(TYPE_TRICORE_CPU, false);
|
||||
qemu_printf("Available CPUs:\n");
|
||||
g_slist_foreach(list, tricore_cpu_list_entry, NULL);
|
||||
g_slist_free(list);
|
||||
}
|
||||
#endif
|
||||
|
||||
void fpu_set_state(CPUTriCoreState *env)
|
||||
{
|
||||
set_float_rounding_mode(env->PSW & MASK_PSW_FPU_RM, &env->fp_status);
|
||||
set_flush_inputs_to_zero(1, &env->fp_status);
|
||||
set_flush_to_zero(1, &env->fp_status);
|
||||
set_default_nan_mode(1, &env->fp_status);
|
||||
}
|
||||
|
||||
uint32_t psw_read(CPUTriCoreState *env)
|
||||
{
|
||||
/* clear all USB bits */
|
||||
env->PSW &= 0x6ffffff;
|
||||
/* now set them from the cache */
|
||||
env->PSW |= ((env->PSW_USB_C != 0) << 31);
|
||||
env->PSW |= ((env->PSW_USB_V & (1 << 31)) >> 1);
|
||||
env->PSW |= ((env->PSW_USB_SV & (1 << 31)) >> 2);
|
||||
env->PSW |= ((env->PSW_USB_AV & (1 << 31)) >> 3);
|
||||
env->PSW |= ((env->PSW_USB_SAV & (1 << 31)) >> 4);
|
||||
|
||||
return env->PSW;
|
||||
}
|
||||
|
||||
void psw_write(CPUTriCoreState *env, uint32_t val)
|
||||
{
|
||||
env->PSW_USB_C = (val & MASK_USB_C);
|
||||
env->PSW_USB_V = (val & MASK_USB_V) << 1;
|
||||
env->PSW_USB_SV = (val & MASK_USB_SV) << 2;
|
||||
env->PSW_USB_AV = (val & MASK_USB_AV) << 3;
|
||||
env->PSW_USB_SAV = (val & MASK_USB_SAV) << 4;
|
||||
env->PSW = val;
|
||||
|
||||
fpu_set_state(env);
|
||||
}
|
163
qemu/target/tricore/helper.h
Normal file
163
qemu/target/tricore/helper.h
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Modified for Unicorn Engine by Eric Poole <eric.poole@aptiv.com>, 2022
|
||||
Copyright 2022 Aptiv
|
||||
*/
|
||||
|
||||
DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64)
|
||||
DEF_HELPER_6(uc_traceopcode, void, ptr, i64, i64, i32, ptr, i64)
|
||||
|
||||
/* Arithmetic */
|
||||
DEF_HELPER_3(add_ssov, i32, env, i32, i32)
|
||||
DEF_HELPER_3(add64_ssov, i64, env, i64, i64)
|
||||
DEF_HELPER_3(add_suov, i32, env, i32, i32)
|
||||
DEF_HELPER_3(add_h_ssov, i32, env, i32, i32)
|
||||
DEF_HELPER_3(add_h_suov, i32, env, i32, i32)
|
||||
DEF_HELPER_4(addr_h_ssov, i32, env, i64, i32, i32)
|
||||
DEF_HELPER_4(addsur_h_ssov, i32, env, i64, i32, i32)
|
||||
DEF_HELPER_3(sub_ssov, i32, env, i32, i32)
|
||||
DEF_HELPER_3(sub64_ssov, i64, env, i64, i64)
|
||||
DEF_HELPER_3(sub_suov, i32, env, i32, i32)
|
||||
DEF_HELPER_3(sub_h_ssov, i32, env, i32, i32)
|
||||
DEF_HELPER_3(sub_h_suov, i32, env, i32, i32)
|
||||
DEF_HELPER_4(subr_h_ssov, i32, env, i64, i32, i32)
|
||||
DEF_HELPER_4(subadr_h_ssov, i32, env, i64, i32, i32)
|
||||
DEF_HELPER_3(mul_ssov, i32, env, i32, i32)
|
||||
DEF_HELPER_3(mul_suov, i32, env, i32, i32)
|
||||
DEF_HELPER_3(sha_ssov, i32, env, i32, i32)
|
||||
DEF_HELPER_3(absdif_ssov, i32, env, i32, i32)
|
||||
DEF_HELPER_4(madd32_ssov, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_4(madd32_suov, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_4(madd64_ssov, i64, env, i32, i64, i32)
|
||||
DEF_HELPER_5(madd64_q_ssov, i64, env, i64, i32, i32, i32)
|
||||
DEF_HELPER_3(madd32_q_add_ssov, i32, env, i64, i64)
|
||||
DEF_HELPER_5(maddr_q_ssov, i32, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_4(madd64_suov, i64, env, i32, i64, i32)
|
||||
DEF_HELPER_4(msub32_ssov, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msub32_suov, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_4(msub64_ssov, i64, env, i32, i64, i32)
|
||||
DEF_HELPER_5(msub64_q_ssov, i64, env, i64, i32, i32, i32)
|
||||
DEF_HELPER_3(msub32_q_sub_ssov, i32, env, i64, i64)
|
||||
DEF_HELPER_5(msubr_q_ssov, i32, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_4(msub64_suov, i64, env, i32, i64, i32)
|
||||
DEF_HELPER_3(absdif_h_ssov, i32, env, i32, i32)
|
||||
DEF_HELPER_2(abs_ssov, i32, env, i32)
|
||||
DEF_HELPER_2(abs_h_ssov, i32, env, i32)
|
||||
/* hword/byte arithmetic */
|
||||
DEF_HELPER_2(abs_b, i32, env, i32)
|
||||
DEF_HELPER_2(abs_h, i32, env, i32)
|
||||
DEF_HELPER_3(absdif_b, i32, env, i32, i32)
|
||||
DEF_HELPER_3(absdif_h, i32, env, i32, i32)
|
||||
DEF_HELPER_4(addr_h, i32, env, i64, i32, i32)
|
||||
DEF_HELPER_4(addsur_h, i32, env, i64, i32, i32)
|
||||
DEF_HELPER_5(maddr_q, i32, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_3(add_b, i32, env, i32, i32)
|
||||
DEF_HELPER_3(add_h, i32, env, i32, i32)
|
||||
DEF_HELPER_3(sub_b, i32, env, i32, i32)
|
||||
DEF_HELPER_3(sub_h, i32, env, i32, i32)
|
||||
DEF_HELPER_4(subr_h, i32, env, i64, i32, i32)
|
||||
DEF_HELPER_4(subadr_h, i32, env, i64, i32, i32)
|
||||
DEF_HELPER_5(msubr_q, i32, env, i32, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(eq_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(eq_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(eqany_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(eqany_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(lt_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(lt_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(lt_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(lt_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(max_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(max_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(max_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(max_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(ixmax, TCG_CALL_NO_RWG_SE, i64, i64, i32)
|
||||
DEF_HELPER_FLAGS_2(ixmax_u, TCG_CALL_NO_RWG_SE, i64, i64, i32)
|
||||
DEF_HELPER_FLAGS_2(min_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(min_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(min_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(min_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(ixmin, TCG_CALL_NO_RWG_SE, i64, i64, i32)
|
||||
DEF_HELPER_FLAGS_2(ixmin_u, TCG_CALL_NO_RWG_SE, i64, i64, i32)
|
||||
/* count leading ... */
|
||||
DEF_HELPER_FLAGS_1(clo_h, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(clz_h, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(cls_h, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
/* sh */
|
||||
DEF_HELPER_FLAGS_2(sh, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(sh_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_3(sha, i32, env, i32, i32)
|
||||
DEF_HELPER_2(sha_h, i32, i32, i32)
|
||||
/* merge/split/parity */
|
||||
DEF_HELPER_FLAGS_2(bmerge, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_1(bsplit, TCG_CALL_NO_RWG_SE, i64, i32)
|
||||
DEF_HELPER_FLAGS_1(parity, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
/* float */
|
||||
DEF_HELPER_FLAGS_4(pack, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32, i32)
|
||||
DEF_HELPER_1(unpack, i64, i32)
|
||||
DEF_HELPER_3(fadd, i32, env, i32, i32)
|
||||
DEF_HELPER_3(fsub, i32, env, i32, i32)
|
||||
DEF_HELPER_3(fmul, i32, env, i32, i32)
|
||||
DEF_HELPER_3(fdiv, i32, env, i32, i32)
|
||||
DEF_HELPER_4(fmadd, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_4(fmsub, i32, env, i32, i32, i32)
|
||||
DEF_HELPER_3(fcmp, i32, env, i32, i32)
|
||||
DEF_HELPER_2(qseed, i32, env, i32)
|
||||
DEF_HELPER_2(ftoi, i32, env, i32)
|
||||
DEF_HELPER_2(itof, i32, env, i32)
|
||||
DEF_HELPER_2(utof, i32, env, i32)
|
||||
DEF_HELPER_2(ftoiz, i32, env, i32)
|
||||
DEF_HELPER_2(ftouz, i32, env, i32)
|
||||
DEF_HELPER_2(updfl, void, env, i32)
|
||||
/* dvinit */
|
||||
DEF_HELPER_3(dvinit_b_13, i64, env, i32, i32)
|
||||
DEF_HELPER_3(dvinit_b_131, i64, env, i32, i32)
|
||||
DEF_HELPER_3(dvinit_h_13, i64, env, i32, i32)
|
||||
DEF_HELPER_3(dvinit_h_131, i64, env, i32, i32)
|
||||
DEF_HELPER_FLAGS_2(dvadj, TCG_CALL_NO_RWG_SE, i64, i64, i32)
|
||||
DEF_HELPER_FLAGS_2(dvstep, TCG_CALL_NO_RWG_SE, i64, i64, i32)
|
||||
DEF_HELPER_FLAGS_2(dvstep_u, TCG_CALL_NO_RWG_SE, i64, i64, i32)
|
||||
DEF_HELPER_3(divide, i64, env, i32, i32)
|
||||
DEF_HELPER_3(divide_u, i64, env, i32, i32)
|
||||
/* mulh */
|
||||
DEF_HELPER_FLAGS_5(mul_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_5(mulm_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_5(mulr_h, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32, i32, i32)
|
||||
/* crc32 */
|
||||
DEF_HELPER_FLAGS_2(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32)
|
||||
/* CSA */
|
||||
DEF_HELPER_2(call, void, env, i32)
|
||||
DEF_HELPER_1(ret, void, env)
|
||||
DEF_HELPER_2(bisr, void, env, i32)
|
||||
DEF_HELPER_1(rfe, void, env)
|
||||
DEF_HELPER_1(rfm, void, env)
|
||||
DEF_HELPER_2(ldlcx, void, env, i32)
|
||||
DEF_HELPER_2(lducx, void, env, i32)
|
||||
DEF_HELPER_2(stlcx, void, env, i32)
|
||||
DEF_HELPER_2(stucx, void, env, i32)
|
||||
DEF_HELPER_1(svlcx, void, env)
|
||||
DEF_HELPER_1(svucx, void, env)
|
||||
DEF_HELPER_1(rslcx, void, env)
|
||||
/* Address mode helper */
|
||||
DEF_HELPER_1(br_update, i32, i32)
|
||||
DEF_HELPER_2(circ_update, i32, i32, i32)
|
||||
/* PSW cache helper */
|
||||
DEF_HELPER_2(psw_write, void, env, i32)
|
||||
DEF_HELPER_1(psw_read, i32, env)
|
||||
/* Exceptions */
|
||||
DEF_HELPER_3(raise_exception_sync, noreturn, env, i32, i32)
|
2795
qemu/target/tricore/op_helper.c
Normal file
2795
qemu/target/tricore/op_helper.c
Normal file
File diff suppressed because it is too large
Load Diff
9374
qemu/target/tricore/translate.c
Normal file
9374
qemu/target/tricore/translate.c
Normal file
File diff suppressed because it is too large
Load Diff
23
qemu/target/tricore/tricore-defs.h
Normal file
23
qemu/target/tricore/tricore-defs.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_TRICORE_DEFS_H
|
||||
#define QEMU_TRICORE_DEFS_H
|
||||
|
||||
#define TRICORE_TLB_MAX 128
|
||||
|
||||
#endif /* QEMU_TRICORE_DEFS_H */
|
1474
qemu/target/tricore/tricore-opcodes.h
Normal file
1474
qemu/target/tricore/tricore-opcodes.h
Normal file
File diff suppressed because it is too large
Load Diff
276
qemu/target/tricore/unicorn.c
Normal file
276
qemu/target/tricore/unicorn.c
Normal file
@ -0,0 +1,276 @@
|
||||
/* Unicorn Emulator Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015 */
|
||||
|
||||
/*
|
||||
Created for Unicorn Engine by Eric Poole <eric.poole@aptiv.com>, 2022
|
||||
Copyright 2022 Aptiv
|
||||
*/
|
||||
|
||||
#include "qemu/typedefs.h"
|
||||
#include "unicorn/unicorn.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "cpu.h"
|
||||
#include "uc_priv.h"
|
||||
#include "unicorn_common.h"
|
||||
#include "unicorn.h"
|
||||
|
||||
TriCoreCPU *cpu_tricore_init(struct uc_struct *uc);
|
||||
|
||||
static void tricore_set_pc(struct uc_struct *uc, uint64_t address)
|
||||
{
|
||||
((CPUTriCoreState *)uc->cpu->env_ptr)->PC = address;
|
||||
}
|
||||
|
||||
static uint64_t tricore_get_pc(struct uc_struct *uc)
|
||||
{
|
||||
return ((CPUTriCoreState *)uc->cpu->env_ptr)->PC;
|
||||
}
|
||||
|
||||
void tricore_reg_reset(struct uc_struct *uc)
|
||||
{
|
||||
CPUTriCoreState *env;
|
||||
(void)uc;
|
||||
|
||||
env = uc->cpu->env_ptr;
|
||||
memset(env->gpr_a, 0, sizeof(env->gpr_a));
|
||||
memset(env->gpr_d, 0, sizeof(env->gpr_d));
|
||||
|
||||
env->PC = 0;
|
||||
}
|
||||
|
||||
static void reg_read(CPUTriCoreState *env, unsigned int regid, void *value)
|
||||
{
|
||||
if (regid >= UC_TRICORE_REG_A0 && regid <= UC_TRICORE_REG_A9)
|
||||
*(int32_t *)value = env->gpr_a[regid - UC_TRICORE_REG_A0];
|
||||
if (regid >= UC_TRICORE_REG_A12 && regid <= UC_TRICORE_REG_A15)
|
||||
*(int32_t *)value = env->gpr_a[regid - UC_TRICORE_REG_A0];
|
||||
else if (regid >= UC_TRICORE_REG_D0 && regid <= UC_TRICORE_REG_D15)
|
||||
*(int32_t *)value = env->gpr_d[regid - UC_TRICORE_REG_D0];
|
||||
else {
|
||||
switch (regid) {
|
||||
// case UC_TRICORE_REG_SP:
|
||||
case UC_TRICORE_REG_A10:
|
||||
*(int32_t *)value = env->gpr_a[10];
|
||||
break;
|
||||
// case UC_TRICORE_REG_LR:
|
||||
case UC_TRICORE_REG_A11:
|
||||
*(int32_t *)value = env->gpr_a[11];
|
||||
break;
|
||||
case UC_TRICORE_REG_PC:
|
||||
*(int32_t *)value = env->PC;
|
||||
break;
|
||||
case UC_TRICORE_REG_PCXI:
|
||||
*(int32_t *)value = env->PCXI;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW:
|
||||
*(int32_t *)value = env->PSW;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_C:
|
||||
*(int32_t *)value = env->PSW_USB_C;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_V:
|
||||
*(int32_t *)value = env->PSW_USB_V;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_SV:
|
||||
*(int32_t *)value = env->PSW_USB_SV;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_AV:
|
||||
*(int32_t *)value = env->PSW_USB_AV;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_SAV:
|
||||
*(int32_t *)value = env->PSW_USB_SAV;
|
||||
break;
|
||||
case UC_TRICORE_REG_SYSCON:
|
||||
*(int32_t *)value = env->SYSCON;
|
||||
break;
|
||||
case UC_TRICORE_REG_CPU_ID:
|
||||
*(int32_t *)value = env->CPU_ID;
|
||||
break;
|
||||
case UC_TRICORE_REG_BIV:
|
||||
*(int32_t *)value = env->BIV;
|
||||
break;
|
||||
case UC_TRICORE_REG_BTV:
|
||||
*(int32_t *)value = env->BTV;
|
||||
break;
|
||||
case UC_TRICORE_REG_ISP:
|
||||
*(int32_t *)value = env->ISP;
|
||||
break;
|
||||
case UC_TRICORE_REG_ICR:
|
||||
*(int32_t *)value = env->ICR;
|
||||
break;
|
||||
case UC_TRICORE_REG_FCX:
|
||||
*(int32_t *)value = env->FCX;
|
||||
break;
|
||||
case UC_TRICORE_REG_LCX:
|
||||
*(int32_t *)value = env->LCX;
|
||||
break;
|
||||
case UC_TRICORE_REG_COMPAT:
|
||||
*(int32_t *)value = env->COMPAT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int tricore_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count)
|
||||
{
|
||||
CPUTriCoreState *env = &(TRICORE_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tricore_context_reg_read(struct uc_context *uc, unsigned int *regs,
|
||||
void **vals, int count)
|
||||
{
|
||||
CPUTriCoreState *env = (CPUTriCoreState *)uc->data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_read(env, regid, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void reg_write(CPUTriCoreState *env, unsigned int regid,
|
||||
const void *value)
|
||||
{
|
||||
if (regid >= UC_TRICORE_REG_A0 && regid <= UC_TRICORE_REG_A9)
|
||||
env->gpr_a[regid - UC_TRICORE_REG_A0] = *(int32_t *)value;
|
||||
if (regid >= UC_TRICORE_REG_A12 && regid <= UC_TRICORE_REG_A15)
|
||||
env->gpr_a[regid - UC_TRICORE_REG_A0] = *(int32_t *)value;
|
||||
else if (regid >= UC_TRICORE_REG_D0 && regid <= UC_TRICORE_REG_D15)
|
||||
env->gpr_d[regid - UC_TRICORE_REG_D0] = *(int32_t *)value;
|
||||
else {
|
||||
switch (regid) {
|
||||
// case UC_TRICORE_REG_SP:
|
||||
case UC_TRICORE_REG_A10:
|
||||
env->gpr_a[10] = *(int32_t *)value;
|
||||
break;
|
||||
// case UC_TRICORE_REG_LR:
|
||||
case UC_TRICORE_REG_A11:
|
||||
env->gpr_a[11] = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PC:
|
||||
env->PC = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PCXI:
|
||||
env->PCXI = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW:
|
||||
env->PSW = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_C:
|
||||
env->PSW_USB_C = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_V:
|
||||
env->PSW_USB_V = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_SV:
|
||||
env->PSW_USB_SV = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_AV:
|
||||
env->PSW_USB_AV = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_PSW_USB_SAV:
|
||||
env->PSW_USB_SAV = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_SYSCON:
|
||||
env->SYSCON = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_CPU_ID:
|
||||
env->CPU_ID = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_BIV:
|
||||
env->BIV = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_BTV:
|
||||
env->BTV = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_ISP:
|
||||
env->ISP = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_ICR:
|
||||
env->ICR = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_FCX:
|
||||
env->FCX = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_LCX:
|
||||
env->LCX = *(int32_t *)value;
|
||||
break;
|
||||
case UC_TRICORE_REG_COMPAT:
|
||||
env->COMPAT = *(int32_t *)value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int tricore_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
{
|
||||
CPUTriCoreState *env = &(TRICORE_CPU(uc->cpu)->env);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
if (regid == UC_TRICORE_REG_PC) {
|
||||
// force to quit execution and flush TB
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tricore_context_reg_write(struct uc_context *uc, unsigned int *regs,
|
||||
void *const *vals, int count)
|
||||
{
|
||||
CPUTriCoreState *env = (CPUTriCoreState *)uc->data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
unsigned int regid = regs[i];
|
||||
const void *value = vals[i];
|
||||
reg_write(env, regid, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tricore_cpus_init(struct uc_struct *uc, const char *cpu_model)
|
||||
{
|
||||
TriCoreCPU *cpu;
|
||||
|
||||
cpu = cpu_tricore_init(uc);
|
||||
if (cpu == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tricore_uc_init(struct uc_struct *uc)
|
||||
{
|
||||
uc->reg_read = tricore_reg_read;
|
||||
uc->reg_write = tricore_reg_write;
|
||||
uc->reg_reset = tricore_reg_reset;
|
||||
uc->set_pc = tricore_set_pc;
|
||||
uc->get_pc = tricore_get_pc;
|
||||
uc->cpus_init = tricore_cpus_init;
|
||||
uc->cpu_context_size = offsetof(CPUTriCoreState, end_reset_fields);
|
||||
uc_common_init(uc);
|
||||
}
|
27
qemu/target/tricore/unicorn.h
Normal file
27
qemu/target/tricore/unicorn.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* Unicorn Emulator Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015 */
|
||||
|
||||
/*
|
||||
Modified for Unicorn Engine by Eric Poole <eric.poole@aptiv.com>, 2022
|
||||
Copyright 2022 Aptiv
|
||||
*/
|
||||
|
||||
#ifndef UC_QEMU_TARGET_TRICORE_H
|
||||
#define UC_QEMU_TARGET_TRICORE_H
|
||||
|
||||
// functions to read & write registers
|
||||
int tricore_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals,
|
||||
int count);
|
||||
int tricore_reg_write(struct uc_struct *uc, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
|
||||
int tricore_context_reg_read(struct uc_context *uc, unsigned int *regs,
|
||||
void **vals, int count);
|
||||
int tricore_context_reg_write(struct uc_context *uc, unsigned int *regs,
|
||||
void *const *vals, int count);
|
||||
|
||||
void tricore_reg_reset(struct uc_struct *uc);
|
||||
|
||||
void tricore_uc_init(struct uc_struct *uc);
|
||||
|
||||
#endif
|
1289
qemu/tricore.h
Normal file
1289
qemu/tricore.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -89,6 +89,9 @@ endif
|
||||
ifneq (,$(findstring m68k,$(UNICORN_ARCHS)))
|
||||
SOURCES += sample_m68k.c
|
||||
endif
|
||||
ifneq (,$(findstring tricore,$(UNICORN_ARCHS)))
|
||||
SOURCES += sample_tricore.c
|
||||
endif
|
||||
|
||||
BINS = $(SOURCES:.c=$(BIN_EXT))
|
||||
OBJS = $(SOURCES:.c=.o)
|
||||
|
84
samples/sample_tricore.c
Normal file
84
samples/sample_tricore.c
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
Created for Unicorn Engine by Eric Poole <eric.poole@aptiv.com>, 2022
|
||||
Copyright 2022 Aptiv
|
||||
*/
|
||||
|
||||
/* Sample code to demonstrate how to emulate TriCore code */
|
||||
|
||||
#include <unicorn/unicorn.h>
|
||||
#include <string.h>
|
||||
|
||||
// code to be emulated
|
||||
#define CODE "\x82\x11\xbb\x00\x00\x08" // mov d0, #0x1; mov.u d0, #0x8000
|
||||
|
||||
// memory address where emulation starts
|
||||
#define ADDRESS 0x10000
|
||||
|
||||
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size,
|
||||
void *user_data)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n",
|
||||
address, size);
|
||||
}
|
||||
|
||||
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size,
|
||||
void *user_data)
|
||||
{
|
||||
printf(">>> Tracing instruction at 0x%" PRIx64
|
||||
", instruction size = 0x%x\n",
|
||||
address, size);
|
||||
}
|
||||
|
||||
static void test_tricore(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
uc_hook trace1, trace2;
|
||||
|
||||
uint32_t d0 = 0x0; // d0 register
|
||||
|
||||
printf("Emulate TriCore code\n");
|
||||
|
||||
// Initialize emulator in TriCore mode
|
||||
err = uc_open(UC_ARCH_TRICORE, UC_MODE_LITTLE_ENDIAN, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n", err,
|
||||
uc_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(uc, ADDRESS, CODE, sizeof(CODE) - 1);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0);
|
||||
|
||||
// tracing one instruction at ADDRESS with customized callback
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, ADDRESS,
|
||||
ADDRESS + sizeof(CODE) - 1);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(CODE) - 1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
||||
}
|
||||
|
||||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(uc, UC_TRICORE_REG_D0, &d0);
|
||||
printf(">>> d0 = 0x%x\n", d0);
|
||||
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
test_tricore();
|
||||
|
||||
return 0;
|
||||
}
|
14
symbols.sh
14
symbols.sh
@ -6274,7 +6274,19 @@ tcg_s390_program_interrupt \
|
||||
tcg_s390_data_exception \
|
||||
"
|
||||
|
||||
ARCHS="x86_64 arm aarch64 riscv32 riscv64 mips mipsel mips64 mips64el sparc sparc64 m68k ppc ppc64 s390x"
|
||||
tricore_SYMBOLS="
|
||||
helper_fadd \
|
||||
helper_fsub \
|
||||
helper_fmul \
|
||||
helper_fdiv \
|
||||
helper_fmadd \
|
||||
helper_fmsub \
|
||||
helper_pack \
|
||||
gen_intermediate_code \
|
||||
restore_state_to_opc \
|
||||
"
|
||||
|
||||
ARCHS="x86_64 arm aarch64 riscv32 riscv64 mips mipsel mips64 mips64el sparc sparc64 m68k ppc ppc64 s390x tricore"
|
||||
|
||||
for arch in $ARCHS; do
|
||||
|
||||
|
@ -195,10 +195,110 @@ static void test_arm64_mrs_hook(void)
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static bool test_arm64_correct_address_in_small_jump_hook_callback(
|
||||
uc_engine *uc, int type, uint64_t address, int size, int64_t value,
|
||||
void *user_data)
|
||||
{
|
||||
// Check registers
|
||||
uint64_t r_x0 = 0x0;
|
||||
uint64_t r_pc = 0x0;
|
||||
OK(uc_reg_read(uc, UC_ARM64_REG_X0, &r_x0));
|
||||
OK(uc_reg_read(uc, UC_ARM64_REG_PC, &r_pc));
|
||||
TEST_CHECK(r_x0 == 0x7F00);
|
||||
TEST_CHECK(r_pc == 0x7F00);
|
||||
|
||||
// Check address
|
||||
// printf("%lx\n", address);
|
||||
TEST_CHECK(address == 0x7F00);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void test_arm64_correct_address_in_small_jump_hook(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
// mov x0, 0x7F00;
|
||||
// br x0
|
||||
char code[] = "\x00\xe0\x8f\xd2\x00\x00\x1f\xd6";
|
||||
|
||||
uint64_t r_x0 = 0x0;
|
||||
uint64_t r_pc = 0x0;
|
||||
uc_hook hook;
|
||||
|
||||
uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1,
|
||||
UC_CPU_ARM64_A72);
|
||||
OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_UNMAPPED,
|
||||
test_arm64_correct_address_in_small_jump_hook_callback, NULL,
|
||||
1, 0));
|
||||
|
||||
uc_assert_err(
|
||||
UC_ERR_FETCH_UNMAPPED,
|
||||
uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
|
||||
|
||||
OK(uc_reg_read(uc, UC_ARM64_REG_X0, &r_x0));
|
||||
OK(uc_reg_read(uc, UC_ARM64_REG_PC, &r_pc));
|
||||
TEST_CHECK(r_x0 == 0x7F00);
|
||||
TEST_CHECK(r_pc == 0x7F00);
|
||||
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static bool test_arm64_correct_address_in_long_jump_hook_callback(
|
||||
uc_engine *uc, int type, uint64_t address, int size, int64_t value,
|
||||
void *user_data)
|
||||
{
|
||||
// Check registers
|
||||
uint64_t r_x0 = 0x0;
|
||||
uint64_t r_pc = 0x0;
|
||||
OK(uc_reg_read(uc, UC_ARM64_REG_X0, &r_x0));
|
||||
OK(uc_reg_read(uc, UC_ARM64_REG_PC, &r_pc));
|
||||
TEST_CHECK(r_x0 == 0x7FFFFFFFFFFFFF00);
|
||||
TEST_CHECK(r_pc == 0x7FFFFFFFFFFFFF00);
|
||||
|
||||
// Check address
|
||||
// printf("%lx\n", address);
|
||||
TEST_CHECK(address == 0x7FFFFFFFFFFFFF00);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void test_arm64_correct_address_in_long_jump_hook(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
// mov x0, 0x7FFFFFFFFFFFFF00;
|
||||
// br x0
|
||||
char code[] = "\xe0\xdb\x78\xb2\x00\x00\x1f\xd6";
|
||||
|
||||
uint64_t r_x0 = 0x0;
|
||||
uint64_t r_pc = 0x0;
|
||||
uc_hook hook;
|
||||
|
||||
uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1,
|
||||
UC_CPU_ARM64_A72);
|
||||
OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_UNMAPPED,
|
||||
test_arm64_correct_address_in_long_jump_hook_callback, NULL,
|
||||
1, 0));
|
||||
|
||||
uc_assert_err(
|
||||
UC_ERR_FETCH_UNMAPPED,
|
||||
uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
|
||||
|
||||
OK(uc_reg_read(uc, UC_ARM64_REG_X0, &r_x0));
|
||||
OK(uc_reg_read(uc, UC_ARM64_REG_PC, &r_pc));
|
||||
TEST_CHECK(r_x0 == 0x7FFFFFFFFFFFFF00);
|
||||
TEST_CHECK(r_pc == 0x7FFFFFFFFFFFFF00);
|
||||
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
TEST_LIST = {{"test_arm64_until", test_arm64_until},
|
||||
{"test_arm64_code_patching", test_arm64_code_patching},
|
||||
{"test_arm64_code_patching_count", test_arm64_code_patching_count},
|
||||
{"test_arm64_v8_pac", test_arm64_v8_pac},
|
||||
{"test_arm64_read_sctlr", test_arm64_read_sctlr},
|
||||
{"test_arm64_mrs_hook", test_arm64_mrs_hook},
|
||||
{"test_arm64_correct_address_in_small_jump_hook",
|
||||
test_arm64_correct_address_in_small_jump_hook},
|
||||
{"test_arm64_correct_address_in_long_jump_hook",
|
||||
test_arm64_correct_address_in_long_jump_hook},
|
||||
{NULL, NULL}};
|
||||
|
@ -49,6 +49,7 @@ static inline int64_t get_clock_realtime(void)
|
||||
#else
|
||||
|
||||
#include <sys/time.h>
|
||||
#include "sys/mman.h"
|
||||
|
||||
/* get host real time in nanosecond */
|
||||
static inline int64_t get_clock_realtime(void)
|
||||
@ -226,6 +227,62 @@ static void test_uc_ctl_arm_cpu(void)
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static void test_uc_hook_cached_cb(uc_engine *uc, uint64_t addr, size_t size,
|
||||
void *user_data)
|
||||
{
|
||||
// Don't add any TEST_CHECK here since we can't refer to the global variable
|
||||
// here.
|
||||
uint64_t *p = (uint64_t *)user_data;
|
||||
(*p)++;
|
||||
return;
|
||||
}
|
||||
|
||||
static void test_uc_hook_cached_uaf(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
// "INC ecx; DEC edx; jmp t; t: nop"
|
||||
char code[] = "\x41\x4a\xeb\x00\x90";
|
||||
uc_hook h;
|
||||
uint64_t count = 0;
|
||||
#ifndef _WIN32
|
||||
void *callback = mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
#else
|
||||
void *callback = VirtualAlloc(NULL, 4096, MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_EXECUTE_READWRITE);
|
||||
#endif
|
||||
|
||||
memcpy(callback, (void *)test_uc_hook_cached_cb, 4096);
|
||||
|
||||
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1);
|
||||
|
||||
OK(uc_hook_add(uc, &h, UC_HOOK_CODE, (void *)callback, (void *)&count, 1,
|
||||
0));
|
||||
|
||||
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
|
||||
|
||||
// Move the hook to the deleted hooks list.
|
||||
OK(uc_hook_del(uc, h));
|
||||
|
||||
// This will clear deleted hooks and SHOULD clear cache.
|
||||
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
|
||||
|
||||
memset(callback, 0, 4096);
|
||||
|
||||
// Now hooks are deleted and thus this will trigger a UAF
|
||||
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
|
||||
|
||||
TEST_CHECK(count == 4);
|
||||
|
||||
OK(uc_close(uc));
|
||||
|
||||
#ifndef _WIN32
|
||||
munmap(callback, 4096);
|
||||
#else
|
||||
VirtualFree(callback, 0, MEM_RELEASE);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode},
|
||||
{"test_uc_ctl_page_size", test_uc_ctl_page_size},
|
||||
{"test_uc_ctl_arch", test_uc_ctl_arch},
|
||||
@ -234,4 +291,5 @@ TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode},
|
||||
{"test_uc_ctl_tb_cache", test_uc_ctl_tb_cache},
|
||||
{"test_uc_ctl_change_page_size", test_uc_ctl_change_page_size},
|
||||
{"test_uc_ctl_arm_cpu", test_uc_ctl_arm_cpu},
|
||||
{"test_uc_hook_cached_uaf", test_uc_hook_cached_uaf},
|
||||
{NULL, NULL}};
|
@ -187,6 +187,84 @@ static void test_map_big_memory(void)
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static void test_mem_protect_remove_exec_callback(uc_engine *uc, uint64_t addr,
|
||||
size_t size, void *data)
|
||||
{
|
||||
uint64_t *p = (uint64_t *)data;
|
||||
(*p)++;
|
||||
|
||||
OK(uc_mem_protect(uc, 0x2000, 0x1000, UC_PROT_READ));
|
||||
}
|
||||
|
||||
static void test_mem_protect_remove_exec(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
char code[] = "\x90\xeb\x00\x90";
|
||||
uc_hook hk;
|
||||
uint64_t called_count = 0;
|
||||
|
||||
OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc));
|
||||
OK(uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL));
|
||||
OK(uc_mem_map(uc, 0x2000, 0x1000, UC_PROT_ALL));
|
||||
|
||||
OK(uc_mem_write(uc, 0x1000, code, sizeof(code) - 1));
|
||||
OK(uc_hook_add(uc, &hk, UC_HOOK_BLOCK,
|
||||
test_mem_protect_remove_exec_callback, (void *)&called_count,
|
||||
1, 0));
|
||||
|
||||
OK(uc_emu_start(uc, 0x1000, 0x1000 + sizeof(code) - 1, 0, 0));
|
||||
|
||||
TEST_CHECK(called_count == 2);
|
||||
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static uint64_t test_mem_protect_mmio_read_cb(struct uc_struct *uc,
|
||||
uint64_t addr, unsigned size,
|
||||
void *user_data)
|
||||
{
|
||||
TEST_CHECK(addr == 0x20); // note, it's not 0x1020
|
||||
|
||||
*(uint64_t *)user_data = *(uint64_t *)user_data + 1;
|
||||
return 0x114514;
|
||||
}
|
||||
|
||||
static void test_mem_protect_mmio_write_cb(struct uc_struct *uc, uint64_t addr,
|
||||
unsigned size, uint64_t data,
|
||||
void *user_data)
|
||||
{
|
||||
TEST_CHECK(false);
|
||||
return;
|
||||
}
|
||||
|
||||
static void test_mem_protect_mmio(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
// mov eax, [0x2020]; mov [0x2020], eax
|
||||
char code[] = "\xa1\x20\x20\x00\x00\x00\x00\x00\x00\xa3\x20\x20\x00\x00\x00"
|
||||
"\x00\x00\x00";
|
||||
uint64_t called = 0;
|
||||
uint64_t r_eax;
|
||||
|
||||
OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc));
|
||||
OK(uc_mem_map(uc, 0x8000, 0x1000, UC_PROT_ALL));
|
||||
OK(uc_mem_write(uc, 0x8000, code, sizeof(code) - 1));
|
||||
|
||||
OK(uc_mmio_map(uc, 0x1000, 0x3000, test_mem_protect_mmio_read_cb,
|
||||
(void *)&called, test_mem_protect_mmio_write_cb,
|
||||
(void *)&called));
|
||||
OK(uc_mem_protect(uc, 0x2000, 0x1000, UC_PROT_READ));
|
||||
|
||||
uc_assert_err(UC_ERR_WRITE_PROT,
|
||||
uc_emu_start(uc, 0x8000, 0x8000 + sizeof(code) - 1, 0, 0));
|
||||
OK(uc_reg_read(uc, UC_X86_REG_RAX, &r_eax));
|
||||
|
||||
TEST_CHECK(called == 1);
|
||||
TEST_CHECK(r_eax == 0x114514);
|
||||
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
TEST_LIST = {{"test_map_correct", test_map_correct},
|
||||
{"test_map_wrapping", test_map_wrapping},
|
||||
{"test_mem_protect", test_mem_protect},
|
||||
@ -196,4 +274,6 @@ TEST_LIST = {{"test_map_correct", test_map_correct},
|
||||
{"test_map_at_the_end", test_map_at_the_end},
|
||||
{"test_map_wrap", test_map_wrap},
|
||||
{"test_map_big_memory", test_map_big_memory},
|
||||
{"test_mem_protect_remove_exec", test_mem_protect_remove_exec},
|
||||
{"test_mem_protect_mmio", test_mem_protect_mmio},
|
||||
{NULL, NULL}};
|
||||
|
@ -537,6 +537,103 @@ static void test_riscv64_mmio_map(void)
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static bool test_riscv_correct_address_in_small_jump_hook_callback(
|
||||
uc_engine *uc, int type, uint64_t address, int size, int64_t value,
|
||||
void *user_data)
|
||||
{
|
||||
// Check registers
|
||||
uint64_t r_x5 = 0x0;
|
||||
uint64_t r_pc = 0x0;
|
||||
OK(uc_reg_read(uc, UC_RISCV_REG_X5, &r_x5));
|
||||
OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc));
|
||||
TEST_CHECK(r_x5 == 0x7F00);
|
||||
TEST_CHECK(r_pc == 0x7F00);
|
||||
|
||||
// Check address
|
||||
// printf("%lx\n", address);
|
||||
TEST_CHECK(address == 0x7F00);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void test_riscv_correct_address_in_small_jump_hook(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
// li 0x7F00, x5 > lui t0, 8; addiw t0, t0, -256;
|
||||
// jr x5
|
||||
char code[] = "\xb7\x82\x00\x00\x9b\x82\x02\xf0\x67\x80\x02\x00";
|
||||
|
||||
uint64_t r_x5 = 0x0;
|
||||
uint64_t r_pc = 0x0;
|
||||
uc_hook hook;
|
||||
|
||||
uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code,
|
||||
sizeof(code) - 1);
|
||||
OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_UNMAPPED,
|
||||
test_riscv_correct_address_in_small_jump_hook_callback, NULL,
|
||||
1, 0));
|
||||
|
||||
uc_assert_err(
|
||||
UC_ERR_FETCH_UNMAPPED,
|
||||
uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
|
||||
|
||||
OK(uc_reg_read(uc, UC_RISCV_REG_X5, &r_x5));
|
||||
OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc));
|
||||
TEST_CHECK(r_x5 == 0x7F00);
|
||||
TEST_CHECK(r_pc == 0x7F00);
|
||||
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static bool test_riscv_correct_address_in_long_jump_hook_callback(
|
||||
uc_engine *uc, int type, uint64_t address, int size, int64_t value,
|
||||
void *user_data)
|
||||
{
|
||||
// Check registers
|
||||
uint64_t r_x5 = 0x0;
|
||||
uint64_t r_pc = 0x0;
|
||||
OK(uc_reg_read(uc, UC_RISCV_REG_X5, &r_x5));
|
||||
OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc));
|
||||
TEST_CHECK(r_x5 == 0x7FFFFFFFFFFFFF00);
|
||||
TEST_CHECK(r_pc == 0x7FFFFFFFFFFFFF00);
|
||||
|
||||
// Check address
|
||||
// printf("%lx\n", address);
|
||||
TEST_CHECK(address == 0x7FFFFFFFFFFFFF00);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void test_riscv_correct_address_in_long_jump_hook(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
// li 0x7FFFFFFFFFFFFF00, x5 > addi t0, zero, -1; slli t0, t0, 63; addi
|
||||
// t0, t0, -256; jr x5
|
||||
char code[] =
|
||||
"\x93\x02\xf0\xff\x93\x92\xf2\x03\x93\x82\x02\xf0\x67\x80\x02\x00";
|
||||
|
||||
uint64_t r_x5 = 0x0;
|
||||
uint64_t r_pc = 0x0;
|
||||
uc_hook hook;
|
||||
|
||||
uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code,
|
||||
sizeof(code) - 1);
|
||||
OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_UNMAPPED,
|
||||
test_riscv_correct_address_in_long_jump_hook_callback, NULL,
|
||||
1, 0));
|
||||
|
||||
uc_assert_err(
|
||||
UC_ERR_FETCH_UNMAPPED,
|
||||
uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
|
||||
|
||||
OK(uc_reg_read(uc, UC_RISCV_REG_X5, &r_x5));
|
||||
OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc));
|
||||
TEST_CHECK(r_x5 == 0x7FFFFFFFFFFFFF00);
|
||||
TEST_CHECK(r_pc == 0x7FFFFFFFFFFFFF00);
|
||||
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
TEST_LIST = {
|
||||
{"test_riscv32_nop", test_riscv32_nop},
|
||||
{"test_riscv64_nop", test_riscv64_nop},
|
||||
@ -556,4 +653,8 @@ TEST_LIST = {
|
||||
{"test_riscv32_map", test_riscv32_map},
|
||||
{"test_riscv64_code_patching", test_riscv64_code_patching},
|
||||
{"test_riscv64_code_patching_count", test_riscv64_code_patching_count},
|
||||
{"test_riscv_correct_address_in_small_jump_hook",
|
||||
test_riscv_correct_address_in_small_jump_hook},
|
||||
{"test_riscv_correct_address_in_long_jump_hook",
|
||||
test_riscv_correct_address_in_long_jump_hook},
|
||||
{NULL, NULL}};
|
||||
|
6
tests/unit/test_tricore.c
Normal file
6
tests/unit/test_tricore.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include "unicorn_test.h"
|
||||
|
||||
const uint64_t code_start = 0x1000;
|
||||
const uint64_t code_len = 0x4000;
|
||||
|
||||
TEST_LIST = {{NULL, NULL}};
|
@ -690,6 +690,35 @@ static void test_x86_clear_tb_cache(void)
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static void test_x86_clear_count_cache(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
// uc_emu_start will clear last TB when exiting so generating a tb at last
|
||||
// by design
|
||||
char code[] =
|
||||
"\x83\xc1\x01\x4a\xeb\x00\x83\xc3\x01"; // ADD ecx, 1; DEC edx;
|
||||
// jmp t;
|
||||
// t:
|
||||
// ADD ebx, 1
|
||||
int r_ecx = 0x1234;
|
||||
int r_edx = 0x7890;
|
||||
|
||||
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1);
|
||||
OK(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx));
|
||||
OK(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx));
|
||||
|
||||
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 2));
|
||||
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
|
||||
|
||||
OK(uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx));
|
||||
OK(uc_reg_read(uc, UC_X86_REG_EDX, &r_edx));
|
||||
|
||||
TEST_CHECK(r_ecx == 0x1236);
|
||||
TEST_CHECK(r_edx == 0x788e);
|
||||
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
// This is a regression bug.
|
||||
static void test_x86_clear_empty_tb(void)
|
||||
{
|
||||
@ -797,7 +826,7 @@ static void test_x86_hook_tcg_op(void)
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static void test_x86_cmpxchg_mem_hook(uc_engine *uc, uc_mem_type type,
|
||||
static bool test_x86_cmpxchg_mem_hook(uc_engine *uc, uc_mem_type type,
|
||||
uint64_t address, int size, int64_t val,
|
||||
void *data)
|
||||
{
|
||||
@ -806,6 +835,8 @@ static void test_x86_cmpxchg_mem_hook(uc_engine *uc, uc_mem_type type,
|
||||
} else {
|
||||
*((int *)data) |= 2;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void test_x86_cmpxchg(void)
|
||||
@ -981,6 +1012,100 @@ static void test_x86_nested_uc_emu_start_exits(void)
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static bool test_x86_correct_address_in_small_jump_hook_callback(
|
||||
uc_engine *uc, int type, uint64_t address, int size, int64_t value,
|
||||
void *user_data)
|
||||
{
|
||||
// Check registers
|
||||
uint64_t r_rax = 0x0;
|
||||
uint64_t r_rip = 0x0;
|
||||
OK(uc_reg_read(uc, UC_X86_REG_RAX, &r_rax));
|
||||
OK(uc_reg_read(uc, UC_X86_REG_RIP, &r_rip));
|
||||
TEST_CHECK(r_rax == 0x7F00);
|
||||
TEST_CHECK(r_rip == 0x7F00);
|
||||
|
||||
// Check address
|
||||
// printf("%lx\n", address);
|
||||
TEST_CHECK(address == 0x7F00);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void test_x86_correct_address_in_small_jump_hook(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
// movabs $0x7F00, %rax
|
||||
// jmp *%rax
|
||||
char code[] = "\x48\xb8\x00\x7F\x00\x00\x00\x00\x00\x00\xff\xe0";
|
||||
|
||||
uint64_t r_rax = 0x0;
|
||||
uint64_t r_rip = 0x0;
|
||||
uc_hook hook;
|
||||
|
||||
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_64, code, sizeof(code) - 1);
|
||||
OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_UNMAPPED,
|
||||
test_x86_correct_address_in_small_jump_hook_callback, NULL,
|
||||
1, 0));
|
||||
|
||||
uc_assert_err(
|
||||
UC_ERR_FETCH_UNMAPPED,
|
||||
uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
|
||||
|
||||
OK(uc_reg_read(uc, UC_X86_REG_RAX, &r_rax));
|
||||
OK(uc_reg_read(uc, UC_X86_REG_RIP, &r_rip));
|
||||
TEST_CHECK(r_rax == 0x7F00);
|
||||
TEST_CHECK(r_rip == 0x7F00);
|
||||
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static bool test_x86_correct_address_in_long_jump_hook_callback(
|
||||
uc_engine *uc, int type, uint64_t address, int size, int64_t value,
|
||||
void *user_data)
|
||||
{
|
||||
// Check registers
|
||||
uint64_t r_rax = 0x0;
|
||||
uint64_t r_rip = 0x0;
|
||||
OK(uc_reg_read(uc, UC_X86_REG_RAX, &r_rax));
|
||||
OK(uc_reg_read(uc, UC_X86_REG_RIP, &r_rip));
|
||||
TEST_CHECK(r_rax == 0x7FFFFFFFFFFFFF00);
|
||||
TEST_CHECK(r_rip == 0x7FFFFFFFFFFFFF00);
|
||||
|
||||
// Check address
|
||||
// printf("%lx\n", address);
|
||||
TEST_CHECK(address == 0x7FFFFFFFFFFFFF00);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void test_x86_correct_address_in_long_jump_hook(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
// movabs $0x7FFFFFFFFFFFFF00, %rax
|
||||
// jmp *%rax
|
||||
char code[] = "\x48\xb8\x00\xff\xff\xff\xff\xff\xff\x7f\xff\xe0";
|
||||
|
||||
uint64_t r_rax = 0x0;
|
||||
uint64_t r_rip = 0x0;
|
||||
uc_hook hook;
|
||||
|
||||
uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_64, code, sizeof(code) - 1);
|
||||
OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_UNMAPPED,
|
||||
test_x86_correct_address_in_long_jump_hook_callback, NULL, 1,
|
||||
0));
|
||||
|
||||
uc_assert_err(
|
||||
UC_ERR_FETCH_UNMAPPED,
|
||||
uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
|
||||
|
||||
OK(uc_reg_read(uc, UC_X86_REG_RAX, &r_rax));
|
||||
OK(uc_reg_read(uc, UC_X86_REG_RIP, &r_rip));
|
||||
TEST_CHECK(r_rax == 0x7FFFFFFFFFFFFF00);
|
||||
TEST_CHECK(r_rip == 0x7FFFFFFFFFFFFF00);
|
||||
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
TEST_LIST = {
|
||||
{"test_x86_in", test_x86_in},
|
||||
{"test_x86_out", test_x86_out},
|
||||
@ -1013,4 +1138,9 @@ TEST_LIST = {
|
||||
{"test_x86_64_nested_emu_start_error", test_x86_64_nested_emu_start_error},
|
||||
{"test_x86_eflags_reserved_bit", test_x86_eflags_reserved_bit},
|
||||
{"test_x86_nested_uc_emu_start_exits", test_x86_nested_uc_emu_start_exits},
|
||||
{"test_x86_clear_count_cache", test_x86_clear_count_cache},
|
||||
{"test_x86_correct_address_in_small_jump_hook",
|
||||
test_x86_correct_address_in_small_jump_hook},
|
||||
{"test_x86_correct_address_in_long_jump_hook",
|
||||
test_x86_correct_address_in_long_jump_hook},
|
||||
{NULL, NULL}};
|
||||
|
114
uc.c
114
uc.c
@ -24,6 +24,7 @@
|
||||
#include "qemu/target/ppc/unicorn.h"
|
||||
#include "qemu/target/riscv/unicorn.h"
|
||||
#include "qemu/target/s390x/unicorn.h"
|
||||
#include "qemu/target/tricore/unicorn.h"
|
||||
|
||||
#include "qemu/include/qemu/queue.h"
|
||||
#include "qemu-common.h"
|
||||
@ -48,6 +49,14 @@ static void *hook_append(struct list *l, struct hook *h)
|
||||
return item;
|
||||
}
|
||||
|
||||
static void hook_invalidate_region(void *key, void *data, void *opaq)
|
||||
{
|
||||
uc_engine *uc = (uc_engine *)opaq;
|
||||
HookedRegion *region = (HookedRegion *)key;
|
||||
|
||||
uc->uc_invalidate_tb(uc, region->start, region->length);
|
||||
}
|
||||
|
||||
static void hook_delete(void *data)
|
||||
{
|
||||
struct hook *h = (struct hook *)data;
|
||||
@ -55,6 +64,7 @@ static void hook_delete(void *data)
|
||||
h->refs--;
|
||||
|
||||
if (h->refs == 0) {
|
||||
g_hash_table_destroy(h->hooked_regions);
|
||||
free(h);
|
||||
}
|
||||
}
|
||||
@ -167,6 +177,10 @@ bool uc_arch_supported(uc_arch arch)
|
||||
#ifdef UNICORN_HAS_S390X
|
||||
case UC_ARCH_S390X:
|
||||
return true;
|
||||
#endif
|
||||
#ifdef UNICORN_HAS_TRICORE
|
||||
case UC_ARCH_TRICORE:
|
||||
return true;
|
||||
#endif
|
||||
/* Invalid or disabled arch */
|
||||
default:
|
||||
@ -384,6 +398,15 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result)
|
||||
}
|
||||
uc->init_arch = s390_uc_init;
|
||||
break;
|
||||
#endif
|
||||
#ifdef UNICORN_HAS_TRICORE
|
||||
case UC_ARCH_TRICORE:
|
||||
if ((mode & ~UC_MODE_TRICORE_MASK)) {
|
||||
free(uc);
|
||||
return UC_ERR_MODE;
|
||||
}
|
||||
uc->init_arch = tricore_uc_init;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -798,6 +821,11 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until,
|
||||
case UC_ARCH_S390X:
|
||||
uc_reg_write(uc, UC_S390X_REG_PC, &begin);
|
||||
break;
|
||||
#endif
|
||||
#ifdef UNICORN_HAS_TRICORE
|
||||
case UC_ARCH_TRICORE:
|
||||
uc_reg_write(uc, UC_TRICORE_REG_PC, &begin);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -808,6 +836,9 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until,
|
||||
if (count <= 0 && uc->count_hook != 0) {
|
||||
uc_hook_del(uc, uc->count_hook);
|
||||
uc->count_hook = 0;
|
||||
|
||||
// In this case, we have to drop all translated blocks.
|
||||
uc->tb_flush(uc);
|
||||
}
|
||||
// set up count hook to count instructions.
|
||||
if (count > 0 && uc->count_hook == 0) {
|
||||
@ -844,10 +875,11 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until,
|
||||
// or we may lost uc_emu_stop
|
||||
if (uc->nested_level == 0) {
|
||||
uc->emulation_done = true;
|
||||
}
|
||||
|
||||
// remove hooks to delete
|
||||
clear_deleted_hooks(uc);
|
||||
// remove hooks to delete
|
||||
// make sure we delete all hooks at the first level.
|
||||
clear_deleted_hooks(uc);
|
||||
}
|
||||
|
||||
if (timeout) {
|
||||
// wait for the timer to finish
|
||||
@ -1091,15 +1123,13 @@ static uint8_t *copy_region(struct uc_struct *uc, MemoryRegion *mr)
|
||||
/*
|
||||
This function is similar to split_region, but for MMIO memory.
|
||||
|
||||
This function would delete the region unconditionally.
|
||||
|
||||
Note this function may be called recursively.
|
||||
*/
|
||||
static bool split_mmio_region(struct uc_struct *uc, MemoryRegion *mr,
|
||||
uint64_t address, size_t size)
|
||||
uint64_t address, size_t size, bool do_delete)
|
||||
{
|
||||
uint64_t begin, end, chunk_end;
|
||||
size_t l_size, r_size;
|
||||
size_t l_size, r_size, m_size;
|
||||
mmio_cbs backup;
|
||||
|
||||
chunk_end = address + size;
|
||||
@ -1142,6 +1172,7 @@ static bool split_mmio_region(struct uc_struct *uc, MemoryRegion *mr,
|
||||
// compute sub region sizes
|
||||
l_size = (size_t)(address - begin);
|
||||
r_size = (size_t)(end - chunk_end);
|
||||
m_size = (size_t)(chunk_end - address);
|
||||
|
||||
if (l_size > 0) {
|
||||
if (uc_mmio_map(uc, begin, l_size, backup.read, backup.user_data_read,
|
||||
@ -1150,6 +1181,13 @@ static bool split_mmio_region(struct uc_struct *uc, MemoryRegion *mr,
|
||||
}
|
||||
}
|
||||
|
||||
if (m_size > 0 && !do_delete) {
|
||||
if (uc_mmio_map(uc, address, m_size, backup.read, backup.user_data_read,
|
||||
backup.write, backup.user_data_write) != UC_ERR_OK) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (r_size > 0) {
|
||||
if (uc_mmio_map(uc, chunk_end, r_size, backup.read,
|
||||
backup.user_data_read, backup.write,
|
||||
@ -1335,6 +1373,7 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size,
|
||||
{
|
||||
MemoryRegion *mr;
|
||||
uint64_t addr = address;
|
||||
uint64_t pc;
|
||||
size_t count, len;
|
||||
bool remove_exec = false;
|
||||
|
||||
@ -1376,18 +1415,28 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size,
|
||||
while (count < size) {
|
||||
mr = memory_mapping(uc, addr);
|
||||
len = (size_t)MIN(size - count, mr->end - addr);
|
||||
if (!split_region(uc, mr, addr, len, false)) {
|
||||
return UC_ERR_NOMEM;
|
||||
}
|
||||
if (mr->ram) {
|
||||
if (!split_region(uc, mr, addr, len, false)) {
|
||||
return UC_ERR_NOMEM;
|
||||
}
|
||||
|
||||
mr = memory_mapping(uc, addr);
|
||||
// will this remove EXEC permission?
|
||||
if (((mr->perms & UC_PROT_EXEC) != 0) &&
|
||||
((perms & UC_PROT_EXEC) == 0)) {
|
||||
remove_exec = true;
|
||||
mr = memory_mapping(uc, addr);
|
||||
// will this remove EXEC permission?
|
||||
if (((mr->perms & UC_PROT_EXEC) != 0) &&
|
||||
((perms & UC_PROT_EXEC) == 0)) {
|
||||
remove_exec = true;
|
||||
}
|
||||
mr->perms = perms;
|
||||
uc->readonly_mem(mr, (perms & UC_PROT_WRITE) == 0);
|
||||
|
||||
} else {
|
||||
if (!split_mmio_region(uc, mr, addr, len, false)) {
|
||||
return UC_ERR_NOMEM;
|
||||
}
|
||||
|
||||
mr = memory_mapping(uc, addr);
|
||||
mr->perms = perms;
|
||||
}
|
||||
mr->perms = perms;
|
||||
uc->readonly_mem(mr, (perms & UC_PROT_WRITE) == 0);
|
||||
|
||||
count += len;
|
||||
addr += len;
|
||||
@ -1396,8 +1445,11 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size,
|
||||
// if EXEC permission is removed, then quit TB and continue at the same
|
||||
// place
|
||||
if (remove_exec) {
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
pc = uc->get_pc(uc);
|
||||
if (pc < address + size && pc >= address) {
|
||||
uc->quit_request = true;
|
||||
uc_emu_stop(uc);
|
||||
}
|
||||
}
|
||||
|
||||
return UC_ERR_OK;
|
||||
@ -1444,7 +1496,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size)
|
||||
mr = memory_mapping(uc, addr);
|
||||
len = (size_t)MIN(size - count, mr->end - addr);
|
||||
if (!mr->ram) {
|
||||
if (!split_mmio_region(uc, mr, addr, len)) {
|
||||
if (!split_mmio_region(uc, mr, addr, len, true)) {
|
||||
return UC_ERR_NOMEM;
|
||||
}
|
||||
} else {
|
||||
@ -1518,6 +1570,8 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback,
|
||||
hook->user_data = user_data;
|
||||
hook->refs = 0;
|
||||
hook->to_delete = false;
|
||||
hook->hooked_regions = g_hash_table_new_full(
|
||||
hooked_regions_hash, hooked_regions_equal, g_free, NULL);
|
||||
*hh = (uc_hook)hook;
|
||||
|
||||
// UC_HOOK_INSN has an extra argument for instruction ID
|
||||
@ -1627,6 +1681,9 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh)
|
||||
// and store the type mask in the hook pointer.
|
||||
for (i = 0; i < UC_HOOK_MAX; i++) {
|
||||
if (list_exists(&uc->hook[i], (void *)hook)) {
|
||||
g_hash_table_foreach(hook->hooked_regions, hook_invalidate_region,
|
||||
uc);
|
||||
g_hash_table_remove_all(hook->hooked_regions);
|
||||
hook->to_delete = true;
|
||||
uc->hooks_count[i]--;
|
||||
hook_append(&uc->hooks_to_del, hook);
|
||||
@ -1956,6 +2013,12 @@ static void find_context_reg_rw_function(uc_arch arch, uc_mode mode,
|
||||
rw->context_reg_read = s390_context_reg_read;
|
||||
rw->context_reg_write = s390_context_reg_write;
|
||||
break;
|
||||
#endif
|
||||
#ifdef UNICORN_HAS_TRICORE
|
||||
case UC_ARCH_TRICORE:
|
||||
rw->context_reg_read = tricore_context_reg_read;
|
||||
rw->context_reg_write = tricore_context_reg_write;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2300,6 +2363,17 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...)
|
||||
break;
|
||||
}
|
||||
|
||||
case UC_CTL_TB_FLUSH:
|
||||
|
||||
UC_INIT(uc);
|
||||
|
||||
if (rw == UC_CTL_IO_WRITE) {
|
||||
uc->tb_flush(uc);
|
||||
} else {
|
||||
err = UC_ERR_ARG;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
err = UC_ERR_ARG;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user