From d7367172e887a994b77389d71bb41e84ebe43133 Mon Sep 17 00:00:00 2001 From: Dani Messerman Date: Thu, 30 Apr 2015 23:28:12 +0300 Subject: [PATCH] Added block linking Each time an instruction finishes it jumps to the next one instead of going back to the switch block --- src/binary_translation/InstructionBlock.cpp | 11 ++++-- src/binary_translation/InstructionBlock.h | 4 --- .../Instructions/DataProcessing.cpp | 6 ++++ src/binary_translation/ModuleGen.cpp | 34 ++++++++++++------- src/binary_translation/ModuleGen.h | 7 ++-- 5 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/binary_translation/InstructionBlock.cpp b/src/binary_translation/InstructionBlock.cpp index 9cf7ef91d..b00d9b414 100644 --- a/src/binary_translation/InstructionBlock.cpp +++ b/src/binary_translation/InstructionBlock.cpp @@ -25,11 +25,18 @@ void InstructionBlock::GenerateEntryBlock() void InstructionBlock::GenerateCode() { - Module()->IrBuilder()->SetInsertPoint(entry_basic_block); + auto ir_builder = Module()->IrBuilder(); + ir_builder->SetInsertPoint(entry_basic_block); 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) diff --git a/src/binary_translation/InstructionBlock.h b/src/binary_translation/InstructionBlock.h index bad4a4e6b..81f9d34ae 100644 --- a/src/binary_translation/InstructionBlock.h +++ b/src/binary_translation/InstructionBlock.h @@ -47,7 +47,6 @@ public: ModuleGen *Module() { return module; } llvm::BasicBlock *GetEntryBasicBlock() { return entry_basic_block; } - llvm::BasicBlock *GetExitBasicBlock() { return exit_basic_block; } private: // Textual representation of the address // Used to generate names @@ -58,7 +57,4 @@ private: // The block at the entry to instruction llvm::BasicBlock *entry_basic_block; - - // The block at the exit from the instruction - llvm::BasicBlock *exit_basic_block; }; \ No newline at end of file diff --git a/src/binary_translation/Instructions/DataProcessing.cpp b/src/binary_translation/Instructions/DataProcessing.cpp index f94ab0003..a9dd62660 100644 --- a/src/binary_translation/Instructions/DataProcessing.cpp +++ b/src/binary_translation/Instructions/DataProcessing.cpp @@ -1,6 +1,7 @@ #include "DataProcessing.h" #include "Disassembler.h" #include "InstructionBlock.h" +#include "ModuleGen.h" static RegisterInstruction register_instruction; @@ -32,4 +33,9 @@ void DataProcessing::GenerateCode(InstructionBlock* instruction_block) auto value = instruction_block->Read(rm); instruction_block->Write(rd, value); + + if (rd == Register::PC) + { + instruction_block->Module()->ReadPC(); + } } \ No newline at end of file diff --git a/src/binary_translation/ModuleGen.cpp b/src/binary_translation/ModuleGen.cpp index 51dc919b5..4a4efb296 100644 --- a/src/binary_translation/ModuleGen.cpp +++ b/src/binary_translation/ModuleGen.cpp @@ -35,12 +35,32 @@ void ModuleGen::Run() GenerateGetBlockAddressFunction(); GenerateInstructionsCode(); - GenerateInstructionsTermination(); AddInstructionsToRunFunction(); 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() { 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() { std::stack basic_blocks_stack; @@ -223,6 +232,7 @@ void ModuleGen::AddInstructionsToRunFunction() { auto basic_block = basic_blocks_stack.top(); basic_blocks_stack.pop(); + if (basic_block->getParent()) continue; // Already added to run basic_block->insertInto(run_function); auto terminator = basic_block->getTerminator(); for (auto i = 0; i < terminator->getNumSuccessors(); ++i) diff --git a/src/binary_translation/ModuleGen.h b/src/binary_translation/ModuleGen.h index a80936103..fa94e1784 100644 --- a/src/binary_translation/ModuleGen.h +++ b/src/binary_translation/ModuleGen.h @@ -20,6 +20,11 @@ public: 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::Module *Module() { return module; } MachineState *Machine() { return machine.get(); } @@ -37,8 +42,6 @@ private: void GenerateInstructionsEntry(); // Generates the code of each instruction void GenerateInstructionsCode(); - // Terminates each block - void GenerateInstructionsTermination(); // Adds all the basic blocks of an instruction to the run function void AddInstructionsToRunFunction();