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:
Kojin 2021-09-06 14:28:26 -04:00 committed by GitHub
parent f9bf87f50d
commit 13dfceff48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
102 changed files with 13189 additions and 12692 deletions

View File

@ -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); 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)); memcpy(newbuf, handle, std::min(old_size, new_size));
_aligned_free(handle); _aligned_free(handle);
} }

View File

@ -159,10 +159,13 @@ extern pxDoAssertFnType *pxDoAssert;
#define pxAssumeDev(cond, msg) (__assume(cond)) #define pxAssumeDev(cond, msg) (__assume(cond))
#define pxFail(msg) \ #define pxFail(msg) \
do { \ do \
{ \
} while (0) } while (0)
#define pxFailDev(msg) \ #define pxFailDev(msg) \
do { \ do \
{ \
} while (0) } while (0)
#endif #endif
@ -202,7 +205,8 @@ extern void pxOnAssert(const DiagnosticOrigin &origin, const wxString &msg);
// //
#ifndef jNO_DEFAULT #ifndef jNO_DEFAULT
#define jNO_DEFAULT \ #define jNO_DEFAULT \
default: { \ default: \
{ \
pxAssumeDev(0, "Incorrect usage of jNO_DEFAULT detected (default case is not unreachable!)"); \ pxAssumeDev(0, "Incorrect usage of jNO_DEFAULT detected (default case is not unreachable!)"); \
break; \ break; \
} }

View File

@ -43,7 +43,8 @@ void CheckedStaticBox::SetValue(bool val)
{ {
wxWindowList& list = GetChildren(); 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; wxWindow* current = *iter;
if (current != &ThisToggle) if (current != &ThisToggle)
current->Enable(IsEnabled() && val); current->Enable(IsEnabled() && val);
@ -66,7 +67,8 @@ bool CheckedStaticBox::Enable(bool enable)
bool val = enable && ThisToggle.GetValue(); bool val = enable && ThisToggle.GetValue();
wxWindowList& list = GetChildren(); 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; wxWindow* current = *iter;
if (current != &ThisToggle) if (current != &ThisToggle)
current->Enable(val); current->Enable(val);

View File

@ -102,7 +102,8 @@ const IConsoleWriter ConsoleWriter_Null =
#if defined(__unix__) #if defined(__unix__)
static __fi const char* GetLinuxConsoleColor(ConsoleColors color) static __fi const char* GetLinuxConsoleColor(ConsoleColors color)
{ {
switch (color) { switch (color)
{
case Color_Black: case Color_Black:
case Color_StrongBlack: case Color_StrongBlack:
return "\033[30m\033[1m"; return "\033[30m\033[1m";
@ -470,7 +471,8 @@ ConsoleColorScope::~ConsoleColorScope()
void ConsoleColorScope::EnterScope() void ConsoleColorScope::EnterScope()
{ {
if (!m_IsScoped) { if (!m_IsScoped)
{
m_old_color = Console.GetColor(); m_old_color = Console.GetColor();
Console.SetColor(m_newcolor); Console.SetColor(m_newcolor);
m_IsScoped = true; m_IsScoped = true;
@ -491,7 +493,8 @@ ConsoleIndentScope::ConsoleIndentScope(int tabs)
ConsoleIndentScope::~ConsoleIndentScope() ConsoleIndentScope::~ConsoleIndentScope()
{ {
try { try
{
LeaveScope(); LeaveScope();
} }
DESTRUCTOR_CATCHALL DESTRUCTOR_CATCHALL
@ -517,7 +520,8 @@ ConsoleAttrScope::ConsoleAttrScope(ConsoleColors newcolor, int indent)
ConsoleAttrScope::~ConsoleAttrScope() ConsoleAttrScope::~ConsoleAttrScope()
{ {
try { try
{
Console.SetColor(m_old_color); Console.SetColor(m_old_color);
Console.SetIndent(-m_tabsize); Console.SetIndent(-m_tabsize);
} }

View File

@ -15,9 +15,10 @@
#pragma once #pragma once
#include "StringHelpers.h" #include "common/StringHelpers.h"
enum ConsoleColors { enum ConsoleColors
{
Color_Current = -1, Color_Current = -1,
Color_Default = 0, Color_Default = 0,

View File

@ -45,11 +45,13 @@ u64 GetPhysicalMemory()
// doesn't change during the course of the program. Thread-safety is // doesn't change during the course of the program. Thread-safety is
// ensured by atomic operations with full-barriers (usually compiled // ensured by atomic operations with full-barriers (usually compiled
// down to XCHG on x86). // 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; u64 getmem = 0;
size_t len = sizeof(getmem); size_t len = sizeof(getmem);
int mib[] = {CTL_HW, HW_MEMSIZE}; 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:"); perror("sysctl:");
} }
__atomic_store_n(&mem, getmem, __ATOMIC_SEQ_CST); __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 // by the time denom is not 0, the structure will have been fully
// updated and no more atomic accesses are necessary. // 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_data_t info;
// mach_timebase_info() is a syscall, very slow, that's why we take // 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 // 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, // to be info.denom == info.numer == 1 (i.e.: the frequency is 1e9,
// which means GetCPUTicks is just nanoseconds). // which means GetCPUTicks is just nanoseconds).
if (mach_timebase_info(&info) != KERN_SUCCESS) { if (mach_timebase_info(&info) != KERN_SUCCESS)
{
abort(); abort();
} }
@ -109,13 +113,15 @@ wxString GetOSVersionString()
static int initialized = 0; static int initialized = 0;
// fetch the OS description only once (thread-safely) // 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 type[32] = {0};
char release[32] = {0}; char release[32] = {0};
char arch[32] = {0}; char arch[32] = {0};
#define SYSCTL_GET(var, base, name) \ #define SYSCTL_GET(var, base, name) \
do { \ do \
{ \
int mib[] = {base, name}; \ int mib[] = {base, name}; \
size_t len = sizeof(var); \ size_t len = sizeof(var); \
sysctl(mib, NELEM(mib), NULL, &len, NULL, 0); \ sysctl(mib, NELEM(mib), NULL, &len, NULL, 0); \

View File

@ -45,8 +45,10 @@
static void MACH_CHECK(kern_return_t mach_retval) static void MACH_CHECK(kern_return_t mach_retval)
{ {
switch (mach_retval) { switch (mach_retval)
case KERN_SUCCESS: break; {
case KERN_SUCCESS:
break;
case KERN_ABORTED: // Awoken due reason unrelated to semaphore (e.g. pthread_cancel) 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 pthread_testcancel(); // Unlike sem_wait, mach semaphore ops aren't cancellation points
// fallthrough // fallthrough
@ -85,7 +87,8 @@ void Threading::Semaphore::Post()
void Threading::Semaphore::Post(int multiple) 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)); MACH_CHECK(semaphore_signal(m_sema));
} }
__atomic_add_fetch(&m_counter, multiple, __ATOMIC_SEQ_CST); __atomic_add_fetch(&m_counter, multiple, __ATOMIC_SEQ_CST);
@ -115,8 +118,10 @@ bool Threading::Semaphore::WaitWithoutYield(const wxTimeSpan &timeout)
mach_timespec_t ts; mach_timespec_t ts;
kern_return_t kr = KERN_ABORTED; kern_return_t kr = KERN_ABORTED;
for (u64 now = mach_absolute_time(), deadline = now + delta; for (u64 now = mach_absolute_time(), deadline = now + delta;
kr == KERN_ABORTED; now = mach_absolute_time()) { kr == KERN_ABORTED; now = mach_absolute_time())
if (now > deadline) { {
if (now > deadline)
{
// timed out by definition // timed out by definition
return false; return false;
} }
@ -135,7 +140,8 @@ bool Threading::Semaphore::WaitWithoutYield(const wxTimeSpan &timeout)
kr = semaphore_timedwait(m_sema, ts); kr = semaphore_timedwait(m_sema, ts);
} }
if (kr == KERN_OPERATION_TIMED_OUT) { if (kr == KERN_OPERATION_TIMED_OUT)
{
return false; return false;
} }
@ -155,13 +161,19 @@ bool Threading::Semaphore::WaitWithoutYield(const wxTimeSpan &timeout)
void Threading::Semaphore::Wait() void Threading::Semaphore::Wait()
{ {
#if wxUSE_GUI #if wxUSE_GUI
if (!wxThread::IsMain() || (wxTheApp == NULL)) { if (!wxThread::IsMain() || (wxTheApp == NULL))
{
WaitWithoutYield(); WaitWithoutYield();
} else if (_WaitGui_RecursionGuard(L"Semaphore::Wait")) { }
else if (_WaitGui_RecursionGuard(L"Semaphore::Wait"))
{
ScopedBusyCursor hourglass(Cursor_ReallyBusy); ScopedBusyCursor hourglass(Cursor_ReallyBusy);
WaitWithoutYield(); WaitWithoutYield();
} else { }
while (!WaitWithoutYield(def_yieldgui_interval)) { else
{
while (!WaitWithoutYield(def_yieldgui_interval))
{
YieldToMain(); YieldToMain();
} }
} }
@ -182,16 +194,22 @@ void Threading::Semaphore::Wait()
bool Threading::Semaphore::Wait(const wxTimeSpan& timeout) bool Threading::Semaphore::Wait(const wxTimeSpan& timeout)
{ {
#if wxUSE_GUI #if wxUSE_GUI
if (!wxThread::IsMain() || (wxTheApp == NULL)) { if (!wxThread::IsMain() || (wxTheApp == NULL))
{
return WaitWithoutYield(timeout); return WaitWithoutYield(timeout);
} else if (_WaitGui_RecursionGuard(L"Semaphore::TimedWait")) { }
else if (_WaitGui_RecursionGuard(L"Semaphore::TimedWait"))
{
ScopedBusyCursor hourglass(Cursor_ReallyBusy); ScopedBusyCursor hourglass(Cursor_ReallyBusy);
return WaitWithoutYield(timeout); return WaitWithoutYield(timeout);
} else { }
else
{
//ScopedBusyCursor hourglass( Cursor_KindaBusy ); //ScopedBusyCursor hourglass( Cursor_KindaBusy );
wxTimeSpan countdown((timeout)); wxTimeSpan countdown((timeout));
do { do
{
if (WaitWithoutYield(def_yieldgui_interval)) if (WaitWithoutYield(def_yieldgui_interval))
break; break;
YieldToMain(); YieldToMain();

View File

@ -70,7 +70,8 @@ static u64 getthreadtime(thread_port_t thread)
kern_return_t kr = thread_info(thread, THREAD_BASIC_INFO, kern_return_t kr = thread_info(thread, THREAD_BASIC_INFO,
(thread_info_t)&info, &count); (thread_info_t)&info, &count);
if (kr != KERN_SUCCESS) { if (kr != KERN_SUCCESS)
{
return 0; 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 // 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(), // thread has used on the CPU (scaled by the value returned by GetThreadTicksPerSecond(),
// which typically would be an OS-provided scalar or some sort). // which typically would be an OS-provided scalar or some sort).
if (!m_native_id) { if (!m_native_id)
{
return 0; return 0;
} }

View File

@ -67,17 +67,20 @@
src = (enumName)((int)src + 1); \ src = (enumName)((int)src + 1); \
return src; \ return src; \
} \ } \
\
static __fi enumName& operator--(enumName& src) \ static __fi enumName& operator--(enumName& src) \
{ \ { \
src = (enumName)((int)src - 1); \ src = (enumName)((int)src - 1); \
return src; \ return src; \
} \ } \
\
static __fi enumName operator++(enumName& src, int) \ static __fi enumName operator++(enumName& src, int) \
{ \ { \
enumName orig = src; \ enumName orig = src; \
src = (enumName)((int)src + 1); \ src = (enumName)((int)src + 1); \
return orig; \ return orig; \
} \ } \
\
static __fi enumName operator--(enumName& src, int) \ static __fi enumName operator--(enumName& src, int) \
{ \ { \
enumName orig = src; \ enumName orig = src; \
@ -93,6 +96,7 @@
{ \ { \
return ((int)id >= enumName##_FIRST) && ((int)id < enumName##_COUNT); \ return ((int)id >= enumName##_FIRST) && ((int)id < enumName##_COUNT); \
} \ } \
\
static __fi void EnumAssert(enumName id) \ static __fi void EnumAssert(enumName id) \
{ \ { \
pxAssert(EnumIsValid(id)); \ pxAssert(EnumIsValid(id)); \

View File

@ -52,7 +52,8 @@ protected:
// //
void _loadImage() void _loadImage()
{ {
if (!m_Image.Ok()) { if (!m_Image.Ok())
{
wxMemoryInputStream joe(ImageType::Data, ImageType::Length); wxMemoryInputStream joe(ImageType::Data, ImageType::Length);
m_Image.LoadFile(joe, ImageType::GetFormat()); m_Image.LoadFile(joe, ImageType::GetFormat());

View File

@ -25,9 +25,11 @@ typename EventSource<ListenerType>::ListenerIterator EventSource<ListenerType>::
ScopedLock locker(m_listeners_lock); ScopedLock locker(m_listeners_lock);
// Check for duplicates before adding the event. // Check for duplicates before adding the event.
if (IsDebugBuild) { if (IsDebugBuild)
{
ListenerIterator iter = m_listeners.begin(); ListenerIterator iter = m_listeners.begin();
while (iter != m_listeners.end()) { while (iter != m_listeners.end())
{
if ((*iter) == &listener) if ((*iter) == &listener)
return iter; return iter;
++iter; ++iter;
@ -64,17 +66,27 @@ typename EventSource<ListenerType>::ListenerIterator EventSource<ListenerType>::
template <typename ListenerType> template <typename ListenerType>
__fi void EventSource<ListenerType>::_DispatchRaw(ListenerIterator iter, const ListenerIterator& iend, const EvtParams& evtparams) __fi void EventSource<ListenerType>::_DispatchRaw(ListenerIterator iter, const ListenerIterator& iend, const EvtParams& evtparams)
{ {
while (iter != iend) { while (iter != iend)
try { {
try
{
(*iter)->DispatchEvent(evtparams); (*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()); 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()); 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(); ex.DiagMsg() = L"Non-runtime BaseException thrown from event listener .. " + ex.DiagMsg();
throw; throw;
} }
@ -87,7 +99,8 @@ __fi void EventSource<ListenerType>::_DispatchRaw(ListenerIterator iter, const L
template <typename ListenerType> template <typename ListenerType>
void EventSource<ListenerType>::Dispatch(const EvtParams& evtparams) void EventSource<ListenerType>::Dispatch(const EvtParams& evtparams)
{ {
if (!m_cache_valid) { if (!m_cache_valid)
{
m_cache_copy = m_listeners; m_cache_copy = m_listeners;
m_cache_valid = true; m_cache_valid = true;
} }

View File

@ -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. // we get meaningless assertions while unwinding stack traces after exceptions have occurred.
RecursionGuard guard(s_assert_guard); RecursionGuard guard(s_assert_guard);
if (guard.Counter > 2) { if (guard.Counter > 2)
{
return pxTrap(); return pxTrap();
} }
@ -114,14 +115,18 @@ DEVASSERT_INLINE void pxOnAssert(const DiagnosticOrigin &origin, const wxString
bool trapit; bool trapit;
if (pxDoAssert == NULL) { if (pxDoAssert == NULL)
{
// Note: Format uses MSVC's syntax for output window hotlinking. // Note: Format uses MSVC's syntax for output window hotlinking.
trapit = pxAssertImpl_LogIt(origin, msg.wc_str()); trapit = pxAssertImpl_LogIt(origin, msg.wc_str());
} else { }
else
{
trapit = pxDoAssert(origin, msg.wc_str()); trapit = pxDoAssert(origin, msg.wc_str());
} }
if (trapit) { if (trapit)
{
pxTrap(); pxTrap();
} }
} }
@ -389,7 +394,8 @@ BaseException *Exception::FromErrno(const wxString &streamname, int errcode)
{ {
pxAssumeDev(errcode != 0, "Invalid NULL error code? (errno)"); pxAssumeDev(errcode != 0, "Invalid NULL error code? (errno)");
switch (errcode) { switch (errcode)
{
case EINVAL: case EINVAL:
pxFailDev(L"Invalid argument"); pxFailDev(L"Invalid argument");
return &(new Exception::BadStream(streamname))->SetDiagMsg(L"Invalid argument? (likely caused by an unforgivable programmer error!)"); return &(new Exception::BadStream(streamname))->SetDiagMsg(L"Invalid argument? (likely caused by an unforgivable programmer error!)");

View File

@ -35,19 +35,25 @@ void pxTrap();
#define __DESTRUCTOR_CATCHALL(funcname) \ #define __DESTRUCTOR_CATCHALL(funcname) \
catch (BaseException & ex) \ catch (BaseException & ex) \
{ \ { \
try { \ try \
{ \
Console.Error("Unhandled BaseException in %s (ignored!):", funcname); \ Console.Error("Unhandled BaseException in %s (ignored!):", funcname); \
Console.Error(ex.FormatDiagnosticMessage()); \ Console.Error(ex.FormatDiagnosticMessage()); \
} catch (...) { \ } \
catch (...) \
{ \
fprintf(stderr, "ERROR: (out of memory?)\n"); \ fprintf(stderr, "ERROR: (out of memory?)\n"); \
} \ } \
} \ } \
catch (std::exception & ex) \ catch (std::exception & ex) \
{ \ { \
try { \ try \
{ \
Console.Error("Unhandled std::exception in %s (ignored!):", funcname); \ Console.Error("Unhandled std::exception in %s (ignored!):", funcname); \
Console.Error(ex.what()); \ Console.Error(ex.what()); \
} catch (...) { \ } \
catch (...) \
{ \
fprintf(stderr, "ERROR: (out of memory?)\n"); \ fprintf(stderr, "ERROR: (out of memory?)\n"); \
} \ } \
} \ } \
@ -162,8 +168,16 @@ private: \
\ \
public: \ public: \
virtual ~classname() = default; \ 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) \ #define DEFINE_EXCEPTION_MESSAGES(classname) \
public: \ public: \
@ -172,11 +186,13 @@ public: \
BaseException::SetBothMsgs(msg_diag); \ BaseException::SetBothMsgs(msg_diag); \
return *this; \ return *this; \
} \ } \
\
classname& SetDiagMsg(const wxString& msg_diag) \ classname& SetDiagMsg(const wxString& msg_diag) \
{ \ { \
m_message_diag = msg_diag; \ m_message_diag = msg_diag; \
return *this; \ return *this; \
} \ } \
\
classname& SetUserMsg(const wxString& msg_user) \ classname& SetUserMsg(const wxString& msg_user) \
{ \ { \
m_message_user = msg_user; \ m_message_user = msg_user; \
@ -185,7 +201,10 @@ public: \
#define DEFINE_RUNTIME_EXCEPTION(classname, parent, message) \ #define DEFINE_RUNTIME_EXCEPTION(classname, parent, message) \
DEFINE_EXCEPTION_COPYTORS(classname, parent) \ DEFINE_EXCEPTION_COPYTORS(classname, parent) \
classname() { SetDiagMsg(message); } \ classname() \
{ \
SetDiagMsg(message); \
} \
DEFINE_EXCEPTION_MESSAGES(classname) DEFINE_EXCEPTION_MESSAGES(classname)
@ -294,6 +313,7 @@ public:
StreamName = name; \ StreamName = name; \
return *this; \ return *this; \
} \ } \
\
virtual classname& SetStreamName(const char* name) \ virtual classname& SetStreamName(const char* name) \
{ \ { \
StreamName = fromUTF8(name); \ StreamName = fromUTF8(name); \
@ -390,7 +410,7 @@ public:
virtual wxString FormatDiagnosticMessage() const; virtual wxString FormatDiagnosticMessage() const;
}; };
#endif #endif
} } // namespace Exception
using Exception::BaseException; using Exception::BaseException;
using Exception::ScopedExcept; using Exception::ScopedExcept;

View File

@ -33,15 +33,15 @@ template class SafeAlignedArray<u8, 16>;
// system deadlock. // system deadlock.
static const int MaxFormattedStringLength = 0x80000; static const int MaxFormattedStringLength = 0x80000;
static
#ifndef __linux__ #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 #endif
void
format_that_ascii_mess(CharBufferType &buffer, uint writepos, const char *fmt, va_list argptr)
{ {
va_list args; va_list args;
while (true) { while (true)
{
int size = buffer.GetLength(); int size = buffer.GetLength();
va_copy(args, argptr); va_copy(args, argptr);
@ -74,15 +74,15 @@ static
} }
// returns the length of the formatted string, in characters (wxChars). // returns the length of the formatted string, in characters (wxChars).
static
#ifndef __linux__ #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 #endif
uint
format_that_unicode_mess(CharBufferType &buffer, uint writepos, const wxChar *fmt, va_list argptr)
{ {
va_list args; va_list args;
while (true) { while (true)
{
int size = buffer.GetLength() / sizeof(wxChar); int size = buffer.GetLength() / sizeof(wxChar);
va_copy(args, argptr); va_copy(args, argptr);

View File

@ -33,10 +33,8 @@
{ {
#define BITFIELD_END \ #define BITFIELD_END \
} \ }; \
; \ };
} \
;
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
@ -257,7 +255,7 @@ void MemProtectStatic(u8 (&arr)[size], const PageProtectionMode &mode)
{ {
MemProtect(arr, size, mode); MemProtect(arr, size, mode);
} }
} } // namespace HostSys
// Safe version of Munmap -- NULLs the pointer variable immediately after free'ing it. // Safe version of Munmap -- NULLs the pointer variable immediately after free'ing it.
#define SafeSysMunmap(ptr, size) \ #define SafeSysMunmap(ptr, size) \

View File

@ -29,7 +29,8 @@ void SetFullBaseDir(wxDirName appRoot)
static int _calcEnumLength(const wxChar* const* enumArray) static int _calcEnumLength(const wxChar* const* enumArray)
{ {
int cnt = 0; int cnt = 0;
while (*enumArray != NULL) { while (*enumArray != NULL)
{
enumArray++; enumArray++;
cnt++; cnt++;
} }
@ -119,7 +120,8 @@ void IniLoader::Entry(const wxString &var, wxDirName &value, const wxDirName def
if (dest.IsEmpty()) if (dest.IsEmpty())
value = defvalue; value = defvalue;
else { else
{
value = dest; value = dest;
if (isAllowRelative) if (isAllowRelative)
value = g_fullBaseDirName + value; 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) void IniLoader::Entry(const wxString& var, wxPoint& value, const wxPoint defvalue)
{ {
if (!m_Config) { if (!m_Config)
{
value = defvalue; value = defvalue;
return; 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) void IniLoader::Entry(const wxString& var, wxSize& value, const wxSize defvalue)
{ {
if (!m_Config) { if (!m_Config)
{
value = defvalue; value = defvalue;
return; 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) void IniLoader::Entry(const wxString& var, wxRect& value, const wxRect defvalue)
{ {
if (!m_Config) { if (!m_Config)
{
value = defvalue; value = defvalue;
return; return;
} }
@ -233,14 +238,16 @@ void IniLoader::_EnumEntry(const wxString &var, int &value, const wxChar *const
// Confirm default value sanity... // Confirm default value sanity...
const int cnt = _calcEnumLength(enumArray); 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."); Console.Error("(LoadSettings) Default enumeration index is out of bounds. Truncating.");
defvalue = cnt - 1; defvalue = cnt - 1;
} }
// Sanity confirmed, proceed with craziness! // Sanity confirmed, proceed with craziness!
if (!m_Config) { if (!m_Config)
{
value = defvalue; value = defvalue;
return; return;
} }
@ -252,11 +259,13 @@ void IniLoader::_EnumEntry(const wxString &var, int &value, const wxChar *const
while (enumArray[i] != NULL && (retval != enumArray[i])) while (enumArray[i] != NULL && (retval != enumArray[i]))
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'.", 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]); WX_STR(retval), WX_STR(var), enumArray[defvalue]);
value = defvalue; value = defvalue;
} else }
else
value = i; value = i;
} }
@ -390,7 +399,8 @@ void IniSaver::_EnumEntry(const wxString &var, int &value, const wxChar *const *
// Confirm default value sanity... // 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."); Console.Error("(SaveSettings) Default enumeration index is out of bounds. Truncating.");
defvalue = cnt - 1; defvalue = cnt - 1;
} }
@ -398,7 +408,8 @@ void IniSaver::_EnumEntry(const wxString &var, int &value, const wxChar *const *
if (!m_Config) if (!m_Config)
return; return;
if (value >= cnt) { if (value >= cnt)
{
Console.Warning(L"(SaveSettings) An illegal enumerated index was detected when saving '%s'", WX_STR(var)); Console.Warning(L"(SaveSettings) An illegal enumerated index was detected when saving '%s'", WX_STR(var));
Console.Indent().Warning( Console.Indent().Warning(
L"Illegal Value: %d\n" L"Illegal Value: %d\n"

View File

@ -64,7 +64,8 @@ static void SysPageFaultSignalFilter(int signal, siginfo_t *siginfo, void *)
if (Source_PageFault->WasHandled()) if (Source_PageFault->WasHandled())
return; return;
if (!wxThread::IsMain()) { if (!wxThread::IsMain())
{
pxFailRel(pxsFmt("Unhandled page fault @ 0x%08x", siginfo->si_addr)); 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) if (result == 0)
return true; return true;
switch (errno) { switch (errno)
{
case EINVAL: case EINVAL:
pxFailDev(pxsFmt(L"mprotect returned EINVAL @ 0x%08X -> 0x%08X (mode=%s)", pxFailDev(pxsFmt(L"mprotect returned EINVAL @ 0x%08X -> 0x%08X (mode=%s)",
baseaddr, (uptr)baseaddr + size, WX_STR(mode.ToString()))); 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) 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") throw Exception::OutOfMemory(L"MemProtect")
.SetDiagMsg(pxsFmt(L"mprotect failed @ 0x%08X -> 0x%08X (mode=%s)", .SetDiagMsg(pxsFmt(L"mprotect failed @ 0x%08X -> 0x%08X (mode=%s)",
baseaddr, (uptr)baseaddr + size, WX_STR(mode.ToString()))); baseaddr, (uptr)baseaddr + size, WX_STR(mode.ToString())));

View File

@ -71,11 +71,14 @@ u64 Threading::GetThreadTicksPerSecond()
static u64 get_thread_time(uptr id = 0) static u64 get_thread_time(uptr id = 0)
{ {
clockid_t cid; clockid_t cid;
if (id) { if (id)
{
int err = pthread_getcpuclockid((pthread_t)id, &cid); int err = pthread_getcpuclockid((pthread_t)id, &cid);
if (err) if (err)
return 0; return 0;
} else { }
else
{
cid = CLOCK_THREAD_CPUTIME_ID; cid = CLOCK_THREAD_CPUTIME_ID;
} }

View File

@ -26,15 +26,18 @@ __noinline void memset_sse_a(void *dest, const size_t size)
__m128 srcreg; __m128 srcreg;
if (data != 0) { if (data != 0)
{
static __aligned16 const u8 loadval[8] = {data, data, data, data, data, data, data, data}; 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); srcreg = _mm_loadh_pi(_mm_load_ps((float*)loadval), (__m64*)loadval);
} else }
else
srcreg = _mm_setzero_ps(); srcreg = _mm_setzero_ps();
float(*destxmm)[4] = (float(*)[4])dest; float(*destxmm)[4] = (float(*)[4])dest;
switch (MZFqwc & 0x07) { switch (MZFqwc & 0x07)
{
case 0x07: case 0x07:
_mm_store_ps(&destxmm[0x07 - 1][0], srcreg); _mm_store_ps(&destxmm[0x07 - 1][0], srcreg);
// Fall through // Fall through
@ -59,7 +62,8 @@ __noinline void memset_sse_a(void *dest, const size_t size)
} }
destxmm += (MZFqwc & 0x07); 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[0][0], srcreg);
_mm_store_ps(&destxmm[1][0], srcreg); _mm_store_ps(&destxmm[1][0], srcreg);
_mm_store_ps(&destxmm[2][0], srcreg); _mm_store_ps(&destxmm[2][0], srcreg);

View File

@ -22,7 +22,7 @@ namespace Threading
{ {
static std::atomic<int> _attr_refcount(0); static std::atomic<int> _attr_refcount(0);
static pthread_mutexattr_t _attr_recursive; static pthread_mutexattr_t _attr_recursive;
} } // namespace Threading
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// Mutex Implementations // Mutex Implementations
@ -57,14 +57,14 @@ static int xpthread_mutex_timedlock(
{ {
int err = 0; 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 // check if the timeout has expired, gettimeofday() is implemented
// efficiently (in userspace) on OSX // efficiently (in userspace) on OSX
struct timeval now; struct timeval now;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
if (now.tv_sec > abs_timeout->tv_sec 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))
|| (now.tv_sec == abs_timeout->tv_sec {
&& (u64)now.tv_usec * 1000ULL > (u64)abs_timeout->tv_nsec)) {
return ETIMEDOUT; return ETIMEDOUT;
} }
@ -72,7 +72,8 @@ static int xpthread_mutex_timedlock(
struct timespec ts; struct timespec ts;
ts.tv_sec = 0; ts.tv_sec = 0;
ts.tv_nsec = TIMEDLOCK_EMU_SLEEP_NS; ts.tv_nsec = TIMEDLOCK_EMU_SLEEP_NS;
while (nanosleep(&ts, &ts) == -1); while (nanosleep(&ts, &ts) == -1)
;
} }
return err; return err;
@ -91,7 +92,8 @@ void Threading::Mutex::Detach()
if (EBUSY != pthread_mutex_destroy(&m_mutex)) if (EBUSY != pthread_mutex_destroy(&m_mutex))
return; return;
if (IsRecursive()) { if (IsRecursive())
{
// Sanity check: Recursive locks could be held by our own thread, which would // Sanity check: Recursive locks could be held by our own thread, which would
// be considered an assertion failure, but can also be handled gracefully. // 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 // (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() Threading::Mutex::~Mutex()
{ {
try { try
{
Mutex::Detach(); Mutex::Detach();
} }
DESTRUCTOR_CATCHALL; DESTRUCTOR_CATCHALL;
@ -121,7 +124,8 @@ Threading::Mutex::~Mutex()
Threading::MutexRecursive::MutexRecursive() Threading::MutexRecursive::MutexRecursive()
: Mutex(false) : Mutex(false)
{ {
if (++_attr_refcount == 1) { if (++_attr_refcount == 1)
{
if (0 != pthread_mutexattr_init(&_attr_recursive)) if (0 != pthread_mutexattr_init(&_attr_recursive))
throw Exception::OutOfMemory(L"Recursive mutexing attributes"); throw Exception::OutOfMemory(L"Recursive mutexing attributes");
@ -153,7 +157,8 @@ void Threading::Mutex::Recreate()
// unlocked. // unlocked.
bool Threading::Mutex::RecreateIfLocked() bool Threading::Mutex::RecreateIfLocked()
{ {
if (!Wait(def_detach_timeout)) { if (!Wait(def_detach_timeout))
{
Recreate(); Recreate();
return true; return true;
} }
@ -194,12 +199,17 @@ bool Threading::Mutex::TryAcquire()
void Threading::Mutex::Acquire() void Threading::Mutex::Acquire()
{ {
#if wxUSE_GUI #if wxUSE_GUI
if (!wxThread::IsMain() || (wxTheApp == NULL)) { if (!wxThread::IsMain() || (wxTheApp == NULL))
{
pthread_mutex_lock(&m_mutex); pthread_mutex_lock(&m_mutex);
} else if (_WaitGui_RecursionGuard(L"Mutex::Acquire")) { }
else if (_WaitGui_RecursionGuard(L"Mutex::Acquire"))
{
ScopedBusyCursor hourglass(Cursor_ReallyBusy); ScopedBusyCursor hourglass(Cursor_ReallyBusy);
pthread_mutex_lock(&m_mutex); pthread_mutex_lock(&m_mutex);
} else { }
else
{
//ScopedBusyCursor hourglass( Cursor_KindaBusy ); //ScopedBusyCursor hourglass( Cursor_KindaBusy );
while (!AcquireWithoutYield(def_yieldgui_interval)) while (!AcquireWithoutYield(def_yieldgui_interval))
YieldToMain(); YieldToMain();
@ -212,16 +222,22 @@ void Threading::Mutex::Acquire()
bool Threading::Mutex::Acquire(const wxTimeSpan& timeout) bool Threading::Mutex::Acquire(const wxTimeSpan& timeout)
{ {
#if wxUSE_GUI #if wxUSE_GUI
if (!wxThread::IsMain() || (wxTheApp == NULL)) { if (!wxThread::IsMain() || (wxTheApp == NULL))
{
return AcquireWithoutYield(timeout); return AcquireWithoutYield(timeout);
} else if (_WaitGui_RecursionGuard(L"Mutex::TimedAcquire")) { }
else if (_WaitGui_RecursionGuard(L"Mutex::TimedAcquire"))
{
ScopedBusyCursor hourglass(Cursor_ReallyBusy); ScopedBusyCursor hourglass(Cursor_ReallyBusy);
return AcquireWithoutYield(timeout); return AcquireWithoutYield(timeout);
} else { }
else
{
//ScopedBusyCursor hourglass( Cursor_KindaBusy ); //ScopedBusyCursor hourglass( Cursor_KindaBusy );
wxTimeSpan countdown((timeout)); wxTimeSpan countdown((timeout));
do { do
{
if (AcquireWithoutYield(def_yieldgui_interval)) if (AcquireWithoutYield(def_yieldgui_interval))
break; break;
YieldToMain(); YieldToMain();
@ -264,7 +280,8 @@ void Threading::Mutex::WaitWithoutYield()
// //
bool Threading::Mutex::Wait(const wxTimeSpan& timeout) bool Threading::Mutex::Wait(const wxTimeSpan& timeout)
{ {
if (Acquire(timeout)) { if (Acquire(timeout))
{
Release(); Release();
return true; return true;
} }
@ -273,7 +290,8 @@ bool Threading::Mutex::Wait(const wxTimeSpan &timeout)
bool Threading::Mutex::WaitWithoutYield(const wxTimeSpan& timeout) bool Threading::Mutex::WaitWithoutYield(const wxTimeSpan& timeout)
{ {
if (AcquireWithoutYield(timeout)) { if (AcquireWithoutYield(timeout))
{
Release(); Release();
return true; return true;
} }

View File

@ -155,7 +155,8 @@ public:
// offsetLocation must be page-aligned // offsetLocation must be page-aligned
void* Alloc(uptr offsetLocation, size_t size) const; 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); return Alloc(size, (uptr)address - m_baseptr);
} }
@ -176,6 +177,7 @@ class VirtualMemoryBumpAllocator
const VirtualMemoryManagerPtr m_allocator; const VirtualMemoryManagerPtr m_allocator;
std::atomic<uptr> m_baseptr{0}; std::atomic<uptr> m_baseptr{0};
const uptr m_endptr = 0; const uptr m_endptr = 0;
public: public:
VirtualMemoryBumpAllocator(VirtualMemoryManagerPtr allocator, size_t size, uptr offsetLocation); VirtualMemoryBumpAllocator(VirtualMemoryManagerPtr allocator, size_t size, uptr offsetLocation);
void* Alloc(size_t size); void* Alloc(size_t size);

View File

@ -86,7 +86,8 @@ public:
wxFileName f(file); wxFileName f(file);
while (1) { while (1)
{
if (this->SameAs(wxDirName(f.GetPath()))) if (this->SameAs(wxDirName(f.GetPath())))
return true; return true;
@ -124,9 +125,12 @@ public:
wxString sv(subject.GetVolume()); wxString sv(subject.GetVolume());
sv.MakeUpper(); sv.MakeUpper();
if (base.IsContains(subject)) { if (base.IsContains(subject))
{
subject.MakeRelativeTo(base.GetFullPath()); subject.MakeRelativeTo(base.GetFullPath());
} else if (base.HasVolume() && subject.HasVolume() && bv == sv) { }
else if (base.HasVolume() && subject.HasVolume() && bv == sv)
{
wxString unusedVolume; wxString unusedVolume;
wxString pathSansVolume; wxString pathSansVolume;
subject.SplitVolume(subject.GetFullPath(), &unusedVolume, &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 GetDirectory(const wxString& src);
extern wxString GetFilenameWithoutExt(const wxString& src); extern wxString GetFilenameWithoutExt(const wxString& src);
extern wxString GetRootDirectory(const wxString& src); extern wxString GetRootDirectory(const wxString& src);
} } // namespace Path

View File

@ -100,7 +100,8 @@ void InfoVector::map(uptr x86, u32 size, const char *symbol)
u32 max_code_size = _1gb; u32 max_code_size = _1gb;
#endif #endif
if (size < max_code_size) { if (size < max_code_size)
{
m_v.emplace_back(x86, size, symbol); m_v.emplace_back(x86, size, symbol);
#ifdef ENABLE_VTUNE #ifdef ENABLE_VTUNE
@ -203,4 +204,4 @@ void dump() {}
void dump_and_reset() {} void dump_and_reset() {}
#endif #endif
} } // namespace Perf

View File

@ -59,4 +59,4 @@ extern InfoVector ee;
extern InfoVector iop; extern InfoVector iop;
extern InfoVector vu; extern InfoVector vu;
extern InfoVector vif; extern InfoVector vif;
} } // namespace Perf

View File

@ -206,4 +206,4 @@ protected:
static void internal_callback_helper(void* func); static void internal_callback_helper(void* func);
static void _pt_callback_cleanup(void* handle); static void _pt_callback_cleanup(void* handle);
}; };
} } // namespace Threading

View File

@ -87,4 +87,4 @@ public:
protected: protected:
ScopedWriteLock(RwMutex& locker, bool isTryLock); ScopedWriteLock(RwMutex& locker, bool isTryLock);
}; };
} } // namespace Threading

View File

@ -42,7 +42,8 @@ T *SafeArray<T>::_virtual_realloc(int newsize)
malloc(newsize * sizeof(T)) : malloc(newsize * sizeof(T)) :
realloc(m_ptr, 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 // Zero everything out to 0xbaadf00d, so that its obviously uncleared
// to a debuggee // to a debuggee
@ -201,7 +202,8 @@ SafeList<T>::SafeList(int initialSize, const wxChar *name)
throw Exception::OutOfMemory(Name) throw Exception::OutOfMemory(Name)
.SetDiagMsg(wxsFormat(L"called from 'SafeList::ctor' [length=%d]", m_length)); .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(); new (&m_ptr[i]) T();
} }
} }
@ -218,14 +220,16 @@ T *SafeList<T>::_getPtr(uint i) const
template <typename T> template <typename T>
void SafeList<T>::MakeRoomFor(int blockSize) void SafeList<T>::MakeRoomFor(int blockSize)
{ {
if (blockSize > m_allocsize) { if (blockSize > m_allocsize)
{
const int newalloc = blockSize + ChunkSize; const int newalloc = blockSize + ChunkSize;
m_ptr = _virtual_realloc(newalloc); m_ptr = _virtual_realloc(newalloc);
if (m_ptr == NULL) if (m_ptr == NULL)
throw Exception::OutOfMemory(Name) throw Exception::OutOfMemory(Name)
.SetDiagMsg(wxsFormat(L"Called from 'SafeList::MakeRoomFor' [oldlen=%d] [newlen=%d]", m_length, blockSize)); .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(); new (&m_ptr[m_allocsize]) T();
} }
} }

View File

@ -51,7 +51,8 @@ void Threading::Semaphore::Post(int multiple)
sem_post_multiple(&m_sema, multiple); sem_post_multiple(&m_sema, multiple);
#else #else
// Only w32pthreads has the post_multiple, but it's easy enough to fake: // Only w32pthreads has the post_multiple, but it's easy enough to fake:
while (multiple > 0) { while (multiple > 0)
{
multiple--; multiple--;
sem_post(&m_sema); sem_post(&m_sema);
} }
@ -80,12 +81,17 @@ bool Threading::Semaphore::WaitWithoutYield(const wxTimeSpan &timeout)
void Threading::Semaphore::Wait() void Threading::Semaphore::Wait()
{ {
#if wxUSE_GUI #if wxUSE_GUI
if (!wxThread::IsMain() || (wxTheApp == NULL)) { if (!wxThread::IsMain() || (wxTheApp == NULL))
{
sem_wait(&m_sema); sem_wait(&m_sema);
} else if (_WaitGui_RecursionGuard(L"Semaphore::Wait")) { }
else if (_WaitGui_RecursionGuard(L"Semaphore::Wait"))
{
ScopedBusyCursor hourglass(Cursor_ReallyBusy); ScopedBusyCursor hourglass(Cursor_ReallyBusy);
sem_wait(&m_sema); sem_wait(&m_sema);
} else { }
else
{
//ScopedBusyCursor hourglass( Cursor_KindaBusy ); //ScopedBusyCursor hourglass( Cursor_KindaBusy );
while (!WaitWithoutYield(def_yieldgui_interval)) while (!WaitWithoutYield(def_yieldgui_interval))
YieldToMain(); YieldToMain();
@ -107,16 +113,22 @@ void Threading::Semaphore::Wait()
bool Threading::Semaphore::Wait(const wxTimeSpan& timeout) bool Threading::Semaphore::Wait(const wxTimeSpan& timeout)
{ {
#if wxUSE_GUI #if wxUSE_GUI
if (!wxThread::IsMain() || (wxTheApp == NULL)) { if (!wxThread::IsMain() || (wxTheApp == NULL))
{
return WaitWithoutYield(timeout); return WaitWithoutYield(timeout);
} else if (_WaitGui_RecursionGuard(L"Semaphore::TimedWait")) { }
else if (_WaitGui_RecursionGuard(L"Semaphore::TimedWait"))
{
ScopedBusyCursor hourglass(Cursor_ReallyBusy); ScopedBusyCursor hourglass(Cursor_ReallyBusy);
return WaitWithoutYield(timeout); return WaitWithoutYield(timeout);
} else { }
else
{
//ScopedBusyCursor hourglass( Cursor_KindaBusy ); //ScopedBusyCursor hourglass( Cursor_KindaBusy );
wxTimeSpan countdown((timeout)); wxTimeSpan countdown((timeout));
do { do
{
if (WaitWithoutYield(def_yieldgui_interval)) if (WaitWithoutYield(def_yieldgui_interval))
break; break;
YieldToMain(); YieldToMain();

View File

@ -94,7 +94,8 @@ void SplitString(wxArrayString &dest, const wxString &src, const wxString &delim
wxString JoinString(const wxArrayString& src, const wxString& separator) wxString JoinString(const wxArrayString& src, const wxString& separator)
{ {
wxString dest; 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()) if (src[i].IsEmpty())
continue; continue;
if (!dest.IsEmpty()) if (!dest.IsEmpty())
@ -107,7 +108,8 @@ wxString JoinString(const wxArrayString &src, const wxString &separator)
wxString JoinString(const wxChar** src, const wxString& separator) wxString JoinString(const wxChar** src, const wxString& separator)
{ {
wxString dest; wxString dest;
while (*src != NULL) { while (*src != NULL)
{
if (*src[0] == 0) if (*src[0] == 0)
continue; continue;
@ -260,10 +262,14 @@ void px_fputs(FILE *fp, const char *src)
const char* curchar = src; const char* curchar = src;
bool prevcr = false; bool prevcr = false;
while (*curchar != 0) { while (*curchar != 0)
if (*curchar == '\r') { {
if (*curchar == '\r')
{
prevcr = true; prevcr = true;
} else { }
else
{
// Only write a CR/LF pair if the current LF is not prefixed nor // Only write a CR/LF pair if the current LF is not prefixed nor
// post-fixed by a CR. // post-fixed by a CR.
if (*curchar == '\n' && !prevcr && (*(curchar + 1) != '\r')) if (*curchar == '\n' && !prevcr && (*(curchar + 1) != '\r'))

View File

@ -75,7 +75,8 @@ static void make_curthread_key(const pxThread *thr)
if (total_key_count++ != 0) if (total_key_count++ != 0)
return; 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 >_<)"); pxThreadLog.Error(thr->GetName(), L"Thread key creation failed (probably out of memory >_<)");
curthread_key = 0; curthread_key = 0;
} }
@ -114,9 +115,12 @@ pxThread *Threading::pxGetCurrentThread()
// nor the Main/UI thread. // nor the Main/UI thread.
wxString Threading::pxGetCurrentThreadName() wxString Threading::pxGetCurrentThreadName()
{ {
if (pxThread *thr = pxGetCurrentThread()) { if (pxThread* thr = pxGetCurrentThread())
{
return thr->GetName(); return thr->GetName();
} else if (wxThread::IsMain()) { }
else if (wxThread::IsMain())
{
return L"Main/UI"; 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. // like marrying your sister, and then cheating on her with your daughter.
Threading::pxThread::~pxThread() Threading::pxThread::~pxThread()
{ {
try { try
{
pxThreadLog.Write(GetName(), L"Executing default destructor!"); pxThreadLog.Write(GetName(), L"Executing default destructor!");
if (m_running) { if (m_running)
{
pxThreadLog.Write(GetName(), L"Waiting for running thread to end..."); pxThreadLog.Write(GetName(), L"Waiting for running thread to end...");
m_mtx_InThread.Wait(); m_mtx_InThread.Wait();
pxThreadLog.Write(GetName(), L"Thread ended gracefully."); pxThreadLog.Write(GetName(), L"Thread ended gracefully.");
@ -222,7 +228,8 @@ bool Threading::pxThread::AffinityAssert_DisallowFromSelf(const DiagnosticOrigin
void Threading::pxThread::FrankenMutex(Mutex& mutex) void Threading::pxThread::FrankenMutex(Mutex& mutex)
{ {
if (mutex.RecreateIfLocked()) { if (mutex.RecreateIfLocked())
{
// Our lock is bupkis, which means the previous thread probably deadlocked. // Our lock is bupkis, which means the previous thread probably deadlocked.
// Let's create a new mutex lock to replace it. // 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: // Prevents sudden parallel startup, and or parallel startup + cancel:
ScopedLock startlock(m_mtx_start); ScopedLock startlock(m_mtx_start);
if (m_running) { if (m_running)
{
pxThreadLog.Write(GetName(), L"Start() called on running thread; ignorning..."); pxThreadLog.Write(GetName(), L"Start() called on running thread; ignorning...");
return; return;
} }
@ -259,12 +267,14 @@ void Threading::pxThread::Start()
// //
// In our case, the semaphore was posted (counter is 1) but thread is still // In our case, the semaphore was posted (counter is 1) but thread is still
// waiting... So waits 100ms and checks the counter value manually // 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) if (m_sem_startup.Count() == 0)
throw Exception::ThreadCreationError(this).SetDiagMsg(L"Thread creation error: %s thread never posted startup semaphore."); throw Exception::ThreadCreationError(this).SetDiagMsg(L"Thread creation error: %s thread never posted startup semaphore.");
} }
#else #else
if (!m_sem_startup.WaitWithoutYield(wxTimeSpan(0, 0, 3, 0))) { if (!m_sem_startup.WaitWithoutYield(wxTimeSpan(0, 0, 3, 0)))
{
RethrowException(); RethrowException();
// And if the thread threw nothing of its own: // And if the thread threw nothing of its own:
@ -305,7 +315,8 @@ bool Threading::pxThread::_basecancel()
if (!m_running) if (!m_running)
return false; return false;
if (m_detached) { if (m_detached)
{
pxThreadLog.Warn(GetName(), L"Ignoring attempted cancellation of detached thread."); pxThreadLog.Warn(GetName(), L"Ignoring attempted cancellation of detached thread.");
return false; return false;
} }
@ -338,7 +349,8 @@ void Threading::pxThread::Cancel(bool isBlocking)
if (!_basecancel()) if (!_basecancel())
return; return;
if (isBlocking) { if (isBlocking)
{
WaitOnSelf(m_mtx_InThread); WaitOnSelf(m_mtx_InThread);
Detach(); Detach();
} }
@ -432,12 +444,14 @@ void Threading::YieldToMain()
void Threading::pxThread::_selfRunningTest(const wxChar* name) const 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)); pxThreadLog.Error(GetName(), pxsFmt(L"An exception was thrown while waiting on a %s.", name));
RethrowException(); RethrowException();
} }
if (!m_running) { if (!m_running)
{
throw Exception::CancelEvent(pxsFmt( throw Exception::CancelEvent(pxsFmt(
L"Blocking thread %s was terminated while another thread was waiting on a %s.", L"Blocking thread %s was terminated while another thread was waiting on a %s.",
WX_STR(GetName()), name)); WX_STR(GetName()), name));
@ -467,7 +481,8 @@ void Threading::pxThread::WaitOnSelf(Semaphore &sem) const
if (!AffinityAssert_DisallowFromSelf(pxDiagSpot)) if (!AffinityAssert_DisallowFromSelf(pxDiagSpot))
return; return;
while (true) { while (true)
{
if (sem.WaitWithoutYield(wxTimeSpan(0, 0, 0, 333))) if (sem.WaitWithoutYield(wxTimeSpan(0, 0, 0, 333)))
return; return;
_selfRunningTest(L"semaphore"); _selfRunningTest(L"semaphore");
@ -492,7 +507,8 @@ void Threading::pxThread::WaitOnSelf(Mutex &mutex) const
if (!AffinityAssert_DisallowFromSelf(pxDiagSpot)) if (!AffinityAssert_DisallowFromSelf(pxDiagSpot))
return; return;
while (true) { while (true)
{
if (mutex.WaitWithoutYield(wxTimeSpan(0, 0, 0, 333))) if (mutex.WaitWithoutYield(wxTimeSpan(0, 0, 0, 333)))
return; return;
_selfRunningTest(L"mutex"); _selfRunningTest(L"mutex");
@ -508,7 +524,8 @@ bool Threading::pxThread::WaitOnSelf(Semaphore &sem, const wxTimeSpan &timeout)
wxTimeSpan runningout(timeout); wxTimeSpan runningout(timeout);
while (runningout.GetMilliseconds() > 0) { while (runningout.GetMilliseconds() > 0)
{
const wxTimeSpan interval((SelfWaitInterval < runningout) ? SelfWaitInterval : runningout); const wxTimeSpan interval((SelfWaitInterval < runningout) ? SelfWaitInterval : runningout);
if (sem.WaitWithoutYield(interval)) if (sem.WaitWithoutYield(interval))
return true; return true;
@ -525,7 +542,8 @@ bool Threading::pxThread::WaitOnSelf(Mutex &mutex, const wxTimeSpan &timeout) co
wxTimeSpan runningout(timeout); wxTimeSpan runningout(timeout);
while (runningout.GetMilliseconds() > 0) { while (runningout.GetMilliseconds() > 0)
{
const wxTimeSpan interval((SelfWaitInterval < runningout) ? SelfWaitInterval : runningout); const wxTimeSpan interval((SelfWaitInterval < runningout) ? SelfWaitInterval : runningout);
if (mutex.WaitWithoutYield(interval)) if (mutex.WaitWithoutYield(interval))
return true; return true;
@ -548,19 +566,22 @@ void Threading::pxThread::TestCancel() const
// Executes the virtual member method // Executes the virtual member method
void Threading::pxThread::_try_virtual_invoke(void (pxThread::*method)()) void Threading::pxThread::_try_virtual_invoke(void (pxThread::*method)())
{ {
try { try
{
(this->*method)(); (this->*method)();
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Neat repackaging for STL Runtime errors... // 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())); m_except = new Exception::RuntimeError(ex, WX_STR(GetName()));
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
catch (Exception::RuntimeError &ex) { catch (Exception::RuntimeError& ex)
{
BaseException* woot = ex.Clone(); BaseException* woot = ex.Clone();
woot->DiagMsg() += pxsFmt(L"(thread:%s)", WX_STR(GetName())); woot->DiagMsg() += pxsFmt(L"(thread:%s)", WX_STR(GetName()));
m_except = woot; m_except = woot;
@ -585,7 +606,8 @@ void Threading::pxThread::_try_virtual_invoke(void (pxThread::*method)())
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// BaseException -- same deal as LogicErrors. // BaseException -- same deal as LogicErrors.
// //
catch (BaseException &ex) { catch (BaseException& ex)
{
BaseException* woot = ex.Clone(); BaseException* woot = ex.Clone();
woot->DiagMsg() += pxsFmt(L"(thread:%s)", WX_STR(GetName())); woot->DiagMsg() += pxsFmt(L"(thread:%s)", WX_STR(GetName()));
m_except = woot; m_except = woot;

View File

@ -100,7 +100,7 @@ extern u64 GetThreadTicksPerSecond();
// Yields the current thread and provides cancellation points if the thread is managed by // Yields the current thread and provides cancellation points if the thread is managed by
// pxThread. Unmanaged threads use standard Sleep. // pxThread. Unmanaged threads use standard Sleep.
extern void pxYield(int ms); extern void pxYield(int ms);
} } // namespace Threading
namespace Exception namespace Exception
{ {
@ -155,7 +155,7 @@ public:
SetBothMsgs(L"Thread creation failure. An unspecified error occurred while trying to create the %s thread."); SetBothMsgs(L"Thread creation failure. An unspecified error occurred while trying to create the %s thread.");
} }
}; };
} } // namespace Exception
namespace Threading namespace Threading
@ -422,4 +422,4 @@ struct ScopedLockBool
m_lock.Release(); m_lock.Release();
} }
}; };
} } // namespace Threading

View File

@ -49,4 +49,4 @@ protected:
void OnTaskComplete(wxCommandEvent& evt); void OnTaskComplete(wxCommandEvent& evt);
//void OnTimer( wxTimerEvent& evt ); //void OnTimer( wxTimerEvent& evt );
}; };
} } // namespace Threading

View File

@ -27,4 +27,4 @@ extern bool _WaitGui_RecursionGuard(const wxChar *name);
extern void YieldToMain(); extern void YieldToMain();
extern bool AllowDeletions(); extern bool AllowDeletions();
} } // namespace Threading

View File

@ -27,7 +27,8 @@ Threading::Mutex PageFault_Mutex;
void pxInstallSignalHandler() void pxInstallSignalHandler()
{ {
if (!Source_PageFault) { if (!Source_PageFault)
{
Source_PageFault = new SrcType_PageFault(); Source_PageFault = new SrcType_PageFault();
} }
@ -59,7 +60,8 @@ void SrcType_PageFault::Dispatch(const PageFaultInfo &params)
void SrcType_PageFault::_DispatchRaw(ListenerIterator iter, const ListenerIterator& iend, const PageFaultInfo& evt) void SrcType_PageFault::_DispatchRaw(ListenerIterator iter, const ListenerIterator& iend, const PageFaultInfo& evt)
{ {
do { do
{
(*iter)->DispatchEvent(evt, m_handled); (*iter)->DispatchEvent(evt, m_handled);
} while ((++iter != iend) && !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) 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); uptr reserved_bytes = pageAlign(size);
m_pages_reserved = reserved_bytes / __pagesize; m_pages_reserved = reserved_bytes / __pagesize;
m_baseptr = (uptr)HostSys::MmapReserve(base, reserved_bytes); 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...", DevCon.Warning(L"%s: host memory @ %ls -> %ls is unavailable; attempting to map elsewhere...",
WX_STR(m_name), pxsPtr(base), pxsPtr(base + size)); WX_STR(m_name), pxsPtr(base), pxsPtr(base + size));
SafeSysMunmap(m_baseptr, reserved_bytes); 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 // Let's try again at an OS-picked memory area, and then hope it meets needed
// boundschecking criteria below. // boundschecking criteria below.
m_baseptr = (uptr)HostSys::MmapReserve(0, reserved_bytes); m_baseptr = (uptr)HostSys::MmapReserve(0, reserved_bytes);
@ -101,11 +109,13 @@ VirtualMemoryManager::VirtualMemoryManager(const wxString &name, uptr base, size
fulfillsRequirements = false; fulfillsRequirements = false;
if ((upper_bounds != 0) && ((m_baseptr + reserved_bytes) > upper_bounds)) if ((upper_bounds != 0) && ((m_baseptr + reserved_bytes) > upper_bounds))
fulfillsRequirements = false; fulfillsRequirements = false;
if (!fulfillsRequirements) { if (!fulfillsRequirements)
{
SafeSysMunmap(m_baseptr, reserved_bytes); SafeSysMunmap(m_baseptr, reserved_bytes);
} }
if (!m_baseptr) return; if (!m_baseptr)
return;
m_pageuse = new std::atomic<bool>[m_pages_reserved](); m_pageuse = new std::atomic<bool>[m_pages_reserved]();
@ -122,17 +132,24 @@ VirtualMemoryManager::VirtualMemoryManager(const wxString &name, uptr base, size
VirtualMemoryManager::~VirtualMemoryManager() VirtualMemoryManager::~VirtualMemoryManager()
{ {
if (m_pageuse) delete[] m_pageuse; if (m_pageuse)
if (m_baseptr) HostSys::Munmap(m_baseptr, m_pages_reserved * __pagesize); 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) { static bool VMMMarkPagesAsInUse(std::atomic<bool>* begin, std::atomic<bool>* end)
for (auto current = begin; current < end; current++) { {
for (auto current = begin; current < end; current++)
{
bool expected = false; 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 // This was already allocated! Undo the things we've set until this point
while (--current >= begin) { while (--current >= begin)
if (!current->compare_exchange_strong(expected, false, std::memory_order_relaxed)) { {
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 // 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 // This should never happen, but if it does we'll just stop and hope nothing bad happens
pxAssert(0); pxAssert(0);
@ -164,7 +181,8 @@ void *VirtualMemoryManager::Alloc(uptr offsetLocation, size_t size) const
void VirtualMemoryManager::Free(void* address, size_t size) const void VirtualMemoryManager::Free(void* address, size_t size) const
{ {
uptr offsetLocation = (uptr)address - m_baseptr; 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); uptr newLoc = pageAlign(offsetLocation);
size -= (offsetLocation - newLoc); size -= (offsetLocation - newLoc);
offsetLocation = newLoc; offsetLocation = newLoc;
@ -175,9 +193,11 @@ void VirtualMemoryManager::Free(void *address, size_t size) const
return; return;
auto puStart = &m_pageuse[offsetLocation / __pagesize]; auto puStart = &m_pageuse[offsetLocation / __pagesize];
auto puEnd = &m_pageuse[(offsetLocation + size) / __pagesize]; auto puEnd = &m_pageuse[(offsetLocation + size) / __pagesize];
for (; puStart < puEnd; puStart++) { for (; puStart < puEnd; puStart++)
{
bool expected = true; 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"); pxAssertDev(0, "(VirtaulMemoryManager) double-free");
} }
} }
@ -187,7 +207,9 @@ void VirtualMemoryManager::Free(void *address, size_t size) const
// VirtualMemoryBumpAllocator (implementations) // VirtualMemoryBumpAllocator (implementations)
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
VirtualMemoryBumpAllocator::VirtualMemoryBumpAllocator(VirtualMemoryManagerPtr allocator, uptr offsetLocation, size_t size) 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) if (m_baseptr.load() == 0)
pxAssertDev(0, "(VirtualMemoryBumpAllocator) tried to construct from bad VirtualMemoryManager"); pxAssertDev(0, "(VirtualMemoryBumpAllocator) tried to construct from bad VirtualMemoryManager");
@ -296,7 +318,8 @@ void VirtualMemoryReserve::Reset()
void VirtualMemoryReserve::Release() void VirtualMemoryReserve::Release()
{ {
if (!m_baseptr) return; if (!m_baseptr)
return;
Reset(); Reset();
m_allocator->Free(m_baseptr, m_pages_reserved * __pagesize); m_allocator->Free(m_baseptr, m_pages_reserved * __pagesize);
m_baseptr = nullptr; m_baseptr = nullptr;
@ -339,13 +362,15 @@ bool VirtualMemoryReserve::TryResize(uint newsize)
{ {
uint newPages = pageAlign(newsize) / __pagesize; uint newPages = pageAlign(newsize) / __pagesize;
if (newPages > m_pages_reserved) { if (newPages > m_pages_reserved)
{
uint toReservePages = newPages - m_pages_reserved; uint toReservePages = newPages - m_pages_reserved;
uint toReserveBytes = toReservePages * __pagesize; uint toReserveBytes = toReservePages * __pagesize;
DevCon.WriteLn(L"%-32s is being expanded by %u pages.", WX_STR(m_name), toReservePages); 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.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); Console.Indent().Warning("(attempted to map memory @ %08p -> %08p)", m_baseptr, (uptr)m_baseptr + toReserveBytes);
return false; return false;
@ -353,7 +378,9 @@ bool VirtualMemoryReserve::TryResize(uint newsize)
DevCon.WriteLn(Color_Gray, L"%-32s @ %08p -> %08p [%umb]", WX_STR(m_name), DevCon.WriteLn(Color_Gray, L"%-32s @ %08p -> %08p [%umb]", WX_STR(m_name),
m_baseptr, (uptr)m_baseptr + toReserveBytes, toReserveBytes / _1mb); 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) if (m_pages_commited > newsize)
return false; return false;

View File

@ -39,9 +39,12 @@ long __stdcall SysPageFaultExceptionFilter(EXCEPTION_POINTERS *eps)
// exception. // exception.
// TODO: find a reliable way to debug the filter itself, I've come up with a few ways that // 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. // work but I don't fully understand why some do and some don't.
__try { __try
{
return DoSysPageFaultExceptionFilter(eps); 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; 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 // 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 // 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; winmode = mode.CanWrite() ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ;
} else if (mode.CanRead()) { }
else if (mode.CanRead())
{
winmode = mode.CanWrite() ? PAGE_READWRITE : PAGE_READONLY; winmode = mode.CanWrite() ? PAGE_READWRITE : PAGE_READONLY;
} }
@ -83,10 +89,13 @@ bool HostSys::MmapCommitPtr(void *base, size_t size, const PageProtectionMode &m
return true; return true;
const DWORD errcode = GetLastError(); 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); 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... 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()); pxFailDev(L"VirtualAlloc COMMIT failed: " + Exception::WinApiError().GetMsgFromWindows());
return false; return false;
} }
@ -140,7 +149,8 @@ void HostSys::MemProtect(void *baseaddr, size_t size, const PageProtectionMode &
__pagesize, __pagesize, size, size)); __pagesize, __pagesize, size, size));
DWORD OldProtect; // enjoy my uselessness, yo! DWORD OldProtect; // enjoy my uselessness, yo!
if (!VirtualProtect(baseaddr, size, ConvertToWinApi(mode), &OldProtect)) { if (!VirtualProtect(baseaddr, size, ConvertToWinApi(mode), &OldProtect))
{
Exception::WinApiError apiError; Exception::WinApiError apiError;
apiError.SetDiagMsg( apiError.SetDiagMsg(

View File

@ -126,9 +126,12 @@ void Threading::SetNameOfCurrentThread(const char *name)
info.dwThreadID = GetCurrentThreadId(); info.dwThreadID = GetCurrentThreadId();
info.dwFlags = 0; info.dwFlags = 0;
__try { __try
{
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
} __except (EXCEPTION_EXECUTE_HANDLER) { }
__except (EXCEPTION_EXECUTE_HANDLER)
{
} }
#endif #endif
} }

View File

@ -55,7 +55,8 @@ SingleCoreAffinity::SingleCoreAffinity()
s_threadId = GetCurrentThread(); s_threadId = GetCurrentThread();
s_oldmask = SetThreadAffinityMask(s_threadId, affinityMask); 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); const int hexWidth = 2 * sizeof(DWORD_PTR);
Console.Warning( Console.Warning(
"CpuDetect: SetThreadAffinityMask failed...\n" "CpuDetect: SetThreadAffinityMask failed...\n"

View File

@ -32,4 +32,4 @@ void xImplBMI_RVM::operator()(const xRegisterInt &to, const xRegisterInt &from1,
{ {
xOpWriteC4(Prefix, MbPrefix, Opcode, to, from1, from2); xOpWriteC4(Prefix, MbPrefix, Opcode, to, from1, from2);
} }
} } // namespace x86Emitter

View File

@ -77,7 +77,8 @@ void x86capabilities::SIMD_EstablishMXCSRmask()
MXCSR_Mask.bitmask = 0xFFBF; // MMX/SSE default MXCSR_Mask.bitmask = 0xFFBF; // MMX/SSE default
if (hasStreamingSIMD2Extensions) { if (hasStreamingSIMD2Extensions)
{
// This is generally safe assumption, but FXSAVE is the "correct" way to // 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 // detect MXCSR masking features of the cpu, so we use it's result below
// and override this. // and override this.
@ -113,12 +114,14 @@ s64 x86capabilities::_CPUSpeedHz(u64 time) const
// Align the cpu execution to a cpuTick boundary. // Align the cpu execution to a cpuTick boundary.
do { do
{
timeStart = GetCPUTicks(); timeStart = GetCPUTicks();
startCycle = __rdtsc(); startCycle = __rdtsc();
} while (GetCPUTicks() == timeStart); } while (GetCPUTicks() == timeStart);
do { do
{
timeStop = GetCPUTicks(); timeStop = GetCPUTicks();
endCycle = __rdtsc(); endCycle = __rdtsc();
} while ((timeStop - timeStart) < time); } while ((timeStop - timeStart) < time);
@ -139,7 +142,8 @@ s64 x86capabilities::_CPUSpeedHz(u64 time) const
wxString x86capabilities::GetTypeName() const wxString x86capabilities::GetTypeName() const
{ {
switch (TypeID) { switch (TypeID)
{
case 0: case 0:
return L"Standard OEM"; return L"Standard OEM";
case 1: case 1:
@ -165,7 +169,8 @@ void x86capabilities::CountCores()
// detect multicore for AMD cpu // 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 // 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. // 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 // (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). // and threads used by the CPU (AMD and Intel can't agree on how to make this info available).
int vid; int vid;
for (vid = 0; vid < x86Vendor_Unknown; ++vid) { for (vid = 0; vid < x86Vendor_Unknown; ++vid)
{
if (memcmp(VendorName, tbl_x86vendors[vid], 12) == 0) if (memcmp(VendorName, tbl_x86vendors[vid], 12) == 0)
break; break;
} }
VendorID = static_cast<x86VendorType>(vid); VendorID = static_cast<x86VendorType>(vid);
if (cmds >= 0x00000001) { if (cmds >= 0x00000001)
{
cpuid(regs, 0x00000001); cpuid(regs, 0x00000001);
StepID = regs[0] & 0xf; StepID = regs[0] & 0xf;
@ -229,7 +236,8 @@ void x86capabilities::Identify()
Flags2 = regs[2]; Flags2 = regs[2];
} }
if (cmds >= 0x00000007) { if (cmds >= 0x00000007)
{
// Note: ECX must be 0 for AVX2 detection. // Note: ECX must be 0 for AVX2 detection.
cpuidex(regs, 0x00000007, 0); cpuidex(regs, 0x00000007, 0);
@ -238,7 +246,8 @@ void x86capabilities::Identify()
cpuid(regs, 0x80000000); cpuid(regs, 0x80000000);
cmds = regs[0]; cmds = regs[0];
if (cmds >= 0x80000001) { if (cmds >= 0x80000001)
{
cpuid(regs, 0x80000001); cpuid(regs, 0x80000001);
#ifdef __M_X86_64 #ifdef __M_X86_64

View File

@ -43,11 +43,14 @@ namespace x86Emitter
// with one of the other overloads). // with one of the other overloads).
static void _g1_IndirectImm(G1Type InstType, const xIndirect64orLess& sibdest, int imm) static void _g1_IndirectImm(G1Type InstType, const xIndirect64orLess& sibdest, int imm)
{ {
if (sibdest.Is8BitOp()) { if (sibdest.Is8BitOp())
{
xOpWrite(sibdest.GetPrefix16(), 0x80, InstType, sibdest); xOpWrite(sibdest.GetPrefix16(), 0x80, InstType, sibdest);
xWrite<s8>(imm); xWrite<s8>(imm);
} else { }
else
{
u8 opcode = is_s8(imm) ? 0x83 : 0x81; u8 opcode = is_s8(imm) ? 0x83 : 0x81;
xOpWrite(sibdest.GetPrefix16(), opcode, InstType, sibdest, is_s8(imm) ? 1 : sibdest.GetImmSize()); 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) 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); xOpWrite(to.GetPrefix16(), 0x83, InstType, to);
xWrite<s8>(imm); xWrite<s8>(imm);
} else { }
if (to.IsAccumulator()) { else
{
if (to.IsAccumulator())
{
u8 opcode = (to.Is8BitOp() ? 4 : 5) | (InstType << 3); u8 opcode = (to.Is8BitOp() ? 4 : 5) | (InstType << 3);
xOpAccWrite(to.GetPrefix16(), opcode, InstType, to); xOpAccWrite(to.GetPrefix16(), opcode, InstType, to);
} else { }
else
{
u8 opcode = to.Is8BitOp() ? 0x80 : 0x81; u8 opcode = to.Is8BitOp() ? 0x80 : 0x81;
xOpWrite(to.GetPrefix16(), opcode, InstType, to); xOpWrite(to.GetPrefix16(), opcode, InstType, to);
} }
@ -132,10 +141,13 @@ void xImpl_Group2::operator()(const xRegisterInt &to, u8 imm) const
if (imm == 0) if (imm == 0)
return; return;
if (imm == 1) { if (imm == 1)
{
// special encoding of 1's // special encoding of 1's
xOpWrite(to.GetPrefix16(), to.Is8BitOp() ? 0xd0 : 0xd1, InstType, to); xOpWrite(to.GetPrefix16(), to.Is8BitOp() ? 0xd0 : 0xd1, InstType, to);
} else { }
else
{
xOpWrite(to.GetPrefix16(), to.Is8BitOp() ? 0xc0 : 0xc1, InstType, to); xOpWrite(to.GetPrefix16(), to.Is8BitOp() ? 0xc0 : 0xc1, InstType, to);
xWrite8(imm); xWrite8(imm);
} }
@ -151,10 +163,13 @@ void xImpl_Group2::operator()(const xIndirect64orLess &sibdest, u8 imm) const
if (imm == 0) if (imm == 0)
return; return;
if (imm == 1) { if (imm == 1)
{
// special encoding of 1's // special encoding of 1's
xOpWrite(sibdest.GetPrefix16(), sibdest.Is8BitOp() ? 0xd0 : 0xd1, InstType, sibdest); xOpWrite(sibdest.GetPrefix16(), sibdest.Is8BitOp() ? 0xd0 : 0xd1, InstType, sibdest);
} else { }
else
{
xOpWrite(sibdest.GetPrefix16(), sibdest.Is8BitOp() ? 0xc0 : 0xc1, InstType, sibdest, 1); xOpWrite(sibdest.GetPrefix16(), sibdest.Is8BitOp() ? 0xc0 : 0xc1, InstType, sibdest, 1);
xWrite8(imm); xWrite8(imm);
} }

View File

@ -58,4 +58,4 @@ struct xImplBMI_RVM
void operator()( const xRegisterInt& to, const xIndirectVoid& from, u8 imm) const; void operator()( const xRegisterInt& to, const xIndirectVoid& from, u8 imm) const;
#endif #endif
}; };
} } // namespace x86Emitter

View File

@ -18,7 +18,8 @@
namespace x86Emitter namespace x86Emitter
{ {
enum G1Type { enum G1Type
{
G1Type_ADD = 0, G1Type_ADD = 0,
G1Type_OR, G1Type_OR,
G1Type_ADC, G1Type_ADC,

View File

@ -18,7 +18,8 @@
namespace x86Emitter namespace x86Emitter
{ {
enum G2Type { enum G2Type
{
G2Type_ROL = 0, G2Type_ROL = 0,
G2Type_ROR, G2Type_ROR,
G2Type_RCL, G2Type_RCL,

View File

@ -18,7 +18,8 @@
namespace x86Emitter namespace x86Emitter
{ {
enum G3Type { enum G3Type
{
G3Type_NOT = 2, G3Type_NOT = 2,
G3Type_NEG = 3, G3Type_NEG = 3,
G3Type_MUL = 4, G3Type_MUL = 4,
@ -105,4 +106,4 @@ struct xImpl_iMul
const xImplSimd_DestRegSSE SS; const xImplSimd_DestRegSSE SS;
const xImplSimd_DestRegSSE SD; const xImplSimd_DestRegSSE SD;
}; };
} } // namespace x86Emitter

View File

@ -36,7 +36,8 @@ struct xImpl_JmpCall
{ {
if (isJmp) if (isJmp)
xJccKnownTarget(Jcc_Unconditional, (void*)(uptr)func, false); // double cast to/from (uptr) needed to appease GCC 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 // 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). // always 5 bytes (16 bit calls are bad mojo, so no bother to do special logic).

View File

@ -170,4 +170,4 @@ struct xImplSimd_PMove
void DQ(const xRegisterSSE& to, const xRegisterSSE& from) const; void DQ(const xRegisterSSE& to, const xRegisterSSE& from) const;
void DQ(const xRegisterSSE& to, const xIndirect64& from) const; void DQ(const xRegisterSSE& to, const xIndirect64& from) const;
}; };
} } // namespace x86Emitter

View File

@ -238,4 +238,4 @@ struct SimdImpl_PExtract
// used to extract any single packed dword value from src into an x86 32 bit register. // used to extract any single packed dword value from src into an x86 32 bit register.
const xImplSimd_InsertExtractHelper D; const xImplSimd_InsertExtractHelper D;
}; };
} } // namespace x86Emitter

View File

@ -31,7 +31,8 @@ struct xImpl_Test
void operator()(const xRegisterInt& to, int imm) const; void operator()(const xRegisterInt& to, int imm) const;
}; };
enum G8Type { enum G8Type
{
G8Type_BT = 4, G8Type_BT = 4,
G8Type_BTS, G8Type_BTS,
G8Type_BTR, G8Type_BTR,

View File

@ -199,6 +199,7 @@ public:
class xScopedSavedRegisters class xScopedSavedRegisters
{ {
std::vector<std::reference_wrapper<const xAddressReg>> regs; std::vector<std::reference_wrapper<const xAddressReg>> regs;
public: public:
xScopedSavedRegisters(std::initializer_list<std::reference_wrapper<const xAddressReg>> regs); xScopedSavedRegisters(std::initializer_list<std::reference_wrapper<const xAddressReg>> regs);
~xScopedSavedRegisters(); ~xScopedSavedRegisters();
@ -599,4 +600,4 @@ extern const xImplSimd_Unpack xUNPCK;
extern const SimdImpl_Pack xPACK; extern const SimdImpl_Pack xPACK;
extern const xImplSimd_PInsert xPINSR; extern const xImplSimd_PInsert xPINSR;
extern const SimdImpl_PExtract xPEXTR; extern const SimdImpl_PExtract xPEXTR;
} } // namespace x86Emitter

View File

@ -137,7 +137,8 @@ __emitinline void xOpWriteC5(u8 prefix, u8 opcode, const T1 &param1, const T2 &p
u8 p = u8 p =
prefix == 0xF2 ? 3 : prefix == 0xF2 ? 3 :
prefix == 0xF3 ? 2 : prefix == 0xF3 ? 2 :
prefix == 0x66 ? 1 : 0; prefix == 0x66 ? 1 :
0;
xWrite8(0xC5); xWrite8(0xC5);
xWrite8(nR | nv | L | p); xWrite8(nR | nv | L | p);
@ -172,11 +173,13 @@ __emitinline void xOpWriteC4(u8 prefix, u8 mb_prefix, u8 opcode, const T1 &param
u8 p = u8 p =
prefix == 0xF2 ? 3 : prefix == 0xF2 ? 3 :
prefix == 0xF3 ? 2 : prefix == 0xF3 ? 2 :
prefix == 0x66 ? 1 : 0; prefix == 0x66 ? 1 :
0;
u8 m = u8 m =
mb_prefix == 0x3A ? 3 : mb_prefix == 0x3A ? 3 :
mb_prefix == 0x38 ? 2 : 1; mb_prefix == 0x38 ? 2 :
1;
xWrite8(0xC4); xWrite8(0xC4);
xWrite8(nR | nX | nB | m); xWrite8(nR | nX | nB | m);
@ -184,4 +187,4 @@ __emitinline void xOpWriteC4(u8 prefix, u8 mb_prefix, u8 opcode, const T1 &param
xWrite8(opcode); xWrite8(opcode);
EmitSibMagic(param1, param3); EmitSibMagic(param1, param3);
} }
} } // namespace x86Emitter

View File

@ -33,11 +33,13 @@
namespace x86Emitter 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 // Jumps are always wide and don't need the rex.W
xOpWrite(0, 0xff, isJmp ? 4 : 2, absreg.GetNonWide()); 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 // Jumps are always wide and don't need the rex.W
EmitRex(0, xIndirect32(src.Base, src.Index, 1, 0)); EmitRex(0, xIndirect32(src.Base, src.Index, 1, 0));
xWrite8(0xff); xWrite8(0xff);
@ -49,78 +51,106 @@ const xImpl_JmpCall xCALL = {false};
template <typename Reg1, typename Reg2> template <typename Reg1, typename Reg2>
void prepareRegsForFastcall(const Reg1 &a1, const Reg2 &a2) { void prepareRegsForFastcall(const Reg1& a1, const Reg2& a2)
if (a1.IsEmpty()) return; {
if (a1.IsEmpty())
return;
// Make sure we don't mess up if someone tries to fastcall with a1 in arg2reg and a2 in arg1reg // 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); xMOV(Reg1(arg1reg), a1);
if (!a2.IsEmpty()) { if (!a2.IsEmpty())
{
xMOV(Reg2(arg2reg), a2); xMOV(Reg2(arg2reg), a2);
} }
} else if (a1.Id != arg2reg.Id) { }
else if (a1.Id != arg2reg.Id)
{
xMOV(Reg2(arg2reg), a2); xMOV(Reg2(arg2reg), a2);
xMOV(Reg1(arg1reg), a1); xMOV(Reg1(arg1reg), a1);
} else { }
else
{
xPUSH(a1); xPUSH(a1);
xMOV(Reg2(arg2reg), a2); xMOV(Reg2(arg2reg), a2);
xPOP(Reg1(arg1reg)); 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); prepareRegsForFastcall(a1, a2);
uptr disp = ((uptr)xGetPtr() + 5) - (uptr)f; uptr disp = ((uptr)xGetPtr() + 5) - (uptr)f;
if ((sptr)disp == (s32)disp) { if ((sptr)disp == (s32)disp)
{
xCALL(f); xCALL(f);
} else { }
else
{
xMOV(rax, ptrNative[f]); xMOV(rax, ptrNative[f]);
xCALL(rax); xCALL(rax);
} }
} }
#ifdef __M_X86_64 #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); prepareRegsForFastcall(a1, a2);
uptr disp = ((uptr)xGetPtr() + 5) - (uptr)f; uptr disp = ((uptr)xGetPtr() + 5) - (uptr)f;
if ((sptr)disp == (s32)disp) { if ((sptr)disp == (s32)disp)
{
xCALL(f); xCALL(f);
} else { }
else
{
xMOV(rax, ptrNative[f]); xMOV(rax, ptrNative[f]);
xCALL(rax); xCALL(rax);
} }
} }
void xImpl_FastCall::operator()(void *f, u32 a1, const xRegisterLong &a2) const { void xImpl_FastCall::operator()(void* f, u32 a1, const xRegisterLong& a2) const
if (!a2.IsEmpty()) { xMOV(arg2reg, a2); } {
if (!a2.IsEmpty())
{
xMOV(arg2reg, a2);
}
xMOV(arg1reg, a1); xMOV(arg1reg, a1);
(*this)(f, arg1reg, arg2reg); (*this)(f, arg1reg, arg2reg);
} }
#endif #endif
void xImpl_FastCall::operator()(void *f, void *a1) const { void xImpl_FastCall::operator()(void* f, void* a1) const
{
xLEA(arg1reg, ptr[a1]); xLEA(arg1reg, ptr[a1]);
(*this)(f, arg1reg, arg2reg); (*this)(f, arg1reg, arg2reg);
} }
void xImpl_FastCall::operator()(void *f, u32 a1, const xRegister32 &a2) const { void xImpl_FastCall::operator()(void* f, u32 a1, const xRegister32& a2) const
if (!a2.IsEmpty()) { xMOV(arg2regd, a2); } {
if (!a2.IsEmpty())
{
xMOV(arg2regd, a2);
}
xMOV(arg1regd, a1); xMOV(arg1regd, a1);
(*this)(f, arg1regd, arg2regd); (*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); xMOV(arg1regd, a1);
(*this)(f, arg1regd); (*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(arg1regd, a1);
xMOV(arg2regd, a2); xMOV(arg2regd, a2);
(*this)(f, arg1regd, arg2regd); (*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); prepareRegsForFastcall(a1, a2);
xCALL(f); xCALL(f);
} }
@ -135,7 +165,8 @@ __emitinline s32 *xJcc32(JccComparisonType comparison, s32 displacement)
{ {
if (comparison == Jcc_Unconditional) if (comparison == Jcc_Unconditional)
xWrite8(0xe9); xWrite8(0xe9);
else { else
{
xWrite8(0x0f); xWrite8(0x0f);
xWrite8(0x80 | comparison); 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; const int slideVal = slideForward ? ((comparison == Jcc_Unconditional) ? 3 : 4) : 0;
displacement8 -= slideVal; displacement8 -= slideVal;
if (slideForward) { if (slideForward)
{
pxAssertDev(displacement8 >= 0, "Used slideForward on a backward jump; nothing to slide!"); pxAssertDev(displacement8 >= 0, "Used slideForward on a backward jump; nothing to slide!");
} }
if (is_s8(displacement8)) if (is_s8(displacement8))
xJcc8(comparison, displacement8); xJcc8(comparison, displacement8);
else { else
{
// Perform a 32 bit jump instead. :( // Perform a 32 bit jump instead. :(
s32* bah = xJcc32(comparison); s32* bah = xJcc32(comparison);
sptr distance = (sptr)target - (sptr)xGetPtr(); sptr distance = (sptr)target - (sptr)xGetPtr();
@ -208,10 +241,12 @@ xForwardJumpBase::xForwardJumpBase(uint opsize, JccComparisonType cctype)
if (opsize == 1) if (opsize == 1)
xWrite8((cctype == Jcc_Unconditional) ? 0xeb : (0x70 | cctype)); xWrite8((cctype == Jcc_Unconditional) ? 0xeb : (0x70 | cctype));
else { else
{
if (cctype == Jcc_Unconditional) if (cctype == Jcc_Unconditional)
xWrite8(0xe9); xWrite8(0xe9);
else { else
{
xWrite8(0x0f); xWrite8(0x0f);
xWrite8(0x80 | cctype); xWrite8(0x80 | cctype);
} }
@ -225,10 +260,13 @@ void xForwardJumpBase::_setTarget(uint opsize) const
pxAssertDev(BasePtr != NULL, ""); pxAssertDev(BasePtr != NULL, "");
sptr displacement = (sptr)xGetPtr() - (sptr)BasePtr; sptr displacement = (sptr)xGetPtr() - (sptr)BasePtr;
if (opsize == 1) { if (opsize == 1)
{
pxAssertDev(is_s8(displacement), "Emitter Error: Invalid short jump displacement."); pxAssertDev(is_s8(displacement), "Emitter Error: Invalid short jump displacement.");
BasePtr[-1] = (s8)displacement; BasePtr[-1] = (s8)displacement;
} else { }
else
{
// full displacement, no sanity checks needed :D // full displacement, no sanity checks needed :D
((s32*)BasePtr)[-1] = displacement; ((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: // x86 conditionals are clever! To invert conditional types, just invert the lower bit:
return (JccComparisonType)((int)src ^ 1); return (JccComparisonType)((int)src ^ 1);
} }
} } // namespace x86Emitter

View File

@ -96,7 +96,8 @@ void x86SetJ8(u8 *j8)
{ {
u32 jump = (x86Ptr - j8) - 1; u32 jump = (x86Ptr - j8) - 1;
if (jump > 0x7f) { if (jump > 0x7f)
{
Console.Error("j8 greater than 0x7f!!"); Console.Error("j8 greater than 0x7f!!");
assert(0); assert(0);
} }
@ -107,16 +108,19 @@ void x86SetJ8A(u8 *j8)
{ {
u32 jump = (x86Ptr - j8) - 1; u32 jump = (x86Ptr - j8) - 1;
if (jump > 0x7f) { if (jump > 0x7f)
{
Console.Error("j8 greater than 0x7f!!"); Console.Error("j8 greater than 0x7f!!");
assert(0); assert(0);
} }
if (((uptr)x86Ptr & 0xf) > 4) { if (((uptr)x86Ptr & 0xf) > 4)
{
uptr newjump = jump + 16 - ((uptr)x86Ptr & 0xf); uptr newjump = jump + 16 - ((uptr)x86Ptr & 0xf);
if (newjump <= 0x7f) { if (newjump <= 0x7f)
{
jump = newjump; jump = newjump;
while ((uptr)x86Ptr & 0xf) while ((uptr)x86Ptr & 0xf)
*x86Ptr++ = 0x90; *x86Ptr++ = 0x90;

View File

@ -57,10 +57,12 @@ void xImpl_Mov::operator()(const xIndirectVoid &dest, const xRegisterInt &from)
#ifndef __M_X86_64 #ifndef __M_X86_64
// Note: On x86-64 this is an immediate 64-bit address, which is larger than the equivalent rip offset instr // 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); xOpAccWrite(from.GetPrefix16(), from.Is8BitOp() ? 0xa2 : 0xa3, from, dest);
xWrite32(dest.Displacement); xWrite32(dest.Displacement);
} else }
else
#endif #endif
{ {
xOpWrite(from.GetPrefix16(), from.Is8BitOp() ? 0x88 : 0x89, from, dest); 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 #ifndef __M_X86_64
// Note: On x86-64 this is an immediate 64-bit address, which is larger than the equivalent rip offset instr // 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); xOpAccWrite(to.GetPrefix16(), to.Is8BitOp() ? 0xa0 : 0xa1, to, src);
xWrite32(src.Displacement); xWrite32(src.Displacement);
} else }
else
#endif #endif
{ {
xOpWrite(to.GetPrefix16(), to.Is8BitOp() ? 0x8a : 0x8b, to, src); 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 void xImpl_Mov::operator()(const xIndirect64orLess& dest, sptr imm) const
{ {
switch (dest.GetOperandSize()) { switch (dest.GetOperandSize())
{
case 1: case 1:
pxAssertMsg(imm == (s8)imm || imm == (u8)imm, "Immediate won't fit!"); pxAssertMsg(imm == (s8)imm || imm == (u8)imm, "Immediate won't fit!");
break; break;
@ -110,7 +115,8 @@ void xImpl_Mov::operator()(const xIndirect64orLess &dest, sptr imm) const
// the flags (namely replacing mov reg,0 with xor). // the flags (namely replacing mov reg,0 with xor).
void xImpl_Mov::operator()(const xRegisterInt& to, sptr imm, bool preserve_flags) const void xImpl_Mov::operator()(const xRegisterInt& to, sptr imm, bool preserve_flags) const
{ {
switch (to.GetOperandSize()) { switch (to.GetOperandSize())
{
case 1: case 1:
pxAssertMsg(imm == (s8)imm || imm == (u8)imm, "Immediate won't fit!"); pxAssertMsg(imm == (s8)imm || imm == (u8)imm, "Immediate won't fit!");
break; break;
@ -127,14 +133,19 @@ void xImpl_Mov::operator()(const xRegisterInt &to, sptr imm, bool preserve_flags
pxAssertMsg(0, "Bad indirect size!"); pxAssertMsg(0, "Bad indirect size!");
} }
const xRegisterInt& to_ = to.GetNonWide(); const xRegisterInt& to_ = to.GetNonWide();
if (!preserve_flags && (imm == 0)) { if (!preserve_flags && (imm == 0))
{
_g1_EmitOp(G1Type_XOR, to_, to_); _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. // Note: MOV does not have (reg16/32,imm8) forms.
u8 opcode = (to_.Is8BitOp() ? 0xb0 : 0xb8) | to_.Id; u8 opcode = (to_.Is8BitOp() ? 0xb0 : 0xb8) | to_.Id;
xOpAccWrite(to_.GetPrefix16(), opcode, 0, to_); xOpAccWrite(to_.GetPrefix16(), opcode, 0, to_);
to_.xWriteImm(imm); to_.xWriteImm(imm);
} else { }
else
{
xOpWrite(to.GetPrefix16(), 0xc7, 0, to); xOpWrite(to.GetPrefix16(), 0xc7, 0, to);
to.xWriteImm(imm); to.xWriteImm(imm);
} }
@ -145,9 +156,12 @@ const xImpl_Mov xMOV;
#ifdef __M_X86_64 #ifdef __M_X86_64
void xImpl_MovImm64::operator()(const xRegister64& to, s64 imm, bool preserve_flags) const 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); xMOV(to, imm, preserve_flags);
} else { }
else
{
u8 opcode = 0xb8 | to.Id; u8 opcode = 0xb8 | to.Id;
xOpAccWrite(to.GetPrefix16(), opcode, 0, to); xOpAccWrite(to.GetPrefix16(), opcode, 0, to);
xWrite64(imm); xWrite64(imm);

View File

@ -23,7 +23,8 @@ SSE_MXCSR MXCSR_Mask;
const wxChar* EnumToString(SSE_RoundMode sse) const wxChar* EnumToString(SSE_RoundMode sse)
{ {
switch (sse) { switch (sse)
{
case SSEround_Nearest: case SSEround_Nearest:
return L"Nearest"; return L"Nearest";
case SSEround_NegInf: case SSEround_NegInf:
@ -104,18 +105,24 @@ __emitinline void SimdPrefix(u8 prefix, u16 opcode)
if (!is16BitOpcode) if (!is16BitOpcode)
pxAssert((opcode >> 8) == 0); pxAssert((opcode >> 8) == 0);
if (prefix != 0) { if (prefix != 0)
{
if (is16BitOpcode) if (is16BitOpcode)
xWrite32((opcode << 16) | 0x0f00 | prefix); xWrite32((opcode << 16) | 0x0f00 | prefix);
else { else
{
xWrite16(0x0f00 | prefix); xWrite16(0x0f00 | prefix);
xWrite8(opcode); xWrite8(opcode);
} }
} else { }
if (is16BitOpcode) { else
{
if (is16BitOpcode)
{
xWrite8(0x0f); xWrite8(0x0f);
xWrite16(opcode); xWrite16(opcode);
} else }
else
xWrite16((opcode << 8) | 0x0f); xWrite16((opcode << 8) | 0x0f);
} }
} }
@ -797,4 +804,4 @@ __emitinline void xFXRSTOR(const xIndirectVoid &src)
{ {
xOpWrite0F(0, 0xae, 1, src); xOpWrite0F(0, 0xae, 1, src);
} }
} } // namespace x86Emitter

View File

@ -17,7 +17,8 @@
#include "common/Dependencies.h" #include "common/Dependencies.h"
enum x86VendorType { enum x86VendorType
{
x86Vendor_Intel = 0, x86Vendor_Intel = 0,
x86Vendor_AMD = 1, x86Vendor_AMD = 1,
x86Vendor_Unknown = 2 x86Vendor_Unknown = 2
@ -124,7 +125,8 @@ protected:
void CountLogicalCores(); void CountLogicalCores();
}; };
enum SSE_RoundMode { enum SSE_RoundMode
{
SSE_RoundMode_FIRST = 0, SSE_RoundMode_FIRST = 0,
SSEround_Nearest = 0, SSEround_Nearest = 0,
SSEround_NegInf, SSEround_NegInf,
@ -136,10 +138,12 @@ enum SSE_RoundMode {
ImplementEnumOperators(SSE_RoundMode); ImplementEnumOperators(SSE_RoundMode);
// Predeclaration for xIndirect32 // Predeclaration for xIndirect32
namespace x86Emitter { namespace x86Emitter
template <typename T> class xIndirect; {
template <typename T>
class xIndirect;
typedef xIndirect<u32> xIndirect32; typedef xIndirect<u32> xIndirect32;
} } // namespace x86Emitter
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// SSE_MXCSR - Control/Status Register (bitfield) // SSE_MXCSR - Control/Status Register (bitfield)

View File

@ -195,21 +195,24 @@ const char *const x86_regnames_gpr8[] =
"al", "cl", "dl", "bl", "al", "cl", "dl", "bl",
"ah", "ch", "dh", "bh", "ah", "ch", "dh", "bh",
"b8", "b9", "b10", "b11", "b8", "b9", "b10", "b11",
"b12", "b13", "b14", "b15"}; "b12", "b13", "b14", "b15"
};
const char* const x86_regnames_gpr16[] = const char* const x86_regnames_gpr16[] =
{ {
"ax", "cx", "dx", "bx", "ax", "cx", "dx", "bx",
"sp", "bp", "si", "di", "sp", "bp", "si", "di",
"h8", "h9", "h10", "h11", "h8", "h9", "h10", "h11",
"h12", "h13", "h14", "h15"}; "h12", "h13", "h14", "h15"
};
const char* const x86_regnames_gpr32[] = const char* const x86_regnames_gpr32[] =
{ {
"eax", "ecx", "edx", "ebx", "eax", "ecx", "edx", "ebx",
"esp", "ebp", "esi", "edi", "esp", "ebp", "esi", "edi",
"e8", "e9", "e10", "e11", "e8", "e9", "e10", "e11",
"e12", "e13", "e14", "e15"}; "e12", "e13", "e14", "e15"
};
#ifdef __M_X86_64 #ifdef __M_X86_64
const char* const x86_regnames_gpr64[] = const char* const x86_regnames_gpr64[] =
@ -217,7 +220,8 @@ const char *const x86_regnames_gpr64[] =
"rax", "rcx", "rdx", "rbx", "rax", "rcx", "rdx", "rbx",
"rsp", "rbp", "rsi", "rdi", "rsp", "rbp", "rsi", "rdi",
"r8", "r9", "r10", "r11", "r8", "r9", "r10", "r11",
"r12", "r13", "r14", "r15"}; "r12", "r13", "r14", "r15"
};
#endif #endif
const char* const x86_regnames_sse[] = const char* const x86_regnames_sse[] =
@ -225,7 +229,8 @@ const char *const x86_regnames_sse[] =
"xmm0", "xmm1", "xmm2", "xmm3", "xmm0", "xmm1", "xmm2", "xmm3",
"xmm4", "xmm5", "xmm6", "xmm7", "xmm4", "xmm5", "xmm6", "xmm7",
"xmm8", "xmm9", "xmm10", "xmm11", "xmm8", "xmm9", "xmm10", "xmm11",
"xmm12", "xmm13", "xmm14", "xmm15"}; "xmm12", "xmm13", "xmm14", "xmm15"
};
const char* xRegisterBase::GetName() const char* xRegisterBase::GetName()
{ {
@ -239,7 +244,8 @@ const char *xRegisterBase::GetName()
if (Id >= (int)iREGCNT_GPR || Id < 0) if (Id >= (int)iREGCNT_GPR || Id < 0)
return "!Register index out of range!"; return "!Register index out of range!";
switch (GetOperandSize()) { switch (GetOperandSize())
{
case 1: case 1:
return x86_regnames_gpr8[Id]; return x86_regnames_gpr8[Id];
case 2: case 2:
@ -299,10 +305,13 @@ void EmitSibMagic(uint regfield, const void *address, int extraRIPOffset)
#else #else
sptr ripRelative = (sptr)address - ((sptr)x86Ptr + sizeof(s8) + sizeof(s32) + extraRIPOffset); 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) // 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); ModRM(0, regfield, ModRm_UseDisp32);
displacement = ripRelative; displacement = ripRelative;
} else { }
else
{
pxAssertDev(displacement == (s32)displacement, "SIB target is too far away, needs an indirect register"); pxAssertDev(displacement == (s32)displacement, "SIB target is too far away, needs an indirect register");
ModRM(0, regfield, ModRm_UseSib); ModRM(0, regfield, ModRm_UseSib);
SibSB(0, Sib_EIZ, Sib_UseDisp32); 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 // Displacement is only 64 bits for rip-relative addressing
pxAssert(info.Displacement == (s32)info.Displacement || (info.Base.IsEmpty() && info.Index.IsEmpty())); 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 // 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, // 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 // 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). // 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); EmitSibMagic(regfield, (void*)info.Displacement, extraRIPOffset);
return; return;
} else { }
else
{
if (info.Index == rbp && displacement_size == 0) if (info.Index == rbp && displacement_size == 0)
displacement_size = 1; // forces [ebp] to be encoded as [ebp+0]! displacement_size = 1; // forces [ebp] to be encoded as [ebp+0]!
ModRM(displacement_size, regfield, info.Index.Id & 7); ModRM(displacement_size, regfield, info.Index.Id & 7);
} }
} else { }
else
{
// In order to encode "just" index*scale (and no base), we have to encode // 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 // it as a special [index*scale + displacement] form, which is done by
// specifying EBP as the base register and setting the displacement field // specifying EBP as the base register and setting the displacement field
// to zero. (same as ModRm w/o SIB form above, basically, except the // 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). // 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); ModRM(0, regfield, ModRm_UseSib);
SibSB(info.Scale, info.Index.Id, Sib_UseDisp32); SibSB(info.Scale, info.Index.Id, Sib_UseDisp32);
xWrite<s32>(info.Displacement); xWrite<s32>(info.Displacement);
return; return;
} else { }
else
{
if (info.Base == rbp && displacement_size == 0) if (info.Base == rbp && displacement_size == 0)
displacement_size = 1; // forces [ebp] to be encoded as [ebp+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) if (displacement_size == 1)
xWrite<s8>(info.Displacement); xWrite<s8>(info.Displacement);
else else
@ -444,7 +463,8 @@ void EmitRex(uint regfield, const xIndirectVoid &info)
bool r = false; bool r = false;
bool x = info.Index.IsExtended(); bool x = info.Index.IsExtended();
bool b = info.Base.IsExtended(); bool b = info.Base.IsExtended();
if (!NeedsSibMagic(info)) { if (!NeedsSibMagic(info))
{
b = x; b = x;
x = false; x = false;
} }
@ -485,7 +505,8 @@ void EmitRex(const xRegisterBase &reg1, const xIndirectVoid &sib)
bool r = reg1.IsExtended(); bool r = reg1.IsExtended();
bool x = sib.Index.IsExtended(); bool x = sib.Index.IsExtended();
bool b = sib.Base.IsExtended(); bool b = sib.Base.IsExtended();
if (!NeedsSibMagic(sib)) { if (!NeedsSibMagic(sib))
{
b = x; b = x;
x = false; x = false;
} }
@ -508,7 +529,8 @@ void EmitRexImplicitlyWide(const xIndirectVoid &sib)
bool r = false; bool r = false;
bool x = sib.Index.IsExtended(); bool x = sib.Index.IsExtended();
bool b = sib.Base.IsExtended(); bool b = sib.Base.IsExtended();
if (!NeedsSibMagic(sib)) { if (!NeedsSibMagic(sib))
{
b = x; b = x;
x = false; x = false;
} }
@ -551,7 +573,8 @@ __emitinline void xAlignCallTarget()
// Core2/i7 CPUs prefer unaligned addresses. Checking for SSSE3 is a decent filter. // Core2/i7 CPUs prefer unaligned addresses. Checking for SSSE3 is a decent filter.
// (also align in debug modes for disasm convenience) // (also align in debug modes for disasm convenience)
if (IsDebugBuild || !x86caps.hasSupplementalStreamingSIMD3Extensions) { if (IsDebugBuild || !x86caps.hasSupplementalStreamingSIMD3Extensions)
{
// - P4's and earlier prefer 16 byte alignment. // - P4's and earlier prefer 16 byte alignment.
// - AMD Athlons and Phenoms prefer 8 byte alignment, but I don't have an easy // - AMD Athlons and Phenoms prefer 8 byte alignment, but I don't have an easy
// heuristic for it yet. // heuristic for it yet.
@ -569,11 +592,13 @@ __emitinline u8 *xGetAlignedCallTarget()
__emitinline void xAdvancePtr(uint bytes) __emitinline void xAdvancePtr(uint bytes)
{ {
if (IsDevBuild) { if (IsDevBuild)
{
// common debugger courtesy: advance with INT3 as filler. // common debugger courtesy: advance with INT3 as filler.
for (uint i = 0; i < bytes; i++) for (uint i = 0; i < bytes; i++)
xWrite8(0xcc); xWrite8(0xcc);
} else }
else
x86Ptr += bytes; x86Ptr += bytes;
} }
@ -582,9 +607,7 @@ __emitinline void xAdvancePtr(uint bytes)
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
xRegisterInt xRegisterInt::MatchSizeTo(xRegisterInt other) const xRegisterInt xRegisterInt::MatchSizeTo(xRegisterInt other) const
{ {
return other.GetOperandSize() == 1 return other.GetOperandSize() == 1 ? xRegisterInt(xRegister8(*this)) : xRegisterInt(other.GetOperandSize(), Id);
? xRegisterInt(xRegister8(*this))
: xRegisterInt(other.GetOperandSize(), Id);
} }
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
@ -676,20 +699,25 @@ xAddressVoid::xAddressVoid(const void *displacement)
xAddressVoid& xAddressVoid::Add(const xAddressReg& src) xAddressVoid& xAddressVoid::Add(const xAddressReg& src)
{ {
if (src == Index) { if (src == Index)
{
Factor++; Factor++;
} else if (src == Base) { }
else if (src == Base)
{
// Compound the existing register reference into the Index/Scale pair. // Compound the existing register reference into the Index/Scale pair.
Base = xEmptyReg; Base = xEmptyReg;
if (src == Index) if (src == Index)
Factor++; Factor++;
else { else
{
pxAssertDev(Index.IsEmpty(), "x86Emitter: Only one scaled index register is allowed in an address modifier."); pxAssertDev(Index.IsEmpty(), "x86Emitter: Only one scaled index register is allowed in an address modifier.");
Index = src; Index = src;
Factor = 2; Factor = 2;
} }
} else if (Base.IsEmpty()) }
else if (Base.IsEmpty())
Base = src; Base = src;
else if (Index.IsEmpty()) else if (Index.IsEmpty())
Index = src; Index = src;
@ -705,14 +733,20 @@ xAddressVoid &xAddressVoid::Add(const xAddressVoid &src)
Add(src.Displacement); Add(src.Displacement);
// If the factor is 1, we can just treat index like a base register also. // 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); Add(src.Index);
} else if (Index.IsEmpty()) { }
else if (Index.IsEmpty())
{
Index = src.Index; Index = src.Index;
Factor = src.Factor; Factor = src.Factor;
} else if (Index == src.Index) { }
else if (Index == src.Index)
{
Factor += src.Factor; 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! pxAssumeDev(false, L"x86Emitter: address modifiers cannot have more than two index registers."); // oops, only 2 regs allowed per ModRm!
return *this; return *this;
@ -763,7 +797,8 @@ xIndirectVoid::xIndirectVoid(xAddressReg base, xAddressReg index, int scale, spt
// //
void xIndirectVoid::Reduce() void xIndirectVoid::Reduce()
{ {
if (Index.IsStackPointer()) { if (Index.IsStackPointer())
{
// esp cannot be encoded as the index, so move it to the Base, if possible. // 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 // note: intentionally leave index assigned to esp also (generates correct
// encoding later, since ESP cannot be encoded 'alone') // 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 no index reg, then load the base register into the index slot.
if (Index.IsEmpty()) { if (Index.IsEmpty())
{
Index = Base; Index = Base;
Scale = 0; Scale = 0;
if (!Base.IsStackPointer()) // prevent ESP from being encoded 'alone' 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: // The Scale has a series of valid forms, all shown here:
switch (Scale) { switch (Scale)
{
case 0: case 0:
break; break;
case 1: case 1:
@ -854,19 +891,24 @@ static void EmitLeaMagic(const xRegisterInt &to, const xIndirectVoid &src, bool
// See EmitSibMagic for commenting on SIB encoding. // 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. // 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 // offset is encodable as an immediate MOV, and a register is encodable
// as a register MOV. // as a register MOV.
if (src.Index.IsEmpty()) { if (src.Index.IsEmpty())
{
xMOV(to, src.Displacement); xMOV(to, src.Displacement);
return; return;
} }
else if (displacement_size == 0) { else if (displacement_size == 0)
{
_xMovRtoR(to, src.Index.MatchSizeTo(to)); _xMovRtoR(to, src.Index.MatchSizeTo(to));
return; return;
} else if (!preserve_flags) { }
else if (!preserve_flags)
{
// encode as MOV and ADD combo. Make sure to use the immediate on the // 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. // 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); xADD(to, src.Displacement);
return; return;
} }
} else { }
if (src.Base.IsEmpty()) { else
if (!preserve_flags && (displacement_size == 0)) { {
if (src.Base.IsEmpty())
{
if (!preserve_flags && (displacement_size == 0))
{
// Encode [Index*Scale] as a combination of Mov and Shl. // Encode [Index*Scale] as a combination of Mov and Shl.
// This is more efficient because of the bloated LEA format which requires // This is more efficient because of the bloated LEA format which requires
// a 32 bit displacement, and the compact nature of the alternative. // 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); xSHL(to, src.Scale);
return; return;
} }
} else { }
if (src.Scale == 0) { else
if (!preserve_flags) { {
if (src.Index == rsp) { if (src.Scale == 0)
{
if (!preserve_flags)
{
if (src.Index == rsp)
{
// ESP is not encodable as an index (ix86 ignores it), thus: // ESP is not encodable as an index (ix86 ignores it), thus:
_xMovRtoR(to, src.Base.MatchSizeTo(to)); // will do the trick! _xMovRtoR(to, src.Base.MatchSizeTo(to)); // will do the trick!
if (src.Displacement) if (src.Displacement)
xADD(to, src.Displacement); xADD(to, src.Displacement);
return; return;
} else if (src.Displacement == 0) { }
else if (src.Displacement == 0)
{
_xMovRtoR(to, src.Base.MatchSizeTo(to)); _xMovRtoR(to, src.Base.MatchSizeTo(to));
_g1_EmitOp(G1Type_ADD, to, src.Index.MatchSizeTo(to)); _g1_EmitOp(G1Type_ADD, to, src.Index.MatchSizeTo(to));
return; 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 // special case handling of ESP as Index, which is replaceable with
// a single MOV even when preserve_flags is set! :D // 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 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); xOpAccWrite(to.GetPrefix16(), to.Is8BitOp() ? 0xa8 : 0xa9, 0, to);
} else { }
else
{
xOpWrite(to.GetPrefix16(), to.Is8BitOp() ? 0xf6 : 0xf7, 0, to); xOpWrite(to.GetPrefix16(), to.Is8BitOp() ? 0xf6 : 0xf7, 0, to);
} }
to.xWriteImm(imm); to.xWriteImm(imm);
@ -980,10 +1038,13 @@ void xImpl_BitScan::operator()(const xRegister16or32or64 &to, const xIndirectVoi
void xImpl_IncDec::operator()(const xRegisterInt& to) const void xImpl_IncDec::operator()(const xRegisterInt& to) const
{ {
if (to.Is8BitOp()) { if (to.Is8BitOp())
{
u8 regfield = isDec ? 1 : 0; u8 regfield = isDec ? 1 : 0;
xOpWrite(to.GetPrefix16(), 0xfe, regfield, to); xOpWrite(to.GetPrefix16(), 0xfe, regfield, to);
} else { }
else
{
#ifdef __M_X86_64 #ifdef __M_X86_64
xOpWrite(to.GetPrefix16(), 0xff, isDec ? 1 : 0, to); xOpWrite(to.GetPrefix16(), 0xff, isDec ? 1 : 0, to);
#else #else
@ -1055,22 +1116,27 @@ __emitinline void xPUSH(const xIndirectVoid &from)
EmitSibMagic(6, from); EmitSibMagic(6, from);
} }
__fi void xPOP(xRegister32or64 from) { __fi void xPOP(xRegister32or64 from)
{
EmitRexImplicitlyWide(from); EmitRexImplicitlyWide(from);
xWrite8(0x58 | (from->Id & 7)); xWrite8(0x58 | (from->Id & 7));
} }
__fi void xPUSH(u32 imm) __fi void xPUSH(u32 imm)
{ {
if (is_s8(imm)) { if (is_s8(imm))
{
xWrite8(0x6a); xWrite8(0x6a);
xWrite8(imm); xWrite8(imm);
} else { }
else
{
xWrite8(0x68); xWrite8(0x68);
xWrite32(imm); xWrite32(imm);
} }
} }
__fi void xPUSH(xRegister32or64 from) { __fi void xPUSH(xRegister32or64 from)
{
EmitRexImplicitlyWide(from); EmitRexImplicitlyWide(from);
xWrite8(0x50 | (from->Id & 7)); xWrite8(0x50 | (from->Id & 7));
} }
@ -1104,7 +1170,8 @@ __fi void xINT(u8 imm)
{ {
if (imm == 3) if (imm == 3)
xWrite8(0xcc); xWrite8(0xcc);
else { else
{
xWrite8(0xcd); xWrite8(0xcd);
xWrite8(imm); xWrite8(imm);
} }
@ -1151,9 +1218,11 @@ __emitinline void xRestoreReg(const xRegisterSSE &dest)
#endif #endif
static void stackAlign(int offset, bool moveDown) { static void stackAlign(int offset, bool moveDown)
{
int needed = (16 - (offset % 16)) % 16; int needed = (16 - (offset % 16)) % 16;
if (moveDown) { if (moveDown)
{
needed = -needed; needed = -needed;
} }
ALIGN_STACK(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) m_offset += sizeof(void*); // Call stores the return address (4 bytes)
// Note rbp can surely be optimized in 64 bits // Note rbp can surely be optimized in 64 bits
if (m_base_frame) { if (m_base_frame)
{
xPUSH(rbp); xPUSH(rbp);
xMOV(rbp, rsp); xMOV(rbp, rsp);
m_offset += sizeof(void*); m_offset += sizeof(void*);
} else if (m_save_base_pointer) { }
else if (m_save_base_pointer)
{
xPUSH(rbp); xPUSH(rbp);
m_offset += sizeof(void*); m_offset += sizeof(void*);
} }
@ -1233,9 +1305,12 @@ xScopedStackFrame::~xScopedStackFrame()
#endif #endif
// Destroy the frame // Destroy the frame
if (m_base_frame) { if (m_base_frame)
{
xLEAVE(); xLEAVE();
} else if (m_save_base_pointer) { }
else if (m_save_base_pointer)
{
xPOP(rbp); xPOP(rbp);
} }
} }
@ -1251,31 +1326,41 @@ xScopedSavedRegisters::xScopedSavedRegisters(std::initializer_list<std::referenc
stackAlign(regs.size() * wordsize, true); stackAlign(regs.size() * wordsize, true);
} }
xScopedSavedRegisters::~xScopedSavedRegisters() { xScopedSavedRegisters::~xScopedSavedRegisters()
{
stackAlign(regs.size() * wordsize, false); 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; const xAddressReg& regRef = *it;
xPOP(regRef); xPOP(regRef);
} }
} }
xAddressVoid xComplexAddress(const xAddressReg& tmpRegister, void *base, const xAddressVoid& offset) { xAddressVoid xComplexAddress(const xAddressReg& tmpRegister, void* base, const xAddressVoid& offset)
if ((sptr)base == (s32)(sptr)base) { {
if ((sptr)base == (s32)(sptr)base)
{
return offset + base; return offset + base;
} else { }
else
{
xLEA(tmpRegister, ptr[base]); xLEA(tmpRegister, ptr[base]);
return offset + tmpRegister; return offset + tmpRegister;
} }
} }
void xLoadFarAddr(const xAddressReg& dst, void *addr) { void xLoadFarAddr(const xAddressReg& dst, void* addr)
{
#ifdef __M_X86_64 #ifdef __M_X86_64
sptr iaddr = (sptr)addr; sptr iaddr = (sptr)addr;
sptr rip = (sptr)xGetPtr() + 7; // LEA will be 7 bytes sptr rip = (sptr)xGetPtr() + 7; // LEA will be 7 bytes
sptr disp = iaddr - rip; sptr disp = iaddr - rip;
if (disp == (s32)disp) { if (disp == (s32)disp)
{
xLEA(dst, ptr[addr]); xLEA(dst, ptr[addr]);
} else { }
else
{
xMOV64(dst, iaddr); xMOV64(dst, iaddr);
} }
#else #else

View File

@ -26,7 +26,8 @@ static const uint iREGCNT_XMM = 8;
static const uint iREGCNT_GPR = 8; static const uint iREGCNT_GPR = 8;
#endif #endif
enum XMMSSEType { enum XMMSSEType
{
XMMT_INT = 0, // integer (sse2 only) XMMT_INT = 0, // integer (sse2 only)
XMMT_FPS = 1, // floating point XMMT_FPS = 1, // floating point
//XMMT_FPD = 3, // double //XMMT_FPD = 3, // double
@ -127,7 +128,8 @@ static const bool AlwaysUseMovaps = false;
#endif #endif
// ModRM 'mod' field enumeration. Provided mostly for reference: // 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_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_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], 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! // JccComparisonType - enumerated possibilities for inspired code branching!
// //
enum JccComparisonType { enum JccComparisonType
{
Jcc_Unknown = -2, Jcc_Unknown = -2,
Jcc_Unconditional = -1, Jcc_Unconditional = -1,
Jcc_Overflow = 0x0, Jcc_Overflow = 0x0,
@ -168,7 +171,8 @@ enum JccComparisonType {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// SSE2_ComparisonType - enumerated possibilities for SIMD data comparison! // SSE2_ComparisonType - enumerated possibilities for SIMD data comparison!
// //
enum SSE2_ComparisonType { enum SSE2_ComparisonType
{
SSE2_Equal = 0, SSE2_Equal = 0,
SSE2_Less, SSE2_Less,
SSE2_LessOrEqual, SSE2_LessOrEqual,
@ -208,8 +212,10 @@ protected:
: _operandSize(operandSize) : _operandSize(operandSize)
{ {
} }
public: public:
uint GetOperandSize() const { uint GetOperandSize() const
{
pxAssertDev(_operandSize != 0, "Attempted to use operand size of uninitialized or void object"); pxAssertDev(_operandSize != 0, "Attempted to use operand size of uninitialized or void object");
return _operandSize; return _operandSize;
} }
@ -222,12 +228,18 @@ public:
xWrite8(0x66); xWrite8(0x66);
} }
int GetImmSize() const { int GetImmSize() const
switch (GetOperandSize()) { {
case 1: return 1; switch (GetOperandSize())
case 2: return 2; {
case 4: return 4; case 1:
case 8: return 4; // Only mov's take 64-bit immediates return 1;
case 2:
return 2;
case 4:
return 4;
case 8:
return 4; // Only mov's take 64-bit immediates
jNO_DEFAULT jNO_DEFAULT
} }
return 0; return 0;
@ -235,7 +247,8 @@ public:
void xWriteImm(int imm) const void xWriteImm(int imm) const
{ {
switch (GetImmSize()) { switch (GetImmSize())
{
case 1: case 1:
xWrite8(imm); xWrite8(imm);
break; break;
@ -270,17 +283,20 @@ class xRegisterBase : public OperandSizedObject
{ {
protected: protected:
xRegisterBase(uint operandSize, int regId) 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 // Note: to avoid tons of ifdef, the 32 bits build will instantiate
// all 16x64 bits registers. // all 16x64 bits registers.
pxAssert((Id >= xRegId_Empty) && (Id < 16)); pxAssert((Id >= xRegId_Empty) && (Id < 16));
} }
public: public:
int Id; int Id;
xRegisterBase() xRegisterBase()
: OperandSizedObject(0), Id(xRegId_Invalid) : OperandSizedObject(0)
, Id(xRegId_Invalid)
{ {
} }
@ -326,6 +342,7 @@ protected:
: _parent(operandSize, regId) : _parent(operandSize, regId)
{ {
} }
public: public:
xRegisterInt() = default; xRegisterInt() = default;
@ -961,7 +978,7 @@ static __fi xAddressVoid operator+(sptr addr, const xAddressReg &reg)
{ {
return reg + (sptr)addr; return reg + (sptr)addr;
} }
} } // namespace x86Emitter
#include "implement/helpers.h" #include "implement/helpers.h"

View File

@ -43,7 +43,8 @@ void pxCheckBox::Init(const wxString &label, const wxString &subtext, int flags)
*this += m_checkbox | pxSizerFlags::StdExpand(); *this += m_checkbox | pxSizerFlags::StdExpand();
static const int Indentation = 23; static const int Indentation = 23;
if (!subtext.IsEmpty()) { if (!subtext.IsEmpty())
{
m_subtext = new pxStaticText(this, subtext, wxALIGN_LEFT); m_subtext = new pxStaticText(this, subtext, wxALIGN_LEFT);
wxFlexGridSizer& spaced(*new wxFlexGridSizer(3)); 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) pxCheckBox& pxCheckBox::SetSubPadding(int pad)
{ {
m_subPadding = pad; m_subPadding = pad;
if (m_sizerItem_subtext) { if (m_sizerItem_subtext)
{
m_sizerItem_subtext->SetBorder(m_subPadding); m_sizerItem_subtext->SetBorder(m_subPadding);
Fit(); Fit();
} }

View File

@ -43,7 +43,7 @@ namespace Threading
class Mutex; class Mutex;
class Semaphore; class Semaphore;
class pxThread; class pxThread;
} } // namespace Threading
namespace Exception namespace Exception
{ {

View File

@ -51,7 +51,8 @@ void pxRadioPanel::Reset()
if (numbuttons == 0) if (numbuttons == 0)
return; 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].LabelObj);
safe_delete(m_objects[i].SubTextObj); safe_delete(m_objects[i].SubTextObj);
} }
@ -80,7 +81,8 @@ void pxRadioPanel::Realize()
for (int i = 1; i < numbuttons; ++i) for (int i = 1; i < numbuttons; ++i)
m_objects[i].LabelObj = new wxRadioButton(this, wxID_ANY, m_buttonStrings[i].Label); 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; m_objects[i].SubTextObj = NULL;
if (m_buttonStrings[i].SubText.IsEmpty()) if (m_buttonStrings[i].SubText.IsEmpty())
continue; continue;
@ -89,10 +91,12 @@ void pxRadioPanel::Realize()
pxAssert(GetSizer() != NULL); pxAssert(GetSizer() != NULL);
for (int i = 0; i < numbuttons; ++i) { for (int i = 0; i < numbuttons; ++i)
{
*this += m_objects[i].LabelObj | pxSizerFlags::StdExpand(); *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 += subobj | pxBorder(wxLEFT, m_Indentation).Expand();
*this += 9 + m_padding.GetHeight(); *this += 9 + m_padding.GetHeight();
} }
@ -137,7 +141,8 @@ pxRadioPanel &pxRadioPanel::SetSelection(int idx)
void pxRadioPanel::_RealizeDefaultOption() void pxRadioPanel::_RealizeDefaultOption()
{ {
if (m_IsRealized && m_DefaultIdx != -1) { if (m_IsRealized && m_DefaultIdx != -1)
{
wxFont def(GetFont()); wxFont def(GetFont());
def.SetWeight(wxFONTWEIGHT_BOLD); def.SetWeight(wxFONTWEIGHT_BOLD);
//def.SetStyle( wxFONTSTYLE_ITALIC ); //def.SetStyle( wxFONTSTYLE_ITALIC );
@ -153,7 +158,8 @@ pxRadioPanel &pxRadioPanel::SetDefaultItem(int idx)
if (idx == m_DefaultIdx) if (idx == m_DefaultIdx)
return *this; return *this;
if (m_IsRealized && m_DefaultIdx != -1) { if (m_IsRealized && m_DefaultIdx != -1)
{
wxFont def(GetFont()); wxFont def(GetFont());
m_objects[m_DefaultIdx].LabelObj->SetFont(def); m_objects[m_DefaultIdx].LabelObj->SetFont(def);
m_objects[m_DefaultIdx].LabelObj->SetForegroundColour(GetForegroundColour()); m_objects[m_DefaultIdx].LabelObj->SetForegroundColour(GetForegroundColour());
@ -193,7 +199,8 @@ int pxRadioPanel::GetSelection() const
if (!VerifyRealizedState()) if (!VerifyRealizedState())
return 0; 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 (wxRadioButton* woot = m_objects[i].LabelObj)
if (woot->GetValue()) if (woot->GetValue())
return i; return i;

View File

@ -168,7 +168,8 @@ wxSize pxStaticText::GetBestWrappedSize(const wxClientDC &dc) const
double parentalFactor = 1.0; double parentalFactor = 1.0;
const wxWindow* millrun = this; const wxWindow* millrun = this;
while (millrun) { while (millrun)
{
// IMPORTANT : wxWizard changes its min size and then expects everything else // 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) // to play nice and NOT resize according to the new min size. (wtf stupid)
// Anyway, this fixes it -- ignore min size specifier on wxWizard! // 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); int min = (int)((millrun->GetMinWidth() - parentalAdjust) * parentalFactor);
if (min > 0 && ((idealWidth < 0) || (min < idealWidth))) { if (min > 0 && ((idealWidth < 0) || (min < idealWidth)))
{
idealWidth = min; idealWidth = min;
} }
@ -185,7 +187,8 @@ wxSize pxStaticText::GetBestWrappedSize(const wxClientDC &dc) const
millrun = millrun->GetParent(); 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 // 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. // the size of the user's display area.
@ -208,7 +211,8 @@ pxStaticText &pxStaticText::WrapAt(int width)
if (width > 1) if (width > 1)
wrappedLabel = pxTextWrapper().Wrap(this, m_label, width).GetResult(); wrappedLabel = pxTextWrapper().Wrap(this, m_label, width).GetResult();
if (m_wrappedLabel != wrappedLabel) { if (m_wrappedLabel != wrappedLabel)
{
m_wrappedLabel = wrappedLabel; m_wrappedLabel = wrappedLabel;
wxSize area = wxClientDC(this).GetMultiLineTextExtent(m_wrappedLabel); wxSize area = wxClientDC(this).GetMultiLineTextExtent(m_wrappedLabel);
SetMinSize(wxSize( SetMinSize(wxSize(
@ -220,7 +224,8 @@ pxStaticText &pxStaticText::WrapAt(int width)
bool pxStaticText::_updateWrapping(bool textChanged) bool pxStaticText::_updateWrapping(bool textChanged)
{ {
if (!m_autowrap) { if (!m_autowrap)
{
//m_wrappedLabel = wxEmptyString; //m_wrappedLabel = wxEmptyString;
//m_wrappedWidth = -1; //m_wrappedWidth = -1;
return false; return false;
@ -257,7 +262,8 @@ void pxStaticText::UpdateWrapping(bool textChanged)
void pxStaticText::SetLabel(const wxString& label) void pxStaticText::SetLabel(const wxString& label)
{ {
const bool labelChanged(label != m_label); const bool labelChanged(label != m_label);
if (labelChanged) { if (labelChanged)
{
m_label = label; m_label = label;
Refresh(); Refresh();
} }
@ -277,7 +283,8 @@ wxFont pxStaticText::GetFontOk() const
bool pxStaticText::Enable(bool enabled) bool pxStaticText::Enable(bool enabled)
{ {
if (_parent::Enable(enabled)) { if (_parent::Enable(enabled))
{
Refresh(); Refresh();
return true; return true;
} }
@ -328,10 +335,13 @@ wxSize pxStaticText::DoGetBestSize() const
wxSize best; wxSize best;
if (m_autowrap) { if (m_autowrap)
{
best = GetBestWrappedSize(dc); best = GetBestWrappedSize(dc);
//best.x = wxDefaultCoord; //best.x = wxDefaultCoord;
} else { }
else
{
// No autowrapping, so we can force a specific size here! // No autowrapping, so we can force a specific size here!
best = dc.GetMultiLineTextExtent(GetLabel()); best = dc.GetMultiLineTextExtent(GetLabel());
best.x += calcPaddingWidth(best.x); best.x += calcPaddingWidth(best.x);

View File

@ -86,7 +86,8 @@ void pxInputStream::SetStream(const wxString &filename, wxInputStream *stream)
void pxInputStream::Read(void* dest, size_t size) void pxInputStream::Read(void* dest, size_t size)
{ {
m_stream_in->Read(dest, 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; int err = errno;
if (!err) if (!err)
throw Exception::BadStream(m_filename).SetDiagMsg(L"Cannot read from file (bad file handle?)"); 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) void pxOutputStream::Write(const void* src, size_t size)
{ {
m_stream_out->Write(src, 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; int err = errno;
if (!err) if (!err)
throw Exception::BadStream(m_filename).SetDiagMsg(L"Cannot write to file/stream."); 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(); dest.clear();
bool isUTF8 = false; bool isUTF8 = false;
while (true) { while (true)
{
char c; char c;
input.Read(&c, sizeof(c)); input.Read(&c, sizeof(c));
if (c == 0) if (c == 0)
@ -176,7 +179,8 @@ bool pxReadLine(wxInputStream &input, std::string &dest)
break; break;
if (c == '\n') if (c == '\n')
break; // eat on UNIX break; // eat on UNIX
if (c == '\r') { if (c == '\r')
{
input.Read(&c, sizeof(c)); input.Read(&c, sizeof(c));
if (c == 0) if (c == 0)
break; break;
@ -201,7 +205,8 @@ void pxReadLine(wxInputStream &input, wxString &dest, std::string &intermed)
dest.clear(); dest.clear();
if (pxReadLine(input, intermed)) if (pxReadLine(input, intermed))
dest = fromUTF8(intermed.c_str()); dest = fromUTF8(intermed.c_str());
else { else
{
// Optimized ToAscii conversion. // Optimized ToAscii conversion.
// wx3.0 : NOT COMPATIBLE!! (on linux anyway) // wx3.0 : NOT COMPATIBLE!! (on linux anyway)
const char* ascii = intermed.c_str(); const char* ascii = intermed.c_str();
@ -230,7 +235,8 @@ void pxWriteLine(wxOutputStream &output)
void pxWriteLine(wxOutputStream& output, const wxString& text) void pxWriteLine(wxOutputStream& output, const wxString& text)
{ {
if (!text.IsEmpty()) { if (!text.IsEmpty())
{
pxToUTF8 utf8(text); pxToUTF8 utf8(text);
output.Write(utf8, utf8.Length()); output.Write(utf8, utf8.Length());
} }

View File

@ -92,9 +92,12 @@ void pxWindowTextWriter::_DoWriteLn(const wxString &msg)
wxPoint dispos(m_curpos); wxPoint dispos(m_curpos);
if (m_align & wxALIGN_CENTER_HORIZONTAL) { if (m_align & wxALIGN_CENTER_HORIZONTAL)
{
dispos.x = (m_dc.GetSize().GetWidth() - tWidth) / 2; 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; dispos.x = m_dc.GetSize().GetWidth() - tWidth;
} }

View File

@ -56,9 +56,12 @@ void SynchronousActionState::SetException(const BaseException &ex)
void SynchronousActionState::SetException(BaseException* ex) void SynchronousActionState::SetException(BaseException* ex)
{ {
if (!m_posted) { if (!m_posted)
{
m_exception = ScopedExcept(ex); m_exception = ScopedExcept(ex);
} else if (wxTheApp) { }
else if (wxTheApp)
{
// transport the exception to the main thread, since the message is fully // transport the exception to the main thread, since the message is fully
// asynchronous, or has already entered an asynchronous state. Message is sent // 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 // 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())); const wxString& prefix(pxsFmt(L"(%s) ", GetClassInfo()->GetClassName()));
ex->DiagMsg() = prefix + ex->DiagMsg(); ex->DiagMsg() = prefix + ex->DiagMsg();
if (!m_state) { if (!m_state)
{
ScopedExcept exptr(ex); // auto-delete it after handling. ScopedExcept exptr(ex); // auto-delete it after handling.
ex->Rethrow(); ex->Rethrow();
} }
@ -202,7 +206,8 @@ void pxSynchronousCommandEvent::SetException(const BaseException &ex)
void pxSynchronousCommandEvent::SetException(BaseException* ex) void pxSynchronousCommandEvent::SetException(BaseException* ex)
{ {
if (!m_sync) { if (!m_sync)
{
ScopedExcept exptr(ex); // auto-delete it after handling. ScopedExcept exptr(ex); // auto-delete it after handling.
ex->Rethrow(); ex->Rethrow();
} }
@ -349,7 +354,8 @@ bool wxAppWithHelpers::Rpc_TryInvokeAsync(FnType_Void *method)
void wxAppWithHelpers::ProcessMethod(FnType_Void* method) void wxAppWithHelpers::ProcessMethod(FnType_Void* method)
{ {
if (wxThread::IsMain()) { if (wxThread::IsMain())
{
method(); method();
return; return;
} }
@ -392,7 +398,8 @@ bool wxAppWithHelpers::ProcessEvent(pxActionEvent &evt)
{ {
if (wxThread::IsMain()) if (wxThread::IsMain())
return _parent::ProcessEvent(evt); return _parent::ProcessEvent(evt);
else { else
{
SynchronousActionState sync; SynchronousActionState sync;
evt.SetSyncState(sync); evt.SetSyncState(sync);
AddPendingEvent(evt); AddPendingEvent(evt);
@ -403,10 +410,13 @@ bool wxAppWithHelpers::ProcessEvent(pxActionEvent &evt)
bool wxAppWithHelpers::ProcessEvent(pxActionEvent* evt) bool wxAppWithHelpers::ProcessEvent(pxActionEvent* evt)
{ {
if (wxThread::IsMain()) { if (wxThread::IsMain())
{
std::unique_ptr<wxEvent> deleteMe(evt); std::unique_ptr<wxEvent> deleteMe(evt);
return _parent::ProcessEvent(*deleteMe); return _parent::ProcessEvent(*deleteMe);
} else { }
else
{
SynchronousActionState sync; SynchronousActionState sync;
evt->SetSyncState(sync); evt->SetSyncState(sync);
AddPendingEvent(*evt); AddPendingEvent(*evt);
@ -436,11 +446,16 @@ void pxActionEvent::_DoInvokeEvent()
{ {
AffinityAssert_AllowFrom_MainUI(); AffinityAssert_AllowFrom_MainUI();
try { try
{
InvokeEvent(); InvokeEvent();
} catch (BaseException &ex) { }
catch (BaseException& ex)
{
SetException(ex); SetException(ex);
} catch (std::runtime_error &ex) { }
catch (std::runtime_error& ex)
{
SetException(new Exception::RuntimeError(ex)); SetException(new Exception::RuntimeError(ex));
} }
@ -455,11 +470,16 @@ void wxAppWithHelpers::OnSynchronousCommand(pxSynchronousCommandEvent &evt)
pxAppLog.Write(L"(App) Executing command event synchronously..."); pxAppLog.Write(L"(App) Executing command event synchronously...");
evt.SetEventType(evt.GetRealEventType()); evt.SetEventType(evt.GetRealEventType());
try { try
{
ProcessEvent(evt); ProcessEvent(evt);
} catch (BaseException &ex) { }
catch (BaseException& ex)
{
evt.SetException(ex); evt.SetException(ex);
} catch (std::runtime_error &ex) { }
catch (std::runtime_error& ex)
{
evt.SetException(new Exception::RuntimeError(ex, evt.GetClassInfo()->GetClassName())); evt.SetException(new Exception::RuntimeError(ex, evt.GetClassInfo()->GetClassName()));
} }
@ -498,12 +518,14 @@ void wxAppWithHelpers::IdleEventDispatcher(const wxChar *action)
ScopedLock lock(m_IdleEventMutex); 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); std::unique_ptr<wxEvent> deleteMe(*node);
m_IdleEventQueue.erase(node); m_IdleEventQueue.erase(node);
lock.Release(); 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 // 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 // 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 // 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."); pxThreadLog.Write(((pxThread*)((wxCommandEvent*)deleteMe.get())->GetClientData())->GetName(), L"Deletion postponed due to mutex or semaphore dependency.");
postponed.push_back(deleteMe.release()); postponed.push_back(deleteMe.release());
} else { }
else
{
pxAppLog.Write(L"(AppIdleQueue%s) Dispatching event '%s'", action, deleteMe->GetClassInfo()->GetClassName()); pxAppLog.Write(L"(AppIdleQueue%s) Dispatching event '%s'", action, deleteMe->GetClassInfo()->GetClassName());
ProcessEvent(*deleteMe); // dereference to prevent auto-deletion by ProcessEvent ProcessEvent(*deleteMe); // dereference to prevent auto-deletion by ProcessEvent
} }
@ -586,12 +610,14 @@ void wxAppWithHelpers::PostAction(const pxActionEvent &evt)
void wxAppWithHelpers::ProcessAction(pxActionEvent& evt) void wxAppWithHelpers::ProcessAction(pxActionEvent& evt)
{ {
if (!wxThread::IsMain()) { if (!wxThread::IsMain())
{
SynchronousActionState sync; SynchronousActionState sync;
evt.SetSyncState(sync); evt.SetSyncState(sync);
AddPendingEvent(evt); AddPendingEvent(evt);
sync.WaitForResult(); sync.WaitForResult();
} else }
else
evt._DoInvokeEvent(); evt._DoInvokeEvent();
} }
@ -658,7 +684,8 @@ wxAppTraits *wxAppWithHelpers::CreateTraits()
void wxAppWithHelpers::OnDeleteThread(wxCommandEvent& evt) void wxAppWithHelpers::OnDeleteThread(wxCommandEvent& evt)
{ {
std::unique_ptr<pxThread> thr((pxThread*)evt.GetClientData()); std::unique_ptr<pxThread> thr((pxThread*)evt.GetClientData());
if (!thr) { if (!thr)
{
pxThreadLog.Write(L"null", L"OnDeleteThread: NULL thread object received (and ignored)."); pxThreadLog.Write(L"null", L"OnDeleteThread: NULL thread object received (and ignored).");
return; return;
} }

View File

@ -142,4 +142,4 @@ namespace Msgbox
{ {
extern int ShowModal(BaseMessageBoxEvent& evt); extern int ShowModal(BaseMessageBoxEvent& evt);
extern int ShowModal(const wxString& title, const wxString& content, const MsgButtons& buttons); extern int ShowModal(const wxString& title, const wxString& content, const MsgButtons& buttons);
} } // namespace Msgbox

View File

@ -40,7 +40,8 @@ const pxStretchType
wxSizerFlags pxAlignmentType::Apply(wxSizerFlags flags) const wxSizerFlags pxAlignmentType::Apply(wxSizerFlags flags) const
{ {
switch (intval) { switch (intval)
{
case Centre: case Centre:
flags.Align(flags.GetFlags() | wxALIGN_CENTRE_HORIZONTAL); flags.Align(flags.GetFlags() | wxALIGN_CENTRE_HORIZONTAL);
break; break;
@ -70,7 +71,8 @@ wxSizerFlags pxAlignmentType::Apply(wxSizerFlags flags) const
wxSizerFlags pxStretchType::Apply(wxSizerFlags flags) const wxSizerFlags pxStretchType::Apply(wxSizerFlags flags) const
{ {
switch (intval) { switch (intval)
{
case Shrink: case Shrink:
//pxFail( "wxSHRINK is an ignored stretch flag." ); //pxFail( "wxSHRINK is an ignored stretch flag." );
break; break;
@ -420,8 +422,10 @@ pxTextWrapperBase &pxTextWrapperBase::Wrap(const wxWindow &win, const wxString &
wxString::const_iterator lastSpace = text.end(); wxString::const_iterator lastSpace = text.end();
wxString::const_iterator lineStart = text.begin(); wxString::const_iterator lineStart = text.begin();
for (wxString::const_iterator p = lineStart;; ++p) { for (wxString::const_iterator p = lineStart;; ++p)
if (IsStartOfNewLine()) { {
if (IsStartOfNewLine())
{
OnNewLine(); OnNewLine();
lastSpace = text.end(); lastSpace = text.end();
@ -433,28 +437,36 @@ pxTextWrapperBase &pxTextWrapperBase::Wrap(const wxWindow &win, const wxString &
line.clear(); line.clear();
} }
if (p == text.end() || *p == L'\n') { if (p == text.end() || *p == L'\n')
{
wasWrapped = false; wasWrapped = false;
DoOutputLine(line); DoOutputLine(line);
if (p == text.end()) if (p == text.end())
break; break;
} else { // not EOL }
if (is_cjk_char(*p)) { else
if (!no_break_before(*p)) { { // not EOL
if (is_cjk_char(*p))
{
if (!no_break_before(*p))
{
if (p == lineStart || !no_break_after(*(p - 1))) if (p == lineStart || !no_break_after(*(p - 1)))
lastSpace = p; lastSpace = p;
} }
} else if (*p == L' ' || *p == L',' || *p == L'/') }
else if (*p == L' ' || *p == L',' || *p == L'/')
lastSpace = p; lastSpace = p;
line += *p; line += *p;
if (widthMax >= 0 && lastSpace != text.end()) { if (widthMax >= 0 && lastSpace != text.end())
{
int width; int width;
win.GetTextExtent(line, &width, NULL); win.GetTextExtent(line, &width, NULL);
if (width > widthMax) { if (width > widthMax)
{
wasWrapped = true; wasWrapped = true;
// remove the last word from this line // remove the last word from this line
@ -544,7 +556,8 @@ ScopedBusyCursor::~ScopedBusyCursor()
if (!pxAssert(wxTheApp != NULL)) if (!pxAssert(wxTheApp != NULL))
return; return;
if (!pxAssert(!m_cursorStack.empty())) { if (!pxAssert(!m_cursorStack.empty()))
{
SetManualBusyCursor(m_defBusyType); SetManualBusyCursor(m_defBusyType);
return; return;
} }
@ -570,7 +583,8 @@ void ScopedBusyCursor::SetDefault(BusyCursorType busytype)
void ScopedBusyCursor::SetManualBusyCursor(BusyCursorType busytype) void ScopedBusyCursor::SetManualBusyCursor(BusyCursorType busytype)
{ {
switch (busytype) { switch (busytype)
{
case Cursor_NotBusy: case Cursor_NotBusy:
wxSetCursor(wxNullCursor); wxSetCursor(wxNullCursor);
break; break;

View File

@ -46,7 +46,7 @@ extern wxSizerFlags SubGroup();
extern wxSizerFlags StdButton(); extern wxSizerFlags StdButton();
extern wxSizerFlags Checkbox(); extern wxSizerFlags Checkbox();
extern void SetBestPadding(); extern void SetBestPadding();
}; }; // namespace pxSizerFlags
#define wxSF wxSizerFlags() #define wxSF wxSizerFlags()
@ -58,7 +58,8 @@ extern void SetBestPadding();
// //
struct pxAlignmentType struct pxAlignmentType
{ {
enum { enum
{
Centre, Centre,
Center = Centre, Center = Centre,
Middle, Middle,
@ -100,7 +101,8 @@ struct pxAlignmentType
struct pxStretchType struct pxStretchType
{ {
enum { enum
{
Shrink, Shrink,
Expand, Expand,
Shaped, Shaped,
@ -745,7 +747,8 @@ public:
const wxCursor& GetArrowWait(); const wxCursor& GetArrowWait();
}; };
enum BusyCursorType { enum BusyCursorType
{
Cursor_NotBusy, Cursor_NotBusy,
Cursor_KindaBusy, Cursor_KindaBusy,
Cursor_ReallyBusy, Cursor_ReallyBusy,

View File

@ -122,7 +122,8 @@ wxDialogWithHelpers::wxDialogWithHelpers(wxWindow *parent, const wxString &title
: wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, cflags.GetWxWindowFlags()) : wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, cflags.GetWxWindowFlags())
{ {
m_hasContextHelp = cflags.hasContextHelp; m_hasContextHelp = cflags.hasContextHelp;
if ((int)cflags.BoxSizerOrient != 0) { if ((int)cflags.BoxSizerOrient != 0)
{
SetSizer(new wxBoxSizer(cflags.BoxSizerOrient)); SetSizer(new wxBoxSizer(cflags.BoxSizerOrient));
*this += StdPadding; *this += StdPadding;
} }
@ -179,10 +180,12 @@ void wxDialogWithHelpers::DoAutoCenter()
// a lot since the main window is small). // a lot since the main window is small).
bool centerfail = true; bool centerfail = true;
if (wxWindow *parent = GetParent()) { if (wxWindow* parent = GetParent())
{
const wxSize parentSize(parent->GetSize()); 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(); CenterOnParent();
centerfail = false; centerfail = false;
} }
@ -197,19 +200,22 @@ void wxDialogWithHelpers::SmartCenterFit()
Fit(); Fit();
const wxString dlgName(GetDialogName()); const wxString dlgName(GetDialogName());
if (dlgName.IsEmpty()) { if (dlgName.IsEmpty())
{
DoAutoCenter(); DoAutoCenter();
return; return;
} }
if (wxConfigBase *cfg = wxConfigBase::Get(false)) { if (wxConfigBase* cfg = wxConfigBase::Get(false))
{
wxRect screenRect(GetScreenRect()); wxRect screenRect(GetScreenRect());
IniLoader loader(cfg); IniLoader loader(cfg);
ScopedIniGroup group(loader, L"DialogPositions"); ScopedIniGroup group(loader, L"DialogPositions");
cfg->SetRecordDefaults(false); cfg->SetRecordDefaults(false);
if (GetWindowStyle() & wxRESIZE_BORDER) { if (GetWindowStyle() & wxRESIZE_BORDER)
{
wxSize size; wxSize size;
loader.Entry(dlgName + L"_Size", size, screenRect.GetSize()); loader.Entry(dlgName + L"_Size", size, screenRect.GetSize());
SetSize(size); SetSize(size);
@ -217,7 +223,8 @@ void wxDialogWithHelpers::SmartCenterFit()
if (!cfg->Exists(dlgName + L"_Pos")) if (!cfg->Exists(dlgName + L"_Pos"))
DoAutoCenter(); DoAutoCenter();
else { else
{
wxPoint pos; wxPoint pos;
loader.Entry(dlgName + L"_Pos", pos, screenRect.GetPosition()); loader.Entry(dlgName + L"_Pos", pos, screenRect.GetPosition());
SetPosition(pos); SetPosition(pos);
@ -241,7 +248,8 @@ int wxDialogWithHelpers::ShowModal()
// 75% larger than the fitted dialog. // 75% larger than the fitted dialog.
bool wxDialogWithHelpers::Show(bool show) bool wxDialogWithHelpers::Show(bool show)
{ {
if (show) { if (show)
{
SmartCenterFit(); SmartCenterFit();
m_CreatedRect = GetScreenRect(); 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 // ... 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 // 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 wxString dlgName(GetDialogName());
const wxRect screenRect(GetScreenRect()); const wxRect screenRect(GetScreenRect());
if (!dlgName.IsEmpty() && (m_CreatedRect != screenRect)) { if (!dlgName.IsEmpty() && (m_CreatedRect != screenRect))
{
wxPoint pos(screenRect.GetPosition()); wxPoint pos(screenRect.GetPosition());
IniSaver saver(cfg); IniSaver saver(cfg);
ScopedIniGroup group(saver, L"DialogPositions"); ScopedIniGroup group(saver, L"DialogPositions");
if (GetWindowStyle() & wxRESIZE_BORDER) { if (GetWindowStyle() & wxRESIZE_BORDER)
{
wxSize size(screenRect.GetSize()); wxSize size(screenRect.GetSize());
saver.Entry(dlgName + L"_Size", 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 // Add the context-sensitive help button on the caption for the platforms
// which support it (currently MSW only) // which support it (currently MSW only)
if (m_hasContextHelp) { if (m_hasContextHelp)
{
SetExtraStyle(wxDIALOG_EX_CONTEXTHELP); SetExtraStyle(wxDIALOG_EX_CONTEXTHELP);
#ifndef __WXMSW__ #ifndef __WXMSW__
*m_extraButtonSizer += new wxContextHelpButton(this) | StdButton(); *m_extraButtonSizer += new wxContextHelpButton(this) | StdButton();