mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 13:31:06 +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();
|
auto ir_builder = Module()->IrBuilder();
|
||||||
ir_builder->SetInsertPoint(entry_basic_block);
|
ir_builder->SetInsertPoint(entry_basic_block);
|
||||||
|
|
||||||
|
module->GenerateIncInstructionCount();
|
||||||
|
|
||||||
instruction->GenerateCode(this);
|
instruction->GenerateCode(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,15 @@ void ModuleGen::Run()
|
|||||||
GenerateBlockAddressArray();
|
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()
|
void ModuleGen::BranchReadPC()
|
||||||
{
|
{
|
||||||
if (verify)
|
if (verify)
|
||||||
@ -111,6 +120,9 @@ void ModuleGen::GenerateGlobals()
|
|||||||
|
|
||||||
// bool Verify - contains the value of verify for citra usage
|
// bool Verify - contains the value of verify for citra usage
|
||||||
new GlobalVariable(*module, ir_builder->getInt1Ty(), true, GlobalValue::ExternalLinkage, ir_builder->getInt1(verify), "Verify");
|
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()
|
void ModuleGen::GenerateBlockAddressArray()
|
||||||
|
@ -27,6 +27,7 @@ public:
|
|||||||
|
|
||||||
void Run();
|
void Run();
|
||||||
|
|
||||||
|
void GenerateIncInstructionCount();
|
||||||
// Generate code to read pc and run all following instructions, used in cases of indirect branch
|
// Generate code to read pc and run all following instructions, used in cases of indirect branch
|
||||||
void BranchReadPC();
|
void BranchReadPC();
|
||||||
// Generate code to write to pc and run all following instructions, used in cases of direct branch
|
// 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::ArrayType *block_address_array_type;
|
||||||
llvm::GlobalVariable *block_address_array;
|
llvm::GlobalVariable *block_address_array;
|
||||||
|
/*
|
||||||
|
* i32 InstructionCount;
|
||||||
|
* The count of instructions executed
|
||||||
|
*/
|
||||||
|
llvm::GlobalVariable *instruction_count;
|
||||||
/*
|
/*
|
||||||
* i8 *GetBlockAddress(u32 pc)
|
* i8 *GetBlockAddress(u32 pc)
|
||||||
* Returns the address of the block for the instruction at 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);
|
register_nodes[i] = md_builder.createTBAAScalarTypeNode(ss.str(), tbaa_root);
|
||||||
}
|
}
|
||||||
const_node = md_builder.createTBAAScalarTypeNode("Readonly", 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)
|
void TBAA::TagRegister(Instruction* instruction, Register reg)
|
||||||
@ -31,3 +32,8 @@ void TBAA::TagConst(Instruction* instruction)
|
|||||||
{
|
{
|
||||||
instruction->setMetadata(LLVMContext::MD_tbaa, const_node);
|
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 TagRegister(llvm::Instruction *instruction, Register reg);
|
||||||
void TagConst(llvm::Instruction *instruction);
|
void TagConst(llvm::Instruction *instruction);
|
||||||
|
void TagInstructionCount(llvm::Instruction *instruction);
|
||||||
private:
|
private:
|
||||||
llvm::MDNode *register_nodes[RegisterCount];
|
llvm::MDNode *register_nodes[RegisterCount];
|
||||||
// Tag for everything that is never written.
|
// Tag for everything that is never written.
|
||||||
// Since it is never written, one tag works
|
// Since it is never written, one tag works
|
||||||
llvm::MDNode *const_node;
|
llvm::MDNode *const_node;
|
||||||
|
llvm::MDNode *instruction_count_node;
|
||||||
};
|
};
|
@ -3985,7 +3985,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
|
|||||||
|
|
||||||
|
|
||||||
#if ENABLE_BINARY_TRANSLATION
|
#if ENABLE_BINARY_TRANSLATION
|
||||||
BinaryTranslationLoader::Run();
|
num_instrs = BinaryTranslationLoader::Run(num_instrs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (cpu->TFlag)
|
if (cpu->TFlag)
|
||||||
|
@ -19,6 +19,7 @@ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> g_loaded_object_info;
|
|||||||
|
|
||||||
void(*g_run_function)();
|
void(*g_run_function)();
|
||||||
bool(*g_can_run_function)();
|
bool(*g_can_run_function)();
|
||||||
|
uint32_t *g_instruction_count;
|
||||||
|
|
||||||
// Used by the verifier
|
// Used by the verifier
|
||||||
struct SavedState
|
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_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_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;
|
g_enabled = true;
|
||||||
}
|
}
|
||||||
@ -145,18 +155,19 @@ bool BinaryTranslationLoader::CanRun(bool specific_address)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BinaryTranslationLoader::Run()
|
uint32_t BinaryTranslationLoader::Run(uint32_t instruction_count)
|
||||||
{
|
{
|
||||||
// No need to check the PC, Run does it anyway
|
// 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 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_run_function();
|
||||||
|
|
||||||
g_state->TFlag = g_state->Reg[15] & 1;
|
g_state->TFlag = g_state->Reg[15] & 1;
|
||||||
@ -164,6 +175,8 @@ void BinaryTranslationLoader::RunInternal()
|
|||||||
g_state->Reg[15] &= 0xfffffffe;
|
g_state->Reg[15] &= 0xfffffffe;
|
||||||
else
|
else
|
||||||
g_state->Reg[15] &= 0xfffffffc;
|
g_state->Reg[15] &= 0xfffffffc;
|
||||||
|
|
||||||
|
return *g_instruction_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Swap(void *a, void *b, size_t size)
|
void Swap(void *a, void *b, size_t size)
|
||||||
@ -198,7 +211,7 @@ void BinaryTranslationLoader::VerifyCallback()
|
|||||||
g_state_copy.SwapWith(*g_state);
|
g_state_copy.SwapWith(*g_state);
|
||||||
|
|
||||||
// Run the opcode
|
// Run the opcode
|
||||||
RunInternal();
|
RunInternal(0);
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
auto current_as_saved_state = SavedState(*g_state);
|
auto current_as_saved_state = SavedState(*g_state);
|
||||||
|
@ -13,8 +13,9 @@ public:
|
|||||||
// If specific_address, checks the specific PC too
|
// If specific_address, checks the specific PC too
|
||||||
static bool CanRun(bool specific_address);
|
static bool CanRun(bool specific_address);
|
||||||
// Runs the state provided at SetCpuState.
|
// 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
|
// Link between Run and VerifyCallback
|
||||||
static void RunInternal();
|
static uint32_t RunInternal(uint32_t instruction_count);
|
||||||
static void VerifyCallback();
|
static void VerifyCallback();
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user