CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Core/MIPS/x86/X64IRRegCache.h
Views: 1401
1
// Copyright (c) 2023- 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
#pragma once
19
20
#include "ppsspp_config.h"
21
#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)
22
23
#include "Common/x64Emitter.h"
24
#include "Core/MIPS/MIPS.h"
25
#include "Core/MIPS/IR/IRJit.h"
26
#include "Core/MIPS/IR/IRRegCache.h"
27
28
namespace X64IRJitConstants {
29
30
#if PPSSPP_ARCH(AMD64)
31
const Gen::X64Reg MEMBASEREG = Gen::RBX;
32
const Gen::X64Reg CTXREG = Gen::R14;
33
// Note: this is actually offset from the base.
34
const Gen::X64Reg JITBASEREG = Gen::R15;
35
const Gen::X64Reg DOWNCOUNTREG = Gen::R15;
36
#else
37
const Gen::X64Reg CTXREG = Gen::EBP;
38
const Gen::X64Reg DOWNCOUNTREG = Gen::INVALID_REG;
39
#endif
40
const Gen::X64Reg SCRATCH1 = Gen::EAX;
41
42
static constexpr auto downcountOffset = offsetof(MIPSState, downcount) - 128;
43
static constexpr auto tempOffset = offsetof(MIPSState, temp) - 128;
44
static constexpr auto fcr31Offset = offsetof(MIPSState, fcr31) - 128;
45
static constexpr auto pcOffset = offsetof(MIPSState, pc) - 128;
46
static constexpr auto mxcsrTempOffset = offsetof(MIPSState, mxcsrTemp) - 128;
47
48
enum class X64Map : uint8_t {
49
NONE = 0,
50
// On 32-bit: EAX, EBX, ECX, EDX
51
LOW_SUBREG = 0x10,
52
// EDX/RDX for DIV/MUL/similar.
53
HIGH_DATA = 0x20,
54
// ECX/RCX only, for shifts.
55
SHIFT = 0x30,
56
// XMM0 for BLENDVPS, funcs.
57
XMM0 = 0x40,
58
MASK = 0xF0,
59
};
60
static inline MIPSMap operator |(const MIPSMap &lhs, const X64Map &rhs) {
61
return MIPSMap((uint8_t)lhs | (uint8_t)rhs);
62
}
63
static inline X64Map operator |(const X64Map &lhs, const X64Map &rhs) {
64
return X64Map((uint8_t)lhs | (uint8_t)rhs);
65
}
66
static inline X64Map operator &(const MIPSMap &lhs, const X64Map &rhs) {
67
return X64Map((uint8_t)lhs & (uint8_t)rhs);
68
}
69
static inline X64Map operator &(const X64Map &lhs, const X64Map &rhs) {
70
return X64Map((uint8_t)lhs & (uint8_t)rhs);
71
}
72
73
} // namespace X64IRJitConstants
74
75
class X64IRRegCache : public IRNativeRegCacheBase {
76
public:
77
X64IRRegCache(MIPSComp::JitOptions *jo);
78
79
void Init(Gen::XEmitter *emitter);
80
81
// May fail and return INVALID_REG if it needs flushing.
82
Gen::X64Reg TryMapTempImm(IRReg reg, X64IRJitConstants::X64Map flags = X64IRJitConstants::X64Map::NONE);
83
84
// Returns an X64 register containing the requested MIPS register.
85
Gen::X64Reg MapGPR(IRReg reg, MIPSMap mapFlags = MIPSMap::INIT);
86
Gen::X64Reg MapGPR2(IRReg reg, MIPSMap mapFlags = MIPSMap::INIT);
87
Gen::X64Reg MapGPRAsPointer(IRReg reg);
88
Gen::X64Reg MapFPR(IRReg reg, MIPSMap mapFlags = MIPSMap::INIT);
89
Gen::X64Reg MapVec4(IRReg first, MIPSMap mapFlags = MIPSMap::INIT);
90
91
Gen::X64Reg MapWithFPRTemp(const IRInst &inst);
92
93
void MapWithFlags(IRInst inst, X64IRJitConstants::X64Map destFlags, X64IRJitConstants::X64Map src1Flags = X64IRJitConstants::X64Map::NONE, X64IRJitConstants::X64Map src2Flags = X64IRJitConstants::X64Map::NONE);
94
95
// Note: may change the high lanes of single-register XMMs.
96
void FlushAll(bool gprs = true, bool fprs = true) override;
97
void FlushBeforeCall();
98
99
Gen::X64Reg GetAndLockTempGPR();
100
Gen::X64Reg GetAndLockTempFPR();
101
void ReserveAndLockXGPR(Gen::X64Reg r);
102
103
Gen::OpArg R(IRReg preg);
104
Gen::OpArg RPtr(IRReg preg);
105
Gen::OpArg F(IRReg preg);
106
Gen::X64Reg RX(IRReg preg); // Returns a cached register, while checking that it's NOT mapped as a pointer
107
Gen::X64Reg RXPtr(IRReg preg); // Returns a cached register, if it has been mapped as a pointer
108
Gen::X64Reg FX(IRReg preg);
109
110
static bool HasLowSubregister(Gen::X64Reg reg);
111
112
protected:
113
const int *GetAllocationOrder(MIPSLoc type, MIPSMap flags, int &count, int &base) const override;
114
void AdjustNativeRegAsPtr(IRNativeReg nreg, bool state) override;
115
116
void LoadNativeReg(IRNativeReg nreg, IRReg first, int lanes) override;
117
void StoreNativeReg(IRNativeReg nreg, IRReg first, int lanes) override;
118
void SetNativeRegValue(IRNativeReg nreg, uint32_t imm) override;
119
void StoreRegValue(IRReg mreg, uint32_t imm) override;
120
bool TransferNativeReg(IRNativeReg nreg, IRNativeReg dest, MIPSLoc type, IRReg first, int lanes, MIPSMap flags) override;
121
122
private:
123
bool TransferVecTo1(IRNativeReg nreg, IRNativeReg dest, IRReg first, int oldlanes);
124
bool Transfer1ToVec(IRNativeReg nreg, IRNativeReg dest, IRReg first, int lanes);
125
126
IRNativeReg GPRToNativeReg(Gen::X64Reg r) {
127
return (IRNativeReg)r;
128
}
129
IRNativeReg XMMToNativeReg(Gen::X64Reg r) {
130
return (IRNativeReg)(r + NUM_X_REGS);
131
}
132
Gen::X64Reg FromNativeReg(IRNativeReg r) {
133
if (r >= NUM_X_REGS)
134
return (Gen::X64Reg)(Gen::XMM0 + (r - NUM_X_REGS));
135
return (Gen::X64Reg)(Gen::RAX + r);
136
}
137
138
Gen::XEmitter *emit_ = nullptr;
139
140
enum {
141
#if PPSSPP_ARCH(AMD64)
142
NUM_X_REGS = 16,
143
NUM_X_FREGS = 16,
144
#elif PPSSPP_ARCH(X86)
145
NUM_X_REGS = 8,
146
NUM_X_FREGS = 8,
147
#endif
148
};
149
};
150
151
#endif
152
153