Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/core/cpu_recompiler_arm32.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_ARM32
11
12
#include "vixl/aarch32/assembler-aarch32.h"
13
#include "vixl/aarch32/operands-aarch32.h"
14
15
namespace CPU {
16
17
class ARM32Recompiler final : public Recompiler
18
{
19
public:
20
ARM32Recompiler();
21
~ARM32Recompiler() override;
22
23
protected:
24
const char* GetHostRegName(u32 reg) const override;
25
26
const void* GetCurrentCodePointer() override;
27
28
void LoadHostRegWithConstant(u32 reg, u32 val) override;
29
void LoadHostRegFromCPUPointer(u32 reg, const void* ptr) override;
30
void StoreConstantToCPUPointer(u32 val, const void* ptr) override;
31
void StoreHostRegToCPUPointer(u32 reg, const void* ptr) override;
32
void CopyHostReg(u32 dst, u32 src) override;
33
34
void Reset(CodeCache::Block* block, u8* code_buffer, u32 code_buffer_space, u8* far_code_buffer,
35
u32 far_code_space) override;
36
void BeginBlock() override;
37
void GenerateBlockProtectCheck(const u8* ram_ptr, const u8* shadow_ptr, u32 size) override;
38
void GenerateICacheCheckAndUpdate() override;
39
void GenerateCall(const void* func, s32 arg1reg = -1, s32 arg2reg = -1, s32 arg3reg = -1) override;
40
void EndBlock(const std::optional<u32>& newpc, bool do_event_test) override;
41
void EndBlockWithException(Exception excode) override;
42
void EndAndLinkBlock(const std::optional<u32>& newpc, bool do_event_test, bool force_run_events);
43
const void* EndCompile(u32* code_size, u32* far_code_size) override;
44
45
void Flush(u32 flags) override;
46
47
void Compile_Fallback() override;
48
49
void CheckBranchTarget(const vixl::aarch32::Register& pcreg);
50
void Compile_jr(CompileFlags cf) override;
51
void Compile_jalr(CompileFlags cf) override;
52
void Compile_bxx(CompileFlags cf, BranchCondition cond) override;
53
54
void Compile_addi(CompileFlags cf, bool overflow);
55
void Compile_addi(CompileFlags cf) override;
56
void Compile_addiu(CompileFlags cf) override;
57
void Compile_slti(CompileFlags cf, bool sign);
58
void Compile_slti(CompileFlags cf) override;
59
void Compile_sltiu(CompileFlags cf) override;
60
void Compile_andi(CompileFlags cf) override;
61
void Compile_ori(CompileFlags cf) override;
62
void Compile_xori(CompileFlags cf) override;
63
64
void Compile_shift(CompileFlags cf,
65
void (vixl::aarch32::Assembler::*op)(vixl::aarch32::Register, vixl::aarch32::Register,
66
const vixl::aarch32::Operand&));
67
void Compile_sll(CompileFlags cf) override;
68
void Compile_srl(CompileFlags cf) override;
69
void Compile_sra(CompileFlags cf) override;
70
void Compile_variable_shift(CompileFlags cf,
71
void (vixl::aarch32::Assembler::*op)(vixl::aarch32::Register, vixl::aarch32::Register,
72
const vixl::aarch32::Operand&));
73
void Compile_sllv(CompileFlags cf) override;
74
void Compile_srlv(CompileFlags cf) override;
75
void Compile_srav(CompileFlags cf) override;
76
void Compile_mult(CompileFlags cf, bool sign);
77
void Compile_mult(CompileFlags cf) override;
78
void Compile_multu(CompileFlags cf) override;
79
void Compile_div(CompileFlags cf) override;
80
void Compile_divu(CompileFlags cf) override;
81
void TestOverflow(const vixl::aarch32::Register& result);
82
void Compile_dst_op(CompileFlags cf,
83
void (vixl::aarch32::Assembler::*op)(vixl::aarch32::Register, vixl::aarch32::Register,
84
const vixl::aarch32::Operand&),
85
bool commutative, bool logical, bool overflow);
86
void Compile_add(CompileFlags cf) override;
87
void Compile_addu(CompileFlags cf) override;
88
void Compile_sub(CompileFlags cf) override;
89
void Compile_subu(CompileFlags cf) override;
90
void Compile_and(CompileFlags cf) override;
91
void Compile_or(CompileFlags cf) override;
92
void Compile_xor(CompileFlags cf) override;
93
void Compile_nor(CompileFlags cf) override;
94
void Compile_slt(CompileFlags cf, bool sign);
95
void Compile_slt(CompileFlags cf) override;
96
void Compile_sltu(CompileFlags cf) override;
97
98
vixl::aarch32::Register
99
ComputeLoadStoreAddressArg(CompileFlags cf, const std::optional<VirtualMemoryAddress>& address,
100
const std::optional<const vixl::aarch32::Register>& reg = std::nullopt);
101
template<typename RegAllocFn>
102
vixl::aarch32::Register GenerateLoad(const vixl::aarch32::Register& addr_reg, MemoryAccessSize size, bool sign,
103
bool use_fastmem, const RegAllocFn& dst_reg_alloc);
104
void GenerateStore(const vixl::aarch32::Register& addr_reg, const vixl::aarch32::Register& value_reg,
105
MemoryAccessSize size, bool use_fastmem);
106
void Compile_lxx(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
107
const std::optional<VirtualMemoryAddress>& address) override;
108
void Compile_lwx(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
109
const std::optional<VirtualMemoryAddress>& address) override;
110
void Compile_lwc2(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
111
const std::optional<VirtualMemoryAddress>& address) override;
112
void Compile_sxx(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
113
const std::optional<VirtualMemoryAddress>& address) override;
114
void Compile_swx(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
115
const std::optional<VirtualMemoryAddress>& address) override;
116
void Compile_swc2(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
117
const std::optional<VirtualMemoryAddress>& address) override;
118
119
void TestInterrupts(const vixl::aarch32::Register& sr);
120
void Compile_mtc0(CompileFlags cf) override;
121
void Compile_rfe(CompileFlags cf) override;
122
123
void Compile_mfc2(CompileFlags cf) override;
124
void Compile_mtc2(CompileFlags cf) override;
125
void Compile_cop2(CompileFlags cf) override;
126
127
void GeneratePGXPCallWithMIPSRegs(const void* func, u32 arg1val, Reg arg2reg = Reg::count,
128
Reg arg3reg = Reg::count) override;
129
130
private:
131
void EmitMov(const vixl::aarch32::Register& dst, u32 val);
132
void EmitCall(const void* ptr, bool force_inline = false);
133
134
vixl::aarch32::Operand armCheckAddSubConstant(s32 val);
135
vixl::aarch32::Operand armCheckAddSubConstant(u32 val);
136
vixl::aarch32::Operand armCheckCompareConstant(s32 val);
137
vixl::aarch32::Operand armCheckLogicalConstant(u32 val);
138
139
void SwitchToFarCode(bool emit_jump, vixl::aarch32::ConditionType cond = vixl::aarch32::ConditionType::al);
140
void SwitchToFarCodeIfBitSet(const vixl::aarch32::Register& reg, u32 bit);
141
void SwitchToFarCodeIfRegZeroOrNonZero(const vixl::aarch32::Register& reg, bool nonzero);
142
void SwitchToNearCode(bool emit_jump, vixl::aarch32::ConditionType cond = vixl::aarch32::ConditionType::al);
143
144
void AssertRegOrConstS(CompileFlags cf) const;
145
void AssertRegOrConstT(CompileFlags cf) const;
146
vixl::aarch32::MemOperand MipsPtr(Reg r) const;
147
vixl::aarch32::Register CFGetRegD(CompileFlags cf) const;
148
vixl::aarch32::Register CFGetRegS(CompileFlags cf) const;
149
vixl::aarch32::Register CFGetRegT(CompileFlags cf) const;
150
vixl::aarch32::Register CFGetRegLO(CompileFlags cf) const;
151
vixl::aarch32::Register CFGetRegHI(CompileFlags cf) const;
152
vixl::aarch32::Register GetMembaseReg();
153
154
void MoveSToReg(const vixl::aarch32::Register& dst, CompileFlags cf);
155
void MoveTToReg(const vixl::aarch32::Register& dst, CompileFlags cf);
156
void MoveMIPSRegToReg(const vixl::aarch32::Register& dst, Reg reg);
157
158
vixl::aarch32::Assembler m_emitter;
159
vixl::aarch32::Assembler m_far_emitter;
160
vixl::aarch32::Assembler* armAsm;
161
162
#ifdef VIXL_DEBUG
163
std::unique_ptr<vixl::CodeBufferCheckScope> m_emitter_check;
164
std::unique_ptr<vixl::CodeBufferCheckScope> m_far_emitter_check;
165
#endif
166
};
167
168
} // namespace CPU
169
170
#endif // CPU_ARCH_ARM32
171
172