diff options
| author | Pierre Bourdon <delroth@gmail.com> | 2012-03-22 15:21:52 +0100 |
|---|---|---|
| committer | Pierre Bourdon <delroth@gmail.com> | 2012-03-22 15:21:52 +0100 |
| commit | 0ffc12bbfd6ac44b3030ec30f400a58e951087b7 (patch) | |
| tree | 53a6fac9ec79bcd71fe2046d8fb579478da12fd2 /Source/Core/Common | |
| parent | 006923e871e496a7c6c0fe9ba76da4ee939ce14e (diff) | |
| parent | d95e31af3f779bfa3141047e8b6275e1fd2e4bbb (diff) | |
Merge branch 'master' into zcomploc-support
Conflicts:
Source/Core/VideoCommon/Src/PixelShaderGen.cpp
Diffstat (limited to 'Source/Core/Common')
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);} |
