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