1 // Copyright (c) 2013- PPSSPP Project. 2 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, version 2.0 or later versions. 6 7 // This program is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 // GNU General Public License 2.0 for more details. 11 12 // A copy of the GPL 2.0 should have been included with the program. 13 // If not, see http://www.gnu.org/licenses/ 14 15 // Official git repository and contact information can be found at 16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. 17 18 19 #pragma once 20 21 #include "Common/Common.h" 22 #include "Common/Log.h" 23 #include "Core/MIPS/MIPS.h" 24 25 struct JitBlock; 26 class JitBlockCache; 27 28 namespace MIPSComp { 29 30 enum CompileDelaySlotFlags 31 { 32 // Easy, nothing extra. 33 DELAYSLOT_NICE = 0, 34 // Flush registers after delay slot. 35 DELAYSLOT_FLUSH = 1, 36 // Preserve flags. 37 DELAYSLOT_SAFE = 2, 38 // Flush registers after and preserve flags. 39 DELAYSLOT_SAFE_FLUSH = DELAYSLOT_FLUSH | DELAYSLOT_SAFE, 40 }; 41 42 struct JitState 43 { 44 enum PrefixState 45 { 46 PREFIX_UNKNOWN = 0x00, 47 PREFIX_KNOWN = 0x01, 48 PREFIX_DIRTY = 0x10, 49 PREFIX_KNOWN_DIRTY = 0x11, 50 }; 51 52 enum AfterOp 53 { 54 AFTER_NONE = 0x00, 55 AFTER_CORE_STATE = 0x01, 56 AFTER_REWIND_PC_BAD_STATE = 0x02, 57 AFTER_MEMCHECK_CLEANUP = 0x04, 58 }; 59 60 u32 compilerPC; 61 u32 blockStart; 62 u32 lastContinuedPC; 63 u32 initialBlockSize; 64 int nextExit; 65 bool cancel; 66 bool inDelaySlot; 67 // See JitState::AfterOp for values. 68 int afterOp; 69 int downcountAmount; 70 int numInstructions; 71 bool compiling; // TODO: get rid of this in favor of using analysis results to determine end of block 72 bool hadBreakpoints; 73 bool preloading = false; 74 JitBlock *curBlock; 75 76 u8 hasSetRounding = 0; 77 u8 lastSetRounding = 0; 78 const u8 *currentRoundingFunc = nullptr; 79 80 // VFPU prefix magic 81 bool startDefaultPrefix = true; 82 u32 prefixS; 83 u32 prefixT; 84 u32 prefixD; 85 PrefixState prefixSFlag = PREFIX_UNKNOWN; 86 PrefixState prefixTFlag = PREFIX_UNKNOWN; 87 PrefixState prefixDFlag = PREFIX_UNKNOWN; 88 PrefixStartJitState89 void PrefixStart() { 90 if (startDefaultPrefix) { 91 EatPrefix(); 92 } else { 93 PrefixUnknown(); 94 } 95 } 96 PrefixUnknownJitState97 void PrefixUnknown() { 98 prefixSFlag = PREFIX_UNKNOWN; 99 prefixTFlag = PREFIX_UNKNOWN; 100 prefixDFlag = PREFIX_UNKNOWN; 101 } 102 HasSPrefixJitState103 bool HasSPrefix() const { 104 return (prefixSFlag & PREFIX_KNOWN) == 0 || prefixS != 0xE4; 105 } 106 HasTPrefixJitState107 bool HasTPrefix() const { 108 return (prefixTFlag & PREFIX_KNOWN) == 0 || prefixT != 0xE4; 109 } 110 HasDPrefixJitState111 bool HasDPrefix() const { 112 return (prefixDFlag & PREFIX_KNOWN) == 0 || prefixD != 0x0; 113 } 114 MayHavePrefixJitState115 bool MayHavePrefix() const { 116 if (HasUnknownPrefix()) { 117 return true; 118 } else if (prefixS != 0xE4 || prefixT != 0xE4 || prefixD != 0) { 119 return true; 120 } 121 return false; 122 } 123 HasUnknownPrefixJitState124 bool HasUnknownPrefix() const { 125 if (!(prefixSFlag & PREFIX_KNOWN) || !(prefixTFlag & PREFIX_KNOWN) || !(prefixDFlag & PREFIX_KNOWN)) { 126 return true; 127 } 128 return false; 129 } 130 HasNoPrefixJitState131 bool HasNoPrefix() const { 132 return !HasSPrefix() && !HasTPrefix() && !HasDPrefix(); 133 } 134 EatPrefixJitState135 void EatPrefix() { 136 if (HasSPrefix()) 137 prefixSFlag = PREFIX_KNOWN_DIRTY; 138 prefixS = 0xE4; 139 if (HasTPrefix()) 140 prefixTFlag = PREFIX_KNOWN_DIRTY; 141 prefixT = 0xE4; 142 if (HasDPrefix()) 143 prefixDFlag = PREFIX_KNOWN_DIRTY; 144 prefixD = 0x0; 145 } 146 VfpuWriteMaskJitState147 u8 VfpuWriteMask() const { 148 _assert_(prefixDFlag & JitState::PREFIX_KNOWN); 149 return (prefixD >> 8) & 0xF; 150 } 151 VfpuWriteMaskJitState152 bool VfpuWriteMask(int i) const { 153 _assert_(prefixDFlag & JitState::PREFIX_KNOWN); 154 return (prefixD >> (8 + i)) & 1; 155 } 156 LogPrefixJitState157 void LogPrefix() { 158 LogSTPrefix("S", prefixS, prefixSFlag); 159 LogSTPrefix("T", prefixT, prefixTFlag); 160 LogDPrefix(); 161 } 162 163 private: LogSTPrefixJitState164 void LogSTPrefix(const char *name, int p, int pflag) { 165 if ((prefixSFlag & PREFIX_KNOWN) == 0) { 166 ERROR_LOG(JIT, "%s: unknown (%08x %i)", name, p, pflag); 167 } else if (prefixS != 0xE4) { 168 ERROR_LOG(JIT, "%s: %08x flag: %i", name, p, pflag); 169 } else { 170 WARN_LOG(JIT, "%s: %08x flag: %i", name, p, pflag); 171 } 172 } LogDPrefixJitState173 void LogDPrefix() { 174 if ((prefixDFlag & PREFIX_KNOWN) == 0) { 175 ERROR_LOG(JIT, "D: unknown (%08x %i)", prefixD, prefixDFlag); 176 } else if (prefixD != 0) { 177 ERROR_LOG(JIT, "D: (%08x %i)", prefixD, prefixDFlag); 178 } else { 179 WARN_LOG(JIT, "D: %08x flag: %i", prefixD, prefixDFlag); 180 } 181 } 182 }; 183 184 enum class JitDisable { 185 ALU = 0x0001, 186 ALU_IMM = 0x0002, 187 ALU_BIT = 0x0004, 188 MULDIV = 0x0008, 189 190 FPU = 0x0010, 191 FPU_COMP = 0x0040, 192 FPU_XFER = 0x0080, 193 194 VFPU_VEC = 0x0100, 195 VFPU_MTX_VTFM = 0x0200, 196 VFPU_COMP = 0x0400, 197 VFPU_XFER = 0x0800, 198 199 LSU = 0x1000, 200 LSU_UNALIGNED = 0x2000, 201 LSU_FPU = 0x4000, 202 LSU_VFPU = 0x8000, 203 204 SIMD = 0x00100000, 205 BLOCKLINK = 0x00200000, 206 POINTERIFY = 0x00400000, 207 STATIC_ALLOC = 0x00800000, 208 CACHE_POINTERS = 0x01000000, 209 REGALLOC_GPR = 0x02000000, // Doesn't really disable regalloc, but flushes after every instr. 210 REGALLOC_FPR = 0x04000000, 211 VFPU_MTX_VMMOV = 0x08000000, 212 VFPU_MTX_VMMUL = 0x10000000, 213 VFPU_MTX_VMSCL = 0x20000000, 214 215 ALL_FLAGS = 0x3FFFFFFF, 216 }; 217 218 struct JitOptions { 219 JitOptions(); 220 221 bool Disabled(JitDisable bit); 222 223 uint32_t disableFlags; 224 225 // x86 226 bool enableVFPUSIMD; 227 bool reserveR15ForAsm; 228 229 // ARM/ARM64 230 bool useBackJump; 231 bool useForwardJump; 232 bool cachePointers; 233 // ARM only 234 bool useNEONVFPU; 235 bool downcountInRegister; 236 // ARM64 only 237 bool useASIMDVFPU; 238 bool useStaticAlloc; 239 bool enablePointerify; 240 241 // Common 242 bool enableBlocklink; 243 bool immBranches; 244 bool continueBranches; 245 bool continueJumps; 246 int continueMaxInstructions; 247 }; 248 249 } 250 251