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/ARM64/Arm64IRCompBranch.cpp
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
#include "ppsspp_config.h"
19
// In other words, PPSSPP_ARCH(ARM64) || DISASM_ALL.
20
#if PPSSPP_ARCH(ARM64) || (PPSSPP_PLATFORM(WINDOWS) && !defined(__LIBRETRO__))
21
22
#include "Core/MIPS/ARM64/Arm64IRJit.h"
23
#include "Core/MIPS/ARM64/Arm64IRRegCache.h"
24
25
// This file contains compilation for exits.
26
//
27
// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly.
28
// Currently known non working ones should have DISABLE. No flags because that's in IR already.
29
30
// #define CONDITIONAL_DISABLE { CompIR_Generic(inst); return; }
31
#define CONDITIONAL_DISABLE {}
32
#define DISABLE { CompIR_Generic(inst); return; }
33
#define INVALIDOP { _assert_msg_(false, "Invalid IR inst %d", (int)inst.op); CompIR_Generic(inst); return; }
34
35
namespace MIPSComp {
36
37
using namespace Arm64Gen;
38
using namespace Arm64IRJitConstants;
39
40
void Arm64JitBackend::CompIR_Exit(IRInst inst) {
41
CONDITIONAL_DISABLE;
42
43
ARM64Reg exitReg = INVALID_REG;
44
switch (inst.op) {
45
case IROp::ExitToConst:
46
FlushAll();
47
WriteConstExit(inst.constant);
48
break;
49
50
case IROp::ExitToReg:
51
exitReg = regs_.MapGPR(inst.src1);
52
FlushAll();
53
MOV(SCRATCH1, exitReg);
54
B(dispatcherPCInSCRATCH1_);
55
break;
56
57
case IROp::ExitToPC:
58
FlushAll();
59
B(dispatcherCheckCoreState_);
60
break;
61
62
default:
63
INVALIDOP;
64
break;
65
}
66
}
67
68
void Arm64JitBackend::CompIR_ExitIf(IRInst inst) {
69
CONDITIONAL_DISABLE;
70
71
ARM64Reg lhs = INVALID_REG;
72
ARM64Reg rhs = INVALID_REG;
73
FixupBranch fixup;
74
switch (inst.op) {
75
case IROp::ExitToConstIfEq:
76
case IROp::ExitToConstIfNeq:
77
if (regs_.IsGPRImm(inst.src1) && regs_.GetGPRImm(inst.src1) == 0) {
78
lhs = regs_.MapGPR(inst.src2);
79
FlushAll();
80
81
if (inst.op == IROp::ExitToConstIfEq)
82
fixup = CBNZ(lhs);
83
else if (inst.op == IROp::ExitToConstIfNeq)
84
fixup = CBZ(lhs);
85
else
86
_assert_(false);
87
} else if (regs_.IsGPRImm(inst.src2) && regs_.GetGPRImm(inst.src2) == 0) {
88
lhs = regs_.MapGPR(inst.src1);
89
FlushAll();
90
91
if (inst.op == IROp::ExitToConstIfEq)
92
fixup = CBNZ(lhs);
93
else if (inst.op == IROp::ExitToConstIfNeq)
94
fixup = CBZ(lhs);
95
else
96
_assert_(false);
97
} else {
98
regs_.Map(inst);
99
lhs = regs_.R(inst.src1);
100
rhs = regs_.R(inst.src2);
101
FlushAll();
102
103
CMP(lhs, rhs);
104
if (inst.op == IROp::ExitToConstIfEq)
105
fixup = B(CC_NEQ);
106
else if (inst.op == IROp::ExitToConstIfNeq)
107
fixup = B(CC_EQ);
108
else
109
_assert_(false);
110
}
111
112
WriteConstExit(inst.constant);
113
SetJumpTarget(fixup);
114
break;
115
116
case IROp::ExitToConstIfGtZ:
117
lhs = regs_.MapGPR(inst.src1);
118
FlushAll();
119
CMP(lhs, 0);
120
fixup = B(CC_LE);
121
WriteConstExit(inst.constant);
122
SetJumpTarget(fixup);
123
break;
124
125
case IROp::ExitToConstIfGeZ:
126
// In other words, exit if sign bit is 0.
127
lhs = regs_.MapGPR(inst.src1);
128
FlushAll();
129
fixup = TBNZ(lhs, 31);
130
WriteConstExit(inst.constant);
131
SetJumpTarget(fixup);
132
break;
133
134
case IROp::ExitToConstIfLtZ:
135
// In other words, exit if sign bit is 1.
136
lhs = regs_.MapGPR(inst.src1);
137
FlushAll();
138
fixup = TBZ(lhs, 31);
139
WriteConstExit(inst.constant);
140
SetJumpTarget(fixup);
141
break;
142
143
case IROp::ExitToConstIfLeZ:
144
lhs = regs_.MapGPR(inst.src1);
145
FlushAll();
146
CMP(lhs, 0);
147
fixup = B(CC_GT);
148
WriteConstExit(inst.constant);
149
SetJumpTarget(fixup);
150
break;
151
152
case IROp::ExitToConstIfFpTrue:
153
case IROp::ExitToConstIfFpFalse:
154
// Note: not used.
155
DISABLE;
156
break;
157
158
default:
159
INVALIDOP;
160
break;
161
}
162
}
163
164
} // namespace MIPSComp
165
166
#endif
167
168