mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-05-22 22:27:01 -05:00
When the interpreter calls MSRUpdated, we should update the membase variable. Not because the interpreter itself needs it, but because the JIT needs it if it's falling back to the interpreter for an instruction that sets the MSR. Additionally, the JIT's FallBackToInterpreter needs to read back the new membase value afterwards. This fixes games crashing on JitArm64 if mtmsr is set to fall back to interpreter. I was unable to reproduce the issue on Jit64, presumably due to a fortunate series of coincidences (instructions that set MSR are always followed by an exception exit, and PowerPCManager::CheckExternalExceptions was always calling JitInterface::UpdateMembase, and Jit64::WriteExceptionExit was always calling Jit64::EmitUpdateMembase.)
126 lines
4.7 KiB
C++
126 lines
4.7 KiB
C++
// Copyright 2008 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#pragma once
|
|
|
|
#include "Common/CommonTypes.h"
|
|
#include "Core/PowerPC/Gekko.h"
|
|
|
|
// Flags that indicate what an instruction can do.
|
|
enum InstructionFlags : u64
|
|
{
|
|
FL_SET_CR0 = (1ull << 0), // Sets CR0.
|
|
FL_SET_CR1 = (1ull << 1), // Sets CR1.
|
|
FL_SET_CRn = (1ull << 2), // Sets a CR determined by the CRFD field.
|
|
FL_SET_CA = (1ull << 3), // Sets the carry flag.
|
|
FL_READ_CA = (1ull << 4), // Reads the carry flag.
|
|
FL_RC_BIT = (1ull << 5), // Sets the record bit.
|
|
FL_RC_BIT_F =
|
|
(1ull << 6), // Sets the record bit. Used for floating point instructions that do this.
|
|
FL_ENDBLOCK =
|
|
(1ull << 7), // Specifies that the instruction can be used as an exit point for a JIT block.
|
|
FL_IN_A = (1ull << 8), // Uses rA as an input.
|
|
FL_IN_A0 = (1ull << 9), // Uses rA as an input. Indicates that if rA is zero, the value zero is
|
|
// used, not the contents of r0.
|
|
FL_IN_B = (1ull << 10), // Uses rB as an input.
|
|
FL_IN_C = (1ull << 11), // Uses rC as an input.
|
|
FL_IN_S = (1ull << 12), // Uses rS as an input.
|
|
FL_IN_AB = FL_IN_A | FL_IN_B,
|
|
FL_IN_AC = FL_IN_A | FL_IN_C,
|
|
FL_IN_ABC = FL_IN_A | FL_IN_B | FL_IN_C,
|
|
FL_IN_SB = FL_IN_S | FL_IN_B,
|
|
FL_IN_A0B = FL_IN_A0 | FL_IN_B,
|
|
FL_IN_A0BC = FL_IN_A0 | FL_IN_B | FL_IN_C,
|
|
FL_OUT_D = (1ull << 13), // rD is used as a destination.
|
|
FL_OUT_A = (1ull << 14), // rA is used as a destination.
|
|
FL_OUT_AD = FL_OUT_A | FL_OUT_D,
|
|
FL_TIMER = (1ull << 15), // Used only for mftb.
|
|
FL_CHECKEXCEPTIONS = (1ull << 16), // Used with rfi/rfid.
|
|
FL_NO_REORDER = (1ull << 17), // Instruction should not be reordered by our optimizations.
|
|
FL_USE_FPU = (1ull << 18), // Used to indicate a floating point instruction.
|
|
FL_LOADSTORE = (1ull << 19), // Used to indicate a load/store instruction.
|
|
FL_SET_FPRF = (1ull << 20), // Sets bits in the FPRF.
|
|
FL_READ_FPRF = (1ull << 21), // Reads bits from the FPRF.
|
|
FL_SET_OE = (1ull << 22), // Sets the overflow flag.
|
|
FL_IN_FLOAT_A = (1ull << 23), // frA is used as an input.
|
|
FL_IN_FLOAT_B = (1ull << 24), // frB is used as an input.
|
|
FL_IN_FLOAT_C = (1ull << 25), // frC is used as an input.
|
|
FL_IN_FLOAT_S = (1ull << 26), // frS is used as an input.
|
|
FL_IN_FLOAT_D = (1ull << 27), // frD is used as an input.
|
|
FL_IN_FLOAT_AB = FL_IN_FLOAT_A | FL_IN_FLOAT_B,
|
|
FL_IN_FLOAT_AC = FL_IN_FLOAT_A | FL_IN_FLOAT_C,
|
|
FL_IN_FLOAT_ABC = FL_IN_FLOAT_A | FL_IN_FLOAT_B | FL_IN_FLOAT_C,
|
|
FL_OUT_FLOAT_D = (1ull << 28), // frD is used as a destination.
|
|
// Used in the case of double ops (they don't modify the top half of the output)
|
|
FL_INOUT_FLOAT_D = FL_IN_FLOAT_D | FL_OUT_FLOAT_D,
|
|
FL_IN_FLOAT_A_BITEXACT = (1ull << 29), // The output is based on the exact bits in frA.
|
|
FL_IN_FLOAT_B_BITEXACT = (1ull << 30), // The output is based on the exact bits in frB.
|
|
FL_IN_FLOAT_C_BITEXACT = (1ull << 31), // The output is based on the exact bits in frC.
|
|
FL_IN_FLOAT_AB_BITEXACT = FL_IN_FLOAT_A_BITEXACT | FL_IN_FLOAT_B_BITEXACT,
|
|
FL_IN_FLOAT_BC_BITEXACT = FL_IN_FLOAT_B_BITEXACT | FL_IN_FLOAT_C_BITEXACT,
|
|
FL_PROGRAMEXCEPTION = (1ull << 32), // May generate a program exception (not floating point).
|
|
FL_FLOAT_EXCEPTION = (1ull << 33), // May generate a program exception (floating point).
|
|
FL_FLOAT_DIV = (1ull << 34), // May generate a program exception (FP) due to division by 0.
|
|
FL_SET_ALL_CR = (1ull << 35), // Sets every CR.
|
|
FL_READ_CRn = (1ull << 36), // Reads a CR determined by the CRFS field.
|
|
FL_READ_CR_BI = (1ull << 37), // Reads a CR determined by the BI field.
|
|
FL_READ_ALL_CR = (1ull << 38), // Reads every CR.
|
|
FL_SET_CRx = FL_SET_CR0 | FL_SET_CR1 | FL_SET_CRn | FL_SET_ALL_CR,
|
|
FL_READ_CRx = FL_READ_CRn | FL_READ_CR_BI | FL_READ_ALL_CR,
|
|
FL_SET_MSR = (1ull << 39),
|
|
};
|
|
|
|
enum class OpType
|
|
{
|
|
Invalid,
|
|
Subtable,
|
|
Integer,
|
|
CR,
|
|
SPR,
|
|
System,
|
|
SystemFP,
|
|
Load,
|
|
Store,
|
|
LoadFP,
|
|
StoreFP,
|
|
DoubleFP,
|
|
SingleFP,
|
|
LoadPS,
|
|
StorePS,
|
|
PS,
|
|
DataCache,
|
|
InstructionCache,
|
|
Branch,
|
|
Unknown,
|
|
};
|
|
|
|
struct GekkoOPStats
|
|
{
|
|
u64 run_count;
|
|
u32 compile_count;
|
|
u32 last_use;
|
|
};
|
|
|
|
struct GekkoOPInfo
|
|
{
|
|
const char* opname;
|
|
OpType type;
|
|
u32 num_cycles;
|
|
u64 flags;
|
|
// Mutable
|
|
GekkoOPStats* stats;
|
|
};
|
|
|
|
namespace PPCTables
|
|
{
|
|
const GekkoOPInfo* GetOpInfo(UGeckoInstruction inst, u32 pc);
|
|
|
|
bool IsValidInstruction(UGeckoInstruction inst, u32 pc);
|
|
|
|
void CountInstruction(UGeckoInstruction inst, u32 pc);
|
|
void CountInstructionCompile(const GekkoOPInfo* info, u32 pc);
|
|
void PrintInstructionRunCounts();
|
|
void LogCompiledInstructions();
|
|
const char* GetInstructionName(UGeckoInstruction inst, u32 pc);
|
|
} // namespace PPCTables
|