CPU/NewRec: Add speculative constants

This commit is contained in:
Stenzek
2023-10-21 22:12:00 +10:00
parent b3cbe5a7ee
commit 6592cafadc
12 changed files with 858 additions and 225 deletions

View File

@ -56,17 +56,18 @@ protected:
FLUSH_LOAD_DELAY_FROM_STATE = (1 << 9),
FLUSH_GTE_DONE_CYCLE = (1 << 10),
FLUSH_GTE_STALL_FROM_STATE = (1 << 11),
FLUSH_INVALIDATE_SPECULATIVE_CONSTANTS = (1 << 12),
FLUSH_FOR_C_CALL = (FLUSH_FREE_CALLER_SAVED_REGISTERS),
FLUSH_FOR_LOADSTORE = (FLUSH_FREE_CALLER_SAVED_REGISTERS | FLUSH_CYCLES),
FLUSH_FOR_BRANCH = (FLUSH_FLUSH_MIPS_REGISTERS),
FLUSH_FOR_EXCEPTION =
(FLUSH_CYCLES | FLUSH_GTE_DONE_CYCLE), // GTE cycles needed because it stalls when a GTE instruction is next.
FLUSH_FOR_INTERPRETER =
(FLUSH_FLUSH_MIPS_REGISTERS | FLUSH_INVALIDATE_MIPS_REGISTERS | FLUSH_FREE_CALLER_SAVED_REGISTERS | FLUSH_PC |
FLUSH_CYCLES | FLUSH_INSTRUCTION_BITS | FLUSH_LOAD_DELAY | FLUSH_GTE_DONE_CYCLE),
FLUSH_FOR_INTERPRETER = (FLUSH_FLUSH_MIPS_REGISTERS | FLUSH_INVALIDATE_MIPS_REGISTERS |
FLUSH_FREE_CALLER_SAVED_REGISTERS | FLUSH_PC | FLUSH_CYCLES | FLUSH_INSTRUCTION_BITS |
FLUSH_LOAD_DELAY | FLUSH_GTE_DONE_CYCLE | FLUSH_INVALIDATE_SPECULATIVE_CONSTANTS),
FLUSH_END_BLOCK = 0xFFFFFFFFu & ~(FLUSH_PC | FLUSH_CYCLES | FLUSH_GTE_DONE_CYCLE | FLUSH_INSTRUCTION_BITS |
FLUSH_GTE_STALL_FROM_STATE),
FLUSH_GTE_STALL_FROM_STATE | FLUSH_INVALIDATE_SPECULATIVE_CONSTANTS),
};
union CompileFlags
@ -267,10 +268,10 @@ protected:
void CompileTemplate(void (Compiler::*const_func)(CompileFlags), void (Compiler::*func)(CompileFlags),
const void* pgxp_cpu_func, u32 tflags);
void CompileLoadStoreTemplate(void (Compiler::*func)(CompileFlags, MemoryAccessSize, bool,
void CompileLoadStoreTemplate(void (Compiler::*func)(CompileFlags, MemoryAccessSize, bool, bool,
const std::optional<VirtualMemoryAddress>&),
MemoryAccessSize size, bool store, bool sign, u32 tflags);
void FlushForLoadStore(const std::optional<VirtualMemoryAddress>& address, bool store);
void FlushForLoadStore(const std::optional<VirtualMemoryAddress>& address, bool store, bool use_fastmem);
void CompileMoveRegTemplate(Reg dst, Reg src, bool pgxp_move);
virtual void GeneratePGXPCallWithMIPSRegs(const void* func, u32 arg1val, Reg arg2reg = Reg::count,
@ -357,17 +358,17 @@ protected:
virtual void Compile_xori(CompileFlags cf) = 0;
void Compile_lui();
virtual void Compile_lxx(CompileFlags cf, MemoryAccessSize size, bool sign,
virtual void Compile_lxx(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
const std::optional<VirtualMemoryAddress>& address) = 0;
virtual void Compile_lwx(CompileFlags cf, MemoryAccessSize size, bool sign,
virtual void Compile_lwx(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
const std::optional<VirtualMemoryAddress>& address) = 0; // lwl/lwr
virtual void Compile_lwc2(CompileFlags cf, MemoryAccessSize size, bool sign,
virtual void Compile_lwc2(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
const std::optional<VirtualMemoryAddress>& address) = 0;
virtual void Compile_sxx(CompileFlags cf, MemoryAccessSize size, bool sign,
virtual void Compile_sxx(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
const std::optional<VirtualMemoryAddress>& address) = 0;
virtual void Compile_swx(CompileFlags cf, MemoryAccessSize size, bool sign,
virtual void Compile_swx(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
const std::optional<VirtualMemoryAddress>& address) = 0; // swl/swr
virtual void Compile_swc2(CompileFlags cf, MemoryAccessSize size, bool sign,
virtual void Compile_swc2(CompileFlags cf, MemoryAccessSize size, bool sign, bool use_fastmem,
const std::optional<VirtualMemoryAddress>& address) = 0;
static u32* GetCop0RegPtr(Cop0Reg reg);
@ -454,6 +455,71 @@ protected:
std::array<HostStateBackup, 2> m_host_state_backup = {};
u32 m_host_state_backup_count = 0;
//////////////////////////////////////////////////////////////////////////
// Speculative Constants
//////////////////////////////////////////////////////////////////////////
using SpecValue = std::optional<u32>;
struct SpeculativeConstants
{
std::array<SpecValue, static_cast<u8>(Reg::count)> regs;
std::unordered_map<PhysicalMemoryAddress, SpecValue> memory;
SpecValue cop0_sr;
};
void InitSpeculativeRegs();
void InvalidateSpeculativeValues();
SpecValue SpecReadReg(Reg reg);
void SpecWriteReg(Reg reg, SpecValue value);
void SpecInvalidateReg(Reg reg);
void SpecCopyReg(Reg dst, Reg src);
SpecValue SpecReadMem(u32 address);
void SpecWriteMem(VirtualMemoryAddress address, SpecValue value);
void SpecInvalidateMem(VirtualMemoryAddress address);
bool SpecIsCacheIsolated();
SpeculativeConstants m_speculative_constants;
void SpecExec_b();
void SpecExec_jal();
void SpecExec_jalr();
void SpecExec_sll();
void SpecExec_srl();
void SpecExec_sra();
void SpecExec_sllv();
void SpecExec_srlv();
void SpecExec_srav();
void SpecExec_mult();
void SpecExec_multu();
void SpecExec_div();
void SpecExec_divu();
void SpecExec_add();
void SpecExec_addu();
void SpecExec_sub();
void SpecExec_subu();
void SpecExec_and();
void SpecExec_or();
void SpecExec_xor();
void SpecExec_nor();
void SpecExec_slt();
void SpecExec_sltu();
void SpecExec_addi();
void SpecExec_addiu();
void SpecExec_slti();
void SpecExec_sltiu();
void SpecExec_andi();
void SpecExec_ori();
void SpecExec_xori();
void SpecExec_lui();
SpecValue SpecExec_LoadStoreAddr();
void SpecExec_lxx(MemoryAccessSize size, bool sign);
void SpecExec_lwx(bool lwr); // lwl/lwr
void SpecExec_sxx(MemoryAccessSize size);
void SpecExec_swx(bool swr); // swl/swr
void SpecExec_swc2();
void SpecExec_mfc0();
void SpecExec_mtc0();
void SpecExec_rfe();
// PGXP memory callbacks
static const std::array<std::array<const void*, 2>, 3> s_pgxp_mem_load_functions;
static const std::array<const void*, 3> s_pgxp_mem_store_functions;