Skip to content

Commit

Permalink
PowerPC: use CPP to generate static instruction information and decod…
Browse files Browse the repository at this point in the history
…ing tables
  • Loading branch information
CrystalGamma committed Sep 18, 2019
1 parent 82fd7f5 commit 650f603
Show file tree
Hide file tree
Showing 18 changed files with 1,097 additions and 743 deletions.
1 change: 0 additions & 1 deletion Source/Core/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,6 @@ add_library(core
PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp
PowerPC/Interpreter/Interpreter_Paired.cpp
PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
PowerPC/Interpreter/Interpreter_Tables.cpp
)

if(_M_X86)
Expand Down
22 changes: 22 additions & 0 deletions Source/Core/Core/PowerPC/Instructions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#pragma once

namespace IForm
{
enum
{
UNKNOWN,
#define ILLEGAL(name)
#define INST(name, type, flags, cycles) name,
#define TABLE(name, bits, shift, start, end)
#include "Core/PowerPC/Instructions.in.cpp"
#undef ILLEGAL
#undef INST
#undef TABLE
NUM_IFORMS
};
using IForm = u8;
} // namespace IForm
550 changes: 550 additions & 0 deletions Source/Core/Core/PowerPC/Instructions.in.cpp

Large diffs are not rendered by default.

61 changes: 16 additions & 45 deletions Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,16 @@ u32 last_pc;
bool Interpreter::m_end_block;

// function tables
std::array<Interpreter::Instruction, 64> Interpreter::m_op_table;
std::array<Interpreter::Instruction, 1024> Interpreter::m_op_table4;
std::array<Interpreter::Instruction, 1024> Interpreter::m_op_table19;
std::array<Interpreter::Instruction, 1024> Interpreter::m_op_table31;
std::array<Interpreter::Instruction, 32> Interpreter::m_op_table59;
std::array<Interpreter::Instruction, 1024> Interpreter::m_op_table63;
const std::array<Interpreter::Instruction, IForm::NUM_IFORMS> Interpreter::m_op_table = {{
Interpreter::unknown_instruction,
#define ILLEGAL(name)
#define INST(name, type, flags, cycles) Interpreter::name,
#define TABLE(name, bits, shift, start, end)
#include "Core/PowerPC/Instructions.in.cpp"
#undef ILLEGAL
#undef INST
#undef TABLE
}};

namespace
{
Expand Down Expand Up @@ -80,30 +84,8 @@ void UpdatePC()
}
} // Anonymous namespace

void Interpreter::RunTable4(UGeckoInstruction inst)
{
m_op_table4[inst.SUBOP10](inst);
}
void Interpreter::RunTable19(UGeckoInstruction inst)
{
m_op_table19[inst.SUBOP10](inst);
}
void Interpreter::RunTable31(UGeckoInstruction inst)
{
m_op_table31[inst.SUBOP10](inst);
}
void Interpreter::RunTable59(UGeckoInstruction inst)
{
m_op_table59[inst.SUBOP5](inst);
}
void Interpreter::RunTable63(UGeckoInstruction inst)
{
m_op_table63[inst.SUBOP10](inst);
}

void Interpreter::Init()
{
InitializeInstructionTables();
m_reserve = false;
m_end_block = false;
}
Expand Down Expand Up @@ -181,35 +163,24 @@ int Interpreter::SingleStepInner()

if (m_prev_inst.hex != 0)
{
IForm::IForm iform = PPCTables::DecodeIForm(m_prev_inst);
if (IsInvalidPairedSingleExecution(m_prev_inst))
{
GenerateProgramException();
CheckExceptions();
}
else if (MSR.FP)
else if (!MSR.FP && (PPCTables::GetIFormInfo(iform).flags & FL_USE_FPU))
{
m_op_table[m_prev_inst.OPCD](m_prev_inst);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
{
CheckExceptions();
}
PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
CheckExceptions();
}
else
{
// check if we have to generate a FPU unavailable exception or a program exception.
if (PPCTables::UsesFPU(m_prev_inst))
m_op_table[iform](m_prev_inst);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
{
PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
CheckExceptions();
}
else
{
m_op_table[m_prev_inst.OPCD](m_prev_inst);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
{
CheckExceptions();
}
}
}
}
else
Expand Down
10 changes: 2 additions & 8 deletions Source/Core/Core/PowerPC/Interpreter/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "Common/CommonTypes.h"
#include "Core/PowerPC/CPUCoreBase.h"
#include "Core/PowerPC/Gekko.h"
#include "Core/PowerPC/Instructions.h"

class Interpreter : public CPUCoreBase
{
Expand Down Expand Up @@ -263,12 +264,7 @@ class Interpreter : public CPUCoreBase
static void isync(UGeckoInstruction inst);

using Instruction = void (*)(UGeckoInstruction inst);
static std::array<Instruction, 64> m_op_table;
static std::array<Instruction, 1024> m_op_table4;
static std::array<Instruction, 1024> m_op_table19;
static std::array<Instruction, 1024> m_op_table31;
static std::array<Instruction, 32> m_op_table59;
static std::array<Instruction, 1024> m_op_table63;
static const std::array<Instruction, IForm::NUM_IFORMS> m_op_table;

// singleton
static Interpreter* getInstance();
Expand All @@ -284,8 +280,6 @@ class Interpreter : public CPUCoreBase
private:
void CheckExceptions();

static void InitializeInstructionTables();

static bool HandleFunctionHooking(u32 address);

// flag helper
Expand Down
496 changes: 0 additions & 496 deletions Source/Core/Core/PowerPC/Interpreter/Interpreter_Tables.cpp

This file was deleted.

14 changes: 4 additions & 10 deletions Source/Core/Core/PowerPC/Jit64/Jit64_Tables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,19 +362,13 @@ const GekkoOPTemplate table63_2[] = {

void Jit64::CompileInstruction(PPCAnalyst::CodeOp& op)
{
u32 iform = PPCTables::DecodeIForm(op.inst);
(this->*dynaOpTable[op.inst.OPCD])(op.inst);

GekkoOPInfo* info = op.opinfo;
if (info)
if (iform)
{
#ifdef OPLOG
if (!strcmp(info->opname, OP_TO_LOG)) // "mcrfs"
{
rsplocations.push_back(js.compilerPC);
}
#endif
info->compileCount++;
info->lastUse = js.compilerPC;
compile_counts[iform].compile_count++;
compile_counts[iform].last_use = js.compilerPC;
}
}

Expand Down
14 changes: 4 additions & 10 deletions Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,19 +370,13 @@ constexpr GekkoOPTemplate table63_2[] = {

void JitArm64::CompileInstruction(PPCAnalyst::CodeOp& op)
{
u32 iform = PPCTables::DecodeIForm(op.inst);
(this->*dynaOpTable[op.inst.OPCD])(op.inst);

GekkoOPInfo* info = op.opinfo;
if (info)
if (iform)
{
#ifdef OPLOG
if (!strcmp(info->opname, OP_TO_LOG))
{ ///"mcrfs"
rsplocations.push_back(js.compilerPC);
}
#endif
info->compileCount++;
info->lastUse = js.compilerPC;
compile_counts[iform].compile_count++;
compile_counts[iform].last_use = js.compilerPC;
}
}

Expand Down
10 changes: 9 additions & 1 deletion Source/Core/Core/PowerPC/JitCommon/JitBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#pragma once

#include <array>
#include <cstddef>
#include <map>
#include <unordered_set>
Expand All @@ -13,6 +14,7 @@
#include "Core/ConfigManager.h"
#include "Core/MachineContext.h"
#include "Core/PowerPC/CPUCoreBase.h"
#include "Core/PowerPC/Instructions.h"
#include "Core/PowerPC/JitCommon/JitAsmCommon.h"
#include "Core/PowerPC/JitCommon/JitCache.h"
#include "Core/PowerPC/PPCAnalyst.h"
Expand All @@ -23,7 +25,6 @@

// Use these to control the instruction selection
// #define INSTRUCTION_START FallBackToInterpreter(inst); return;
// #define INSTRUCTION_START PPCTables::CountInstruction(inst);
#define INSTRUCTION_START

#define FALLBACK_IF(cond) \
Expand Down Expand Up @@ -117,6 +118,13 @@ class JitBase : public CPUCoreBase

static constexpr std::size_t code_buffer_size = 32000;

struct CompileCount
{
u32 compile_count;
u32 last_use;
};
std::array<CompileCount, IForm::NUM_IFORMS> compile_counts = {};

// This should probably be removed from public:
JitOptions jo{};
JitState js{};
Expand Down
21 changes: 21 additions & 0 deletions Source/Core/Core/PowerPC/JitInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/File.h"
#include "Common/FileUtil.h"
#include "Common/MsgHandler.h"
#include "Common/StringUtil.h"

#include "Core/Core.h"
#include "Core/PowerPC/CPUCoreBase.h"
Expand Down Expand Up @@ -272,4 +274,23 @@ void Shutdown()
g_jit = nullptr;
}
}

void LogCompiledInstructions()
{
if (!g_jit)
return;
static unsigned int time = 0;

File::IOFile f(StringFromFormat("%sinst_log%i.txt", File::GetUserPath(D_LOGS_IDX).c_str(), time),
"w");
for (IForm::IForm iform = 0; iform < IForm::NUM_IFORMS; iform++)
{
const JitBase::CompileCount& count = g_jit->compile_counts[iform];
fprintf(f.GetHandle(), "%s\t%i\t%08x\n", PPCTables::GetIFormInfo(iform).opname,
count.compile_count, count.last_use);
}

++time;
}

} // namespace JitInterface
2 changes: 2 additions & 0 deletions Source/Core/Core/PowerPC/JitInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,6 @@ void CompileExceptionCheck(ExceptionType type);
void SetJit(JitBase* jit);

void Shutdown();

void LogCompiledInstructions();
} // namespace JitInterface
12 changes: 8 additions & 4 deletions Source/Core/Core/PowerPC/PPCAnalyst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,9 @@ static bool CanSwapAdjacentOps(const CodeOp& a, const CodeOp& b)
(PowerPC::breakpoints.IsAddressBreakPoint(a.address) ||
PowerPC::breakpoints.IsAddressBreakPoint(b.address)))
return false;
if (b_flags & (FL_SET_CRx | FL_ENDBLOCK | FL_TIMER | FL_EVIL | FL_SET_OE))
if (b_flags & (FL_SET_CRx | FL_ENDBLOCK | FL_TIMER | FL_EVIL))
return false;
if ((b_flags & FL_OE_BIT) && b.inst.OE)
return false;
if ((b_flags & (FL_RC_BIT | FL_RC_BIT_F)) && (b.inst.Rc))
return false;
Expand Down Expand Up @@ -439,8 +441,8 @@ static bool isCmp(const CodeOp& a)

static bool isCarryOp(const CodeOp& a)
{
return (a.opinfo->flags & FL_SET_CA) && !(a.opinfo->flags & FL_SET_OE) &&
a.opinfo->type == OpType::Integer;
return a.opinfo->type == OpType::Integer && (a.opinfo->flags & FL_SET_CA) &&
!((a.opinfo->flags & FL_OE_BIT) && a.inst.OE);
}

static bool isCror(const CodeOp& a)
Expand Down Expand Up @@ -771,8 +773,10 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, std:
num_inst++;

const UGeckoInstruction inst = result.hex;
GekkoOPInfo* opinfo = PPCTables::GetOpInfo(inst);
const IForm::IForm iform = PPCTables::DecodeIForm(inst);
const GekkoOPInfo* opinfo = &PPCTables::GetIFormInfo(iform);
code[i] = {};
code[i].iform = iform;
code[i].opinfo = opinfo;
code[i].address = address;
code[i].inst = inst;
Expand Down
3 changes: 2 additions & 1 deletion Source/Core/Core/PowerPC/PPCAnalyst.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ namespace PPCAnalyst
struct CodeOp // 16B
{
UGeckoInstruction inst;
GekkoOPInfo* opinfo;
IForm::IForm iform;
const GekkoOPInfo* opinfo;
u32 address;
u32 branchTo; // if UINT32_MAX, not a branch
BitSet32 regsOut;
Expand Down
Loading

0 comments on commit 650f603

Please sign in to comment.