mirror of
https://github.com/citra-emu/citra.git
synced 2025-02-22 18:40:04 +00:00
Added bl, blx
17% of the instructions in 3dscraft
This commit is contained in:
parent
4daf99fa44
commit
7882bb2c4c
@ -9,6 +9,7 @@ set(SRCS
|
|||||||
|
|
||||||
Instructions/Instruction.cpp
|
Instructions/Instruction.cpp
|
||||||
Instructions/DataProcessing.cpp
|
Instructions/DataProcessing.cpp
|
||||||
|
Instructions/Branch.cpp
|
||||||
)
|
)
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
CodeGen.h
|
CodeGen.h
|
||||||
@ -21,6 +22,7 @@ set(HEADERS
|
|||||||
Instructions/Types.h
|
Instructions/Types.h
|
||||||
Instructions/Instruction.h
|
Instructions/Instruction.h
|
||||||
Instructions/DataProcessing.h
|
Instructions/DataProcessing.h
|
||||||
|
Instructions/Branch.h
|
||||||
)
|
)
|
||||||
|
|
||||||
create_directory_groups(${SRCS} ${HEADERS})
|
create_directory_groups(${SRCS} ${HEADERS})
|
||||||
|
@ -35,7 +35,7 @@ void InstructionBlock::GenerateCode()
|
|||||||
// If not, jump to the next instruction
|
// If not, jump to the next instruction
|
||||||
if (!basic_block->getTerminator())
|
if (!basic_block->getTerminator())
|
||||||
{
|
{
|
||||||
Module()->WritePCConst(Address() + 4);
|
Module()->BranchWritePCConst(Address() + 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ llvm::Value *InstructionBlock::Write(Register reg, llvm::Value *value)
|
|||||||
return module->Machine()->WriteRegiser(reg, value);
|
return module->Machine()->WriteRegiser(reg, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t InstructionBlock::Address()
|
u32 InstructionBlock::Address()
|
||||||
{
|
{
|
||||||
return instruction->Address();
|
return instruction->Address();
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <common/common_types.h>
|
||||||
|
|
||||||
namespace llvm
|
namespace llvm
|
||||||
{
|
{
|
||||||
@ -43,7 +44,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
llvm::Value *Write(Register reg, llvm::Value *value);
|
llvm::Value *Write(Register reg, llvm::Value *value);
|
||||||
|
|
||||||
size_t Address();
|
u32 Address();
|
||||||
ModuleGen *Module() { return module; }
|
ModuleGen *Module() { return module; }
|
||||||
|
|
||||||
llvm::BasicBlock *GetEntryBasicBlock() { return entry_basic_block; }
|
llvm::BasicBlock *GetEntryBasicBlock() { return entry_basic_block; }
|
||||||
|
51
src/binary_translation/Instructions/Branch.cpp
Normal file
51
src/binary_translation/Instructions/Branch.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include "Branch.h"
|
||||||
|
#include "Disassembler.h"
|
||||||
|
#include "InstructionBlock.h"
|
||||||
|
#include "ModuleGen.h"
|
||||||
|
|
||||||
|
static RegisterInstruction<Branch> register_instruction;
|
||||||
|
|
||||||
|
bool Branch::Decode()
|
||||||
|
{
|
||||||
|
// B imm, BL imm
|
||||||
|
if (ReadFields({ FieldDef<4>(&cond), FieldDef<3>(5), FieldDef<1>(&link), FieldDef<24>(&imm24) }))
|
||||||
|
{
|
||||||
|
if (cond != Condition::AL) return false;
|
||||||
|
|
||||||
|
form = Form::Immediate;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// BLX reg
|
||||||
|
if (ReadFields({ FieldDef<4>(&cond), FieldDef<24>(0x12fff3), FieldDef<4>(&rm)}))
|
||||||
|
{
|
||||||
|
if (cond != Condition::AL) return false;
|
||||||
|
if (rm == Register::PC) return false;
|
||||||
|
|
||||||
|
link = true;
|
||||||
|
form = Form::Register;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Branch::GenerateCode(InstructionBlock* instruction_block)
|
||||||
|
{
|
||||||
|
auto ir_builder = instruction_block->Module()->IrBuilder();
|
||||||
|
if (link)
|
||||||
|
{
|
||||||
|
instruction_block->Write(Register::LR, ir_builder->getInt32(instruction_block->Address() + 4));
|
||||||
|
}
|
||||||
|
if (form == Form::Immediate)
|
||||||
|
{
|
||||||
|
auto pc = static_cast<s32>(imm24 << 2);
|
||||||
|
pc = pc << 6 >> 6; // Sign extend
|
||||||
|
pc += instruction_block->Address() + 8;
|
||||||
|
instruction_block->Module()->BranchWritePCConst(pc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto pc = instruction_block->Read(rm);
|
||||||
|
instruction_block->Write(Register::PC, pc);
|
||||||
|
instruction_block->Module()->BranchReadPC();
|
||||||
|
}
|
||||||
|
}
|
26
src/binary_translation/Instructions/Branch.h
Normal file
26
src/binary_translation/Instructions/Branch.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#include "Instruction.h"
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data processing instructions
|
||||||
|
* ARMv7-A 5.2.1 (register), 5.2.2 (register-shifted register, 5.2.3 (immediate)
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Branch : public Instruction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Form
|
||||||
|
{
|
||||||
|
Immediate, Register
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual bool Decode() override;
|
||||||
|
void GenerateCode(InstructionBlock* instruction_block) override;
|
||||||
|
private:
|
||||||
|
Form form;
|
||||||
|
Condition cond;
|
||||||
|
bool link;
|
||||||
|
u32 imm24;
|
||||||
|
Register rm;
|
||||||
|
};
|
@ -37,6 +37,6 @@ void DataProcessing::GenerateCode(InstructionBlock* instruction_block)
|
|||||||
|
|
||||||
if (rd == Register::PC)
|
if (rd == Register::PC)
|
||||||
{
|
{
|
||||||
instruction_block->Module()->ReadPC();
|
instruction_block->Module()->BranchReadPC();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -42,12 +42,12 @@ void ModuleGen::Run()
|
|||||||
GenerateBlockAddressArray();
|
GenerateBlockAddressArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleGen::ReadPC()
|
void ModuleGen::BranchReadPC()
|
||||||
{
|
{
|
||||||
ir_builder->CreateBr(run_function_re_entry);
|
ir_builder->CreateBr(run_function_re_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleGen::WritePCConst(u32 pc)
|
void ModuleGen::BranchWritePCConst(u32 pc)
|
||||||
{
|
{
|
||||||
auto i = instruction_blocks_by_pc.find(pc);
|
auto i = instruction_blocks_by_pc.find(pc);
|
||||||
if (i != instruction_blocks_by_pc.end())
|
if (i != instruction_blocks_by_pc.end())
|
||||||
|
@ -22,9 +22,9 @@ public:
|
|||||||
void Run();
|
void Run();
|
||||||
|
|
||||||
// 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 ReadPC();
|
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
|
||||||
void WritePCConst(u32 pc);
|
void BranchWritePCConst(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; }
|
||||||
|
Loading…
Reference in New Issue
Block a user