diff --git a/src/common/code_block.h b/src/common/code_block.h index 0dde07d59..0e87e854f 100644 --- a/src/common/code_block.h +++ b/src/common/code_block.h @@ -1,5 +1,5 @@ // Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 or any later version +// Licensed under GPLv2 // Refer to the license.txt file included. #pragma once diff --git a/src/common/cpu_detect.h b/src/common/cpu_detect.h index b585f9608..c63076ff7 100644 --- a/src/common/cpu_detect.h +++ b/src/common/cpu_detect.h @@ -1,78 +1,89 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 // Refer to the license.txt file included. -// Detect the cpu, so we'll know which optimizations to use +// Detect the CPU, so we'll know which optimizations to use #pragma once #include enum CPUVendor { - VENDOR_INTEL = 0, - VENDOR_AMD = 1, - VENDOR_ARM = 2, - VENDOR_OTHER = 3, + VENDOR_INTEL = 0, + VENDOR_AMD = 1, + VENDOR_ARM = 2, + VENDOR_OTHER = 3, }; struct CPUInfo { - CPUVendor vendor; + CPUVendor vendor; - char cpu_string[0x21]; - char brand_string[0x41]; - bool OS64bit; - bool CPU64bit; - bool Mode64bit; + char cpu_string[0x41]; + char brand_string[0x21]; + bool OS64bit; + bool CPU64bit; + bool Mode64bit; - bool HTT; - int num_cores; - int logical_cpu_count; + bool HTT; + int num_cores; + int logical_cpu_count; - bool bSSE; - bool bSSE2; - bool bSSE3; - bool bSSSE3; - bool bPOPCNT; - bool bSSE4_1; - bool bSSE4_2; - bool bLZCNT; - bool bSSE4A; - bool bAVX; - bool bAES; - bool bLAHFSAHF64; - bool bLongMode; + bool bSSE; + bool bSSE2; + bool bSSE3; + bool bSSSE3; + bool bPOPCNT; + bool bSSE4_1; + bool bSSE4_2; + bool bLZCNT; + bool bSSE4A; + bool bAVX; + bool bAVX2; + bool bBMI1; + bool bBMI2; + bool bFMA; + bool bAES; + // FXSAVE/FXRSTOR + bool bFXSR; + bool bMOVBE; + // This flag indicates that the hardware supports some mode + // in which denormal inputs _and_ outputs are automatically set to (signed) zero. + bool bFlushToZero; + bool bLAHFSAHF64; + bool bLongMode; + bool bAtom; - // ARM specific CPUInfo - bool bSwp; - bool bHalf; - bool bThumb; - bool bFastMult; - bool bVFP; - bool bEDSP; - bool bThumbEE; - bool bNEON; - bool bVFPv3; - bool bTLS; - bool bVFPv4; - bool bIDIVa; - bool bIDIVt; - bool bArmV7; // enable MOVT, MOVW etc + // ARM specific CPUInfo + bool bSwp; + bool bHalf; + bool bThumb; + bool bFastMult; + bool bVFP; + bool bEDSP; + bool bThumbEE; + bool bNEON; + bool bVFPv3; + bool bTLS; + bool bVFPv4; + bool bIDIVa; + bool bIDIVt; + bool bArmV7; // enable MOVT, MOVW etc - // ARMv8 specific - bool bFP; - bool bASIMD; + // ARMv8 specific + bool bFP; + bool bASIMD; - // Call Detect() - explicit CPUInfo(); + // Call Detect() + explicit CPUInfo(); - // Turn the cpu info into a string we can show - std::string Summarize(); + // Turn the CPU info into a string we can show + std::string Summarize(); private: - // Detects the various cpu features - void Detect(); + // Detects the various CPU features + void Detect(); }; extern CPUInfo cpu_info; diff --git a/src/common/logging/log.h b/src/common/logging/log.h index 3d94bf0d9..aaccc89f8 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -47,6 +47,7 @@ enum class Class : ClassType { Debug_Emulated, ///< Debug messages from the emulated programs Debug_GPU, ///< GPU debugging tools Debug_Breakpoint, ///< Logging breakpoints and watchpoints + DYNA_REC, ///< Dolphin x64 emitter Kernel, ///< The HLE implementation of the CTR kernel Kernel_SVC, ///< Kernel system calls Service, ///< HLE implementation of system services. Each major service @@ -105,4 +106,5 @@ void LogMessage(Class log_class, Level log_level, #define LOG_INFO( log_class, ...) LOG_GENERIC(log_class, Info, __VA_ARGS__) #define LOG_WARNING( log_class, ...) LOG_GENERIC(log_class, Warning, __VA_ARGS__) #define LOG_ERROR( log_class, ...) LOG_GENERIC(log_class, Error, __VA_ARGS__) +#define ERROR_LOG LOG_ERROR #define LOG_CRITICAL(log_class, ...) LOG_GENERIC(log_class, Critical, __VA_ARGS__) diff --git a/src/common/x64_emitter.h b/src/common/x64_emitter.h index 3a8419c99..2722d601e 100644 --- a/src/common/x64_emitter.h +++ b/src/common/x64_emitter.h @@ -10,9 +10,9 @@ #include #include -#include "Common/bit_set.h" -#include "Common/code_block.h" -#include "Common/common_types.h" +#include "common/bit_set.h" +#include "common/code_block.h" +#include "common/common_types.h" namespace Gen { diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 6bc3a763b..a93038c45 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -13,6 +13,8 @@ set(SRCS arm/interpreter/armsupp.cpp arm/interpreter/armvirt.cpp arm/interpreter/thumbemu.cpp + arm/jit_common/jit_base.cpp + arm/jit_x64/jit.cpp arm/skyeye_common/vfp/vfp.cpp arm/skyeye_common/vfp/vfpdouble.cpp arm/skyeye_common/vfp/vfpinstr.cpp @@ -99,6 +101,7 @@ set(HEADERS arm/interpreter/arm_interpreter.h arm/jit_common/jit_util.h arm/jit_common/jit_base.h + arm/jit_x64/jit.h arm/skyeye_common/arm_regformat.h arm/skyeye_common/armcpu.h arm/skyeye_common/armdefs.h diff --git a/src/core/arm/jit_common/jit_base.cpp b/src/core/arm/jit_common/jit_base.cpp index 81409d697..3d1b96573 100644 --- a/src/core/arm/jit_common/jit_base.cpp +++ b/src/core/arm/jit_common/jit_base.cpp @@ -1,12 +1,13 @@ -// Copyright 2014 Citra Emulator Project +// Copyright 2015 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "core/arm/jit_common/jit_base.h" + #include "core/arm/skyeye_common/armcpu.h" #include "core/arm/skyeye_common/armemu.h" #include "core/arm/skyeye_common/vfp/vfp.h" - -#include "core/arm/jit_common/jit_base.h" +#include "core/arm/skyeye_common/armdefs.h" #include "core/core.h" #include "core/core_timing.h" @@ -71,7 +72,7 @@ void JitBase::SetCPSR(u32 cpsr) { } u64 JitBase::GetTicks() const { - // TODO(Subv): Remove ARM_DynCom::GetTicks() and use CoreTiming::GetTicks() directly once ARMemu is gone + // TODO(Subv, Alegend45): Remove JitBase::GetTicks() and use CoreTiming::GetTicks() directly once ARMemu is gone return CoreTiming::GetTicks(); } @@ -81,7 +82,7 @@ void JitBase::AddTicks(u64 ticks) { CoreTiming::Advance(); } -void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { +void JitBase::SaveContext(Core::ThreadContext& ctx) { memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers)); memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers)); @@ -97,7 +98,7 @@ void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { ctx.mode = state->NextInstr; } -void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) { +void JitBase::LoadContext(const Core::ThreadContext& ctx) { memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers)); memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers)); @@ -113,6 +114,6 @@ void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) { state->NextInstr = ctx.mode; } -void ARM_DynCom::PrepareReschedule() { +void JitBase::PrepareReschedule() { state->NumInstrsToExecute = 0; } diff --git a/src/core/arm/jit_common/jit_base.h b/src/core/arm/jit_common/jit_base.h index 9c6d72fef..4628e8970 100644 --- a/src/core/arm/jit_common/jit_base.h +++ b/src/core/arm/jit_common/jit_base.h @@ -1,11 +1,14 @@ -// Copyright 2014 Citra Emulator Project +// Copyright 2015 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #pragma once +#include + #include "common/x64_abi.h" #include "common/x64_emitter.h" +#include "common/common_types.h" #include "jit_util.h" #include "core/arm/arm_interface.h" #include "core/arm/skyeye_common/armdefs.h" @@ -13,13 +16,15 @@ #define RSCRATCH RAX #define RSCRATCH2 RDX +#define ARMSTATE(x) &state->x + class JitBase : virtual public ARM_Interface { protected: struct JitState { - u32 compilerPC; - u32 blockStart; + u32 compilerPC; + u32 blockStart; }; public: JitState js; @@ -38,6 +43,6 @@ private: std::unique_ptr state; }; -class Jitx64Base : public JitBase, X64CodeBlock +class Jitx64Base : public JitBase, public EmuCodeBlock { }; diff --git a/src/core/arm/jit_common/jit_util.h b/src/core/arm/jit_common/jit_util.h index 1aa5f273a..7aac530e8 100644 --- a/src/core/arm/jit_common/jit_util.h +++ b/src/core/arm/jit_common/jit_util.h @@ -1,4 +1,4 @@ -// Copyright 2014 Citra Emulator Project +// Copyright 2015 Citra Emulator Project // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -12,9 +12,29 @@ private: bool m_enabled = false; public: bool Enabled() { return m_enabled; } - void Init() { AllocCodeSpace(size); m_enabled = true; } + void Init(int size) { AllocCodeSpace(size); m_enabled = true; } void Shutdown() { FreeCodeSpace(); m_enabled = false; } }; static const int CODE_SIZE = 1024 * 1024 * 32; -static const int FARCODE_SIZE = 1024 * 1024 * 8; \ No newline at end of file +static const int FARCODE_SIZE = 1024 * 1024 * 8; + +class EmuCodeBlock : public Gen::X64CodeBlock +{ +public: + FarCodeCache farcode; + u8* nearcode; // Backed up when we switch to far code. + + // Simple functions to switch between near and far code emitting + void SwitchToFarCode() + { + nearcode = GetWritableCodePtr(); + SetCodePtr(farcode.GetWritableCodePtr()); + } + + void SwitchToNearCode() + { + farcode.SetCodePtr(GetWritableCodePtr()); + SetCodePtr(nearcode); + } +}; diff --git a/src/core/arm/jit_x64/jit.cpp b/src/core/arm/jit_x64/jit.cpp new file mode 100644 index 000000000..288dc22b8 --- /dev/null +++ b/src/core/arm/jit_x64/jit.cpp @@ -0,0 +1,44 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/x64_abi.h" +#include "common/x64_emitter.h" +#include "core/arm/arm_interface.h" +#include "core/arm/dyncom/arm_dyncom.h" +#include "core/arm/dyncom/arm_dyncom_interpreter.h" +#include "core/arm/skyeye_common/armdefs.h" +#include "core/arm/jit_common/jit_util.h" +#include "core/arm/jit_common/jit_base.h" +#include "core/arm/jit_x64/jit.h" + +Jit64::Jit64() +{ + interpreter = new ARM_DynCom(); +} + +void Jit64::ExecuteInstructions(int num_instructions) +{ + unsigned ticks_executed = MainLoop(num_instructions); + AddTicks(ticks_executed); +} + +unsigned Jit64::MainLoop(int num_instructions) +{ + //Always fallback to dyncom + for(;num_instructions>0;num_instructions--) + { + FallbackToInterpreter(); + } +} + +void Jit64::FallbackToInterpreter() +{ + MOV(32, ARMSTATE(pc), Imm32(js.compilerPC - 8)); + MOV(32, ARMSTATE(Reg(15)), Imm32(js.compilerPC)); //R15 -> R15 + 8 in execute stage. + ABI_PushRegistersAndAdjustStack({},0); + //Hacky but should get the job done. + MOV(32, ARMSTATE(NumInstrsToExecute), Imm32(1)); + ABI_CallFunctionC((void*)InterpreterMainLoop,M(state.get())); + ABI_PopRegistersAndAdjustStack({},0); +} diff --git a/src/core/arm/jit_x64/jit.h b/src/core/arm/jit_x64/jit.h new file mode 100644 index 000000000..3c95e444f --- /dev/null +++ b/src/core/arm/jit_x64/jit.h @@ -0,0 +1,24 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/x64_abi.h" +#include "common/x64_emitter.h" +#include "core/arm/arm_interface.h" +#include "core/arm/dyncom/arm_dyncom.h" +#include "core/arm/skyeye_common/armdefs.h" +#include "core/arm/jit_common/jit_util.h" +#include "core/arm/jit_common/jit_base.h" + +class Jit64 final : public Jitx64Base +{ +private: + ARM_DynCom* interpreter = nullptr; +public: + Jit64(); + void ExecuteInstructions(int num_instructions) override; + unsigned MainLoop(int num_instructions); + void FallbackToInterpreter(); +}; diff --git a/src/core/core.cpp b/src/core/core.cpp index e9e5c35cc..cfc1bcc91 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -12,6 +12,7 @@ #include "core/arm/disassembler/arm_disasm.h" #include "core/arm/interpreter/arm_interpreter.h" #include "core/arm/dyncom/arm_dyncom.h" +#include "core/arm/jit_x64/jit.h" #include "core/hle/hle.h" #include "core/hle/kernel/thread.h" #include "core/hw/hw.h" @@ -62,6 +63,8 @@ int Init() { g_sys_core = new ARM_Interpreter(); switch (Settings::values.cpu_core) { + case CPU_JIT: + g_app_core = new Jit64(); case CPU_Interpreter: g_app_core = new ARM_DynCom(); break; diff --git a/src/core/core.h b/src/core/core.h index 2f5e8bc6b..5ddfeaf67 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -13,6 +13,7 @@ class ARM_Interface; namespace Core { enum CPUCore { + CPU_JIT, CPU_Interpreter, CPU_OldInterpreter, };