TriCore Support (#1568)

* TriCore Support

python sample

* Update sample_tricore.py

Correct attribution

* Update sample_tricore.py

Fixed byte code to execute properly.

* Update sample_tricore.py

Removed testing artifact

* Added tricore msvc config-file.h

* Added STATIC to tricore config and added helper methods to symbol file generation.

* Update op_helper.c

Use built in crc32

* Fix tricore samples and small code blocks are now handled properly

* Add CPU types

* Generate bindings

* Format code

Co-authored-by: lazymio <mio@lazym.io>
This commit is contained in:
Eric Poole 2022-04-29 17:11:34 -04:00 committed by GitHub
parent f49f62ecef
commit cfee2139a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 18103 additions and 12 deletions

2
.gitignore vendored
View File

@ -12,8 +12,6 @@
*.jar
*~
qemu/*-softmmu/
tags
qemu/config-host.ld
qemu/config.log

View File

@ -44,7 +44,7 @@ option(BUILD_SHARED_LIBS "Build shared instead of static library" ${PROJECT_IS_T
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})
@ -209,6 +209,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 +246,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 +290,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 +384,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 +1051,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
@ -1194,6 +1241,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)

View File

@ -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': '',

View File

@ -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

View 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

View 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
)

View File

@ -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

View 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;
}

View File

@ -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;

View 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.

View File

@ -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;

View 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()

View 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

View File

@ -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

View 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

View File

@ -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

View File

@ -33,6 +33,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]))

174
include/unicorn/tricore.h Normal file
View 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

View File

@ -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")))
@ -103,6 +104,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;

View 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

11
qemu/configure vendored
View File

@ -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)
;;

View File

@ -795,6 +795,12 @@ struct TCGContext {
/* 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;

View 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

View 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
View 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
View 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 */

View 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)

View 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);
}

View 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);
}

View 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)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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 */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,270 @@
/* 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);
void tricore_set_pc(struct uc_struct *uc, uint64_t address)
{
((CPUTriCoreState *)uc->cpu->env_ptr)->PC = address;
}
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->cpus_init = tricore_cpus_init;
uc->cpu_context_size = offsetof(CPUTriCoreState, end_reset_fields);
uc_common_init(uc);
}

View 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

File diff suppressed because it is too large Load Diff

View File

@ -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)

100
samples/sample_tricore.c Normal file
View File

@ -0,0 +1,100 @@
/*
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)
{
// dynamically load shared library
#ifdef DYNLOAD
if (!uc_dyn_load(NULL, 0)) {
printf("Error dynamically loading shared library.\n");
printf("Please check that unicorn.dll/unicorn.so is available as well "
"as\n");
printf("any other dependent dll/so files.\n");
printf("The easiest way is to place them in the same directory as this "
"app.\n");
return 1;
}
#endif
test_tricore();
#ifdef DYNLOAD
uc_dyn_free();
#endif
return 0;
}

View File

@ -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

View 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}};

25
uc.c
View File

@ -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"
@ -167,6 +168,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 +389,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 +812,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
}
@ -1960,6 +1979,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
}