summaryrefslogtreecommitdiff
path: root/Source/Core/Common
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2012-03-22 15:21:52 +0100
committerPierre Bourdon <delroth@gmail.com>2012-03-22 15:21:52 +0100
commit0ffc12bbfd6ac44b3030ec30f400a58e951087b7 (patch)
tree53a6fac9ec79bcd71fe2046d8fb579478da12fd2 /Source/Core/Common
parent006923e871e496a7c6c0fe9ba76da4ee939ce14e (diff)
parentd95e31af3f779bfa3141047e8b6275e1fd2e4bbb (diff)
Merge branch 'master' into zcomploc-support
Conflicts: Source/Core/VideoCommon/Src/PixelShaderGen.cpp
Diffstat (limited to 'Source/Core/Common')
-rw-r--r--Source/Core/Common/Common.vcxproj2
-rw-r--r--Source/Core/Common/Src/ABI.cpp7
-rw-r--r--Source/Core/Common/Src/BreakPoints.cpp23
-rw-r--r--Source/Core/Common/Src/BreakPoints.h2
-rw-r--r--Source/Core/Common/Src/CPUDetect.cpp25
-rw-r--r--Source/Core/Common/Src/ChunkFile.h27
-rw-r--r--Source/Core/Common/Src/Common.h22
-rw-r--r--Source/Core/Common/Src/CommonFuncs.h13
-rw-r--r--Source/Core/Common/Src/CommonPaths.h2
-rw-r--r--Source/Core/Common/Src/Hash.cpp12
-rw-r--r--Source/Core/Common/Src/IniFile.cpp6
-rw-r--r--Source/Core/Common/Src/LinearDiskCache.h43
-rw-r--r--Source/Core/Common/Src/LogManager.cpp13
-rw-r--r--Source/Core/Common/Src/LogManager.h12
-rw-r--r--Source/Core/Common/Src/MemoryUtil.cpp49
-rw-r--r--Source/Core/Common/Src/MsgHandler.cpp2
-rw-r--r--Source/Core/Common/Src/StdThread.h2
-rw-r--r--Source/Core/Common/Src/StringUtil.cpp17
-rw-r--r--Source/Core/Common/Src/SysConf.cpp2
-rw-r--r--Source/Core/Common/Src/SysConf.h5
-rw-r--r--Source/Core/Common/Src/Thread.h7
-rw-r--r--Source/Core/Common/Src/Version.cpp5
-rw-r--r--Source/Core/Common/Src/VideoBackendBase.h6
-rw-r--r--Source/Core/Common/Src/x64Emitter.cpp96
-rw-r--r--Source/Core/Common/Src/x64Emitter.h11
25 files changed, 352 insertions, 59 deletions
diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj
index d29043eb7d..732fc7258c 100644
--- a/Source/Core/Common/Common.vcxproj
+++ b/Source/Core/Common/Common.vcxproj
@@ -45,7 +45,6 @@
<UseDebugLibraries>false</UseDebugLibraries>
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@@ -56,7 +55,6 @@
<UseDebugLibraries>false</UseDebugLibraries>
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
- <WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
diff --git a/Source/Core/Common/Src/ABI.cpp b/Source/Core/Common/Src/ABI.cpp
index 08e021f083..63a8e76934 100644
--- a/Source/Core/Common/Src/ABI.cpp
+++ b/Source/Core/Common/Src/ABI.cpp
@@ -189,7 +189,7 @@ unsigned int XEmitter::ABI_GetAlignedFrameSize(unsigned int frameSize) {
#ifdef __GNUC__
(frameSize + 15) & -16;
#else
- frameSize;
+ (frameSize + 3) & -4;
#endif
return alignedSize;
}
@@ -200,16 +200,15 @@ void XEmitter::ABI_AlignStack(unsigned int frameSize) {
// Linux requires the stack to be 16-byte aligned before calls that put SSE
// vectors on the stack, but since we do not keep track of which calls do that,
// it is effectively every call as well.
-// Windows binaries compiled with MSVC do not have such a restriction, but I
+// Windows binaries compiled with MSVC do not have such a restriction*, but I
// expect that GCC on Windows acts the same as GCC on Linux in this respect.
// It would be nice if someone could verify this.
-#ifdef __GNUC__
+// *However, the MSVC optimizing compiler assumes a 4-byte-aligned stack at times.
unsigned int fillSize =
ABI_GetAlignedFrameSize(frameSize) - (frameSize + 4);
if (fillSize != 0) {
SUB(32, R(ESP), Imm8(fillSize));
}
-#endif
}
void XEmitter::ABI_RestoreStack(unsigned int frameSize) {
diff --git a/Source/Core/Common/Src/BreakPoints.cpp b/Source/Core/Common/Src/BreakPoints.cpp
index 45a0b52daf..1700276d85 100644
--- a/Source/Core/Common/Src/BreakPoints.cpp
+++ b/Source/Core/Common/Src/BreakPoints.cpp
@@ -18,6 +18,7 @@
#include "Common.h"
#include "DebugInterface.h"
#include "BreakPoints.h"
+#include "../../Core/Src/PowerPC/JitCommon/JitBase.h"
#include <sstream>
bool BreakPoints::IsAddressBreakPoint(u32 _iAddress)
@@ -70,7 +71,11 @@ void BreakPoints::AddFromStrings(const TBreakPointsStr& bps)
void BreakPoints::Add(const TBreakPoint& bp)
{
if (!IsAddressBreakPoint(bp.iAddress))
+ {
m_BreakPoints.push_back(bp);
+ if (jit)
+ jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
+ }
}
void BreakPoints::Add(u32 em_address, bool temp)
@@ -83,21 +88,35 @@ void BreakPoints::Add(u32 em_address, bool temp)
pt.iAddress = em_address;
m_BreakPoints.push_back(pt);
+
+ if (jit)
+ jit->GetBlockCache()->InvalidateICache(em_address, 4);
}
}
-void BreakPoints::Remove(u32 _iAddress)
+void BreakPoints::Remove(u32 em_address)
{
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
{
- if (i->iAddress == _iAddress)
+ if (i->iAddress == em_address)
{
m_BreakPoints.erase(i);
+ if (jit)
+ jit->GetBlockCache()->InvalidateICache(em_address, 4);
return;
}
}
}
+void BreakPoints::Clear()
+{
+ for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
+ {
+ if (jit)
+ jit->GetBlockCache()->InvalidateICache(i->iAddress, 4);
+ m_BreakPoints.erase(i);
+ }
+}
MemChecks::TMemChecksStr MemChecks::GetStrings() const
{
diff --git a/Source/Core/Common/Src/BreakPoints.h b/Source/Core/Common/Src/BreakPoints.h
index a97452cde6..c742f812a7 100644
--- a/Source/Core/Common/Src/BreakPoints.h
+++ b/Source/Core/Common/Src/BreakPoints.h
@@ -78,7 +78,7 @@ public:
// Remove Breakpoint
void Remove(u32 _iAddress);
- void Clear() { m_BreakPoints.clear(); };
+ void Clear();
void DeleteByAddress(u32 _Address);
diff --git a/Source/Core/Common/Src/CPUDetect.cpp b/Source/Core/Common/Src/CPUDetect.cpp
index 810c5d2a59..93e9d25087 100644
--- a/Source/Core/Common/Src/CPUDetect.cpp
+++ b/Source/Core/Common/Src/CPUDetect.cpp
@@ -32,6 +32,10 @@
//#include <config/i386/cpuid.h>
#include <xmmintrin.h>
+#if defined __FreeBSD__
+#include <sys/types.h>
+#include <machine/cpufunc.h>
+#else
static inline void do_cpuid(unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
{
@@ -39,41 +43,42 @@ static inline void do_cpuid(unsigned int *eax, unsigned int *ebx,
// Note: EBX is reserved on Mac OS X and in PIC on Linux, so it has to
// restored at the end of the asm block.
__asm__ (
- "mov %%rbx,%%rdi;"
"cpuid;"
"movl %%ebx,%1;"
- "mov %%rdi,%%rbx;"
: "=a" (*eax),
- "=g" (*ebx),
+ "=S" (*ebx),
"=c" (*ecx),
"=d" (*edx)
: "a" (*eax)
- : "rdi", "rbx"
+ : "rbx"
);
#else
- __asm__(
- "movl %%ebx,%%edi;"
+ __asm__ (
"cpuid;"
- "movl %%ebx,%1;"
- "movl %%edi,%%ebx;"
+ "movl %%ebx,%1;"
: "=a" (*eax),
- "=g" (*ebx),
+ "=S" (*ebx),
"=c" (*ecx),
"=d" (*edx)
: "a" (*eax)
- : "edi", "ebx"
+ : "ebx"
);
#endif
}
+#endif /* defined __FreeBSD__ */
static void __cpuid(int info[4], int x)
{
+#if defined __FreeBSD__
+ do_cpuid((unsigned int)x, (unsigned int*)info);
+#else
unsigned int eax = x, ebx = 0, ecx = 0, edx = 0;
do_cpuid(&eax, &ebx, &ecx, &edx);
info[0] = eax;
info[1] = ebx;
info[2] = ecx;
info[3] = edx;
+#endif
}
#endif
diff --git a/Source/Core/Common/Src/ChunkFile.h b/Source/Core/Common/Src/ChunkFile.h
index 03216deaf1..4ed781dcbd 100644
--- a/Source/Core/Common/Src/ChunkFile.h
+++ b/Source/Core/Common/Src/ChunkFile.h
@@ -154,7 +154,21 @@ public:
}
(*ptr) += stringLen;
}
-
+
+ void Do(std::wstring &x)
+ {
+ int stringLen = sizeof(wchar_t)*((int)x.length() + 1);
+ Do(stringLen);
+
+ switch (mode) {
+ case MODE_READ: x = (wchar_t*)*ptr; break;
+ case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break;
+ case MODE_MEASURE: break;
+ case MODE_VERIFY: _dbg_assert_msg_(COMMON, x == (wchar_t*)*ptr, "Savestate verification failure: \"%s\" != \"%s\" (at %p).\n", x.c_str(), (wchar_t*)*ptr, ptr); break;
+ }
+ (*ptr) += stringLen;
+ }
+
template<class T>
void DoArray(T *x, int count) {
DoVoid((void *)x, sizeof(T) * count);
@@ -170,6 +184,17 @@ public:
// TODO
PanicAlert("Do(linked list<>) does not yet work.");
}
+
+ void DoMarker(const char* prevName, u32 arbitraryNumber=0x42)
+ {
+ u32 cookie = arbitraryNumber;
+ Do(cookie);
+ if(mode == PointerWrap::MODE_READ && cookie != arbitraryNumber)
+ {
+ PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", prevName, cookie, cookie, arbitraryNumber, arbitraryNumber);
+ mode = PointerWrap::MODE_MEASURE;
+ }
+ }
};
diff --git a/Source/Core/Common/Src/Common.h b/Source/Core/Common/Src/Common.h
index bc9b4dc051..db889f7ddf 100644
--- a/Source/Core/Common/Src/Common.h
+++ b/Source/Core/Common/Src/Common.h
@@ -89,6 +89,8 @@ private:
// Since it is always around on windows
#define HAVE_WX 1
+ #define HAVE_PORTAUDIO 1
+
// Debug definitions
#if defined(_DEBUG)
#include <crtdbg.h>
@@ -137,14 +139,18 @@ private:
// wxWidgets does not have a true dummy macro for this.
#define _trans(a) a
-#if defined __APPLE__ && defined __i386__
-#define _M_SSE 0x300
-#elif defined __APPLE__ && defined __x86_64__
-#define _M_SSE 0x301
-#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
-#define _M_SSE 0x301
-#elif _MSC_VER >= 1500 // Visual Studio 2008
-#define _M_SSE 0x402
+#if defined __GNUC__
+# if defined __SSE4_2__
+# define _M_SSE 0x402
+# elif defined __SSE4_1__
+# define _M_SSE 0x401
+# elif defined __SSSE3__
+# define _M_SSE 0x301
+# elif defined __SSE3__
+# define _M_SSE 0x300
+# endif
+#elif (_MSC_VER >= 1500) || __INTEL_COMPILER // Visual Studio 2008
+# define _M_SSE 0x402
#endif
// Host communication.
diff --git a/Source/Core/Common/Src/CommonFuncs.h b/Source/Core/Common/Src/CommonFuncs.h
index 7dd156f42e..74d317d95f 100644
--- a/Source/Core/Common/Src/CommonFuncs.h
+++ b/Source/Core/Common/Src/CommonFuncs.h
@@ -27,6 +27,13 @@
template <bool> struct CompileTimeAssert;
template<> struct CompileTimeAssert<true> {};
+#define b2(x) ( (x) | ( (x) >> 1) )
+#define b4(x) ( b2(x) | ( b2(x) >> 2) )
+#define b8(x) ( b4(x) | ( b4(x) >> 4) )
+#define b16(x) ( b8(x) | ( b8(x) >> 8) )
+#define b32(x) (b16(x) | (b16(x) >>16) )
+#define ROUND_UP_POW2(x) (b32(x - 1) + 1)
+
#if defined __GNUC__ && !defined __SSSE3__
#include <emmintrin.h>
static __inline __m128i __attribute__((__always_inline__))
@@ -45,6 +52,8 @@ _mm_shuffle_epi8(__m128i a, __m128i mask)
#include <errno.h>
#ifdef __linux__
#include <byteswap.h>
+#elif defined __FreeBSD__
+#include <sys/endian.h>
#endif
// go to debugger mode
@@ -137,6 +146,10 @@ inline __attribute__((always_inline)) u32 swap32(u32 _data)
{return __builtin_bswap32(_data);}
inline __attribute__((always_inline)) u64 swap64(u64 _data)
{return __builtin_bswap64(_data);}
+#elif __FreeBSD__
+inline u16 swap16(u16 _data) {return bswap16(_data);}
+inline u32 swap32(u32 _data) {return bswap32(_data);}
+inline u64 swap64(u64 _data) {return bswap64(_data);}
#else
// Slow generic implementation.
inline u16 swap16(u16 data) {return (data >> 8) | (data << 8);}
diff --git a/Source/Core/Common/Src/CommonPaths.h b/Source/Core/Common/Src/CommonPaths.h
index 8d37482ce1..d319fb541e 100644
--- a/Source/Core/Common/Src/CommonPaths.h
+++ b/Source/Core/Common/Src/CommonPaths.h
@@ -126,6 +126,8 @@
#define WII_USA_SETTING "setting-usa.txt"
#define WII_JAP_SETTING "setting-jpn.txt"
+#define GECKO_CODE_HANDLER "codehandler.bin"
+
// Subdirs in Sys
#define GC_SYS_DIR "GC"
#define WII_SYS_DIR "Wii"
diff --git a/Source/Core/Common/Src/Hash.cpp b/Source/Core/Common/Src/Hash.cpp
index 62ea25519e..8e8d6f85bd 100644
--- a/Source/Core/Common/Src/Hash.cpp
+++ b/Source/Core/Common/Src/Hash.cpp
@@ -167,7 +167,7 @@ u64 GetMurmurHash3(const u8 *src, int len, u32 samples)
const u8 * data = (const u8*)src;
const int nblocks = len / 16;
u32 Step = (len / 8);
- if(samples == 0) samples = Step;
+ if(samples == 0) samples = max(Step, 1u);
Step = Step / samples;
if(Step < 1) Step = 1;
@@ -245,7 +245,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples)
u32 Step = (len / 8);
const u64 *data = (const u64 *)src;
const u64 *end = data + Step;
- if(samples == 0) samples = Step;
+ if(samples == 0) samples = max(Step, 1u);
Step = Step / samples;
if(Step < 1) Step = 1;
while(data < end)
@@ -275,7 +275,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
u32 Step = (len / 8);
const u64 *data = (const u64 *)src;
const u64 *end = data + Step;
- if(samples == 0) samples = Step;
+ if(samples == 0) samples = max(Step, 1u);
Step = Step / samples;
if(Step < 1) Step = 1;
while(data < end)
@@ -318,7 +318,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples)
u32 Step = (len/4);
const u32 *data = (const u32 *)src;
const u32 *end = data + Step;
- if(samples == 0) samples = Step;
+ if(samples == 0) samples = max(Step, 1u);
Step = Step / samples;
if(Step < 1) Step = 1;
while(data < end)
@@ -390,7 +390,7 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples)
u32 out[2];
const int nblocks = len / 8;
u32 Step = (len / 4);
- if(samples == 0) samples = Step;
+ if(samples == 0) samples = max(Step, 1u);
Step = Step / samples;
if(Step < 1) Step = 1;
@@ -464,7 +464,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
u32 Step = (len / 8);
const u64 *data = (const u64 *)src;
const u64 *end = data + Step;
- if(samples == 0) samples = Step;
+ if(samples == 0) samples = max(Step, 1u);
Step = Step / samples;
if(Step < 1) Step = 1;
while(data < end)
diff --git a/Source/Core/Common/Src/IniFile.cpp b/Source/Core/Common/Src/IniFile.cpp
index c81c060f1d..acad498106 100644
--- a/Source/Core/Common/Src/IniFile.cpp
+++ b/Source/Core/Common/Src/IniFile.cpp
@@ -459,7 +459,11 @@ bool IniFile::Save(const char* filename)
return false;
}
- for (std::vector<Section>::const_iterator iter = sections.begin(); iter != sections.end(); ++iter)
+ // Currently testing if dolphin community can handle the requirements of C++11 compilation
+ // If you get a compiler error on this line, your compiler is probably old.
+ // Update to g++ 4.4 or a recent version of clang (XCode 4.2 on OS X).
+ // If you don't want to update, complain in a google code issue, the dolphin forums or #dolphin-emu.
+ for (auto iter = sections.begin(); iter != sections.end(); ++iter)
{
const Section& section = *iter;
diff --git a/Source/Core/Common/Src/LinearDiskCache.h b/Source/Core/Common/Src/LinearDiskCache.h
index 7a124aaa7b..f6e0d95f8c 100644
--- a/Source/Core/Common/Src/LinearDiskCache.h
+++ b/Source/Core/Common/Src/LinearDiskCache.h
@@ -21,12 +21,10 @@
#include "Common.h"
#include <fstream>
-// Update this to the current SVN revision every time you change shader generation code.
-// We don't automatically get this from SVN_REV because that would mean regenerating the
-// shader cache for every revision, graphics-related or not, which is simply annoying.
+// Increment this every time you change shader generation code.
enum
{
- LINEAR_DISKCACHE_VER = 6964
+ LINEAR_DISKCACHE_VER = 6972
};
// On disk format:
@@ -73,36 +71,58 @@ public:
// close any currently opened file
Close();
+ m_num_entries = 0;
// try opening for reading/writing
- m_file.open(filename, ios_base::in | ios_base::out | ios_base::binary | ios_base::app);
+ m_file.open(filename, ios_base::in | ios_base::out | ios_base::binary);
+
+ m_file.seekg(0, std::ios::end);
+ std::fstream::pos_type end_pos = m_file.tellg();
+ m_file.seekg(0, std::ios::beg);
+ std::fstream::pos_type start_pos = m_file.tellg();
+ std::streamoff file_size = end_pos - start_pos;
if (m_file.is_open() && ValidateHeader())
{
// good header, read some key/value pairs
- u32 num_entries = 0;
K key;
V *value = NULL;
u32 value_size;
+ u32 entry_number;
+
+ std::fstream::pos_type last_pos = m_file.tellg();
while (Read(&value_size))
{
+ std::streamoff next_extent = (last_pos - start_pos) + sizeof(value_size) + value_size;
+ if (next_extent > file_size)
+ break;
+
delete[] value;
value = new V[value_size];
// read key/value and pass to reader
- if (Read(&key) && Read(value, value_size))
+ if (Read(&key) &&
+ Read(value, value_size) &&
+ Read(&entry_number) &&
+ entry_number == m_num_entries+1)
+ {
reader.Read(key, value, value_size);
+ }
else
+ {
break;
+ }
- ++num_entries;
+ m_num_entries++;
+ last_pos = m_file.tellg();
}
+ m_file.seekp(last_pos);
m_file.clear();
delete[] value;
- return num_entries;
+ return m_num_entries;
}
// failed to open file for reading or bad header
@@ -129,10 +149,12 @@ public:
// Appends a key-value pair to the store.
void Append(const K &key, const V *value, u32 value_size)
{
- // TODO: Should do a check that we don't already have "key"?
+ // TODO: Should do a check that we don't already have "key"? (I think each caller does that already.)
Write(&value_size);
Write(&key);
Write(value, value_size);
+ m_num_entries++;
+ Write(&m_num_entries);
}
private:
@@ -176,6 +198,7 @@ private:
} m_header;
std::fstream m_file;
+ u32 m_num_entries;
};
#endif // _LINEAR_DISKCACHE
diff --git a/Source/Core/Common/Src/LogManager.cpp b/Source/Core/Common/Src/LogManager.cpp
index d95e76ac5b..a79c413cf8 100644
--- a/Source/Core/Common/Src/LogManager.cpp
+++ b/Source/Core/Common/Src/LogManager.cpp
@@ -85,12 +85,17 @@ LogManager::LogManager()
m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX).c_str());
m_consoleLog = new ConsoleListener();
+ m_debuggerLog = new DebuggerLogListener();
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
{
m_Log[i]->SetEnable(true);
m_Log[i]->AddListener(m_fileLog);
m_Log[i]->AddListener(m_consoleLog);
+#ifdef _MSC_VER
+ if (IsDebuggerPresent())
+ m_Log[i]->AddListener(m_debuggerLog);
+#endif
}
}
@@ -100,6 +105,7 @@ LogManager::~LogManager()
{
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog);
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog);
+ m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_debuggerLog);
}
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
@@ -187,3 +193,10 @@ void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
std::lock_guard<std::mutex> lk(m_log_lock);
m_logfile << msg << std::flush;
}
+
+void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
+{
+#if _MSC_VER
+ ::OutputDebugStringA(msg);
+#endif
+}
diff --git a/Source/Core/Common/Src/LogManager.h b/Source/Core/Common/Src/LogManager.h
index 3f2b5cd168..1722c0b1bf 100644
--- a/Source/Core/Common/Src/LogManager.h
+++ b/Source/Core/Common/Src/LogManager.h
@@ -58,6 +58,12 @@ private:
bool m_enable;
};
+class DebuggerLogListener : public LogListener
+{
+public:
+ void Log(LogTypes::LOG_LEVELS, const char *msg);
+};
+
class LogContainer
{
public:
@@ -97,6 +103,7 @@ private:
LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS];
FileLogListener *m_fileLog;
ConsoleListener *m_consoleLog;
+ DebuggerLogListener *m_debuggerLog;
static LogManager *m_logManager; // Singleton. Ugh.
LogManager();
@@ -153,6 +160,11 @@ public:
return m_consoleLog;
}
+ DebuggerLogListener *GetDebuggerListener() const
+ {
+ return m_debuggerLog;
+ }
+
static LogManager* GetInstance()
{
return m_logManager;
diff --git a/Source/Core/Common/Src/MemoryUtil.cpp b/Source/Core/Common/Src/MemoryUtil.cpp
index bc65f856f4..3e3cafa335 100644
--- a/Source/Core/Common/Src/MemoryUtil.cpp
+++ b/Source/Core/Common/Src/MemoryUtil.cpp
@@ -27,28 +27,65 @@
#include <stdio.h>
#endif
+#if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT)
+#include <unistd.h>
+#define PAGE_MASK (getpagesize() - 1)
+#define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK))
+#endif
+
// This is purposely not a full wrapper for virtualalloc/mmap, but it
// provides exactly the primitive operations that Dolphin needs.
void* AllocateExecutableMemory(size_t size, bool low)
{
-#ifdef _WIN32
- void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+#if defined(_WIN32)
+ void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#else
- void* ptr = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC,
+ static char *map_hint = 0;
+#if defined(__x86_64__) && !defined(MAP_32BIT)
+ // This OS has no flag to enforce allocation below the 4 GB boundary,
+ // but if we hint that we want a low address it is very likely we will
+ // get one.
+ // An older version of this code used MAP_FIXED, but that has the side
+ // effect of discarding already mapped pages that happen to be in the
+ // requested virtual memory range (such as the emulated RAM, sometimes).
+ if (low && (!map_hint))
+ map_hint = (char*)round_page(512*1024*1024); /* 0.5 GB rounded up to the next page */
+#endif
+ void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE
-#if defined __linux__ && defined __x86_64__
+#if defined(__x86_64__) && defined(MAP_32BIT)
| (low ? MAP_32BIT : 0)
#endif
, -1, 0);
-#endif
+#endif /* defined(_WIN32) */
// printf("Mapped executable memory at %p (size %ld)\n", ptr,
// (unsigned long)size);
+#if defined(__FreeBSD__)
+ if (ptr == MAP_FAILED)
+ {
+ ptr = NULL;
+#else
if (ptr == NULL)
+ {
+#endif
PanicAlert("Failed to allocate executable memory");
-#ifdef _M_X64
+ }
+#if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT)
+ else
+ {
+ if (low)
+ {
+ map_hint += size;
+ map_hint = (char*)round_page(map_hint); /* round up to the next page */
+ // printf("Next map will (hopefully) be at %p\n", map_hint);
+ }
+ }
+#endif
+
+#if defined(_M_X64)
if ((u64)ptr >= 0x80000000 && low == true)
PanicAlert("Executable memory ended up above 2GB!");
#endif
diff --git a/Source/Core/Common/Src/MsgHandler.cpp b/Source/Core/Common/Src/MsgHandler.cpp
index 3f68e1d29a..7c666227aa 100644
--- a/Source/Core/Common/Src/MsgHandler.cpp
+++ b/Source/Core/Common/Src/MsgHandler.cpp
@@ -86,7 +86,7 @@ bool MsgAlert(bool yes_no, int Style, const char* format, ...)
va_list args;
va_start(args, format);
- CharArrayFromFormatV(buffer, 2047, str_translator(format).c_str(), args);
+ CharArrayFromFormatV(buffer, sizeof(buffer)-1, str_translator(format).c_str(), args);
va_end(args);
ERROR_LOG(MASTER_LOG, "%s: %s", caption.c_str(), buffer);
diff --git a/Source/Core/Common/Src/StdThread.h b/Source/Core/Common/Src/StdThread.h
index 6e9e903561..b64dbf2c4e 100644
--- a/Source/Core/Common/Src/StdThread.h
+++ b/Source/Core/Common/Src/StdThread.h
@@ -7,7 +7,9 @@
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
// GCC 4.4 provides <thread>
+#ifndef _GLIBCXX_USE_SCHED_YIELD
#define _GLIBCXX_USE_SCHED_YIELD
+#endif
#include <thread>
#else
diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp
index 18a3575086..664987d350 100644
--- a/Source/Core/Common/Src/StringUtil.cpp
+++ b/Source/Core/Common/Src/StringUtil.cpp
@@ -125,15 +125,26 @@ std::string StripQuotes(const std::string& s)
bool TryParse(const std::string &str, u32 *const output)
{
char *endptr = NULL;
- u32 value = strtoul(str.c_str(), &endptr, 0);
+
+ // Reset errno to a value other than ERANGE
+ errno = 0;
+
+ unsigned long value = strtoul(str.c_str(), &endptr, 0);
if (!endptr || *endptr)
return false;
- if (value == ULONG_MAX && errno == ERANGE)
+ if (errno == ERANGE)
return false;
- *output = value;
+ if (ULONG_MAX > UINT_MAX) {
+ // Note: The typecasts avoid GCC warnings when long is 32 bits wide.
+ if (value >= static_cast<unsigned long>(0x100000000ull)
+ && value <= static_cast<unsigned long>(0xFFFFFFFF00000000ull))
+ return false;
+ }
+
+ *output = static_cast<u32>(value);
return true;
}
diff --git a/Source/Core/Common/Src/SysConf.cpp b/Source/Core/Common/Src/SysConf.cpp
index ed8a4953e5..97170e5ff1 100644
--- a/Source/Core/Common/Src/SysConf.cpp
+++ b/Source/Core/Common/Src/SysConf.cpp
@@ -387,7 +387,7 @@ bool SysConf::SaveToFile(const char *filename)
}
else if (i->type == Type_SmallArray)
{
- const u8 len = i->dataLength;
+ const u8 len = (u8)(i->dataLength);
f.WriteArray(&len, 1);
}
diff --git a/Source/Core/Common/Src/SysConf.h b/Source/Core/Common/Src/SysConf.h
index 119cc3c45a..fb9c775828 100644
--- a/Source/Core/Common/Src/SysConf.h
+++ b/Source/Core/Common/Src/SysConf.h
@@ -66,10 +66,9 @@ struct SSysConfEntry
}
bool SetArrayData(u8* buffer, u16 bufferSize)
{
-
- if (buffer && bufferSize <= dataLength)
+ if (buffer)
{
- memcpy(data, buffer, bufferSize);
+ memcpy(data, buffer, min<u16>(bufferSize, dataLength));
return true;
}
return false;
diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h
index ba713ed64c..e711fcab5c 100644
--- a/Source/Core/Common/Src/Thread.h
+++ b/Source/Core/Common/Src/Thread.h
@@ -72,6 +72,13 @@ public:
is_set = false;
}
+ void Reset()
+ {
+ std::unique_lock<std::mutex> lk(m_mutex);
+ // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration
+ is_set = false;
+ }
+
private:
class IsSet
{
diff --git a/Source/Core/Common/Src/Version.cpp b/Source/Core/Common/Src/Version.cpp
index f3d30398c8..97e232785d 100644
--- a/Source/Core/Common/Src/Version.cpp
+++ b/Source/Core/Common/Src/Version.cpp
@@ -30,7 +30,12 @@ const char *scm_rev_str = "Dolphin "
#if !SCM_IS_MASTER
"[" SCM_BRANCH_STR "] "
#endif
+
+#ifdef __INTEL_COMPILER
+ BUILD_TYPE_STR SCM_DESC_STR "-ICC";
+#else
BUILD_TYPE_STR SCM_DESC_STR;
+#endif
#ifdef _M_X64
#define NP_ARCH "x64"
diff --git a/Source/Core/Common/Src/VideoBackendBase.h b/Source/Core/Common/Src/VideoBackendBase.h
index 667a3d3a32..96f639832b 100644
--- a/Source/Core/Common/Src/VideoBackendBase.h
+++ b/Source/Core/Common/Src/VideoBackendBase.h
@@ -119,6 +119,7 @@ public:
virtual void Video_GatherPipeBursted() = 0;
virtual bool Video_IsPossibleWaitingSetDrawDone() = 0;
+ virtual bool Video_IsHiWatermarkActive() = 0;
virtual void Video_AbortFrame() = 0;
virtual readFn16 Video_CPRead16() = 0;
@@ -140,6 +141,7 @@ class VideoBackendHardware : public VideoBackend
{
void DoState(PointerWrap &p);
void RunLoop(bool enable);
+ bool Initialize(void *&) { InitializeShared(); return true; }
void EmuStateChange(EMUSTATE_CHANGE);
@@ -158,6 +160,7 @@ class VideoBackendHardware : public VideoBackend
void Video_GatherPipeBursted();
bool Video_IsPossibleWaitingSetDrawDone();
+ bool Video_IsHiWatermarkActive();
void Video_AbortFrame();
readFn16 Video_CPRead16();
@@ -165,6 +168,9 @@ class VideoBackendHardware : public VideoBackend
readFn16 Video_PERead16();
writeFn16 Video_PEWrite16();
writeFn32 Video_PEWrite32();
+
+protected:
+ void InitializeShared();
};
#endif
diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp
index 9acfac5864..00c58a0fbc 100644
--- a/Source/Core/Common/Src/x64Emitter.cpp
+++ b/Source/Core/Common/Src/x64Emitter.cpp
@@ -834,6 +834,102 @@ void XEmitter::SHL(int bits, OpArg dest, OpArg shift) {WriteShift(bits, dest, sh
void XEmitter::SHR(int bits, OpArg dest, OpArg shift) {WriteShift(bits, dest, shift, 5);}
void XEmitter::SAR(int bits, OpArg dest, OpArg shift) {WriteShift(bits, dest, shift, 7);}
+// index can be either imm8 or register, don't use memory destination because it's slow
+void XEmitter::WriteBitTest(int bits, OpArg &dest, OpArg &index, int ext)
+{
+ if (dest.IsImm())
+ {
+ _assert_msg_(DYNA_REC, 0, "WriteBitTest - can't test imms");
+ }
+ if ((index.IsImm() && index.GetImmBits() != 8))
+ {
+ _assert_msg_(DYNA_REC, 0, "WriteBitTest - illegal argument");
+ }
+ if (bits == 16) Write8(0x66);
+ if (index.IsImm())
+ {
+ dest.WriteRex(this, bits, bits);
+ Write8(0x0F); Write8(0xBA);
+ dest.WriteRest(this, 1, (X64Reg)ext);
+ Write8((u8)index.offset);
+ }
+ else
+ {
+ X64Reg operand = index.GetSimpleReg();
+ dest.WriteRex(this, bits, bits, operand);
+ Write8(0x0F); Write8(0x83 + 8*ext);
+ dest.WriteRest(this, 1, operand);
+ }
+}
+
+void XEmitter::BT(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 4);}
+void XEmitter::BTS(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 5);}
+void XEmitter::BTR(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 6);}
+void XEmitter::BTC(int bits, OpArg dest, OpArg index) {WriteBitTest(bits, dest, index, 7);}
+
+//shift can be either imm8 or cl
+void XEmitter::SHRD(int bits, OpArg dest, OpArg src, OpArg shift)
+{
+ bool writeImm = false;
+ if (dest.IsImm())
+ {
+ _assert_msg_(DYNA_REC, 0, "SHRD - can't use imms as destination");
+ }
+ if (!src.IsSimpleReg())
+ {
+ _assert_msg_(DYNA_REC, 0, "SHRD - must use simple register as source");
+ }
+ if ((shift.IsSimpleReg() && shift.GetSimpleReg() != ECX) || (shift.IsImm() && shift.GetImmBits() != 8))
+ {
+ _assert_msg_(DYNA_REC, 0, "SHRD - illegal shift");
+ }
+ if (bits == 16) Write8(0x66);
+ X64Reg operand = src.GetSimpleReg();
+ dest.WriteRex(this, bits, bits, operand);
+ if (shift.GetImmBits() == 8)
+ {
+ Write8(0x0F); Write8(0xAC);
+ dest.WriteRest(this, 1, operand);
+ Write8((u8)shift.offset);
+ }
+ else
+ {
+ Write8(0x0F); Write8(0xAD);
+ dest.WriteRest(this, 0, operand);
+ }
+}
+
+void XEmitter::SHLD(int bits, OpArg dest, OpArg src, OpArg shift)
+{
+ bool writeImm = false;
+ if (dest.IsImm())
+ {
+ _assert_msg_(DYNA_REC, 0, "SHLD - can't use imms as destination");
+ }
+ if (!src.IsSimpleReg())
+ {
+ _assert_msg_(DYNA_REC, 0, "SHLD - must use simple register as source");
+ }
+ if ((shift.IsSimpleReg() && shift.GetSimpleReg() != ECX) || (shift.IsImm() && shift.GetImmBits() != 8))
+ {
+ _assert_msg_(DYNA_REC, 0, "SHLD - illegal shift");
+ }
+ if (bits == 16) Write8(0x66);
+ X64Reg operand = src.GetSimpleReg();
+ dest.WriteRex(this, bits, bits, operand);
+ if (shift.GetImmBits() == 8)
+ {
+ Write8(0x0F); Write8(0xA4);
+ dest.WriteRest(this, 1, operand);
+ Write8((u8)shift.offset);
+ }
+ else
+ {
+ Write8(0x0F); Write8(0xA5);
+ dest.WriteRest(this, 0, operand);
+ }
+}
+
void OpArg::WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg _operandReg, int bits)
{
if (bits == 16)
diff --git a/Source/Core/Common/Src/x64Emitter.h b/Source/Core/Common/Src/x64Emitter.h
index 9ffb890f54..3b699c81a0 100644
--- a/Source/Core/Common/Src/x64Emitter.h
+++ b/Source/Core/Common/Src/x64Emitter.h
@@ -249,6 +249,7 @@ private:
void WriteMulDivType(int bits, OpArg src, int ext);
void WriteBitSearchType(int bits, X64Reg dest, OpArg src, u8 byte2);
void WriteShift(int bits, OpArg dest, OpArg &shift, int ext);
+ void WriteBitTest(int bits, OpArg &dest, OpArg &index, int ext);
void WriteMXCSR(OpArg arg, int ext);
void WriteSSEOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes = 0);
void WriteNormalOp(XEmitter *emit, int bits, NormalOp op, const OpArg &a1, const OpArg &a2);
@@ -374,6 +375,16 @@ public:
void SHR(int bits, OpArg dest, OpArg shift);
void SAR(int bits, OpArg dest, OpArg shift);
+ // Bit Test
+ void BT(int bits, OpArg dest, OpArg index);
+ void BTS(int bits, OpArg dest, OpArg index);
+ void BTR(int bits, OpArg dest, OpArg index);
+ void BTC(int bits, OpArg dest, OpArg index);
+
+ // Double-Precision Shift
+ void SHRD(int bits, OpArg dest, OpArg src, OpArg shift);
+ void SHLD(int bits, OpArg dest, OpArg src, OpArg shift);
+
// Extend EAX into EDX in various ways
void CWD(int bits = 16);
inline void CDQ() {CWD(32);}