From 00e637645c629ee67f369d24243d7be245a72dfb Mon Sep 17 00:00:00 2001 From: Robert Xu Date: Tue, 10 Feb 2015 23:17:39 -0500 Subject: [PATCH] Fix building on OS X 10.10 --- Utilities/StrFmt.h | 48 +++++++++++++++++++++++++ Utilities/Thread.cpp | 74 +++++++++++++++++++++++++++++++++----- rpcs3/Emu/Cell/PPUThread.h | 14 ++++++++ rpcs3/Emu/FS/VFS.h | 2 +- rpcs3/Emu/IdManager.h | 2 +- rpcs3/Emu/Memory/vm.h | 15 ++++++++ 6 files changed, 145 insertions(+), 10 deletions(-) diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index bdc99a83af..e9c7c23334 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -263,6 +263,30 @@ namespace fmt } }; + template<> + struct get_fmt + { + 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 { @@ -359,6 +383,30 @@ namespace fmt } }; + template<> + struct get_fmt + { + 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 { diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 25d5981e23..faa0b1b04e 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -9,6 +9,8 @@ #ifdef _WIN32 #include #else +#define _XOPEN_SOURCE +#define __USE_GNU #include #include #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()) { diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 834200b1ae..1c32cd7e3e 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -887,6 +887,20 @@ struct cast_ppu_gpr } }; +template<> +struct cast_ppu_gpr +{ + __forceinline static u64 to_gpr(const unsigned long& value) + { + return value; + } + + __forceinline static unsigned long from_gpr(const u64 reg) + { + return static_cast(reg); + } +}; + template<> struct cast_ppu_gpr { diff --git a/rpcs3/Emu/FS/VFS.h b/rpcs3/Emu/FS/VFS.h index 38a63e94c4..9d202d4cb9 100644 --- a/rpcs3/Emu/FS/VFS.h +++ b/rpcs3/Emu/FS/VFS.h @@ -61,7 +61,7 @@ struct VFS struct links_sorter { - bool operator()(const std::vector& a, const std::vector& b) + bool operator()(const std::vector& a, const std::vector& b) const { return b.size() < a.size(); } diff --git a/rpcs3/Emu/IdManager.h b/rpcs3/Emu/IdManager.h index ef3c78aacd..ac066d142f 100644 --- a/rpcs3/Emu/IdManager.h +++ b/rpcs3/Emu/IdManager.h @@ -252,7 +252,7 @@ public: else { assert(!"Invalid ID type"); - return{}; + return std::set{}; } } }; diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index a49c21eaab..0955c24b33 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -84,6 +84,21 @@ namespace vm } }; + template<> + struct cast_ptr + { + __forceinline static u32 cast(const unsigned long addr, const char* func) + { + const u32 res = static_cast(addr); + if (res != addr) + { + vm::error(addr, func); + } + + return res; + } + }; + template<> struct cast_ptr {