testing
This commit is contained in:
parent
fc90d84788
commit
b18c61f4b2
|
@ -714,22 +714,11 @@ PageFaultHandler::HandlerResult PageFaultHandler::HandlePageFault(void* exceptio
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace CPU::CodeCache::CachedInterpreterFunctions {
|
||||
static void CompileOrRevalidateBlock(const CachedInterpreterInstruction* cinst);
|
||||
static void LookupAndExecuteBlock(const CachedInterpreterInstruction* cinst);
|
||||
static void LogCurrentState(const CachedInterpreterInstruction* cinst);
|
||||
static void CheckAndUpdateICacheTags(const CachedInterpreterInstruction* cinst);
|
||||
static void AddDynamicFetchTicks(const CachedInterpreterInstruction* cinst);
|
||||
static void AddUncachedFetchTicks(const CachedInterpreterInstruction* cinst);
|
||||
static void EndBlock(const CachedInterpreterInstruction* cinst);
|
||||
static DEFINE_CACHED_INTERPRETER_HANDLER(CompileOrRevalidateBlock);
|
||||
static DEFINE_CACHED_INTERPRETER_HANDLER(LookupAndExecuteBlock);
|
||||
} // namespace CPU::CodeCache::CachedInterpreterFunctions
|
||||
|
||||
void CPU::CodeCache::CachedInterpreterFunctions::CompileOrRevalidateBlock(const CachedInterpreterInstruction* cinst)
|
||||
{
|
||||
CompileCachedInterpreterBlock(g_state.pc);
|
||||
END_CACHED_INTERPRETER_INSTRUCTION(cinst);
|
||||
}
|
||||
|
||||
void CPU::CodeCache::CachedInterpreterFunctions::LookupAndExecuteBlock(const CachedInterpreterInstruction*)
|
||||
DEFINE_CACHED_INTERPRETER_HANDLER(CPU::CodeCache::CachedInterpreterFunctions::LookupAndExecuteBlock)
|
||||
{
|
||||
const u32 pc = g_state.pc;
|
||||
const u32 table = pc >> LUT_TABLE_SHIFT;
|
||||
|
@ -742,56 +731,13 @@ void CPU::CodeCache::CachedInterpreterFunctions::LookupAndExecuteBlock(const Cac
|
|||
#else
|
||||
do
|
||||
{
|
||||
cinst->handler(cinst);
|
||||
cinst++;
|
||||
} while (cinst->handler);
|
||||
cinst = cinst->handler(cinst);
|
||||
} while (cinst);
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CPU::CodeCache::CachedInterpreterFunctions::LogCurrentState(const CachedInterpreterInstruction* cinst)
|
||||
{
|
||||
CPU::CodeCache::LogCurrentState();
|
||||
END_CACHED_INTERPRETER_INSTRUCTION(cinst);
|
||||
}
|
||||
|
||||
void CPU::CodeCache::CachedInterpreterFunctions::CheckAndUpdateICacheTags(const CachedInterpreterInstruction* cinst)
|
||||
{
|
||||
CPU::CheckAndUpdateICacheTags(cinst->arg);
|
||||
END_CACHED_INTERPRETER_INSTRUCTION(cinst);
|
||||
}
|
||||
|
||||
void CPU::CodeCache::CachedInterpreterFunctions::AddDynamicFetchTicks(const CachedInterpreterInstruction* cinst)
|
||||
{
|
||||
AddPendingTicks(static_cast<TickCount>(
|
||||
cinst->arg *
|
||||
static_cast<u32>(*Bus::GetMemoryAccessTimePtr(g_state.pc & PHYSICAL_MEMORY_ADDRESS_MASK, MemoryAccessSize::Word))));
|
||||
END_CACHED_INTERPRETER_INSTRUCTION(cinst);
|
||||
}
|
||||
|
||||
void CPU::CodeCache::CachedInterpreterFunctions::AddUncachedFetchTicks(const CachedInterpreterInstruction* cinst)
|
||||
{
|
||||
CPU::AddPendingTicks(static_cast<TickCount>(cinst->arg));
|
||||
END_CACHED_INTERPRETER_INSTRUCTION(cinst);
|
||||
}
|
||||
|
||||
void CPU::CodeCache::CachedInterpreterFunctions::EndBlock(const CachedInterpreterInstruction* cinst)
|
||||
{
|
||||
// TODO: jump to top of block if looping, block linking, etc.
|
||||
return;
|
||||
}
|
||||
|
||||
void CPU::CodeCache::SetCachedInterpreterHandlers()
|
||||
{
|
||||
static constexpr const CachedInterpreterInstruction compile_or_revalidate_block[] = {
|
||||
{&CachedInterpreterFunctions::CompileOrRevalidateBlock, 0u},
|
||||
{&CachedInterpreterFunctions::LookupAndExecuteBlock, 0u},
|
||||
{nullptr, 0u},
|
||||
};
|
||||
|
||||
g_compile_or_revalidate_block = compile_or_revalidate_block;
|
||||
}
|
||||
|
||||
void CPU::CodeCache::CompileCachedInterpreterBlock(const u32)
|
||||
DEFINE_CACHED_INTERPRETER_HANDLER(CPU::CodeCache::CachedInterpreterFunctions::CompileOrRevalidateBlock)
|
||||
{
|
||||
const u32 start_pc = g_state.pc;
|
||||
MemMap::BeginCodeWrite();
|
||||
|
@ -806,13 +752,13 @@ void CPU::CodeCache::CompileCachedInterpreterBlock(const u32)
|
|||
{
|
||||
DebugAssert(block->host_code);
|
||||
SetCodeLUT(start_pc, block->host_code);
|
||||
// BacklinkBlocks(start_pc, block->host_code);
|
||||
BacklinkBlocks(start_pc, block->host_code);
|
||||
MemMap::EndCodeWrite();
|
||||
return;
|
||||
CACHED_INTERPRETER_HANDLER_RETURN(static_cast<const CachedInterpreterInstruction*>(block->host_code));
|
||||
}
|
||||
|
||||
// remove outward links from this block, since we're recompiling it
|
||||
// UnlinkBlockExits(block);
|
||||
UnlinkBlockExits(block);
|
||||
}
|
||||
|
||||
BlockMetadata metadata = {};
|
||||
|
@ -822,6 +768,7 @@ void CPU::CodeCache::CompileCachedInterpreterBlock(const u32)
|
|||
Panic("Fixme");
|
||||
}
|
||||
|
||||
// TODO: size calc is wrong, should use max insn size
|
||||
const u32 required_space = sizeof(CachedInterpreterInstruction) * (static_cast<u32>(s_block_instructions.size()) + 3);
|
||||
if (GetFreeCodeSpace() < required_space)
|
||||
{
|
||||
|
@ -833,67 +780,34 @@ void CPU::CodeCache::CompileCachedInterpreterBlock(const u32)
|
|||
if (!block)
|
||||
{
|
||||
Panic("Fixme");
|
||||
return;
|
||||
}
|
||||
|
||||
const CPU::Instruction* mips_insns = block->Instructions();
|
||||
CachedInterpreterInstruction* cstart = reinterpret_cast<CachedInterpreterInstruction*>(GetFreeCodePointer());
|
||||
CachedInterpreterInstruction* cinst = cstart;
|
||||
CachedInterpreterCompiler compiler(block, reinterpret_cast<CachedInterpreterInstruction*>(GetFreeCodePointer()));
|
||||
if (!compiler.CompileBlock())
|
||||
Panic("Fixme");
|
||||
|
||||
if (false)
|
||||
{
|
||||
cinst->handler = &CachedInterpreterFunctions::LogCurrentState;
|
||||
cinst->arg = 0;
|
||||
cinst++;
|
||||
}
|
||||
block->host_code = compiler.GetCodeStart();
|
||||
block->host_code_size = compiler.GetCodeSize();
|
||||
CommitCode(block->host_code_size);
|
||||
|
||||
if (block->HasFlag(BlockFlags::IsUsingICache))
|
||||
{
|
||||
cinst->handler = &CachedInterpreterFunctions::CheckAndUpdateICacheTags;
|
||||
cinst->arg = block->icache_line_count;
|
||||
cinst++;
|
||||
}
|
||||
else if (block->HasFlag(BlockFlags::NeedsDynamicFetchTicks))
|
||||
{
|
||||
cinst->handler = &CachedInterpreterFunctions::AddDynamicFetchTicks;
|
||||
cinst->arg = block->size;
|
||||
cinst++;
|
||||
}
|
||||
else if (block->uncached_fetch_ticks > 0)
|
||||
{
|
||||
cinst->handler = &CachedInterpreterFunctions::AddUncachedFetchTicks;
|
||||
cinst->arg = static_cast<u32>(block->uncached_fetch_ticks);
|
||||
cinst++;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < block->size; i++)
|
||||
{
|
||||
const Instruction insn = *(mips_insns++);
|
||||
cinst->handler = GetCachedInterpreterHandler(insn);
|
||||
cinst->arg = insn.bits;
|
||||
if (!cinst->handler)
|
||||
Panic("Fixme");
|
||||
|
||||
cinst++;
|
||||
}
|
||||
|
||||
// end
|
||||
#ifdef HAS_MUSTTAIL
|
||||
cinst->handler = &CachedInterpreterFunctions::EndBlock;
|
||||
#else
|
||||
cinst->handler = nullptr;
|
||||
#endif
|
||||
cinst->arg = 0;
|
||||
cinst++;
|
||||
|
||||
block->host_code = cstart;
|
||||
block->host_code_size = static_cast<u32>(cinst - cstart) * sizeof(CachedInterpreterInstruction);
|
||||
|
||||
SetCodeLUT(start_pc, cstart);
|
||||
CommitCode(required_space);
|
||||
SetCodeLUT(start_pc, block->host_code);
|
||||
BacklinkBlocks(start_pc, block->host_code);
|
||||
MemMap::EndCodeWrite();
|
||||
|
||||
// TODO: Block linking!
|
||||
|
||||
CACHED_INTERPRETER_HANDLER_RETURN(static_cast<const CachedInterpreterInstruction*>(block->host_code));
|
||||
}
|
||||
|
||||
void CPU::CodeCache::SetCachedInterpreterHandlers()
|
||||
{
|
||||
static constexpr const CachedInterpreterInstruction compile_or_revalidate_block_seq = {
|
||||
&CachedInterpreterFunctions::CompileOrRevalidateBlock};
|
||||
static constexpr const CachedInterpreterInstruction lookup_and_execute_block_seq = {
|
||||
&CachedInterpreterFunctions::LookupAndExecuteBlock};
|
||||
|
||||
g_compile_or_revalidate_block = &compile_or_revalidate_block_seq;
|
||||
g_dispatcher = &lookup_and_execute_block_seq;
|
||||
}
|
||||
|
||||
[[noreturn]] void CPU::CodeCache::ExecuteCachedInterpreter()
|
||||
|
@ -933,9 +847,8 @@ void CPU::CodeCache::CompileCachedInterpreterBlock(const u32)
|
|||
#else
|
||||
do
|
||||
{
|
||||
cinst->handler(cinst);
|
||||
cinst++;
|
||||
} while (cinst->handler);
|
||||
cinst = cinst->handler(cinst);
|
||||
} while (cinst);
|
||||
#endif
|
||||
|
||||
CHECK_DOWNCOUNT();
|
||||
|
@ -952,7 +865,7 @@ void CPU::CodeCache::CompileCachedInterpreterBlock(const u32)
|
|||
void CPU::CodeCache::LogCurrentState()
|
||||
{
|
||||
#if 0
|
||||
if (System::GetGlobalTickCounter() == 2546728915)
|
||||
if (System::GetGlobalTickCounter() == 9953322268)
|
||||
__debugbreak();
|
||||
#endif
|
||||
#if 0
|
||||
|
@ -1542,11 +1455,25 @@ void CPU::CodeCache::BacklinkBlocks(u32 pc, const void* dst)
|
|||
return;
|
||||
|
||||
const auto link_range = s_block_links.equal_range(pc);
|
||||
for (auto it = link_range.first; it != link_range.second; ++it)
|
||||
if (IsUsingRecompiler())
|
||||
{
|
||||
DEBUG_LOG("Backlinking {} with dst pc {:08X} to {}{}", it->second, pc, dst,
|
||||
(dst == g_compile_or_revalidate_block) ? "[compiler]" : "");
|
||||
EmitJump(it->second, dst, true);
|
||||
for (auto it = link_range.first; it != link_range.second; ++it)
|
||||
{
|
||||
DEBUG_LOG("Backlinking {} with dst pc {:08X} to {}{}", it->second, pc, dst,
|
||||
(dst == g_compile_or_revalidate_block) ? "[compiler]" : "");
|
||||
EmitJump(it->second, dst, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: maybe move this up to the compiler function
|
||||
for (auto it = link_range.first; it != link_range.second; ++it)
|
||||
{
|
||||
DEBUG_LOG("Backlinking {} with dst pc {:08X} to {}{}", it->second, pc, dst,
|
||||
(dst == g_compile_or_revalidate_block) ? "[compiler]" : "");
|
||||
|
||||
std::memcpy(it->second, &dst, sizeof(void*));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -212,21 +212,108 @@ static_assert(sizeof(PageProtectionInfo) == (sizeof(Block*) * 2 + 8));
|
|||
|
||||
struct CachedInterpreterInstruction;
|
||||
|
||||
using CachedInterpreterHandler = void (*)(const CachedInterpreterInstruction*);
|
||||
CachedInterpreterHandler GetCachedInterpreterHandler(const Instruction inst);
|
||||
|
||||
#ifdef HAS_MUSTTAIL
|
||||
#define END_CACHED_INTERPRETER_INSTRUCTION(arg) RETURN_MUSTTAIL((arg + 1)->handler(arg + 1));
|
||||
using CachedInterpreterHandler = void (*)(const CachedInterpreterInstruction*);
|
||||
|
||||
#define DEFINE_CACHED_INTERPRETER_HANDLER(name) void name(const CPU::CodeCache::CachedInterpreterInstruction* cbaseinst)
|
||||
#define CACHED_INTERPRETER_INSTRUCTION_TYPE(type) const type* cinst = static_cast<const type*>(cbaseinst)
|
||||
#define CACHED_INTERPRETER_HANDLER_RETURN(value) RETURN_MUSTTAIL(value->handler(value))
|
||||
#define END_CACHED_INTERPRETER_INSTRUCTION() CACHED_INTERPRETER_HANDLER_RETURN((cinst + 1))
|
||||
#else
|
||||
#define END_CACHED_INTERPRETER_INSTRUCTION(arg)
|
||||
using CachedInterpreterHandler = const CachedInterpreterInstruction* (*)(const CachedInterpreterInstruction*);
|
||||
|
||||
#define DEFINE_CACHED_INTERPRETER_HANDLER(name) \
|
||||
const CPU::CodeCache::CachedInterpreterInstruction* name( \
|
||||
const CPU::CodeCache::CachedInterpreterInstruction* cbaseinst)
|
||||
#define CACHED_INTERPRETER_INSTRUCTION_TYPE(type) const type* cinst = static_cast<const type*>(cbaseinst)
|
||||
#define CACHED_INTERPRETER_HANDLER_RETURN(value) return value
|
||||
#define END_CACHED_INTERPRETER_INSTRUCTION() CACHED_INTERPRETER_HANDLER_RETURN((cinst + 1))
|
||||
#endif
|
||||
|
||||
struct CachedInterpreterInstruction
|
||||
{
|
||||
CachedInterpreterHandler handler;
|
||||
};
|
||||
static_assert(sizeof(CachedInterpreterInstruction) == sizeof(CachedInterpreterHandler));
|
||||
|
||||
struct CachedInterpreterIntArgInstruction : CachedInterpreterInstruction
|
||||
{
|
||||
u32 arg;
|
||||
};
|
||||
|
||||
struct CachedInterpreterMIPSInstruction : CachedInterpreterInstruction
|
||||
{
|
||||
Instruction inst;
|
||||
u32 pc;
|
||||
};
|
||||
|
||||
struct CachedInterpreterBlockLinkInstruction : CachedInterpreterInstruction
|
||||
{
|
||||
const CachedInterpreterInstruction* target;
|
||||
u32 target_pc;
|
||||
};
|
||||
|
||||
struct CachedInterpreterConditionalBranchInstruction : CachedInterpreterMIPSInstruction
|
||||
{
|
||||
const CachedInterpreterInstruction* not_taken_target;
|
||||
};
|
||||
|
||||
class CachedInterpreterCompiler
|
||||
{
|
||||
public:
|
||||
CachedInterpreterCompiler(Block* block, CachedInterpreterInstruction* cinst);
|
||||
|
||||
CachedInterpreterInstruction* GetCodeStart() const { return m_code_start; }
|
||||
u32 GetCodeSize() const
|
||||
{
|
||||
return static_cast<u32>(reinterpret_cast<u8*>(m_code_ptr) - reinterpret_cast<u8*>(m_code_start));
|
||||
}
|
||||
|
||||
bool CompileBlock();
|
||||
|
||||
private:
|
||||
bool CompileInstruction();
|
||||
bool CompileBranchDelaySlot();
|
||||
bool CompileUnconditionalBranch();
|
||||
bool CompileConditionalBranch();
|
||||
bool CompileIndirectBranch();
|
||||
|
||||
void BackupState();
|
||||
void RestoreState();
|
||||
|
||||
void AddBlockLinkInstruction(u32 target_pc);
|
||||
|
||||
template<typename T>
|
||||
T* AddInstruction()
|
||||
{
|
||||
T* ret = static_cast<T*>(m_code_ptr);
|
||||
m_code_ptr = (ret + 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Block* m_block = nullptr;
|
||||
CachedInterpreterInstruction* m_code_start = nullptr;
|
||||
CachedInterpreterInstruction* m_code_ptr = nullptr;
|
||||
|
||||
const Instruction* inst = nullptr;
|
||||
const InstructionInfo* iinfo = nullptr;
|
||||
u32 m_compiler_pc = 0;
|
||||
u32 m_current_instruction_pc = 0;
|
||||
bool m_block_ended = false;
|
||||
bool m_has_load_delay = false;
|
||||
|
||||
struct StateBackup
|
||||
{
|
||||
const Instruction* inst;
|
||||
const InstructionInfo* iinfo;
|
||||
u32 compiler_pc;
|
||||
u32 current_instruction_pc;
|
||||
bool block_ended;
|
||||
bool has_load_delay;
|
||||
};
|
||||
StateBackup m_state_backup = {};
|
||||
};
|
||||
|
||||
template<PGXPMode pgxp_mode>
|
||||
void InterpretUncachedBlock();
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -168,77 +168,79 @@ void UncheckedWriteMemoryWord(u32 address, u32 value);
|
|||
|
||||
#endif
|
||||
|
||||
#define CPU_FOR_EACH_INSTRUCTION(X) \
|
||||
X(b) \
|
||||
X(j) \
|
||||
X(jal) \
|
||||
X(beq) \
|
||||
X(bne) \
|
||||
X(blez) \
|
||||
X(bgtz) \
|
||||
X(addi) \
|
||||
X(addiu) \
|
||||
X(slti) \
|
||||
X(sltiu) \
|
||||
X(andi) \
|
||||
X(ori) \
|
||||
X(xori) \
|
||||
X(lui) \
|
||||
X(lb) \
|
||||
X(lh) \
|
||||
X(lwl) \
|
||||
X(lw) \
|
||||
X(lbu) \
|
||||
X(lhu) \
|
||||
X(lwr) \
|
||||
X(sb) \
|
||||
X(sh) \
|
||||
X(swl) \
|
||||
X(sw) \
|
||||
X(swr) \
|
||||
X(mfc0) \
|
||||
X(mtc0) \
|
||||
X(rfe) \
|
||||
X(mfc2) \
|
||||
X(mtc2) \
|
||||
X(cfc2) \
|
||||
X(ctc2) \
|
||||
X(cop2) \
|
||||
X(lwc0) \
|
||||
X(lwc1) \
|
||||
X(lwc2) \
|
||||
X(lwc3) \
|
||||
X(swc0) \
|
||||
X(swc1) \
|
||||
X(swc2) \
|
||||
X(swc3) \
|
||||
X(sll) \
|
||||
X(srl) \
|
||||
X(sra) \
|
||||
X(sllv) \
|
||||
X(srlv) \
|
||||
X(srav) \
|
||||
X(jr) \
|
||||
X(jalr) \
|
||||
X(syscall) \
|
||||
X(break) \
|
||||
X(mfhi) \
|
||||
X(mthi) \
|
||||
X(mflo) \
|
||||
X(mtlo) \
|
||||
X(mult) \
|
||||
X(multu) \
|
||||
X(div) \
|
||||
X(divu) \
|
||||
X(add) \
|
||||
X(addu) \
|
||||
X(sub) \
|
||||
X(subu) \
|
||||
X(and) \
|
||||
X(or) \
|
||||
X(xor) \
|
||||
X(nor) \
|
||||
X(slt) \
|
||||
// clang-format off
|
||||
#define CPU_FOR_EACH_INSTRUCTION(X, eX) \
|
||||
X(b) \
|
||||
X(j) \
|
||||
X(jal) \
|
||||
X(beq) \
|
||||
X(bne) \
|
||||
X(blez) \
|
||||
X(bgtz) \
|
||||
eX(addi) \
|
||||
X(addiu) \
|
||||
X(slti) \
|
||||
X(sltiu) \
|
||||
X(andi) \
|
||||
X(ori) \
|
||||
X(xori) \
|
||||
X(lui) \
|
||||
eX(lb) \
|
||||
eX(lh) \
|
||||
eX(lwl) \
|
||||
eX(lw) \
|
||||
eX(lbu) \
|
||||
eX(lhu) \
|
||||
eX(lwr) \
|
||||
eX(sb) \
|
||||
eX(sh) \
|
||||
eX(swl) \
|
||||
eX(sw) \
|
||||
eX(swr) \
|
||||
eX(mfc0) \
|
||||
eX(mtc0) \
|
||||
X(rfe) \
|
||||
X(mfc2) \
|
||||
X(mtc2) \
|
||||
X(cfc2) \
|
||||
X(ctc2) \
|
||||
X(cop2) \
|
||||
eX(lwc0) \
|
||||
eX(lwc1) \
|
||||
eX(lwc2) \
|
||||
eX(lwc3) \
|
||||
eX(swc0) \
|
||||
eX(swc1) \
|
||||
eX(swc2) \
|
||||
eX(swc3) \
|
||||
X(sll) \
|
||||
X(srl) \
|
||||
X(sra) \
|
||||
X(sllv) \
|
||||
X(srlv) \
|
||||
X(srav) \
|
||||
X(jr) \
|
||||
X(jalr) \
|
||||
X(syscall) \
|
||||
X(break)\
|
||||
X(mfhi) \
|
||||
X(mthi) \
|
||||
X(mflo) \
|
||||
X(mtlo) \
|
||||
X(mult) \
|
||||
X(multu) \
|
||||
X(div) \
|
||||
X(divu) \
|
||||
eX(add) \
|
||||
X(addu) \
|
||||
eX(sub) \
|
||||
X(subu) \
|
||||
X(and) \
|
||||
X(or) \
|
||||
X(xor) \
|
||||
X(nor) \
|
||||
X(slt) \
|
||||
X(sltu)
|
||||
// clang-format on
|
||||
|
||||
} // namespace CPU
|
Loading…
Reference in New Issue