mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-07-09 17:25:18 -06:00
SPU Precompilation: Add support for unaligned segments
This commit is contained in:
parent
8eaa3ec9a2
commit
5b41d5880d
@ -646,18 +646,32 @@ spu_cache::~spu_cache()
|
||||
|
||||
extern void utilize_spu_data_segment(u32 vaddr, const void* ls_data_vaddr, u32 size)
|
||||
{
|
||||
if (vaddr % 4)
|
||||
if (u32 rem = vaddr % 4)
|
||||
{
|
||||
return;
|
||||
// The remainder that it needs to be aligned up to the next DWORD
|
||||
rem = 4 - rem;
|
||||
|
||||
if (size < rem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vaddr += rem;
|
||||
ls_data_vaddr = reinterpret_cast<const char*>(ls_data_vaddr) + rem;
|
||||
size -= rem;
|
||||
}
|
||||
|
||||
size &= -4;
|
||||
|
||||
if (!size || vaddr + size > SPU_LS_SIZE)
|
||||
if (!size || vaddr >= SPU_LS_SIZE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Let SPU block search mistakes pass through
|
||||
// SPU code mining is too important
|
||||
size = std::min<u32>(SPU_LS_SIZE - vaddr, size);
|
||||
|
||||
if (!g_cfg.core.llvm_precompilation)
|
||||
{
|
||||
return;
|
||||
@ -2364,11 +2378,22 @@ std::vector<u32> spu_thread::discover_functions(u32 base_addr, std::span<const u
|
||||
// TODO: Does not detect jumptables or fixed-addr indirect calls
|
||||
const v128 brasl_mask = is_known_addr ? v128::from32p(0x62u << 23) : v128::from32p(umax);
|
||||
|
||||
for (u32 i = utils::align<u32>(base_addr, 0x10); i < std::min<u32>(base_addr + ::size32(ls), 0x3FFF0); i += 0x10)
|
||||
for (u32 i = base_addr, end_ls = std::min<u32>(base_addr + ::size32(ls), SPU_LS_SIZE); i < end_ls; i = utils::align<u32>(i + 1, 0x10))
|
||||
{
|
||||
// Search for BRSL LR and BRASL LR or BR
|
||||
// TODO: BISL
|
||||
const v128 inst = read_from_ptr<be_t<v128>>(ls, i - base_addr);
|
||||
be_t<v128> inst_be{};
|
||||
|
||||
if (end_ls - i < 16)
|
||||
{
|
||||
std::memcpy(&inst_be, ls.data() + (i - base_addr), end_ls - i);
|
||||
}
|
||||
else
|
||||
{
|
||||
inst_be = read_from_ptr<be_t<v128>>(ls, i - base_addr);
|
||||
}
|
||||
|
||||
const v128 inst = inst_be;
|
||||
const v128 cleared_i16 = gv_and32(inst, v128::from32p(std::rotl<u32>(~0xffff, 7)));
|
||||
const v128 eq_brsl = gv_eq32(cleared_i16, v128::from32p(0x66u << 23));
|
||||
const v128 eq_brasl = gv_eq32(cleared_i16, brasl_mask);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user