1 // Copyright 2010 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include <cstddef>
8 #include <map>
9 #include <unordered_set>
10 
11 #include "Common/CommonTypes.h"
12 #include "Common/x64Emitter.h"
13 #include "Core/ConfigManager.h"
14 #include "Core/MachineContext.h"
15 #include "Core/PowerPC/CPUCoreBase.h"
16 #include "Core/PowerPC/JitCommon/JitAsmCommon.h"
17 #include "Core/PowerPC/JitCommon/JitCache.h"
18 #include "Core/PowerPC/PPCAnalyst.h"
19 
20 //#define JIT_LOG_GENERATED_CODE  // Enables logging of generated code
21 //#define JIT_LOG_GPR             // Enables logging of the PPC general purpose regs
22 //#define JIT_LOG_FPR             // Enables logging of the PPC floating point regs
23 
24 // Use these to control the instruction selection
25 // #define INSTRUCTION_START FallBackToInterpreter(inst); return;
26 // #define INSTRUCTION_START PPCTables::CountInstruction(inst);
27 #define INSTRUCTION_START
28 
29 #define FALLBACK_IF(cond)                                                                          \
30   do                                                                                               \
31   {                                                                                                \
32     if (cond)                                                                                      \
33     {                                                                                              \
34       FallBackToInterpreter(inst);                                                                 \
35       return;                                                                                      \
36     }                                                                                              \
37   } while (0)
38 
39 #define JITDISABLE(setting)                                                                        \
40   FALLBACK_IF(SConfig::GetInstance().bJITOff || SConfig::GetInstance().setting)
41 
42 class JitBase : public CPUCoreBase
43 {
44 protected:
45   struct JitOptions
46   {
47     bool enableBlocklink;
48     bool optimizeGatherPipe;
49     bool accurateSinglePrecision;
50     bool fastmem;
51     bool fastmem_arena;
52     bool memcheck;
53     bool profile_blocks;
54   };
55   struct JitState
56   {
57     u32 compilerPC;
58     u32 blockStart;
59     int instructionNumber;
60     int instructionsLeft;
61     int downcountAmount;
62     u32 numLoadStoreInst;
63     u32 numFloatingPointInst;
64     // If this is set, we need to generate an exception handler for the fastmem load.
65     u8* fastmemLoadStore;
66     // If this is set, a load or store already prepared a jump to the exception handler for us,
67     // so just fixup that branch instead of testing for a DSI again.
68     bool fixupExceptionHandler;
69     Gen::FixupBranch exceptionHandler;
70 
71     bool assumeNoPairedQuantize;
72     std::map<u8, u32> constantGqr;
73     bool firstFPInstructionFound;
74     bool isLastInstruction;
75     int skipInstructions;
76     bool carryFlagSet;
77     bool carryFlagInverted;
78 
79     bool generatingTrampoline = false;
80     u8* trampolineExceptionHandler;
81 
82     bool mustCheckFifo;
83     int fifoBytesSinceCheck;
84 
85     PPCAnalyst::BlockStats st;
86     PPCAnalyst::BlockRegStats gpa;
87     PPCAnalyst::BlockRegStats fpa;
88     PPCAnalyst::CodeOp* op;
89 
90     JitBlock* curBlock;
91 
92     std::unordered_set<u32> fifoWriteAddresses;
93     std::unordered_set<u32> pairedQuantizeAddresses;
94     std::unordered_set<u32> noSpeculativeConstantsAddresses;
95   };
96 
97   PPCAnalyst::CodeBlock code_block;
98   PPCAnalyst::CodeBuffer m_code_buffer;
99   PPCAnalyst::PPCAnalyzer analyzer;
100 
101   bool CanMergeNextInstructions(int count) const;
102 
103   void UpdateMemoryOptions();
104 
105 public:
106   JitBase();
107   ~JitBase() override;
108 
109   static const u8* Dispatch(JitBase& jit);
110   virtual JitBaseBlockCache* GetBlockCache() = 0;
111 
112   virtual void Jit(u32 em_address) = 0;
113 
114   virtual const CommonAsmRoutinesBase* GetAsmRoutines() = 0;
115 
116   virtual bool HandleFault(uintptr_t access_address, SContext* ctx) = 0;
HandleStackFault()117   virtual bool HandleStackFault() { return false; }
118 
119   static constexpr std::size_t code_buffer_size = 32000;
120 
121   // This should probably be removed from public:
122   JitOptions jo{};
123   JitState js{};
124 };
125 
126 void JitTrampoline(JitBase& jit, u32 em_address);
127