mirror of https://github.com/PCSX2/pcsx2.git
Common: reformat (#4720)
* common: format AlignedMalloc.cpp * common: format AppTrait.h * common: format Assertions.h * common: format CheckedStaticBox * common: format Console * common: format Dependencies.h * common: format EmbeddedImage * common: format EventSource * common: format Exceptions * common: format FastFormatString.cpp * common: format General.h * common: format InitInterface * common: format MathUtils.h * common: format MemsetFast/MemcpyFast * common: format Mutex.cpp * common: format PageFaultSource.h * common: format Path.h * common: format PathUtils.cpp * common: format Pcsx2Types.h * common: format Perf * common: format PersistentThread.h * common: format RwMutex * common: format SafeArray * common: format ScopedAlloc.h * common: format ScopedPtrMT.h * common: format Semaphore.cpp * common: format StringHelpers * common: format ThreadTools.cpp * common: format Threading.h * common: format ThreadingDialogs * common: format ThreadingInternal.h * common: format TraceLog.h * common: format VirtualMemory.cpp * common: format pxCheckBox * common: format pxEvents.h * common: format pxForwardDefs.h * common: format pxRadioPanel * common: format pxStaticText * common: format pxStreams * common: format pxTranslate.cpp * common: format pxWindowTextWriter.cpp * common: format wxAppWithHelpers * common: format wxBaseTools.h * common: format wxGuiTools * common: format wxHelpers.cpp * common: format Darwin directory * common: format Linux directory * common: format Windows directory * common: format LnxCpuDetect.cpp * common: format WinCpuDetect.cpp * common: format bmi.cpp * common: format cpudetect.cpp * common: format cpu_detect_internal.h * common: format fpu.cpp * common: format groups.cpp * common: format instructions.h * common: format internal.h * common: format jmp.cpp * common: format legacy.cpp * common: format legacy_instructions.h * common: format legacy_internal.h * common: format movs.cpp * common: format simd.cpp * common: format tools.h * common: format x86emitter.cpp * common: format x86types.h * common: format bmi.h * common: format dwshift.h * common: format group1.h group2.h group3.h * common: format incdec.h * common: format jmpcall.h * common: format movs.h * common: format simd_arithmetic.h * common: format simd_comparisons.h * common: format simd_helpers.h * common: format simd_moremovs.h * common: format simd_shufflepack.h * common: format simd_templated_helpers.h * common: format test.h
This commit is contained in:
parent
f9bf87f50d
commit
13dfceff48
|
@ -39,7 +39,8 @@ void *__fastcall pcsx2_aligned_realloc(void *handle, size_t new_size, size_t ali
|
|||
|
||||
void* newbuf = _aligned_malloc(new_size, align);
|
||||
|
||||
if (newbuf != NULL && handle != NULL) {
|
||||
if (newbuf != NULL && handle != NULL)
|
||||
{
|
||||
memcpy(newbuf, handle, std::min(old_size, new_size));
|
||||
_aligned_free(handle);
|
||||
}
|
||||
|
|
|
@ -159,10 +159,13 @@ extern pxDoAssertFnType *pxDoAssert;
|
|||
#define pxAssumeDev(cond, msg) (__assume(cond))
|
||||
|
||||
#define pxFail(msg) \
|
||||
do { \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
|
||||
#define pxFailDev(msg) \
|
||||
do { \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
@ -202,7 +205,8 @@ extern void pxOnAssert(const DiagnosticOrigin &origin, const wxString &msg);
|
|||
//
|
||||
#ifndef jNO_DEFAULT
|
||||
#define jNO_DEFAULT \
|
||||
default: { \
|
||||
default: \
|
||||
{ \
|
||||
pxAssumeDev(0, "Incorrect usage of jNO_DEFAULT detected (default case is not unreachable!)"); \
|
||||
break; \
|
||||
}
|
||||
|
|
|
@ -43,7 +43,8 @@ void CheckedStaticBox::SetValue(bool val)
|
|||
{
|
||||
wxWindowList& list = GetChildren();
|
||||
|
||||
for (wxWindowList::iterator iter = list.begin(); iter != list.end(); ++iter) {
|
||||
for (wxWindowList::iterator iter = list.begin(); iter != list.end(); ++iter)
|
||||
{
|
||||
wxWindow* current = *iter;
|
||||
if (current != &ThisToggle)
|
||||
current->Enable(IsEnabled() && val);
|
||||
|
@ -66,7 +67,8 @@ bool CheckedStaticBox::Enable(bool enable)
|
|||
bool val = enable && ThisToggle.GetValue();
|
||||
wxWindowList& list = GetChildren();
|
||||
|
||||
for (wxWindowList::iterator iter = list.begin(); iter != list.end(); ++iter) {
|
||||
for (wxWindowList::iterator iter = list.begin(); iter != list.end(); ++iter)
|
||||
{
|
||||
wxWindow* current = *iter;
|
||||
if (current != &ThisToggle)
|
||||
current->Enable(val);
|
||||
|
|
|
@ -102,7 +102,8 @@ const IConsoleWriter ConsoleWriter_Null =
|
|||
#if defined(__unix__)
|
||||
static __fi const char* GetLinuxConsoleColor(ConsoleColors color)
|
||||
{
|
||||
switch (color) {
|
||||
switch (color)
|
||||
{
|
||||
case Color_Black:
|
||||
case Color_StrongBlack:
|
||||
return "\033[30m\033[1m";
|
||||
|
@ -470,7 +471,8 @@ ConsoleColorScope::~ConsoleColorScope()
|
|||
|
||||
void ConsoleColorScope::EnterScope()
|
||||
{
|
||||
if (!m_IsScoped) {
|
||||
if (!m_IsScoped)
|
||||
{
|
||||
m_old_color = Console.GetColor();
|
||||
Console.SetColor(m_newcolor);
|
||||
m_IsScoped = true;
|
||||
|
@ -491,7 +493,8 @@ ConsoleIndentScope::ConsoleIndentScope(int tabs)
|
|||
|
||||
ConsoleIndentScope::~ConsoleIndentScope()
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
LeaveScope();
|
||||
}
|
||||
DESTRUCTOR_CATCHALL
|
||||
|
@ -517,7 +520,8 @@ ConsoleAttrScope::ConsoleAttrScope(ConsoleColors newcolor, int indent)
|
|||
|
||||
ConsoleAttrScope::~ConsoleAttrScope()
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
Console.SetColor(m_old_color);
|
||||
Console.SetIndent(-m_tabsize);
|
||||
}
|
||||
|
|
|
@ -15,9 +15,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "StringHelpers.h"
|
||||
#include "common/StringHelpers.h"
|
||||
|
||||
enum ConsoleColors {
|
||||
enum ConsoleColors
|
||||
{
|
||||
Color_Current = -1,
|
||||
|
||||
Color_Default = 0,
|
||||
|
|
|
@ -45,11 +45,13 @@ u64 GetPhysicalMemory()
|
|||
// doesn't change during the course of the program. Thread-safety is
|
||||
// ensured by atomic operations with full-barriers (usually compiled
|
||||
// down to XCHG on x86).
|
||||
if (__atomic_load_n(&mem, __ATOMIC_SEQ_CST) == 0) {
|
||||
if (__atomic_load_n(&mem, __ATOMIC_SEQ_CST) == 0)
|
||||
{
|
||||
u64 getmem = 0;
|
||||
size_t len = sizeof(getmem);
|
||||
int mib[] = {CTL_HW, HW_MEMSIZE};
|
||||
if (sysctl(mib, NELEM(mib), &getmem, &len, NULL, 0) < 0) {
|
||||
if (sysctl(mib, NELEM(mib), &getmem, &len, NULL, 0) < 0)
|
||||
{
|
||||
perror("sysctl:");
|
||||
}
|
||||
__atomic_store_n(&mem, getmem, __ATOMIC_SEQ_CST);
|
||||
|
@ -76,14 +78,16 @@ u64 GetTickFrequency()
|
|||
|
||||
// by the time denom is not 0, the structure will have been fully
|
||||
// updated and no more atomic accesses are necessary.
|
||||
if (__atomic_load_n(&freq, __ATOMIC_SEQ_CST) == 0) {
|
||||
if (__atomic_load_n(&freq, __ATOMIC_SEQ_CST) == 0)
|
||||
{
|
||||
mach_timebase_info_data_t info;
|
||||
|
||||
// mach_timebase_info() is a syscall, very slow, that's why we take
|
||||
// pains to only do it once. On x86(-64), the result is guaranteed
|
||||
// to be info.denom == info.numer == 1 (i.e.: the frequency is 1e9,
|
||||
// which means GetCPUTicks is just nanoseconds).
|
||||
if (mach_timebase_info(&info) != KERN_SUCCESS) {
|
||||
if (mach_timebase_info(&info) != KERN_SUCCESS)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
|
@ -109,13 +113,15 @@ wxString GetOSVersionString()
|
|||
static int initialized = 0;
|
||||
|
||||
// fetch the OS description only once (thread-safely)
|
||||
if (__atomic_load_n(&initialized, __ATOMIC_SEQ_CST) == 0) {
|
||||
if (__atomic_load_n(&initialized, __ATOMIC_SEQ_CST) == 0)
|
||||
{
|
||||
char type[32] = {0};
|
||||
char release[32] = {0};
|
||||
char arch[32] = {0};
|
||||
|
||||
#define SYSCTL_GET(var, base, name) \
|
||||
do { \
|
||||
do \
|
||||
{ \
|
||||
int mib[] = {base, name}; \
|
||||
size_t len = sizeof(var); \
|
||||
sysctl(mib, NELEM(mib), NULL, &len, NULL, 0); \
|
||||
|
|
|
@ -45,8 +45,10 @@
|
|||
|
||||
static void MACH_CHECK(kern_return_t mach_retval)
|
||||
{
|
||||
switch (mach_retval) {
|
||||
case KERN_SUCCESS: break;
|
||||
switch (mach_retval)
|
||||
{
|
||||
case KERN_SUCCESS:
|
||||
break;
|
||||
case KERN_ABORTED: // Awoken due reason unrelated to semaphore (e.g. pthread_cancel)
|
||||
pthread_testcancel(); // Unlike sem_wait, mach semaphore ops aren't cancellation points
|
||||
// fallthrough
|
||||
|
@ -85,7 +87,8 @@ void Threading::Semaphore::Post()
|
|||
|
||||
void Threading::Semaphore::Post(int multiple)
|
||||
{
|
||||
for (int i = 0; i < multiple; ++i) {
|
||||
for (int i = 0; i < multiple; ++i)
|
||||
{
|
||||
MACH_CHECK(semaphore_signal(m_sema));
|
||||
}
|
||||
__atomic_add_fetch(&m_counter, multiple, __ATOMIC_SEQ_CST);
|
||||
|
@ -115,8 +118,10 @@ bool Threading::Semaphore::WaitWithoutYield(const wxTimeSpan &timeout)
|
|||
mach_timespec_t ts;
|
||||
kern_return_t kr = KERN_ABORTED;
|
||||
for (u64 now = mach_absolute_time(), deadline = now + delta;
|
||||
kr == KERN_ABORTED; now = mach_absolute_time()) {
|
||||
if (now > deadline) {
|
||||
kr == KERN_ABORTED; now = mach_absolute_time())
|
||||
{
|
||||
if (now > deadline)
|
||||
{
|
||||
// timed out by definition
|
||||
return false;
|
||||
}
|
||||
|
@ -135,7 +140,8 @@ bool Threading::Semaphore::WaitWithoutYield(const wxTimeSpan &timeout)
|
|||
kr = semaphore_timedwait(m_sema, ts);
|
||||
}
|
||||
|
||||
if (kr == KERN_OPERATION_TIMED_OUT) {
|
||||
if (kr == KERN_OPERATION_TIMED_OUT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -155,13 +161,19 @@ bool Threading::Semaphore::WaitWithoutYield(const wxTimeSpan &timeout)
|
|||
void Threading::Semaphore::Wait()
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
if (!wxThread::IsMain() || (wxTheApp == NULL)) {
|
||||
if (!wxThread::IsMain() || (wxTheApp == NULL))
|
||||
{
|
||||
WaitWithoutYield();
|
||||
} else if (_WaitGui_RecursionGuard(L"Semaphore::Wait")) {
|
||||
}
|
||||
else if (_WaitGui_RecursionGuard(L"Semaphore::Wait"))
|
||||
{
|
||||
ScopedBusyCursor hourglass(Cursor_ReallyBusy);
|
||||
WaitWithoutYield();
|
||||
} else {
|
||||
while (!WaitWithoutYield(def_yieldgui_interval)) {
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!WaitWithoutYield(def_yieldgui_interval))
|
||||
{
|
||||
YieldToMain();
|
||||
}
|
||||
}
|
||||
|
@ -182,16 +194,22 @@ void Threading::Semaphore::Wait()
|
|||
bool Threading::Semaphore::Wait(const wxTimeSpan& timeout)
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
if (!wxThread::IsMain() || (wxTheApp == NULL)) {
|
||||
if (!wxThread::IsMain() || (wxTheApp == NULL))
|
||||
{
|
||||
return WaitWithoutYield(timeout);
|
||||
} else if (_WaitGui_RecursionGuard(L"Semaphore::TimedWait")) {
|
||||
}
|
||||
else if (_WaitGui_RecursionGuard(L"Semaphore::TimedWait"))
|
||||
{
|
||||
ScopedBusyCursor hourglass(Cursor_ReallyBusy);
|
||||
return WaitWithoutYield(timeout);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
//ScopedBusyCursor hourglass( Cursor_KindaBusy );
|
||||
wxTimeSpan countdown((timeout));
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (WaitWithoutYield(def_yieldgui_interval))
|
||||
break;
|
||||
YieldToMain();
|
||||
|
|
|
@ -70,7 +70,8 @@ static u64 getthreadtime(thread_port_t thread)
|
|||
|
||||
kern_return_t kr = thread_info(thread, THREAD_BASIC_INFO,
|
||||
(thread_info_t)&info, &count);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
if (kr != KERN_SUCCESS)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -103,7 +104,8 @@ u64 Threading::pxThread::GetCpuTime() const
|
|||
// m_native_handle to implement it. Return value should be a measure of total time the
|
||||
// thread has used on the CPU (scaled by the value returned by GetThreadTicksPerSecond(),
|
||||
// which typically would be an OS-provided scalar or some sort).
|
||||
if (!m_native_id) {
|
||||
if (!m_native_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,17 +67,20 @@
|
|||
src = (enumName)((int)src + 1); \
|
||||
return src; \
|
||||
} \
|
||||
\
|
||||
static __fi enumName& operator--(enumName& src) \
|
||||
{ \
|
||||
src = (enumName)((int)src - 1); \
|
||||
return src; \
|
||||
} \
|
||||
\
|
||||
static __fi enumName operator++(enumName& src, int) \
|
||||
{ \
|
||||
enumName orig = src; \
|
||||
src = (enumName)((int)src + 1); \
|
||||
return orig; \
|
||||
} \
|
||||
\
|
||||
static __fi enumName operator--(enumName& src, int) \
|
||||
{ \
|
||||
enumName orig = src; \
|
||||
|
@ -93,6 +96,7 @@
|
|||
{ \
|
||||
return ((int)id >= enumName##_FIRST) && ((int)id < enumName##_COUNT); \
|
||||
} \
|
||||
\
|
||||
static __fi void EnumAssert(enumName id) \
|
||||
{ \
|
||||
pxAssert(EnumIsValid(id)); \
|
||||
|
|
|
@ -52,7 +52,8 @@ protected:
|
|||
//
|
||||
void _loadImage()
|
||||
{
|
||||
if (!m_Image.Ok()) {
|
||||
if (!m_Image.Ok())
|
||||
{
|
||||
wxMemoryInputStream joe(ImageType::Data, ImageType::Length);
|
||||
m_Image.LoadFile(joe, ImageType::GetFormat());
|
||||
|
||||
|
|
|
@ -25,9 +25,11 @@ typename EventSource<ListenerType>::ListenerIterator EventSource<ListenerType>::
|
|||
ScopedLock locker(m_listeners_lock);
|
||||
|
||||
// Check for duplicates before adding the event.
|
||||
if (IsDebugBuild) {
|
||||
if (IsDebugBuild)
|
||||
{
|
||||
ListenerIterator iter = m_listeners.begin();
|
||||
while (iter != m_listeners.end()) {
|
||||
while (iter != m_listeners.end())
|
||||
{
|
||||
if ((*iter) == &listener)
|
||||
return iter;
|
||||
++iter;
|
||||
|
@ -64,17 +66,27 @@ typename EventSource<ListenerType>::ListenerIterator EventSource<ListenerType>::
|
|||
template <typename ListenerType>
|
||||
__fi void EventSource<ListenerType>::_DispatchRaw(ListenerIterator iter, const ListenerIterator& iend, const EvtParams& evtparams)
|
||||
{
|
||||
while (iter != iend) {
|
||||
try {
|
||||
while (iter != iend)
|
||||
{
|
||||
try
|
||||
{
|
||||
(*iter)->DispatchEvent(evtparams);
|
||||
} catch (Exception::RuntimeError &ex) {
|
||||
if (IsDevBuild) {
|
||||
}
|
||||
catch (Exception::RuntimeError& ex)
|
||||
{
|
||||
if (IsDevBuild)
|
||||
{
|
||||
pxFailDev(L"Ignoring runtime error thrown from event listener (event listeners should not throw exceptions!): " + ex.FormatDiagnosticMessage());
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error(L"Ignoring runtime error thrown from event listener: " + ex.FormatDiagnosticMessage());
|
||||
}
|
||||
} catch (BaseException &ex) {
|
||||
if (IsDevBuild) {
|
||||
}
|
||||
catch (BaseException& ex)
|
||||
{
|
||||
if (IsDevBuild)
|
||||
{
|
||||
ex.DiagMsg() = L"Non-runtime BaseException thrown from event listener .. " + ex.DiagMsg();
|
||||
throw;
|
||||
}
|
||||
|
@ -87,7 +99,8 @@ __fi void EventSource<ListenerType>::_DispatchRaw(ListenerIterator iter, const L
|
|||
template <typename ListenerType>
|
||||
void EventSource<ListenerType>::Dispatch(const EvtParams& evtparams)
|
||||
{
|
||||
if (!m_cache_valid) {
|
||||
if (!m_cache_valid)
|
||||
{
|
||||
m_cache_copy = m_listeners;
|
||||
m_cache_valid = true;
|
||||
}
|
||||
|
|
|
@ -103,7 +103,8 @@ DEVASSERT_INLINE void pxOnAssert(const DiagnosticOrigin &origin, const wxString
|
|||
// we get meaningless assertions while unwinding stack traces after exceptions have occurred.
|
||||
|
||||
RecursionGuard guard(s_assert_guard);
|
||||
if (guard.Counter > 2) {
|
||||
if (guard.Counter > 2)
|
||||
{
|
||||
return pxTrap();
|
||||
}
|
||||
|
||||
|
@ -114,14 +115,18 @@ DEVASSERT_INLINE void pxOnAssert(const DiagnosticOrigin &origin, const wxString
|
|||
|
||||
bool trapit;
|
||||
|
||||
if (pxDoAssert == NULL) {
|
||||
if (pxDoAssert == NULL)
|
||||
{
|
||||
// Note: Format uses MSVC's syntax for output window hotlinking.
|
||||
trapit = pxAssertImpl_LogIt(origin, msg.wc_str());
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
trapit = pxDoAssert(origin, msg.wc_str());
|
||||
}
|
||||
|
||||
if (trapit) {
|
||||
if (trapit)
|
||||
{
|
||||
pxTrap();
|
||||
}
|
||||
}
|
||||
|
@ -389,7 +394,8 @@ BaseException *Exception::FromErrno(const wxString &streamname, int errcode)
|
|||
{
|
||||
pxAssumeDev(errcode != 0, "Invalid NULL error code? (errno)");
|
||||
|
||||
switch (errcode) {
|
||||
switch (errcode)
|
||||
{
|
||||
case EINVAL:
|
||||
pxFailDev(L"Invalid argument");
|
||||
return &(new Exception::BadStream(streamname))->SetDiagMsg(L"Invalid argument? (likely caused by an unforgivable programmer error!)");
|
||||
|
|
|
@ -35,19 +35,25 @@ void pxTrap();
|
|||
#define __DESTRUCTOR_CATCHALL(funcname) \
|
||||
catch (BaseException & ex) \
|
||||
{ \
|
||||
try { \
|
||||
try \
|
||||
{ \
|
||||
Console.Error("Unhandled BaseException in %s (ignored!):", funcname); \
|
||||
Console.Error(ex.FormatDiagnosticMessage()); \
|
||||
} catch (...) { \
|
||||
} \
|
||||
catch (...) \
|
||||
{ \
|
||||
fprintf(stderr, "ERROR: (out of memory?)\n"); \
|
||||
} \
|
||||
} \
|
||||
catch (std::exception & ex) \
|
||||
{ \
|
||||
try { \
|
||||
try \
|
||||
{ \
|
||||
Console.Error("Unhandled std::exception in %s (ignored!):", funcname); \
|
||||
Console.Error(ex.what()); \
|
||||
} catch (...) { \
|
||||
} \
|
||||
catch (...) \
|
||||
{ \
|
||||
fprintf(stderr, "ERROR: (out of memory?)\n"); \
|
||||
} \
|
||||
} \
|
||||
|
@ -162,8 +168,16 @@ private: \
|
|||
\
|
||||
public: \
|
||||
virtual ~classname() = default; \
|
||||
virtual void Rethrow() const { throw * this; } \
|
||||
virtual classname *Clone() const { return new classname(*this); }
|
||||
\
|
||||
virtual void Rethrow() const \
|
||||
{ \
|
||||
throw *this; \
|
||||
} \
|
||||
\
|
||||
virtual classname* Clone() const \
|
||||
{ \
|
||||
return new classname(*this); \
|
||||
}
|
||||
|
||||
#define DEFINE_EXCEPTION_MESSAGES(classname) \
|
||||
public: \
|
||||
|
@ -172,11 +186,13 @@ public: \
|
|||
BaseException::SetBothMsgs(msg_diag); \
|
||||
return *this; \
|
||||
} \
|
||||
\
|
||||
classname& SetDiagMsg(const wxString& msg_diag) \
|
||||
{ \
|
||||
m_message_diag = msg_diag; \
|
||||
return *this; \
|
||||
} \
|
||||
\
|
||||
classname& SetUserMsg(const wxString& msg_user) \
|
||||
{ \
|
||||
m_message_user = msg_user; \
|
||||
|
@ -185,7 +201,10 @@ public: \
|
|||
|
||||
#define DEFINE_RUNTIME_EXCEPTION(classname, parent, message) \
|
||||
DEFINE_EXCEPTION_COPYTORS(classname, parent) \
|
||||
classname() { SetDiagMsg(message); } \
|
||||
classname() \
|
||||
{ \
|
||||
SetDiagMsg(message); \
|
||||
} \
|
||||
DEFINE_EXCEPTION_MESSAGES(classname)
|
||||
|
||||
|
||||
|
@ -294,6 +313,7 @@ public:
|
|||
StreamName = name; \
|
||||
return *this; \
|
||||
} \
|
||||
\
|
||||
virtual classname& SetStreamName(const char* name) \
|
||||
{ \
|
||||
StreamName = fromUTF8(name); \
|
||||
|
@ -390,7 +410,7 @@ public:
|
|||
virtual wxString FormatDiagnosticMessage() const;
|
||||
};
|
||||
#endif
|
||||
}
|
||||
} // namespace Exception
|
||||
|
||||
using Exception::BaseException;
|
||||
using Exception::ScopedExcept;
|
||||
|
|
|
@ -33,15 +33,15 @@ template class SafeAlignedArray<u8, 16>;
|
|||
// system deadlock.
|
||||
static const int MaxFormattedStringLength = 0x80000;
|
||||
|
||||
static
|
||||
#ifndef __linux__
|
||||
__ri
|
||||
static __ri void format_that_ascii_mess(CharBufferType& buffer, uint writepos, const char* fmt, va_list argptr)
|
||||
#else
|
||||
static void format_that_ascii_mess(CharBufferType& buffer, uint writepos, const char* fmt, va_list argptr)
|
||||
#endif
|
||||
void
|
||||
format_that_ascii_mess(CharBufferType &buffer, uint writepos, const char *fmt, va_list argptr)
|
||||
{
|
||||
va_list args;
|
||||
while (true) {
|
||||
while (true)
|
||||
{
|
||||
int size = buffer.GetLength();
|
||||
|
||||
va_copy(args, argptr);
|
||||
|
@ -74,15 +74,15 @@ static
|
|||
}
|
||||
|
||||
// returns the length of the formatted string, in characters (wxChars).
|
||||
static
|
||||
#ifndef __linux__
|
||||
__ri
|
||||
static __ri uint format_that_unicode_mess(CharBufferType& buffer, uint writepos, const wxChar* fmt, va_list argptr)
|
||||
#else
|
||||
static uint format_that_unicode_mess(CharBufferType& buffer, uint writepos, const wxChar* fmt, va_list argptr)
|
||||
#endif
|
||||
uint
|
||||
format_that_unicode_mess(CharBufferType &buffer, uint writepos, const wxChar *fmt, va_list argptr)
|
||||
{
|
||||
va_list args;
|
||||
while (true) {
|
||||
while (true)
|
||||
{
|
||||
int size = buffer.GetLength() / sizeof(wxChar);
|
||||
|
||||
va_copy(args, argptr);
|
||||
|
|
|
@ -33,10 +33,8 @@
|
|||
{
|
||||
|
||||
#define BITFIELD_END \
|
||||
} \
|
||||
; \
|
||||
} \
|
||||
;
|
||||
}; \
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
@ -257,7 +255,7 @@ void MemProtectStatic(u8 (&arr)[size], const PageProtectionMode &mode)
|
|||
{
|
||||
MemProtect(arr, size, mode);
|
||||
}
|
||||
}
|
||||
} // namespace HostSys
|
||||
|
||||
// Safe version of Munmap -- NULLs the pointer variable immediately after free'ing it.
|
||||
#define SafeSysMunmap(ptr, size) \
|
||||
|
|
|
@ -29,7 +29,8 @@ void SetFullBaseDir(wxDirName appRoot)
|
|||
static int _calcEnumLength(const wxChar* const* enumArray)
|
||||
{
|
||||
int cnt = 0;
|
||||
while (*enumArray != NULL) {
|
||||
while (*enumArray != NULL)
|
||||
{
|
||||
enumArray++;
|
||||
cnt++;
|
||||
}
|
||||
|
@ -119,7 +120,8 @@ void IniLoader::Entry(const wxString &var, wxDirName &value, const wxDirName def
|
|||
|
||||
if (dest.IsEmpty())
|
||||
value = defvalue;
|
||||
else {
|
||||
else
|
||||
{
|
||||
value = dest;
|
||||
if (isAllowRelative)
|
||||
value = g_fullBaseDirName + value;
|
||||
|
@ -203,7 +205,8 @@ void IniLoader::Entry(const wxString &var, double& value, const double defvalue)
|
|||
|
||||
void IniLoader::Entry(const wxString& var, wxPoint& value, const wxPoint defvalue)
|
||||
{
|
||||
if (!m_Config) {
|
||||
if (!m_Config)
|
||||
{
|
||||
value = defvalue;
|
||||
return;
|
||||
}
|
||||
|
@ -212,7 +215,8 @@ void IniLoader::Entry(const wxString &var, wxPoint &value, const wxPoint defvalu
|
|||
|
||||
void IniLoader::Entry(const wxString& var, wxSize& value, const wxSize defvalue)
|
||||
{
|
||||
if (!m_Config) {
|
||||
if (!m_Config)
|
||||
{
|
||||
value = defvalue;
|
||||
return;
|
||||
}
|
||||
|
@ -221,7 +225,8 @@ void IniLoader::Entry(const wxString &var, wxSize &value, const wxSize defvalue)
|
|||
|
||||
void IniLoader::Entry(const wxString& var, wxRect& value, const wxRect defvalue)
|
||||
{
|
||||
if (!m_Config) {
|
||||
if (!m_Config)
|
||||
{
|
||||
value = defvalue;
|
||||
return;
|
||||
}
|
||||
|
@ -233,14 +238,16 @@ void IniLoader::_EnumEntry(const wxString &var, int &value, const wxChar *const
|
|||
// Confirm default value sanity...
|
||||
|
||||
const int cnt = _calcEnumLength(enumArray);
|
||||
if (!IndexBoundsCheck(L"IniLoader EnumDefaultValue", defvalue, cnt)) {
|
||||
if (!IndexBoundsCheck(L"IniLoader EnumDefaultValue", defvalue, cnt))
|
||||
{
|
||||
Console.Error("(LoadSettings) Default enumeration index is out of bounds. Truncating.");
|
||||
defvalue = cnt - 1;
|
||||
}
|
||||
|
||||
// Sanity confirmed, proceed with craziness!
|
||||
|
||||
if (!m_Config) {
|
||||
if (!m_Config)
|
||||
{
|
||||
value = defvalue;
|
||||
return;
|
||||
}
|
||||
|
@ -252,11 +259,13 @@ void IniLoader::_EnumEntry(const wxString &var, int &value, const wxChar *const
|
|||
while (enumArray[i] != NULL && (retval != enumArray[i]))
|
||||
i++;
|
||||
|
||||
if (enumArray[i] == NULL) {
|
||||
if (enumArray[i] == NULL)
|
||||
{
|
||||
Console.Warning(L"(LoadSettings) Warning: Unrecognized value '%s' on key '%s'\n\tUsing the default setting of '%s'.",
|
||||
WX_STR(retval), WX_STR(var), enumArray[defvalue]);
|
||||
value = defvalue;
|
||||
} else
|
||||
}
|
||||
else
|
||||
value = i;
|
||||
}
|
||||
|
||||
|
@ -390,7 +399,8 @@ void IniSaver::_EnumEntry(const wxString &var, int &value, const wxChar *const *
|
|||
|
||||
// Confirm default value sanity...
|
||||
|
||||
if (!IndexBoundsCheck(L"IniSaver EnumDefaultValue", defvalue, cnt)) {
|
||||
if (!IndexBoundsCheck(L"IniSaver EnumDefaultValue", defvalue, cnt))
|
||||
{
|
||||
Console.Error("(SaveSettings) Default enumeration index is out of bounds. Truncating.");
|
||||
defvalue = cnt - 1;
|
||||
}
|
||||
|
@ -398,7 +408,8 @@ void IniSaver::_EnumEntry(const wxString &var, int &value, const wxChar *const *
|
|||
if (!m_Config)
|
||||
return;
|
||||
|
||||
if (value >= cnt) {
|
||||
if (value >= cnt)
|
||||
{
|
||||
Console.Warning(L"(SaveSettings) An illegal enumerated index was detected when saving '%s'", WX_STR(var));
|
||||
Console.Indent().Warning(
|
||||
L"Illegal Value: %d\n"
|
||||
|
|
|
@ -64,7 +64,8 @@ static void SysPageFaultSignalFilter(int signal, siginfo_t *siginfo, void *)
|
|||
if (Source_PageFault->WasHandled())
|
||||
return;
|
||||
|
||||
if (!wxThread::IsMain()) {
|
||||
if (!wxThread::IsMain())
|
||||
{
|
||||
pxFailRel(pxsFmt("Unhandled page fault @ 0x%08x", siginfo->si_addr));
|
||||
}
|
||||
|
||||
|
@ -126,7 +127,8 @@ static bool _memprotect(void *baseaddr, size_t size, const PageProtectionMode &m
|
|||
if (result == 0)
|
||||
return true;
|
||||
|
||||
switch (errno) {
|
||||
switch (errno)
|
||||
{
|
||||
case EINVAL:
|
||||
pxFailDev(pxsFmt(L"mprotect returned EINVAL @ 0x%08X -> 0x%08X (mode=%s)",
|
||||
baseaddr, (uptr)baseaddr + size, WX_STR(mode.ToString())));
|
||||
|
@ -218,7 +220,8 @@ void HostSys::Munmap(uptr base, size_t size)
|
|||
|
||||
void HostSys::MemProtect(void* baseaddr, size_t size, const PageProtectionMode& mode)
|
||||
{
|
||||
if (!_memprotect(baseaddr, size, mode)) {
|
||||
if (!_memprotect(baseaddr, size, mode))
|
||||
{
|
||||
throw Exception::OutOfMemory(L"MemProtect")
|
||||
.SetDiagMsg(pxsFmt(L"mprotect failed @ 0x%08X -> 0x%08X (mode=%s)",
|
||||
baseaddr, (uptr)baseaddr + size, WX_STR(mode.ToString())));
|
||||
|
|
|
@ -71,11 +71,14 @@ u64 Threading::GetThreadTicksPerSecond()
|
|||
static u64 get_thread_time(uptr id = 0)
|
||||
{
|
||||
clockid_t cid;
|
||||
if (id) {
|
||||
if (id)
|
||||
{
|
||||
int err = pthread_getcpuclockid((pthread_t)id, &cid);
|
||||
if (err)
|
||||
return 0;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
cid = CLOCK_THREAD_CPUTIME_ID;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,15 +26,18 @@ __noinline void memset_sse_a(void *dest, const size_t size)
|
|||
|
||||
__m128 srcreg;
|
||||
|
||||
if (data != 0) {
|
||||
if (data != 0)
|
||||
{
|
||||
static __aligned16 const u8 loadval[8] = {data, data, data, data, data, data, data, data};
|
||||
srcreg = _mm_loadh_pi(_mm_load_ps((float*)loadval), (__m64*)loadval);
|
||||
} else
|
||||
}
|
||||
else
|
||||
srcreg = _mm_setzero_ps();
|
||||
|
||||
float(*destxmm)[4] = (float(*)[4])dest;
|
||||
|
||||
switch (MZFqwc & 0x07) {
|
||||
switch (MZFqwc & 0x07)
|
||||
{
|
||||
case 0x07:
|
||||
_mm_store_ps(&destxmm[0x07 - 1][0], srcreg);
|
||||
// Fall through
|
||||
|
@ -59,7 +62,8 @@ __noinline void memset_sse_a(void *dest, const size_t size)
|
|||
}
|
||||
|
||||
destxmm += (MZFqwc & 0x07);
|
||||
for (uint i = 0; i < MZFqwc / 8; ++i, destxmm += 8) {
|
||||
for (uint i = 0; i < MZFqwc / 8; ++i, destxmm += 8)
|
||||
{
|
||||
_mm_store_ps(&destxmm[0][0], srcreg);
|
||||
_mm_store_ps(&destxmm[1][0], srcreg);
|
||||
_mm_store_ps(&destxmm[2][0], srcreg);
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Threading
|
|||
{
|
||||
static std::atomic<int> _attr_refcount(0);
|
||||
static pthread_mutexattr_t _attr_recursive;
|
||||
}
|
||||
} // namespace Threading
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Mutex Implementations
|
||||
|
@ -57,14 +57,14 @@ static int xpthread_mutex_timedlock(
|
|||
{
|
||||
int err = 0;
|
||||
|
||||
while ((err = pthread_mutex_trylock(mutex)) == EBUSY) {
|
||||
while ((err = pthread_mutex_trylock(mutex)) == EBUSY)
|
||||
{
|
||||
// check if the timeout has expired, gettimeofday() is implemented
|
||||
// efficiently (in userspace) on OSX
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
if (now.tv_sec > abs_timeout->tv_sec
|
||||
|| (now.tv_sec == abs_timeout->tv_sec
|
||||
&& (u64)now.tv_usec * 1000ULL > (u64)abs_timeout->tv_nsec)) {
|
||||
if (now.tv_sec > abs_timeout->tv_sec || (now.tv_sec == abs_timeout->tv_sec && (u64)now.tv_usec * 1000ULL > (u64)abs_timeout->tv_nsec))
|
||||
{
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,8 @@ static int xpthread_mutex_timedlock(
|
|||
struct timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = TIMEDLOCK_EMU_SLEEP_NS;
|
||||
while (nanosleep(&ts, &ts) == -1);
|
||||
while (nanosleep(&ts, &ts) == -1)
|
||||
;
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@ -91,7 +92,8 @@ void Threading::Mutex::Detach()
|
|||
if (EBUSY != pthread_mutex_destroy(&m_mutex))
|
||||
return;
|
||||
|
||||
if (IsRecursive()) {
|
||||
if (IsRecursive())
|
||||
{
|
||||
// Sanity check: Recursive locks could be held by our own thread, which would
|
||||
// be considered an assertion failure, but can also be handled gracefully.
|
||||
// (note: if the mutex is locked recursively more than twice then this assert won't
|
||||
|
@ -112,7 +114,8 @@ void Threading::Mutex::Detach()
|
|||
|
||||
Threading::Mutex::~Mutex()
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
Mutex::Detach();
|
||||
}
|
||||
DESTRUCTOR_CATCHALL;
|
||||
|
@ -121,7 +124,8 @@ Threading::Mutex::~Mutex()
|
|||
Threading::MutexRecursive::MutexRecursive()
|
||||
: Mutex(false)
|
||||
{
|
||||
if (++_attr_refcount == 1) {
|
||||
if (++_attr_refcount == 1)
|
||||
{
|
||||
if (0 != pthread_mutexattr_init(&_attr_recursive))
|
||||
throw Exception::OutOfMemory(L"Recursive mutexing attributes");
|
||||
|
||||
|
@ -153,7 +157,8 @@ void Threading::Mutex::Recreate()
|
|||
// unlocked.
|
||||
bool Threading::Mutex::RecreateIfLocked()
|
||||
{
|
||||
if (!Wait(def_detach_timeout)) {
|
||||
if (!Wait(def_detach_timeout))
|
||||
{
|
||||
Recreate();
|
||||
return true;
|
||||
}
|
||||
|
@ -194,12 +199,17 @@ bool Threading::Mutex::TryAcquire()
|
|||
void Threading::Mutex::Acquire()
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
if (!wxThread::IsMain() || (wxTheApp == NULL)) {
|
||||
if (!wxThread::IsMain() || (wxTheApp == NULL))
|
||||
{
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
} else if (_WaitGui_RecursionGuard(L"Mutex::Acquire")) {
|
||||
}
|
||||
else if (_WaitGui_RecursionGuard(L"Mutex::Acquire"))
|
||||
{
|
||||
ScopedBusyCursor hourglass(Cursor_ReallyBusy);
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
//ScopedBusyCursor hourglass( Cursor_KindaBusy );
|
||||
while (!AcquireWithoutYield(def_yieldgui_interval))
|
||||
YieldToMain();
|
||||
|
@ -212,16 +222,22 @@ void Threading::Mutex::Acquire()
|
|||
bool Threading::Mutex::Acquire(const wxTimeSpan& timeout)
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
if (!wxThread::IsMain() || (wxTheApp == NULL)) {
|
||||
if (!wxThread::IsMain() || (wxTheApp == NULL))
|
||||
{
|
||||
return AcquireWithoutYield(timeout);
|
||||
} else if (_WaitGui_RecursionGuard(L"Mutex::TimedAcquire")) {
|
||||
}
|
||||
else if (_WaitGui_RecursionGuard(L"Mutex::TimedAcquire"))
|
||||
{
|
||||
ScopedBusyCursor hourglass(Cursor_ReallyBusy);
|
||||
return AcquireWithoutYield(timeout);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
//ScopedBusyCursor hourglass( Cursor_KindaBusy );
|
||||
wxTimeSpan countdown((timeout));
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (AcquireWithoutYield(def_yieldgui_interval))
|
||||
break;
|
||||
YieldToMain();
|
||||
|
@ -264,7 +280,8 @@ void Threading::Mutex::WaitWithoutYield()
|
|||
//
|
||||
bool Threading::Mutex::Wait(const wxTimeSpan& timeout)
|
||||
{
|
||||
if (Acquire(timeout)) {
|
||||
if (Acquire(timeout))
|
||||
{
|
||||
Release();
|
||||
return true;
|
||||
}
|
||||
|
@ -273,7 +290,8 @@ bool Threading::Mutex::Wait(const wxTimeSpan &timeout)
|
|||
|
||||
bool Threading::Mutex::WaitWithoutYield(const wxTimeSpan& timeout)
|
||||
{
|
||||
if (AcquireWithoutYield(timeout)) {
|
||||
if (AcquireWithoutYield(timeout))
|
||||
{
|
||||
Release();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -155,7 +155,8 @@ public:
|
|||
// offsetLocation must be page-aligned
|
||||
void* Alloc(uptr offsetLocation, size_t size) const;
|
||||
|
||||
void *AllocAtAddress(void *address, size_t size) const {
|
||||
void* AllocAtAddress(void* address, size_t size) const
|
||||
{
|
||||
return Alloc(size, (uptr)address - m_baseptr);
|
||||
}
|
||||
|
||||
|
@ -176,6 +177,7 @@ class VirtualMemoryBumpAllocator
|
|||
const VirtualMemoryManagerPtr m_allocator;
|
||||
std::atomic<uptr> m_baseptr{0};
|
||||
const uptr m_endptr = 0;
|
||||
|
||||
public:
|
||||
VirtualMemoryBumpAllocator(VirtualMemoryManagerPtr allocator, size_t size, uptr offsetLocation);
|
||||
void* Alloc(size_t size);
|
||||
|
|
|
@ -86,7 +86,8 @@ public:
|
|||
|
||||
wxFileName f(file);
|
||||
|
||||
while (1) {
|
||||
while (1)
|
||||
{
|
||||
if (this->SameAs(wxDirName(f.GetPath())))
|
||||
return true;
|
||||
|
||||
|
@ -124,9 +125,12 @@ public:
|
|||
wxString sv(subject.GetVolume());
|
||||
sv.MakeUpper();
|
||||
|
||||
if (base.IsContains(subject)) {
|
||||
if (base.IsContains(subject))
|
||||
{
|
||||
subject.MakeRelativeTo(base.GetFullPath());
|
||||
} else if (base.HasVolume() && subject.HasVolume() && bv == sv) {
|
||||
}
|
||||
else if (base.HasVolume() && subject.HasVolume() && bv == sv)
|
||||
{
|
||||
wxString unusedVolume;
|
||||
wxString pathSansVolume;
|
||||
subject.SplitVolume(subject.GetFullPath(), &unusedVolume, &pathSansVolume);
|
||||
|
@ -227,4 +231,4 @@ extern wxString GetFilename(const wxString &src);
|
|||
extern wxString GetDirectory(const wxString& src);
|
||||
extern wxString GetFilenameWithoutExt(const wxString& src);
|
||||
extern wxString GetRootDirectory(const wxString& src);
|
||||
}
|
||||
} // namespace Path
|
||||
|
|
|
@ -100,7 +100,8 @@ void InfoVector::map(uptr x86, u32 size, const char *symbol)
|
|||
u32 max_code_size = _1gb;
|
||||
#endif
|
||||
|
||||
if (size < max_code_size) {
|
||||
if (size < max_code_size)
|
||||
{
|
||||
m_v.emplace_back(x86, size, symbol);
|
||||
|
||||
#ifdef ENABLE_VTUNE
|
||||
|
@ -203,4 +204,4 @@ void dump() {}
|
|||
void dump_and_reset() {}
|
||||
|
||||
#endif
|
||||
}
|
||||
} // namespace Perf
|
||||
|
|
|
@ -59,4 +59,4 @@ extern InfoVector ee;
|
|||
extern InfoVector iop;
|
||||
extern InfoVector vu;
|
||||
extern InfoVector vif;
|
||||
}
|
||||
} // namespace Perf
|
||||
|
|
|
@ -206,4 +206,4 @@ protected:
|
|||
static void internal_callback_helper(void* func);
|
||||
static void _pt_callback_cleanup(void* handle);
|
||||
};
|
||||
}
|
||||
} // namespace Threading
|
||||
|
|
|
@ -87,4 +87,4 @@ public:
|
|||
protected:
|
||||
ScopedWriteLock(RwMutex& locker, bool isTryLock);
|
||||
};
|
||||
}
|
||||
} // namespace Threading
|
||||
|
|
|
@ -42,7 +42,8 @@ T *SafeArray<T>::_virtual_realloc(int newsize)
|
|||
malloc(newsize * sizeof(T)) :
|
||||
realloc(m_ptr, newsize * sizeof(T)));
|
||||
|
||||
if (IsDebugBuild && (retval != NULL)) {
|
||||
if (IsDebugBuild && (retval != NULL))
|
||||
{
|
||||
// Zero everything out to 0xbaadf00d, so that its obviously uncleared
|
||||
// to a debuggee
|
||||
|
||||
|
@ -201,7 +202,8 @@ SafeList<T>::SafeList(int initialSize, const wxChar *name)
|
|||
throw Exception::OutOfMemory(Name)
|
||||
.SetDiagMsg(wxsFormat(L"called from 'SafeList::ctor' [length=%d]", m_length));
|
||||
|
||||
for (int i = 0; i < m_allocsize; ++i) {
|
||||
for (int i = 0; i < m_allocsize; ++i)
|
||||
{
|
||||
new (&m_ptr[i]) T();
|
||||
}
|
||||
}
|
||||
|
@ -218,14 +220,16 @@ T *SafeList<T>::_getPtr(uint i) const
|
|||
template <typename T>
|
||||
void SafeList<T>::MakeRoomFor(int blockSize)
|
||||
{
|
||||
if (blockSize > m_allocsize) {
|
||||
if (blockSize > m_allocsize)
|
||||
{
|
||||
const int newalloc = blockSize + ChunkSize;
|
||||
m_ptr = _virtual_realloc(newalloc);
|
||||
if (m_ptr == NULL)
|
||||
throw Exception::OutOfMemory(Name)
|
||||
.SetDiagMsg(wxsFormat(L"Called from 'SafeList::MakeRoomFor' [oldlen=%d] [newlen=%d]", m_length, blockSize));
|
||||
|
||||
for (; m_allocsize < newalloc; ++m_allocsize) {
|
||||
for (; m_allocsize < newalloc; ++m_allocsize)
|
||||
{
|
||||
new (&m_ptr[m_allocsize]) T();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,8 @@ void Threading::Semaphore::Post(int multiple)
|
|||
sem_post_multiple(&m_sema, multiple);
|
||||
#else
|
||||
// Only w32pthreads has the post_multiple, but it's easy enough to fake:
|
||||
while (multiple > 0) {
|
||||
while (multiple > 0)
|
||||
{
|
||||
multiple--;
|
||||
sem_post(&m_sema);
|
||||
}
|
||||
|
@ -80,12 +81,17 @@ bool Threading::Semaphore::WaitWithoutYield(const wxTimeSpan &timeout)
|
|||
void Threading::Semaphore::Wait()
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
if (!wxThread::IsMain() || (wxTheApp == NULL)) {
|
||||
if (!wxThread::IsMain() || (wxTheApp == NULL))
|
||||
{
|
||||
sem_wait(&m_sema);
|
||||
} else if (_WaitGui_RecursionGuard(L"Semaphore::Wait")) {
|
||||
}
|
||||
else if (_WaitGui_RecursionGuard(L"Semaphore::Wait"))
|
||||
{
|
||||
ScopedBusyCursor hourglass(Cursor_ReallyBusy);
|
||||
sem_wait(&m_sema);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
//ScopedBusyCursor hourglass( Cursor_KindaBusy );
|
||||
while (!WaitWithoutYield(def_yieldgui_interval))
|
||||
YieldToMain();
|
||||
|
@ -107,16 +113,22 @@ void Threading::Semaphore::Wait()
|
|||
bool Threading::Semaphore::Wait(const wxTimeSpan& timeout)
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
if (!wxThread::IsMain() || (wxTheApp == NULL)) {
|
||||
if (!wxThread::IsMain() || (wxTheApp == NULL))
|
||||
{
|
||||
return WaitWithoutYield(timeout);
|
||||
} else if (_WaitGui_RecursionGuard(L"Semaphore::TimedWait")) {
|
||||
}
|
||||
else if (_WaitGui_RecursionGuard(L"Semaphore::TimedWait"))
|
||||
{
|
||||
ScopedBusyCursor hourglass(Cursor_ReallyBusy);
|
||||
return WaitWithoutYield(timeout);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
//ScopedBusyCursor hourglass( Cursor_KindaBusy );
|
||||
wxTimeSpan countdown((timeout));
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (WaitWithoutYield(def_yieldgui_interval))
|
||||
break;
|
||||
YieldToMain();
|
||||
|
|
|
@ -94,7 +94,8 @@ void SplitString(wxArrayString &dest, const wxString &src, const wxString &delim
|
|||
wxString JoinString(const wxArrayString& src, const wxString& separator)
|
||||
{
|
||||
wxString dest;
|
||||
for (int i = 0, len = src.GetCount(); i < len; ++i) {
|
||||
for (int i = 0, len = src.GetCount(); i < len; ++i)
|
||||
{
|
||||
if (src[i].IsEmpty())
|
||||
continue;
|
||||
if (!dest.IsEmpty())
|
||||
|
@ -107,7 +108,8 @@ wxString JoinString(const wxArrayString &src, const wxString &separator)
|
|||
wxString JoinString(const wxChar** src, const wxString& separator)
|
||||
{
|
||||
wxString dest;
|
||||
while (*src != NULL) {
|
||||
while (*src != NULL)
|
||||
{
|
||||
if (*src[0] == 0)
|
||||
continue;
|
||||
|
||||
|
@ -260,10 +262,14 @@ void px_fputs(FILE *fp, const char *src)
|
|||
|
||||
const char* curchar = src;
|
||||
bool prevcr = false;
|
||||
while (*curchar != 0) {
|
||||
if (*curchar == '\r') {
|
||||
while (*curchar != 0)
|
||||
{
|
||||
if (*curchar == '\r')
|
||||
{
|
||||
prevcr = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only write a CR/LF pair if the current LF is not prefixed nor
|
||||
// post-fixed by a CR.
|
||||
if (*curchar == '\n' && !prevcr && (*(curchar + 1) != '\r'))
|
||||
|
|
|
@ -75,7 +75,8 @@ static void make_curthread_key(const pxThread *thr)
|
|||
if (total_key_count++ != 0)
|
||||
return;
|
||||
|
||||
if (0 != pthread_key_create(&curthread_key, NULL)) {
|
||||
if (0 != pthread_key_create(&curthread_key, NULL))
|
||||
{
|
||||
pxThreadLog.Error(thr->GetName(), L"Thread key creation failed (probably out of memory >_<)");
|
||||
curthread_key = 0;
|
||||
}
|
||||
|
@ -114,9 +115,12 @@ pxThread *Threading::pxGetCurrentThread()
|
|||
// nor the Main/UI thread.
|
||||
wxString Threading::pxGetCurrentThreadName()
|
||||
{
|
||||
if (pxThread *thr = pxGetCurrentThread()) {
|
||||
if (pxThread* thr = pxGetCurrentThread())
|
||||
{
|
||||
return thr->GetName();
|
||||
} else if (wxThread::IsMain()) {
|
||||
}
|
||||
else if (wxThread::IsMain())
|
||||
{
|
||||
return L"Main/UI";
|
||||
}
|
||||
|
||||
|
@ -184,10 +188,12 @@ Threading::pxThread::pxThread(const wxString &name)
|
|||
// like marrying your sister, and then cheating on her with your daughter.
|
||||
Threading::pxThread::~pxThread()
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
pxThreadLog.Write(GetName(), L"Executing default destructor!");
|
||||
|
||||
if (m_running) {
|
||||
if (m_running)
|
||||
{
|
||||
pxThreadLog.Write(GetName(), L"Waiting for running thread to end...");
|
||||
m_mtx_InThread.Wait();
|
||||
pxThreadLog.Write(GetName(), L"Thread ended gracefully.");
|
||||
|
@ -222,7 +228,8 @@ bool Threading::pxThread::AffinityAssert_DisallowFromSelf(const DiagnosticOrigin
|
|||
|
||||
void Threading::pxThread::FrankenMutex(Mutex& mutex)
|
||||
{
|
||||
if (mutex.RecreateIfLocked()) {
|
||||
if (mutex.RecreateIfLocked())
|
||||
{
|
||||
// Our lock is bupkis, which means the previous thread probably deadlocked.
|
||||
// Let's create a new mutex lock to replace it.
|
||||
|
||||
|
@ -240,7 +247,8 @@ void Threading::pxThread::Start()
|
|||
{
|
||||
// Prevents sudden parallel startup, and or parallel startup + cancel:
|
||||
ScopedLock startlock(m_mtx_start);
|
||||
if (m_running) {
|
||||
if (m_running)
|
||||
{
|
||||
pxThreadLog.Write(GetName(), L"Start() called on running thread; ignorning...");
|
||||
return;
|
||||
}
|
||||
|
@ -259,12 +267,14 @@ void Threading::pxThread::Start()
|
|||
//
|
||||
// In our case, the semaphore was posted (counter is 1) but thread is still
|
||||
// waiting... So waits 100ms and checks the counter value manually
|
||||
if (!m_sem_startup.WaitWithoutYield(wxTimeSpan(0, 0, 0, 100))) {
|
||||
if (!m_sem_startup.WaitWithoutYield(wxTimeSpan(0, 0, 0, 100)))
|
||||
{
|
||||
if (m_sem_startup.Count() == 0)
|
||||
throw Exception::ThreadCreationError(this).SetDiagMsg(L"Thread creation error: %s thread never posted startup semaphore.");
|
||||
}
|
||||
#else
|
||||
if (!m_sem_startup.WaitWithoutYield(wxTimeSpan(0, 0, 3, 0))) {
|
||||
if (!m_sem_startup.WaitWithoutYield(wxTimeSpan(0, 0, 3, 0)))
|
||||
{
|
||||
RethrowException();
|
||||
|
||||
// And if the thread threw nothing of its own:
|
||||
|
@ -305,7 +315,8 @@ bool Threading::pxThread::_basecancel()
|
|||
if (!m_running)
|
||||
return false;
|
||||
|
||||
if (m_detached) {
|
||||
if (m_detached)
|
||||
{
|
||||
pxThreadLog.Warn(GetName(), L"Ignoring attempted cancellation of detached thread.");
|
||||
return false;
|
||||
}
|
||||
|
@ -338,7 +349,8 @@ void Threading::pxThread::Cancel(bool isBlocking)
|
|||
if (!_basecancel())
|
||||
return;
|
||||
|
||||
if (isBlocking) {
|
||||
if (isBlocking)
|
||||
{
|
||||
WaitOnSelf(m_mtx_InThread);
|
||||
Detach();
|
||||
}
|
||||
|
@ -432,12 +444,14 @@ void Threading::YieldToMain()
|
|||
|
||||
void Threading::pxThread::_selfRunningTest(const wxChar* name) const
|
||||
{
|
||||
if (HasPendingException()) {
|
||||
if (HasPendingException())
|
||||
{
|
||||
pxThreadLog.Error(GetName(), pxsFmt(L"An exception was thrown while waiting on a %s.", name));
|
||||
RethrowException();
|
||||
}
|
||||
|
||||
if (!m_running) {
|
||||
if (!m_running)
|
||||
{
|
||||
throw Exception::CancelEvent(pxsFmt(
|
||||
L"Blocking thread %s was terminated while another thread was waiting on a %s.",
|
||||
WX_STR(GetName()), name));
|
||||
|
@ -467,7 +481,8 @@ void Threading::pxThread::WaitOnSelf(Semaphore &sem) const
|
|||
if (!AffinityAssert_DisallowFromSelf(pxDiagSpot))
|
||||
return;
|
||||
|
||||
while (true) {
|
||||
while (true)
|
||||
{
|
||||
if (sem.WaitWithoutYield(wxTimeSpan(0, 0, 0, 333)))
|
||||
return;
|
||||
_selfRunningTest(L"semaphore");
|
||||
|
@ -492,7 +507,8 @@ void Threading::pxThread::WaitOnSelf(Mutex &mutex) const
|
|||
if (!AffinityAssert_DisallowFromSelf(pxDiagSpot))
|
||||
return;
|
||||
|
||||
while (true) {
|
||||
while (true)
|
||||
{
|
||||
if (mutex.WaitWithoutYield(wxTimeSpan(0, 0, 0, 333)))
|
||||
return;
|
||||
_selfRunningTest(L"mutex");
|
||||
|
@ -508,7 +524,8 @@ bool Threading::pxThread::WaitOnSelf(Semaphore &sem, const wxTimeSpan &timeout)
|
|||
|
||||
wxTimeSpan runningout(timeout);
|
||||
|
||||
while (runningout.GetMilliseconds() > 0) {
|
||||
while (runningout.GetMilliseconds() > 0)
|
||||
{
|
||||
const wxTimeSpan interval((SelfWaitInterval < runningout) ? SelfWaitInterval : runningout);
|
||||
if (sem.WaitWithoutYield(interval))
|
||||
return true;
|
||||
|
@ -525,7 +542,8 @@ bool Threading::pxThread::WaitOnSelf(Mutex &mutex, const wxTimeSpan &timeout) co
|
|||
|
||||
wxTimeSpan runningout(timeout);
|
||||
|
||||
while (runningout.GetMilliseconds() > 0) {
|
||||
while (runningout.GetMilliseconds() > 0)
|
||||
{
|
||||
const wxTimeSpan interval((SelfWaitInterval < runningout) ? SelfWaitInterval : runningout);
|
||||
if (mutex.WaitWithoutYield(interval))
|
||||
return true;
|
||||
|
@ -548,19 +566,22 @@ void Threading::pxThread::TestCancel() const
|
|||
// Executes the virtual member method
|
||||
void Threading::pxThread::_try_virtual_invoke(void (pxThread::*method)())
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
(this->*method)();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Neat repackaging for STL Runtime errors...
|
||||
//
|
||||
catch (std::runtime_error &ex) {
|
||||
catch (std::runtime_error& ex)
|
||||
{
|
||||
m_except = new Exception::RuntimeError(ex, WX_STR(GetName()));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
catch (Exception::RuntimeError &ex) {
|
||||
catch (Exception::RuntimeError& ex)
|
||||
{
|
||||
BaseException* woot = ex.Clone();
|
||||
woot->DiagMsg() += pxsFmt(L"(thread:%s)", WX_STR(GetName()));
|
||||
m_except = woot;
|
||||
|
@ -585,7 +606,8 @@ void Threading::pxThread::_try_virtual_invoke(void (pxThread::*method)())
|
|||
// ----------------------------------------------------------------------------
|
||||
// BaseException -- same deal as LogicErrors.
|
||||
//
|
||||
catch (BaseException &ex) {
|
||||
catch (BaseException& ex)
|
||||
{
|
||||
BaseException* woot = ex.Clone();
|
||||
woot->DiagMsg() += pxsFmt(L"(thread:%s)", WX_STR(GetName()));
|
||||
m_except = woot;
|
||||
|
|
|
@ -100,7 +100,7 @@ extern u64 GetThreadTicksPerSecond();
|
|||
// Yields the current thread and provides cancellation points if the thread is managed by
|
||||
// pxThread. Unmanaged threads use standard Sleep.
|
||||
extern void pxYield(int ms);
|
||||
}
|
||||
} // namespace Threading
|
||||
|
||||
namespace Exception
|
||||
{
|
||||
|
@ -155,7 +155,7 @@ public:
|
|||
SetBothMsgs(L"Thread creation failure. An unspecified error occurred while trying to create the %s thread.");
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace Exception
|
||||
|
||||
|
||||
namespace Threading
|
||||
|
@ -422,4 +422,4 @@ struct ScopedLockBool
|
|||
m_lock.Release();
|
||||
}
|
||||
};
|
||||
}
|
||||
} // namespace Threading
|
||||
|
|
|
@ -49,4 +49,4 @@ protected:
|
|||
void OnTaskComplete(wxCommandEvent& evt);
|
||||
//void OnTimer( wxTimerEvent& evt );
|
||||
};
|
||||
}
|
||||
} // namespace Threading
|
||||
|
|
|
@ -27,4 +27,4 @@ extern bool _WaitGui_RecursionGuard(const wxChar *name);
|
|||
|
||||
extern void YieldToMain();
|
||||
extern bool AllowDeletions();
|
||||
}
|
||||
} // namespace Threading
|
||||
|
|
|
@ -27,7 +27,8 @@ Threading::Mutex PageFault_Mutex;
|
|||
|
||||
void pxInstallSignalHandler()
|
||||
{
|
||||
if (!Source_PageFault) {
|
||||
if (!Source_PageFault)
|
||||
{
|
||||
Source_PageFault = new SrcType_PageFault();
|
||||
}
|
||||
|
||||
|
@ -59,7 +60,8 @@ void SrcType_PageFault::Dispatch(const PageFaultInfo ¶ms)
|
|||
|
||||
void SrcType_PageFault::_DispatchRaw(ListenerIterator iter, const ListenerIterator& iend, const PageFaultInfo& evt)
|
||||
{
|
||||
do {
|
||||
do
|
||||
{
|
||||
(*iter)->DispatchEvent(evt, m_handled);
|
||||
} while ((++iter != iend) && !m_handled);
|
||||
}
|
||||
|
@ -74,22 +76,28 @@ static size_t pageAlign(size_t size)
|
|||
// --------------------------------------------------------------------------------------
|
||||
|
||||
VirtualMemoryManager::VirtualMemoryManager(const wxString& name, uptr base, size_t size, uptr upper_bounds, bool strict)
|
||||
: m_name(name), m_baseptr(0), m_pageuse(nullptr), m_pages_reserved(0)
|
||||
: m_name(name)
|
||||
, m_baseptr(0)
|
||||
, m_pageuse(nullptr)
|
||||
, m_pages_reserved(0)
|
||||
{
|
||||
if (!size) return;
|
||||
if (!size)
|
||||
return;
|
||||
|
||||
uptr reserved_bytes = pageAlign(size);
|
||||
m_pages_reserved = reserved_bytes / __pagesize;
|
||||
|
||||
m_baseptr = (uptr)HostSys::MmapReserve(base, reserved_bytes);
|
||||
|
||||
if (!m_baseptr || (upper_bounds != 0 && (((uptr)m_baseptr + reserved_bytes) > upper_bounds))) {
|
||||
if (!m_baseptr || (upper_bounds != 0 && (((uptr)m_baseptr + reserved_bytes) > upper_bounds)))
|
||||
{
|
||||
DevCon.Warning(L"%s: host memory @ %ls -> %ls is unavailable; attempting to map elsewhere...",
|
||||
WX_STR(m_name), pxsPtr(base), pxsPtr(base + size));
|
||||
|
||||
SafeSysMunmap(m_baseptr, reserved_bytes);
|
||||
|
||||
if (base) {
|
||||
if (base)
|
||||
{
|
||||
// Let's try again at an OS-picked memory area, and then hope it meets needed
|
||||
// boundschecking criteria below.
|
||||
m_baseptr = (uptr)HostSys::MmapReserve(0, reserved_bytes);
|
||||
|
@ -101,11 +109,13 @@ VirtualMemoryManager::VirtualMemoryManager(const wxString &name, uptr base, size
|
|||
fulfillsRequirements = false;
|
||||
if ((upper_bounds != 0) && ((m_baseptr + reserved_bytes) > upper_bounds))
|
||||
fulfillsRequirements = false;
|
||||
if (!fulfillsRequirements) {
|
||||
if (!fulfillsRequirements)
|
||||
{
|
||||
SafeSysMunmap(m_baseptr, reserved_bytes);
|
||||
}
|
||||
|
||||
if (!m_baseptr) return;
|
||||
if (!m_baseptr)
|
||||
return;
|
||||
|
||||
m_pageuse = new std::atomic<bool>[m_pages_reserved]();
|
||||
|
||||
|
@ -122,17 +132,24 @@ VirtualMemoryManager::VirtualMemoryManager(const wxString &name, uptr base, size
|
|||
|
||||
VirtualMemoryManager::~VirtualMemoryManager()
|
||||
{
|
||||
if (m_pageuse) delete[] m_pageuse;
|
||||
if (m_baseptr) HostSys::Munmap(m_baseptr, m_pages_reserved * __pagesize);
|
||||
if (m_pageuse)
|
||||
delete[] m_pageuse;
|
||||
if (m_baseptr)
|
||||
HostSys::Munmap(m_baseptr, m_pages_reserved * __pagesize);
|
||||
}
|
||||
|
||||
static bool VMMMarkPagesAsInUse(std::atomic<bool> *begin, std::atomic<bool> *end) {
|
||||
for (auto current = begin; current < end; current++) {
|
||||
static bool VMMMarkPagesAsInUse(std::atomic<bool>* begin, std::atomic<bool>* end)
|
||||
{
|
||||
for (auto current = begin; current < end; current++)
|
||||
{
|
||||
bool expected = false;
|
||||
if (!current->compare_exchange_strong(expected, true), std::memory_order_relaxed) {
|
||||
if (!current->compare_exchange_strong(expected, true), std::memory_order_relaxed)
|
||||
{
|
||||
// This was already allocated! Undo the things we've set until this point
|
||||
while (--current >= begin) {
|
||||
if (!current->compare_exchange_strong(expected, false, std::memory_order_relaxed)) {
|
||||
while (--current >= begin)
|
||||
{
|
||||
if (!current->compare_exchange_strong(expected, false, std::memory_order_relaxed))
|
||||
{
|
||||
// In the time we were doing this, someone set one of the things we just set to true back to false
|
||||
// This should never happen, but if it does we'll just stop and hope nothing bad happens
|
||||
pxAssert(0);
|
||||
|
@ -164,7 +181,8 @@ void *VirtualMemoryManager::Alloc(uptr offsetLocation, size_t size) const
|
|||
void VirtualMemoryManager::Free(void* address, size_t size) const
|
||||
{
|
||||
uptr offsetLocation = (uptr)address - m_baseptr;
|
||||
if (!pxAssertDev(offsetLocation % __pagesize == 0, "(VirtualMemoryManager) free at unaligned address")) {
|
||||
if (!pxAssertDev(offsetLocation % __pagesize == 0, "(VirtualMemoryManager) free at unaligned address"))
|
||||
{
|
||||
uptr newLoc = pageAlign(offsetLocation);
|
||||
size -= (offsetLocation - newLoc);
|
||||
offsetLocation = newLoc;
|
||||
|
@ -175,9 +193,11 @@ void VirtualMemoryManager::Free(void *address, size_t size) const
|
|||
return;
|
||||
auto puStart = &m_pageuse[offsetLocation / __pagesize];
|
||||
auto puEnd = &m_pageuse[(offsetLocation + size) / __pagesize];
|
||||
for (; puStart < puEnd; puStart++) {
|
||||
for (; puStart < puEnd; puStart++)
|
||||
{
|
||||
bool expected = true;
|
||||
if (!puStart->compare_exchange_strong(expected, false, std::memory_order_relaxed)) {
|
||||
if (!puStart->compare_exchange_strong(expected, false, std::memory_order_relaxed))
|
||||
{
|
||||
pxAssertDev(0, "(VirtaulMemoryManager) double-free");
|
||||
}
|
||||
}
|
||||
|
@ -187,7 +207,9 @@ void VirtualMemoryManager::Free(void *address, size_t size) const
|
|||
// VirtualMemoryBumpAllocator (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
VirtualMemoryBumpAllocator::VirtualMemoryBumpAllocator(VirtualMemoryManagerPtr allocator, uptr offsetLocation, size_t size)
|
||||
: m_allocator(std::move(allocator)), m_baseptr((uptr)m_allocator->Alloc(offsetLocation, size)), m_endptr(m_baseptr + size)
|
||||
: m_allocator(std::move(allocator))
|
||||
, m_baseptr((uptr)m_allocator->Alloc(offsetLocation, size))
|
||||
, m_endptr(m_baseptr + size)
|
||||
{
|
||||
if (m_baseptr.load() == 0)
|
||||
pxAssertDev(0, "(VirtualMemoryBumpAllocator) tried to construct from bad VirtualMemoryManager");
|
||||
|
@ -296,7 +318,8 @@ void VirtualMemoryReserve::Reset()
|
|||
|
||||
void VirtualMemoryReserve::Release()
|
||||
{
|
||||
if (!m_baseptr) return;
|
||||
if (!m_baseptr)
|
||||
return;
|
||||
Reset();
|
||||
m_allocator->Free(m_baseptr, m_pages_reserved * __pagesize);
|
||||
m_baseptr = nullptr;
|
||||
|
@ -339,13 +362,15 @@ bool VirtualMemoryReserve::TryResize(uint newsize)
|
|||
{
|
||||
uint newPages = pageAlign(newsize) / __pagesize;
|
||||
|
||||
if (newPages > m_pages_reserved) {
|
||||
if (newPages > m_pages_reserved)
|
||||
{
|
||||
uint toReservePages = newPages - m_pages_reserved;
|
||||
uint toReserveBytes = toReservePages * __pagesize;
|
||||
|
||||
DevCon.WriteLn(L"%-32s is being expanded by %u pages.", WX_STR(m_name), toReservePages);
|
||||
|
||||
if (!m_allocator->AllocAtAddress(GetPtrEnd(), toReserveBytes)) {
|
||||
if (!m_allocator->AllocAtAddress(GetPtrEnd(), toReserveBytes))
|
||||
{
|
||||
Console.Warning("%-32s could not be passively resized due to virtual memory conflict!", WX_STR(m_name));
|
||||
Console.Indent().Warning("(attempted to map memory @ %08p -> %08p)", m_baseptr, (uptr)m_baseptr + toReserveBytes);
|
||||
return false;
|
||||
|
@ -353,7 +378,9 @@ bool VirtualMemoryReserve::TryResize(uint newsize)
|
|||
|
||||
DevCon.WriteLn(Color_Gray, L"%-32s @ %08p -> %08p [%umb]", WX_STR(m_name),
|
||||
m_baseptr, (uptr)m_baseptr + toReserveBytes, toReserveBytes / _1mb);
|
||||
} else if (newPages < m_pages_reserved) {
|
||||
}
|
||||
else if (newPages < m_pages_reserved)
|
||||
{
|
||||
if (m_pages_commited > newsize)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -39,9 +39,12 @@ long __stdcall SysPageFaultExceptionFilter(EXCEPTION_POINTERS *eps)
|
|||
// exception.
|
||||
// TODO: find a reliable way to debug the filter itself, I've come up with a few ways that
|
||||
// work but I don't fully understand why some do and some don't.
|
||||
__try {
|
||||
__try
|
||||
{
|
||||
return DoSysPageFaultExceptionFilter(eps);
|
||||
} __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
|
||||
}
|
||||
__except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
|
||||
{
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
}
|
||||
|
@ -62,9 +65,12 @@ static DWORD ConvertToWinApi(const PageProtectionMode &mode)
|
|||
// numbering (like flags) but is in fact not a flag value. *Someone* from the early
|
||||
// microsoft days wasn't a very good coder, me thinks. --air
|
||||
|
||||
if (mode.CanExecute()) {
|
||||
if (mode.CanExecute())
|
||||
{
|
||||
winmode = mode.CanWrite() ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ;
|
||||
} else if (mode.CanRead()) {
|
||||
}
|
||||
else if (mode.CanRead())
|
||||
{
|
||||
winmode = mode.CanWrite() ? PAGE_READWRITE : PAGE_READONLY;
|
||||
}
|
||||
|
||||
|
@ -83,10 +89,13 @@ bool HostSys::MmapCommitPtr(void *base, size_t size, const PageProtectionMode &m
|
|||
return true;
|
||||
|
||||
const DWORD errcode = GetLastError();
|
||||
if (errcode == ERROR_COMMITMENT_MINIMUM) {
|
||||
if (errcode == ERROR_COMMITMENT_MINIMUM)
|
||||
{
|
||||
Console.Warning("(MmapCommit) Received windows error %u {Virtual Memory Minimum Too Low}.", ERROR_COMMITMENT_MINIMUM);
|
||||
Sleep(1000); // Cut windows some time to rework its memory...
|
||||
} else if (errcode != ERROR_NOT_ENOUGH_MEMORY && errcode != ERROR_OUTOFMEMORY) {
|
||||
}
|
||||
else if (errcode != ERROR_NOT_ENOUGH_MEMORY && errcode != ERROR_OUTOFMEMORY)
|
||||
{
|
||||
pxFailDev(L"VirtualAlloc COMMIT failed: " + Exception::WinApiError().GetMsgFromWindows());
|
||||
return false;
|
||||
}
|
||||
|
@ -140,7 +149,8 @@ void HostSys::MemProtect(void *baseaddr, size_t size, const PageProtectionMode &
|
|||
__pagesize, __pagesize, size, size));
|
||||
|
||||
DWORD OldProtect; // enjoy my uselessness, yo!
|
||||
if (!VirtualProtect(baseaddr, size, ConvertToWinApi(mode), &OldProtect)) {
|
||||
if (!VirtualProtect(baseaddr, size, ConvertToWinApi(mode), &OldProtect))
|
||||
{
|
||||
Exception::WinApiError apiError;
|
||||
|
||||
apiError.SetDiagMsg(
|
||||
|
|
|
@ -126,9 +126,12 @@ void Threading::SetNameOfCurrentThread(const char *name)
|
|||
info.dwThreadID = GetCurrentThreadId();
|
||||
info.dwFlags = 0;
|
||||
|
||||
__try {
|
||||
__try
|
||||
{
|
||||
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
|
||||
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -55,7 +55,8 @@ SingleCoreAffinity::SingleCoreAffinity()
|
|||
s_threadId = GetCurrentThread();
|
||||
s_oldmask = SetThreadAffinityMask(s_threadId, affinityMask);
|
||||
|
||||
if (s_oldmask == ERROR_INVALID_PARAMETER) {
|
||||
if (s_oldmask == ERROR_INVALID_PARAMETER)
|
||||
{
|
||||
const int hexWidth = 2 * sizeof(DWORD_PTR);
|
||||
Console.Warning(
|
||||
"CpuDetect: SetThreadAffinityMask failed...\n"
|
||||
|
|
|
@ -32,4 +32,4 @@ void xImplBMI_RVM::operator()(const xRegisterInt &to, const xRegisterInt &from1,
|
|||
{
|
||||
xOpWriteC4(Prefix, MbPrefix, Opcode, to, from1, from2);
|
||||
}
|
||||
}
|
||||
} // namespace x86Emitter
|
||||
|
|
|
@ -77,7 +77,8 @@ void x86capabilities::SIMD_EstablishMXCSRmask()
|
|||
|
||||
MXCSR_Mask.bitmask = 0xFFBF; // MMX/SSE default
|
||||
|
||||
if (hasStreamingSIMD2Extensions) {
|
||||
if (hasStreamingSIMD2Extensions)
|
||||
{
|
||||
// This is generally safe assumption, but FXSAVE is the "correct" way to
|
||||
// detect MXCSR masking features of the cpu, so we use it's result below
|
||||
// and override this.
|
||||
|
@ -113,12 +114,14 @@ s64 x86capabilities::_CPUSpeedHz(u64 time) const
|
|||
|
||||
// Align the cpu execution to a cpuTick boundary.
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
timeStart = GetCPUTicks();
|
||||
startCycle = __rdtsc();
|
||||
} while (GetCPUTicks() == timeStart);
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
timeStop = GetCPUTicks();
|
||||
endCycle = __rdtsc();
|
||||
} while ((timeStop - timeStart) < time);
|
||||
|
@ -139,7 +142,8 @@ s64 x86capabilities::_CPUSpeedHz(u64 time) const
|
|||
|
||||
wxString x86capabilities::GetTypeName() const
|
||||
{
|
||||
switch (TypeID) {
|
||||
switch (TypeID)
|
||||
{
|
||||
case 0:
|
||||
return L"Standard OEM";
|
||||
case 1:
|
||||
|
@ -165,7 +169,8 @@ void x86capabilities::CountCores()
|
|||
|
||||
// detect multicore for AMD cpu
|
||||
|
||||
if ((cmds >= 0x80000008) && (VendorID == x86Vendor_AMD)) {
|
||||
if ((cmds >= 0x80000008) && (VendorID == x86Vendor_AMD))
|
||||
{
|
||||
// AMD note: they don't support hyperthreading, but they like to flag this true
|
||||
// anyway. Let's force-unflag it until we come up with a better solution.
|
||||
// (note: seems to affect some Phenom II's only? -- Athlon X2's and PhenomI's do
|
||||
|
@ -209,13 +214,15 @@ void x86capabilities::Identify()
|
|||
// and threads used by the CPU (AMD and Intel can't agree on how to make this info available).
|
||||
|
||||
int vid;
|
||||
for (vid = 0; vid < x86Vendor_Unknown; ++vid) {
|
||||
for (vid = 0; vid < x86Vendor_Unknown; ++vid)
|
||||
{
|
||||
if (memcmp(VendorName, tbl_x86vendors[vid], 12) == 0)
|
||||
break;
|
||||
}
|
||||
VendorID = static_cast<x86VendorType>(vid);
|
||||
|
||||
if (cmds >= 0x00000001) {
|
||||
if (cmds >= 0x00000001)
|
||||
{
|
||||
cpuid(regs, 0x00000001);
|
||||
|
||||
StepID = regs[0] & 0xf;
|
||||
|
@ -229,7 +236,8 @@ void x86capabilities::Identify()
|
|||
Flags2 = regs[2];
|
||||
}
|
||||
|
||||
if (cmds >= 0x00000007) {
|
||||
if (cmds >= 0x00000007)
|
||||
{
|
||||
// Note: ECX must be 0 for AVX2 detection.
|
||||
cpuidex(regs, 0x00000007, 0);
|
||||
|
||||
|
@ -238,7 +246,8 @@ void x86capabilities::Identify()
|
|||
|
||||
cpuid(regs, 0x80000000);
|
||||
cmds = regs[0];
|
||||
if (cmds >= 0x80000001) {
|
||||
if (cmds >= 0x80000001)
|
||||
{
|
||||
cpuid(regs, 0x80000001);
|
||||
|
||||
#ifdef __M_X86_64
|
||||
|
|
|
@ -43,11 +43,14 @@ namespace x86Emitter
|
|||
// with one of the other overloads).
|
||||
static void _g1_IndirectImm(G1Type InstType, const xIndirect64orLess& sibdest, int imm)
|
||||
{
|
||||
if (sibdest.Is8BitOp()) {
|
||||
if (sibdest.Is8BitOp())
|
||||
{
|
||||
xOpWrite(sibdest.GetPrefix16(), 0x80, InstType, sibdest);
|
||||
|
||||
xWrite<s8>(imm);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 opcode = is_s8(imm) ? 0x83 : 0x81;
|
||||
xOpWrite(sibdest.GetPrefix16(), opcode, InstType, sibdest, is_s8(imm) ? 1 : sibdest.GetImmSize());
|
||||
|
||||
|
@ -80,14 +83,20 @@ static void _g1_EmitOp(G1Type InstType, const xRegisterInt &to, const xIndirectV
|
|||
|
||||
static void _g1_EmitOp(G1Type InstType, const xRegisterInt& to, int imm)
|
||||
{
|
||||
if (!to.Is8BitOp() && is_s8(imm)) {
|
||||
if (!to.Is8BitOp() && is_s8(imm))
|
||||
{
|
||||
xOpWrite(to.GetPrefix16(), 0x83, InstType, to);
|
||||
xWrite<s8>(imm);
|
||||
} else {
|
||||
if (to.IsAccumulator()) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (to.IsAccumulator())
|
||||
{
|
||||
u8 opcode = (to.Is8BitOp() ? 4 : 5) | (InstType << 3);
|
||||
xOpAccWrite(to.GetPrefix16(), opcode, InstType, to);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 opcode = to.Is8BitOp() ? 0x80 : 0x81;
|
||||
xOpWrite(to.GetPrefix16(), opcode, InstType, to);
|
||||
}
|
||||
|
@ -132,10 +141,13 @@ void xImpl_Group2::operator()(const xRegisterInt &to, u8 imm) const
|
|||
if (imm == 0)
|
||||
return;
|
||||
|
||||
if (imm == 1) {
|
||||
if (imm == 1)
|
||||
{
|
||||
// special encoding of 1's
|
||||
xOpWrite(to.GetPrefix16(), to.Is8BitOp() ? 0xd0 : 0xd1, InstType, to);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
xOpWrite(to.GetPrefix16(), to.Is8BitOp() ? 0xc0 : 0xc1, InstType, to);
|
||||
xWrite8(imm);
|
||||
}
|
||||
|
@ -151,10 +163,13 @@ void xImpl_Group2::operator()(const xIndirect64orLess &sibdest, u8 imm) const
|
|||
if (imm == 0)
|
||||
return;
|
||||
|
||||
if (imm == 1) {
|
||||
if (imm == 1)
|
||||
{
|
||||
// special encoding of 1's
|
||||
xOpWrite(sibdest.GetPrefix16(), sibdest.Is8BitOp() ? 0xd0 : 0xd1, InstType, sibdest);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
xOpWrite(sibdest.GetPrefix16(), sibdest.Is8BitOp() ? 0xc0 : 0xc1, InstType, sibdest, 1);
|
||||
xWrite8(imm);
|
||||
}
|
||||
|
|
|
@ -58,4 +58,4 @@ struct xImplBMI_RVM
|
|||
void operator()( const xRegisterInt& to, const xIndirectVoid& from, u8 imm) const;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
} // namespace x86Emitter
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
namespace x86Emitter
|
||||
{
|
||||
|
||||
enum G1Type {
|
||||
enum G1Type
|
||||
{
|
||||
G1Type_ADD = 0,
|
||||
G1Type_OR,
|
||||
G1Type_ADC,
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
namespace x86Emitter
|
||||
{
|
||||
|
||||
enum G2Type {
|
||||
enum G2Type
|
||||
{
|
||||
G2Type_ROL = 0,
|
||||
G2Type_ROR,
|
||||
G2Type_RCL,
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
namespace x86Emitter
|
||||
{
|
||||
|
||||
enum G3Type {
|
||||
enum G3Type
|
||||
{
|
||||
G3Type_NOT = 2,
|
||||
G3Type_NEG = 3,
|
||||
G3Type_MUL = 4,
|
||||
|
@ -105,4 +106,4 @@ struct xImpl_iMul
|
|||
const xImplSimd_DestRegSSE SS;
|
||||
const xImplSimd_DestRegSSE SD;
|
||||
};
|
||||
}
|
||||
} // namespace x86Emitter
|
||||
|
|
|
@ -36,7 +36,8 @@ struct xImpl_JmpCall
|
|||
{
|
||||
if (isJmp)
|
||||
xJccKnownTarget(Jcc_Unconditional, (void*)(uptr)func, false); // double cast to/from (uptr) needed to appease GCC
|
||||
else {
|
||||
else
|
||||
{
|
||||
// calls are relative to the instruction after this one, and length is
|
||||
// always 5 bytes (16 bit calls are bad mojo, so no bother to do special logic).
|
||||
|
||||
|
|
|
@ -170,4 +170,4 @@ struct xImplSimd_PMove
|
|||
void DQ(const xRegisterSSE& to, const xRegisterSSE& from) const;
|
||||
void DQ(const xRegisterSSE& to, const xIndirect64& from) const;
|
||||
};
|
||||
}
|
||||
} // namespace x86Emitter
|
||||
|
|
|
@ -238,4 +238,4 @@ struct SimdImpl_PExtract
|
|||
// used to extract any single packed dword value from src into an x86 32 bit register.
|
||||
const xImplSimd_InsertExtractHelper D;
|
||||
};
|
||||
}
|
||||
} // namespace x86Emitter
|
||||
|
|
|
@ -31,7 +31,8 @@ struct xImpl_Test
|
|||
void operator()(const xRegisterInt& to, int imm) const;
|
||||
};
|
||||
|
||||
enum G8Type {
|
||||
enum G8Type
|
||||
{
|
||||
G8Type_BT = 4,
|
||||
G8Type_BTS,
|
||||
G8Type_BTR,
|
||||
|
|
|
@ -199,6 +199,7 @@ public:
|
|||
class xScopedSavedRegisters
|
||||
{
|
||||
std::vector<std::reference_wrapper<const xAddressReg>> regs;
|
||||
|
||||
public:
|
||||
xScopedSavedRegisters(std::initializer_list<std::reference_wrapper<const xAddressReg>> regs);
|
||||
~xScopedSavedRegisters();
|
||||
|
@ -599,4 +600,4 @@ extern const xImplSimd_Unpack xUNPCK;
|
|||
extern const SimdImpl_Pack xPACK;
|
||||
extern const xImplSimd_PInsert xPINSR;
|
||||
extern const SimdImpl_PExtract xPEXTR;
|
||||
}
|
||||
} // namespace x86Emitter
|
||||
|
|
|
@ -137,7 +137,8 @@ __emitinline void xOpWriteC5(u8 prefix, u8 opcode, const T1 ¶m1, const T2 &p
|
|||
u8 p =
|
||||
prefix == 0xF2 ? 3 :
|
||||
prefix == 0xF3 ? 2 :
|
||||
prefix == 0x66 ? 1 : 0;
|
||||
prefix == 0x66 ? 1 :
|
||||
0;
|
||||
|
||||
xWrite8(0xC5);
|
||||
xWrite8(nR | nv | L | p);
|
||||
|
@ -172,11 +173,13 @@ __emitinline void xOpWriteC4(u8 prefix, u8 mb_prefix, u8 opcode, const T1 ¶m
|
|||
u8 p =
|
||||
prefix == 0xF2 ? 3 :
|
||||
prefix == 0xF3 ? 2 :
|
||||
prefix == 0x66 ? 1 : 0;
|
||||
prefix == 0x66 ? 1 :
|
||||
0;
|
||||
|
||||
u8 m =
|
||||
mb_prefix == 0x3A ? 3 :
|
||||
mb_prefix == 0x38 ? 2 : 1;
|
||||
mb_prefix == 0x38 ? 2 :
|
||||
1;
|
||||
|
||||
xWrite8(0xC4);
|
||||
xWrite8(nR | nX | nB | m);
|
||||
|
@ -184,4 +187,4 @@ __emitinline void xOpWriteC4(u8 prefix, u8 mb_prefix, u8 opcode, const T1 ¶m
|
|||
xWrite8(opcode);
|
||||
EmitSibMagic(param1, param3);
|
||||
}
|
||||
}
|
||||
} // namespace x86Emitter
|
||||
|
|
|
@ -33,11 +33,13 @@
|
|||
namespace x86Emitter
|
||||
{
|
||||
|
||||
void xImpl_JmpCall::operator()(const xAddressReg &absreg) const {
|
||||
void xImpl_JmpCall::operator()(const xAddressReg& absreg) const
|
||||
{
|
||||
// Jumps are always wide and don't need the rex.W
|
||||
xOpWrite(0, 0xff, isJmp ? 4 : 2, absreg.GetNonWide());
|
||||
}
|
||||
void xImpl_JmpCall::operator()(const xIndirectNative &src) const {
|
||||
void xImpl_JmpCall::operator()(const xIndirectNative& src) const
|
||||
{
|
||||
// Jumps are always wide and don't need the rex.W
|
||||
EmitRex(0, xIndirect32(src.Base, src.Index, 1, 0));
|
||||
xWrite8(0xff);
|
||||
|
@ -49,78 +51,106 @@ const xImpl_JmpCall xCALL = {false};
|
|||
|
||||
|
||||
template <typename Reg1, typename Reg2>
|
||||
void prepareRegsForFastcall(const Reg1 &a1, const Reg2 &a2) {
|
||||
if (a1.IsEmpty()) return;
|
||||
void prepareRegsForFastcall(const Reg1& a1, const Reg2& a2)
|
||||
{
|
||||
if (a1.IsEmpty())
|
||||
return;
|
||||
|
||||
// Make sure we don't mess up if someone tries to fastcall with a1 in arg2reg and a2 in arg1reg
|
||||
if (a2.Id != arg1reg.Id) {
|
||||
if (a2.Id != arg1reg.Id)
|
||||
{
|
||||
xMOV(Reg1(arg1reg), a1);
|
||||
if (!a2.IsEmpty()) {
|
||||
if (!a2.IsEmpty())
|
||||
{
|
||||
xMOV(Reg2(arg2reg), a2);
|
||||
}
|
||||
} else if (a1.Id != arg2reg.Id) {
|
||||
}
|
||||
else if (a1.Id != arg2reg.Id)
|
||||
{
|
||||
xMOV(Reg2(arg2reg), a2);
|
||||
xMOV(Reg1(arg1reg), a1);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
xPUSH(a1);
|
||||
xMOV(Reg2(arg2reg), a2);
|
||||
xPOP(Reg1(arg1reg));
|
||||
}
|
||||
}
|
||||
|
||||
void xImpl_FastCall::operator()(void *f, const xRegister32 &a1, const xRegister32 &a2) const {
|
||||
void xImpl_FastCall::operator()(void* f, const xRegister32& a1, const xRegister32& a2) const
|
||||
{
|
||||
prepareRegsForFastcall(a1, a2);
|
||||
uptr disp = ((uptr)xGetPtr() + 5) - (uptr)f;
|
||||
if ((sptr)disp == (s32)disp) {
|
||||
if ((sptr)disp == (s32)disp)
|
||||
{
|
||||
xCALL(f);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
xMOV(rax, ptrNative[f]);
|
||||
xCALL(rax);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __M_X86_64
|
||||
void xImpl_FastCall::operator()(void *f, const xRegisterLong &a1, const xRegisterLong &a2) const {
|
||||
void xImpl_FastCall::operator()(void* f, const xRegisterLong& a1, const xRegisterLong& a2) const
|
||||
{
|
||||
prepareRegsForFastcall(a1, a2);
|
||||
uptr disp = ((uptr)xGetPtr() + 5) - (uptr)f;
|
||||
if ((sptr)disp == (s32)disp) {
|
||||
if ((sptr)disp == (s32)disp)
|
||||
{
|
||||
xCALL(f);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
xMOV(rax, ptrNative[f]);
|
||||
xCALL(rax);
|
||||
}
|
||||
}
|
||||
|
||||
void xImpl_FastCall::operator()(void *f, u32 a1, const xRegisterLong &a2) const {
|
||||
if (!a2.IsEmpty()) { xMOV(arg2reg, a2); }
|
||||
void xImpl_FastCall::operator()(void* f, u32 a1, const xRegisterLong& a2) const
|
||||
{
|
||||
if (!a2.IsEmpty())
|
||||
{
|
||||
xMOV(arg2reg, a2);
|
||||
}
|
||||
xMOV(arg1reg, a1);
|
||||
(*this)(f, arg1reg, arg2reg);
|
||||
}
|
||||
#endif
|
||||
|
||||
void xImpl_FastCall::operator()(void *f, void *a1) const {
|
||||
void xImpl_FastCall::operator()(void* f, void* a1) const
|
||||
{
|
||||
xLEA(arg1reg, ptr[a1]);
|
||||
(*this)(f, arg1reg, arg2reg);
|
||||
}
|
||||
|
||||
void xImpl_FastCall::operator()(void *f, u32 a1, const xRegister32 &a2) const {
|
||||
if (!a2.IsEmpty()) { xMOV(arg2regd, a2); }
|
||||
void xImpl_FastCall::operator()(void* f, u32 a1, const xRegister32& a2) const
|
||||
{
|
||||
if (!a2.IsEmpty())
|
||||
{
|
||||
xMOV(arg2regd, a2);
|
||||
}
|
||||
xMOV(arg1regd, a1);
|
||||
(*this)(f, arg1regd, arg2regd);
|
||||
}
|
||||
|
||||
void xImpl_FastCall::operator()(void *f, const xIndirect32 &a1) const {
|
||||
void xImpl_FastCall::operator()(void* f, const xIndirect32& a1) const
|
||||
{
|
||||
xMOV(arg1regd, a1);
|
||||
(*this)(f, arg1regd);
|
||||
}
|
||||
|
||||
void xImpl_FastCall::operator()(void *f, u32 a1, u32 a2) const {
|
||||
void xImpl_FastCall::operator()(void* f, u32 a1, u32 a2) const
|
||||
{
|
||||
xMOV(arg1regd, a1);
|
||||
xMOV(arg2regd, a2);
|
||||
(*this)(f, arg1regd, arg2regd);
|
||||
}
|
||||
|
||||
void xImpl_FastCall::operator()(const xIndirectNative &f, const xRegisterLong &a1, const xRegisterLong &a2) const {
|
||||
void xImpl_FastCall::operator()(const xIndirectNative& f, const xRegisterLong& a1, const xRegisterLong& a2) const
|
||||
{
|
||||
prepareRegsForFastcall(a1, a2);
|
||||
xCALL(f);
|
||||
}
|
||||
|
@ -135,7 +165,8 @@ __emitinline s32 *xJcc32(JccComparisonType comparison, s32 displacement)
|
|||
{
|
||||
if (comparison == Jcc_Unconditional)
|
||||
xWrite8(0xe9);
|
||||
else {
|
||||
else
|
||||
{
|
||||
xWrite8(0x0f);
|
||||
xWrite8(0x80 | comparison);
|
||||
}
|
||||
|
@ -170,13 +201,15 @@ __emitinline void xJccKnownTarget(JccComparisonType comparison, const void *targ
|
|||
const int slideVal = slideForward ? ((comparison == Jcc_Unconditional) ? 3 : 4) : 0;
|
||||
displacement8 -= slideVal;
|
||||
|
||||
if (slideForward) {
|
||||
if (slideForward)
|
||||
{
|
||||
pxAssertDev(displacement8 >= 0, "Used slideForward on a backward jump; nothing to slide!");
|
||||
}
|
||||
|
||||
if (is_s8(displacement8))
|
||||
xJcc8(comparison, displacement8);
|
||||
else {
|
||||
else
|
||||
{
|
||||
// Perform a 32 bit jump instead. :(
|
||||
s32* bah = xJcc32(comparison);
|
||||
sptr distance = (sptr)target - (sptr)xGetPtr();
|
||||
|
@ -208,10 +241,12 @@ xForwardJumpBase::xForwardJumpBase(uint opsize, JccComparisonType cctype)
|
|||
|
||||
if (opsize == 1)
|
||||
xWrite8((cctype == Jcc_Unconditional) ? 0xeb : (0x70 | cctype));
|
||||
else {
|
||||
else
|
||||
{
|
||||
if (cctype == Jcc_Unconditional)
|
||||
xWrite8(0xe9);
|
||||
else {
|
||||
else
|
||||
{
|
||||
xWrite8(0x0f);
|
||||
xWrite8(0x80 | cctype);
|
||||
}
|
||||
|
@ -225,10 +260,13 @@ void xForwardJumpBase::_setTarget(uint opsize) const
|
|||
pxAssertDev(BasePtr != NULL, "");
|
||||
|
||||
sptr displacement = (sptr)xGetPtr() - (sptr)BasePtr;
|
||||
if (opsize == 1) {
|
||||
if (opsize == 1)
|
||||
{
|
||||
pxAssertDev(is_s8(displacement), "Emitter Error: Invalid short jump displacement.");
|
||||
BasePtr[-1] = (s8)displacement;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// full displacement, no sanity checks needed :D
|
||||
((s32*)BasePtr)[-1] = displacement;
|
||||
}
|
||||
|
@ -244,4 +282,4 @@ __fi JccComparisonType xInvertCond(JccComparisonType src)
|
|||
// x86 conditionals are clever! To invert conditional types, just invert the lower bit:
|
||||
return (JccComparisonType)((int)src ^ 1);
|
||||
}
|
||||
}
|
||||
} // namespace x86Emitter
|
||||
|
|
|
@ -96,7 +96,8 @@ void x86SetJ8(u8 *j8)
|
|||
{
|
||||
u32 jump = (x86Ptr - j8) - 1;
|
||||
|
||||
if (jump > 0x7f) {
|
||||
if (jump > 0x7f)
|
||||
{
|
||||
Console.Error("j8 greater than 0x7f!!");
|
||||
assert(0);
|
||||
}
|
||||
|
@ -107,16 +108,19 @@ void x86SetJ8A(u8 *j8)
|
|||
{
|
||||
u32 jump = (x86Ptr - j8) - 1;
|
||||
|
||||
if (jump > 0x7f) {
|
||||
if (jump > 0x7f)
|
||||
{
|
||||
Console.Error("j8 greater than 0x7f!!");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (((uptr)x86Ptr & 0xf) > 4) {
|
||||
if (((uptr)x86Ptr & 0xf) > 4)
|
||||
{
|
||||
|
||||
uptr newjump = jump + 16 - ((uptr)x86Ptr & 0xf);
|
||||
|
||||
if (newjump <= 0x7f) {
|
||||
if (newjump <= 0x7f)
|
||||
{
|
||||
jump = newjump;
|
||||
while ((uptr)x86Ptr & 0xf)
|
||||
*x86Ptr++ = 0x90;
|
||||
|
|
|
@ -57,10 +57,12 @@ void xImpl_Mov::operator()(const xIndirectVoid &dest, const xRegisterInt &from)
|
|||
|
||||
#ifndef __M_X86_64
|
||||
// Note: On x86-64 this is an immediate 64-bit address, which is larger than the equivalent rip offset instr
|
||||
if (from.IsAccumulator() && dest.Index.IsEmpty() && dest.Base.IsEmpty()) {
|
||||
if (from.IsAccumulator() && dest.Index.IsEmpty() && dest.Base.IsEmpty())
|
||||
{
|
||||
xOpAccWrite(from.GetPrefix16(), from.Is8BitOp() ? 0xa2 : 0xa3, from, dest);
|
||||
xWrite32(dest.Displacement);
|
||||
} else
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
xOpWrite(from.GetPrefix16(), from.Is8BitOp() ? 0x88 : 0x89, from, dest);
|
||||
|
@ -74,10 +76,12 @@ void xImpl_Mov::operator()(const xRegisterInt &to, const xIndirectVoid &src) con
|
|||
|
||||
#ifndef __M_X86_64
|
||||
// Note: On x86-64 this is an immediate 64-bit address, which is larger than the equivalent rip offset instr
|
||||
if (to.IsAccumulator() && src.Index.IsEmpty() && src.Base.IsEmpty()) {
|
||||
if (to.IsAccumulator() && src.Index.IsEmpty() && src.Base.IsEmpty())
|
||||
{
|
||||
xOpAccWrite(to.GetPrefix16(), to.Is8BitOp() ? 0xa0 : 0xa1, to, src);
|
||||
xWrite32(src.Displacement);
|
||||
} else
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
xOpWrite(to.GetPrefix16(), to.Is8BitOp() ? 0x8a : 0x8b, to, src);
|
||||
|
@ -86,7 +90,8 @@ void xImpl_Mov::operator()(const xRegisterInt &to, const xIndirectVoid &src) con
|
|||
|
||||
void xImpl_Mov::operator()(const xIndirect64orLess& dest, sptr imm) const
|
||||
{
|
||||
switch (dest.GetOperandSize()) {
|
||||
switch (dest.GetOperandSize())
|
||||
{
|
||||
case 1:
|
||||
pxAssertMsg(imm == (s8)imm || imm == (u8)imm, "Immediate won't fit!");
|
||||
break;
|
||||
|
@ -110,7 +115,8 @@ void xImpl_Mov::operator()(const xIndirect64orLess &dest, sptr imm) const
|
|||
// the flags (namely replacing mov reg,0 with xor).
|
||||
void xImpl_Mov::operator()(const xRegisterInt& to, sptr imm, bool preserve_flags) const
|
||||
{
|
||||
switch (to.GetOperandSize()) {
|
||||
switch (to.GetOperandSize())
|
||||
{
|
||||
case 1:
|
||||
pxAssertMsg(imm == (s8)imm || imm == (u8)imm, "Immediate won't fit!");
|
||||
break;
|
||||
|
@ -127,14 +133,19 @@ void xImpl_Mov::operator()(const xRegisterInt &to, sptr imm, bool preserve_flags
|
|||
pxAssertMsg(0, "Bad indirect size!");
|
||||
}
|
||||
const xRegisterInt& to_ = to.GetNonWide();
|
||||
if (!preserve_flags && (imm == 0)) {
|
||||
if (!preserve_flags && (imm == 0))
|
||||
{
|
||||
_g1_EmitOp(G1Type_XOR, to_, to_);
|
||||
} else if (imm == (u32)imm || !to.IsWide()) {
|
||||
}
|
||||
else if (imm == (u32)imm || !to.IsWide())
|
||||
{
|
||||
// Note: MOV does not have (reg16/32,imm8) forms.
|
||||
u8 opcode = (to_.Is8BitOp() ? 0xb0 : 0xb8) | to_.Id;
|
||||
xOpAccWrite(to_.GetPrefix16(), opcode, 0, to_);
|
||||
to_.xWriteImm(imm);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
xOpWrite(to.GetPrefix16(), 0xc7, 0, to);
|
||||
to.xWriteImm(imm);
|
||||
}
|
||||
|
@ -145,9 +156,12 @@ const xImpl_Mov xMOV;
|
|||
#ifdef __M_X86_64
|
||||
void xImpl_MovImm64::operator()(const xRegister64& to, s64 imm, bool preserve_flags) const
|
||||
{
|
||||
if (imm == (u32)imm || imm == (s32)imm) {
|
||||
if (imm == (u32)imm || imm == (s32)imm)
|
||||
{
|
||||
xMOV(to, imm, preserve_flags);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 opcode = 0xb8 | to.Id;
|
||||
xOpAccWrite(to.GetPrefix16(), opcode, 0, to);
|
||||
xWrite64(imm);
|
||||
|
|
|
@ -23,7 +23,8 @@ SSE_MXCSR MXCSR_Mask;
|
|||
|
||||
const wxChar* EnumToString(SSE_RoundMode sse)
|
||||
{
|
||||
switch (sse) {
|
||||
switch (sse)
|
||||
{
|
||||
case SSEround_Nearest:
|
||||
return L"Nearest";
|
||||
case SSEround_NegInf:
|
||||
|
@ -104,18 +105,24 @@ __emitinline void SimdPrefix(u8 prefix, u16 opcode)
|
|||
if (!is16BitOpcode)
|
||||
pxAssert((opcode >> 8) == 0);
|
||||
|
||||
if (prefix != 0) {
|
||||
if (prefix != 0)
|
||||
{
|
||||
if (is16BitOpcode)
|
||||
xWrite32((opcode << 16) | 0x0f00 | prefix);
|
||||
else {
|
||||
else
|
||||
{
|
||||
xWrite16(0x0f00 | prefix);
|
||||
xWrite8(opcode);
|
||||
}
|
||||
} else {
|
||||
if (is16BitOpcode) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is16BitOpcode)
|
||||
{
|
||||
xWrite8(0x0f);
|
||||
xWrite16(opcode);
|
||||
} else
|
||||
}
|
||||
else
|
||||
xWrite16((opcode << 8) | 0x0f);
|
||||
}
|
||||
}
|
||||
|
@ -797,4 +804,4 @@ __emitinline void xFXRSTOR(const xIndirectVoid &src)
|
|||
{
|
||||
xOpWrite0F(0, 0xae, 1, src);
|
||||
}
|
||||
}
|
||||
} // namespace x86Emitter
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
|
||||
#include "common/Dependencies.h"
|
||||
|
||||
enum x86VendorType {
|
||||
enum x86VendorType
|
||||
{
|
||||
x86Vendor_Intel = 0,
|
||||
x86Vendor_AMD = 1,
|
||||
x86Vendor_Unknown = 2
|
||||
|
@ -124,7 +125,8 @@ protected:
|
|||
void CountLogicalCores();
|
||||
};
|
||||
|
||||
enum SSE_RoundMode {
|
||||
enum SSE_RoundMode
|
||||
{
|
||||
SSE_RoundMode_FIRST = 0,
|
||||
SSEround_Nearest = 0,
|
||||
SSEround_NegInf,
|
||||
|
@ -136,10 +138,12 @@ enum SSE_RoundMode {
|
|||
ImplementEnumOperators(SSE_RoundMode);
|
||||
|
||||
// Predeclaration for xIndirect32
|
||||
namespace x86Emitter {
|
||||
template <typename T> class xIndirect;
|
||||
namespace x86Emitter
|
||||
{
|
||||
template <typename T>
|
||||
class xIndirect;
|
||||
typedef xIndirect<u32> xIndirect32;
|
||||
}
|
||||
} // namespace x86Emitter
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// SSE_MXCSR - Control/Status Register (bitfield)
|
||||
|
|
|
@ -195,21 +195,24 @@ const char *const x86_regnames_gpr8[] =
|
|||
"al", "cl", "dl", "bl",
|
||||
"ah", "ch", "dh", "bh",
|
||||
"b8", "b9", "b10", "b11",
|
||||
"b12", "b13", "b14", "b15"};
|
||||
"b12", "b13", "b14", "b15"
|
||||
};
|
||||
|
||||
const char* const x86_regnames_gpr16[] =
|
||||
{
|
||||
"ax", "cx", "dx", "bx",
|
||||
"sp", "bp", "si", "di",
|
||||
"h8", "h9", "h10", "h11",
|
||||
"h12", "h13", "h14", "h15"};
|
||||
"h12", "h13", "h14", "h15"
|
||||
};
|
||||
|
||||
const char* const x86_regnames_gpr32[] =
|
||||
{
|
||||
"eax", "ecx", "edx", "ebx",
|
||||
"esp", "ebp", "esi", "edi",
|
||||
"e8", "e9", "e10", "e11",
|
||||
"e12", "e13", "e14", "e15"};
|
||||
"e12", "e13", "e14", "e15"
|
||||
};
|
||||
|
||||
#ifdef __M_X86_64
|
||||
const char* const x86_regnames_gpr64[] =
|
||||
|
@ -217,7 +220,8 @@ const char *const x86_regnames_gpr64[] =
|
|||
"rax", "rcx", "rdx", "rbx",
|
||||
"rsp", "rbp", "rsi", "rdi",
|
||||
"r8", "r9", "r10", "r11",
|
||||
"r12", "r13", "r14", "r15"};
|
||||
"r12", "r13", "r14", "r15"
|
||||
};
|
||||
#endif
|
||||
|
||||
const char* const x86_regnames_sse[] =
|
||||
|
@ -225,7 +229,8 @@ const char *const x86_regnames_sse[] =
|
|||
"xmm0", "xmm1", "xmm2", "xmm3",
|
||||
"xmm4", "xmm5", "xmm6", "xmm7",
|
||||
"xmm8", "xmm9", "xmm10", "xmm11",
|
||||
"xmm12", "xmm13", "xmm14", "xmm15"};
|
||||
"xmm12", "xmm13", "xmm14", "xmm15"
|
||||
};
|
||||
|
||||
const char* xRegisterBase::GetName()
|
||||
{
|
||||
|
@ -239,7 +244,8 @@ const char *xRegisterBase::GetName()
|
|||
if (Id >= (int)iREGCNT_GPR || Id < 0)
|
||||
return "!Register index out of range!";
|
||||
|
||||
switch (GetOperandSize()) {
|
||||
switch (GetOperandSize())
|
||||
{
|
||||
case 1:
|
||||
return x86_regnames_gpr8[Id];
|
||||
case 2:
|
||||
|
@ -299,10 +305,13 @@ void EmitSibMagic(uint regfield, const void *address, int extraRIPOffset)
|
|||
#else
|
||||
sptr ripRelative = (sptr)address - ((sptr)x86Ptr + sizeof(s8) + sizeof(s32) + extraRIPOffset);
|
||||
// Can we use a rip-relative address? (Prefer this over eiz because it's a byte shorter)
|
||||
if (ripRelative == (s32)ripRelative) {
|
||||
if (ripRelative == (s32)ripRelative)
|
||||
{
|
||||
ModRM(0, regfield, ModRm_UseDisp32);
|
||||
displacement = ripRelative;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
pxAssertDev(displacement == (s32)displacement, "SIB target is too far away, needs an indirect register");
|
||||
ModRM(0, regfield, ModRm_UseSib);
|
||||
SibSB(0, Sib_EIZ, Sib_UseDisp32);
|
||||
|
@ -352,34 +361,43 @@ void EmitSibMagic(uint regfield, const xIndirectVoid &info, int extraRIPOffset)
|
|||
// Displacement is only 64 bits for rip-relative addressing
|
||||
pxAssert(info.Displacement == (s32)info.Displacement || (info.Base.IsEmpty() && info.Index.IsEmpty()));
|
||||
|
||||
if (!NeedsSibMagic(info)) {
|
||||
if (!NeedsSibMagic(info))
|
||||
{
|
||||
// Use ModRm-only encoding, with the rm field holding an index/base register, if
|
||||
// one has been specified. If neither register is specified then use Disp32 form,
|
||||
// which is encoded as "EBP w/o displacement" (which is why EBP must always be
|
||||
// encoded *with* a displacement of 0, if it would otherwise not have one).
|
||||
|
||||
if (info.Index.IsEmpty()) {
|
||||
if (info.Index.IsEmpty())
|
||||
{
|
||||
EmitSibMagic(regfield, (void*)info.Displacement, extraRIPOffset);
|
||||
return;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info.Index == rbp && displacement_size == 0)
|
||||
displacement_size = 1; // forces [ebp] to be encoded as [ebp+0]!
|
||||
|
||||
ModRM(displacement_size, regfield, info.Index.Id & 7);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// In order to encode "just" index*scale (and no base), we have to encode
|
||||
// it as a special [index*scale + displacement] form, which is done by
|
||||
// specifying EBP as the base register and setting the displacement field
|
||||
// to zero. (same as ModRm w/o SIB form above, basically, except the
|
||||
// ModRm_UseDisp flag is specified in the SIB instead of the ModRM field).
|
||||
|
||||
if (info.Base.IsEmpty()) {
|
||||
if (info.Base.IsEmpty())
|
||||
{
|
||||
ModRM(0, regfield, ModRm_UseSib);
|
||||
SibSB(info.Scale, info.Index.Id, Sib_UseDisp32);
|
||||
xWrite<s32>(info.Displacement);
|
||||
return;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info.Base == rbp && displacement_size == 0)
|
||||
displacement_size = 1; // forces [ebp] to be encoded as [ebp+0]!
|
||||
|
||||
|
@ -388,7 +406,8 @@ void EmitSibMagic(uint regfield, const xIndirectVoid &info, int extraRIPOffset)
|
|||
}
|
||||
}
|
||||
|
||||
if (displacement_size != 0) {
|
||||
if (displacement_size != 0)
|
||||
{
|
||||
if (displacement_size == 1)
|
||||
xWrite<s8>(info.Displacement);
|
||||
else
|
||||
|
@ -444,7 +463,8 @@ void EmitRex(uint regfield, const xIndirectVoid &info)
|
|||
bool r = false;
|
||||
bool x = info.Index.IsExtended();
|
||||
bool b = info.Base.IsExtended();
|
||||
if (!NeedsSibMagic(info)) {
|
||||
if (!NeedsSibMagic(info))
|
||||
{
|
||||
b = x;
|
||||
x = false;
|
||||
}
|
||||
|
@ -485,7 +505,8 @@ void EmitRex(const xRegisterBase ®1, const xIndirectVoid &sib)
|
|||
bool r = reg1.IsExtended();
|
||||
bool x = sib.Index.IsExtended();
|
||||
bool b = sib.Base.IsExtended();
|
||||
if (!NeedsSibMagic(sib)) {
|
||||
if (!NeedsSibMagic(sib))
|
||||
{
|
||||
b = x;
|
||||
x = false;
|
||||
}
|
||||
|
@ -508,7 +529,8 @@ void EmitRexImplicitlyWide(const xIndirectVoid &sib)
|
|||
bool r = false;
|
||||
bool x = sib.Index.IsExtended();
|
||||
bool b = sib.Base.IsExtended();
|
||||
if (!NeedsSibMagic(sib)) {
|
||||
if (!NeedsSibMagic(sib))
|
||||
{
|
||||
b = x;
|
||||
x = false;
|
||||
}
|
||||
|
@ -551,7 +573,8 @@ __emitinline void xAlignCallTarget()
|
|||
// Core2/i7 CPUs prefer unaligned addresses. Checking for SSSE3 is a decent filter.
|
||||
// (also align in debug modes for disasm convenience)
|
||||
|
||||
if (IsDebugBuild || !x86caps.hasSupplementalStreamingSIMD3Extensions) {
|
||||
if (IsDebugBuild || !x86caps.hasSupplementalStreamingSIMD3Extensions)
|
||||
{
|
||||
// - P4's and earlier prefer 16 byte alignment.
|
||||
// - AMD Athlons and Phenoms prefer 8 byte alignment, but I don't have an easy
|
||||
// heuristic for it yet.
|
||||
|
@ -569,11 +592,13 @@ __emitinline u8 *xGetAlignedCallTarget()
|
|||
|
||||
__emitinline void xAdvancePtr(uint bytes)
|
||||
{
|
||||
if (IsDevBuild) {
|
||||
if (IsDevBuild)
|
||||
{
|
||||
// common debugger courtesy: advance with INT3 as filler.
|
||||
for (uint i = 0; i < bytes; i++)
|
||||
xWrite8(0xcc);
|
||||
} else
|
||||
}
|
||||
else
|
||||
x86Ptr += bytes;
|
||||
}
|
||||
|
||||
|
@ -582,9 +607,7 @@ __emitinline void xAdvancePtr(uint bytes)
|
|||
// --------------------------------------------------------------------------------------
|
||||
xRegisterInt xRegisterInt::MatchSizeTo(xRegisterInt other) const
|
||||
{
|
||||
return other.GetOperandSize() == 1
|
||||
? xRegisterInt(xRegister8(*this))
|
||||
: xRegisterInt(other.GetOperandSize(), Id);
|
||||
return other.GetOperandSize() == 1 ? xRegisterInt(xRegister8(*this)) : xRegisterInt(other.GetOperandSize(), Id);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
@ -676,20 +699,25 @@ xAddressVoid::xAddressVoid(const void *displacement)
|
|||
|
||||
xAddressVoid& xAddressVoid::Add(const xAddressReg& src)
|
||||
{
|
||||
if (src == Index) {
|
||||
if (src == Index)
|
||||
{
|
||||
Factor++;
|
||||
} else if (src == Base) {
|
||||
}
|
||||
else if (src == Base)
|
||||
{
|
||||
// Compound the existing register reference into the Index/Scale pair.
|
||||
Base = xEmptyReg;
|
||||
|
||||
if (src == Index)
|
||||
Factor++;
|
||||
else {
|
||||
else
|
||||
{
|
||||
pxAssertDev(Index.IsEmpty(), "x86Emitter: Only one scaled index register is allowed in an address modifier.");
|
||||
Index = src;
|
||||
Factor = 2;
|
||||
}
|
||||
} else if (Base.IsEmpty())
|
||||
}
|
||||
else if (Base.IsEmpty())
|
||||
Base = src;
|
||||
else if (Index.IsEmpty())
|
||||
Index = src;
|
||||
|
@ -705,14 +733,20 @@ xAddressVoid &xAddressVoid::Add(const xAddressVoid &src)
|
|||
Add(src.Displacement);
|
||||
|
||||
// If the factor is 1, we can just treat index like a base register also.
|
||||
if (src.Factor == 1) {
|
||||
if (src.Factor == 1)
|
||||
{
|
||||
Add(src.Index);
|
||||
} else if (Index.IsEmpty()) {
|
||||
}
|
||||
else if (Index.IsEmpty())
|
||||
{
|
||||
Index = src.Index;
|
||||
Factor = src.Factor;
|
||||
} else if (Index == src.Index) {
|
||||
}
|
||||
else if (Index == src.Index)
|
||||
{
|
||||
Factor += src.Factor;
|
||||
} else
|
||||
}
|
||||
else
|
||||
pxAssumeDev(false, L"x86Emitter: address modifiers cannot have more than two index registers."); // oops, only 2 regs allowed per ModRm!
|
||||
|
||||
return *this;
|
||||
|
@ -763,7 +797,8 @@ xIndirectVoid::xIndirectVoid(xAddressReg base, xAddressReg index, int scale, spt
|
|||
//
|
||||
void xIndirectVoid::Reduce()
|
||||
{
|
||||
if (Index.IsStackPointer()) {
|
||||
if (Index.IsStackPointer())
|
||||
{
|
||||
// esp cannot be encoded as the index, so move it to the Base, if possible.
|
||||
// note: intentionally leave index assigned to esp also (generates correct
|
||||
// encoding later, since ESP cannot be encoded 'alone')
|
||||
|
@ -776,7 +811,8 @@ void xIndirectVoid::Reduce()
|
|||
}
|
||||
|
||||
// If no index reg, then load the base register into the index slot.
|
||||
if (Index.IsEmpty()) {
|
||||
if (Index.IsEmpty())
|
||||
{
|
||||
Index = Base;
|
||||
Scale = 0;
|
||||
if (!Base.IsStackPointer()) // prevent ESP from being encoded 'alone'
|
||||
|
@ -786,7 +822,8 @@ void xIndirectVoid::Reduce()
|
|||
|
||||
// The Scale has a series of valid forms, all shown here:
|
||||
|
||||
switch (Scale) {
|
||||
switch (Scale)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
|
@ -854,19 +891,24 @@ static void EmitLeaMagic(const xRegisterInt &to, const xIndirectVoid &src, bool
|
|||
|
||||
// See EmitSibMagic for commenting on SIB encoding.
|
||||
|
||||
if (!NeedsSibMagic(src) && src.Displacement == (s32)src.Displacement) {
|
||||
if (!NeedsSibMagic(src) && src.Displacement == (s32)src.Displacement)
|
||||
{
|
||||
// LEA Land: means we have either 1-register encoding or just an offset.
|
||||
// offset is encodable as an immediate MOV, and a register is encodable
|
||||
// as a register MOV.
|
||||
|
||||
if (src.Index.IsEmpty()) {
|
||||
if (src.Index.IsEmpty())
|
||||
{
|
||||
xMOV(to, src.Displacement);
|
||||
return;
|
||||
}
|
||||
else if (displacement_size == 0) {
|
||||
else if (displacement_size == 0)
|
||||
{
|
||||
_xMovRtoR(to, src.Index.MatchSizeTo(to));
|
||||
return;
|
||||
} else if (!preserve_flags) {
|
||||
}
|
||||
else if (!preserve_flags)
|
||||
{
|
||||
// encode as MOV and ADD combo. Make sure to use the immediate on the
|
||||
// ADD since it can encode as an 8-bit sign-extended value.
|
||||
|
||||
|
@ -874,9 +916,13 @@ static void EmitLeaMagic(const xRegisterInt &to, const xIndirectVoid &src, bool
|
|||
xADD(to, src.Displacement);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (src.Base.IsEmpty()) {
|
||||
if (!preserve_flags && (displacement_size == 0)) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (src.Base.IsEmpty())
|
||||
{
|
||||
if (!preserve_flags && (displacement_size == 0))
|
||||
{
|
||||
// Encode [Index*Scale] as a combination of Mov and Shl.
|
||||
// This is more efficient because of the bloated LEA format which requires
|
||||
// a 32 bit displacement, and the compact nature of the alternative.
|
||||
|
@ -888,21 +934,30 @@ static void EmitLeaMagic(const xRegisterInt &to, const xIndirectVoid &src, bool
|
|||
xSHL(to, src.Scale);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (src.Scale == 0) {
|
||||
if (!preserve_flags) {
|
||||
if (src.Index == rsp) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (src.Scale == 0)
|
||||
{
|
||||
if (!preserve_flags)
|
||||
{
|
||||
if (src.Index == rsp)
|
||||
{
|
||||
// ESP is not encodable as an index (ix86 ignores it), thus:
|
||||
_xMovRtoR(to, src.Base.MatchSizeTo(to)); // will do the trick!
|
||||
if (src.Displacement)
|
||||
xADD(to, src.Displacement);
|
||||
return;
|
||||
} else if (src.Displacement == 0) {
|
||||
}
|
||||
else if (src.Displacement == 0)
|
||||
{
|
||||
_xMovRtoR(to, src.Base.MatchSizeTo(to));
|
||||
_g1_EmitOp(G1Type_ADD, to, src.Index.MatchSizeTo(to));
|
||||
return;
|
||||
}
|
||||
} else if ((src.Index == rsp) && (src.Displacement == 0)) {
|
||||
}
|
||||
else if ((src.Index == rsp) && (src.Displacement == 0))
|
||||
{
|
||||
// special case handling of ESP as Index, which is replaceable with
|
||||
// a single MOV even when preserve_flags is set! :D
|
||||
|
||||
|
@ -960,9 +1015,12 @@ void xImpl_Test::operator()(const xIndirect64orLess &dest, int imm) const
|
|||
|
||||
void xImpl_Test::operator()(const xRegisterInt& to, int imm) const
|
||||
{
|
||||
if (to.IsAccumulator()) {
|
||||
if (to.IsAccumulator())
|
||||
{
|
||||
xOpAccWrite(to.GetPrefix16(), to.Is8BitOp() ? 0xa8 : 0xa9, 0, to);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
xOpWrite(to.GetPrefix16(), to.Is8BitOp() ? 0xf6 : 0xf7, 0, to);
|
||||
}
|
||||
to.xWriteImm(imm);
|
||||
|
@ -980,10 +1038,13 @@ void xImpl_BitScan::operator()(const xRegister16or32or64 &to, const xIndirectVoi
|
|||
|
||||
void xImpl_IncDec::operator()(const xRegisterInt& to) const
|
||||
{
|
||||
if (to.Is8BitOp()) {
|
||||
if (to.Is8BitOp())
|
||||
{
|
||||
u8 regfield = isDec ? 1 : 0;
|
||||
xOpWrite(to.GetPrefix16(), 0xfe, regfield, to);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __M_X86_64
|
||||
xOpWrite(to.GetPrefix16(), 0xff, isDec ? 1 : 0, to);
|
||||
#else
|
||||
|
@ -1055,22 +1116,27 @@ __emitinline void xPUSH(const xIndirectVoid &from)
|
|||
EmitSibMagic(6, from);
|
||||
}
|
||||
|
||||
__fi void xPOP(xRegister32or64 from) {
|
||||
__fi void xPOP(xRegister32or64 from)
|
||||
{
|
||||
EmitRexImplicitlyWide(from);
|
||||
xWrite8(0x58 | (from->Id & 7));
|
||||
}
|
||||
|
||||
__fi void xPUSH(u32 imm)
|
||||
{
|
||||
if (is_s8(imm)) {
|
||||
if (is_s8(imm))
|
||||
{
|
||||
xWrite8(0x6a);
|
||||
xWrite8(imm);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
xWrite8(0x68);
|
||||
xWrite32(imm);
|
||||
}
|
||||
}
|
||||
__fi void xPUSH(xRegister32or64 from) {
|
||||
__fi void xPUSH(xRegister32or64 from)
|
||||
{
|
||||
EmitRexImplicitlyWide(from);
|
||||
xWrite8(0x50 | (from->Id & 7));
|
||||
}
|
||||
|
@ -1104,7 +1170,8 @@ __fi void xINT(u8 imm)
|
|||
{
|
||||
if (imm == 3)
|
||||
xWrite8(0xcc);
|
||||
else {
|
||||
else
|
||||
{
|
||||
xWrite8(0xcd);
|
||||
xWrite8(imm);
|
||||
}
|
||||
|
@ -1151,9 +1218,11 @@ __emitinline void xRestoreReg(const xRegisterSSE &dest)
|
|||
|
||||
#endif
|
||||
|
||||
static void stackAlign(int offset, bool moveDown) {
|
||||
static void stackAlign(int offset, bool moveDown)
|
||||
{
|
||||
int needed = (16 - (offset % 16)) % 16;
|
||||
if (moveDown) {
|
||||
if (moveDown)
|
||||
{
|
||||
needed = -needed;
|
||||
}
|
||||
ALIGN_STACK(needed);
|
||||
|
@ -1168,11 +1237,14 @@ xScopedStackFrame::xScopedStackFrame(bool base_frame, bool save_base_pointer, in
|
|||
m_offset += sizeof(void*); // Call stores the return address (4 bytes)
|
||||
|
||||
// Note rbp can surely be optimized in 64 bits
|
||||
if (m_base_frame) {
|
||||
if (m_base_frame)
|
||||
{
|
||||
xPUSH(rbp);
|
||||
xMOV(rbp, rsp);
|
||||
m_offset += sizeof(void*);
|
||||
} else if (m_save_base_pointer) {
|
||||
}
|
||||
else if (m_save_base_pointer)
|
||||
{
|
||||
xPUSH(rbp);
|
||||
m_offset += sizeof(void*);
|
||||
}
|
||||
|
@ -1233,9 +1305,12 @@ xScopedStackFrame::~xScopedStackFrame()
|
|||
#endif
|
||||
|
||||
// Destroy the frame
|
||||
if (m_base_frame) {
|
||||
if (m_base_frame)
|
||||
{
|
||||
xLEAVE();
|
||||
} else if (m_save_base_pointer) {
|
||||
}
|
||||
else if (m_save_base_pointer)
|
||||
{
|
||||
xPOP(rbp);
|
||||
}
|
||||
}
|
||||
|
@ -1251,31 +1326,41 @@ xScopedSavedRegisters::xScopedSavedRegisters(std::initializer_list<std::referenc
|
|||
stackAlign(regs.size() * wordsize, true);
|
||||
}
|
||||
|
||||
xScopedSavedRegisters::~xScopedSavedRegisters() {
|
||||
xScopedSavedRegisters::~xScopedSavedRegisters()
|
||||
{
|
||||
stackAlign(regs.size() * wordsize, false);
|
||||
for (auto it = regs.rbegin(); it < regs.rend(); ++it) {
|
||||
for (auto it = regs.rbegin(); it < regs.rend(); ++it)
|
||||
{
|
||||
const xAddressReg& regRef = *it;
|
||||
xPOP(regRef);
|
||||
}
|
||||
}
|
||||
|
||||
xAddressVoid xComplexAddress(const xAddressReg& tmpRegister, void *base, const xAddressVoid& offset) {
|
||||
if ((sptr)base == (s32)(sptr)base) {
|
||||
xAddressVoid xComplexAddress(const xAddressReg& tmpRegister, void* base, const xAddressVoid& offset)
|
||||
{
|
||||
if ((sptr)base == (s32)(sptr)base)
|
||||
{
|
||||
return offset + base;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
xLEA(tmpRegister, ptr[base]);
|
||||
return offset + tmpRegister;
|
||||
}
|
||||
}
|
||||
|
||||
void xLoadFarAddr(const xAddressReg& dst, void *addr) {
|
||||
void xLoadFarAddr(const xAddressReg& dst, void* addr)
|
||||
{
|
||||
#ifdef __M_X86_64
|
||||
sptr iaddr = (sptr)addr;
|
||||
sptr rip = (sptr)xGetPtr() + 7; // LEA will be 7 bytes
|
||||
sptr disp = iaddr - rip;
|
||||
if (disp == (s32)disp) {
|
||||
if (disp == (s32)disp)
|
||||
{
|
||||
xLEA(dst, ptr[addr]);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
xMOV64(dst, iaddr);
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -26,7 +26,8 @@ static const uint iREGCNT_XMM = 8;
|
|||
static const uint iREGCNT_GPR = 8;
|
||||
#endif
|
||||
|
||||
enum XMMSSEType {
|
||||
enum XMMSSEType
|
||||
{
|
||||
XMMT_INT = 0, // integer (sse2 only)
|
||||
XMMT_FPS = 1, // floating point
|
||||
//XMMT_FPD = 3, // double
|
||||
|
@ -127,7 +128,8 @@ static const bool AlwaysUseMovaps = false;
|
|||
#endif
|
||||
|
||||
// ModRM 'mod' field enumeration. Provided mostly for reference:
|
||||
enum ModRm_ModField {
|
||||
enum ModRm_ModField
|
||||
{
|
||||
Mod_NoDisp = 0, // effective address operation with no displacement, in the form of [reg] (or uses special Disp32-only encoding in the case of [ebp] form)
|
||||
Mod_Disp8, // effective address operation with 8 bit displacement, in the form of [reg+disp8]
|
||||
Mod_Disp32, // effective address operation with 32 bit displacement, in the form of [reg+disp32],
|
||||
|
@ -137,7 +139,8 @@ enum ModRm_ModField {
|
|||
// ----------------------------------------------------------------------------
|
||||
// JccComparisonType - enumerated possibilities for inspired code branching!
|
||||
//
|
||||
enum JccComparisonType {
|
||||
enum JccComparisonType
|
||||
{
|
||||
Jcc_Unknown = -2,
|
||||
Jcc_Unconditional = -1,
|
||||
Jcc_Overflow = 0x0,
|
||||
|
@ -168,7 +171,8 @@ enum JccComparisonType {
|
|||
// ----------------------------------------------------------------------------
|
||||
// SSE2_ComparisonType - enumerated possibilities for SIMD data comparison!
|
||||
//
|
||||
enum SSE2_ComparisonType {
|
||||
enum SSE2_ComparisonType
|
||||
{
|
||||
SSE2_Equal = 0,
|
||||
SSE2_Less,
|
||||
SSE2_LessOrEqual,
|
||||
|
@ -208,8 +212,10 @@ protected:
|
|||
: _operandSize(operandSize)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
uint GetOperandSize() const {
|
||||
uint GetOperandSize() const
|
||||
{
|
||||
pxAssertDev(_operandSize != 0, "Attempted to use operand size of uninitialized or void object");
|
||||
return _operandSize;
|
||||
}
|
||||
|
@ -222,12 +228,18 @@ public:
|
|||
xWrite8(0x66);
|
||||
}
|
||||
|
||||
int GetImmSize() const {
|
||||
switch (GetOperandSize()) {
|
||||
case 1: return 1;
|
||||
case 2: return 2;
|
||||
case 4: return 4;
|
||||
case 8: return 4; // Only mov's take 64-bit immediates
|
||||
int GetImmSize() const
|
||||
{
|
||||
switch (GetOperandSize())
|
||||
{
|
||||
case 1:
|
||||
return 1;
|
||||
case 2:
|
||||
return 2;
|
||||
case 4:
|
||||
return 4;
|
||||
case 8:
|
||||
return 4; // Only mov's take 64-bit immediates
|
||||
jNO_DEFAULT
|
||||
}
|
||||
return 0;
|
||||
|
@ -235,7 +247,8 @@ public:
|
|||
|
||||
void xWriteImm(int imm) const
|
||||
{
|
||||
switch (GetImmSize()) {
|
||||
switch (GetImmSize())
|
||||
{
|
||||
case 1:
|
||||
xWrite8(imm);
|
||||
break;
|
||||
|
@ -270,17 +283,20 @@ class xRegisterBase : public OperandSizedObject
|
|||
{
|
||||
protected:
|
||||
xRegisterBase(uint operandSize, int regId)
|
||||
: OperandSizedObject(operandSize), Id(regId)
|
||||
: OperandSizedObject(operandSize)
|
||||
, Id(regId)
|
||||
{
|
||||
// Note: to avoid tons of ifdef, the 32 bits build will instantiate
|
||||
// all 16x64 bits registers.
|
||||
pxAssert((Id >= xRegId_Empty) && (Id < 16));
|
||||
}
|
||||
|
||||
public:
|
||||
int Id;
|
||||
|
||||
xRegisterBase()
|
||||
: OperandSizedObject(0), Id(xRegId_Invalid)
|
||||
: OperandSizedObject(0)
|
||||
, Id(xRegId_Invalid)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -326,6 +342,7 @@ protected:
|
|||
: _parent(operandSize, regId)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
xRegisterInt() = default;
|
||||
|
||||
|
@ -961,7 +978,7 @@ static __fi xAddressVoid operator+(sptr addr, const xAddressReg ®)
|
|||
{
|
||||
return reg + (sptr)addr;
|
||||
}
|
||||
}
|
||||
} // namespace x86Emitter
|
||||
|
||||
#include "implement/helpers.h"
|
||||
|
||||
|
|
|
@ -43,7 +43,8 @@ void pxCheckBox::Init(const wxString &label, const wxString &subtext, int flags)
|
|||
*this += m_checkbox | pxSizerFlags::StdExpand();
|
||||
|
||||
static const int Indentation = 23;
|
||||
if (!subtext.IsEmpty()) {
|
||||
if (!subtext.IsEmpty())
|
||||
{
|
||||
m_subtext = new pxStaticText(this, subtext, wxALIGN_LEFT);
|
||||
|
||||
wxFlexGridSizer& spaced(*new wxFlexGridSizer(3));
|
||||
|
@ -61,7 +62,8 @@ void pxCheckBox::Init(const wxString &label, const wxString &subtext, int flags)
|
|||
pxCheckBox& pxCheckBox::SetSubPadding(int pad)
|
||||
{
|
||||
m_subPadding = pad;
|
||||
if (m_sizerItem_subtext) {
|
||||
if (m_sizerItem_subtext)
|
||||
{
|
||||
m_sizerItem_subtext->SetBorder(m_subPadding);
|
||||
Fit();
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace Threading
|
|||
class Mutex;
|
||||
class Semaphore;
|
||||
class pxThread;
|
||||
}
|
||||
} // namespace Threading
|
||||
|
||||
namespace Exception
|
||||
{
|
||||
|
|
|
@ -51,7 +51,8 @@ void pxRadioPanel::Reset()
|
|||
if (numbuttons == 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < numbuttons; ++i) {
|
||||
for (int i = 0; i < numbuttons; ++i)
|
||||
{
|
||||
safe_delete(m_objects[i].LabelObj);
|
||||
safe_delete(m_objects[i].SubTextObj);
|
||||
}
|
||||
|
@ -80,7 +81,8 @@ void pxRadioPanel::Realize()
|
|||
for (int i = 1; i < numbuttons; ++i)
|
||||
m_objects[i].LabelObj = new wxRadioButton(this, wxID_ANY, m_buttonStrings[i].Label);
|
||||
|
||||
for (int i = 0; i < numbuttons; ++i) {
|
||||
for (int i = 0; i < numbuttons; ++i)
|
||||
{
|
||||
m_objects[i].SubTextObj = NULL;
|
||||
if (m_buttonStrings[i].SubText.IsEmpty())
|
||||
continue;
|
||||
|
@ -89,10 +91,12 @@ void pxRadioPanel::Realize()
|
|||
|
||||
pxAssert(GetSizer() != NULL);
|
||||
|
||||
for (int i = 0; i < numbuttons; ++i) {
|
||||
for (int i = 0; i < numbuttons; ++i)
|
||||
{
|
||||
*this += m_objects[i].LabelObj | pxSizerFlags::StdExpand();
|
||||
|
||||
if (pxStaticText *subobj = m_objects[i].SubTextObj) {
|
||||
if (pxStaticText* subobj = m_objects[i].SubTextObj)
|
||||
{
|
||||
*this += subobj | pxBorder(wxLEFT, m_Indentation).Expand();
|
||||
*this += 9 + m_padding.GetHeight();
|
||||
}
|
||||
|
@ -137,7 +141,8 @@ pxRadioPanel &pxRadioPanel::SetSelection(int idx)
|
|||
|
||||
void pxRadioPanel::_RealizeDefaultOption()
|
||||
{
|
||||
if (m_IsRealized && m_DefaultIdx != -1) {
|
||||
if (m_IsRealized && m_DefaultIdx != -1)
|
||||
{
|
||||
wxFont def(GetFont());
|
||||
def.SetWeight(wxFONTWEIGHT_BOLD);
|
||||
//def.SetStyle( wxFONTSTYLE_ITALIC );
|
||||
|
@ -153,7 +158,8 @@ pxRadioPanel &pxRadioPanel::SetDefaultItem(int idx)
|
|||
if (idx == m_DefaultIdx)
|
||||
return *this;
|
||||
|
||||
if (m_IsRealized && m_DefaultIdx != -1) {
|
||||
if (m_IsRealized && m_DefaultIdx != -1)
|
||||
{
|
||||
wxFont def(GetFont());
|
||||
m_objects[m_DefaultIdx].LabelObj->SetFont(def);
|
||||
m_objects[m_DefaultIdx].LabelObj->SetForegroundColour(GetForegroundColour());
|
||||
|
@ -193,7 +199,8 @@ int pxRadioPanel::GetSelection() const
|
|||
if (!VerifyRealizedState())
|
||||
return 0;
|
||||
|
||||
for (uint i = 0; i < m_buttonStrings.size(); ++i) {
|
||||
for (uint i = 0; i < m_buttonStrings.size(); ++i)
|
||||
{
|
||||
if (wxRadioButton* woot = m_objects[i].LabelObj)
|
||||
if (woot->GetValue())
|
||||
return i;
|
||||
|
|
|
@ -168,7 +168,8 @@ wxSize pxStaticText::GetBestWrappedSize(const wxClientDC &dc) const
|
|||
double parentalFactor = 1.0;
|
||||
const wxWindow* millrun = this;
|
||||
|
||||
while (millrun) {
|
||||
while (millrun)
|
||||
{
|
||||
// IMPORTANT : wxWizard changes its min size and then expects everything else
|
||||
// to play nice and NOT resize according to the new min size. (wtf stupid)
|
||||
// Anyway, this fixes it -- ignore min size specifier on wxWizard!
|
||||
|
@ -177,7 +178,8 @@ wxSize pxStaticText::GetBestWrappedSize(const wxClientDC &dc) const
|
|||
|
||||
int min = (int)((millrun->GetMinWidth() - parentalAdjust) * parentalFactor);
|
||||
|
||||
if (min > 0 && ((idealWidth < 0) || (min < idealWidth))) {
|
||||
if (min > 0 && ((idealWidth < 0) || (min < idealWidth)))
|
||||
{
|
||||
idealWidth = min;
|
||||
}
|
||||
|
||||
|
@ -185,7 +187,8 @@ wxSize pxStaticText::GetBestWrappedSize(const wxClientDC &dc) const
|
|||
millrun = millrun->GetParent();
|
||||
}
|
||||
|
||||
if (idealWidth <= 0) {
|
||||
if (idealWidth <= 0)
|
||||
{
|
||||
// FIXME: The minimum size of this control is unknown, so let's just pick a guess based on
|
||||
// the size of the user's display area.
|
||||
|
||||
|
@ -208,7 +211,8 @@ pxStaticText &pxStaticText::WrapAt(int width)
|
|||
if (width > 1)
|
||||
wrappedLabel = pxTextWrapper().Wrap(this, m_label, width).GetResult();
|
||||
|
||||
if (m_wrappedLabel != wrappedLabel) {
|
||||
if (m_wrappedLabel != wrappedLabel)
|
||||
{
|
||||
m_wrappedLabel = wrappedLabel;
|
||||
wxSize area = wxClientDC(this).GetMultiLineTextExtent(m_wrappedLabel);
|
||||
SetMinSize(wxSize(
|
||||
|
@ -220,7 +224,8 @@ pxStaticText &pxStaticText::WrapAt(int width)
|
|||
|
||||
bool pxStaticText::_updateWrapping(bool textChanged)
|
||||
{
|
||||
if (!m_autowrap) {
|
||||
if (!m_autowrap)
|
||||
{
|
||||
//m_wrappedLabel = wxEmptyString;
|
||||
//m_wrappedWidth = -1;
|
||||
return false;
|
||||
|
@ -257,7 +262,8 @@ void pxStaticText::UpdateWrapping(bool textChanged)
|
|||
void pxStaticText::SetLabel(const wxString& label)
|
||||
{
|
||||
const bool labelChanged(label != m_label);
|
||||
if (labelChanged) {
|
||||
if (labelChanged)
|
||||
{
|
||||
m_label = label;
|
||||
Refresh();
|
||||
}
|
||||
|
@ -277,7 +283,8 @@ wxFont pxStaticText::GetFontOk() const
|
|||
|
||||
bool pxStaticText::Enable(bool enabled)
|
||||
{
|
||||
if (_parent::Enable(enabled)) {
|
||||
if (_parent::Enable(enabled))
|
||||
{
|
||||
Refresh();
|
||||
return true;
|
||||
}
|
||||
|
@ -328,10 +335,13 @@ wxSize pxStaticText::DoGetBestSize() const
|
|||
|
||||
wxSize best;
|
||||
|
||||
if (m_autowrap) {
|
||||
if (m_autowrap)
|
||||
{
|
||||
best = GetBestWrappedSize(dc);
|
||||
//best.x = wxDefaultCoord;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// No autowrapping, so we can force a specific size here!
|
||||
best = dc.GetMultiLineTextExtent(GetLabel());
|
||||
best.x += calcPaddingWidth(best.x);
|
||||
|
|
|
@ -86,7 +86,8 @@ void pxInputStream::SetStream(const wxString &filename, wxInputStream *stream)
|
|||
void pxInputStream::Read(void* dest, size_t size)
|
||||
{
|
||||
m_stream_in->Read(dest, size);
|
||||
if (m_stream_in->GetLastError() == wxSTREAM_READ_ERROR) {
|
||||
if (m_stream_in->GetLastError() == wxSTREAM_READ_ERROR)
|
||||
{
|
||||
int err = errno;
|
||||
if (!err)
|
||||
throw Exception::BadStream(m_filename).SetDiagMsg(L"Cannot read from file (bad file handle?)");
|
||||
|
@ -147,7 +148,8 @@ void pxOutputStream::SetStream(const wxString &filename, wxOutputStream *stream)
|
|||
void pxOutputStream::Write(const void* src, size_t size)
|
||||
{
|
||||
m_stream_out->Write(src, size);
|
||||
if (m_stream_out->GetLastError() == wxSTREAM_WRITE_ERROR) {
|
||||
if (m_stream_out->GetLastError() == wxSTREAM_WRITE_ERROR)
|
||||
{
|
||||
int err = errno;
|
||||
if (!err)
|
||||
throw Exception::BadStream(m_filename).SetDiagMsg(L"Cannot write to file/stream.");
|
||||
|
@ -167,7 +169,8 @@ bool pxReadLine(wxInputStream &input, std::string &dest)
|
|||
{
|
||||
dest.clear();
|
||||
bool isUTF8 = false;
|
||||
while (true) {
|
||||
while (true)
|
||||
{
|
||||
char c;
|
||||
input.Read(&c, sizeof(c));
|
||||
if (c == 0)
|
||||
|
@ -176,7 +179,8 @@ bool pxReadLine(wxInputStream &input, std::string &dest)
|
|||
break;
|
||||
if (c == '\n')
|
||||
break; // eat on UNIX
|
||||
if (c == '\r') {
|
||||
if (c == '\r')
|
||||
{
|
||||
input.Read(&c, sizeof(c));
|
||||
if (c == 0)
|
||||
break;
|
||||
|
@ -201,7 +205,8 @@ void pxReadLine(wxInputStream &input, wxString &dest, std::string &intermed)
|
|||
dest.clear();
|
||||
if (pxReadLine(input, intermed))
|
||||
dest = fromUTF8(intermed.c_str());
|
||||
else {
|
||||
else
|
||||
{
|
||||
// Optimized ToAscii conversion.
|
||||
// wx3.0 : NOT COMPATIBLE!! (on linux anyway)
|
||||
const char* ascii = intermed.c_str();
|
||||
|
@ -230,7 +235,8 @@ void pxWriteLine(wxOutputStream &output)
|
|||
|
||||
void pxWriteLine(wxOutputStream& output, const wxString& text)
|
||||
{
|
||||
if (!text.IsEmpty()) {
|
||||
if (!text.IsEmpty())
|
||||
{
|
||||
pxToUTF8 utf8(text);
|
||||
output.Write(utf8, utf8.Length());
|
||||
}
|
||||
|
|
|
@ -92,9 +92,12 @@ void pxWindowTextWriter::_DoWriteLn(const wxString &msg)
|
|||
|
||||
wxPoint dispos(m_curpos);
|
||||
|
||||
if (m_align & wxALIGN_CENTER_HORIZONTAL) {
|
||||
if (m_align & wxALIGN_CENTER_HORIZONTAL)
|
||||
{
|
||||
dispos.x = (m_dc.GetSize().GetWidth() - tWidth) / 2;
|
||||
} else if (m_align & wxALIGN_RIGHT) {
|
||||
}
|
||||
else if (m_align & wxALIGN_RIGHT)
|
||||
{
|
||||
dispos.x = m_dc.GetSize().GetWidth() - tWidth;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,9 +56,12 @@ void SynchronousActionState::SetException(const BaseException &ex)
|
|||
|
||||
void SynchronousActionState::SetException(BaseException* ex)
|
||||
{
|
||||
if (!m_posted) {
|
||||
if (!m_posted)
|
||||
{
|
||||
m_exception = ScopedExcept(ex);
|
||||
} else if (wxTheApp) {
|
||||
}
|
||||
else if (wxTheApp)
|
||||
{
|
||||
// transport the exception to the main thread, since the message is fully
|
||||
// asynchronous, or has already entered an asynchronous state. Message is sent
|
||||
// as a non-blocking action since proper handling of user errors on async messages
|
||||
|
@ -143,7 +146,8 @@ void pxActionEvent::SetException(BaseException *ex)
|
|||
const wxString& prefix(pxsFmt(L"(%s) ", GetClassInfo()->GetClassName()));
|
||||
ex->DiagMsg() = prefix + ex->DiagMsg();
|
||||
|
||||
if (!m_state) {
|
||||
if (!m_state)
|
||||
{
|
||||
ScopedExcept exptr(ex); // auto-delete it after handling.
|
||||
ex->Rethrow();
|
||||
}
|
||||
|
@ -202,7 +206,8 @@ void pxSynchronousCommandEvent::SetException(const BaseException &ex)
|
|||
|
||||
void pxSynchronousCommandEvent::SetException(BaseException* ex)
|
||||
{
|
||||
if (!m_sync) {
|
||||
if (!m_sync)
|
||||
{
|
||||
ScopedExcept exptr(ex); // auto-delete it after handling.
|
||||
ex->Rethrow();
|
||||
}
|
||||
|
@ -349,7 +354,8 @@ bool wxAppWithHelpers::Rpc_TryInvokeAsync(FnType_Void *method)
|
|||
|
||||
void wxAppWithHelpers::ProcessMethod(FnType_Void* method)
|
||||
{
|
||||
if (wxThread::IsMain()) {
|
||||
if (wxThread::IsMain())
|
||||
{
|
||||
method();
|
||||
return;
|
||||
}
|
||||
|
@ -392,7 +398,8 @@ bool wxAppWithHelpers::ProcessEvent(pxActionEvent &evt)
|
|||
{
|
||||
if (wxThread::IsMain())
|
||||
return _parent::ProcessEvent(evt);
|
||||
else {
|
||||
else
|
||||
{
|
||||
SynchronousActionState sync;
|
||||
evt.SetSyncState(sync);
|
||||
AddPendingEvent(evt);
|
||||
|
@ -403,10 +410,13 @@ bool wxAppWithHelpers::ProcessEvent(pxActionEvent &evt)
|
|||
|
||||
bool wxAppWithHelpers::ProcessEvent(pxActionEvent* evt)
|
||||
{
|
||||
if (wxThread::IsMain()) {
|
||||
if (wxThread::IsMain())
|
||||
{
|
||||
std::unique_ptr<wxEvent> deleteMe(evt);
|
||||
return _parent::ProcessEvent(*deleteMe);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
SynchronousActionState sync;
|
||||
evt->SetSyncState(sync);
|
||||
AddPendingEvent(*evt);
|
||||
|
@ -436,11 +446,16 @@ void pxActionEvent::_DoInvokeEvent()
|
|||
{
|
||||
AffinityAssert_AllowFrom_MainUI();
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
InvokeEvent();
|
||||
} catch (BaseException &ex) {
|
||||
}
|
||||
catch (BaseException& ex)
|
||||
{
|
||||
SetException(ex);
|
||||
} catch (std::runtime_error &ex) {
|
||||
}
|
||||
catch (std::runtime_error& ex)
|
||||
{
|
||||
SetException(new Exception::RuntimeError(ex));
|
||||
}
|
||||
|
||||
|
@ -455,11 +470,16 @@ void wxAppWithHelpers::OnSynchronousCommand(pxSynchronousCommandEvent &evt)
|
|||
pxAppLog.Write(L"(App) Executing command event synchronously...");
|
||||
evt.SetEventType(evt.GetRealEventType());
|
||||
|
||||
try {
|
||||
try
|
||||
{
|
||||
ProcessEvent(evt);
|
||||
} catch (BaseException &ex) {
|
||||
}
|
||||
catch (BaseException& ex)
|
||||
{
|
||||
evt.SetException(ex);
|
||||
} catch (std::runtime_error &ex) {
|
||||
}
|
||||
catch (std::runtime_error& ex)
|
||||
{
|
||||
evt.SetException(new Exception::RuntimeError(ex, evt.GetClassInfo()->GetClassName()));
|
||||
}
|
||||
|
||||
|
@ -498,12 +518,14 @@ void wxAppWithHelpers::IdleEventDispatcher(const wxChar *action)
|
|||
|
||||
ScopedLock lock(m_IdleEventMutex);
|
||||
|
||||
while (node = m_IdleEventQueue.begin(), node != m_IdleEventQueue.end()) {
|
||||
while (node = m_IdleEventQueue.begin(), node != m_IdleEventQueue.end())
|
||||
{
|
||||
std::unique_ptr<wxEvent> deleteMe(*node);
|
||||
m_IdleEventQueue.erase(node);
|
||||
|
||||
lock.Release();
|
||||
if (!Threading::AllowDeletions() && (deleteMe->GetEventType() == pxEvt_DeleteThread)) {
|
||||
if (!Threading::AllowDeletions() && (deleteMe->GetEventType() == pxEvt_DeleteThread))
|
||||
{
|
||||
// Threads that have active semaphores or mutexes (other threads are waiting on them) cannot
|
||||
// be deleted because those mutex/sema objects will become invalid and cause the pending
|
||||
// thread to crash. So we disallow deletions when those waits are in action, and continue
|
||||
|
@ -511,7 +533,9 @@ void wxAppWithHelpers::IdleEventDispatcher(const wxChar *action)
|
|||
|
||||
pxThreadLog.Write(((pxThread*)((wxCommandEvent*)deleteMe.get())->GetClientData())->GetName(), L"Deletion postponed due to mutex or semaphore dependency.");
|
||||
postponed.push_back(deleteMe.release());
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
pxAppLog.Write(L"(AppIdleQueue%s) Dispatching event '%s'", action, deleteMe->GetClassInfo()->GetClassName());
|
||||
ProcessEvent(*deleteMe); // dereference to prevent auto-deletion by ProcessEvent
|
||||
}
|
||||
|
@ -586,12 +610,14 @@ void wxAppWithHelpers::PostAction(const pxActionEvent &evt)
|
|||
|
||||
void wxAppWithHelpers::ProcessAction(pxActionEvent& evt)
|
||||
{
|
||||
if (!wxThread::IsMain()) {
|
||||
if (!wxThread::IsMain())
|
||||
{
|
||||
SynchronousActionState sync;
|
||||
evt.SetSyncState(sync);
|
||||
AddPendingEvent(evt);
|
||||
sync.WaitForResult();
|
||||
} else
|
||||
}
|
||||
else
|
||||
evt._DoInvokeEvent();
|
||||
}
|
||||
|
||||
|
@ -658,7 +684,8 @@ wxAppTraits *wxAppWithHelpers::CreateTraits()
|
|||
void wxAppWithHelpers::OnDeleteThread(wxCommandEvent& evt)
|
||||
{
|
||||
std::unique_ptr<pxThread> thr((pxThread*)evt.GetClientData());
|
||||
if (!thr) {
|
||||
if (!thr)
|
||||
{
|
||||
pxThreadLog.Write(L"null", L"OnDeleteThread: NULL thread object received (and ignored).");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -142,4 +142,4 @@ namespace Msgbox
|
|||
{
|
||||
extern int ShowModal(BaseMessageBoxEvent& evt);
|
||||
extern int ShowModal(const wxString& title, const wxString& content, const MsgButtons& buttons);
|
||||
}
|
||||
} // namespace Msgbox
|
||||
|
|
|
@ -40,7 +40,8 @@ const pxStretchType
|
|||
|
||||
wxSizerFlags pxAlignmentType::Apply(wxSizerFlags flags) const
|
||||
{
|
||||
switch (intval) {
|
||||
switch (intval)
|
||||
{
|
||||
case Centre:
|
||||
flags.Align(flags.GetFlags() | wxALIGN_CENTRE_HORIZONTAL);
|
||||
break;
|
||||
|
@ -70,7 +71,8 @@ wxSizerFlags pxAlignmentType::Apply(wxSizerFlags flags) const
|
|||
|
||||
wxSizerFlags pxStretchType::Apply(wxSizerFlags flags) const
|
||||
{
|
||||
switch (intval) {
|
||||
switch (intval)
|
||||
{
|
||||
case Shrink:
|
||||
//pxFail( "wxSHRINK is an ignored stretch flag." );
|
||||
break;
|
||||
|
@ -420,8 +422,10 @@ pxTextWrapperBase &pxTextWrapperBase::Wrap(const wxWindow &win, const wxString &
|
|||
|
||||
wxString::const_iterator lastSpace = text.end();
|
||||
wxString::const_iterator lineStart = text.begin();
|
||||
for (wxString::const_iterator p = lineStart;; ++p) {
|
||||
if (IsStartOfNewLine()) {
|
||||
for (wxString::const_iterator p = lineStart;; ++p)
|
||||
{
|
||||
if (IsStartOfNewLine())
|
||||
{
|
||||
OnNewLine();
|
||||
|
||||
lastSpace = text.end();
|
||||
|
@ -433,28 +437,36 @@ pxTextWrapperBase &pxTextWrapperBase::Wrap(const wxWindow &win, const wxString &
|
|||
line.clear();
|
||||
}
|
||||
|
||||
if (p == text.end() || *p == L'\n') {
|
||||
if (p == text.end() || *p == L'\n')
|
||||
{
|
||||
wasWrapped = false;
|
||||
DoOutputLine(line);
|
||||
|
||||
if (p == text.end())
|
||||
break;
|
||||
} else { // not EOL
|
||||
if (is_cjk_char(*p)) {
|
||||
if (!no_break_before(*p)) {
|
||||
}
|
||||
else
|
||||
{ // not EOL
|
||||
if (is_cjk_char(*p))
|
||||
{
|
||||
if (!no_break_before(*p))
|
||||
{
|
||||
if (p == lineStart || !no_break_after(*(p - 1)))
|
||||
lastSpace = p;
|
||||
}
|
||||
} else if (*p == L' ' || *p == L',' || *p == L'/')
|
||||
}
|
||||
else if (*p == L' ' || *p == L',' || *p == L'/')
|
||||
lastSpace = p;
|
||||
|
||||
line += *p;
|
||||
|
||||
if (widthMax >= 0 && lastSpace != text.end()) {
|
||||
if (widthMax >= 0 && lastSpace != text.end())
|
||||
{
|
||||
int width;
|
||||
win.GetTextExtent(line, &width, NULL);
|
||||
|
||||
if (width > widthMax) {
|
||||
if (width > widthMax)
|
||||
{
|
||||
wasWrapped = true;
|
||||
|
||||
// remove the last word from this line
|
||||
|
@ -544,7 +556,8 @@ ScopedBusyCursor::~ScopedBusyCursor()
|
|||
if (!pxAssert(wxTheApp != NULL))
|
||||
return;
|
||||
|
||||
if (!pxAssert(!m_cursorStack.empty())) {
|
||||
if (!pxAssert(!m_cursorStack.empty()))
|
||||
{
|
||||
SetManualBusyCursor(m_defBusyType);
|
||||
return;
|
||||
}
|
||||
|
@ -570,7 +583,8 @@ void ScopedBusyCursor::SetDefault(BusyCursorType busytype)
|
|||
|
||||
void ScopedBusyCursor::SetManualBusyCursor(BusyCursorType busytype)
|
||||
{
|
||||
switch (busytype) {
|
||||
switch (busytype)
|
||||
{
|
||||
case Cursor_NotBusy:
|
||||
wxSetCursor(wxNullCursor);
|
||||
break;
|
||||
|
|
|
@ -46,7 +46,7 @@ extern wxSizerFlags SubGroup();
|
|||
extern wxSizerFlags StdButton();
|
||||
extern wxSizerFlags Checkbox();
|
||||
extern void SetBestPadding();
|
||||
};
|
||||
}; // namespace pxSizerFlags
|
||||
|
||||
#define wxSF wxSizerFlags()
|
||||
|
||||
|
@ -58,7 +58,8 @@ extern void SetBestPadding();
|
|||
//
|
||||
struct pxAlignmentType
|
||||
{
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
Centre,
|
||||
Center = Centre,
|
||||
Middle,
|
||||
|
@ -100,7 +101,8 @@ struct pxAlignmentType
|
|||
|
||||
struct pxStretchType
|
||||
{
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
Shrink,
|
||||
Expand,
|
||||
Shaped,
|
||||
|
@ -745,7 +747,8 @@ public:
|
|||
const wxCursor& GetArrowWait();
|
||||
};
|
||||
|
||||
enum BusyCursorType {
|
||||
enum BusyCursorType
|
||||
{
|
||||
Cursor_NotBusy,
|
||||
Cursor_KindaBusy,
|
||||
Cursor_ReallyBusy,
|
||||
|
|
|
@ -122,7 +122,8 @@ wxDialogWithHelpers::wxDialogWithHelpers(wxWindow *parent, const wxString &title
|
|||
: wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, cflags.GetWxWindowFlags())
|
||||
{
|
||||
m_hasContextHelp = cflags.hasContextHelp;
|
||||
if ((int)cflags.BoxSizerOrient != 0) {
|
||||
if ((int)cflags.BoxSizerOrient != 0)
|
||||
{
|
||||
SetSizer(new wxBoxSizer(cflags.BoxSizerOrient));
|
||||
*this += StdPadding;
|
||||
}
|
||||
|
@ -179,10 +180,12 @@ void wxDialogWithHelpers::DoAutoCenter()
|
|||
// a lot since the main window is small).
|
||||
|
||||
bool centerfail = true;
|
||||
if (wxWindow *parent = GetParent()) {
|
||||
if (wxWindow* parent = GetParent())
|
||||
{
|
||||
const wxSize parentSize(parent->GetSize());
|
||||
|
||||
if ((parentSize.x > ((int)GetSize().x * 1.5)) || (parentSize.y > ((int)GetSize().y * 1.5))) {
|
||||
if ((parentSize.x > ((int)GetSize().x * 1.5)) || (parentSize.y > ((int)GetSize().y * 1.5)))
|
||||
{
|
||||
CenterOnParent();
|
||||
centerfail = false;
|
||||
}
|
||||
|
@ -197,19 +200,22 @@ void wxDialogWithHelpers::SmartCenterFit()
|
|||
Fit();
|
||||
|
||||
const wxString dlgName(GetDialogName());
|
||||
if (dlgName.IsEmpty()) {
|
||||
if (dlgName.IsEmpty())
|
||||
{
|
||||
DoAutoCenter();
|
||||
return;
|
||||
}
|
||||
|
||||
if (wxConfigBase *cfg = wxConfigBase::Get(false)) {
|
||||
if (wxConfigBase* cfg = wxConfigBase::Get(false))
|
||||
{
|
||||
wxRect screenRect(GetScreenRect());
|
||||
|
||||
IniLoader loader(cfg);
|
||||
ScopedIniGroup group(loader, L"DialogPositions");
|
||||
cfg->SetRecordDefaults(false);
|
||||
|
||||
if (GetWindowStyle() & wxRESIZE_BORDER) {
|
||||
if (GetWindowStyle() & wxRESIZE_BORDER)
|
||||
{
|
||||
wxSize size;
|
||||
loader.Entry(dlgName + L"_Size", size, screenRect.GetSize());
|
||||
SetSize(size);
|
||||
|
@ -217,7 +223,8 @@ void wxDialogWithHelpers::SmartCenterFit()
|
|||
|
||||
if (!cfg->Exists(dlgName + L"_Pos"))
|
||||
DoAutoCenter();
|
||||
else {
|
||||
else
|
||||
{
|
||||
wxPoint pos;
|
||||
loader.Entry(dlgName + L"_Pos", pos, screenRect.GetPosition());
|
||||
SetPosition(pos);
|
||||
|
@ -241,7 +248,8 @@ int wxDialogWithHelpers::ShowModal()
|
|||
// 75% larger than the fitted dialog.
|
||||
bool wxDialogWithHelpers::Show(bool show)
|
||||
{
|
||||
if (show) {
|
||||
if (show)
|
||||
{
|
||||
SmartCenterFit();
|
||||
m_CreatedRect = GetScreenRect();
|
||||
}
|
||||
|
@ -270,15 +278,18 @@ void wxDialogWithHelpers::RememberPosition()
|
|||
// ... not sure how to fix that yet. I could register a list of open windows into wxAppWithHelpers
|
||||
// that systematically get closed. Seems like work, maybe later. --air
|
||||
|
||||
if (wxConfigBase *cfg = IsIconized() ? NULL : wxConfigBase::Get(false)) {
|
||||
if (wxConfigBase* cfg = IsIconized() ? NULL : wxConfigBase::Get(false))
|
||||
{
|
||||
const wxString dlgName(GetDialogName());
|
||||
const wxRect screenRect(GetScreenRect());
|
||||
if (!dlgName.IsEmpty() && (m_CreatedRect != screenRect)) {
|
||||
if (!dlgName.IsEmpty() && (m_CreatedRect != screenRect))
|
||||
{
|
||||
wxPoint pos(screenRect.GetPosition());
|
||||
IniSaver saver(cfg);
|
||||
ScopedIniGroup group(saver, L"DialogPositions");
|
||||
|
||||
if (GetWindowStyle() & wxRESIZE_BORDER) {
|
||||
if (GetWindowStyle() & wxRESIZE_BORDER)
|
||||
{
|
||||
wxSize size(screenRect.GetSize());
|
||||
saver.Entry(dlgName + L"_Size", size, screenRect.GetSize());
|
||||
}
|
||||
|
@ -313,7 +324,8 @@ void wxDialogWithHelpers::AddOkCancel(wxSizer &sizer, bool hasApply)
|
|||
|
||||
// Add the context-sensitive help button on the caption for the platforms
|
||||
// which support it (currently MSW only)
|
||||
if (m_hasContextHelp) {
|
||||
if (m_hasContextHelp)
|
||||
{
|
||||
SetExtraStyle(wxDIALOG_EX_CONTEXTHELP);
|
||||
#ifndef __WXMSW__
|
||||
*m_extraButtonSizer += new wxContextHelpButton(this) | StdButton();
|
||||
|
|
Loading…
Reference in New Issue