mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-22 12:35:21 +00:00
Insignificant changes
This commit is contained in:
parent
be4e85f0f2
commit
88476fe698
6 changed files with 672 additions and 597 deletions
|
@ -666,6 +666,9 @@ namespace PPU_instr
|
|||
static auto BCTR = std::bind(BCCTR, 0x10 | 0x04, 0, 0, 0);
|
||||
static auto BCTRL = std::bind(BCCTR, 0x10 | 0x04, 0, 0, 1);
|
||||
static auto MTCTR = std::bind(MTSPR, (0x1 << 5) | 0x8, std::placeholders::_1);
|
||||
|
||||
static inline u32 BNE(s32 imm) { return BC(4, 30, imm, 0, 0); }
|
||||
static inline u32 BEQ(s32 imm) { return BC(12, 30, imm, 0, 0); }
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -115,8 +115,6 @@ enum
|
|||
|
||||
struct g_imm_table_struct
|
||||
{
|
||||
//u16 cntb_table[65536];
|
||||
|
||||
__m128i fsmb_table[65536];
|
||||
__m128i fsmh_table[256];
|
||||
__m128i fsm_table[16];
|
||||
|
@ -127,20 +125,8 @@ struct g_imm_table_struct
|
|||
|
||||
g_imm_table_struct()
|
||||
{
|
||||
/*static_assert(offsetof(g_imm_table_struct, cntb_table) == 0, "offsetof(cntb_table) != 0");
|
||||
for (u32 i = 0; i < sizeof(cntb_table) / sizeof(cntb_table[0]); i++)
|
||||
{
|
||||
u32 cnt_low = 0, cnt_high = 0;
|
||||
for (u32 j = 0; j < 8; j++)
|
||||
{
|
||||
cnt_low += (i >> j) & 1;
|
||||
cnt_high += (i >> (j + 8)) & 1;
|
||||
}
|
||||
cntb_table[i] = (cnt_high << 8) | cnt_low;
|
||||
}*/
|
||||
for (u32 i = 0; i < sizeof(fsm_table) / sizeof(fsm_table[0]); i++)
|
||||
{
|
||||
|
||||
for (u32 j = 0; j < 4; j++) mmToU32Ptr(fsm_table[i])[j] = (i & (1 << j)) ? ~0 : 0;
|
||||
}
|
||||
for (u32 i = 0; i < sizeof(fsmh_table) / sizeof(fsmh_table[0]); i++)
|
||||
|
|
|
@ -30,7 +30,7 @@ u32 add_ppu_func_sub(StaticFunc func)
|
|||
return func.index;
|
||||
}
|
||||
|
||||
u32 add_ppu_func_sub(const char group[8], const u64 ops[], const char* name, Module* module, ppu_func_caller func)
|
||||
u32 add_ppu_func_sub(const char group[8], const SearchPatternEntry ops[], const size_t count, const char* name, Module* module, ppu_func_caller func)
|
||||
{
|
||||
char group_name[9] = {};
|
||||
|
||||
|
@ -45,13 +45,14 @@ u32 add_ppu_func_sub(const char group[8], const u64 ops[], const char* name, Mod
|
|||
sf.group = *(u64*)group_name;
|
||||
sf.found = 0;
|
||||
|
||||
// TODO: check for self-inclusions, use CRC
|
||||
for (u32 i = 0; ops[i]; i++)
|
||||
for (u32 i = 0; i < count; i++)
|
||||
{
|
||||
SFuncOp op;
|
||||
op.mask = re32((u32)(ops[i] >> 32));
|
||||
op.crc = re32((u32)(ops[i]));
|
||||
if (op.mask) op.crc &= op.mask;
|
||||
SearchPatternEntry op;
|
||||
op.type = ops[i].type;
|
||||
op.data = re32(ops[i].data);
|
||||
op.mask = re32(ops[i].mask);
|
||||
op.num = ops[i].num;
|
||||
assert(!op.mask || (op.data & ~op.mask) == 0);
|
||||
sf.ops.push_back(op);
|
||||
}
|
||||
|
||||
|
@ -173,90 +174,155 @@ u32 get_function_id(const char* name)
|
|||
return (u32&)output[0];
|
||||
}
|
||||
|
||||
void hook_ppu_funcs(u32* base, u32 size)
|
||||
void hook_ppu_func(vm::ptr<u32> base, u32 pos, u32 size)
|
||||
{
|
||||
size /= 4;
|
||||
using namespace PPU_instr;
|
||||
|
||||
for (auto& sub : g_ppu_func_subs)
|
||||
{
|
||||
bool found = true;
|
||||
|
||||
for (u32 k = pos, x = 0; x + 1 <= sub.ops.size(); k++, x++)
|
||||
{
|
||||
if (k >= size)
|
||||
{
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// skip NOP
|
||||
if (base[k].data() == se32(0x60000000))
|
||||
{
|
||||
x--;
|
||||
continue;
|
||||
}
|
||||
|
||||
const u32 data = sub.ops[x].data;
|
||||
const u32 mask = sub.ops[x].mask;
|
||||
|
||||
const bool match = (base[k].data() & mask) == data;
|
||||
|
||||
switch (sub.ops[x].type)
|
||||
{
|
||||
case SPET_MASKED_OPCODE:
|
||||
{
|
||||
// masked pattern
|
||||
if (!match)
|
||||
{
|
||||
found = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SPET_OPTIONAL_MASKED_OPCODE:
|
||||
{
|
||||
// optional masked pattern
|
||||
if (!match)
|
||||
{
|
||||
k--;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SPET_LABEL:
|
||||
{
|
||||
const auto addr = (base + k--).addr();
|
||||
const auto lnum = data;
|
||||
const auto label = sub.labels.find(lnum);
|
||||
|
||||
if (label == sub.labels.end()) // register the label
|
||||
{
|
||||
sub.labels[lnum] = addr;
|
||||
}
|
||||
else if (label->second != addr) // or check registered label
|
||||
{
|
||||
found = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case SPET_BRANCH_TO_LABEL:
|
||||
{
|
||||
if (!match)
|
||||
{
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
|
||||
const auto addr = (base[k].data() & se32(2) ? 0 : (base + k).addr()) + ((s32)base[k] << cntlz32(mask) >> (cntlz32(mask) + 2));
|
||||
const auto lnum = sub.ops[x].num;
|
||||
const auto label = sub.labels.find(lnum);
|
||||
|
||||
if (label == sub.labels.end()) // register the label
|
||||
{
|
||||
sub.labels[lnum] = addr;
|
||||
}
|
||||
else if (label->second != addr) // or check registered label
|
||||
{
|
||||
found = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
//case SPET_BRANCH_TO_FUNC:
|
||||
//{
|
||||
// if (!match)
|
||||
// {
|
||||
// found = false;
|
||||
// break;
|
||||
// }
|
||||
|
||||
// const auto addr = (base[k].data() & se32(2) ? 0 : (base + k).addr()) + ((s32)base[k] << cntlz32(mask) >> (cntlz32(mask) + 2));
|
||||
// const auto nid = sub.ops[x].num;
|
||||
// // TODO: recursive call
|
||||
//}
|
||||
default:
|
||||
{
|
||||
LOG_ERROR(LOADER, "Unknown search pattern type (%d)", sub.ops[x].type);
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "Function '%s' hooked (addr=0x%x)", sub.name, (base + pos).addr());
|
||||
sub.found++;
|
||||
base[pos] = HACK(sub.index | EIF_PERFORM_BLR);
|
||||
}
|
||||
|
||||
if (sub.labels.size())
|
||||
{
|
||||
sub.labels.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hook_ppu_funcs(vm::ptr<u32> base, u32 size)
|
||||
{
|
||||
using namespace PPU_instr;
|
||||
|
||||
if (!Ini.HLEHookStFunc.GetValue())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: optimize search
|
||||
for (u32 i = 0; i < size; i++)
|
||||
{
|
||||
for (u32 j = 0; j < g_ppu_func_subs.size(); j++)
|
||||
// skip NOP
|
||||
if (base[i].data() == se32(0x60000000))
|
||||
{
|
||||
if ((base[i] & g_ppu_func_subs[j].ops[0].mask) == g_ppu_func_subs[j].ops[0].crc)
|
||||
{
|
||||
bool found = true;
|
||||
u32 can_skip = 0;
|
||||
for (u32 k = i, x = 0; x + 1 <= g_ppu_func_subs[j].ops.size(); k++, x++)
|
||||
{
|
||||
if (k >= size)
|
||||
{
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// skip NOP
|
||||
if (base[k] == se32(0x60000000))
|
||||
{
|
||||
x--;
|
||||
continue;
|
||||
}
|
||||
|
||||
const u32 mask = g_ppu_func_subs[j].ops[x].mask;
|
||||
const u32 crc = g_ppu_func_subs[j].ops[x].crc;
|
||||
|
||||
if (!mask)
|
||||
{
|
||||
// TODO: define syntax
|
||||
if (crc < 4) // skip various number of instructions that don't match next pattern entry
|
||||
{
|
||||
can_skip += crc;
|
||||
k--; // process this position again
|
||||
}
|
||||
else if (base[k] != crc) // skippable pattern ("optional" instruction), no mask allowed
|
||||
{
|
||||
k--;
|
||||
if (can_skip) // cannot define this behaviour properly
|
||||
{
|
||||
LOG_WARNING(LOADER, "hook_ppu_funcs(): can_skip = %d (unchanged)", can_skip);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (can_skip) // cannot define this behaviour properly
|
||||
{
|
||||
LOG_WARNING(LOADER, "hook_ppu_funcs(): can_skip = %d (set to 0)", can_skip);
|
||||
can_skip = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((base[k] & mask) != crc) // masked pattern
|
||||
{
|
||||
if (can_skip)
|
||||
{
|
||||
can_skip--;
|
||||
}
|
||||
else
|
||||
{
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
can_skip = 0;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "Function '%s' hooked (addr=0x%x)", g_ppu_func_subs[j].name, vm::get_addr(base + i * 4));
|
||||
g_ppu_func_subs[j].found++;
|
||||
base[i] = re32(0x04000000 | g_ppu_func_subs[j].index | EIF_PERFORM_BLR); // hack
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
hook_ppu_func(base, i, size);
|
||||
}
|
||||
|
||||
// check function groups
|
||||
|
|
|
@ -43,19 +43,31 @@ struct ModuleFunc
|
|||
}
|
||||
};
|
||||
|
||||
struct SFuncOp
|
||||
enum : u32
|
||||
{
|
||||
u32 crc;
|
||||
SPET_MASKED_OPCODE,
|
||||
SPET_OPTIONAL_MASKED_OPCODE,
|
||||
SPET_LABEL,
|
||||
SPET_BRANCH_TO_LABEL,
|
||||
SPET_BRANCH_TO_FUNC,
|
||||
};
|
||||
|
||||
struct SearchPatternEntry
|
||||
{
|
||||
u32 type;
|
||||
u32 data;
|
||||
u32 mask;
|
||||
u32 num; // supplement info
|
||||
};
|
||||
|
||||
struct StaticFunc
|
||||
{
|
||||
u32 index;
|
||||
const char* name;
|
||||
std::vector<SFuncOp> ops;
|
||||
std::vector<SearchPatternEntry> ops;
|
||||
u64 group;
|
||||
u32 found;
|
||||
std::unordered_map<u32, u32> labels;
|
||||
};
|
||||
|
||||
class Module : public LogBase
|
||||
|
@ -138,9 +150,9 @@ void clear_ppu_functions();
|
|||
u32 get_function_id(const char* name);
|
||||
|
||||
u32 add_ppu_func_sub(StaticFunc sf);
|
||||
u32 add_ppu_func_sub(const char group[8], const u64 ops[], const char* name, Module* module, ppu_func_caller func);
|
||||
u32 add_ppu_func_sub(const char group[8], const SearchPatternEntry ops[], size_t count, const char* name, Module* module, ppu_func_caller func);
|
||||
|
||||
void hook_ppu_funcs(u32* base, u32 size);
|
||||
void hook_ppu_funcs(vm::ptr<u32> base, u32 size);
|
||||
|
||||
#define REG_FUNC(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), 0, &module, bind_func(name)))
|
||||
#define REG_FUNC_FH(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), MFF_FORCED_HLE, &module, bind_func(name)))
|
||||
|
@ -148,9 +160,13 @@ void hook_ppu_funcs(u32* base, u32 size);
|
|||
#define REG_UNNAMED(module, nid) add_ppu_func(ModuleFunc(0x##nid, 0, &module, bind_func(_nid_##nid)))
|
||||
|
||||
#define REG_SUB(module, group, name, ...) \
|
||||
static const u64 name ## _table[] = {__VA_ARGS__ , 0}; \
|
||||
if (name ## _table[0]) add_ppu_func_sub(group, name ## _table, #name, &module, bind_func(name))
|
||||
const SearchPatternEntry name##_table[] = {__VA_ARGS__}; \
|
||||
add_ppu_func_sub(group, name##_table, sizeof(name##_table) / sizeof(SearchPatternEntry), #name, &module, bind_func(name))
|
||||
|
||||
#define op_mask(op) []() -> u64 { s32 XXX = 0; u64 _op = (op); XXX = -1; return ((op) ^ ~_op) << 32 | _op; }()
|
||||
#define se_op(op) []() { SearchPatternEntry res = { SPET_MASKED_OPCODE }; s32 XXX = 0; res.data = (op); XXX = -1; res.mask = (op) ^ ~res.data; return res; }()
|
||||
#define se_opt(op) []() { SearchPatternEntry res = { SPET_OPTIONAL_MASKED_OPCODE }; s32 XXX = 0; res.data = (op); XXX = -1; res.mask = (op) ^ ~res.data; return res; }()
|
||||
#define se_label(label) { SPET_LABEL, (label) }
|
||||
#define se_lbr(op, label) []() { SearchPatternEntry res = { SPET_BRANCH_TO_LABEL, 0, 0, (label) }; s32 XXX = 0; res.data = (op); XXX = -1; res.mask = (op) ^ ~res.data; return res; }()
|
||||
#define se_call(op, name) []() { SearchPatternEntry res = { SPET_BRANCH_TO_FUNC, 0, 0, get_function_id(#name) }; s32 XXX = 0; res.data = (op); XXX = -1; res.mask = (op) ^ ~res.data; return res; }()
|
||||
|
||||
#define UNIMPLEMENTED_FUNC(module) module.Error("%s", __FUNCTION__)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -576,7 +576,7 @@ namespace loader
|
|||
{
|
||||
m_stream->Seek(handler::get_stream_offset() + phdr.p_offset);
|
||||
m_stream->Read(phdr.p_vaddr.get_ptr(), phdr.p_filesz);
|
||||
hook_ppu_funcs((u32*)phdr.p_vaddr.get_ptr(), vm::cast(phdr.p_filesz));
|
||||
hook_ppu_funcs(vm::ptr<u32>::make(phdr.p_vaddr.addr()), vm::cast(phdr.p_filesz) / 4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Add table
Reference in a new issue