Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/core/cpu_recompiler_loongarch64.h
10595 views
1
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]> and contributors.
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#pragma once
5
6
#include "cpu_recompiler.h"
7
8
#ifdef CPU_ARCH_LOONGARCH64
9
10
extern "C" {
11
#include "lagoon.h"
12
}
13
14
namespace CPU {
15
16
// Function pointer types for lagoon operations
17
using LaRRROp = void (*)(lagoon_assembler_t*, la_gpr_t, la_gpr_t, la_gpr_t);
18
using LaRROp = void (*)(lagoon_assembler_t*, la_gpr_t, la_gpr_t);
19
using LaRRSImmOp = void (*)(lagoon_assembler_t*, la_gpr_t, la_gpr_t, int32_t);
20
using LaRRUImmOp = void (*)(lagoon_assembler_t*, la_gpr_t, la_gpr_t, uint32_t);
21
22
// Branch condition enum for SwitchToFarCode
23
enum class LaBranchCondition
24
{
25
None,
26
EQ,
27
NE,
28
LT,
29
GE,
30
LTU,
31
GEU
32
};
33
34
class LoongArch64Recompiler final : public Recompiler
35
{
36
public:
37
LoongArch64Recompiler();
38
~LoongArch64Recompiler() override;
39
40
protected:
41
const char* GetHostRegName(u32 reg) const override;
42
43
const void* GetCurrentCodePointer() override;
44
45
void LoadHostRegWithConstant(u32 reg, u32 val) override;
46
void LoadHostRegFromCPUPointer(u32 reg, const void* ptr) override;
47
void StoreConstantToCPUPointer(u32 val, const void* ptr) override;
48
void StoreHostRegToCPUPointer(u32 reg, const void* ptr) override;
49
void CopyHostReg(u32 dst, u32 src) override;
50
51
void Reset(CodeCache::Block* block, u8* code_buffer, u32 code_buffer_space, u8* far_code_buffer,
52
u32 far_code_space) override;
53
void GenerateBlockProtectCheck(const u8* ram_ptr, const u8* shadow_ptr, u32 size) override;
54
void GenerateICacheCheckAndUpdate() override;
55
void GenerateCall(const void* func, s32 arg1reg = -1, s32 arg2reg = -1, s32 arg3reg = -1) override;
56
void EndBlock(const std::optional<u32>& newpc, bool do_event_test) override;
57
void EndBlockWithException(Exception excode) override;
58
void EndAndLinkBlock(const std::optional<u32>& newpc, bool do_event_test, bool force_run_events);
59
const void* EndCompile(u32* code_size, u32* far_code_size) override;
60
61
void Flush(u32 flags) override;
62
63
void Compile_Fallback() override;
64
65
void CheckBranchTarget(la_gpr_t pcreg);
66
void Compile_jr(CompileFlags cf) override;
67
void Compile_jalr(CompileFlags cf) override;
68
void Compile_bxx(CompileFlags cf, BranchCondition cond) override;
69
70
void Compile_addi(CompileFlags cf, bool overflow);
71
void Compile_addi(CompileFlags cf) override;
72
void Compile_addiu(CompileFlags cf) override;
73
void Compile_slti(CompileFlags cf, bool sign);
74
void Compile_slti(CompileFlags cf) override;
75
void Compile_sltiu(CompileFlags cf) override;
76
void Compile_andi(CompileFlags cf) override;
77
void Compile_ori(CompileFlags cf) override;
78
void Compile_xori(CompileFlags cf) override;
79
80
void Compile_shift(CompileFlags cf, LaRRROp op, LaRRUImmOp op_const);
81
void Compile_sll(CompileFlags cf) override;
82
void Compile_srl(CompileFlags cf) override;
83
void Compile_sra(CompileFlags cf) override;
84
void Compile_variable_shift(CompileFlags cf, LaRRROp op, LaRRUImmOp op_const);
85
void Compile_sllv(CompileFlags cf) override;
86
void Compile_srlv(CompileFlags cf) override;
87
void Compile_srav(CompileFlags cf) override;
88
void Compile_mult(CompileFlags cf, bool sign);
89
void Compile_mult(CompileFlags cf) override;
90
void Compile_multu(CompileFlags cf) override;
91
void Compile_div(CompileFlags cf) override;
92
void Compile_divu(CompileFlags cf) override;
93
void TestOverflow(la_gpr_t long_res, la_gpr_t res, la_gpr_t reg_to_discard);
94
void Compile_dst_op(CompileFlags cf, LaRRROp op,
95
void (LoongArch64Recompiler::*op_const)(la_gpr_t rd, la_gpr_t rs, u32 imm), LaRRROp op_long,
96
bool commutative, bool overflow);
97
void Compile_add(CompileFlags cf) override;
98
void Compile_addu(CompileFlags cf) override;
99
void Compile_sub(CompileFlags cf) override;
100
void Compile_subu(CompileFlags cf) override;
101
void Compile_and(CompileFlags cf) override;
102
void Compile_or(CompileFlags cf) override;
103
void Compile_xor(CompileFlags cf) override;
104
void Compile_nor(CompileFlags cf) override;
105
void Compile_slt(CompileFlags cf, bool sign);
106
void Compile_slt(CompileFlags cf) override;
107
void Compile_sltu(CompileFlags cf) override;
108
109
la_gpr_t ComputeLoadStoreAddressArg(CompileFlags cf, const std::optional<VirtualMemoryAddress>& address,
110
const std::optional<la_gpr_t>& reg = std::nullopt);
111
template<typename RegAllocFn>
112
la_gpr_t GenerateLoad(la_gpr_t addr_reg, MemoryAccessSize size, bool sign, bool use_fastmem,
113
const RegAllocFn& dst_reg_alloc);
114
void GenerateStore(la_gpr_t addr_reg, la_gpr_t value_reg, MemoryAccessSize size, bool use_fastmem);
115
void Compile_lxx(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
116
const std::optional<VirtualMemoryAddress>& address) override;
117
void Compile_lwx(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
118
const std::optional<VirtualMemoryAddress>& address) override;
119
void Compile_lwc2(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
120
const std::optional<VirtualMemoryAddress>& address) override;
121
void Compile_sxx(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
122
const std::optional<VirtualMemoryAddress>& address) override;
123
void Compile_swx(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
124
const std::optional<VirtualMemoryAddress>& address) override;
125
void Compile_swc2(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
126
const std::optional<VirtualMemoryAddress>& address) override;
127
128
void TestInterrupts(la_gpr_t sr);
129
void Compile_mtc0(CompileFlags cf) override;
130
void Compile_rfe(CompileFlags cf) override;
131
132
void Compile_mfc2(CompileFlags cf) override;
133
void Compile_mtc2(CompileFlags cf) override;
134
void Compile_cop2(CompileFlags cf) override;
135
136
void GeneratePGXPCallWithMIPSRegs(const void* func, u32 arg1val, Reg arg2reg = Reg::count,
137
Reg arg3reg = Reg::count) override;
138
139
private:
140
void EmitMov(la_gpr_t dst, u32 val);
141
void EmitCall(const void* ptr);
142
143
void SwitchToFarCode(bool emit_jump, LaBranchCondition cond = LaBranchCondition::None, la_gpr_t rs1 = LA_ZERO,
144
la_gpr_t rs2 = LA_ZERO);
145
void SwitchToNearCode(bool emit_jump);
146
147
void AssertRegOrConstS(CompileFlags cf) const;
148
void AssertRegOrConstT(CompileFlags cf) const;
149
150
void SafeImmSImm12(la_gpr_t rd, la_gpr_t rs, u32 imm, LaRRSImmOp iop, LaRRROp rop);
151
void SafeImmUImm12(la_gpr_t rd, la_gpr_t rs, u32 imm, LaRRUImmOp iop, LaRRROp rop);
152
153
void SafeADDI(la_gpr_t rd, la_gpr_t rs, u32 imm);
154
void SafeADDIW(la_gpr_t rd, la_gpr_t rs, u32 imm);
155
void SafeSUBIW(la_gpr_t rd, la_gpr_t rs, u32 imm);
156
void SafeANDI(la_gpr_t rd, la_gpr_t rs, u32 imm);
157
void SafeORI(la_gpr_t rd, la_gpr_t rs, u32 imm);
158
void SafeXORI(la_gpr_t rd, la_gpr_t rs, u32 imm);
159
void SafeSLTI(la_gpr_t rd, la_gpr_t rs, u32 imm);
160
void SafeSLTIU(la_gpr_t rd, la_gpr_t rs, u32 imm);
161
162
void EmitSExtB(la_gpr_t rd, la_gpr_t rs);
163
void EmitUExtB(la_gpr_t rd, la_gpr_t rs);
164
void EmitSExtH(la_gpr_t rd, la_gpr_t rs);
165
void EmitUExtH(la_gpr_t rd, la_gpr_t rs);
166
void EmitDSExtW(la_gpr_t rd, la_gpr_t rs);
167
void EmitDUExtW(la_gpr_t rd, la_gpr_t rs);
168
169
la_gpr_t CFGetSafeRegS(CompileFlags cf, la_gpr_t temp_reg);
170
la_gpr_t CFGetSafeRegT(CompileFlags cf, la_gpr_t temp_reg);
171
172
la_gpr_t CFGetRegD(CompileFlags cf) const;
173
la_gpr_t CFGetRegS(CompileFlags cf) const;
174
la_gpr_t CFGetRegT(CompileFlags cf) const;
175
la_gpr_t CFGetRegLO(CompileFlags cf) const;
176
la_gpr_t CFGetRegHI(CompileFlags cf) const;
177
178
void MoveSToReg(la_gpr_t dst, CompileFlags cf);
179
void MoveTToReg(la_gpr_t dst, CompileFlags cf);
180
void MoveMIPSRegToReg(la_gpr_t dst, Reg reg, bool ignore_load_delays = false);
181
182
lagoon_assembler_t m_emitter;
183
lagoon_assembler_t m_far_emitter;
184
lagoon_assembler_t* laAsm;
185
};
186
187
} // namespace CPU
188
189
#endif // CPU_ARCH_LOONGARCH64
190