mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 12:01:04 +00:00
Added instruction counting
This commit is contained in:
parent
3ae4d8b646
commit
70463da199
@ -28,6 +28,8 @@ void InstructionBlock::GenerateCode()
|
||||
auto ir_builder = Module()->IrBuilder();
|
||||
ir_builder->SetInsertPoint(entry_basic_block);
|
||||
|
||||
module->GenerateIncInstructionCount();
|
||||
|
||||
instruction->GenerateCode(this);
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,15 @@ void ModuleGen::Run()
|
||||
GenerateBlockAddressArray();
|
||||
}
|
||||
|
||||
void ModuleGen::GenerateIncInstructionCount()
|
||||
{
|
||||
auto load = ir_builder->CreateLoad(instruction_count);
|
||||
auto inc = ir_builder->CreateAdd(load, ir_builder->getInt32(1));
|
||||
auto store = ir_builder->CreateStore(inc, instruction_count);
|
||||
tbaa->TagInstructionCount(load);
|
||||
tbaa->TagInstructionCount(store);
|
||||
}
|
||||
|
||||
void ModuleGen::BranchReadPC()
|
||||
{
|
||||
if (verify)
|
||||
@ -111,6 +120,9 @@ void ModuleGen::GenerateGlobals()
|
||||
|
||||
// bool Verify - contains the value of verify for citra usage
|
||||
new GlobalVariable(*module, ir_builder->getInt1Ty(), true, GlobalValue::ExternalLinkage, ir_builder->getInt1(verify), "Verify");
|
||||
|
||||
instruction_count = new GlobalVariable(*Module(), ir_builder->getInt32Ty(), false, GlobalValue::ExternalLinkage,
|
||||
ir_builder->getInt32(0), "InstructionCount");
|
||||
}
|
||||
|
||||
void ModuleGen::GenerateBlockAddressArray()
|
||||
|
@ -27,6 +27,7 @@ public:
|
||||
|
||||
void Run();
|
||||
|
||||
void GenerateIncInstructionCount();
|
||||
// Generate code to read pc and run all following instructions, used in cases of indirect branch
|
||||
void BranchReadPC();
|
||||
// Generate code to write to pc and run all following instructions, used in cases of direct branch
|
||||
@ -80,6 +81,11 @@ private:
|
||||
*/
|
||||
llvm::ArrayType *block_address_array_type;
|
||||
llvm::GlobalVariable *block_address_array;
|
||||
/*
|
||||
* i32 InstructionCount;
|
||||
* The count of instructions executed
|
||||
*/
|
||||
llvm::GlobalVariable *instruction_count;
|
||||
/*
|
||||
* i8 *GetBlockAddress(u32 pc)
|
||||
* Returns the address of the block for the instruction at pc
|
||||
|
@ -20,6 +20,7 @@ void TBAA::GenerateTags()
|
||||
register_nodes[i] = md_builder.createTBAAScalarTypeNode(ss.str(), tbaa_root);
|
||||
}
|
||||
const_node = md_builder.createTBAAScalarTypeNode("Readonly", tbaa_root);
|
||||
instruction_count_node = md_builder.createTBAAScalarTypeNode("InstructionCount", tbaa_root);
|
||||
}
|
||||
|
||||
void TBAA::TagRegister(Instruction* instruction, Register reg)
|
||||
@ -31,3 +32,8 @@ void TBAA::TagConst(Instruction* instruction)
|
||||
{
|
||||
instruction->setMetadata(LLVMContext::MD_tbaa, const_node);
|
||||
}
|
||||
|
||||
void TBAA::TagInstructionCount(llvm::Instruction* instruction)
|
||||
{
|
||||
instruction->setMetadata(LLVMContext::MD_tbaa, instruction_count_node);
|
||||
}
|
@ -21,9 +21,11 @@ public:
|
||||
|
||||
void TagRegister(llvm::Instruction *instruction, Register reg);
|
||||
void TagConst(llvm::Instruction *instruction);
|
||||
void TagInstructionCount(llvm::Instruction *instruction);
|
||||
private:
|
||||
llvm::MDNode *register_nodes[RegisterCount];
|
||||
// Tag for everything that is never written.
|
||||
// Since it is never written, one tag works
|
||||
llvm::MDNode *const_node;
|
||||
llvm::MDNode *instruction_count_node;
|
||||
};
|
@ -3985,7 +3985,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
|
||||
|
||||
|
||||
#if ENABLE_BINARY_TRANSLATION
|
||||
BinaryTranslationLoader::Run();
|
||||
num_instrs = BinaryTranslationLoader::Run(num_instrs);
|
||||
#endif
|
||||
|
||||
if (cpu->TFlag)
|
||||
|
@ -19,6 +19,7 @@ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> g_loaded_object_info;
|
||||
|
||||
void(*g_run_function)();
|
||||
bool(*g_can_run_function)();
|
||||
uint32_t *g_instruction_count;
|
||||
|
||||
// Used by the verifier
|
||||
struct SavedState
|
||||
@ -117,7 +118,16 @@ void BinaryTranslationLoader::Load(FileUtil::IOFile& file)
|
||||
|
||||
g_run_function = static_cast<decltype(g_run_function)>(g_dyld->getSymbolAddress("Run"));
|
||||
g_can_run_function = static_cast<decltype(g_can_run_function)>(g_dyld->getSymbolAddress("CanRun"));
|
||||
g_verify = *static_cast<bool*>(g_dyld->getSymbolAddress("Verify"));
|
||||
auto verify_ptr = static_cast<bool*>(g_dyld->getSymbolAddress("Verify"));
|
||||
g_instruction_count = static_cast<uint32_t *>(g_dyld->getSymbolAddress("InstructionCount"));
|
||||
|
||||
if (!g_run_function || !g_can_run_function || !verify_ptr || !g_instruction_count)
|
||||
{
|
||||
LOG_WARNING(Loader, "Cannot load optimized file, missing critical function");
|
||||
return;
|
||||
}
|
||||
|
||||
g_verify = *verify_ptr;
|
||||
|
||||
g_enabled = true;
|
||||
}
|
||||
@ -145,18 +155,19 @@ bool BinaryTranslationLoader::CanRun(bool specific_address)
|
||||
return true;
|
||||
}
|
||||
|
||||
void BinaryTranslationLoader::Run()
|
||||
uint32_t BinaryTranslationLoader::Run(uint32_t instruction_count)
|
||||
{
|
||||
// No need to check the PC, Run does it anyway
|
||||
if (!CanRun(false)) return;
|
||||
if (!CanRun(false)) return instruction_count;
|
||||
// If verify is enabled, it will run opcodes
|
||||
if (g_verify) return;
|
||||
if (g_verify) return instruction_count;
|
||||
|
||||
RunInternal();
|
||||
return RunInternal(instruction_count);
|
||||
}
|
||||
|
||||
void BinaryTranslationLoader::RunInternal()
|
||||
uint32_t BinaryTranslationLoader::RunInternal(uint32_t instruction_count)
|
||||
{
|
||||
*g_instruction_count = instruction_count;
|
||||
g_run_function();
|
||||
|
||||
g_state->TFlag = g_state->Reg[15] & 1;
|
||||
@ -164,6 +175,8 @@ void BinaryTranslationLoader::RunInternal()
|
||||
g_state->Reg[15] &= 0xfffffffe;
|
||||
else
|
||||
g_state->Reg[15] &= 0xfffffffc;
|
||||
|
||||
return *g_instruction_count;
|
||||
}
|
||||
|
||||
void Swap(void *a, void *b, size_t size)
|
||||
@ -198,7 +211,7 @@ void BinaryTranslationLoader::VerifyCallback()
|
||||
g_state_copy.SwapWith(*g_state);
|
||||
|
||||
// Run the opcode
|
||||
RunInternal();
|
||||
RunInternal(0);
|
||||
|
||||
// Test
|
||||
auto current_as_saved_state = SavedState(*g_state);
|
||||
|
@ -13,8 +13,9 @@ public:
|
||||
// If specific_address, checks the specific PC too
|
||||
static bool CanRun(bool specific_address);
|
||||
// Runs the state provided at SetCpuState.
|
||||
static void Run();
|
||||
// Returns instruction_count + number of instructions executed
|
||||
static uint32_t Run(uint32_t instruction_count);
|
||||
// Link between Run and VerifyCallback
|
||||
static void RunInternal();
|
||||
static uint32_t RunInternal(uint32_t instruction_count);
|
||||
static void VerifyCallback();
|
||||
};
|
Loading…
Reference in New Issue
Block a user