mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 09:31:04 +00:00
Tab to space
This commit is contained in:
parent
af8817314a
commit
03527aba71
@ -27,7 +27,7 @@ ARMFuncs::ResultCarry ARMFuncs::Shift_C(InstructionBlock* instruction, llvm::Val
|
|||||||
{
|
{
|
||||||
auto ir_builder = instruction->IrBuilder();
|
auto ir_builder = instruction->IrBuilder();
|
||||||
|
|
||||||
auto amount_zero = ir_builder->CreateICmpEQ(amount, ir_builder->getInt32(0));
|
auto amount_zero = ir_builder->CreateICmpEQ(amount, ir_builder->getInt32(0));
|
||||||
ResultCarry result_amount_not_zero = {};
|
ResultCarry result_amount_not_zero = {};
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@ -39,8 +39,8 @@ ARMFuncs::ResultCarry ARMFuncs::Shift_C(InstructionBlock* instruction, llvm::Val
|
|||||||
default: assert(false, "Invalid shift type");
|
default: assert(false, "Invalid shift type");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = ir_builder->CreateSelect(amount_zero, value, result_amount_not_zero.result);
|
auto result = ir_builder->CreateSelect(amount_zero, value, result_amount_not_zero.result);
|
||||||
auto carry = ir_builder->CreateSelect(amount_zero, carry_in, result_amount_not_zero.carry);
|
auto carry = ir_builder->CreateSelect(amount_zero, carry_in, result_amount_not_zero.carry);
|
||||||
|
|
||||||
return{ result, carry };
|
return{ result, carry };
|
||||||
}
|
}
|
||||||
@ -52,10 +52,10 @@ llvm::Value* ShiftZeroCheck(
|
|||||||
{
|
{
|
||||||
auto ir_builder = instruction->IrBuilder();
|
auto ir_builder = instruction->IrBuilder();
|
||||||
|
|
||||||
auto amount_zero = ir_builder->CreateICmpEQ(shift, ir_builder->getInt32(0));
|
auto amount_zero = ir_builder->CreateICmpEQ(shift, ir_builder->getInt32(0));
|
||||||
auto result_amount_not_zero = non_zero_function(instruction, x, shift);
|
auto result_amount_not_zero = non_zero_function(instruction, x, shift);
|
||||||
|
|
||||||
return ir_builder->CreateSelect(amount_zero, x, result_amount_not_zero.result);
|
return ir_builder->CreateSelect(amount_zero, x, result_amount_not_zero.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
ARMFuncs::ResultCarry ARMFuncs::LSL_C(InstructionBlock* instruction, llvm::Value* x, llvm::Value* shift)
|
ARMFuncs::ResultCarry ARMFuncs::LSL_C(InstructionBlock* instruction, llvm::Value* x, llvm::Value* shift)
|
||||||
@ -128,11 +128,11 @@ llvm::Value* ARMFuncs::ARMExpandImm(InstructionBlock* instruction, u32 imm12)
|
|||||||
|
|
||||||
ARMFuncs::ResultCarry ARMFuncs::ARMExpandImm_C(InstructionBlock *instruction, u32 imm12, llvm::Value* carry)
|
ARMFuncs::ResultCarry ARMFuncs::ARMExpandImm_C(InstructionBlock *instruction, u32 imm12, llvm::Value* carry)
|
||||||
{
|
{
|
||||||
auto ir_builder = instruction->IrBuilder();
|
auto ir_builder = instruction->IrBuilder();
|
||||||
|
|
||||||
auto value = ir_builder->getInt32(imm12 & 0xFF);
|
auto value = ir_builder->getInt32(imm12 & 0xFF);
|
||||||
auto shift = ir_builder->getInt32(2 * (imm12 >> 8));
|
auto shift = ir_builder->getInt32(2 * (imm12 >> 8));
|
||||||
return Shift_C(instruction, value, SRType::ROR, shift, carry);
|
return Shift_C(instruction, value, SRType::ROR, shift, carry);
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddWithCarry from armsupp.cpp
|
// AddWithCarry from armsupp.cpp
|
||||||
|
@ -45,7 +45,7 @@ public:
|
|||||||
static ResultCarry RRX_C(InstructionBlock *instruction, llvm::Value *x, llvm::Value *carry_in);
|
static ResultCarry RRX_C(InstructionBlock *instruction, llvm::Value *x, llvm::Value *carry_in);
|
||||||
|
|
||||||
static llvm::Value *ARMExpandImm(InstructionBlock *instruction, u32 imm12);
|
static llvm::Value *ARMExpandImm(InstructionBlock *instruction, u32 imm12);
|
||||||
static ResultCarry ARMExpandImm_C(InstructionBlock *instruction, u32 imm12, llvm::Value *carry);
|
static ResultCarry ARMExpandImm_C(InstructionBlock *instruction, u32 imm12, llvm::Value *carry);
|
||||||
|
|
||||||
static ResultCarryOverflow AddWithCarry(InstructionBlock *instruction, llvm::Value *x, llvm::Value *y, llvm::Value *carry_in);
|
static ResultCarryOverflow AddWithCarry(InstructionBlock *instruction, llvm::Value *x, llvm::Value *y, llvm::Value *carry_in);
|
||||||
};
|
};
|
@ -8,8 +8,8 @@ using namespace llvm;
|
|||||||
|
|
||||||
BlockColors::BlockColors(ModuleGen* module) : module(module)
|
BlockColors::BlockColors(ModuleGen* module) : module(module)
|
||||||
{
|
{
|
||||||
auto ir_builder = module->IrBuilder();
|
auto ir_builder = module->IrBuilder();
|
||||||
function_type = FunctionType::get(ir_builder->getVoidTy(), ir_builder->getInt32Ty(), false);
|
function_type = FunctionType::get(ir_builder->getVoidTy(), ir_builder->getInt32Ty(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockColors::~BlockColors()
|
BlockColors::~BlockColors()
|
||||||
@ -18,69 +18,69 @@ BlockColors::~BlockColors()
|
|||||||
|
|
||||||
void BlockColors::AddBlock(InstructionBlock* block)
|
void BlockColors::AddBlock(InstructionBlock* block)
|
||||||
{
|
{
|
||||||
if (block->HasColor()) return;
|
if (block->HasColor()) return;
|
||||||
|
|
||||||
std::stack<InstructionBlock *> current_color_stack;
|
std::stack<InstructionBlock *> current_color_stack;
|
||||||
current_color_stack.push(block);
|
current_color_stack.push(block);
|
||||||
auto color = colors.size();
|
auto color = colors.size();
|
||||||
colors.push_back({ color });
|
colors.push_back({ color });
|
||||||
|
|
||||||
while (current_color_stack.size())
|
while (current_color_stack.size())
|
||||||
{
|
{
|
||||||
auto item = current_color_stack.top();
|
auto item = current_color_stack.top();
|
||||||
current_color_stack.pop();
|
current_color_stack.pop();
|
||||||
|
|
||||||
item->SetColor(color);
|
item->SetColor(color);
|
||||||
colors[color].instructions.push_back(item);
|
colors[color].instructions.push_back(item);
|
||||||
for (auto next : item->GetNexts())
|
for (auto next : item->GetNexts())
|
||||||
{
|
{
|
||||||
if (next->HasColor()) assert(next->GetColor() == color);
|
if (next->HasColor()) assert(next->GetColor() == color);
|
||||||
else current_color_stack.push(next);
|
else current_color_stack.push(next);
|
||||||
}
|
}
|
||||||
for (auto prev : item->GetPrevs())
|
for (auto prev : item->GetPrevs())
|
||||||
{
|
{
|
||||||
if (prev->HasColor()) assert(prev->GetColor() == color);
|
if (prev->HasColor()) assert(prev->GetColor() == color);
|
||||||
else current_color_stack.push(prev);
|
else current_color_stack.push(prev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockColors::GenerateFunctions()
|
void BlockColors::GenerateFunctions()
|
||||||
{
|
{
|
||||||
auto ir_builder = module->IrBuilder();
|
auto ir_builder = module->IrBuilder();
|
||||||
|
|
||||||
LOG_INFO(BinaryTranslator, "%x block colors", colors.size());
|
LOG_INFO(BinaryTranslator, "%x block colors", colors.size());
|
||||||
|
|
||||||
for (auto &color : colors)
|
for (auto &color : colors)
|
||||||
{
|
{
|
||||||
auto function = Function::Create(function_type, GlobalValue::PrivateLinkage,
|
auto function = Function::Create(function_type, GlobalValue::PrivateLinkage,
|
||||||
"ColorFunction", module->Module());
|
"ColorFunction", module->Module());
|
||||||
color.function = function;
|
color.function = function;
|
||||||
auto index = &function->getArgumentList().front();
|
auto index = &function->getArgumentList().front();
|
||||||
|
|
||||||
auto entry_basic_block = BasicBlock::Create(getGlobalContext(), "Entry", function);
|
auto entry_basic_block = BasicBlock::Create(getGlobalContext(), "Entry", function);
|
||||||
auto default_case_basic_block = BasicBlock::Create(getGlobalContext(), "Default", function);
|
auto default_case_basic_block = BasicBlock::Create(getGlobalContext(), "Default", function);
|
||||||
|
|
||||||
ir_builder->SetInsertPoint(default_case_basic_block);
|
ir_builder->SetInsertPoint(default_case_basic_block);
|
||||||
ir_builder->CreateUnreachable();
|
ir_builder->CreateUnreachable();
|
||||||
|
|
||||||
ir_builder->SetInsertPoint(entry_basic_block);
|
ir_builder->SetInsertPoint(entry_basic_block);
|
||||||
auto switch_instruction = ir_builder->CreateSwitch(index, default_case_basic_block, color.instructions.size());
|
auto switch_instruction = ir_builder->CreateSwitch(index, default_case_basic_block, color.instructions.size());
|
||||||
for (size_t i = 0; i < color.instructions.size(); ++i)
|
for (size_t i = 0; i < color.instructions.size(); ++i)
|
||||||
{
|
{
|
||||||
switch_instruction->addCase(ir_builder->getInt32(i), color.instructions[i]->GetEntryBasicBlock());
|
switch_instruction->addCase(ir_builder->getInt32(i), color.instructions[i]->GetEntryBasicBlock());
|
||||||
AddBasicBlocksToFunction(function, color.instructions[i]->GetEntryBasicBlock());
|
AddBasicBlocksToFunction(function, color.instructions[i]->GetEntryBasicBlock());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockColors::AddBasicBlocksToFunction(Function* function, BasicBlock* basic_block)
|
void BlockColors::AddBasicBlocksToFunction(Function* function, BasicBlock* basic_block)
|
||||||
{
|
{
|
||||||
if (basic_block->getParent())
|
if (basic_block->getParent())
|
||||||
{
|
{
|
||||||
assert(basic_block->getParent() == function);
|
assert(basic_block->getParent() == function);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::stack<BasicBlock *> basic_blocks;
|
std::stack<BasicBlock *> basic_blocks;
|
||||||
basic_blocks.push(basic_block);
|
basic_blocks.push(basic_block);
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace llvm
|
namespace llvm
|
||||||
{
|
{
|
||||||
class BasicBlock;
|
class BasicBlock;
|
||||||
class Function;
|
class Function;
|
||||||
class FunctionType;
|
class FunctionType;
|
||||||
}
|
}
|
||||||
class InstructionBlock;
|
class InstructionBlock;
|
||||||
class ModuleGen;
|
class ModuleGen;
|
||||||
@ -19,32 +19,32 @@ And to generate a function for each color
|
|||||||
class BlockColors
|
class BlockColors
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BlockColors(ModuleGen *module);
|
BlockColors(ModuleGen *module);
|
||||||
~BlockColors();
|
~BlockColors();
|
||||||
|
|
||||||
void AddBlock(InstructionBlock *block);
|
void AddBlock(InstructionBlock *block);
|
||||||
// Generates a function for each color
|
// Generates a function for each color
|
||||||
void GenerateFunctions();
|
void GenerateFunctions();
|
||||||
|
|
||||||
llvm::FunctionType *GetFunctionType() { return function_type; }
|
llvm::FunctionType *GetFunctionType() { return function_type; }
|
||||||
size_t GetColorCount() const { return colors.size(); }
|
size_t GetColorCount() const { return colors.size(); }
|
||||||
size_t GetColorInstructionCount(size_t color) const { return colors[color].instructions.size(); }
|
size_t GetColorInstructionCount(size_t color) const { return colors[color].instructions.size(); }
|
||||||
InstructionBlock *GetColorInstruction(size_t color, size_t index) { return colors[color].instructions[index]; }
|
InstructionBlock *GetColorInstruction(size_t color, size_t index) { return colors[color].instructions[index]; }
|
||||||
llvm::Function *GetColorFunction(size_t color) { return colors[color].function; }
|
llvm::Function *GetColorFunction(size_t color) { return colors[color].function; }
|
||||||
private:
|
private:
|
||||||
ModuleGen *module;
|
ModuleGen *module;
|
||||||
|
|
||||||
// void ColorFunction(int i)
|
// void ColorFunction(int i)
|
||||||
// Runs the code for color->instructions[i]
|
// Runs the code for color->instructions[i]
|
||||||
llvm::FunctionType *function_type;
|
llvm::FunctionType *function_type;
|
||||||
|
|
||||||
void AddBasicBlocksToFunction(llvm::Function *function, llvm::BasicBlock *basic_block);
|
void AddBasicBlocksToFunction(llvm::Function *function, llvm::BasicBlock *basic_block);
|
||||||
|
|
||||||
struct Color
|
struct Color
|
||||||
{
|
{
|
||||||
size_t color;
|
size_t color;
|
||||||
std::vector<InstructionBlock *> instructions;
|
std::vector<InstructionBlock *> instructions;
|
||||||
llvm::Function *function;
|
llvm::Function *function;
|
||||||
};
|
};
|
||||||
std::vector<Color> colors;
|
std::vector<Color> colors;
|
||||||
};
|
};
|
@ -1,39 +1,39 @@
|
|||||||
set(SRCS
|
set(SRCS
|
||||||
main.cpp
|
main.cpp
|
||||||
CodeGen.cpp
|
CodeGen.cpp
|
||||||
ModuleGen.cpp
|
ModuleGen.cpp
|
||||||
Disassembler.cpp
|
Disassembler.cpp
|
||||||
InstructionBlock.cpp
|
InstructionBlock.cpp
|
||||||
MachineState.cpp
|
MachineState.cpp
|
||||||
TBAA.cpp
|
TBAA.cpp
|
||||||
ARMFuncs.cpp
|
ARMFuncs.cpp
|
||||||
BlockColors.cpp
|
BlockColors.cpp
|
||||||
|
|
||||||
Instructions/Instruction.cpp
|
Instructions/Instruction.cpp
|
||||||
Instructions/MovShift.cpp
|
Instructions/MovShift.cpp
|
||||||
Instructions/Branch.cpp
|
Instructions/Branch.cpp
|
||||||
Instructions/Arithmetic.cpp
|
Instructions/Arithmetic.cpp
|
||||||
Instructions/Ldr.cpp
|
Instructions/Ldr.cpp
|
||||||
Instructions/Str.cpp
|
Instructions/Str.cpp
|
||||||
)
|
)
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
CodeGen.h
|
CodeGen.h
|
||||||
ModuleGen.h
|
ModuleGen.h
|
||||||
Disassembler.h
|
Disassembler.h
|
||||||
InstructionBlock.h
|
InstructionBlock.h
|
||||||
MachineState.h
|
MachineState.h
|
||||||
TBAA.h
|
TBAA.h
|
||||||
BinarySearch.h
|
BinarySearch.h
|
||||||
ARMFuncs.h
|
ARMFuncs.h
|
||||||
BlockColors.h
|
BlockColors.h
|
||||||
|
|
||||||
Instructions/Types.h
|
Instructions/Types.h
|
||||||
Instructions/Instruction.h
|
Instructions/Instruction.h
|
||||||
Instructions/MovShift.h
|
Instructions/MovShift.h
|
||||||
Instructions/Branch.h
|
Instructions/Branch.h
|
||||||
Instructions/Arithmetic.h
|
Instructions/Arithmetic.h
|
||||||
Instructions/Ldr.h
|
Instructions/Ldr.h
|
||||||
Instructions/Str.h
|
Instructions/Str.h
|
||||||
)
|
)
|
||||||
|
|
||||||
create_directory_groups(${SRCS} ${HEADERS})
|
create_directory_groups(${SRCS} ${HEADERS})
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
CodeGen::CodeGen(const char* output_object_filename, const char* output_debug_filename, bool verify)
|
CodeGen::CodeGen(const char* output_object_filename, const char* output_debug_filename, bool verify)
|
||||||
: output_object_filename(output_object_filename),
|
: output_object_filename(output_object_filename),
|
||||||
output_debug_filename(output_debug_filename),
|
output_debug_filename(output_debug_filename),
|
||||||
verify(verify)
|
verify(verify)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -31,11 +31,11 @@ CodeGen::~CodeGen()
|
|||||||
|
|
||||||
void CodeGen::Run()
|
void CodeGen::Run()
|
||||||
{
|
{
|
||||||
if (!Loader::ROMCodeStart)
|
if (!Loader::ROMCodeStart)
|
||||||
{
|
{
|
||||||
LOG_CRITICAL(BinaryTranslator, "No information from the loader about ROM file.");
|
LOG_CRITICAL(BinaryTranslator, "No information from the loader about ROM file.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
InitializeLLVM();
|
InitializeLLVM();
|
||||||
GenerateModule();
|
GenerateModule();
|
||||||
|
@ -15,8 +15,8 @@ class ModuleGen;
|
|||||||
class CodeGen
|
class CodeGen
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CodeGen(const char *output_object_filename, const char *output_debug_filename, bool verify);
|
CodeGen(const char *output_object_filename, const char *output_debug_filename, bool verify);
|
||||||
~CodeGen();
|
~CodeGen();
|
||||||
|
|
||||||
void Run();
|
void Run();
|
||||||
void InitializeLLVM();
|
void InitializeLLVM();
|
||||||
@ -25,8 +25,8 @@ public:
|
|||||||
bool Verify();
|
bool Verify();
|
||||||
void OptimizeAndGenerate();
|
void OptimizeAndGenerate();
|
||||||
private:
|
private:
|
||||||
const char *output_object_filename;
|
const char *output_object_filename;
|
||||||
const char *output_debug_filename;
|
const char *output_debug_filename;
|
||||||
bool verify;
|
bool verify;
|
||||||
|
|
||||||
std::unique_ptr<ModuleGen> moduleGenerator;
|
std::unique_ptr<ModuleGen> moduleGenerator;
|
||||||
|
@ -50,8 +50,8 @@ llvm::BasicBlock *InstructionBlock::CreateBasicBlock(const char *name)
|
|||||||
|
|
||||||
void InstructionBlock::Link(InstructionBlock* prev, InstructionBlock* next)
|
void InstructionBlock::Link(InstructionBlock* prev, InstructionBlock* next)
|
||||||
{
|
{
|
||||||
prev->nexts.push_back(next);
|
prev->nexts.push_back(next);
|
||||||
next->prevs.push_back(prev);
|
next->prevs.push_back(prev);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 InstructionBlock::Address() const
|
u32 InstructionBlock::Address() const
|
||||||
|
@ -50,9 +50,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
llvm::BasicBlock *CreateBasicBlock(const char *name);
|
llvm::BasicBlock *CreateBasicBlock(const char *name);
|
||||||
/*
|
/*
|
||||||
* Links two instructions, adding to prev and next lists
|
* Links two instructions, adding to prev and next lists
|
||||||
*/
|
*/
|
||||||
static void Link(InstructionBlock *prev, InstructionBlock *next);
|
static void Link(InstructionBlock *prev, InstructionBlock *next);
|
||||||
|
|
||||||
u32 Address() const;
|
u32 Address() const;
|
||||||
ModuleGen *Module() { return module; }
|
ModuleGen *Module() { return module; }
|
||||||
@ -60,11 +60,11 @@ public:
|
|||||||
|
|
||||||
llvm::BasicBlock *GetEntryBasicBlock() { return entry_basic_block; }
|
llvm::BasicBlock *GetEntryBasicBlock() { return entry_basic_block; }
|
||||||
|
|
||||||
bool HasColor() const { return has_color; }
|
bool HasColor() const { return has_color; }
|
||||||
void SetColor(size_t color) { this->color = color; has_color = true; }
|
void SetColor(size_t color) { this->color = color; has_color = true; }
|
||||||
size_t GetColor() const { return color; }
|
size_t GetColor() const { return color; }
|
||||||
|
|
||||||
std::list<InstructionBlock *> GetNexts() const { return nexts; }
|
std::list<InstructionBlock *> GetNexts() const { return nexts; }
|
||||||
std::list<InstructionBlock *> GetPrevs() const { return prevs; }
|
std::list<InstructionBlock *> GetPrevs() const { return prevs; }
|
||||||
private:
|
private:
|
||||||
// Textual representation of the address
|
// Textual representation of the address
|
||||||
@ -77,9 +77,9 @@ 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;
|
||||||
|
|
||||||
bool has_color = false;
|
bool has_color = false;
|
||||||
size_t color;
|
size_t color;
|
||||||
|
|
||||||
std::list<InstructionBlock *> nexts;
|
std::list<InstructionBlock *> nexts;
|
||||||
std::list<InstructionBlock *> prevs;
|
std::list<InstructionBlock *> prevs;
|
||||||
};
|
};
|
@ -56,7 +56,7 @@ void Instruction::GenerateCode(InstructionBlock *instruction_block)
|
|||||||
// If not, jump to the next instruction
|
// If not, jump to the next instruction
|
||||||
if (!ir_builder->GetInsertBlock()->getTerminator())
|
if (!ir_builder->GetInsertBlock()->getTerminator())
|
||||||
{
|
{
|
||||||
instruction_block->Module()->BranchWritePCConst(instruction_block, Address() + 4);
|
instruction_block->Module()->BranchWritePCConst(instruction_block, Address() + 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,20 +17,20 @@ bool MovShift::Decode()
|
|||||||
if (rd == Register::PC && s) return false; // SEE SUBS PC, LR and related instructions;
|
if (rd == Register::PC && s) return false; // SEE SUBS PC, LR and related instructions;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ReadFields({ CondDef(), FieldDef<7>(0x1d), FieldDef<1>(&s), FieldDef<4>(0),
|
if (ReadFields({ CondDef(), FieldDef<7>(0x1d), FieldDef<1>(&s), FieldDef<4>(0),
|
||||||
FieldDef<4>(&rd), FieldDef<12>(&imm12) }))
|
FieldDef<4>(&rd), FieldDef<12>(&imm12) }))
|
||||||
{
|
{
|
||||||
form = Form::ImmediateA1;
|
form = Form::ImmediateA1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ReadFields({ CondDef(), FieldDef<8>(0x30), FieldDef<4>(&imm4),
|
if (ReadFields({ CondDef(), FieldDef<8>(0x30), FieldDef<4>(&imm4),
|
||||||
FieldDef<4>(&rd), FieldDef<12>(&imm12) }))
|
FieldDef<4>(&rd), FieldDef<12>(&imm12) }))
|
||||||
{
|
{
|
||||||
s = false;
|
s = false;
|
||||||
form = Form::ImmediateA2;
|
form = Form::ImmediateA2;
|
||||||
if (rd == Register::PC) return false; // UNPREDICTIBLE
|
if (rd == Register::PC) return false; // UNPREDICTIBLE
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,50 +39,50 @@ void MovShift::GenerateInstructionCode(InstructionBlock* instruction_block)
|
|||||||
auto ir_builder = instruction_block->IrBuilder();
|
auto ir_builder = instruction_block->IrBuilder();
|
||||||
|
|
||||||
auto carry_in = instruction_block->Read(Register::C);
|
auto carry_in = instruction_block->Read(Register::C);
|
||||||
ARMFuncs::ResultCarry result = {};
|
ARMFuncs::ResultCarry result = {};
|
||||||
|
|
||||||
switch (form)
|
switch (form)
|
||||||
{
|
{
|
||||||
case Form::Register:
|
case Form::Register:
|
||||||
result = { instruction_block->Read(rm), carry_in };
|
result = { instruction_block->Read(rm), carry_in };
|
||||||
switch (op2)
|
switch (op2)
|
||||||
{
|
{
|
||||||
case Op2Type::MoveAndLSL:
|
case Op2Type::MoveAndLSL:
|
||||||
if (imm5 != 0)
|
if (imm5 != 0)
|
||||||
{
|
{
|
||||||
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::LSL,
|
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::LSL,
|
||||||
ARMFuncs::DecodeImmShift(instruction_block, 0, imm5).amount, result.carry);
|
ARMFuncs::DecodeImmShift(instruction_block, 0, imm5).amount, result.carry);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Op2Type::LSR:
|
case Op2Type::LSR:
|
||||||
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::LSR,
|
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::LSR,
|
||||||
ARMFuncs::DecodeImmShift(instruction_block, 1, imm5).amount, result.carry);
|
ARMFuncs::DecodeImmShift(instruction_block, 1, imm5).amount, result.carry);
|
||||||
break;
|
break;
|
||||||
case Op2Type::ASR:
|
case Op2Type::ASR:
|
||||||
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::ASR,
|
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::ASR,
|
||||||
ARMFuncs::DecodeImmShift(instruction_block, 2, imm5).amount, result.carry);
|
ARMFuncs::DecodeImmShift(instruction_block, 2, imm5).amount, result.carry);
|
||||||
break;
|
break;
|
||||||
case Op2Type::RRXAndROR:
|
case Op2Type::RRXAndROR:
|
||||||
if (imm5 == 0)
|
if (imm5 == 0)
|
||||||
{
|
{
|
||||||
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::RRX,
|
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::RRX,
|
||||||
ir_builder->getInt32(1), result.carry);
|
ir_builder->getInt32(1), result.carry);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::ROR,
|
result = ARMFuncs::Shift_C(instruction_block, result.result, ARMFuncs::SRType::ROR,
|
||||||
ARMFuncs::DecodeImmShift(instruction_block, 3, imm5).amount, result.carry);
|
ARMFuncs::DecodeImmShift(instruction_block, 3, imm5).amount, result.carry);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Form::ImmediateA1:
|
case Form::ImmediateA1:
|
||||||
result = ARMFuncs::ARMExpandImm_C(instruction_block, imm12, carry_in);
|
result = ARMFuncs::ARMExpandImm_C(instruction_block, imm12, carry_in);
|
||||||
break;
|
break;
|
||||||
case Form::ImmediateA2:
|
case Form::ImmediateA2:
|
||||||
result.result = ir_builder->getInt32((imm4 << 12) | imm12);
|
result.result = ir_builder->getInt32((imm4 << 12) | imm12);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
instruction_block->Write(rd, result.result);
|
instruction_block->Write(rd, result.result);
|
||||||
|
|
||||||
|
@ -28,6 +28,6 @@ private:
|
|||||||
Register rm;
|
Register rm;
|
||||||
u32 imm12;
|
u32 imm12;
|
||||||
u32 imm5;
|
u32 imm5;
|
||||||
u32 imm4;
|
u32 imm4;
|
||||||
Op2Type op2;
|
Op2Type op2;
|
||||||
};
|
};
|
@ -21,7 +21,7 @@ ModuleGen::ModuleGen(llvm::Module* module, bool verify)
|
|||||||
ir_builder = make_unique<IRBuilder<>>(getGlobalContext());
|
ir_builder = make_unique<IRBuilder<>>(getGlobalContext());
|
||||||
machine = make_unique<MachineState>(this);
|
machine = make_unique<MachineState>(this);
|
||||||
tbaa = make_unique<TBAA>();
|
tbaa = make_unique<TBAA>();
|
||||||
block_colors = make_unique<BlockColors>(this);
|
block_colors = make_unique<BlockColors>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleGen::~ModuleGen()
|
ModuleGen::~ModuleGen()
|
||||||
@ -42,7 +42,7 @@ void ModuleGen::Run()
|
|||||||
|
|
||||||
GenerateInstructionsCode();
|
GenerateInstructionsCode();
|
||||||
|
|
||||||
ColorBlocks();
|
ColorBlocks();
|
||||||
GenerateBlockAddressArray();
|
GenerateBlockAddressArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,11 +99,11 @@ void ModuleGen::GenerateGlobals()
|
|||||||
{
|
{
|
||||||
machine->GenerateGlobals();
|
machine->GenerateGlobals();
|
||||||
|
|
||||||
auto function_pointer = PointerType::get(block_colors->GetFunctionType(), 0);
|
auto function_pointer = PointerType::get(block_colors->GetFunctionType(), 0);
|
||||||
block_address_type = StructType::get(function_pointer, ir_builder->getInt32Ty(), nullptr);
|
block_address_type = StructType::get(function_pointer, ir_builder->getInt32Ty(), nullptr);
|
||||||
block_address_not_present = ConstantStruct::get(block_address_type, ConstantPointerNull::get(function_pointer), ir_builder->getInt32(0), nullptr);
|
block_address_not_present = ConstantStruct::get(block_address_type, ConstantPointerNull::get(function_pointer), ir_builder->getInt32(0), nullptr);
|
||||||
|
|
||||||
auto get_block_address_function_type = FunctionType::get(block_address_type, ir_builder->getInt32Ty(), false);
|
auto get_block_address_function_type = FunctionType::get(block_address_type, ir_builder->getInt32Ty(), false);
|
||||||
get_block_address_function = Function::Create(get_block_address_function_type, GlobalValue::PrivateLinkage, "GetBlockAddress", module);
|
get_block_address_function = Function::Create(get_block_address_function_type, GlobalValue::PrivateLinkage, "GetBlockAddress", module);
|
||||||
|
|
||||||
auto can_run_function_type = FunctionType::get(ir_builder->getInt1Ty(), false);
|
auto can_run_function_type = FunctionType::get(ir_builder->getInt1Ty(), false);
|
||||||
@ -115,7 +115,7 @@ void ModuleGen::GenerateGlobals()
|
|||||||
block_address_array_base = Loader::ROMCodeStart / 4;
|
block_address_array_base = Loader::ROMCodeStart / 4;
|
||||||
block_address_array_size = Loader::ROMCodeSize / 4;
|
block_address_array_size = Loader::ROMCodeSize / 4;
|
||||||
|
|
||||||
block_address_array_type = ArrayType::get(block_address_type, block_address_array_size);
|
block_address_array_type = ArrayType::get(block_address_type, block_address_array_size);
|
||||||
block_address_array = new GlobalVariable(*module, block_address_array_type, true, GlobalValue::ExternalLinkage, nullptr, "BlockAddressArray");
|
block_address_array = new GlobalVariable(*module, block_address_array_type, true, GlobalValue::ExternalLinkage, nullptr, "BlockAddressArray");
|
||||||
|
|
||||||
// bool Verify - contains the value of verify for citra usage
|
// bool Verify - contains the value of verify for citra usage
|
||||||
@ -132,27 +132,27 @@ void ModuleGen::GenerateBlockAddressArray()
|
|||||||
std::fill(
|
std::fill(
|
||||||
local_block_address_array_values.get(),
|
local_block_address_array_values.get(),
|
||||||
local_block_address_array_values.get() + block_address_array_size,
|
local_block_address_array_values.get() + block_address_array_size,
|
||||||
block_address_not_present);
|
block_address_not_present);
|
||||||
|
|
||||||
/*for (auto i = 0; i < instruction_blocks.size(); ++i)
|
/*for (auto i = 0; i < instruction_blocks.size(); ++i)
|
||||||
{
|
{
|
||||||
auto &block = instruction_blocks[i];
|
auto &block = instruction_blocks[i];
|
||||||
auto entry_basic_block = block->GetEntryBasicBlock();
|
auto entry_basic_block = block->GetEntryBasicBlock();
|
||||||
auto index = block->Address() / 4 - block_address_array_base;
|
auto index = block->Address() / 4 - block_address_array_base;
|
||||||
auto color_index = 0;
|
auto color_index = 0;
|
||||||
local_block_address_array_values[index] = BConst
|
local_block_address_array_values[index] = BConst
|
||||||
}*/
|
}*/
|
||||||
for (auto color = 0; color < block_colors->GetColorCount(); ++color)
|
for (auto color = 0; color < block_colors->GetColorCount(); ++color)
|
||||||
{
|
{
|
||||||
auto function = block_colors->GetColorFunction(color);
|
auto function = block_colors->GetColorFunction(color);
|
||||||
for (auto i = 0; i < block_colors->GetColorInstructionCount(color); ++i)
|
for (auto i = 0; i < block_colors->GetColorInstructionCount(color); ++i)
|
||||||
{
|
{
|
||||||
auto block = block_colors->GetColorInstruction(color, i);
|
auto block = block_colors->GetColorInstruction(color, i);
|
||||||
auto index = block->Address() / 4 - block_address_array_base;
|
auto index = block->Address() / 4 - block_address_array_base;
|
||||||
auto value = ConstantStruct::get(block_address_type, function, ir_builder->getInt32(i), nullptr);
|
auto value = ConstantStruct::get(block_address_type, function, ir_builder->getInt32(i), nullptr);
|
||||||
local_block_address_array_values[index] = value;
|
local_block_address_array_values[index] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto local_block_address_array_values_ref = ArrayRef<Constant*>(local_block_address_array_values.get(), block_address_array_size);
|
auto local_block_address_array_values_ref = ArrayRef<Constant*>(local_block_address_array_values.get(), block_address_array_size);
|
||||||
auto local_blocks_address_array = ConstantArray::get(block_address_array_type, local_block_address_array_values_ref);
|
auto local_blocks_address_array = ConstantArray::get(block_address_array_type, local_block_address_array_values_ref);
|
||||||
@ -205,9 +205,9 @@ void ModuleGen::GenerateCanRunFunction()
|
|||||||
|
|
||||||
ir_builder->SetInsertPoint(basic_block);
|
ir_builder->SetInsertPoint(basic_block);
|
||||||
auto block_address = ir_builder->CreateCall(get_block_address_function, machine->ReadRegiser(Register::PC, true));
|
auto block_address = ir_builder->CreateCall(get_block_address_function, machine->ReadRegiser(Register::PC, true));
|
||||||
auto function = ir_builder->CreateExtractValue(block_address, 0);
|
auto function = ir_builder->CreateExtractValue(block_address, 0);
|
||||||
ir_builder->CreateRet(ir_builder->CreateICmpNE(function,
|
ir_builder->CreateRet(ir_builder->CreateICmpNE(function,
|
||||||
ConstantPointerNull::get(cast<PointerType>(function->getType()))));
|
ConstantPointerNull::get(cast<PointerType>(function->getType()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleGen::GenerateRunFunction()
|
void ModuleGen::GenerateRunFunction()
|
||||||
@ -231,18 +231,18 @@ void ModuleGen::GenerateRunFunction()
|
|||||||
auto block_present_basic_block = BasicBlock::Create(getGlobalContext(), "BlockPresent", run_function);
|
auto block_present_basic_block = BasicBlock::Create(getGlobalContext(), "BlockPresent", run_function);
|
||||||
auto block_not_present_basic_block = BasicBlock::Create(getGlobalContext(), "BlockNotPresent", run_function);
|
auto block_not_present_basic_block = BasicBlock::Create(getGlobalContext(), "BlockNotPresent", run_function);
|
||||||
|
|
||||||
ir_builder->SetInsertPoint(run_function_entry);
|
ir_builder->SetInsertPoint(run_function_entry);
|
||||||
auto block_address = ir_builder->CreateCall(get_block_address_function, Machine()->ReadRegiser(Register::PC, true));
|
auto block_address = ir_builder->CreateCall(get_block_address_function, Machine()->ReadRegiser(Register::PC, true));
|
||||||
auto function = ir_builder->CreateExtractValue(block_address, 0);
|
auto function = ir_builder->CreateExtractValue(block_address, 0);
|
||||||
auto block_present_pred = ir_builder->CreateICmpNE(function,
|
auto block_present_pred = ir_builder->CreateICmpNE(function,
|
||||||
ConstantPointerNull::get(cast<PointerType>(function->getType())));
|
ConstantPointerNull::get(cast<PointerType>(function->getType())));
|
||||||
ir_builder->CreateCondBr(block_present_pred, block_present_basic_block, block_not_present_basic_block);
|
ir_builder->CreateCondBr(block_present_pred, block_present_basic_block, block_not_present_basic_block);
|
||||||
|
|
||||||
ir_builder->SetInsertPoint(block_present_basic_block);
|
ir_builder->SetInsertPoint(block_present_basic_block);
|
||||||
auto index = ir_builder->CreateExtractValue(block_address, 1);
|
auto index = ir_builder->CreateExtractValue(block_address, 1);
|
||||||
auto call = ir_builder->CreateCall(function, index);
|
auto call = ir_builder->CreateCall(function, index);
|
||||||
call->setTailCall();
|
call->setTailCall();
|
||||||
ir_builder->CreateRetVoid();
|
ir_builder->CreateRetVoid();
|
||||||
|
|
||||||
ir_builder->SetInsertPoint(block_not_present_basic_block);
|
ir_builder->SetInsertPoint(block_not_present_basic_block);
|
||||||
ir_builder->CreateRetVoid();
|
ir_builder->CreateRetVoid();
|
||||||
@ -286,9 +286,9 @@ void ModuleGen::GenerateInstructionsCode()
|
|||||||
|
|
||||||
void ModuleGen::ColorBlocks()
|
void ModuleGen::ColorBlocks()
|
||||||
{
|
{
|
||||||
for (auto &instruction : instruction_blocks)
|
for (auto &instruction : instruction_blocks)
|
||||||
{
|
{
|
||||||
block_colors->AddBlock(instruction.get());
|
block_colors->AddBlock(instruction.get());
|
||||||
}
|
}
|
||||||
block_colors->GenerateFunctions();
|
block_colors->GenerateFunctions();
|
||||||
}
|
}
|
@ -50,10 +50,10 @@ private:
|
|||||||
// Generates the entry basic blocks for each instruction
|
// Generates the entry basic blocks for each instruction
|
||||||
void GenerateInstructionsEntry();
|
void GenerateInstructionsEntry();
|
||||||
// Generates the code of each instruction
|
// Generates the code of each instruction
|
||||||
void GenerateInstructionsCode();
|
void GenerateInstructionsCode();
|
||||||
// Must be run after the instruction code is generated since it depends on the
|
// Must be run after the instruction code is generated since it depends on the
|
||||||
// inter block jumps
|
// inter block jumps
|
||||||
void ColorBlocks();
|
void ColorBlocks();
|
||||||
|
|
||||||
llvm::Module *module;
|
llvm::Module *module;
|
||||||
bool verify;
|
bool verify;
|
||||||
@ -64,16 +64,16 @@ private:
|
|||||||
std::unique_ptr<llvm::IRBuilder<>> ir_builder;
|
std::unique_ptr<llvm::IRBuilder<>> ir_builder;
|
||||||
|
|
||||||
size_t block_address_array_base;
|
size_t block_address_array_base;
|
||||||
size_t block_address_array_size;
|
size_t block_address_array_size;
|
||||||
/*
|
/*
|
||||||
* struct BlockAddress
|
* struct BlockAddress
|
||||||
* {
|
* {
|
||||||
* void (*function)(u32 index);
|
* void (*function)(u32 index);
|
||||||
* u32 index;
|
* u32 index;
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
llvm::StructType *block_address_type;
|
llvm::StructType *block_address_type;
|
||||||
llvm::Constant *block_address_not_present;
|
llvm::Constant *block_address_not_present;
|
||||||
/*
|
/*
|
||||||
* i8 **BlockAddressArray;
|
* i8 **BlockAddressArray;
|
||||||
* The array at [i/4 - block_address_array_base] contains the block address for the instruction at i
|
* The array at [i/4 - block_address_array_base] contains the block address for the instruction at i
|
||||||
@ -109,5 +109,5 @@ private:
|
|||||||
std::vector<std::unique_ptr<InstructionBlock>> instruction_blocks;
|
std::vector<std::unique_ptr<InstructionBlock>> instruction_blocks;
|
||||||
std::unordered_map<u32, InstructionBlock *> instruction_blocks_by_pc;
|
std::unordered_map<u32, InstructionBlock *> instruction_blocks_by_pc;
|
||||||
|
|
||||||
std::unique_ptr<BlockColors> block_colors;
|
std::unique_ptr<BlockColors> block_colors;
|
||||||
};
|
};
|
@ -28,30 +28,30 @@ int main(int argc, const char *const *argv)
|
|||||||
}
|
}
|
||||||
cl::ParseCommandLineOptions(argc, argv);
|
cl::ParseCommandLineOptions(argc, argv);
|
||||||
|
|
||||||
std::shared_ptr<Log::Logger> logger = Log::InitGlobalLogger();
|
std::shared_ptr<Log::Logger> logger = Log::InitGlobalLogger();
|
||||||
Log::Filter log_filter(Log::Level::Debug);
|
Log::Filter log_filter(Log::Level::Debug);
|
||||||
Log::SetFilter(&log_filter);
|
Log::SetFilter(&log_filter);
|
||||||
std::thread logging_thread(Log::TextLoggingLoop, logger);
|
std::thread logging_thread(Log::TextLoggingLoop, logger);
|
||||||
SCOPE_EXIT({
|
SCOPE_EXIT({
|
||||||
logger->Close();
|
logger->Close();
|
||||||
logging_thread.join();
|
logging_thread.join();
|
||||||
});
|
});
|
||||||
|
|
||||||
auto input_rom = InputFilename.c_str();
|
auto input_rom = InputFilename.c_str();
|
||||||
auto output_object = OutputFilename.c_str();
|
auto output_object = OutputFilename.c_str();
|
||||||
auto output_debug = DebugFilename.getNumOccurrences() ? DebugFilename.c_str() : nullptr;
|
auto output_debug = DebugFilename.getNumOccurrences() ? DebugFilename.c_str() : nullptr;
|
||||||
bool verify = Verify;
|
bool verify = Verify;
|
||||||
|
|
||||||
Core::Init();
|
Core::Init();
|
||||||
Memory::Init();
|
Memory::Init();
|
||||||
|
|
||||||
auto load_result = Loader::LoadFile(input_rom);
|
auto load_result = Loader::LoadFile(input_rom);
|
||||||
if (Loader::ResultStatus::Success != load_result)
|
if (Loader::ResultStatus::Success != load_result)
|
||||||
{
|
{
|
||||||
LOG_CRITICAL(BinaryTranslator, "Failed to load ROM (Error %i)!", load_result);
|
LOG_CRITICAL(BinaryTranslator, "Failed to load ROM (Error %i)!", load_result);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeGen code_generator(output_object, output_debug, verify);
|
CodeGen code_generator(output_object, output_debug, verify);
|
||||||
code_generator.Run();
|
code_generator.Run();
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user