diff --git a/CMakeLists.txt b/CMakeLists.txt index b561cf5c..38e7b535 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,8 @@ option(UNICORN_BUILD_SHARED "Build shared instead of static library" ON) if (NOT UNICORN_ARCH) # build all architectures - set(UNICORN_ARCH "x86 arm aarch64 riscv mips sparc m68k ppc") + # set(UNICORN_ARCH "x86 arm aarch64 riscv mips sparc m68k ppc s390x") + set(UNICORN_ARCH "s390x") endif() string(TOUPPER ${UNICORN_ARCH} UNICORN_ARCH) @@ -197,6 +198,9 @@ else() if (UNICORN_HAS_RISCV) set (EXTRA_CFLAGS "${EXTRA_CFLAGS}-DUNICORN_HAS_RISCV ") endif() + if (UNICORN_HAS_S390X) + set (EXTRA_CFLAGS "${EXTRA_CFLAGS}-DUNICORN_HAS_S390X ") + endif() set (EXTRA_CFLAGS "${EXTRA_CFLAGS}-fPIC") if(ANDROID_ABI) @@ -232,6 +236,9 @@ else() if (UNICORN_HAS_RISCV) set (TARGET_LIST "${TARGET_LIST}riscv32-softmmu, riscv64-softmmu, ") endif() + if (UNICORN_HAS_S390X) + set (TARGET_LIST "${TARGET_LIST}s390x-softmmu, ") + endif() set (TARGET_LIST "${TARGET_LIST} ") # GEN config-host.mak & target directories @@ -325,6 +332,12 @@ else() OUTPUT_FILE ${CMAKE_BINARY_DIR}/riscv64-softmmu/config-target.h ) endif() + if (UNICORN_HAS_S390X) + execute_process(COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/qemu/scripts/create_config + INPUT_FILE ${CMAKE_BINARY_DIR}/s390x-softmmu/config-target.mak + OUTPUT_FILE ${CMAKE_BINARY_DIR}/s390x-softmmu/config-target.h + ) + endif() add_compile_options( ${UNICORN_CFLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}/qemu/tcg/${UNICORN_TARGET_ARCH} @@ -950,6 +963,54 @@ else() endif() endif() +if (UNICORN_HAS_S390X) +add_library(s390x-softmmu + ${UNICORN_ARCH_COMMON} + + qemu/hw/s390x/s390-skeys.c + + qemu/target/s390x/cc_helper.c + qemu/target/s390x/cpu.c + qemu/target/s390x/cpu_features.c + qemu/target/s390x/cpu_models.c + qemu/target/s390x/crypto_helper.c + qemu/target/s390x/excp_helper.c + qemu/target/s390x/fpu_helper.c + qemu/target/s390x/helper.c + qemu/target/s390x/interrupt.c + qemu/target/s390x/int_helper.c + qemu/target/s390x/ioinst.c + qemu/target/s390x/mem_helper.c + qemu/target/s390x/misc_helper.c + qemu/target/s390x/mmu_helper.c + qemu/target/s390x/sigp.c + qemu/target/s390x/tcg-stub.c + qemu/target/s390x/translate.c + # qemu/target/s390x/translate_vx.inc.c + qemu/target/s390x/vec_fpu_helper.c + qemu/target/s390x/vec_helper.c + qemu/target/s390x/vec_int_helper.c + qemu/target/s390x/vec_string_helper.c + qemu/target/s390x/unicorn.c +) + +if(MSVC) + target_compile_options(s390x-softmmu PRIVATE + -DNEED_CPU_H + /FIs390x.h + /I${CMAKE_CURRENT_SOURCE_DIR}/msvc/s390x-softmmu + /I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/s390x + ) +else() + target_compile_options(s390x-softmmu PRIVATE + -DNEED_CPU_H + -include s390x.h + -I${CMAKE_BINARY_DIR}/s390x-softmmu + -I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/s390x + ) +endif() +endif() + set(UNICORN_SRCS uc.c @@ -1095,6 +1156,13 @@ if (UNICORN_HAS_RISCV) target_link_libraries(riscv64-softmmu unicorn-common) set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_riscv) endif() +if (UNICORN_HAS_S390X) + set(UNICORN_COMPILE_OPTIONS ${UNICORN_COMPILE_OPTIONS} -DUNICORN_HAS_S390X) + set(UNICORN_LINK_LIBRARIES ${UNICORN_LINK_LIBRARIES} s390x-softmmu) + set(UNICORN_SAMPLE_FILE ${UNICORN_SAMPLE_FILE} sample_s390x) + target_link_libraries(s390x-softmmu unicorn-common) + set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_s390x) +endif() target_compile_options(unicorn PRIVATE ${UNICORN_COMPILE_OPTIONS} @@ -1146,7 +1214,7 @@ endif() if(UNICORN_FUZZ) - set(UNICORN_FUZZ_SUFFIX "arm_arm;arm_armbe;arm_thumb;arm64_arm;arm64_armbe;m68k_be;mips_32be;mips_32le;sparc_32be;x86_16;x86_32;x86_64") + set(UNICORN_FUZZ_SUFFIX "arm_arm;arm_armbe;arm_thumb;arm64_arm;arm64_armbe;m68k_be;mips_32be;mips_32le;sparc_32be;x86_16;x86_32;x86_64;s390x") set(SAMPLES_LIB ${SAMPLES_LIB} rt) foreach(SUFFIX ${UNICORN_FUZZ_SUFFIX}) add_executable(fuzz_emu_${SUFFIX} diff --git a/README.md b/README.md index 19a71e76..27124a34 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Unicorn is a lightweight, multi-platform, multi-architecture CPU emulator framew Unicorn offers some unparalleled features: -- Multi-architecture: ARM, ARM64 (ARMv8), M68K, MIPS, PowerPC, RISCV, SPARC, and X86 (16, 32, 64-bit) +- Multi-architecture: ARM, ARM64 (ARMv8), M68K, MIPS, PowerPC, RISCV, SPARC, S390X and X86 (16, 32, 64-bit) - Clean/simple/lightweight/intuitive architecture-neutral API - Implemented in pure C language, with bindings for Crystal, Clojure, Visual Basic, Perl, Rust, Ruby, Python, Java, .NET, Go, Delphi/Free Pascal, Haskell, Pharo, and Lua. - Native support for Windows & *nix (with Mac OSX, Linux, Android, *BSD & Solaris confirmed) diff --git a/include/uc_priv.h b/include/uc_priv.h index 8c564396..4866e6b3 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -23,6 +23,7 @@ #define UC_MODE_SPARC_MASK (UC_MODE_SPARC32|UC_MODE_SPARC64|UC_MODE_BIG_ENDIAN) #define UC_MODE_M68K_MASK (UC_MODE_BIG_ENDIAN) #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 ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index d7780e56..940f3081 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -34,6 +34,7 @@ typedef size_t uc_hook; #include "sparc.h" #include "ppc.h" #include "riscv.h" +#include "s390x.h" #ifdef __GNUC__ #define DEFAULT_VISIBILITY __attribute__((visibility("default"))) @@ -98,6 +99,7 @@ typedef enum uc_arch { UC_ARCH_SPARC, // Sparc architecture UC_ARCH_M68K, // M68K architecture UC_ARCH_RISCV, // RISCV architecture + UC_ARCH_S390X, // S390X architecture UC_ARCH_MAX, } uc_arch; diff --git a/qemu/configure b/qemu/configure index 851530c0..b67e75a9 100755 --- a/qemu/configure +++ b/qemu/configure @@ -852,7 +852,7 @@ QEMU_CFLAGS="$CPU_CFLAGS $QEMU_CFLAGS" default_target_list="aarch64eb-softmmu aarch64-softmmu armeb-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" + x86_64-softmmu riscv32-softmmu riscv64-softmmu s390x-softmmu" if test x"$show_help" = x"yes" ; then cat << EOF diff --git a/qemu/include/qemu-common.h b/qemu/include/qemu-common.h index 5b6a6cba..1cda0555 100644 --- a/qemu/include/qemu-common.h +++ b/qemu/include/qemu-common.h @@ -78,4 +78,6 @@ void os_setup_early_signal_handling(void); void page_size_init(struct uc_struct *uc); +CPUState *qemu_get_cpu(struct uc_struct *uc, int index); + #endif diff --git a/symbols.sh b/symbols.sh index 19997fb4..f04ca8a3 100755 --- a/symbols.sh +++ b/symbols.sh @@ -6268,7 +6268,7 @@ ppc_irq_reset \ ppc64_SYMBOLS=${ppc_SYMBOLS} -ARCHS="x86_64 arm armeb aarch64 aarch64eb riscv32 riscv64 mips mipsel mips64 mips64el sparc sparc64 m68k ppc ppc64" +ARCHS="x86_64 arm armeb aarch64 aarch64eb riscv32 riscv64 mips mipsel mips64 mips64el sparc sparc64 m68k ppc ppc64 s390x" for arch in $ARCHS; do diff --git a/uc.c b/uc.c index 3e24674c..41088dbc 100644 --- a/uc.c +++ b/uc.c @@ -23,6 +23,7 @@ #include "qemu/target/sparc/unicorn.h" #include "qemu/target/ppc/unicorn.h" #include "qemu/target/riscv/unicorn.h" +#include "qemu/target/s390x/unicorn.h" #include "qemu/include/qemu/queue.h" @@ -124,6 +125,9 @@ bool uc_arch_supported(uc_arch arch) #endif #ifdef UNICORN_HAS_RISCV case UC_ARCH_RISCV: return true; +#endif +#ifdef UNICORN_HAS_S390X + case UC_ARCH_S390X: return true; #endif /* Invalid or disabled arch */ default: return false; @@ -291,6 +295,16 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) } break; #endif +#ifdef UNICORN_HAS_S390X + case UC_ARCH_S390X: + if ((mode & ~UC_MODE_S390X_MASK) || + !(mode & UC_MODE_BIG_ENDIAN)) { + free(uc); + return UC_ERR_MODE; + } + uc->init_arch = s390_uc_init; + break; +#endif } @@ -699,6 +713,11 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time case UC_ARCH_RISCV: uc_reg_write(uc, UC_RISCV_REG_PC, &begin); break; +#endif +#ifdef UNICORN_HAS_S390X + case UC_ARCH_S390X: + uc_reg_write(uc, UC_S390X_REG_PC, &begin); + break; #endif } @@ -1621,6 +1640,12 @@ static void find_context_reg_rw_function(uc_arch arch, uc_mode mode, context_reg rw->context_reg_write = riscv64_context_reg_write; } break; +#endif +#ifdef UNICORN_HAS_S390X + case UC_ARCH_S390X: + rw->context_reg_read = s390_context_reg_read; + rw->context_reg_write = s390_context_reg_write; + break; #endif }