mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-24 14:51:04 +00:00
Added str
This commit is contained in:
parent
b528ddeebc
commit
be7070d093
@ -14,6 +14,7 @@ set(SRCS
|
|||||||
Instructions/Branch.cpp
|
Instructions/Branch.cpp
|
||||||
Instructions/Arithmetic.cpp
|
Instructions/Arithmetic.cpp
|
||||||
Instructions/Ldr.cpp
|
Instructions/Ldr.cpp
|
||||||
|
Instructions/Str.cpp
|
||||||
)
|
)
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
CodeGen.h
|
CodeGen.h
|
||||||
@ -32,6 +33,7 @@ set(HEADERS
|
|||||||
Instructions/Branch.h
|
Instructions/Branch.h
|
||||||
Instructions/Arithmetic.h
|
Instructions/Arithmetic.h
|
||||||
Instructions/Ldr.h
|
Instructions/Ldr.h
|
||||||
|
Instructions/Str.h
|
||||||
)
|
)
|
||||||
|
|
||||||
create_directory_groups(${SRCS} ${HEADERS})
|
create_directory_groups(${SRCS} ${HEADERS})
|
||||||
|
@ -70,8 +70,8 @@ void Ldr::GenerateInstructionCode(InstructionBlock* instruction_block)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto index = (bool)P;
|
auto index = P == 1;
|
||||||
auto wback = !P || W;
|
auto wback = P == 0 || W == 1;
|
||||||
auto source_register = instruction_block->Read(rn);
|
auto source_register = instruction_block->Read(rn);
|
||||||
auto imm32 = ir_builder->getInt32(add ? imm12 : -imm12);
|
auto imm32 = ir_builder->getInt32(add ? imm12 : -imm12);
|
||||||
|
|
||||||
|
70
src/binary_translation/Instructions/Str.cpp
Normal file
70
src/binary_translation/Instructions/Str.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#include "Str.h"
|
||||||
|
#include "Disassembler.h"
|
||||||
|
#include "InstructionBlock.h"
|
||||||
|
#include <llvm/IR/Value.h>
|
||||||
|
#include <core/loader/loader.h>
|
||||||
|
#include <core/mem_map.h>
|
||||||
|
#include "MachineState.h"
|
||||||
|
|
||||||
|
static RegisterInstruction<Str> register_instruction;
|
||||||
|
|
||||||
|
bool Str::Decode()
|
||||||
|
{
|
||||||
|
if (ReadFields({ CondDef(), FieldDef<3>(2), FieldDef<1>(&P), FieldDef<1>(&U), FieldDef<1>(0), FieldDef<1>(&W), FieldDef<1>(0), FieldDef<4>(&rn),
|
||||||
|
FieldDef<4>(&rt), FieldDef<12>(&imm12) }))
|
||||||
|
{
|
||||||
|
form = Form::Immediate;
|
||||||
|
|
||||||
|
if (!P && W) return false; // SEE LDRT;
|
||||||
|
if ((!P || W) && (rn == rt || rn == Register::PC)) return false; // UNPREDICTABLE;
|
||||||
|
if (rn == Register::PC) return false; // Currently unimplemented
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (ReadFields({ CondDef(), FieldDef<6>(0x24), FieldDef<1>(&W), FieldDef<1>(0), FieldDef<4>(&rn),
|
||||||
|
FieldDef<16>(®ister_list) }))
|
||||||
|
{
|
||||||
|
form = Form::MultiReg;
|
||||||
|
|
||||||
|
if (rn == Register::PC || register_list.size() < 1) return false; // UNPREDICTABLE;
|
||||||
|
if (register_list[(int)Register::PC]) return false; // Currently unimplemented
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Str::GenerateInstructionCode(InstructionBlock* instruction_block)
|
||||||
|
{
|
||||||
|
auto ir_builder = instruction_block->IrBuilder();
|
||||||
|
|
||||||
|
if (form == Form::Immediate)
|
||||||
|
{
|
||||||
|
auto add = U == 1;
|
||||||
|
auto index = P == 1;
|
||||||
|
auto wback = P == 0 || W == 1;
|
||||||
|
auto source_register = instruction_block->Read(rn);
|
||||||
|
auto imm32 = ir_builder->getInt32(add ? imm12 : -imm12);
|
||||||
|
|
||||||
|
auto offset_address = ir_builder->CreateAdd(source_register, imm32);
|
||||||
|
auto address = index ? offset_address : source_register;
|
||||||
|
if (wback)
|
||||||
|
instruction_block->Write(rn, offset_address);
|
||||||
|
instruction_block->Module()->Machine()->WriteMemory32(address, instruction_block->Read(rt));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto wback = W == 1;
|
||||||
|
auto write_back_address = ir_builder->CreateSub(instruction_block->Read(rn), ir_builder->getInt32(4 * register_list.count()));
|
||||||
|
auto address = write_back_address;
|
||||||
|
for (auto i = 0; i < 16; ++i)
|
||||||
|
{
|
||||||
|
if (!register_list[i]) continue;
|
||||||
|
instruction_block->Module()->Machine()->WriteMemory32(address, instruction_block->Read((Register)i));
|
||||||
|
address = ir_builder->CreateAdd(address, ir_builder->getInt32(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wback)
|
||||||
|
instruction_block->Write(rn, write_back_address);
|
||||||
|
}
|
||||||
|
}
|
26
src/binary_translation/Instructions/Str.h
Normal file
26
src/binary_translation/Instructions/Str.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#include "Instruction.h"
|
||||||
|
#include "Types.h"
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
|
class Str : public Instruction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Form
|
||||||
|
{
|
||||||
|
Immediate, Reg, MultiReg
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual bool Decode() override;
|
||||||
|
void GenerateInstructionCode(InstructionBlock* instruction_block) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Form form;
|
||||||
|
bool U;
|
||||||
|
Register rt;
|
||||||
|
u32 imm12;
|
||||||
|
bool P;
|
||||||
|
bool W;
|
||||||
|
Register rn;
|
||||||
|
std::bitset<16> register_list;
|
||||||
|
};
|
@ -15,6 +15,8 @@ MachineState::MachineState(ModuleGen *module) : module(module)
|
|||||||
|
|
||||||
void MachineState::GenerateGlobals()
|
void MachineState::GenerateGlobals()
|
||||||
{
|
{
|
||||||
|
auto ir_builder = module->IrBuilder();
|
||||||
|
|
||||||
auto registers_global_initializer = ConstantPointerNull::get(IntegerType::getInt32PtrTy(getGlobalContext()));
|
auto registers_global_initializer = ConstantPointerNull::get(IntegerType::getInt32PtrTy(getGlobalContext()));
|
||||||
registers_global = new GlobalVariable(*module->Module(), registers_global_initializer->getType(),
|
registers_global = new GlobalVariable(*module->Module(), registers_global_initializer->getType(),
|
||||||
false, GlobalValue::ExternalLinkage, registers_global_initializer, "Registers");
|
false, GlobalValue::ExternalLinkage, registers_global_initializer, "Registers");
|
||||||
@ -24,11 +26,18 @@ void MachineState::GenerateGlobals()
|
|||||||
flags_global = new GlobalVariable(*module->Module(), flags_global_initializer->getType(),
|
flags_global = new GlobalVariable(*module->Module(), flags_global_initializer->getType(),
|
||||||
false, GlobalValue::ExternalLinkage, flags_global_initializer, "Flags");
|
false, GlobalValue::ExternalLinkage, flags_global_initializer, "Flags");
|
||||||
|
|
||||||
auto memory_read_32_signature = FunctionType::get(IntegerType::getInt32Ty(getGlobalContext()), IntegerType::getInt32Ty(getGlobalContext()), false);
|
auto memory_read_32_signature = FunctionType::get(ir_builder->getInt32Ty(), ir_builder->getInt32Ty(), false);
|
||||||
auto memory_read_32_ptr = PointerType::get(memory_read_32_signature, 0);
|
auto memory_read_32_ptr = PointerType::get(memory_read_32_signature, 0);
|
||||||
auto memory_read_32_initializer = ConstantPointerNull::get(memory_read_32_ptr);
|
auto memory_read_32_initializer = ConstantPointerNull::get(memory_read_32_ptr);
|
||||||
memory_read_32_global = new GlobalVariable(*module->Module(), memory_read_32_ptr,
|
memory_read_32_global = new GlobalVariable(*module->Module(), memory_read_32_ptr,
|
||||||
false, GlobalValue::ExternalLinkage, memory_read_32_initializer, "Memory::Read32");
|
false, GlobalValue::ExternalLinkage, memory_read_32_initializer, "Memory::Read32");
|
||||||
|
|
||||||
|
llvm::Type *memory_write_32_args[] = { ir_builder->getInt32Ty(), ir_builder->getInt32Ty() };
|
||||||
|
auto memory_write_32_signature = FunctionType::get(ir_builder->getVoidTy(), memory_write_32_args, false);
|
||||||
|
auto memory_write_32_ptr = PointerType::get(memory_write_32_signature, 0);
|
||||||
|
auto memory_write_32_initializer = ConstantPointerNull::get(memory_write_32_ptr);
|
||||||
|
memory_write_32_global = new GlobalVariable(*module->Module(), memory_write_32_ptr,
|
||||||
|
false, GlobalValue::ExternalLinkage, memory_write_32_initializer, "Memory::Write32");
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *MachineState::GetRegisterPtr(Register reg)
|
Value *MachineState::GetRegisterPtr(Register reg)
|
||||||
@ -50,8 +59,9 @@ Value *MachineState::GetRegisterPtr(Register reg)
|
|||||||
return module->IrBuilder()->CreateConstInBoundsGEP1_32(base, index);
|
return module->IrBuilder()->CreateConstInBoundsGEP1_32(base, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* MachineState::ReadRegiser(Register reg)
|
Value* MachineState::ReadRegiser(Register reg, bool allow_pc)
|
||||||
{
|
{
|
||||||
|
assert(allow_pc || reg != Register::PC);
|
||||||
auto load = module->IrBuilder()->CreateAlignedLoad(GetRegisterPtr(reg), 4);
|
auto load = module->IrBuilder()->CreateAlignedLoad(GetRegisterPtr(reg), 4);
|
||||||
module->GetTBAA()->TagRegister(load, reg);
|
module->GetTBAA()->TagRegister(load, reg);
|
||||||
return load;
|
return load;
|
||||||
@ -107,3 +117,15 @@ llvm::Value* MachineState::ReadMemory32(llvm::Value* address)
|
|||||||
module->GetTBAA()->TagMemory(call);
|
module->GetTBAA()->TagMemory(call);
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::Value* MachineState::WriteMemory32(llvm::Value* address, llvm::Value* value)
|
||||||
|
{
|
||||||
|
auto ir_builder = module->IrBuilder();
|
||||||
|
|
||||||
|
auto memory_write_32 = ir_builder->CreateLoad(memory_write_32_global);
|
||||||
|
module->GetTBAA()->TagConst(memory_write_32);
|
||||||
|
|
||||||
|
auto call = ir_builder->CreateCall2(memory_write_32, address, value);
|
||||||
|
module->GetTBAA()->TagMemory(call);
|
||||||
|
return value;
|
||||||
|
}
|
@ -20,10 +20,12 @@ public:
|
|||||||
MachineState(ModuleGen *module);
|
MachineState(ModuleGen *module);
|
||||||
|
|
||||||
void GenerateGlobals();
|
void GenerateGlobals();
|
||||||
llvm::Value *ReadRegiser(Register reg);
|
// allow_pc exists because most of the times reading the PC is not what the instruction meant
|
||||||
|
llvm::Value *ReadRegiser(Register reg, bool allow_pc = false);
|
||||||
llvm::Value *WriteRegiser(Register reg, llvm::Value *value);
|
llvm::Value *WriteRegiser(Register reg, llvm::Value *value);
|
||||||
llvm::Value* ConditionPassed(Condition cond);
|
llvm::Value* ConditionPassed(Condition cond);
|
||||||
llvm::Value* ReadMemory32(llvm::Value* address);
|
llvm::Value* ReadMemory32(llvm::Value* address);
|
||||||
|
llvm::Value* WriteMemory32(llvm::Value* address, llvm::Value* value);
|
||||||
private:
|
private:
|
||||||
// Returns the address of a register or a flag
|
// Returns the address of a register or a flag
|
||||||
llvm::Value *GetRegisterPtr(Register reg);
|
llvm::Value *GetRegisterPtr(Register reg);
|
||||||
@ -43,8 +45,14 @@ private:
|
|||||||
llvm::GlobalVariable *flags_global;
|
llvm::GlobalVariable *flags_global;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* u32 (u32) Memory::Read
|
* u32 (u32) Memory::Read32
|
||||||
* Reads the memory at address
|
* Reads the memory at address
|
||||||
*/
|
*/
|
||||||
llvm::GlobalVariable *memory_read_32_global;
|
llvm::GlobalVariable *memory_read_32_global;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void (u32, u32) Memory::Write32
|
||||||
|
* Writes the memory at address
|
||||||
|
*/
|
||||||
|
llvm::GlobalVariable *memory_write_32_global;
|
||||||
};
|
};
|
@ -204,7 +204,7 @@ void ModuleGen::GenerateCanRunFunction()
|
|||||||
auto basic_block = BasicBlock::Create(getGlobalContext(), "Entry", can_run_function);
|
auto basic_block = BasicBlock::Create(getGlobalContext(), "Entry", can_run_function);
|
||||||
|
|
||||||
ir_builder->SetInsertPoint(basic_block);
|
ir_builder->SetInsertPoint(basic_block);
|
||||||
auto block_address = ir_builder->CreateCall(get_block_address_function, machine->ReadRegiser(Register::PC));
|
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()))));
|
||||||
@ -232,7 +232,7 @@ void ModuleGen::GenerateRunFunction()
|
|||||||
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));
|
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())));
|
||||||
|
@ -122,8 +122,9 @@ void BinaryTranslationLoader::Load(FileUtil::IOFile& file)
|
|||||||
auto verify_ptr = static_cast<bool*>(g_dyld->getSymbolAddress("Verify"));
|
auto verify_ptr = static_cast<bool*>(g_dyld->getSymbolAddress("Verify"));
|
||||||
g_instruction_count = static_cast<uint32_t *>(g_dyld->getSymbolAddress("InstructionCount"));
|
g_instruction_count = static_cast<uint32_t *>(g_dyld->getSymbolAddress("InstructionCount"));
|
||||||
auto memory_read_32_ptr = static_cast<decltype(&Memory::Read32) *>(g_dyld->getSymbolAddress("Memory::Read32"));
|
auto memory_read_32_ptr = static_cast<decltype(&Memory::Read32) *>(g_dyld->getSymbolAddress("Memory::Read32"));
|
||||||
|
auto memory_write_32_ptr = static_cast<decltype(&Memory::Write32) *>(g_dyld->getSymbolAddress("Memory::Write32"));
|
||||||
|
|
||||||
if (!g_run_function || !g_can_run_function || !verify_ptr || !g_instruction_count || !memory_read_32_ptr)
|
if (!g_run_function || !g_can_run_function || !verify_ptr || !g_instruction_count || !memory_read_32_ptr || !memory_write_32_ptr)
|
||||||
{
|
{
|
||||||
LOG_WARNING(Loader, "Cannot load optimized file, missing critical function");
|
LOG_WARNING(Loader, "Cannot load optimized file, missing critical function");
|
||||||
return;
|
return;
|
||||||
@ -131,6 +132,7 @@ void BinaryTranslationLoader::Load(FileUtil::IOFile& file)
|
|||||||
|
|
||||||
g_verify = *verify_ptr;
|
g_verify = *verify_ptr;
|
||||||
*memory_read_32_ptr = &Memory::Read32;
|
*memory_read_32_ptr = &Memory::Read32;
|
||||||
|
*memory_write_32_ptr = &Memory::Write32;
|
||||||
|
|
||||||
g_enabled = true;
|
g_enabled = true;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user