Implemented some FP instructions but did not add support for updating the FPSCR. Many misc changes.

This commit is contained in:
S Gopal Rajagopal 2014-09-18 16:59:49 +05:30
parent ccc37b5dc5
commit e687a91243
2 changed files with 278 additions and 90 deletions

View File

@ -84,21 +84,15 @@ PPULLVMRecompiler::~PPULLVMRecompiler() {
log_file << i->first << " = " << i->second << "\n";
}
std::set<std::pair<u64, u32>> sorted_block_info;
for (auto i = m_address_to_compiled_block_map.begin(); i != m_address_to_compiled_block_map.end(); i++) {
sorted_block_info.insert(std::make_pair(~i->second.request_count, i->first));
}
log_file << "\nBlock Information:\n";
for (auto i = sorted_block_info.begin(); i != sorted_block_info.end(); i++) {
auto j = m_address_to_compiled_block_map.find(i->second);
log_file << fmt::Format("%s: Size = %u bytes, Times requested = %llu\n", j->second.llvm_function->getName().str().c_str(), j->second.size, j->second.request_count);
for (auto i = m_compiled_blocks.begin(); i != m_compiled_blocks.end(); i++) {
log_file << fmt::Format("\n%s: Size = %u bytes, Reference count = %llu\n", i->second.llvm_function->getName().str().c_str(), i->second.size, i->second.reference_count);
log_file << "\nDisassembly:\n";
for (size_t pc = 0; pc < j->second.size;) {
log_file << "Disassembly:\n";
for (size_t pc = 0; pc < i->second.size;) {
char str[1024];
auto size = LLVMDisasmInstruction(m_disassembler, (uint8_t *)j->second.block + pc, j->second.size - pc, (uint64_t)((uint8_t *)j->second.block + pc), str, sizeof(str));
auto size = LLVMDisasmInstruction(m_disassembler, (uint8_t *)i->second.block + pc, i->second.size - pc, (uint64_t)((uint8_t *)i->second.block + pc), str, sizeof(str));
log_file << str << '\n';
pc += size;
}
@ -113,19 +107,33 @@ PPULLVMRecompiler::~PPULLVMRecompiler() {
delete m_llvm_context;
}
PPULLVMRecompiler::CompiledBlock PPULLVMRecompiler::GetCompiledBlock(u32 address) {
{
std::lock_guard<std::mutex> lock(m_address_to_compiled_block_map_mutex);
auto i = m_address_to_compiled_block_map.find(address);
if (i != m_address_to_compiled_block_map.end()) {
i->second.request_count++;
return i->second.block;
}
PPULLVMRecompiler::CompiledBlockInfo PPULLVMRecompiler::GetCompiledBlock(u32 address) {
static CompiledBlockInfo unknown_block_info = {0};
std::lock_guard<std::mutex> lock(m_compiled_blocks_mutex);
auto compiled_block = m_compiled_blocks.lower_bound(std::make_pair(address, 0));
if (compiled_block != m_compiled_blocks.end() && compiled_block->first.first == address) {
compiled_block->second.reference_count++;
return compiled_block->second;
}
return unknown_block_info;
}
void PPULLVMRecompiler::ReleaseCompiledBlock(u32 address, u32 revision) {
std::lock_guard<std::mutex> lock(m_compiled_blocks_mutex);
auto compiled_block = m_compiled_blocks.find(std::make_pair(address, revision));
if (compiled_block != m_compiled_blocks.end()) {
compiled_block->second.reference_count--;
}
}
void PPULLVMRecompiler::RequestCompilation(u32 address) {
{
std::lock_guard<std::mutex> lock(m_pending_blocks_set_mutex);
m_pending_blocks_set.insert(address);
std::lock_guard<std::mutex> lock(m_pending_compilation_blocks_mutex);
m_pending_compilation_blocks.insert(address);
}
if (!IsAlive()) {
@ -133,7 +141,6 @@ PPULLVMRecompiler::CompiledBlock PPULLVMRecompiler::GetCompiledBlock(u32 address
}
Notify();
return nullptr;
}
void PPULLVMRecompiler::Task() {
@ -146,12 +153,12 @@ void PPULLVMRecompiler::Task() {
u32 address;
{
std::lock_guard<std::mutex> lock(m_pending_blocks_set_mutex);
std::lock_guard<std::mutex> lock(m_pending_compilation_blocks_mutex);
auto i = m_pending_blocks_set.begin();
if (i != m_pending_blocks_set.end()) {
auto i = m_pending_compilation_blocks.begin();
if (i != m_pending_compilation_blocks.end()) {
address = *i;
m_pending_blocks_set.erase(i);
m_pending_compilation_blocks.erase(i);
} else {
break;
}
@ -1536,7 +1543,10 @@ void PPULLVMRecompiler::MULHWU(u32 rd, u32 ra, u32 rb, bool rc) {
}
void PPULLVMRecompiler::MFOCRF(u32 a, u32 rd, u32 crm) {
InterpreterCall("MFOCRF", &PPUInterpreter::MFOCRF, a, rd, crm);
auto cr_i32 = GetCr();
auto cr_i64 = m_ir_builder->CreateZExt(cr_i32, m_ir_builder->getInt64Ty());
SetGpr(rd, cr_i64);
//InterpreterCall("MFOCRF", &PPUInterpreter::MFOCRF, a, rd, crm);
}
void PPULLVMRecompiler::LWARX(u32 rd, u32 ra, u32 rb) {
@ -1785,7 +1795,24 @@ void PPULLVMRecompiler::ADDE(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) {
}
void PPULLVMRecompiler::MTOCRF(u32 l, u32 crm, u32 rs) {
InterpreterCall("MTOCRF", &PPUInterpreter::MTOCRF, l, crm, rs);
auto rs_i32 = GetGpr(rs, 32);
auto cr_i32 = GetCr();
u32 mask = 0;
for (u32 i = 0; i < 8; i++) {
if (crm & (1 << i)) {
mask |= 0xF << ((7 - i) * 4);
if (l) {
break;
}
}
}
cr_i32 = m_ir_builder->CreateAnd(cr_i32, ~mask);
rs_i32 = m_ir_builder->CreateAnd(rs_i32, ~mask);
cr_i32 = m_ir_builder->CreateOr(cr_i32, rs_i32);
SetCr(cr_i32);
//InterpreterCall("MTOCRF", &PPUInterpreter::MTOCRF, l, crm, rs);
}
void PPULLVMRecompiler::STDX(u32 rs, u32 ra, u32 rb) {
@ -1843,7 +1870,18 @@ void PPULLVMRecompiler::STVEWX(u32 vs, u32 ra, u32 rb) {
}
void PPULLVMRecompiler::ADDZE(u32 rd, u32 ra, u32 oe, bool rc) {
InterpreterCall("ADDZE", &PPUInterpreter::ADDZE, rd, ra, oe, rc);
auto ra_i64 = GetGpr(ra);
auto ca_i64 = GetXerCa();
auto res_s = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::sadd_with_overflow, {m_ir_builder->getInt64Ty()}), ra_i64, ca_i64);
auto sum_i64 = m_ir_builder->CreateExtractValue(res_s, {0});
auto carry_i1 = m_ir_builder->CreateExtractValue(res_s, {1});
SetGpr(rd, sum_i64);
SetXerCa(carry_i1);
if (rc) {
SetCrFieldSignedCmp(0, sum_i64, m_ir_builder->getInt64(0));
}
//InterpreterCall("ADDZE", &PPUInterpreter::ADDZE, rd, ra, oe, rc);
}
void PPULLVMRecompiler::SUBFZE(u32 rd, u32 ra, u32 oe, bool rc) {
@ -2418,14 +2456,34 @@ void PPULLVMRecompiler::DSS(u32 strm, u32 a) {
}
void PPULLVMRecompiler::SRAWI(u32 ra, u32 rs, u32 sh, bool rc) {
//auto rs_i32 = GetGpr(rs, 32);
//auto res_i32 = m_ir_builder->CreateAShr(rs_i32, sh);
//auto res_i64 = m_ir_builder->CreateSExt(rs_i32, m_ir_builder->getInt64Ty());
//SetGpr(ra, res_i64);
//if (rc) {
// SetCrFieldSignedCmp(0, res_i64, m_ir_builder->getInt64(0));
//}
// TODO: Set XER.CA
InterpreterCall("SRAWI", &PPUInterpreter::SRAWI, ra, rs, sh, rc);
}
void PPULLVMRecompiler::SRADI1(u32 ra, u32 rs, u32 sh, bool rc) {
//auto rs_i64 = GetGpr(rs);
//auto res_i64 = m_ir_builder->CreateAShr(rs_i64, sh);
//SetGpr(ra, res_i64);
//if (rc) {
// SetCrFieldSignedCmp(0, res_i64, m_ir_builder->getInt64(0));
//}
// TODO: Set XER.CA
InterpreterCall("SRADI1", &PPUInterpreter::SRADI1, ra, rs, sh, rc);
}
void PPULLVMRecompiler::SRADI2(u32 ra, u32 rs, u32 sh, bool rc) {
//SRADI1(ra, rs, sh, rc);
InterpreterCall("SRADI2", &PPUInterpreter::SRADI2, ra, rs, sh, rc);
}
@ -2805,7 +2863,13 @@ void PPULLVMRecompiler::LWA(u32 rd, u32 ra, s32 ds) {
}
void PPULLVMRecompiler::FDIVS(u32 frd, u32 fra, u32 frb, bool rc) {
InterpreterCall("FDIVS", &PPUInterpreter::FDIVS, frd, fra, frb, rc);
auto ra_f32 = GetFpr(fra, 32);
auto rb_f32 = GetFpr(frb, 32);
auto res_f32 = m_ir_builder->CreateFDiv(ra_f32, rb_f32);
SetFpr(frd, res_f32);
// TODO: Set flags
//InterpreterCall("FDIVS", &PPUInterpreter::FDIVS, frd, fra, frb, rc);
}
void PPULLVMRecompiler::FSUBS(u32 frd, u32 fra, u32 frb, bool rc) {
@ -2813,7 +2877,13 @@ void PPULLVMRecompiler::FSUBS(u32 frd, u32 fra, u32 frb, bool rc) {
}
void PPULLVMRecompiler::FADDS(u32 frd, u32 fra, u32 frb, bool rc) {
InterpreterCall("FADDS", &PPUInterpreter::FADDS, frd, fra, frb, rc);
auto ra_f32 = GetFpr(fra, 32);
auto rb_f32 = GetFpr(frb, 32);
auto res_f32 = m_ir_builder->CreateFAdd(ra_f32, rb_f32);
SetFpr(frd, res_f32);
// TODO: Set flags
//InterpreterCall("FADDS", &PPUInterpreter::FADDS, frd, fra, frb, rc);
}
void PPULLVMRecompiler::FSQRTS(u32 frd, u32 frb, bool rc) {
@ -2825,14 +2895,35 @@ void PPULLVMRecompiler::FRES(u32 frd, u32 frb, bool rc) {
}
void PPULLVMRecompiler::FMULS(u32 frd, u32 fra, u32 frc, bool rc) {
InterpreterCall("FMULS", &PPUInterpreter::FMULS, frd, fra, frc, rc);
auto ra_f32 = GetFpr(fra, 32);
auto rc_f32 = GetFpr(frc, 32);
auto res_f32 = m_ir_builder->CreateFMul(ra_f32, rc_f32);
SetFpr(frd, res_f32);
// TODO: Set flags
//InterpreterCall("FMULS", &PPUInterpreter::FMULS, frd, fra, frc, rc);
}
void PPULLVMRecompiler::FMADDS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) {
InterpreterCall("FMADDS", &PPUInterpreter::FMADDS, frd, fra, frc, frb, rc);
auto ra_f64 = GetFpr(fra);
auto rb_f64 = GetFpr(frb);
auto rc_f64 = GetFpr(frc);
auto res_f64 = m_ir_builder->CreateCall3(Intrinsic::getDeclaration(m_module, Intrinsic::fma, {m_ir_builder->getDoubleTy()}), ra_f64, rc_f64, rb_f64);
SetFpr(frd, res_f64);
// TODO: Set flags
//InterpreterCall("FMADDS", &PPUInterpreter::FMADDS, frd, fra, frc, frb, rc);
}
void PPULLVMRecompiler::FMSUBS(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) {
//auto ra_f64 = GetFpr(fra);
//auto rb_f64 = GetFpr(frb);
//auto rc_f64 = GetFpr(frc);
//rb_f64 = m_ir_builder->CreateNeg(rb_f64);
//auto res_f64 = m_ir_builder->CreateCall3(Intrinsic::getDeclaration(m_module, Intrinsic::fma, {m_ir_builder->getDoubleTy()}), ra_f64, rc_f64, rb_f64);
//SetFpr(frd, res_f64);
// TODO: Set flags
InterpreterCall("FMSUBS", &PPUInterpreter::FMSUBS, frd, fra, frc, frb, rc);
}
@ -2894,7 +2985,11 @@ void PPULLVMRecompiler::FCMPU(u32 crfd, u32 fra, u32 frb) {
}
void PPULLVMRecompiler::FRSP(u32 frd, u32 frb, bool rc) {
InterpreterCall("FRSP", &PPUInterpreter::FRSP, frd, frb, rc);
auto rb_f64 = GetFpr(frb);
SetFpr(frd, rb_f64);
// TODO: Set flags
//InterpreterCall("FRSP", &PPUInterpreter::FRSP, frd, frb, rc);
}
void PPULLVMRecompiler::FCTIW(u32 frd, u32 frb, bool rc) {
@ -2906,21 +3001,33 @@ void PPULLVMRecompiler::FCTIWZ(u32 frd, u32 frb, bool rc) {
}
void PPULLVMRecompiler::FDIV(u32 frd, u32 fra, u32 frb, bool rc) {
InterpreterCall("FDIV", &PPUInterpreter::FDIV, frd, fra, frb, rc);
auto ra_f64 = GetFpr(fra);
auto rb_f64 = GetFpr(frb);
auto res_f64 = m_ir_builder->CreateFDiv(ra_f64, rb_f64);
SetFpr(frd, res_f64);
// TODO: Set flags
//InterpreterCall("FDIV", &PPUInterpreter::FDIV, frd, fra, frb, rc);
}
void PPULLVMRecompiler::FSUB(u32 frd, u32 fra, u32 frb, bool rc) {
InterpreterCall("FSUB", &PPUInterpreter::FSUB, frd, fra, frb, rc);
auto ra_f64 = GetFpr(fra);
auto rb_f64 = GetFpr(frb);
auto res_f64 = m_ir_builder->CreateFSub(ra_f64, rb_f64);
SetFpr(frd, res_f64);
// TODO: Set flags
//InterpreterCall("FSUB", &PPUInterpreter::FSUB, frd, fra, frb, rc);
}
void PPULLVMRecompiler::FADD(u32 frd, u32 fra, u32 frb, bool rc) {
//auto ra_f64 = GetFpr(fra);
//auto rb_f64 = GetFpr(frb);
//auto res_f64 = m_ir_builder->CreateFAdd(ra_f64, rb_f64);
//SetFpr(frd, res_f64);
auto ra_f64 = GetFpr(fra);
auto rb_f64 = GetFpr(frb);
auto res_f64 = m_ir_builder->CreateFAdd(ra_f64, rb_f64);
SetFpr(frd, res_f64);
// TODO: Set FPRF
InterpreterCall("FADD", &PPUInterpreter::FADD, frd, fra, frb, rc);
// TODO: Set flags
//InterpreterCall("FADD", &PPUInterpreter::FADD, frd, fra, frb, rc);
}
void PPULLVMRecompiler::FSQRT(u32 frd, u32 frb, bool rc) {
@ -2932,7 +3039,13 @@ void PPULLVMRecompiler::FSEL(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) {
}
void PPULLVMRecompiler::FMUL(u32 frd, u32 fra, u32 frc, bool rc) {
InterpreterCall("FMUL", &PPUInterpreter::FMUL, frd, fra, frc, rc);
auto ra_f64 = GetFpr(fra);
auto rc_f64 = GetFpr(frc);
auto res_f64 = m_ir_builder->CreateFMul(ra_f64, rc_f64);
SetFpr(frd, res_f64);
// TODO: Set flags
//InterpreterCall("FMUL", &PPUInterpreter::FMUL, frd, fra, frc, rc);
}
void PPULLVMRecompiler::FRSQRTE(u32 frd, u32 frb, bool rc) {
@ -2940,11 +3053,26 @@ void PPULLVMRecompiler::FRSQRTE(u32 frd, u32 frb, bool rc) {
}
void PPULLVMRecompiler::FMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) {
//auto ra_f64 = GetFpr(fra);
//auto rb_f64 = GetFpr(frb);
//auto rc_f64 = GetFpr(frc);
//rb_f64 = m_ir_builder->CreateNeg(rb_f64);
//auto res_f64 = m_ir_builder->CreateCall3(Intrinsic::getDeclaration(m_module, Intrinsic::fma, {m_ir_builder->getDoubleTy()}), ra_f64, rc_f64, rb_f64);
//SetFpr(frd, res_f64);
// TODO: Set flags
InterpreterCall("FMSUB", &PPUInterpreter::FMSUB, frd, fra, frc, frb, rc);
}
void PPULLVMRecompiler::FMADD(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) {
InterpreterCall("FMADD", &PPUInterpreter::FMADD, frd, fra, frc, frb, rc);
auto ra_f64 = GetFpr(fra);
auto rb_f64 = GetFpr(frb);
auto rc_f64 = GetFpr(frc);
auto res_f64 = m_ir_builder->CreateCall3(Intrinsic::getDeclaration(m_module, Intrinsic::fma, {m_ir_builder->getDoubleTy()}), ra_f64, rc_f64, rb_f64);
SetFpr(frd, res_f64);
// TODO: Set flags
//InterpreterCall("FMADD", &PPUInterpreter::FMADD, frd, fra, frc, frb, rc);
}
void PPULLVMRecompiler::FNMSUB(u32 frd, u32 fra, u32 frc, u32 frb, bool rc) {
@ -2960,11 +3088,18 @@ void PPULLVMRecompiler::FCMPO(u32 crfd, u32 fra, u32 frb) {
}
void PPULLVMRecompiler::FNEG(u32 frd, u32 frb, bool rc) {
//auto rb_f64 = GetFpr(frb);
//rb_f64 = m_ir_builder->CreateSub(ConstantFP::getZeroValueForNegation(rb_f64->getType()), rb_f64);
//SetGpr(frd, rb_f64);
// TODO: Set flags
InterpreterCall("FNEG", &PPUInterpreter::FNEG, frd, frb, rc);
}
void PPULLVMRecompiler::FMR(u32 frd, u32 frb, bool rc) {
InterpreterCall("FMR", &PPUInterpreter::FMR, frd, frb, rc);
SetFpr(frd, GetFpr(frb));
// TODO: Set flags
//InterpreterCall("FMR", &PPUInterpreter::FMR, frd, frb, rc);
}
void PPULLVMRecompiler::FNABS(u32 frd, u32 frb, bool rc) {
@ -2984,7 +3119,12 @@ void PPULLVMRecompiler::FCTIDZ(u32 frd, u32 frb, bool rc) {
}
void PPULLVMRecompiler::FCFID(u32 frd, u32 frb, bool rc) {
InterpreterCall("FCFID", &PPUInterpreter::FCFID, frd, frb, rc);
auto rb_i64 = GetFpr(frb, 64, true);
auto res_f64 = m_ir_builder->CreateSIToFP(rb_i64, m_ir_builder->getDoubleTy());
SetFpr(frd, res_f64);
// TODO: Set flag
//InterpreterCall("FCFID", &PPUInterpreter::FCFID, frd, frb, rc);
}
void PPULLVMRecompiler::UNK(const u32 code, const u32 opcode, const u32 gcode) {
@ -3028,13 +3168,15 @@ void PPULLVMRecompiler::Compile(u32 address) {
m_execution_engine->runJITOnFunction(m_function, &mci);
CompiledBlockInfo block_info;
block_info.block_address = address;
block_info.revision = 0xFFFFFFFF;
block_info.block = (CompiledBlock)mci.address();
block_info.request_count = 0;
block_info.reference_count = 0;
block_info.size = mci.size();
block_info.llvm_function = m_function;
{
std::lock_guard<std::mutex> lock(m_address_to_compiled_block_map_mutex);
m_address_to_compiled_block_map[address] = block_info;
std::lock_guard<std::mutex> lock(m_compiled_blocks_mutex);
m_compiled_blocks[std::make_pair(address, block_info.revision)] = block_info;
}
}
@ -3313,8 +3455,9 @@ void PPULLVMRecompiler::SetUsprg0(Value * val_x64) {
m_ir_builder->CreateStore(val_i64, usprg0_i64_ptr);
}
Value * PPULLVMRecompiler::GetFpr(u32 r, u32 bits) {
Value * PPULLVMRecompiler::GetFpr(u32 r, u32 bits, bool as_int) {
auto r_i8_ptr = m_ir_builder->CreateConstGEP1_32(GetPPUState(), (unsigned int)offsetof(PPUThread, FPR[r]));
if (!as_int) {
auto r_f64_ptr = m_ir_builder->CreateBitCast(r_i8_ptr, m_ir_builder->getDoubleTy()->getPointerTo());
auto r_f64 = m_ir_builder->CreateLoad(r_f64_ptr);
if (bits == 32) {
@ -3322,6 +3465,15 @@ Value * PPULLVMRecompiler::GetFpr(u32 r, u32 bits) {
} else {
return r_f64;
}
} else {
auto r_i64_ptr = m_ir_builder->CreateBitCast(r_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
auto r_i64 = m_ir_builder->CreateLoad(r_i64_ptr);
if (bits == 32) {
return m_ir_builder->CreateTrunc(r_i64, m_ir_builder->getInt32Ty());
} else {
return r_i64;
}
}
}
void PPULLVMRecompiler::SetFpr(u32 r, Value * val) {
@ -3560,15 +3712,31 @@ PPULLVMEmulator::~PPULLVMEmulator() {
u8 PPULLVMEmulator::DecodeMemory(const u32 address) {
static u32 last_instr_address = 0;
PPULLVMRecompiler::CompiledBlock compiled_block = nullptr;
auto compiled_block = m_compiled_blocks.find(address);
if (compiled_block == m_compiled_blocks.end()) {
auto compiled_block_info = s_recompiler->GetCompiledBlock(address);
if (compiled_block_info.block) {
compiled_block = m_compiled_blocks.insert(m_compiled_blocks.end(), std::make_pair(address, std::make_pair(compiled_block_info.block, compiled_block_info.revision)));
m_pending_compilation_blocks.erase(address);
} else {
if (address != (last_instr_address + 4)) {
compiled_block = s_recompiler->GetCompiledBlock(address);
auto pending_compilation_block = m_pending_compilation_blocks.find(address);
if (pending_compilation_block != m_pending_compilation_blocks.end()) {
pending_compilation_block->second++;
if ((pending_compilation_block->second % 1000) == 0) {
s_recompiler->RequestCompilation(address);
}
} else {
m_pending_compilation_blocks[address] = 0;
}
}
}
}
last_instr_address = address;
if (compiled_block) {
compiled_block(&m_ppu, (u64)Memory.GetBaseAddr(), m_interpreter);
if (compiled_block != m_compiled_blocks.end()) {
compiled_block->second.first(&m_ppu, (u64)Memory.GetBaseAddr(), m_interpreter);
return 0;
} else {
return m_decoder.DecodeMemory(address);

View File

@ -19,6 +19,26 @@ class PPULLVMRecompiler : public ThreadBase, protected PPUOpcodes, protected PPC
public:
typedef void(*CompiledBlock)(PPUThread * ppu_state, u64 base_address, PPUInterpreter * interpreter);
struct CompiledBlockInfo {
/// Address of the block
u32 block_address;
/// The version of the block
u32 revision;
/// Pointer to the block
CompiledBlock block;
/// Size of the compiled block
size_t size;
/// Reference count for the block
u64 reference_count;
/// LLVM function for this block
llvm::Function * llvm_function;
};
PPULLVMRecompiler();
PPULLVMRecompiler(const PPULLVMRecompiler & other) = delete;
@ -29,8 +49,14 @@ public:
PPULLVMRecompiler & operator = (const PPULLVMRecompiler & other) = delete;
PPULLVMRecompiler & operator = (PPULLVMRecompiler && other) = delete;
/// Get a pointer to a compiled block
CompiledBlock GetCompiledBlock(u32 address);
/// Get a compiled block
CompiledBlockInfo GetCompiledBlock(u32 address);
/// Release a compiled block
void ReleaseCompiledBlock(u32 address, u32 revision);
/// Request a block to be compiled
void RequestCompilation(u32 address);
/// Execute all tests
void RunAllTests(PPUThread * ppu_state, u64 base_address, PPUInterpreter * interpreter);
@ -441,32 +467,18 @@ protected:
void UNK(const u32 code, const u32 opcode, const u32 gcode) override;
private:
struct CompiledBlockInfo {
/// Pointer to the block
CompiledBlock block;
/// Mutex for accessing m_compiled_blocks
std::mutex m_compiled_blocks_mutex;
/// Size of the compiled block
size_t size;
/// Blocks that have been compiled
/// Key is block address
std::map<std::pair<u32, u32>, CompiledBlockInfo> m_compiled_blocks;
/// Number of times this block was requested
u64 request_count;
/// Mutex for accessing m_pending_compilation_blocks;
std::mutex m_pending_compilation_blocks_mutex;
/// LLVM function for this block
llvm::Function * llvm_function;
};
/// Mutex for accessing m_address_to_compiled_block_map
/// TODO: Use a RW lock instead of mutex
std::mutex m_address_to_compiled_block_map_mutex;
/// Map from address to compiled block
std::map<u32, CompiledBlockInfo> m_address_to_compiled_block_map;
/// Mutex for accessing m_pending_blocks_set;
std::mutex m_pending_blocks_set_mutex;
/// Set of blocks pending compilation
std::set<u32> m_pending_blocks_set;
/// Blocks pending compilation
std::set<u32> m_pending_compilation_blocks;
/// LLVM context
llvm::LLVMContext * m_llvm_context;
@ -609,7 +621,7 @@ private:
void SetUsprg0(llvm::Value * val_x64);
/// Get FPR
llvm::Value * GetFpr(u32 r, u32 bits = 64);
llvm::Value * GetFpr(u32 r, u32 bits = 64, bool as_int = false);
/// Set FPR
void SetFpr(u32 r, llvm::Value * val);
@ -693,6 +705,14 @@ private:
/// PPU instruction Decoder
PPUDecoder m_decoder;
/// Compiled blocks
/// Key is block address.
std::unordered_map<u32, std::pair<PPULLVMRecompiler::CompiledBlock, u32>> m_compiled_blocks;
/// Uncompiled blocks
/// Key is block address
std::unordered_map<u32, u64> m_pending_compilation_blocks;
/// Number of instances of this class
static u32 s_num_instances;