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