mirror of https://github.com/RPCS3/rpcs3.git
Compare commits
3 Commits
ed30669052
...
e85f96879c
Author | SHA1 | Date |
---|---|---|
Elad | e85f96879c | |
capriots | 66eae05e75 | |
Elad Ashkenazi | 660a37c7a0 |
|
@ -121,6 +121,7 @@ void AtracXdecDecoder::alloc_avcodec()
|
||||||
|
|
||||||
// Allows FFmpeg to output directly into guest memory
|
// Allows FFmpeg to output directly into guest memory
|
||||||
ctx->opaque = this;
|
ctx->opaque = this;
|
||||||
|
ctx->thread_type = FF_THREAD_SLICE; // Silences a warning by FFmpeg about requesting frame threading with a custom get_buffer2(). Default is FF_THREAD_FRAME & FF_THREAD_SLICE
|
||||||
ctx->get_buffer2 = [](AVCodecContext* s, AVFrame* frame, int /*flags*/) -> int
|
ctx->get_buffer2 = [](AVCodecContext* s, AVFrame* frame, int /*flags*/) -> int
|
||||||
{
|
{
|
||||||
for (s32 i = 0; i < frame->ch_layout.nb_channels; i++)
|
for (s32 i = 0; i < frame->ch_layout.nb_channels; i++)
|
||||||
|
|
|
@ -2112,6 +2112,138 @@ bool ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, const std::b
|
||||||
}
|
}
|
||||||
|
|
||||||
ppu_log.notice("Block analysis: %zu blocks (%zu enqueued)", funcs.size(), block_queue.size());
|
ppu_log.notice("Block analysis: %zu blocks (%zu enqueued)", funcs.size(), block_queue.size());
|
||||||
|
|
||||||
|
std::unordered_map<std::string_view, std::pair<u32, u32>> duplicate_data_map;
|
||||||
|
duplicate_map.clear();
|
||||||
|
|
||||||
|
for (auto& func : funcs)
|
||||||
|
{
|
||||||
|
if (func.size == 0 || func.size > 10000u)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& data = duplicate_data_map[std::string_view{get_ptr<char>(func.addr), func.size}];
|
||||||
|
|
||||||
|
const usz count = data.first;
|
||||||
|
|
||||||
|
if (!count)
|
||||||
|
{
|
||||||
|
data.first++;
|
||||||
|
data.second = func.addr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.second)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 1)
|
||||||
|
{
|
||||||
|
const u32 faddr = func.addr;
|
||||||
|
const u32 fend = func.addr + func.size;
|
||||||
|
|
||||||
|
bool fail = false;
|
||||||
|
|
||||||
|
//for (const auto [addr, size] : func.blocks)
|
||||||
|
const u32 addr = func.addr;
|
||||||
|
const u32 size = func.size;
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto i_ptr = ensure(get_ptr<u32>(addr));
|
||||||
|
|
||||||
|
for (u32 i = addr; i < fend; i += 4, i_ptr++)
|
||||||
|
{
|
||||||
|
/ const ppu_opcode_t op{*i_ptr};
|
||||||
|
const auto itype = s_ppu_itype.decode(op.opcode);
|
||||||
|
|
||||||
|
if (itype != ppu_itype::BC && itype != ppu_itype::B)
|
||||||
|
{
|
||||||
|
if (i == fend - 4)
|
||||||
|
{
|
||||||
|
if (!(itype & ppu_itype::branch))
|
||||||
|
{
|
||||||
|
// Inserts a branch to following code
|
||||||
|
fail = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!op.aa)
|
||||||
|
{
|
||||||
|
fail = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itype == ppu_itype::BC && (op.bo & 0x14) != 0x14)
|
||||||
|
{
|
||||||
|
if (i == fend - 4)
|
||||||
|
{
|
||||||
|
// Can branch to next
|
||||||
|
fail = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fail)
|
||||||
|
{
|
||||||
|
data.first = 1;
|
||||||
|
data.second = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.first++;
|
||||||
|
|
||||||
|
// Choose the lowest function as the source
|
||||||
|
data.second = std::min<u32>(data.second, func.addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
usz dups_count = 0;
|
||||||
|
|
||||||
|
for (auto& func : funcs)
|
||||||
|
{
|
||||||
|
if (func.size == 0 || func.size > 10000u)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto data = ::at32(duplicate_data_map, std::string_view{get_ptr<char>(func.addr), func.size});
|
||||||
|
|
||||||
|
if (data.first > 1)
|
||||||
|
{
|
||||||
|
duplicate_map[func.addr] = data.second;
|
||||||
|
|
||||||
|
for (const auto [addr, size] : func.blocks)
|
||||||
|
{
|
||||||
|
if (size == 0 || addr >= func.addr + func.size)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicate_map[addr] = data.second + (addr - func.addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (func.addr != data.second)
|
||||||
|
{
|
||||||
|
dups_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ppu_log.trace("Found PPU function duplicate: func 0x%x vs 0x%x (%d times) (size=%d)", func.addr, data.second, data.first, func.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ppu_log.success("Function duplication count: %d/%d (%g%)", dups_count, duplicate_data_map.size(), dups_count * 100.0 / duplicate_data_map.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@ struct ppu_module
|
||||||
std::vector<ppu_function> funcs{};
|
std::vector<ppu_function> funcs{};
|
||||||
std::deque<std::shared_ptr<void>> allocations;
|
std::deque<std::shared_ptr<void>> allocations;
|
||||||
std::map<u32, u32> addr_to_seg_index;
|
std::map<u32, u32> addr_to_seg_index;
|
||||||
|
std::unordered_map<u32, u32> duplicate_map;
|
||||||
|
|
||||||
// Copy info without functions
|
// Copy info without functions
|
||||||
void copy_part(const ppu_module& info)
|
void copy_part(const ppu_module& info)
|
||||||
|
@ -107,6 +108,7 @@ struct ppu_module
|
||||||
secs = info.secs;
|
secs = info.secs;
|
||||||
allocations = info.allocations;
|
allocations = info.allocations;
|
||||||
addr_to_seg_index = info.addr_to_seg_index;
|
addr_to_seg_index = info.addr_to_seg_index;
|
||||||
|
duplicate_map = info.duplicate_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool analyse(u32 lib_toc, u32 entry, u32 end, const std::basic_string<u32>& applied, const std::vector<u32>& exported_funcs = std::vector<u32>{}, std::function<bool()> check_aborted = {});
|
bool analyse(u32 lib_toc, u32 entry, u32 end, const std::basic_string<u32>& applied, const std::vector<u32>& exported_funcs = std::vector<u32>{}, std::function<bool()> check_aborted = {});
|
||||||
|
|
|
@ -3999,12 +3999,12 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
||||||
|
|
||||||
if (mself.read(hdr) && hdr.get_count(mself.size()))
|
if (mself.read(hdr) && hdr.get_count(mself.size()))
|
||||||
{
|
{
|
||||||
|
std::set<u64> offs;
|
||||||
|
|
||||||
for (u32 j = 0; j < hdr.count; j++)
|
for (u32 j = 0; j < hdr.count; j++)
|
||||||
{
|
{
|
||||||
mself_record rec{};
|
mself_record rec{};
|
||||||
|
|
||||||
std::set<u64> offs;
|
|
||||||
|
|
||||||
if (mself.read(rec) && rec.get_pos(mself.size()))
|
if (mself.read(rec) && rec.get_pos(mself.size()))
|
||||||
{
|
{
|
||||||
if (rec.size <= 0x20)
|
if (rec.size <= 0x20)
|
||||||
|
@ -4245,7 +4245,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
||||||
}
|
}
|
||||||
|
|
||||||
ppu_log.notice("Failed to precompile '%s' (prx: %s, ovl: %s): Attempting compilation as executable file", path, prx_err, ovl_err);
|
ppu_log.notice("Failed to precompile '%s' (prx: %s, ovl: %s): Attempting compilation as executable file", path, prx_err, ovl_err);
|
||||||
possible_exec_file_paths.push(path, offset, file_size);
|
possible_exec_file_paths.push(file_queue[func_i]);
|
||||||
inc_fdone = 0;
|
inc_fdone = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4751,8 +4751,15 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size)
|
||||||
// Copy block or function entry
|
// Copy block or function entry
|
||||||
ppu_function& entry = part.funcs.emplace_back(func);
|
ppu_function& entry = part.funcs.emplace_back(func);
|
||||||
|
|
||||||
|
u32 og_func = entry.addr;
|
||||||
|
|
||||||
|
if (auto it = info.duplicate_map.find(entry.addr); it != info.duplicate_map.end())
|
||||||
|
{
|
||||||
|
og_func = it->second;
|
||||||
|
}
|
||||||
|
|
||||||
// Fixup some information
|
// Fixup some information
|
||||||
entry.name = fmt::format("__0x%x", entry.addr - reloc);
|
entry.name = fmt::format("__0x%x", og_func - reloc);
|
||||||
|
|
||||||
if (has_mfvscr && g_cfg.core.ppu_set_sat_bit)
|
if (has_mfvscr && g_cfg.core.ppu_set_sat_bit)
|
||||||
{
|
{
|
||||||
|
@ -4919,7 +4926,7 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size)
|
||||||
settings += ppu_settings::contains_symbol_resolver; // Avoid invalidating all modules for this purpose
|
settings += ppu_settings::contains_symbol_resolver; // Avoid invalidating all modules for this purpose
|
||||||
|
|
||||||
// Write version, hash, CPU, settings
|
// Write version, hash, CPU, settings
|
||||||
fmt::append(obj_name, "v6-kusa-%s-%s-%s.obj", fmt::base57(output, 16), fmt::base57(settings), jit_compiler::cpu(g_cfg.core.llvm_cpu));
|
fmt::append(obj_name, "v7-kusa-%s-%s-%s.obj", fmt::base57(output, 16), fmt::base57(settings), jit_compiler::cpu(g_cfg.core.llvm_cpu));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu ? cpu->state.all_of(cpu_flag::exit) : Emu.IsStopped())
|
if (cpu ? cpu->state.all_of(cpu_flag::exit) : Emu.IsStopped())
|
||||||
|
@ -5183,6 +5190,9 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Find a BLR-only function in order to copy it to all BLRs (some games need it)
|
// Find a BLR-only function in order to copy it to all BLRs (some games need it)
|
||||||
|
bool early_exit = false;
|
||||||
|
|
||||||
|
// Get and install function addresses
|
||||||
for (const auto& func : info.funcs)
|
for (const auto& func : info.funcs)
|
||||||
{
|
{
|
||||||
if (func.size == 4 && *info.get_ptr<u32>(func.addr) == ppu_instructions::BLR())
|
if (func.size == 4 && *info.get_ptr<u32>(func.addr) == ppu_instructions::BLR())
|
||||||
|
@ -5253,6 +5263,11 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
|
||||||
{
|
{
|
||||||
if (func.size)
|
if (func.size)
|
||||||
{
|
{
|
||||||
|
if (auto it = module_part.duplicate_map.find(func.addr); it != module_part.duplicate_map.end() && it->second != it->first)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const auto f = cast<Function>(_module->getOrInsertFunction(func.name, _func).getCallee());
|
const auto f = cast<Function>(_module->getOrInsertFunction(func.name, _func).getCallee());
|
||||||
f->setCallingConv(CallingConv::GHC);
|
f->setCallingConv(CallingConv::GHC);
|
||||||
f->addParamAttr(1, llvm::Attribute::NoAlias);
|
f->addParamAttr(1, llvm::Attribute::NoAlias);
|
||||||
|
@ -5326,6 +5341,15 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
|
||||||
|
|
||||||
if (module_part.funcs[fi].size)
|
if (module_part.funcs[fi].size)
|
||||||
{
|
{
|
||||||
|
const u32 faddr = module_part.funcs[fi].addr;
|
||||||
|
auto it = module_part.duplicate_map.find(faddr);
|
||||||
|
|
||||||
|
if (it != module_part.duplicate_map.end() && it->second != faddr)
|
||||||
|
{
|
||||||
|
ppu_log.trace("LLVM: Function 0x%x was skipped (duplicate)", faddr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Translate
|
// Translate
|
||||||
if (const auto func = translator.Translate(module_part.funcs[fi]))
|
if (const auto func = translator.Translate(module_part.funcs[fi]))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue