duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

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