mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 18:53:28 +01:00
commit
fcd300ad4d
@ -263,6 +263,30 @@ namespace fmt
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct get_fmt<unsigned long>
|
||||
{
|
||||
static std::string text(const char* fmt, size_t len, unsigned long arg)
|
||||
{
|
||||
if (fmt[len - 1] == 'x')
|
||||
{
|
||||
return to_hex(arg, get_fmt_precision(fmt, len));
|
||||
}
|
||||
else if (fmt[len - 1] == 'X')
|
||||
{
|
||||
return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len)));
|
||||
}
|
||||
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
|
||||
{
|
||||
return to_udec(arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Invalid formatting (unsigned long): " + std::string(fmt, len);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct get_fmt<u64>
|
||||
{
|
||||
@ -359,6 +383,30 @@ namespace fmt
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct get_fmt<long>
|
||||
{
|
||||
static std::string text(const char* fmt, size_t len, long arg)
|
||||
{
|
||||
if (fmt[len - 1] == 'x')
|
||||
{
|
||||
return to_hex((u64)arg, get_fmt_precision(fmt, len));
|
||||
}
|
||||
else if (fmt[len - 1] == 'X')
|
||||
{
|
||||
return fmt::toupper(to_hex((u64)arg, get_fmt_precision(fmt, len)));
|
||||
}
|
||||
else if (fmt[len - 1] == 'd')
|
||||
{
|
||||
return to_sdec(arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw "Invalid formatting (long): " + std::string(fmt, len);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct get_fmt<s64>
|
||||
{
|
||||
|
@ -9,6 +9,8 @@
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#define _XOPEN_SOURCE
|
||||
#define __USE_GNU
|
||||
#include <signal.h>
|
||||
#include <ucontext.h>
|
||||
#endif
|
||||
@ -195,21 +197,72 @@ void decode_x64_reg_op(const u8* code, x64_op_t& decoded_op, x64_reg_t& decoded_
|
||||
typedef CONTEXT x64_context;
|
||||
|
||||
#define RIP 16
|
||||
#define X64REG(context, reg) ((&context->Rax)[reg])
|
||||
#define X64REG(context, reg) (&(&context->Rax)[reg])
|
||||
|
||||
#else
|
||||
|
||||
typedef ucontext_t x64_context;
|
||||
typedef decltype(REG_RIP) reg_table_t;
|
||||
#define RIP 16
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
#define X64REG(context, reg) (darwin_x64reg(context, reg))
|
||||
|
||||
uint64_t* darwin_x64reg(x64_context *context, int reg)
|
||||
{
|
||||
auto *state = &context->uc_mcontext->__ss;
|
||||
switch(reg)
|
||||
{
|
||||
case 0: // RAX
|
||||
return &state->__rax;
|
||||
case 1: // RCX
|
||||
return &state->__rcx;
|
||||
case 2: // RDX
|
||||
return &state->__rdx;
|
||||
case 3: // RBX
|
||||
return &state->__rbx;
|
||||
case 4: // RSP
|
||||
return &state->__rsp;
|
||||
case 5: // RBP
|
||||
return &state->__rbp;
|
||||
case 6: // RSI
|
||||
return &state->__rsi;
|
||||
case 7: // RDI
|
||||
return &state->__rdi;
|
||||
case 8: // R8
|
||||
return &state->__r8;
|
||||
case 9: // R9
|
||||
return &state->__r9;
|
||||
case 10: // R10
|
||||
return &state->__r10;
|
||||
case 11: // R11
|
||||
return &state->__r11;
|
||||
case 12: // R12
|
||||
return &state->__r12;
|
||||
case 13: // R13
|
||||
return &state->__r13;
|
||||
case 14: // R14
|
||||
return &state->__r14;
|
||||
case 15: // R15
|
||||
return &state->__r15;
|
||||
case 16: // RIP
|
||||
return &state->__rip;
|
||||
default: // FAIL
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
typedef decltype(REG_RIP) reg_table_t;
|
||||
|
||||
static const reg_table_t reg_table[17] =
|
||||
{
|
||||
REG_RAX, REG_RCX, REG_RDX, REG_RBX, REG_RSP, REG_RBP, REG_RSI, REG_RDI,
|
||||
REG_R8, REG_R9, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15, REG_RIP
|
||||
};
|
||||
|
||||
#define X64REG(context, reg) (context->uc_mcontext.gregs[reg_table[reg]])
|
||||
#define X64REG(context, reg) (&context->uc_mcontext.gregs[reg_table[reg]])
|
||||
#endif // __APPLE__
|
||||
|
||||
#endif
|
||||
|
||||
@ -222,19 +275,19 @@ bool handle_access_violation(const u32 addr, bool is_writing, x64_context* conte
|
||||
x64_op_t op;
|
||||
x64_reg_t reg;
|
||||
size_t size;
|
||||
decode_x64_reg_op((const u8*)X64REG(context, RIP), op, reg, size);
|
||||
decode_x64_reg_op((const u8*)(*X64REG(context, RIP)), op, reg, size);
|
||||
|
||||
// get x64 reg value (for store operations)
|
||||
u64 reg_value;
|
||||
if (reg - X64R32 < 16)
|
||||
{
|
||||
// load the value from x64 register
|
||||
reg_value = (u32)X64REG(context, reg - X64R32);
|
||||
reg_value = (u32)*X64REG(context, reg - X64R32);
|
||||
}
|
||||
else if (reg == X64_IMM32)
|
||||
{
|
||||
// load the immediate value (assuming it's at the end of the instruction)
|
||||
reg_value = *(u32*)(X64REG(context, RIP) + size - 4);
|
||||
reg_value = *(u32*)(*X64REG(context, RIP) + size - 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -265,7 +318,7 @@ bool handle_access_violation(const u32 addr, bool is_writing, x64_context* conte
|
||||
if (reg - X64R32 < 16)
|
||||
{
|
||||
// store the value into x64 register
|
||||
X64REG(context, reg - X64R32) = (u32)reg_value;
|
||||
*X64REG(context, reg - X64R32) = (u32)reg_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -274,7 +327,7 @@ bool handle_access_violation(const u32 addr, bool is_writing, x64_context* conte
|
||||
}
|
||||
|
||||
// skip decoded instruction
|
||||
X64REG(context, RIP) += size;
|
||||
*X64REG(context, RIP) += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -324,7 +377,12 @@ const PVOID exception_handler = (atexit([]{ RemoveVectoredExceptionHandler(excep
|
||||
void signal_handler(int sig, siginfo_t* info, void* uct)
|
||||
{
|
||||
const u64 addr64 = (u64)info->si_addr - (u64)vm::g_base_addr;
|
||||
|
||||
#ifdef __APPLE__
|
||||
const bool is_writing = ((ucontext_t*)uct)->uc_mcontext->__es.__err & 0x2;
|
||||
#else
|
||||
const bool is_writing = ((ucontext_t*)uct)->uc_mcontext.gregs[REG_ERR] & 0x2;
|
||||
#endif
|
||||
|
||||
if ((u32)addr64 == addr64 && GetCurrentNamedThread())
|
||||
{
|
||||
|
@ -887,6 +887,20 @@ struct cast_ppu_gpr<u32, false>
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cast_ppu_gpr<unsigned long, false>
|
||||
{
|
||||
__forceinline static u64 to_gpr(const unsigned long& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
__forceinline static unsigned long from_gpr(const u64 reg)
|
||||
{
|
||||
return static_cast<unsigned long>(reg);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cast_ppu_gpr<u64, false>
|
||||
{
|
||||
|
@ -61,7 +61,7 @@ struct VFS
|
||||
|
||||
struct links_sorter
|
||||
{
|
||||
bool operator()(const std::vector<std::string>& a, const std::vector<std::string>& b)
|
||||
bool operator()(const std::vector<std::string>& a, const std::vector<std::string>& b) const
|
||||
{
|
||||
return b.size() < a.size();
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ public:
|
||||
else
|
||||
{
|
||||
assert(!"Invalid ID type");
|
||||
return{};
|
||||
return std::set<u32>{};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -84,6 +84,21 @@ namespace vm
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cast_ptr<unsigned long>
|
||||
{
|
||||
__forceinline static u32 cast(const unsigned long addr, const char* func)
|
||||
{
|
||||
const u32 res = static_cast<u32>(addr);
|
||||
if (res != addr)
|
||||
{
|
||||
vm::error(addr, func);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct cast_ptr<u32>
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user