diff --git a/src/ARMJIT.cpp b/src/ARMJIT.cpp index 6948eeed..74554d76 100644 --- a/src/ARMJIT.cpp +++ b/src/ARMJIT.cpp @@ -188,6 +188,8 @@ CompiledBlock CompileBlock(ARM* cpu) void InvalidateBlockCache() { + printf("Resetting JIT block cache...\n"); + memset(cache.MainRAM, 0, sizeof(cache.MainRAM)); memset(cache.SWRAM, 0, sizeof(cache.SWRAM)); memset(cache.ARM9_BIOS, 0, sizeof(cache.ARM9_BIOS)); diff --git a/src/ARMJIT_x64/ARMJIT_ALU.cpp b/src/ARMJIT_x64/ARMJIT_ALU.cpp index 368fd8b3..f0bcf8ed 100644 --- a/src/ARMJIT_x64/ARMJIT_ALU.cpp +++ b/src/ARMJIT_x64/ARMJIT_ALU.cpp @@ -257,7 +257,7 @@ void Compiler::Comp_MulOp(bool S, bool add, Gen::OpArg rd, Gen::OpArg rm, Gen::O Comp_AddCycles_CI(RSCRATCH, add ? 2 : 1); } - static_assert(EAX == RSCRATCH); + static_assert(EAX == RSCRATCH, "Someone changed RSCRATCH!"); MOV(32, R(RSCRATCH), rm); if (add) { @@ -383,7 +383,7 @@ OpArg Compiler::Comp_RegShiftReg(int op, Gen::OpArg rs, Gen::OpArg rm, bool S, b } MOV(32, R(RSCRATCH), rm); - static_assert(RSCRATCH3 == ECX); + static_assert(RSCRATCH3 == ECX, "Someone changed RSCRATCH3"); MOV(32, R(ECX), rs); AND(32, R(ECX), Imm32(0xFF)); diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.cpp b/src/ARMJIT_x64/ARMJIT_Compiler.cpp index cb11f732..0fbcfda9 100644 --- a/src/ARMJIT_x64/ARMJIT_Compiler.cpp +++ b/src/ARMJIT_x64/ARMJIT_Compiler.cpp @@ -63,12 +63,11 @@ Compiler::Compiler() mprotect(pageAligned, alignedSize, PROT_EXEC | PROT_READ | PROT_WRITE); #endif - region = pageAligned; - region_size = alignedSize; - total_region_size = region_size; + ResetStart = pageAligned; + CodeMemSize = alignedSize; } - ClearCodeSpace(); + Reset(); for (int i = 0; i < 3; i++) { @@ -169,9 +168,8 @@ Compiler::Compiler() } // move the region forward to prevent overwriting the generated functions - region_size -= GetWritableCodePtr() - region; - total_region_size = region_size; - region = GetWritableCodePtr(); + CodeMemSize -= GetWritableCodePtr() - ResetStart; + ResetStart = GetWritableCodePtr(); } void Compiler::LoadCPSR() @@ -208,7 +206,7 @@ Gen::FixupBranch Compiler::CheckCondition(u32 cond) { if (cond >= 0x8) { - static_assert(RSCRATCH3 == ECX); + static_assert(RSCRATCH3 == ECX, "RSCRATCH has to be equal to ECX!"); MOV(32, R(RSCRATCH3), R(RCPSR)); SHR(32, R(RSCRATCH3), Imm8(28)); MOV(32, R(RSCRATCH), Imm32(1)); @@ -346,12 +344,13 @@ const Compiler::CompileFunc T_Comp[ARMInstrInfo::tk_Count] = { void Compiler::Reset() { - ClearCodeSpace(); + memset(ResetStart, 0xcc, CodeMemSize); + SetCodePtr(ResetStart); } CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrsCount) { - if (IsAlmostFull()) + if (CodeMemSize - (GetWritableCodePtr() - ResetStart) < 1024 * 32) // guess... InvalidateBlockCache(); ConstantCycles = 0; diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.h b/src/ARMJIT_x64/ARMJIT_Compiler.h index 0ce7d8d2..3151cbc1 100644 --- a/src/ARMJIT_x64/ARMJIT_Compiler.h +++ b/src/ARMJIT_x64/ARMJIT_Compiler.h @@ -17,7 +17,7 @@ const Gen::X64Reg RSCRATCH2 = Gen::EDX; const Gen::X64Reg RSCRATCH3 = Gen::ECX; -class Compiler : public Gen::X64CodeBlock +class Compiler : public Gen::XEmitter { public: Compiler(); @@ -132,6 +132,9 @@ public: return Gen::R(RegCache.Mapping[reg]); } + u8* ResetStart; + u32 CodeMemSize; + void* MemoryFuncs9[3][2]; void* MemoryFuncs7[3][2][2]; diff --git a/src/ARMJIT_x64/ARMJIT_LoadStore.cpp b/src/ARMJIT_x64/ARMJIT_LoadStore.cpp index ee0a7af7..6386f8ba 100644 --- a/src/ARMJIT_x64/ARMJIT_LoadStore.cpp +++ b/src/ARMJIT_x64/ARMJIT_LoadStore.cpp @@ -171,7 +171,7 @@ void* Compiler::Gen_MemoryRoutine9(bool store, int size) } RET(); - static_assert(RSCRATCH == EAX); + static_assert(RSCRATCH == EAX, "Someone changed RSCRATCH!"); return res; } diff --git a/src/dolphin/CodeBlock.h b/src/dolphin/CodeBlock.h deleted file mode 100644 index e71cf6d5..00000000 --- a/src/dolphin/CodeBlock.h +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2014 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license_dolphin.txt file included. - -#pragma once - -#include -#include - -#include "Assert.h" -#include "../types.h" - -namespace Common -{ -// Everything that needs to generate code should inherit from this. -// You get memory management for free, plus, you can use all emitter functions without -// having to prefix them with gen-> or something similar. -// Example implementation: -// class JIT : public CodeBlock {} -template -class CodeBlock : public T -{ -private: - // A privately used function to set the executable RAM space to something invalid. - // For debugging usefulness it should be used to set the RAM to a host specific breakpoint - // instruction - virtual void PoisonMemory() = 0; - -protected: - u8* region = nullptr; - // Size of region we can use. - size_t region_size = 0; - // Original size of the region we allocated. - size_t total_region_size = 0; - - bool m_is_child = false; - std::vector m_children; - -public: - CodeBlock() = default; - virtual ~CodeBlock() - { - } - CodeBlock(const CodeBlock&) = delete; - CodeBlock& operator=(const CodeBlock&) = delete; - CodeBlock(CodeBlock&&) = delete; - CodeBlock& operator=(CodeBlock&&) = delete; - - // Always clear code space with breakpoints, so that if someone accidentally executes - // uninitialized, it just breaks into the debugger. - void ClearCodeSpace() - { - PoisonMemory(); - ResetCodePtr(); - } - - bool IsInSpace(const u8* ptr) const { return ptr >= region && ptr < (region + region_size); } - - void ResetCodePtr() { T::SetCodePtr(region); } - size_t GetSpaceLeft() const - { - ASSERT(static_cast(T::GetCodePtr() - region) < region_size); - return region_size - (T::GetCodePtr() - region); - } - - bool IsAlmostFull() const - { - // This should be bigger than the biggest block ever. - return GetSpaceLeft() < 0x10000; - } - - bool HasChildren() const { return region_size != total_region_size; } - u8* AllocChildCodeSpace(size_t child_size) - { - ASSERT_MSG(DYNA_REC, child_size < GetSpaceLeft(), "Insufficient space for child allocation."); - u8* child_region = region + region_size - child_size; - region_size -= child_size; - return child_region; - } - void AddChildCodeSpace(CodeBlock* child, size_t child_size) - { - u8* child_region = AllocChildCodeSpace(child_size); - child->m_is_child = true; - child->region = child_region; - child->region_size = child_size; - child->total_region_size = child_size; - child->ResetCodePtr(); - m_children.emplace_back(child); - } -}; -} // namespace Common diff --git a/src/dolphin/Assert.h b/src/dolphin/Compat.h similarity index 89% rename from src/dolphin/Assert.h rename to src/dolphin/Compat.h index 4eb16e09..f2f52a5c 100644 --- a/src/dolphin/Assert.h +++ b/src/dolphin/Compat.h @@ -1,11 +1,9 @@ -// Copyright 2015 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license_dolphin.txt file included. - +// Stubs for Assert.h and Log.h #pragma once #include +// Assert stub #define ASSERT_MSG(_t_, _a_, _fmt_, ...) \ assert(_a_) \ /*do \ @@ -45,3 +43,21 @@ if (MAX_LOGLEVEL >= LogTypes::LOG_LEVELS::LDEBUG) \ ASSERT(_a_); \ } while (0)*/ + +// Log Stub +#include + +#define PanicAlert(fmt, ...) \ + do \ + { \ + printf(fmt "\n", ## __VA_ARGS__); \ + abort(); \ + } while (false) + +#define DYNA_REC 0 + +#define ERROR_LOG(which, fmt, ...) \ + do \ + { \ + printf(fmt "\n", ## __VA_ARGS__); \ + } while (false) diff --git a/src/dolphin/Intrinsics.h b/src/dolphin/Intrinsics.h deleted file mode 100644 index 483f2195..00000000 --- a/src/dolphin/Intrinsics.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2015 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license_dolphin.txt file included. - -#pragma once - -#if defined(_M_X86) - -/** - * It is assumed that all compilers used to build Dolphin support intrinsics up to and including - * SSE 4.2 on x86/x64. - */ - -#if defined(__GNUC__) || defined(__clang__) - -/** - * Due to limitations in GCC, SSE intrinsics are only available when compiling with the - * corresponding instruction set enabled. However, using the target attribute, we can compile - * single functions with a different target instruction set, while still creating a generic build. - * - * Since this instruction set is enabled per-function, any callers should verify that the - * instruction set is supported at runtime before calling it, and provide a fallback implementation - * when not supported. - * - * When building with -march=native, or enabling the instruction sets in the compile flags, permit - * usage of the instrinsics without any function attributes. If the command-line architecture does - * not support this instruction set, enable it via function targeting. - */ - -#include -#ifndef __SSE4_2__ -#define FUNCTION_TARGET_SSE42 [[gnu::target("sse4.2")]] -#endif -#ifndef __SSE4_1__ -#define FUNCTION_TARGET_SSR41 [[gnu::target("sse4.1")]] -#endif -#ifndef __SSSE3__ -#define FUNCTION_TARGET_SSSE3 [[gnu::target("ssse3")]] -#endif -#ifndef __SSE3__ -#define FUNCTION_TARGET_SSE3 [[gnu::target("sse3")]] -#endif - -#elif defined(_MSC_VER) || defined(__INTEL_COMPILER) - -/** - * MSVC and ICC support intrinsics for any instruction set without any function attributes. - */ -#include - -#endif // defined(_MSC_VER) || defined(__INTEL_COMPILER) - -#endif // _M_X86 - -/** - * Define the FUNCTION_TARGET macros to nothing if they are not needed, or not on an X86 platform. - * This way when a function is defined with FUNCTION_TARGET you don't need to define a second - * version without the macro around a #ifdef guard. Be careful when using intrinsics, as all use - * should still be placed around a #ifdef _M_X86 if the file is compiled on all architectures. - */ -#ifndef FUNCTION_TARGET_SSE42 -#define FUNCTION_TARGET_SSE42 -#endif -#ifndef FUNCTION_TARGET_SSR41 -#define FUNCTION_TARGET_SSR41 -#endif -#ifndef FUNCTION_TARGET_SSSE3 -#define FUNCTION_TARGET_SSSE3 -#endif -#ifndef FUNCTION_TARGET_SSE3 -#define FUNCTION_TARGET_SSE3 -#endif diff --git a/src/dolphin/Log.h b/src/dolphin/Log.h deleted file mode 100644 index a7f4b6a0..00000000 --- a/src/dolphin/Log.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "CommonFuncs.h" - -#include - -#define PanicAlert(fmt, ...) \ - do \ - { \ - printf(fmt "\n", ## __VA_ARGS__); \ - abort(); \ - } while (false) - - -#define DYNA_REC 0 - -#define ERROR_LOG(which, fmt, ...) \ - do \ - { \ - printf(fmt "\n", ## __VA_ARGS__); \ - } while (false) diff --git a/src/dolphin/x64CPUDetect.cpp b/src/dolphin/x64CPUDetect.cpp index 05ee11ca..49b51c9d 100644 --- a/src/dolphin/x64CPUDetect.cpp +++ b/src/dolphin/x64CPUDetect.cpp @@ -7,7 +7,6 @@ #include "CPUDetect.h" #include "../types.h" -#include "Intrinsics.h" #ifndef _MSVC_VER diff --git a/src/dolphin/x64Emitter.cpp b/src/dolphin/x64Emitter.cpp index 78496243..343f314c 100644 --- a/src/dolphin/x64Emitter.cpp +++ b/src/dolphin/x64Emitter.cpp @@ -7,9 +7,10 @@ #include "CPUDetect.h" #include "../types.h" -#include "Log.h" #include "x64Emitter.h" #include "x64Reg.h" +#include "Compat.h" +#include "CommonFuncs.h" namespace Gen { diff --git a/src/dolphin/x64Emitter.h b/src/dolphin/x64Emitter.h index 122850d0..869acb6f 100644 --- a/src/dolphin/x64Emitter.h +++ b/src/dolphin/x64Emitter.h @@ -12,9 +12,8 @@ #include #include -#include "Assert.h" +#include "Compat.h" #include "BitSet.h" -#include "CodeBlock.h" #include "../types.h" #include "x64ABI.h" @@ -1167,14 +1166,4 @@ public: } }; // class XEmitter -class X64CodeBlock : public Common::CodeBlock -{ -private: - void PoisonMemory() override - { - // x86/64: 0xCC = breakpoint - memset(region, 0xCC, region_size); - } -}; - } // namespace