mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 14:41:04 +00:00
Added block linking
Each time an instruction finishes it jumps to the next one instead of going back to the switch block
This commit is contained in:
parent
3864675b6d
commit
d7367172e8
@ -25,11 +25,18 @@ void InstructionBlock::GenerateEntryBlock()
|
|||||||
|
|
||||||
void InstructionBlock::GenerateCode()
|
void InstructionBlock::GenerateCode()
|
||||||
{
|
{
|
||||||
Module()->IrBuilder()->SetInsertPoint(entry_basic_block);
|
auto ir_builder = Module()->IrBuilder();
|
||||||
|
ir_builder->SetInsertPoint(entry_basic_block);
|
||||||
|
|
||||||
instruction->GenerateCode(this);
|
instruction->GenerateCode(this);
|
||||||
|
|
||||||
exit_basic_block = Module()->IrBuilder()->GetInsertBlock();
|
auto basic_block = ir_builder->GetInsertBlock();
|
||||||
|
// If the basic block is terminated there has been a jump
|
||||||
|
// If not, jump to the next instruction
|
||||||
|
if (!basic_block->getTerminator())
|
||||||
|
{
|
||||||
|
Module()->WritePCConst(Address() + 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Value *InstructionBlock::Read(Register reg)
|
llvm::Value *InstructionBlock::Read(Register reg)
|
||||||
|
@ -47,7 +47,6 @@ public:
|
|||||||
ModuleGen *Module() { return module; }
|
ModuleGen *Module() { return module; }
|
||||||
|
|
||||||
llvm::BasicBlock *GetEntryBasicBlock() { return entry_basic_block; }
|
llvm::BasicBlock *GetEntryBasicBlock() { return entry_basic_block; }
|
||||||
llvm::BasicBlock *GetExitBasicBlock() { return exit_basic_block; }
|
|
||||||
private:
|
private:
|
||||||
// Textual representation of the address
|
// Textual representation of the address
|
||||||
// Used to generate names
|
// Used to generate names
|
||||||
@ -58,7 +57,4 @@ private:
|
|||||||
|
|
||||||
// The block at the entry to instruction
|
// The block at the entry to instruction
|
||||||
llvm::BasicBlock *entry_basic_block;
|
llvm::BasicBlock *entry_basic_block;
|
||||||
|
|
||||||
// The block at the exit from the instruction
|
|
||||||
llvm::BasicBlock *exit_basic_block;
|
|
||||||
};
|
};
|
@ -1,6 +1,7 @@
|
|||||||
#include "DataProcessing.h"
|
#include "DataProcessing.h"
|
||||||
#include "Disassembler.h"
|
#include "Disassembler.h"
|
||||||
#include "InstructionBlock.h"
|
#include "InstructionBlock.h"
|
||||||
|
#include "ModuleGen.h"
|
||||||
|
|
||||||
static RegisterInstruction<DataProcessing> register_instruction;
|
static RegisterInstruction<DataProcessing> register_instruction;
|
||||||
|
|
||||||
@ -32,4 +33,9 @@ void DataProcessing::GenerateCode(InstructionBlock* instruction_block)
|
|||||||
|
|
||||||
auto value = instruction_block->Read(rm);
|
auto value = instruction_block->Read(rm);
|
||||||
instruction_block->Write(rd, value);
|
instruction_block->Write(rd, value);
|
||||||
|
|
||||||
|
if (rd == Register::PC)
|
||||||
|
{
|
||||||
|
instruction_block->Module()->ReadPC();
|
||||||
|
}
|
||||||
}
|
}
|
@ -35,12 +35,32 @@ void ModuleGen::Run()
|
|||||||
GenerateGetBlockAddressFunction();
|
GenerateGetBlockAddressFunction();
|
||||||
|
|
||||||
GenerateInstructionsCode();
|
GenerateInstructionsCode();
|
||||||
GenerateInstructionsTermination();
|
|
||||||
AddInstructionsToRunFunction();
|
AddInstructionsToRunFunction();
|
||||||
|
|
||||||
GenerateBlockAddressArray();
|
GenerateBlockAddressArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModuleGen::ReadPC()
|
||||||
|
{
|
||||||
|
ir_builder->CreateBr(run_function_re_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModuleGen::WritePCConst(u32 pc)
|
||||||
|
{
|
||||||
|
auto i = instruction_blocks_by_pc.find(pc);
|
||||||
|
if (i != instruction_blocks_by_pc.end())
|
||||||
|
{
|
||||||
|
// Found instruction, jump to it
|
||||||
|
ir_builder->CreateBr(i->second->GetEntryBasicBlock());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Didn't find instruction, write PC and exit
|
||||||
|
machine->WriteRegiser(Register::PC, ir_builder->getInt32(pc));
|
||||||
|
ir_builder->CreateRetVoid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ModuleGen::GenerateGlobals()
|
void ModuleGen::GenerateGlobals()
|
||||||
{
|
{
|
||||||
machine->GenerateGlobals();
|
machine->GenerateGlobals();
|
||||||
@ -200,17 +220,6 @@ void ModuleGen::GenerateInstructionsCode()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleGen::GenerateInstructionsTermination()
|
|
||||||
{
|
|
||||||
// Return to the switch
|
|
||||||
for (auto &block : instruction_blocks)
|
|
||||||
{
|
|
||||||
ir_builder->SetInsertPoint(block->GetExitBasicBlock());
|
|
||||||
Machine()->WriteRegiser(Register::PC, ir_builder->getInt32(block->Address() + 4));
|
|
||||||
ir_builder->CreateBr(run_function_re_entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModuleGen::AddInstructionsToRunFunction()
|
void ModuleGen::AddInstructionsToRunFunction()
|
||||||
{
|
{
|
||||||
std::stack<BasicBlock *> basic_blocks_stack;
|
std::stack<BasicBlock *> basic_blocks_stack;
|
||||||
@ -223,6 +232,7 @@ void ModuleGen::AddInstructionsToRunFunction()
|
|||||||
{
|
{
|
||||||
auto basic_block = basic_blocks_stack.top();
|
auto basic_block = basic_blocks_stack.top();
|
||||||
basic_blocks_stack.pop();
|
basic_blocks_stack.pop();
|
||||||
|
if (basic_block->getParent()) continue; // Already added to run
|
||||||
basic_block->insertInto(run_function);
|
basic_block->insertInto(run_function);
|
||||||
auto terminator = basic_block->getTerminator();
|
auto terminator = basic_block->getTerminator();
|
||||||
for (auto i = 0; i < terminator->getNumSuccessors(); ++i)
|
for (auto i = 0; i < terminator->getNumSuccessors(); ++i)
|
||||||
|
@ -20,6 +20,11 @@ public:
|
|||||||
|
|
||||||
void Run();
|
void Run();
|
||||||
|
|
||||||
|
// Generate code to read pc and run all following instructions, used in cases of indirect branch
|
||||||
|
void ReadPC();
|
||||||
|
// Generate code to write to pc and run all following instructions, used in cases of direct branch
|
||||||
|
void WritePCConst(u32 pc);
|
||||||
|
|
||||||
llvm::IRBuilder<> *IrBuilder() { return ir_builder.get(); }
|
llvm::IRBuilder<> *IrBuilder() { return ir_builder.get(); }
|
||||||
llvm::Module *Module() { return module; }
|
llvm::Module *Module() { return module; }
|
||||||
MachineState *Machine() { return machine.get(); }
|
MachineState *Machine() { return machine.get(); }
|
||||||
@ -37,8 +42,6 @@ private:
|
|||||||
void GenerateInstructionsEntry();
|
void GenerateInstructionsEntry();
|
||||||
// Generates the code of each instruction
|
// Generates the code of each instruction
|
||||||
void GenerateInstructionsCode();
|
void GenerateInstructionsCode();
|
||||||
// Terminates each block
|
|
||||||
void GenerateInstructionsTermination();
|
|
||||||
// Adds all the basic blocks of an instruction to the run function
|
// Adds all the basic blocks of an instruction to the run function
|
||||||
void AddInstructionsToRunFunction();
|
void AddInstructionsToRunFunction();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user