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/DataProcessing.cpp
|
||||
Instructions/Branch.cpp
|
||||
)
|
||||
set(HEADERS
|
||||
CodeGen.h
|
||||
@ -21,6 +22,7 @@ set(HEADERS
|
||||
Instructions/Types.h
|
||||
Instructions/Instruction.h
|
||||
Instructions/DataProcessing.h
|
||||
Instructions/Branch.h
|
||||
)
|
||||
|
||||
create_directory_groups(${SRCS} ${HEADERS})
|
||||
|
@ -35,7 +35,7 @@ void InstructionBlock::GenerateCode()
|
||||
// If not, jump to the next instruction
|
||||
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);
|
||||
}
|
||||
|
||||
size_t InstructionBlock::Address()
|
||||
u32 InstructionBlock::Address()
|
||||
{
|
||||
return instruction->Address();
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <common/common_types.h>
|
||||
|
||||
namespace llvm
|
||||
{
|
||||
@ -43,7 +44,7 @@ public:
|
||||
*/
|
||||
llvm::Value *Write(Register reg, llvm::Value *value);
|
||||
|
||||
size_t Address();
|
||||
u32 Address();
|
||||
ModuleGen *Module() { return module; }
|
||||
|
||||
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)
|
||||
{
|
||||
instruction_block->Module()->ReadPC();
|
||||
instruction_block->Module()->BranchReadPC();
|
||||
}
|
||||
}
|
@ -42,12 +42,12 @@ void ModuleGen::Run()
|
||||
GenerateBlockAddressArray();
|
||||
}
|
||||
|
||||
void ModuleGen::ReadPC()
|
||||
void ModuleGen::BranchReadPC()
|
||||
{
|
||||
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);
|
||||
if (i != instruction_blocks_by_pc.end())
|
||||
|
@ -22,9 +22,9 @@ public:
|
||||
void Run();
|
||||
|
||||
// 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
|
||||
void WritePCConst(u32 pc);
|
||||
void BranchWritePCConst(u32 pc);
|
||||
|
||||
llvm::IRBuilder<> *IrBuilder() { return ir_builder.get(); }
|
||||
llvm::Module *Module() { return module; }
|
||||
|
Loading…
Reference in New Issue
Block a user