summaryrefslogtreecommitdiff
path: root/Source/Core/Common
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/Common')
-rw-r--r--Source/Core/Common/CMakeLists.txt23
-rw-r--r--Source/Core/Common/Common.vcxproj13
-rw-r--r--Source/Core/Common/Common.vcxproj.filters9
-rw-r--r--Source/Core/Common/Src/ArmCPUDetect.cpp167
-rw-r--r--Source/Core/Common/Src/ArmEmitter.cpp1110
-rw-r--r--Source/Core/Common/Src/ArmEmitter.h637
-rw-r--r--Source/Core/Common/Src/BreakPoints.h8
-rw-r--r--Source/Core/Common/Src/CDUtils.cpp11
-rw-r--r--Source/Core/Common/Src/CPUDetect.h29
-rw-r--r--Source/Core/Common/Src/ChunkFile.h242
-rw-r--r--Source/Core/Common/Src/Common.h7
-rw-r--r--Source/Core/Common/Src/CommonFuncs.h59
-rw-r--r--Source/Core/Common/Src/CommonPaths.h9
-rw-r--r--Source/Core/Common/Src/ConsoleListener.cpp12
-rw-r--r--Source/Core/Common/Src/Crypto/md5.cpp9
-rw-r--r--Source/Core/Common/Src/Crypto/sha1.cpp9
-rw-r--r--Source/Core/Common/Src/ExtendedTrace.cpp52
-rw-r--r--Source/Core/Common/Src/ExtendedTrace.h19
-rw-r--r--Source/Core/Common/Src/FPURoundMode.h52
-rw-r--r--Source/Core/Common/Src/FileSearch.cpp5
-rw-r--r--Source/Core/Common/Src/FileUtil.cpp95
-rw-r--r--Source/Core/Common/Src/FileUtil.h12
-rw-r--r--Source/Core/Common/Src/GenericFPURoundMode.cpp41
-rw-r--r--Source/Core/Common/Src/Hash.cpp172
-rw-r--r--Source/Core/Common/Src/IniFile.cpp5
-rw-r--r--Source/Core/Common/Src/LinearDiskCache.h17
-rw-r--r--Source/Core/Common/Src/LogManager.cpp29
-rw-r--r--Source/Core/Common/Src/LogManager.h2
-rw-r--r--Source/Core/Common/Src/MathUtil.cpp148
-rw-r--r--Source/Core/Common/Src/MathUtil.h66
-rw-r--r--Source/Core/Common/Src/MemArena.cpp34
-rw-r--r--Source/Core/Common/Src/MemoryUtil.cpp9
-rw-r--r--Source/Core/Common/Src/Misc.cpp2
-rw-r--r--Source/Core/Common/Src/MsgHandler.cpp15
-rw-r--r--Source/Core/Common/Src/NandPaths.cpp6
-rw-r--r--Source/Core/Common/Src/SDCardUtil.cpp7
-rw-r--r--Source/Core/Common/Src/StdConditionVariable.h4
-rw-r--r--Source/Core/Common/Src/StdMutex.h2
-rw-r--r--Source/Core/Common/Src/StdThread.h4
-rw-r--r--Source/Core/Common/Src/StringUtil.cpp186
-rw-r--r--Source/Core/Common/Src/StringUtil.h24
-rw-r--r--Source/Core/Common/Src/Thread.cpp2
-rw-r--r--Source/Core/Common/Src/Thread.h4
-rw-r--r--Source/Core/Common/Src/Version.cpp2
-rw-r--r--Source/Core/Common/Src/VideoBackendBase.cpp25
-rw-r--r--Source/Core/Common/Src/VideoBackendBase.h8
-rw-r--r--Source/Core/Common/Src/x64ABI.cpp (renamed from Source/Core/Common/Src/ABI.cpp)98
-rw-r--r--Source/Core/Common/Src/x64ABI.h (renamed from Source/Core/Common/Src/ABI.h)0
-rw-r--r--Source/Core/Common/Src/x64Analyzer.cpp42
-rw-r--r--Source/Core/Common/Src/x64Analyzer.h2
-rw-r--r--Source/Core/Common/Src/x64CPUDetect.cpp (renamed from Source/Core/Common/Src/CPUDetect.cpp)8
-rw-r--r--Source/Core/Common/Src/x64Emitter.cpp218
-rw-r--r--Source/Core/Common/Src/x64Emitter.h4
-rw-r--r--Source/Core/Common/Src/x64FPURoundMode.cpp120
-rw-r--r--Source/Core/Common/Src/x64Thunk.cpp (renamed from Source/Core/Common/Src/Thunk.cpp)3
55 files changed, 3175 insertions, 723 deletions
diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt
index 122f681085..361337e421 100644
--- a/Source/Core/Common/CMakeLists.txt
+++ b/Source/Core/Common/CMakeLists.txt
@@ -1,9 +1,7 @@
-set(SRCS Src/ABI.cpp
- Src/BreakPoints.cpp
+set(SRCS Src/BreakPoints.cpp
Src/CDUtils.cpp
Src/ColorUtil.cpp
Src/ConsoleListener.cpp
- Src/CPUDetect.cpp
Src/FileSearch.cpp
Src/FileUtil.cpp
Src/Hash.cpp
@@ -21,10 +19,10 @@ set(SRCS Src/ABI.cpp
Src/SymbolDB.cpp
Src/SysConf.cpp
Src/Thread.cpp
- Src/Thunk.cpp
Src/Timer.cpp
Src/Version.cpp
Src/VideoBackendBase.cpp
+ Src/x64ABI.cpp
Src/x64Analyzer.cpp
Src/x64Emitter.cpp
Src/Crypto/aes_cbc.cpp
@@ -34,6 +32,23 @@ set(SRCS Src/ABI.cpp
Src/Crypto/md5.cpp
Src/Crypto/sha1.cpp)
+if(_M_ARM) #ARM
+ set(SRCS ${SRCS}
+ Src/ArmCPUDetect.cpp
+ Src/ArmEmitter.cpp)
+else()
+ if(NOT _M_GENERIC) #X86
+ set(SRCS ${SRCS}
+ Src/x64FPURoundMode.cpp
+ Src/x64Thunk.cpp
+ )
+ endif()
+ set(SRCS ${SRCS} Src/x64CPUDetect.cpp)
+endif()
+if(_M_GENERIC) #Generic
+ set(SRCS ${SRCS}
+ Src/GenericFPURoundMode.cpp)
+endif()
if(WIN32)
set(SRCS ${SRCS} Src/ExtendedTrace.cpp)
endif(WIN32)
diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj
index 626204f344..373d274907 100644
--- a/Source/Core/Common/Common.vcxproj
+++ b/Source/Core/Common/Common.vcxproj
@@ -44,7 +44,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<ConfigurationType>StaticLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@@ -54,7 +54,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<ConfigurationType>StaticLibrary</ConfigurationType>
- <CharacterSet>MultiByte</CharacterSet>
+ <CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugFast|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
@@ -158,12 +158,10 @@
<Lib />
</ItemDefinitionGroup>
<ItemGroup>
- <ClCompile Include="Src\ABI.cpp" />
<ClCompile Include="Src\BreakPoints.cpp" />
<ClCompile Include="Src\CDUtils.cpp" />
<ClCompile Include="Src\ColorUtil.cpp" />
<ClCompile Include="Src\ConsoleListener.cpp" />
- <ClCompile Include="Src\CPUDetect.cpp" />
<ClCompile Include="Src\Crypto\aes_cbc.cpp" />
<ClCompile Include="Src\Crypto\aes_core.cpp" />
<ClCompile Include="Src\Crypto\bn.cpp" />
@@ -196,15 +194,17 @@
<ClCompile Include="Src\SymbolDB.cpp" />
<ClCompile Include="Src\SysConf.cpp" />
<ClCompile Include="Src\Thread.cpp" />
- <ClCompile Include="Src\Thunk.cpp" />
<ClCompile Include="Src\Timer.cpp" />
<ClCompile Include="Src\Version.cpp" />
<ClCompile Include="Src\VideoBackendBase.cpp" />
+ <ClCompile Include="Src\x64ABI.cpp" />
<ClCompile Include="Src\x64Analyzer.cpp" />
+ <ClCompile Include="Src\x64CPUDetect.cpp" />
<ClCompile Include="Src\x64Emitter.cpp" />
+ <ClCompile Include="Src\x64FPURoundMode.cpp" />
+ <ClCompile Include="Src\x64Thunk.cpp" />
</ItemGroup>
<ItemGroup>
- <ClInclude Include="Src\ABI.h" />
<ClInclude Include="Src\Atomic.h" />
<ClInclude Include="Src\Atomic_GCC.h" />
<ClInclude Include="Src\Atomic_Win32.h" />
@@ -253,6 +253,7 @@
<ClInclude Include="Src\Thunk.h" />
<ClInclude Include="Src\Timer.h" />
<ClInclude Include="Src\VideoBackendBase.h" />
+ <ClInclude Include="Src\x64ABI.h" />
<ClInclude Include="Src\x64Analyzer.h" />
<ClInclude Include="Src\x64Emitter.h" />
</ItemGroup>
diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters
index 6ae75788ce..26f66b850a 100644
--- a/Source/Core/Common/Common.vcxproj.filters
+++ b/Source/Core/Common/Common.vcxproj.filters
@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
- <ClCompile Include="Src\ABI.cpp" />
<ClCompile Include="Src\BreakPoints.cpp" />
<ClCompile Include="Src\CDUtils.cpp" />
<ClCompile Include="Src\ColorUtil.cpp" />
- <ClCompile Include="Src\CPUDetect.cpp" />
<ClCompile Include="Src\ExtendedTrace.cpp" />
<ClCompile Include="Src\FileSearch.cpp" />
<ClCompile Include="Src\FileUtil.cpp" />
@@ -23,7 +21,6 @@
<ClCompile Include="Src\SymbolDB.cpp" />
<ClCompile Include="Src\SysConf.cpp" />
<ClCompile Include="Src\Thread.cpp" />
- <ClCompile Include="Src\Thunk.cpp" />
<ClCompile Include="Src\Timer.cpp" />
<ClCompile Include="Src\Version.cpp" />
<ClCompile Include="Src\VideoBackendBase.cpp" />
@@ -54,9 +51,12 @@
<Filter>Crypto</Filter>
</ClCompile>
<ClCompile Include="Src\SettingsHandler.cpp" />
+ <ClCompile Include="Src\x64ABI.cpp" />
+ <ClCompile Include="Src\x64CPUDetect.cpp" />
+ <ClCompile Include="Src\x64FPURoundMode.cpp" />
+ <ClCompile Include="Src\x64Thunk.cpp" />
</ItemGroup>
<ItemGroup>
- <ClInclude Include="Src\ABI.h" />
<ClInclude Include="Src\Atomic.h" />
<ClInclude Include="Src\Atomic_GCC.h" />
<ClInclude Include="Src\Atomic_Win32.h" />
@@ -123,6 +123,7 @@
<ClInclude Include="Src\StdMutex.h" />
<ClInclude Include="Src\StdConditionVariable.h" />
<ClInclude Include="Src\SettingsHandler.h" />
+ <ClInclude Include="Src\x64ABI.h" />
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />
diff --git a/Source/Core/Common/Src/ArmCPUDetect.cpp b/Source/Core/Common/Src/ArmCPUDetect.cpp
new file mode 100644
index 0000000000..33eee9f05e
--- /dev/null
+++ b/Source/Core/Common/Src/ArmCPUDetect.cpp
@@ -0,0 +1,167 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Common.h"
+#include "CPUDetect.h"
+#include "StringUtil.h"
+#include "FileUtil.h"
+
+const char procfile[] = "/proc/cpuinfo";
+
+char *GetCPUString()
+{
+ const char marker[] = "Hardware\t: ";
+ char *cpu_string = 0;
+ // Count the number of processor lines in /proc/cpuinfo
+ char buf[1024];
+
+ File::IOFile file(procfile, "r");
+ auto const fp = file.GetHandle();
+ if (!fp)
+ return 0;
+
+ while (fgets(buf, sizeof(buf), fp))
+ {
+ if (strncmp(buf, marker, sizeof(marker) - 1))
+ continue;
+ cpu_string = buf + sizeof(marker) - 1;
+ cpu_string = strndup(cpu_string, strlen(cpu_string) - 1); // Strip the newline
+ break;
+ }
+ return cpu_string;
+}
+bool CheckCPUFeature(const char *feature)
+{
+ const char marker[] = "Features\t: ";
+ char buf[1024];
+
+ File::IOFile file(procfile, "r");
+ auto const fp = file.GetHandle();
+ if (!fp)
+ return 0;
+
+ while (fgets(buf, sizeof(buf), fp))
+ {
+ if (strncmp(buf, marker, sizeof(marker) - 1))
+ continue;
+ char *featurestring = buf + sizeof(marker) - 1;
+ char *token = strtok(featurestring, " ");
+ while (token != NULL)
+ {
+ if (strstr(token, feature))
+ return true;
+ token = strtok(NULL, " ");
+ }
+ }
+ return false;
+}
+int GetCoreCount()
+{
+ const char marker[] = "processor\t: ";
+ int cores = 0;
+ char buf[1024];
+
+ File::IOFile file(procfile, "r");
+ auto const fp = file.GetHandle();
+ if (!fp)
+ return 0;
+
+ while (fgets(buf, sizeof(buf), fp))
+ {
+ if (strncmp(buf, marker, sizeof(marker) - 1))
+ continue;
+ ++cores;
+ }
+ return cores;
+}
+
+CPUInfo cpu_info;
+
+CPUInfo::CPUInfo() {
+ Detect();
+}
+
+// Detects the various cpu features
+void CPUInfo::Detect()
+{
+ // Set some defaults here
+ // When ARMv8 cpus come out, these need to be updated.
+ HTT = false;
+ OS64bit = false;
+ CPU64bit = false;
+ Mode64bit = false;
+ vendor = VENDOR_ARM;
+
+ // Get the information about the CPU
+ strncpy(cpu_string, GetCPUString(), sizeof(cpu_string));
+ num_cores = GetCoreCount();
+ bSwp = CheckCPUFeature("swp");
+ bHalf = CheckCPUFeature("half");
+ bThumb = CheckCPUFeature("thumb");
+ bFastMult = CheckCPUFeature("fastmult");
+ bVFP = CheckCPUFeature("vfp");
+ bEDSP = CheckCPUFeature("edsp");
+ bThumbEE = CheckCPUFeature("thumbee");
+ bNEON = CheckCPUFeature("neon");
+ bVFPv3 = CheckCPUFeature("vfpv3");
+ bTLS = CheckCPUFeature("tls");
+ bVFPv4 = CheckCPUFeature("vfpv4");
+ bIDIVa = CheckCPUFeature("idiva");
+ bIDIVt = CheckCPUFeature("idivt");
+
+ // On some buggy kernels(Qualcomm) they show that they support VFPv4 but not IDIVa
+ // All VFPv4 CPUs will support IDIVa
+ if (bVFPv4)
+ bIDIVa = bIDIVt = true;
+
+ // These two are ARMv8 specific.
+ bFP = CheckCPUFeature("fp");
+ bASIMD = CheckCPUFeature("asimd");
+
+
+#if defined(__ARM_ARCH_7A__)
+ bArmV7 = true;
+#else
+ bArmV7 = false;
+#endif
+}
+
+// Turn the cpu info into a string we can show
+std::string CPUInfo::Summarize()
+{
+ std::string sum;
+ if (num_cores == 1)
+ sum = StringFromFormat("%s, %i core", cpu_string, num_cores);
+ else
+ sum = StringFromFormat("%s, %i cores", cpu_string, num_cores);
+
+ if (bSwp) sum += ", SWP";
+ if (bHalf) sum += ", Half";
+ if (bThumb) sum += ", Thumb";
+ if (bFastMult) sum += ", FastMult";
+ if (bVFP) sum += ", VFP";
+ if (bEDSP) sum += ", EDSP";
+ if (bThumbEE) sum += ", ThumbEE";
+ if (bNEON) sum += ", NEON";
+ if (bVFPv3) sum += ", VFPv3";
+ if (bTLS) sum += ", TLS";
+ if (bVFPv4) sum += ", VFPv4";
+ if (bIDIVa) sum += ", IDIVa";
+ if (bIDIVt) sum += ", IDIVt";
+
+ return sum;
+}
diff --git a/Source/Core/Common/Src/ArmEmitter.cpp b/Source/Core/Common/Src/ArmEmitter.cpp
new file mode 100644
index 0000000000..9b738be030
--- /dev/null
+++ b/Source/Core/Common/Src/ArmEmitter.cpp
@@ -0,0 +1,1110 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Common.h"
+#include "ArmEmitter.h"
+#include "CPUDetect.h"
+
+#include <assert.h>
+#include <stdarg.h>
+
+// For cache flushing on Symbian/iOS/Blackberry
+#ifdef __SYMBIAN32__
+#include <e32std.h>
+#endif
+
+#ifdef IOS
+#include <libkern/OSCacheControl.h>
+#include <sys/mman.h>
+#endif
+
+#ifdef BLACKBERRY
+#include <sys/mman.h>
+#endif
+
+namespace ArmGen
+{
+
+inline u32 RotR(u32 a, int amount) {
+ if (!amount) return a;
+ return (a >> amount) | (a << (32 - amount));
+}
+
+inline u32 RotL(u32 a, int amount) {
+ if (!amount) return a;
+ return (a << amount) | (a >> (32 - amount));
+}
+
+bool TryMakeOperand2(u32 imm, Operand2 &op2) {
+ // Just brute force it.
+ for (int i = 0; i < 16; i++) {
+ int mask = RotR(0xFF, i * 2);
+ if ((imm & mask) == imm) {
+ op2 = Operand2((u8)(RotL(imm, i * 2)), (u8)i);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse)
+{
+ if (!TryMakeOperand2(imm, op2)) {
+ *inverse = true;
+ return TryMakeOperand2(~imm, op2);
+ } else {
+ *inverse = false;
+ return true;
+ }
+}
+
+bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated)
+{
+ if (!TryMakeOperand2(imm, op2)) {
+ *negated = true;
+ return TryMakeOperand2(-imm, op2);
+ } else {
+ *negated = false;
+ return true;
+ }
+}
+
+void ARMXEmitter::MOVI2F(ARMReg dest, float val, ARMReg tempReg)
+{
+ union {float f; u32 u;} conv;
+ conv.f = val;
+ MOVI2R(tempReg, conv.u);
+ VMOV(dest, tempReg);
+ // TODO: VMOV an IMM directly if possible
+ // Otherwise, use a literal pool and VLDR directly (+- 1020)
+}
+
+void ARMXEmitter::ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch)
+{
+ Operand2 op2;
+ bool inverse;
+ if (TryMakeOperand2_AllowInverse(val, op2, &inverse)) {
+ if (!inverse) {
+ AND(rd, rs, op2);
+ } else {
+ BIC(rd, rs, op2);
+ }
+ } else {
+ MOVI2R(scratch, val);
+ AND(rd, rs, scratch);
+ }
+}
+
+void ARMXEmitter::ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch)
+{
+ Operand2 op2;
+ if (TryMakeOperand2(val, op2)) {
+ ORR(rd, rs, op2);
+ } else {
+ MOVI2R(scratch, val);
+ ORR(rd, rs, scratch);
+ }
+}
+
+void ARMXEmitter::FlushLitPool()
+{
+ for(std::vector<LiteralPool>::iterator it = currentLitPool.begin(); it != currentLitPool.end(); ++it) {
+ // Search for duplicates
+ for(std::vector<LiteralPool>::iterator old_it = currentLitPool.begin(); old_it != it; ++old_it) {
+ if ((*old_it).val == (*it).val)
+ (*it).loc = (*old_it).loc;
+ }
+
+ // Write the constant to Literal Pool
+ if (!(*it).loc)
+ {
+ (*it).loc = (s32)code;
+ Write32((*it).val);
+ }
+ s32 offset = (*it).loc - (s32)(*it).ldr_address - 8;
+
+ // Backpatch the LDR
+ *(u32*)(*it).ldr_address |= (offset >= 0) << 23 | abs(offset);
+ }
+ // TODO: Save a copy of previous pools in case they are still in range.
+ currentLitPool.clear();
+}
+
+void ARMXEmitter::AddNewLit(u32 val)
+{
+ LiteralPool pool_item;
+ pool_item.loc = 0;
+ pool_item.val = val;
+ pool_item.ldr_address = code;
+ currentLitPool.push_back(pool_item);
+}
+
+void ARMXEmitter::MOVI2R(ARMReg reg, u32 val, bool optimize)
+{
+ Operand2 op2;
+ bool inverse;
+
+ if (cpu_info.bArmV7 && !optimize)
+ {
+ // For backpatching on ARMv7
+ MOVW(reg, val & 0xFFFF);
+ MOVT(reg, val, true);
+ }
+ else if (TryMakeOperand2_AllowInverse(val, op2, &inverse)) {
+ inverse ? MVN(reg, op2) : MOV(reg, op2);
+ } else {
+ if (cpu_info.bArmV7)
+ {
+ // Use MOVW+MOVT for ARMv7+
+ MOVW(reg, val & 0xFFFF);
+ if(val & 0xFFFF0000)
+ MOVT(reg, val, true);
+ } else {
+ // Use literal pool for ARMv6.
+ AddNewLit(val);
+ LDR(reg, _PC); // To be backpatched later
+ }
+ }
+}
+
+void ARMXEmitter::QuickCallFunction(ARMReg reg, void *func) {
+ MOVI2R(reg, (u32)(func));
+ BL(reg);
+}
+
+void ARMXEmitter::SetCodePtr(u8 *ptr)
+{
+ code = ptr;
+ startcode = code;
+#ifdef IOS
+ lastCacheFlushEnd = ptr;
+#endif
+}
+
+const u8 *ARMXEmitter::GetCodePtr() const
+{
+ return code;
+}
+
+u8 *ARMXEmitter::GetWritableCodePtr()
+{
+ return code;
+}
+
+void ARMXEmitter::ReserveCodeSpace(u32 bytes)
+{
+ for (u32 i = 0; i < bytes/4; i++)
+ Write32(0xE1200070); //bkpt 0
+}
+
+const u8 *ARMXEmitter::AlignCode16()
+{
+ ReserveCodeSpace((-(s32)code) & 15);
+ return code;
+}
+
+const u8 *ARMXEmitter::AlignCodePage()
+{
+ ReserveCodeSpace((-(s32)code) & 4095);
+ return code;
+}
+
+void ARMXEmitter::FlushIcache()
+{
+ FlushIcacheSection(lastCacheFlushEnd, code);
+ lastCacheFlushEnd = code;
+}
+
+void ARMXEmitter::FlushIcacheSection(u8 *start, u8 *end)
+{
+#ifdef __SYMBIAN32__
+ User::IMB_Range(start, end);
+#elif defined(BLACKBERRY)
+ msync(start, end - start, MS_SYNC | MS_INVALIDATE_ICACHE);
+#elif defined(IOS)
+ if (start != NULL)
+ sys_cache_control(kCacheFunctionPrepareForExecution, start, end - start);
+#elif !defined(_WIN32)
+#ifndef ANDROID
+ start = startcode; // Should be Linux Only
+#endif
+ __builtin___clear_cache(start, end);
+#endif
+}
+
+void ARMXEmitter::SetCC(CCFlags cond)
+{
+ condition = cond << 28;
+}
+
+void ARMXEmitter::NOP(int count)
+{
+ for (int i = 0; i < count; i++) {
+ Write32(condition | 0x01A00000);
+ }
+}
+
+void ARMXEmitter::SETEND(bool BE)
+{
+ //SETEND is non-conditional
+ Write32( 0xF1010000 | (BE << 9));
+}
+void ARMXEmitter::BKPT(u16 arg)
+{
+ Write32(condition | 0x01200070 | (arg << 4 & 0x000FFF00) | (arg & 0x0000000F));
+}
+void ARMXEmitter::YIELD()
+{
+ Write32(condition | 0x0320F001);
+}
+
+FixupBranch ARMXEmitter::B()
+{
+ FixupBranch branch;
+ branch.type = 0; // Zero for B
+ branch.ptr = code;
+ branch.condition = condition;
+ //We'll write NOP here for now.
+ Write32(condition | 0x01A00000);
+ return branch;
+}
+FixupBranch ARMXEmitter::BL()
+{
+ FixupBranch branch;
+ branch.type = 1; // Zero for B
+ branch.ptr = code;
+ branch.condition = condition;
+ //We'll write NOP here for now.
+ Write32(condition | 0x01A00000);
+ return branch;
+}
+
+FixupBranch ARMXEmitter::B_CC(CCFlags Cond)
+{
+ FixupBranch branch;
+ branch.type = 0; // Zero for B
+ branch.ptr = code;
+ branch.condition = Cond << 28;
+ //We'll write NOP here for now.
+ Write32(condition | 0x01A00000);
+ return branch;
+}
+void ARMXEmitter::B_CC(CCFlags Cond, const void *fnptr)
+{
+ s32 distance = (s32)fnptr - (s32(code) + 8);
+ _assert_msg_(DYNA_REC, distance > -33554432
+ && distance <= 33554432,
+ "B_CC out of range (%p calls %p)", code, fnptr);
+
+ Write32((Cond << 28) | 0x0A000000 | ((distance >> 2) & 0x00FFFFFF));
+}
+FixupBranch ARMXEmitter::BL_CC(CCFlags Cond)
+{
+ FixupBranch branch;
+ branch.type = 1; // Zero for B
+ branch.ptr = code;
+ branch.condition = Cond << 28;
+ //We'll write NOP here for now.
+ Write32(condition | 0x01A00000);
+ return branch;
+}
+void ARMXEmitter::SetJumpTarget(FixupBranch const &branch)
+{
+ s32 distance = (s32(code) - 8) - (s32)branch.ptr;
+ _assert_msg_(DYNA_REC, distance > -33554432
+ && distance <= 33554432,
+ "SetJumpTarget out of range (%p calls %p)", code,
+ branch.ptr);
+ if(branch.type == 0) // B
+ *(u32*)branch.ptr = (u32)(branch.condition | (10 << 24) | ((distance >> 2) &
+ 0x00FFFFFF));
+ else // BL
+ *(u32*)branch.ptr = (u32)(branch.condition | 0x0B000000 | ((distance >> 2)
+ & 0x00FFFFFF));
+}
+void ARMXEmitter::B (const void *fnptr)
+{
+ s32 distance = (s32)fnptr - (s32(code) + 8);
+ _assert_msg_(DYNA_REC, distance > -33554432
+ && distance <= 33554432,
+ "B out of range (%p calls %p)", code, fnptr);
+
+ Write32(condition | 0x0A000000 | ((distance >> 2) & 0x00FFFFFF));
+}
+
+void ARMXEmitter::B(ARMReg src)
+{
+ Write32(condition | 0x12FFF10 | src);
+}
+
+void ARMXEmitter::BL(const void *fnptr)
+{
+ s32 distance = (s32)fnptr - (s32(code) + 8);
+ _assert_msg_(DYNA_REC, distance > -33554432
+ && distance <= 33554432,
+ "BL out of range (%p calls %p)", code, fnptr);
+ Write32(condition | 0x0B000000 | ((distance >> 2) & 0x00FFFFFF));
+}
+void ARMXEmitter::BL(ARMReg src)
+{
+ Write32(condition | 0x12FFF30 | src);
+}
+void ARMXEmitter::PUSH(const int num, ...)
+{
+ u16 RegList = 0;
+ u8 Reg;
+ int i;
+ va_list vl;
+ va_start(vl, num);
+ for (i=0;i<num;i++)
+ {
+ Reg = va_arg(vl, u32);
+ RegList |= (1 << Reg);
+ }
+ va_end(vl);
+ Write32(condition | (2349 << 16) | RegList);
+}
+void ARMXEmitter::POP(const int num, ...)
+{
+ u16 RegList = 0;
+ u8 Reg;
+ int i;
+ va_list vl;
+ va_start(vl, num);
+ for (i=0;i<num;i++)
+ {
+ Reg = va_arg(vl, u32);
+ RegList |= (1 << Reg);
+ }
+ va_end(vl);
+ Write32(condition | (2237 << 16) | RegList);
+}
+
+void ARMXEmitter::WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2)
+{
+ Write32(condition | (13 << 21) | (SetFlags << 20) | (dest << 12) | op2.Imm5() | (op << 4) | src);
+}
+void ARMXEmitter::WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, ARMReg op2)
+{
+ Write32(condition | (13 << 21) | (SetFlags << 20) | (dest << 12) | (op2 << 8) | (op << 4) | src);
+}
+
+// IMM, REG, IMMSREG, RSR
+// -1 for invalid if the instruction doesn't support that
+const s32 InstOps[][4] = {{16, 0, 0, 0}, // AND(s)
+ {17, 1, 1, 1}, // EOR(s)
+ {18, 2, 2, 2}, // SUB(s)
+ {19, 3, 3, 3}, // RSB(s)
+ {20, 4, 4, 4}, // ADD(s)
+ {21, 5, 5, 5}, // ADC(s)
+ {22, 6, 6, 6}, // SBC(s)
+ {23, 7, 7, 7}, // RSC(s)
+ {24, 8, 8, 8}, // TST
+ {25, 9, 9, 9}, // TEQ
+ {26, 10, 10, 10}, // CMP
+ {27, 11, 11, 11}, // CMN
+ {28, 12, 12, 12}, // ORR(s)
+ {29, 13, 13, 13}, // MOV(s)
+ {30, 14, 14, 14}, // BIC(s)
+ {31, 15, 15, 15}, // MVN(s)
+ {24, -1, -1, -1}, // MOVW
+ {26, -1, -1, -1}, // MOVT
+ };
+
+const char *InstNames[] = { "AND",
+ "EOR",
+ "SUB",
+ "RSB",
+ "ADD",
+ "ADC",
+ "SBC",
+ "RSC",
+ "TST",
+ "TEQ",
+ "CMP",
+ "CMN",
+ "ORR",
+ "MOV",
+ "BIC",
+ "MVN"
+ };
+
+void ARMXEmitter::AND (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(0, Rd, Rn, Rm); }
+void ARMXEmitter::ANDS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(0, Rd, Rn, Rm, true); }
+void ARMXEmitter::EOR (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(1, Rd, Rn, Rm); }
+void ARMXEmitter::EORS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(1, Rd, Rn, Rm, true); }
+void ARMXEmitter::SUB (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(2, Rd, Rn, Rm); }
+void ARMXEmitter::SUBS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(2, Rd, Rn, Rm, true); }
+void ARMXEmitter::RSB (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(3, Rd, Rn, Rm); }
+void ARMXEmitter::RSBS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(3, Rd, Rn, Rm, true); }
+void ARMXEmitter::ADD (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(4, Rd, Rn, Rm); }
+void ARMXEmitter::ADDS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(4, Rd, Rn, Rm, true); }
+void ARMXEmitter::ADC (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(5, Rd, Rn, Rm); }
+void ARMXEmitter::ADCS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(5, Rd, Rn, Rm, true); }
+void ARMXEmitter::SBC (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(6, Rd, Rn, Rm); }
+void ARMXEmitter::SBCS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(6, Rd, Rn, Rm, true); }
+void ARMXEmitter::RSC (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(7, Rd, Rn, Rm); }
+void ARMXEmitter::RSCS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(7, Rd, Rn, Rm, true); }
+void ARMXEmitter::TST ( ARMReg Rn, Operand2 Rm) { WriteInstruction(8, R0, Rn, Rm, true); }
+void ARMXEmitter::TEQ ( ARMReg Rn, Operand2 Rm) { WriteInstruction(9, R0, Rn, Rm, true); }
+void ARMXEmitter::CMP ( ARMReg Rn, Operand2 Rm) { WriteInstruction(10, R0, Rn, Rm, true); }
+void ARMXEmitter::CMN ( ARMReg Rn, Operand2 Rm) { WriteInstruction(11, R0, Rn, Rm, true); }
+void ARMXEmitter::ORR (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(12, Rd, Rn, Rm); }
+void ARMXEmitter::ORRS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(12, Rd, Rn, Rm, true); }
+void ARMXEmitter::MOV (ARMReg Rd, Operand2 Rm) { WriteInstruction(13, Rd, R0, Rm); }
+void ARMXEmitter::MOVS(ARMReg Rd, Operand2 Rm) { WriteInstruction(13, Rd, R0, Rm, true); }
+void ARMXEmitter::BIC (ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(14, Rd, Rn, Rm); }
+void ARMXEmitter::BICS(ARMReg Rd, ARMReg Rn, Operand2 Rm) { WriteInstruction(14, Rd, Rn, Rm, true); }
+void ARMXEmitter::MVN (ARMReg Rd, Operand2 Rm) { WriteInstruction(15, Rd, R0, Rm); }
+void ARMXEmitter::MVNS(ARMReg Rd, Operand2 Rm) { WriteInstruction(15, Rd, R0, Rm, true); }
+void ARMXEmitter::MOVW(ARMReg Rd, Operand2 Rm) { WriteInstruction(16, Rd, R0, Rm); }
+void ARMXEmitter::MOVT(ARMReg Rd, Operand2 Rm, bool TopBits) { WriteInstruction(17, Rd, R0, TopBits ? Rm.Value >> 16 : Rm); }
+
+void ARMXEmitter::WriteInstruction (u32 Op, ARMReg Rd, ARMReg Rn, Operand2 Rm, bool SetFlags) // This can get renamed later
+{
+ s32 op = InstOps[Op][Rm.GetType()]; // Type always decided by last operand
+ u32 Data = Rm.GetData();
+ if (Rm.GetType() == TYPE_IMM)
+ {
+ switch (Op)
+ {
+ // MOV cases that support IMM16
+ case 16:
+ case 17:
+ Data = Rm.Imm16();
+ break;
+ default:
+ break;
+ }
+ }
+ if (op == -1)
+ _assert_msg_(DYNA_REC, false, "%s not yet support %d", InstNames[Op], Rm.GetType());
+ Write32(condition | (op << 21) | (SetFlags ? (1 << 20) : 0) | Rn << 16 | Rd << 12 | Data);
+}
+
+// Data Operations
+void ARMXEmitter::WriteSignedMultiply(u32 Op, u32 Op2, u32 Op3, ARMReg dest, ARMReg r1, ARMReg r2)
+{
+ Write32(condition | (0x7 << 24) | (Op << 20) | (dest << 16) | (Op2 << 12) | (r1 << 8) | (Op3 << 5) | (1 << 4) | r2);
+}
+void ARMXEmitter::UDIV(ARMReg dest, ARMReg dividend, ARMReg divisor)
+{
+ if (!cpu_info.bIDIVa)
+ PanicAlert("Trying to use integer divide on hardware that doesn't support it. Bad programmer.");
+ WriteSignedMultiply(3, 0xF, 0, dest, divisor, dividend);
+}
+void ARMXEmitter::SDIV(ARMReg dest, ARMReg dividend, ARMReg divisor)
+{
+ if (!cpu_info.bIDIVa)
+ PanicAlert("Trying to use integer divide on hardware that doesn't support it. Bad programmer.");
+ WriteSignedMultiply(1, 0xF, 0, dest, divisor, dividend);
+}
+void ARMXEmitter::LSL (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(0, false, dest, src, op2);}
+void ARMXEmitter::LSLS(ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(0, true, dest, src, op2);}
+void ARMXEmitter::LSL (ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(1, false, dest, src, op2);}
+void ARMXEmitter::LSLS(ARMReg dest, ARMReg src, ARMReg op2) { WriteShiftedDataOp(1, true, dest, src, op2);}
+void ARMXEmitter::LSR (ARMReg dest, ARMReg src, Operand2 op2) { WriteShiftedDataOp(3, false, dest, src, op2);}
+void ARMXEmitter::MUL (ARMReg dest, ARMReg src, ARMReg op2)
+{
+ Write32(condition | (dest << 16) | (src << 8) | (9 << 4) | op2);
+}
+void ARMXEmitter::MULS(ARMReg dest, ARMReg src, ARMReg op2)
+{
+ Write32(condition | (1 << 20) | (dest << 16) | (src << 8) | (9 << 4) | op2);
+}
+
+void ARMXEmitter::Write4OpMultiply(u32 op, ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn) {
+ Write32(condition | (op << 20) | (destHi << 16) | (destLo << 12) | (rm << 8) | (9 << 4) | rn);
+}
+
+void ARMXEmitter::UMULL(ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn)
+{
+ Write4OpMultiply(0x8, destLo, destHi, rn, rm);
+}
+
+void ARMXEmitter::SMULL(ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn)
+{
+ Write4OpMultiply(0xC, destLo, destHi, rn, rm);
+}
+
+void ARMXEmitter::UMLAL(ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn)
+{
+ Write4OpMultiply(0xA, destLo, destHi, rn, rm);
+}
+
+void ARMXEmitter::SMLAL(ARMReg destLo, ARMReg destHi, ARMReg rm, ARMReg rn)
+{
+ Write4OpMultiply(0xE, destLo, destHi, rn, rm);
+}
+
+void ARMXEmitter::UBFX(ARMReg dest, ARMReg rn, u8 lsb, u8 width)
+{
+ Write32(condition | (0x7E0 << 16) | ((width - 1) << 16) | (dest << 12) | (lsb << 7) | (5 << 4) | rn);
+}
+
+void ARMXEmitter::CLZ(ARMReg rd, ARMReg rm)
+{
+ Write32(condition | (0x16F << 16) | (rd << 12) | (0xF1 << 4) | rm);
+}
+
+void ARMXEmitter::BFI(ARMReg rd, ARMReg rn, u8 lsb, u8 width)
+{
+ u32 msb = (lsb + width - 1);
+ if (msb > 31) msb = 31;
+ Write32(condition | (0x7C0 << 16) | (msb << 16) | (rd << 12) | (lsb << 7) | (1 << 4) | rn);
+}
+
+void ARMXEmitter::SXTB (ARMReg dest, ARMReg op2)
+{
+ Write32(condition | (0x6AF << 16) | (dest << 12) | (7 << 4) | op2);
+}
+
+void ARMXEmitter::SXTH (ARMReg dest, ARMReg op2, u8 rotation)
+{
+ SXTAH(dest, (ARMReg)15, op2, rotation);
+}
+void ARMXEmitter::SXTAH(ARMReg dest, ARMReg src, ARMReg op2, u8 rotation)
+{
+ // bits ten and 11 are the rotation amount, see 8.8.232 for more
+ // information
+ Write32(condition | (0x6B << 20) | (src << 16) | (dest << 12) | (rotation << 10) | (7 << 4) | op2);
+}
+void ARMXEmitter::RBIT(ARMReg dest, ARMReg src)
+{
+ Write32(condition | (0x6F << 20) | (0xF << 16) | (dest << 12) | (0xF3 << 4) | src);
+}
+void ARMXEmitter::REV (ARMReg dest, ARMReg src)
+{
+ Write32(condition | (0x6B << 20) | (0xF << 16) | (dest << 12) | (0xF3 << 4) | src);
+}
+void ARMXEmitter::REV16(ARMReg dest, ARMReg src)
+{
+ Write32(condition | (0x3DF << 16) | (dest << 12) | (0xFD << 4) | src);
+}
+
+void ARMXEmitter::_MSR (bool write_nzcvq, bool write_g, Operand2 op2)
+{
+ Write32(condition | (0x320F << 12) | (write_nzcvq << 19) | (write_g << 18) | op2.Imm12Mod());
+}
+void ARMXEmitter::_MSR (bool write_nzcvq, bool write_g, ARMReg src)
+{
+ Write32(condition | (0x120F << 12) | (write_nzcvq << 19) | (write_g << 18) | src);
+}
+void ARMXEmitter::MRS (ARMReg dest)
+{
+ Write32(condition | (16 << 20) | (15 << 16) | (dest << 12));
+}
+void ARMXEmitter::LDREX(ARMReg dest, ARMReg base)
+{
+ Write32(condition | (25 << 20) | (base << 16) | (dest << 12) | 0xF9F);
+}
+void ARMXEmitter::STREX(ARMReg result, ARMReg base, ARMReg op)
+{
+ _assert_msg_(DYNA_REC, (result != base && result != op), "STREX dest can't be other two registers");
+ Write32(condition | (24 << 20) | (base << 16) | (result << 12) | (0xF9 << 4) | op);
+}
+void ARMXEmitter::DMB ()
+{
+ Write32(0xF57FF05E);
+}
+void ARMXEmitter::SVC(Operand2 op)
+{
+ Write32(condition | (0x0F << 24) | op.Imm24());
+}
+
+// IMM, REG, IMMSREG, RSR
+// -1 for invalid if the instruction doesn't support that
+const s32 LoadStoreOps[][4] = { {0x40, 0x60, 0x60, -1}, // STR
+ {0x41, 0x61, 0x61, -1}, // LDR
+ {0x44, 0x64, 0x64, -1}, // STRB
+ {0x45, 0x65, 0x65, -1}, // LDRB
+ // Special encodings
+ { 0x4, 0x0, -1, -1}, // STRH
+ { 0x5, 0x1, -1, -1}, // LDRH
+ { 0x5, 0x1, -1, -1}, // LDRSB
+ { 0x5, 0x1, -1, -1}, // LDRSH
+ };
+const char *LoadStoreNames[] = { "STR",
+ "LDR",
+ "STRB",
+ "LDRB",
+ "STRH",
+ "LDRH",
+ "LDRSB",
+ "LDRSH",
+ };
+
+void ARMXEmitter::WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 Rm, bool RegAdd)
+{
+ s32 op = LoadStoreOps[Op][Rm.GetType()]; // Type always decided by last operand
+ u32 Data;
+
+ // Qualcomm chipsets get /really/ angry if you don't use index, even if the offset is zero.
+ // Some of these encodings require Index at all times anyway. Doesn't really matter.
+ // bool Index = op2 != 0 ? true : false;
+ bool Index = true;
+ bool Add = false;
+
+ // Special Encoding
+ bool SpecialOp = false;
+ bool Half = false;
+ bool SignedLoad = false;
+
+ if (op == -1)
+ _assert_msg_(DYNA_REC, false, "%s does not support %d", LoadStoreNames[Op], Rm.GetType());
+
+ switch (Op)
+ {
+ case 4: // STRH
+ SpecialOp = true;
+ Half = true;
+ SignedLoad = false;
+ break;
+ case 5: // LDRH
+ SpecialOp = true;
+ Half = true;
+ SignedLoad = false;
+ break;
+ case 6: // LDRSB
+ SpecialOp = true;
+ Half = false;
+ SignedLoad = true;
+ break;
+ case 7: // LDRSH
+ SpecialOp = true;
+ Half = true;
+ SignedLoad = true;
+ break;
+ }
+ switch (Rm.GetType())
+ {
+ case TYPE_IMM:
+ {
+ s32 Temp = (s32)Rm.Value;
+ Data = abs(Temp);
+ // The offset is encoded differently on this one.
+ if (SpecialOp)
+ Data = (Data & 0xF0 << 4) | (Data & 0xF);
+ if (Temp >= 0) Add = true;
+ }
+ break;
+ case TYPE_REG:
+ case TYPE_IMMSREG:
+ if (!SpecialOp)
+ {
+ Data = Rm.GetData();
+ Add = RegAdd;
+ break;
+ }
+ default:
+ // RSR not supported for any of these
+ // We already have the warning above
+ BKPT(0x2);
+ return;
+ break;
+ }
+ if (SpecialOp)
+ {
+ // Add SpecialOp things
+ Data = (0x5 << 4) | (SignedLoad << 6) | (Half << 5) | Data;
+ }
+ Write32(condition | (op << 20) | (Index << 24) | (Add << 23) | (Rn << 16) | (Rt << 12) | Data);
+}
+
+void ARMXEmitter::LDR (ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(1, dest, base, op2, RegAdd);}
+void ARMXEmitter::LDRB(ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(3, dest, base, op2, RegAdd);}
+void ARMXEmitter::LDRH(ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(5, dest, base, op2, RegAdd);}
+void ARMXEmitter::LDRSB(ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(6, dest, base, op2, RegAdd);}
+void ARMXEmitter::LDRSH(ARMReg dest, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(7, dest, base, op2, RegAdd);}
+void ARMXEmitter::STR (ARMReg result, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(0, result, base, op2, RegAdd);}
+void ARMXEmitter::STRH (ARMReg result, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(4, result, base, op2, RegAdd);}
+void ARMXEmitter::STRB (ARMReg result, ARMReg base, Operand2 op2, bool RegAdd) { WriteStoreOp(2, result, base, op2, RegAdd);}
+
+void ARMXEmitter::WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList)
+{
+ Write32(condition | (op << 20) | (WriteBack << 21) | (dest << 16) | RegList);
+}
+void ARMXEmitter::STMFD(ARMReg dest, bool WriteBack, const int Regnum, ...)
+{
+ u16 RegList = 0;
+ u8 Reg;
+ int i;
+ va_list vl;
+ va_start(vl, Regnum);
+ for (i=0;i<Regnum;i++)
+ {
+ Reg = va_arg(vl, u32);
+ RegList |= (1 << Reg);
+ }
+ va_end(vl);
+ WriteRegStoreOp(0x90, dest, WriteBack, RegList);
+}
+void ARMXEmitter::LDMFD(ARMReg dest, bool WriteBack, const int Regnum, ...)
+{
+ u16 RegList = 0;
+ u8 Reg;
+ int i;
+ va_list vl;
+ va_start(vl, Regnum);
+ for (i=0;i<Regnum;i++)
+ {
+ Reg = va_arg(vl, u32);
+ RegList |= (1 << Reg);
+ }
+ va_end(vl);
+ WriteRegStoreOp(0x89, dest, WriteBack, RegList);
+}
+
+ARMReg ARMXEmitter::SubBase(ARMReg Reg)
+{
+ if (Reg >= S0)
+ {
+ if (Reg >= D0)
+ {
+ if (Reg >= Q0)
+ return (ARMReg)((Reg - Q0) * 2); // Always gets encoded as a double register
+ return (ARMReg)(Reg - D0);
+ }
+ return (ARMReg)(Reg - S0);
+ }
+ return Reg;
+}
+
+// NEON Specific
+void ARMXEmitter::VADD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to VADD(integer)");
+ _assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use VADD(integer) when CPU doesn't support it");
+
+ bool register_quad = Vd >= Q0;
+
+ // Gets encoded as a double register
+ Vd = SubBase(Vd);
+ Vn = SubBase(Vn);
+ Vm = SubBase(Vm);
+
+ Write32((0xF2 << 24) | ((Vd & 0x10) << 18) | (Size << 20) | ((Vn & 0xF) << 16) \
+ | ((Vd & 0xF) << 12) | (0x8 << 8) | ((Vn & 0x10) << 3) | (register_quad << 6) \
+ | ((Vm & 0x10) << 2) | (Vm & 0xF));
+
+}
+void ARMXEmitter::VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ _assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to VSUB(integer)");
+ _assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use VSUB(integer) when CPU doesn't support it");
+
+ // Gets encoded as a double register
+ Vd = SubBase(Vd);
+ Vn = SubBase(Vn);
+ Vm = SubBase(Vm);
+
+ Write32((0xF3 << 24) | ((Vd & 0x10) << 18) | (Size << 20) | ((Vn & 0xF) << 16) \
+ | ((Vd & 0xF) << 12) | (0x8 << 8) | ((Vn & 0x10) << 3) | (1 << 6) \
+ | ((Vm & 0x10) << 2) | (Vm & 0xF));
+}
+
+// VFP Specific
+struct VFPEnc
+{
+ s16 opc1;
+ s16 opc2;
+};
+// Double/single, Neon
+const VFPEnc VFPOps[][2] = {
+ {{0xE0, 0xA0}, {0x20, 0xD1}}, // 0: VMLA
+ {{0xE0, 0xA4}, {0x22, 0xD1}}, // 1: VMLS
+ {{0xE3, 0xA0}, {0x20, 0xD0}}, // 2: VADD
+ {{0xE3, 0xA4}, {0x22, 0xD0}}, // 3: VSUB
+ {{0xE2, 0xA0}, {0x30, 0xD1}}, // 4: VMUL
+ {{0xEB, 0xAC}, { -1 /* 0x3B */, -1 /* 0x70 */}}, // 5: VABS(Vn(0x0) used for encoding)
+ {{0xE8, 0xA0}, { -1, -1}}, // 6: VDIV
+ {{0xEB, 0xA4}, { -1 /* 0x3B */, -1 /* 0x78 */}}, // 7: VNEG(Vn(0x1) used for encoding)
+ {{0xEB, 0xAC}, { -1, -1}}, // 8: VSQRT (Vn(0x1) used for encoding)
+ {{0xEB, 0xA4}, { -1, -1}}, // 9: VCMP (Vn(0x4 | #0 ? 1 : 0) used for encoding)
+ {{0xEB, 0xAC}, { -1, -1}}, // 10: VCMPE (Vn(0x4 | #0 ? 1 : 0) used for encoding)
+ {{ -1, -1}, {0x3B, 0x30}}, // 11: VABSi
+ };
+const char *VFPOpNames[] = {
+ "VMLA",
+ "VMLS",
+ "VADD",
+ "VSUB",
+ "VMUL",
+ "VABS",
+ "VDIV",
+ "VNEG",
+ "VSQRT",
+ "VCMP",
+ "VCMPE",
+ "VABSi",
+};
+
+u32 ARMXEmitter::EncodeVd(ARMReg Vd)
+{
+ bool quad_reg = Vd >= Q0;
+ bool double_reg = Vd >= D0;
+
+ ARMReg Reg = SubBase(Vd);
+
+ if (quad_reg)
+ return ((Reg & 0x10) << 18) | ((Reg & 0xF) << 12);
+ else
+ if (double_reg)
+ return ((Reg & 0x10) << 18) | ((Reg & 0xF) << 12);
+ else
+ return ((Reg & 0x1) << 22) | ((Reg & 0x1E) << 11);
+}
+u32 ARMXEmitter::EncodeVn(ARMReg Vn)
+{
+ bool quad_reg = Vn >= Q0;
+ bool double_reg = Vn >= D0;
+
+ ARMReg Reg = SubBase(Vn);
+ if (quad_reg)
+ return ((Reg & 0xF) << 16) | ((Reg & 0x10) << 3);
+ else
+ if (double_reg)
+ return ((Reg & 0xF) << 16) | ((Reg & 0x10) << 3);
+ else
+ return ((Reg & 0x1E) << 15) | ((Reg & 0x1) << 7);
+}
+u32 ARMXEmitter::EncodeVm(ARMReg Vm)
+{
+ bool quad_reg = Vm >= Q0;
+ bool double_reg = Vm >= D0;
+
+ ARMReg Reg = SubBase(Vm);
+
+ if (quad_reg)
+ return ((Reg & 0x10) << 2) | (Reg & 0xF);
+ else
+ if (double_reg)
+ return ((Reg & 0x10) << 2) | (Reg & 0xF);
+ else
+ return ((Reg & 0x1) << 5) | (Reg >> 1);
+}
+void ARMXEmitter::WriteVFPDataOp(u32 Op, ARMReg Vd, ARMReg Vn, ARMReg Vm)
+{
+ bool quad_reg = Vd >= Q0;
+ bool double_reg = Vd >= D0 && Vd < Q0;
+
+ VFPEnc enc = VFPOps[Op][quad_reg];
+ if (enc.opc1 == -1 && enc.opc2 == -1)
+ _assert_msg_(DYNA_REC, false, "%s does not support %s", VFPOpNames[Op], quad_reg ? "NEON" : "VFP");
+ u32 VdEnc = EncodeVd(Vd);
+ u32 VnEnc = EncodeVn(Vn);
+ u32 VmEnc = EncodeVm(Vm);
+ u32 cond = quad_reg ? (0xF << 28) : condition;
+
+ Write32(cond | (enc.opc1 << 20) | VnEnc | VdEnc | (enc.opc2 << 4) | (quad_reg << 6) | (double_reg << 8) | VmEnc);
+}
+void ARMXEmitter::VMLA(ARMReg Vd, ARMReg Vn, ARMReg Vm){ WriteVFPDataOp(0, Vd, Vn, Vm); }
+void ARMXEmitter::VMLS(ARMReg Vd, ARMReg Vn, ARMReg Vm){ WriteVFPDataOp(1, Vd, Vn, Vm); }
+void ARMXEmitter::VADD(ARMReg Vd, ARMReg Vn, ARMReg Vm){ WriteVFPDataOp(2, Vd, Vn, Vm); }
+void ARMXEmitter::VSUB(ARMReg Vd, ARMReg Vn, ARMReg Vm){ WriteVFPDataOp(3, Vd, Vn, Vm); }
+void ARMXEmitter::VMUL(ARMReg Vd, ARMReg Vn, ARMReg Vm){ WriteVFPDataOp(4, Vd, Vn, Vm); }
+void ARMXEmitter::VABS(ARMReg Vd, ARMReg Vm){ WriteVFPDataOp(5, Vd, D0, Vm); }
+void ARMXEmitter::VDIV(ARMReg Vd, ARMReg Vn, ARMReg Vm){ WriteVFPDataOp(6, Vd, Vn, Vm); }
+void ARMXEmitter::VNEG(ARMReg Vd, ARMReg Vm){ WriteVFPDataOp(7, Vd, D1, Vm); }
+void ARMXEmitter::VSQRT(ARMReg Vd, ARMReg Vm){ WriteVFPDataOp(8, Vd, D1, Vm); }
+void ARMXEmitter::VCMP(ARMReg Vd, ARMReg Vm){ WriteVFPDataOp(9, Vd, D4, Vm); }
+void ARMXEmitter::VCMPE(ARMReg Vd, ARMReg Vm){ WriteVFPDataOp(10, Vd, D4, Vm); }
+void ARMXEmitter::VCMP(ARMReg Vd){ WriteVFPDataOp(9, Vd, D5, D0); }
+void ARMXEmitter::VCMPE(ARMReg Vd){ WriteVFPDataOp(10, Vd, D5, D0); }
+
+void ARMXEmitter::VLDR(ARMReg Dest, ARMReg Base, s16 offset)
+{
+ _assert_msg_(DYNA_REC, Dest >= S0 && Dest <= D31, "Passed Invalid dest register to VLDR");
+ _assert_msg_(DYNA_REC, Base <= R15, "Passed invalid Base register to VLDR");
+
+ bool Add = offset >= 0 ? true : false;
+ u32 imm = abs(offset);
+
+ _assert_msg_(DYNA_REC, (imm & 0xC03) == 0, "VLDR: Offset needs to be word aligned and small enough");
+
+ if (imm & 0xC03)
+ ERROR_LOG(DYNA_REC, "VLDR: Bad offset %08x", imm);
+
+ bool single_reg = Dest < D0;
+
+ Dest = SubBase(Dest);
+
+ if (single_reg)
+ {
+ Write32(condition | (0xD << 24) | (Add << 23) | ((Dest & 0x1) << 22) | (1 << 20) | (Base << 16) \
+ | ((Dest & 0x1E) << 11) | (10 << 8) | (imm >> 2));
+
+ }
+ else
+ {
+ Write32(condition | (0xD << 24) | (Add << 23) | ((Dest & 0x10) << 18) | (1 << 20) | (Base << 16) \
+ | ((Dest & 0xF) << 12) | (11 << 8) | (imm >> 2));
+ }
+}
+void ARMXEmitter::VSTR(ARMReg Src, ARMReg Base, s16 offset)
+{
+ _assert_msg_(DYNA_REC, Src >= S0 && Src <= D31, "Passed invalid src register to VSTR");
+ _assert_msg_(DYNA_REC, Base <= R15, "Passed invalid base register to VSTR");
+
+ bool Add = offset >= 0 ? true : false;
+ u32 imm = abs(offset);
+
+ _assert_msg_(DYNA_REC, (imm & 0xC03) == 0, "VSTR: Offset needs to be word aligned and small enough");
+
+ if (imm & 0xC03)
+ ERROR_LOG(DYNA_REC, "VSTR: Bad offset %08x", imm);
+
+ bool single_reg = Src < D0;
+
+ Src = SubBase(Src);
+
+ if (single_reg)
+ {
+ Write32(condition | (0xD << 24) | (Add << 23) | ((Src & 0x1) << 22) | (Base << 16) \
+ | ((Src & 0x1E) << 11) | (10 << 8) | (imm >> 2));
+ }
+ else
+ {
+ Write32(condition | (0xD << 24) | (Add << 23) | ((Src & 0x10) << 18) | (Base << 16) \
+ | ((Src & 0xF) << 12) | (11 << 8) | (imm >> 2));
+ }
+}
+
+void ARMXEmitter::VMRS_APSR() {
+ Write32(condition | 0xEF10A10 | (15 << 12));
+}
+void ARMXEmitter::VMRS(ARMReg Rt) {
+ Write32(condition | (0xEF << 20) | (1 << 16) | (Rt << 12) | 0xA10);
+}
+void ARMXEmitter::VMSR(ARMReg Rt) {
+ Write32(condition | (0xEE << 20) | (1 << 16) | (Rt << 12) | 0xA10);
+}
+
+// VFP and ASIMD
+void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src, bool high)
+{
+ _assert_msg_(DYNA_REC, Src < S0, "This VMOV doesn't support SRC other than ARM Reg");
+ _assert_msg_(DYNA_REC, Dest >= D0, "This VMOV doesn't support DEST other than VFP");
+
+ Dest = SubBase(Dest);
+
+ Write32(condition | (0xE << 24) | (high << 21) | ((Dest & 0xF) << 16) | (Src << 12) \
+ | (11 << 8) | ((Dest & 0x10) << 3) | (1 << 4));
+}
+
+void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src)
+{
+ if (Dest > R15)
+ {
+ if (Src < S0)
+ {
+ if (Dest < D0)
+ {
+ // Moving to a Neon register FROM ARM Reg
+ Dest = (ARMReg)(Dest - S0);
+ Write32(condition | (0xE0 << 20) | ((Dest & 0x1E) << 15) | (Src << 12) \
+ | (0xA << 8) | ((Dest & 0x1) << 7) | (1 << 4));
+ return;
+ }
+ else
+ {
+ // Move 64bit from Arm reg
+ _assert_msg_(DYNA_REC, false, "This VMOV doesn't support moving 64bit ARM to NEON");
+ return;
+ }
+ }
+ }
+ else
+ {
+ if (Src > R15)
+ {
+ if (Src < D0)
+ {
+ // Moving to ARM Reg from Neon Register
+ Src = (ARMReg)(Src - S0);
+ Write32(condition | (0xE1 << 20) | ((Src & 0x1E) << 15) | (Dest << 12) \
+ | (0xA << 8) | ((Src & 0x1) << 7) | (1 << 4));
+ return;
+ }
+ else
+ {
+ // Move 64bit To Arm reg
+ _assert_msg_(DYNA_REC, false, "This VMOV doesn't support moving 64bit ARM From NEON");
+ return;
+ }
+ }
+ else
+ {
+ // Move Arm reg to Arm reg
+ _assert_msg_(DYNA_REC, false, "VMOV doesn't support moving ARM registers");
+ }
+ }
+ // Moving NEON registers
+ int SrcSize = Src < D0 ? 1 : Src < Q0 ? 2 : 4;
+ int DestSize = Dest < D0 ? 1 : Dest < Q0 ? 2 : 4;
+ bool Single = DestSize == 1;
+ bool Quad = DestSize == 4;
+
+ _assert_msg_(DYNA_REC, SrcSize == DestSize, "VMOV doesn't support moving different register sizes");
+
+ Dest = SubBase(Dest);
+ Src = SubBase(Src);
+
+ if (Single)
+ {
+ Write32(condition | (0x1D << 23) | ((Dest & 0x1) << 22) | (0x3 << 20) | ((Dest & 0x1E) << 11) \
+ | (0x5 << 9) | (1 << 6) | ((Src & 0x1) << 5) | ((Src & 0x1E) >> 1));
+ }
+ else
+ {
+ // Double and quad
+ if (Quad)
+ {
+ _assert_msg_(DYNA_REC, cpu_info.bNEON, "Trying to use quad registers when you don't support ASIMD.");
+ // Gets encoded as a Double register
+ Write32((0xF2 << 24) | ((Dest & 0x10) << 18) | (2 << 20) | ((Src & 0xF) << 16) \
+ | ((Dest & 0xF) << 12) | (1 << 8) | ((Src & 0x10) << 3) | (1 << 6) \
+ | ((Src & 0x10) << 1) | (1 << 4) | (Src & 0xF));
+
+ }
+ else
+ {
+ Write32(condition | (0x1D << 23) | ((Dest & 0x10) << 18) | (0x3 << 20) | ((Dest & 0xF) << 12) \
+ | (0x2D << 6) | ((Src & 0x10) << 1) | (Src & 0xF));
+ }
+ }
+}
+
+void ARMXEmitter::VCVT(ARMReg Dest, ARMReg Source, int flags)
+{
+ bool single_reg = (Dest < D0) && (Source < D0);
+ int op = ((flags & TO_INT) ? (flags & ROUND_TO_ZERO) : (flags & IS_SIGNED)) ? 1 : 0;
+ int op2 = ((flags & TO_INT) ? (flags & IS_SIGNED) : 0) ? 1 : 0;
+ Dest = SubBase(Dest);
+ Source = SubBase(Source);
+
+ if (single_reg)
+ {
+ Write32(condition | (0x1D << 23) | ((Dest & 0x1) << 22) | (0x7 << 19) | ((flags & TO_INT) << 18) | (op2 << 16) \
+ | ((Dest & 0x1E) << 11) | (op << 7) | (0x29 << 6) | ((Source & 0x1) << 5) | (Source >> 1));
+ } else {
+ Write32(condition | (0x1D << 23) | ((Dest & 0x10) << 18) | (0x7 << 19) | ((flags & TO_INT) << 18) | (op2 << 16) \
+ | ((Dest & 0xF) << 12) | (1 << 8) | (op << 7) | (0x29 << 6) | ((Source & 0x10) << 1) | (Source & 0xF));
+ }
+}
+
+}
diff --git a/Source/Core/Common/Src/ArmEmitter.h b/Source/Core/Common/Src/ArmEmitter.h
new file mode 100644
index 0000000000..fe64584e0c
--- /dev/null
+++ b/Source/Core/Common/Src/ArmEmitter.h
@@ -0,0 +1,637 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+// WARNING - THIS LIBRARY IS NOT THREAD SAFE!!!
+
+#ifndef _DOLPHIN_ARM_CODEGEN_
+#define _DOLPHIN_ARM_CODEGEN_
+
+#include "Common.h"
+#include "MemoryUtil.h"
+#if defined(__SYMBIAN32__) || defined(PANDORA)
+#include <signal.h>
+#endif
+#include <vector>
+
+#undef _IP
+#undef R0
+#undef _SP
+#undef _LR
+#undef _PC
+
+// VCVT flags
+#define TO_FLOAT 0
+#define TO_INT 1 << 0
+#define IS_SIGNED 1 << 1
+#define ROUND_TO_ZERO 1 << 2
+
+namespace ArmGen
+{
+enum ARMReg
+{
+ // GPRs
+ R0 = 0, R1, R2, R3, R4, R5,
+ R6, R7, R8, R9, R10, R11,
+
+ // SPRs
+ // R13 - R15 are SP, LR, and PC.
+ // Almost always referred to by name instead of register number
+ R12 = 12, R13 = 13, R14 = 14, R15 = 15,
+ _IP = 12, _SP = 13, _LR = 14, _PC = 15,
+
+
+ // VFP single precision registers
+ S0, S1, S2, S3, S4, S5, S6,
+ S7, S8, S9, S10, S11, S12, S13,
+ S14, S15, S16, S17, S18, S19, S20,
+ S21, S22, S23, S24, S25, S26, S27,
+ S28, S29, S30, S31,
+
+ // VFP Double Precision registers
+ D0, D1, D2, D3, D4, D5, D6, D7,
+ D8, D9, D10, D11, D12, D13, D14, D15,
+ D16, D17, D18, D19, D20, D21, D22, D23,
+ D24, D25, D26, D27, D28, D29, D30, D31,
+
+ // ASIMD Quad-Word registers
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7,
+ Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15,
+ INVALID_REG = 0xFFFFFFFF
+};
+
+enum CCFlags
+{
+ CC_EQ = 0, // Equal
+ CC_NEQ, // Not equal
+ CC_CS, // Carry Set
+ CC_CC, // Carry Clear
+ CC_MI, // Minus (Negative)
+ CC_PL, // Plus
+ CC_VS, // Overflow
+ CC_VC, // No Overflow
+ CC_HI, // Unsigned higher
+ CC_LS, // Unsigned lower or same
+ CC_GE, // Signed greater than or equal
+ CC_LT, // Signed less than
+ CC_GT, // Signed greater than
+ CC_LE, // Signed less than or equal
+ CC_AL, // Always (unconditional) 14
+ CC_HS = CC_CS, // Alias of CC_CS Unsigned higher or same
+ CC_LO = CC_CC, // Alias of CC_CC Unsigned lower
+};
+const u32 NO_COND = 0xE0000000;
+
+enum ShiftType
+{
+ ST_LSL = 0,
+ ST_ASL = 0,
+ ST_LSR = 1,
+ ST_ASR = 2,
+ ST_ROR = 3,
+ ST_RRX = 4
+};
+enum IntegerSize
+{
+ I_I8 = 0,
+ I_I16,
+ I_I32,
+ I_I64
+};
+
+enum
+{
+ NUMGPRs = 13,
+};
+
+class ARMXEmitter;
+
+enum OpType
+{
+ TYPE_IMM = 0,
+ TYPE_REG,
+ TYPE_IMMSREG,
+ TYPE_RSR,
+ TYPE_MEM
+};
+
+// This is no longer a proper operand2 class. Need to split up.
+class Operand2
+{
+ friend class ARMXEmitter;
+protected:
+ u32 Value;
+
+private:
+ OpType Type;
+
+ // IMM types
+ u8 Rotation; // Only for u8 values
+
+ // Register types
+ u8 IndexOrShift;
+ ShiftType Shift;
+public:
+ OpType GetType()
+ {
+ return Type;
+ }
+ Operand2() {}
+ Operand2(u32 imm, OpType type = TYPE_IMM)
+ {
+ Type = type;
+ Value = imm;
+ Rotation = 0;
+ }
+
+ Operand2(ARMReg Reg)
+ {
+ Type = TYPE_REG;
+ Value = Reg;
+ Rotation = 0;
+ }
+ Operand2(u8 imm, u8 rotation)
+ {
+ Type = TYPE_IMM;
+ Value = imm;
+ Rotation = rotation;
+ }
+ Operand2(ARMReg base, ShiftType type, ARMReg shift) // RSR
+ {
+ Type = TYPE_RSR;
+ _assert_msg_(DYNA_REC, type != ST_RRX, "Invalid Operand2: RRX does not take a register shift amount");
+ IndexOrShift = shift;
+ Shift = type;
+ Value = base;
+ }
+
+ Operand2(ARMReg base, ShiftType type, u8 shift)// For IMM shifted register
+ {
+ if(shift == 32) shift = 0;
+ switch (type)
+ {
+ case ST_LSL:
+ _assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: LSL %u", shift);
+ break;
+ case ST_LSR:
+ _assert_msg_(DYNA_REC, shift <= 32, "Invalid Operand2: LSR %u", shift);
+ if (!shift)
+ type = ST_LSL;
+ if (shift == 32)
+ shift = 0;
+ break;
+ case ST_ASR:
+ _assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: LSR %u", shift);
+ if (!shift)
+ type = ST_LSL;
+ if (shift == 32)
+ shift = 0;
+ break;
+ case ST_ROR:
+ _assert_msg_(DYNA_REC, shift < 32, "Invalid Operand2: ROR %u", shift);
+ if (!shift)
+ type = ST_LSL;
+ break;
+ case ST_RRX:
+ _assert_msg_(DYNA_REC, shift == 0, "Invalid Operand2: RRX does not take an immediate shift amount");
+ type = ST_ROR;
+ break;
+ }
+ IndexOrShift = shift;
+ Shift = type;
+ Value = base;
+ Type = TYPE_IMMSREG;
+ }
+ u32 GetData()
+ {
+ switch(Type)
+ {
+ case TYPE_IMM:
+ return Imm12Mod(); // This'll need to be changed later
+ case TYPE_REG:
+ return Rm();
+ case TYPE_IMMSREG:
+ return IMMSR();
+ case TYPE_RSR:
+ return RSR();
+ default:
+ _assert_msg_(DYNA_REC, false, "GetData with Invalid Type");
+ return 0;
+ }
+ }
+ u32 IMMSR() // IMM shifted register
+ {
+ _assert_msg_(DYNA_REC, Type == TYPE_IMMSREG, "IMMSR must be imm shifted register");
+ return ((IndexOrShift & 0x1f) << 7 | (Shift << 5) | Value);
+ }
+ u32 RSR() // Register shifted register
+ {
+ _assert_msg_(DYNA_REC, Type == TYPE_RSR, "RSR must be RSR Of Course");
+ return (IndexOrShift << 8) | (Shift << 5) | 0x10 | Value;
+ }
+ u32 Rm()
+ {
+ _assert_msg_(DYNA_REC, Type == TYPE_REG, "Rm must be with Reg");
+ return Value;
+ }
+
+ u32 Imm5()
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm5 not IMM value");
+ return ((Value & 0x0000001F) << 7);
+ }
+ u32 Imm8()
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value");
+ return Value & 0xFF;
+ }
+ u32 Imm8Rot() // IMM8 with Rotation
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8Rot not IMM value");
+ _assert_msg_(DYNA_REC, (Rotation & 0xE1) != 0, "Invalid Operand2: immediate rotation %u", Rotation);
+ return (1 << 25) | (Rotation << 7) | (Value & 0x000000FF);
+ }
+ u32 Imm12()
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12 not IMM");
+ return (Value & 0x00000FFF);
+ }
+
+ u32 Imm12Mod()
+ {
+ // This is a IMM12 with the top four bits being rotation and the
+ // bottom eight being a IMM. This is for instructions that need to
+ // expand a 8bit IMM to a 32bit value and gives you some rotation as
+ // well.
+ // Each rotation rotates to the right by 2 bits
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm12Mod not IMM");
+ return ((Rotation & 0xF) << 8) | (Value & 0xFF);
+ }
+ u32 Imm16()
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
+ return ( (Value & 0xF000) << 4) | (Value & 0x0FFF);
+ }
+ u32 Imm16Low()
+ {
+ return Imm16();
+ }
+ u32 Imm16High() // Returns high 16bits
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
+ return ( ((Value >> 16) & 0xF000) << 4) | ((Value >> 16) & 0x0FFF);
+ }
+ u32 Imm24()
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm16 not IMM");
+ return (Value & 0x0FFFFFFF);
+ }
+ // NEON and ASIMD specific
+ u32 Imm8ASIMD()
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8ASIMD not IMM");
+ return ((Value & 0x80) << 17) | ((Value & 0x70) << 12) | (Value & 0xF);
+ }
+ u32 Imm8VFP()
+ {
+ _assert_msg_(DYNA_REC, (Type == TYPE_IMM), "Imm8VFP not IMM");
+ return ((Value & 0xF0) << 12) | (Value & 0xF);
+ }
+};
+
+// Use these when you don't know if an imm can be represented as an operand2.
+// This lets you generate both an optimal and a fallback solution by checking
+// the return value, which will be false if these fail to find a Operand2 that
+// represents your 32-bit imm value.
+bool TryMakeOperand2(u32 imm, Operand2 &op2);
+bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse);
+bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated);
+
+inline Operand2 R(ARMReg Reg) { return Operand2(Reg, TYPE_REG); }
+inline Operand2 IMM(u32 Imm) { return Operand2(Imm, TYPE_IMM); }
+inline Operand2 Mem(void *ptr) { return Operand2((u32)ptr, TYPE_IMM); }
+//usage: struct {int e;} s; STRUCT_OFFSET(s,e)
+#define STRUCT_OFF(str,elem) ((u32)((u32)&(str).elem-(u32)&(str)))
+
+
+struct FixupBranch
+{
+ u8 *ptr;
+ u32 condition; // Remembers our codition at the time
+ int type; //0 = B 1 = BL
+};
+
+struct LiteralPool
+{
+ s32 loc;
+ u8* ldr_address;
+ u32 val;
+};
+
+typedef const u8* JumpTarget;
+
+class ARMXEmitter
+{
+ friend struct OpArg; // for Write8 etc
+private:
+ u8 *code, *startcode;
+ u8 *lastCacheFlushEnd;
+ u32 condition;
+ std::vector<LiteralPool> currentLitPool;
+
+ void WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 op2, bool RegAdd);
+ void WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList);
+ void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, ARMReg op2);
+ void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2);
+ void WriteSignedMultiply(u32 Op, u32 Op2, u32 Op3, ARMReg dest, ARMReg r1, ARMReg r2);
+
+ u32 EncodeVd(ARMReg Vd);
+ u32 EncodeVn(ARMReg Vn);
+ u32 EncodeVm(ARMReg Vm);
+ void WriteVFPDataOp(u32 Op, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+
+ void Write4OpMultiply(u32 op, ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
+
+ // New Ops
+ void WriteInstruction(u32 op, ARMReg Rd, ARMReg Rn, Operand2 Rm, bool SetFlags = false);
+
+protected:
+ inline void Write32(u32 value) {*(u32*)code = value; code+=4;}
+
+public:
+ ARMXEmitter() : code(0), startcode(0), lastCacheFlushEnd(0) {
+ condition = CC_AL << 28;
+ }
+ ARMXEmitter(u8 *code_ptr) {
+ code = code_ptr;
+ lastCacheFlushEnd = code_ptr;
+ startcode = code_ptr;
+ condition = CC_AL << 28;
+ }
+ virtual ~ARMXEmitter() {}
+
+ void SetCodePtr(u8 *ptr);
+ void ReserveCodeSpace(u32 bytes);
+ const u8 *AlignCode16();
+ const u8 *AlignCodePage();
+ const u8 *GetCodePtr() const;
+ void FlushIcache();
+ void FlushIcacheSection(u8 *start, u8 *end);
+ u8 *GetWritableCodePtr();
+
+ void FlushLitPool();
+ void AddNewLit(u32 val);
+
+ CCFlags GetCC() { return CCFlags(condition >> 28); }
+ void SetCC(CCFlags cond = CC_AL);
+
+ // Special purpose instructions
+
+ // Dynamic Endian Switching
+ void SETEND(bool BE);
+ // Debug Breakpoint
+ void BKPT(u16 arg);
+
+ // Hint instruction
+ void YIELD();
+
+ // Do nothing
+ void NOP(int count = 1); //nop padding - TODO: fast nop slides, for amd and intel (check their manuals)
+
+#ifdef CALL
+#undef CALL
+#endif
+
+ // Branching
+ FixupBranch B();
+ FixupBranch B_CC(CCFlags Cond);
+ void B_CC(CCFlags Cond, const void *fnptr);
+ FixupBranch BL();
+ FixupBranch BL_CC(CCFlags Cond);
+ void SetJumpTarget(FixupBranch const &branch);
+
+ void B (const void *fnptr);
+ void B (ARMReg src);
+ void BL(const void *fnptr);
+ void BL(ARMReg src);
+
+ void PUSH(const int num, ...);
+ void POP(const int num, ...);
+
+ // New Data Ops
+ void AND (ARMReg Rd, ARMReg Rn, Operand2 Rm);
+ void ANDS(ARMReg Rd, ARMReg Rn, Operand2 Rm);
+ void EOR (ARMReg dest, ARMReg src, Operand2 op2);
+ void EORS(ARMReg dest, ARMReg src, Operand2 op2);
+ void SUB (ARMReg dest, ARMReg src, Operand2 op2);
+ void SUBS(ARMReg dest, ARMReg src, Operand2 op2);
+ void RSB (ARMReg dest, ARMReg src, Operand2 op2);
+ void RSBS(ARMReg dest, ARMReg src, Operand2 op2);
+ void ADD (ARMReg dest, ARMReg src, Operand2 op2);
+ void ADDS(ARMReg dest, ARMReg src, Operand2 op2);
+ void ADC (ARMReg dest, ARMReg src, Operand2 op2);
+ void ADCS(ARMReg dest, ARMReg src, Operand2 op2);
+ void LSL (ARMReg dest, ARMReg src, Operand2 op2);
+ void LSL (ARMReg dest, ARMReg src, ARMReg op2);
+ void LSLS(ARMReg dest, ARMReg src, Operand2 op2);
+ void LSLS(ARMReg dest, ARMReg src, ARMReg op2);
+ void LSR (ARMReg dest, ARMReg src, Operand2 op2);
+ void SBC (ARMReg dest, ARMReg src, Operand2 op2);
+ void SBCS(ARMReg dest, ARMReg src, Operand2 op2);
+ void RBIT(ARMReg dest, ARMReg src);
+ void REV (ARMReg dest, ARMReg src);
+ void REV16 (ARMReg dest, ARMReg src);
+ void RSC (ARMReg dest, ARMReg src, Operand2 op2);
+ void RSCS(ARMReg dest, ARMReg src, Operand2 op2);
+ void TST ( ARMReg src, Operand2 op2);
+ void TEQ ( ARMReg src, Operand2 op2);
+ void CMP ( ARMReg src, Operand2 op2);
+ void CMN ( ARMReg src, Operand2 op2);
+ void ORR (ARMReg dest, ARMReg src, Operand2 op2);
+ void ORRS(ARMReg dest, ARMReg src, Operand2 op2);
+ void MOV (ARMReg dest, Operand2 op2);
+ void MOVS(ARMReg dest, Operand2 op2);
+ void BIC (ARMReg dest, ARMReg src, Operand2 op2); // BIC = ANDN
+ void BICS(ARMReg dest, ARMReg src, Operand2 op2);
+ void MVN (ARMReg dest, Operand2 op2);
+ void MVNS(ARMReg dest, Operand2 op2);
+ void MOVW(ARMReg dest, Operand2 op2);
+ void MOVT(ARMReg dest, Operand2 op2, bool TopBits = false);
+
+ // UDIV and SDIV are only available on CPUs that have
+ // the idiva hardare capacity
+ void UDIV(ARMReg dest, ARMReg dividend, ARMReg divisor);
+ void SDIV(ARMReg dest, ARMReg dividend, ARMReg divisor);
+
+ void MUL (ARMReg dest, ARMReg src, ARMReg op2);
+ void MULS(ARMReg dest, ARMReg src, ARMReg op2);
+
+ void UMULL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
+ void SMULL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
+
+ void UMLAL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
+ void SMLAL(ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
+
+ void SXTB(ARMReg dest, ARMReg op2);
+ void SXTH(ARMReg dest, ARMReg op2, u8 rotation = 0);
+ void SXTAH(ARMReg dest, ARMReg src, ARMReg op2, u8 rotation = 0);
+ void BFI(ARMReg rd, ARMReg rn, u8 lsb, u8 width);
+ void UBFX(ARMReg dest, ARMReg op2, u8 lsb, u8 width);
+ void CLZ(ARMReg rd, ARMReg rm);
+
+ // Using just MSR here messes with our defines on the PPC side of stuff (when this code was in dolphin...)
+ // Just need to put an underscore here, bit annoying.
+ void _MSR (bool nzcvq, bool g, Operand2 op2);
+ void _MSR (bool nzcvq, bool g, ARMReg src);
+ void MRS (ARMReg dest);
+
+ // Memory load/store operations
+ void LDR (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+ void LDRB (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+ void LDRH (ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+ void LDRSB(ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+ void LDRSH(ARMReg dest, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+ void STR (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+ void STRB (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+ void STRH (ARMReg result, ARMReg base, Operand2 op2 = 0, bool RegAdd = true);
+
+ void STMFD(ARMReg dest, bool WriteBack, const int Regnum, ...);
+ void LDMFD(ARMReg dest, bool WriteBack, const int Regnum, ...);
+
+ // Exclusive Access operations
+ void LDREX(ARMReg dest, ARMReg base);
+ // result contains the result if the instruction managed to store the value
+ void STREX(ARMReg result, ARMReg base, ARMReg op);
+ void DMB ();
+ void SVC(Operand2 op);
+
+ // NEON and ASIMD instructions
+ // None of these will be created with conditional since ARM
+ // is deprecating conditional execution of ASIMD instructions.
+ // ASIMD instructions don't even have a conditional encoding.
+
+ // Subtracts the base from the register to give us the real one
+ ARMReg SubBase(ARMReg Reg);
+ // NEON Only
+ void VADD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
+
+ // VFP Only
+ void VLDR(ARMReg Dest, ARMReg Base, s16 offset);
+ void VSTR(ARMReg Src, ARMReg Base, s16 offset);
+ void VCMP(ARMReg Vd, ARMReg Vm);
+ void VCMPE(ARMReg Vd, ARMReg Vm);
+ // Compares against zero
+ void VCMP(ARMReg Vd);
+ void VCMPE(ARMReg Vd);
+ void VDIV(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VSQRT(ARMReg Vd, ARMReg Vm);
+
+ // NEON and VFP
+ void VADD(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VSUB(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VABS(ARMReg Vd, ARMReg Vm);
+ void VNEG(ARMReg Vd, ARMReg Vm);
+ void VMUL(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VMLA(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VMLS(ARMReg Vd, ARMReg Vn, ARMReg Vm);
+ void VMOV(ARMReg Dest, ARMReg Src, bool high);
+ void VMOV(ARMReg Dest, ARMReg Src);
+ void VCVT(ARMReg Dest, ARMReg Src, int flags);
+
+ void VMRS_APSR();
+ void VMRS(ARMReg Rt);
+ void VMSR(ARMReg Rt);
+
+ void QuickCallFunction(ARMReg scratchreg, void *func);
+
+ // Wrapper around MOVT/MOVW with fallbacks.
+ void MOVI2R(ARMReg reg, u32 val, bool optimize = true);
+ void MOVI2F(ARMReg dest, float val, ARMReg tempReg);
+
+ void ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
+ void ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
+
+
+}; // class ARMXEmitter
+
+
+// Everything that needs to generate X86 code should inherit from this.
+// You get memory management for free, plus, you can use all the MOV etc functions without
+// having to prefix them with gen-> or something similar.
+class ARMXCodeBlock : public ARMXEmitter
+{
+protected:
+ u8 *region;
+ size_t region_size;
+
+public:
+ ARMXCodeBlock() : region(NULL), region_size(0) {}
+ virtual ~ARMXCodeBlock() { if (region) FreeCodeSpace(); }
+
+ // Call this before you generate any code.
+ void AllocCodeSpace(int size)
+ {
+ region_size = size;
+ region = (u8*)AllocateExecutableMemory(region_size);
+ SetCodePtr(region);
+ }
+
+ // Always clear code space with breakpoints, so that if someone accidentally executes
+ // uninitialized, it just breaks into the debugger.
+ void ClearCodeSpace()
+ {
+ // x86/64: 0xCC = breakpoint
+ memset(region, 0xCC, region_size);
+ ResetCodePtr();
+ }
+
+ // Call this when shutting down. Don't rely on the destructor, even though it'll do the job.
+ void FreeCodeSpace()
+ {
+#ifndef __SYMBIAN32__
+ FreeMemoryPages(region, region_size);
+#endif
+ region = NULL;
+ region_size = 0;
+ }
+
+ bool IsInSpace(u8 *ptr)
+ {
+ return ptr >= region && ptr < region + region_size;
+ }
+
+ // Cannot currently be undone. Will write protect the entire code region.
+ // Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()).
+ void WriteProtect()
+ {
+ WriteProtectMemory(region, region_size, true);
+ }
+
+ void ResetCodePtr()
+ {
+ SetCodePtr(region);
+ }
+
+ size_t GetSpaceLeft() const
+ {
+ return region_size - (GetCodePtr() - region);
+ }
+};
+
+} // namespace
+
+#endif // _DOLPHIN_INTEL_CODEGEN_
diff --git a/Source/Core/Common/Src/BreakPoints.h b/Source/Core/Common/Src/BreakPoints.h
index c742f812a7..1268b4e80a 100644
--- a/Source/Core/Common/Src/BreakPoints.h
+++ b/Source/Core/Common/Src/BreakPoints.h
@@ -27,9 +27,9 @@ class DebugInterface;
struct TBreakPoint
{
- u32 iAddress;
+ u32 iAddress;
bool bOn;
- bool bTemporary;
+ bool bTemporary;
};
struct TMemCheck
@@ -96,9 +96,9 @@ public:
typedef std::vector<std::string> TMemChecksStr;
TMemChecks m_MemChecks;
-
+
const TMemChecks& GetMemChecks() { return m_MemChecks; }
-
+
TMemChecksStr GetStrings() const;
void AddFromStrings(const TMemChecksStr& mcs);
diff --git a/Source/Core/Common/Src/CDUtils.cpp b/Source/Core/Common/Src/CDUtils.cpp
index 42aa9bfe34..9a302b9189 100644
--- a/Source/Core/Common/Src/CDUtils.cpp
+++ b/Source/Core/Common/Src/CDUtils.cpp
@@ -6,6 +6,7 @@
#include <memory> // for std::unique_ptr
#ifdef _WIN32
#include <windows.h>
+#include "StringUtil.h"
#elif __APPLE__
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOBSD.h>
@@ -25,7 +26,7 @@
#ifdef _WIN32
// takes a root drive path, returns true if it is a cdrom drive
-bool is_cdrom(const char drive[])
+bool is_cdrom(const TCHAR* drive)
{
return (DRIVE_CDROM == GetDriveType(drive));
}
@@ -36,15 +37,15 @@ std::vector<std::string> cdio_get_devices()
std::vector<std::string> drives;
const DWORD buffsize = GetLogicalDriveStrings(0, NULL);
- std::unique_ptr<char[]> buff(new char[buffsize]);
- if (GetLogicalDriveStrings(buffsize, buff.get()) == buffsize - 1)
+ std::vector<TCHAR> buff(buffsize);
+ if (GetLogicalDriveStrings(buffsize, buff.data()) == buffsize - 1)
{
- const char* drive = buff.get();
+ auto drive = buff.data();
while (*drive)
{
if (is_cdrom(drive))
{
- std::string str(drive);
+ std::string str(TStrToUTF8(drive));
str.pop_back(); // we don't want the final backslash
drives.push_back(std::move(str));
}
diff --git a/Source/Core/Common/Src/CPUDetect.h b/Source/Core/Common/Src/CPUDetect.h
index 928b34c109..5c2b33b4b3 100644
--- a/Source/Core/Common/Src/CPUDetect.h
+++ b/Source/Core/Common/Src/CPUDetect.h
@@ -25,19 +25,20 @@ enum CPUVendor
{
VENDOR_INTEL = 0,
VENDOR_AMD = 1,
- VENDOR_OTHER = 2,
+ VENDOR_ARM = 2,
+ VENDOR_OTHER = 3,
};
struct CPUInfo
{
CPUVendor vendor;
-
+
char cpu_string[0x21];
char brand_string[0x41];
bool OS64bit;
bool CPU64bit;
bool Mode64bit;
-
+
bool HTT;
int num_cores;
int logical_cpu_count;
@@ -56,9 +57,29 @@ struct CPUInfo
bool bLAHFSAHF64;
bool bLongMode;
+ // ARM specific CPUInfo
+ bool bSwp;
+ bool bHalf;
+ bool bThumb;
+ bool bFastMult;
+ bool bVFP;
+ bool bEDSP;
+ bool bThumbEE;
+ bool bNEON;
+ bool bVFPv3;
+ bool bTLS;
+ bool bVFPv4;
+ bool bIDIVa;
+ bool bIDIVt;
+ bool bArmV7; // enable MOVT, MOVW etc
+
+ // ARMv8 specific
+ bool bFP;
+ bool bASIMD;
+
// Call Detect()
explicit CPUInfo();
-
+
// Turn the cpu info into a string we can show
std::string Summarize();
diff --git a/Source/Core/Common/Src/ChunkFile.h b/Source/Core/Common/Src/ChunkFile.h
index 38e1b2176c..ecf641a27b 100644
--- a/Source/Core/Common/Src/ChunkFile.h
+++ b/Source/Core/Common/Src/ChunkFile.h
@@ -29,6 +29,7 @@
#include <map>
#include <vector>
+#include <list>
#include <deque>
#include <string>
@@ -45,7 +46,8 @@ struct LinkedListItem : public T
class PointerWrap
{
public:
- enum Mode {
+ enum Mode
+ {
MODE_READ = 1, // load
MODE_WRITE, // save
MODE_MEASURE, // calculate size
@@ -57,124 +59,95 @@ public:
public:
PointerWrap(u8 **ptr_, Mode mode_) : ptr(ptr_), mode(mode_) {}
- PointerWrap(unsigned char **ptr_, int mode_) : ptr((u8**)ptr_), mode((Mode)mode_) {}
- void SetMode(Mode mode_) {mode = mode_;}
- Mode GetMode() const {return mode;}
- u8 **GetPPtr() {return ptr;}
+ void SetMode(Mode mode_) { mode = mode_; }
+ Mode GetMode() const { return mode; }
+ u8** GetPPtr() { return ptr; }
- void DoVoid(void *data, int size)
+ template <typename K, class V>
+ void Do(std::map<K, V>& x)
{
- switch (mode) {
- case MODE_READ: memcpy(data, *ptr, size); break;
- case MODE_WRITE: memcpy(*ptr, data, size); break;
- case MODE_MEASURE: break; // MODE_MEASURE - don't need to do anything
- case MODE_VERIFY: for(int i = 0; i < size; i++) _dbg_assert_msg_(COMMON, ((u8*)data)[i] == (*ptr)[i], "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n", ((u8*)data)[i], ((u8*)data)[i], &((u8*)data)[i], (*ptr)[i], (*ptr)[i], &(*ptr)[i]); break;
- default: break; // throw an error?
- }
- (*ptr) += size;
- }
+ u32 count = (u32)x.size();
+ Do(count);
- template<class T>
- void Do(std::map<unsigned int, T> &x)
- {
- unsigned int number = (unsigned int)x.size();
- Do(number);
- switch (mode) {
+ switch (mode)
+ {
case MODE_READ:
+ for (x.clear(); count != 0; --count)
{
- x.clear();
- while (number > 0)
- {
- unsigned int first = 0;
- Do(first);
- T second;
- Do(second);
- x[first] = second;
- --number;
- }
+ std::pair<K, V> pair;
+ Do(pair.first);
+ Do(pair.second);
+ x.insert(pair);
}
break;
+
case MODE_WRITE:
case MODE_MEASURE:
case MODE_VERIFY:
+ for (auto itr = x.begin(); itr != x.end(); ++itr)
{
- typename std::map<unsigned int, T>::iterator itr = x.begin();
- while (number > 0)
- {
- Do(itr->first);
- Do(itr->second);
- --number;
- ++itr;
- }
+ Do(itr->first);
+ Do(itr->second);
}
break;
}
}
- // Store vectors.
- template<class T>
- void Do(std::vector<T> &x)
+ template <typename T>
+ void DoContainer(T& x)
{
- u32 vec_size = (u32)x.size();
- Do(vec_size);
- x.resize(vec_size);
- DoArray(&x[0], vec_size);
+ u32 size = (u32)x.size();
+ Do(size);
+ x.resize(size);
+
+ for (auto itr = x.begin(); itr != x.end(); ++itr)
+ Do(*itr);
}
-
- // Store deques.
- template<class T>
- void Do(std::deque<T> &x)
+
+ template <typename T>
+ void Do(std::vector<T>& x)
{
- u32 deq_size = (u32)x.size();
- Do(deq_size);
- x.resize(deq_size);
- u32 i;
- for(i = 0; i < deq_size; i++)
- DoVoid(&x[i],sizeof(T));
+ DoContainer(x);
}
-
- // Store strings.
- void Do(std::string &x)
+
+ template <typename T>
+ void Do(std::list<T>& x)
{
- int stringLen = (int)x.length() + 1;
- Do(stringLen);
-
- switch (mode) {
- case MODE_READ: x = (char*)*ptr; break;
- case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break;
- case MODE_MEASURE: break;
- case MODE_VERIFY: _dbg_assert_msg_(COMMON, !strcmp(x.c_str(), (char*)*ptr), "Savestate verification failure: \"%s\" != \"%s\" (at %p).\n", x.c_str(), (char*)*ptr, ptr); break;
- }
- (*ptr) += stringLen;
+ DoContainer(x);
}
- void Do(std::wstring &x)
+ template <typename T>
+ void Do(std::deque<T>& x)
{
- int stringLen = sizeof(wchar_t)*((int)x.length() + 1);
- Do(stringLen);
-
- switch (mode) {
- case MODE_READ: x.assign((wchar_t*)*ptr, (stringLen / sizeof(wchar_t)) - 1); 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: \"%ls\" != \"%ls\" (at %p).\n", x.c_str(), (wchar_t*)*ptr, ptr); break;
- }
- (*ptr) += stringLen;
+ DoContainer(x);
}
- template<class T>
- void DoArray(T *x, int count) {
- DoVoid((void *)x, sizeof(T) * count);
- }
-
- template<class T>
- void Do(T &x) {
- DoVoid((void *)&x, sizeof(x));
+ template <typename T>
+ void Do(std::basic_string<T>& x)
+ {
+ DoContainer(x);
}
- template<class T>
- void DoPointer(T* &x, T*const base) {
+ template <typename T>
+ void DoArray(T* x, u32 count)
+ {
+ for (u32 i = 0; i != count; ++i)
+ Do(x[i]);
+ }
+
+ template <typename T>
+ void Do(T& x)
+ {
+ // TODO: Bad, Do(some_non_POD) will compile and fail at runtime
+ // type_traits are not fully supported everywhere yet
+
+ DoVoid((void*)&x, sizeof(x));
+ }
+
+ template <typename T>
+ void DoPointer(T*& x, T* const base)
+ {
// pointers can be more than 2^31 apart, but you're using this function wrong if you need that much range
s32 offset = x - base;
Do(offset);
@@ -182,7 +155,8 @@ public:
x = base + offset;
}
- template<class T, LinkedListItem<T>* (*TNew)(), void (*TFree)(LinkedListItem<T>*), void (*TDo)(PointerWrap&, T*)>
+ // Let's pretend std::list doesn't exist!
+ template <class T, LinkedListItem<T>* (*TNew)(), void (*TFree)(LinkedListItem<T>*), void (*TDo)(PointerWrap&, T*)>
void DoLinkedList(LinkedListItem<T>*& list_start, LinkedListItem<T>** list_end=0)
{
LinkedListItem<T>* list_cur = list_start;
@@ -242,25 +216,61 @@ public:
}
}
- void DoMarker(const char* prevName, u32 arbitraryNumber=0x42)
+ void DoMarker(const char* prevName, u32 arbitraryNumber = 0x42)
{
u32 cookie = arbitraryNumber;
Do(cookie);
- if(mode == PointerWrap::MODE_READ && cookie != arbitraryNumber)
+
+ 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);
+ 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;
}
}
-};
+private:
+ __forceinline void DoByte(u8& x)
+ {
+ switch (mode)
+ {
+ case MODE_READ:
+ x = **ptr;
+ break;
+
+ case MODE_WRITE:
+ **ptr = x;
+ break;
+
+ case MODE_MEASURE:
+ break;
+
+ case MODE_VERIFY:
+ _dbg_assert_msg_(COMMON, (x == **ptr),
+ "Savestate verification failure: %d (0x%X) (at %p) != %d (0x%X) (at %p).\n",
+ x, x, &x, **ptr, **ptr, *ptr);
+ break;
+
+ default:
+ break;
+ }
+
+ ++(*ptr);
+ }
+
+ void DoVoid(void *data, u32 size)
+ {
+ for(u32 i = 0; i != size; ++i)
+ DoByte(reinterpret_cast<u8*>(data)[i]);
+ }
+};
class CChunkFileReader
{
public:
// Load file template
template<class T>
- static bool Load(const std::string& _rFilename, int _Revision, T& _class)
+ static bool Load(const std::string& _rFilename, u32 _Revision, T& _class)
{
INFO_LOG(COMMON, "ChunkReader: Loading %s" , _rFilename.c_str());
@@ -290,7 +300,7 @@ public:
ERROR_LOG(COMMON,"ChunkReader: Bad header size");
return false;
}
-
+
// Check revision
if (header.Revision != _Revision)
{
@@ -298,36 +308,35 @@ public:
header.Revision, _Revision);
return false;
}
-
+
// get size
- const int sz = (int)(fileSize - headerSize);
+ const u32 sz = (u32)(fileSize - headerSize);
if (header.ExpectedSize != sz)
{
ERROR_LOG(COMMON,"ChunkReader: Bad file size, got %d expected %d",
sz, header.ExpectedSize);
return false;
}
-
+
// read the state
- u8* buffer = new u8[sz];
- if (!pFile.ReadBytes(buffer, sz))
+ std::vector<u8> buffer(sz);
+ if (!pFile.ReadArray(&buffer[0], sz))
{
ERROR_LOG(COMMON,"ChunkReader: Error reading file");
return false;
}
- u8 *ptr = buffer;
+ u8* ptr = &buffer[0];
PointerWrap p(&ptr, PointerWrap::MODE_READ);
_class.DoState(p);
- delete[] buffer;
INFO_LOG(COMMON, "ChunkReader: Done loading %s" , _rFilename.c_str());
return true;
}
-
+
// Save file template
template<class T>
- static bool Save(const std::string& _rFilename, int _Revision, T& _class)
+ static bool Save(const std::string& _rFilename, u32 _Revision, T& _class)
{
INFO_LOG(COMMON, "ChunkReader: Writing %s" , _rFilename.c_str());
File::IOFile pFile(_rFilename, "wb");
@@ -346,13 +355,12 @@ public:
ptr = &buffer[0];
p.SetMode(PointerWrap::MODE_WRITE);
_class.DoState(p);
-
+
// Create header
SChunkHeader header;
- header.Compress = 0;
header.Revision = _Revision;
- header.ExpectedSize = (int)sz;
-
+ header.ExpectedSize = (u32)sz;
+
// Write to file
if (!pFile.WriteArray(&header, 1))
{
@@ -360,23 +368,21 @@ public:
return false;
}
- if (!pFile.WriteBytes(&buffer[0], sz))
+ if (!pFile.WriteArray(&buffer[0], sz))
{
ERROR_LOG(COMMON,"ChunkReader: Failed writing data");
return false;
}
-
- INFO_LOG(COMMON,"ChunkReader: Done writing %s",
- _rFilename.c_str());
+
+ INFO_LOG(COMMON,"ChunkReader: Done writing %s", _rFilename.c_str());
return true;
}
-
+
private:
struct SChunkHeader
{
- int Revision;
- int Compress;
- int ExpectedSize;
+ u32 Revision;
+ u32 ExpectedSize;
};
};
diff --git a/Source/Core/Common/Src/Common.h b/Source/Core/Common/Src/Common.h
index c3cab37dd8..904095e255 100644
--- a/Source/Core/Common/Src/Common.h
+++ b/Source/Core/Common/Src/Common.h
@@ -133,7 +133,9 @@ private:
// wxWidgets does not have a true dummy macro for this.
#define _trans(a) a
-#if defined __GNUC__
+#if defined _M_GENERIC
+# define _M_SSE 0x0
+#elif defined __GNUC__
# if defined __SSE4_2__
# define _M_SSE 0x402
# elif defined __SSE4_1__
@@ -144,7 +146,7 @@ private:
# define _M_SSE 0x300
# endif
#elif (_MSC_VER >= 1500) || __INTEL_COMPILER // Visual Studio 2008
-# define _M_SSE 0x402
+# define _M_SSE 0x402
#endif
// Host communication.
@@ -155,7 +157,6 @@ enum HOST_COMM
WM_USER_CREATE,
WM_USER_SETCURSOR,
WM_USER_KEYDOWN,
- WIIMOTE_DISCONNECT // Disconnect Wiimote
};
// Used for notification on emulation state
diff --git a/Source/Core/Common/Src/CommonFuncs.h b/Source/Core/Common/Src/CommonFuncs.h
index 585fe0999a..f892769280 100644
--- a/Source/Core/Common/Src/CommonFuncs.h
+++ b/Source/Core/Common/Src/CommonFuncs.h
@@ -35,7 +35,7 @@ template<> struct CompileTimeAssert<true> {};
#define b32(x) (b16(x) | (b16(x) >>16) )
#define ROUND_UP_POW2(x) (b32(x - 1) + 1)
-#if defined __GNUC__ && !defined __SSSE3__
+#if defined __GNUC__ && !defined __SSSE3__ && !defined _M_GENERIC
#include <emmintrin.h>
static __inline __m128i __attribute__((__always_inline__))
_mm_shuffle_epi8(__m128i a, __m128i mask)
@@ -60,15 +60,17 @@ _mm_shuffle_epi8(__m128i a, __m128i mask)
// go to debugger mode
#ifdef GEKKO
#define Crash()
+ #elif defined _M_GENERIC
+ #define Crash() { exit(1); }
#else
#define Crash() {asm ("int $3");}
#endif
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
inline u32 _rotl(u32 x, int shift) {
- shift &= 31;
- if (!shift) return x;
- return (x << shift) | (x >> (32 - shift));
+ shift &= 31;
+ if (!shift) return x;
+ return (x << shift) | (x >> (32 - shift));
}
inline u64 _rotl64(u64 x, unsigned int shift){
@@ -77,9 +79,9 @@ inline u64 _rotl64(u64 x, unsigned int shift){
}
inline u32 _rotr(u32 x, int shift) {
- shift &= 31;
- if (!shift) return x;
- return (x >> shift) | (x << (32 - shift));
+ shift &= 31;
+ if (!shift) return x;
+ return (x >> shift) | (x << (32 - shift));
}
inline u64 _rotr64(u64 x, unsigned int shift){
@@ -136,6 +138,15 @@ inline u8 swap8(u8 _data) {return _data;}
inline u16 swap16(u16 _data) {return _byteswap_ushort(_data);}
inline u32 swap32(u32 _data) {return _byteswap_ulong (_data);}
inline u64 swap64(u64 _data) {return _byteswap_uint64(_data);}
+#elif _M_ARM
+#ifdef ANDROID
+#undef swap16
+#undef swap32
+#undef swap64
+#endif
+inline u16 swap16 (u16 _data) { u32 data = _data; __asm__ ("rev16 %0, %1\n" : "=l" (data) : "l" (data)); return (u16)data;}
+inline u32 swap32 (u32 _data) {__asm__ ("rev %0, %1\n" : "=l" (_data) : "l" (_data)); return _data;}
+inline u64 swap64(u64 _data) {return ((u64)swap32(_data) << 32) | swap32(_data >> 32);}
#elif __linux__
inline u16 swap16(u16 _data) {return bswap_16(_data);}
inline u32 swap32(u32 _data) {return bswap_32(_data);}
@@ -162,6 +173,40 @@ inline u16 swap16(const u8* _pData) {return swap16(*(const u16*)_pData);}
inline u32 swap32(const u8* _pData) {return swap32(*(const u32*)_pData);}
inline u64 swap64(const u8* _pData) {return swap64(*(const u64*)_pData);}
+template <int count>
+void swap(u8*);
+
+template <>
+inline void swap<1>(u8* data)
+{}
+
+template <>
+inline void swap<2>(u8* data)
+{
+ *reinterpret_cast<u16*>(data) = swap16(data);
+}
+
+template <>
+inline void swap<4>(u8* data)
+{
+ *reinterpret_cast<u32*>(data) = swap32(data);
+}
+
+template <>
+inline void swap<8>(u8* data)
+{
+ *reinterpret_cast<u64*>(data) = swap64(data);
+}
+
+template <typename T>
+inline T FromBigEndian(T data)
+{
+ //static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types");
+
+ swap<sizeof(data)>(reinterpret_cast<u8*>(&data));
+ return data;
+}
+
} // Namespace Common
#endif // _COMMONFUNCS_H_
diff --git a/Source/Core/Common/Src/CommonPaths.h b/Source/Core/Common/Src/CommonPaths.h
index 01180c67e3..ac6676cfcb 100644
--- a/Source/Core/Common/Src/CommonPaths.h
+++ b/Source/Core/Common/Src/CommonPaths.h
@@ -36,6 +36,9 @@
// You can use the File::GetUserPath() util for this
#define USERDATA_DIR "Contents/Resources/User"
#define DOLPHIN_DATA_DIR "Library/Application Support/Dolphin"
+#elif defined ANDROID
+ #define USERDATA_DIR "user"
+ #define DOLPHIN_DATA_DIR "/sdcard/dolphin-emu"
#else
#define USERDATA_DIR "user"
#ifdef USER_DIR
@@ -52,6 +55,8 @@
#define SYSDATA_DIR "Contents/Resources/Sys"
#define SHARED_USER_DIR File::GetBundleDirectory() + \
DIR_SEP USERDATA_DIR DIR_SEP
+#elif defined ANDROID
+ #define SYSDATA_DIR "/sdcard/dolphin-emu"
#else
#ifdef DATA_DIR
#define SYSDATA_DIR DATA_DIR "sys"
@@ -123,9 +128,9 @@
#define GC_MEMCARDA "MemoryCardA"
#define GC_MEMCARDB "MemoryCardB"
-#define WII_STATE "state.dat"
+#define WII_STATE "state.dat"
-#define WII_SETTING "setting.txt"
+#define WII_SETTING "setting.txt"
#define GECKO_CODE_HANDLER "codehandler.bin"
diff --git a/Source/Core/Common/Src/ConsoleListener.cpp b/Source/Core/Common/Src/ConsoleListener.cpp
index cf03581431..934300f777 100644
--- a/Source/Core/Common/Src/ConsoleListener.cpp
+++ b/Source/Core/Common/Src/ConsoleListener.cpp
@@ -61,7 +61,7 @@ void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title
// Save the window handle that AllocConsole() created
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Set the console window title
- SetConsoleTitle(Title);
+ SetConsoleTitle(UTF8ToTStr(Title).c_str());
// Set letter space
LetterSpace(80, 4000);
//MoveWindow(GetConsoleWindow(), 200,200, 800,800, true);
@@ -195,7 +195,7 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool
static const int MAX_BYTES = 1024 * 16;
- std::vector<std::array<CHAR, MAX_BYTES>> Str;
+ std::vector<std::array<TCHAR, MAX_BYTES>> Str;
std::vector<std::array<WORD, MAX_BYTES>> Attr;
// ReadConsoleOutputAttribute seems to have a limit at this level
@@ -227,7 +227,7 @@ void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool
LetterSpace(LBufWidth, LBufHeight);
- ClearScreen(true);
+ ClearScreen(true);
coordScreen.Y = 0;
coordScreen.X = 0;
DWORD cCharsWritten = 0;
@@ -270,7 +270,7 @@ void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text)
*/
DWORD cCharsWritten;
WORD Color;
-
+
switch (Level)
{
case NOTICE_LEVEL: // light green
@@ -334,9 +334,9 @@ void ConsoleListener::ClearScreen(bool Cursor)
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
-
+
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
-
+
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
// Write space to the entire console
diff --git a/Source/Core/Common/Src/Crypto/md5.cpp b/Source/Core/Common/Src/Crypto/md5.cpp
index 7fff7713da..7b8dc149f4 100644
--- a/Source/Core/Common/Src/Crypto/md5.cpp
+++ b/Source/Core/Common/Src/Crypto/md5.cpp
@@ -37,6 +37,8 @@
#include <string.h>
#include <stdio.h>
+#include "../FileUtil.h"
+
/*
* 32-bit integer manipulation macros (little endian)
*/
@@ -301,7 +303,10 @@ int md5_file( char *path, unsigned char output[16] )
md5_context ctx;
unsigned char buf[1024];
- if( ( f = fopen( path, "rb" ) ) == NULL )
+ File::IOFile file(path, "rb");
+ f = file.GetHandle();
+
+ if (f == NULL)
return( 1 );
md5_starts( &ctx );
@@ -315,11 +320,9 @@ int md5_file( char *path, unsigned char output[16] )
if( ferror( f ) != 0 )
{
- fclose( f );
return( 2 );
}
- fclose( f );
return( 0 );
}
diff --git a/Source/Core/Common/Src/Crypto/sha1.cpp b/Source/Core/Common/Src/Crypto/sha1.cpp
index 17ad930986..45b88b2b6e 100644
--- a/Source/Core/Common/Src/Crypto/sha1.cpp
+++ b/Source/Core/Common/Src/Crypto/sha1.cpp
@@ -36,6 +36,8 @@
#include <string.h>
#include <stdio.h>
+#include "../FileUtil.h"
+
/*
* 32-bit integer manipulation macros (big endian)
*/
@@ -335,7 +337,10 @@ int sha1_file( char *path, unsigned char output[20] )
sha1_context ctx;
unsigned char buf[1024];
- if( ( f = fopen( path, "rb" ) ) == NULL )
+ File::IOFile file(path, "rb");
+ f = file.GetHandle();
+
+ if (f == NULL)
return( 1 );
sha1_starts( &ctx );
@@ -349,11 +354,9 @@ int sha1_file( char *path, unsigned char output[20] )
if( ferror( f ) != 0 )
{
- fclose( f );
return( 2 );
}
- fclose( f );
return( 0 );
}
diff --git a/Source/Core/Common/Src/ExtendedTrace.cpp b/Source/Core/Common/Src/ExtendedTrace.cpp
index 3fe661f2e4..85057639a5 100644
--- a/Source/Core/Common/Src/ExtendedTrace.cpp
+++ b/Source/Core/Common/Src/ExtendedTrace.cpp
@@ -17,6 +17,7 @@
#include <windows.h>
#include <stdio.h>
#include "ExtendedTrace.h"
+#include "StringUtil.h"
using namespace std;
#include <tchar.h>
@@ -274,13 +275,21 @@ static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo )
return ret;
}
-void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
+void PrintFunctionAndSourceInfo(FILE* file, const STACKFRAME& callstack)
+{
+ TCHAR symInfo[BUFFERSIZE] = _T("?");
+ TCHAR srcInfo[BUFFERSIZE] = _T("?");
+
+ GetFunctionInfoFromAddresses((ULONG)callstack.AddrPC.Offset, (ULONG)callstack.AddrFrame.Offset, symInfo);
+ GetSourceInfoFromAddress((ULONG)callstack.AddrPC.Offset, srcInfo);
+ etfprint(file, " " + TStrToUTF8(srcInfo) + " : " + TStrToUTF8(symInfo) + "\n");
+}
+
+void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file )
{
STACKFRAME callStack;
BOOL bResult;
CONTEXT context;
- TCHAR symInfo[BUFFERSIZE] = _T("?");
- TCHAR srcInfo[BUFFERSIZE] = _T("?");
HANDLE hProcess = GetCurrentProcess();
// If it's not this thread, let's suspend it, and resume it at the end
@@ -318,9 +327,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
etfprint(file, "Call stack info: \n");
etfprint(file, lpszMessage);
- GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
- GetSourceInfoFromAddress( (ULONG)callStack.AddrPC.Offset, srcInfo );
- etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
+ PrintFunctionAndSourceInfo(file, callStack);
for( ULONG index = 0; ; index++ )
{
@@ -341,9 +348,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
if( !bResult || callStack.AddrFrame.Offset == 0 )
break;
- GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
- GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo );
- etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
+ PrintFunctionAndSourceInfo(file, callStack);
}
@@ -351,19 +356,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file )
ResumeThread( hThread );
}
-void StackTrace( HANDLE hThread, wchar_t const*lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
-{
- // TODO: remove when Common builds as unicode
- size_t origsize = wcslen(lpszMessage) + 1;
- const size_t newsize = 100;
- size_t convertedChars = 0;
- char nstring[newsize];
- wcstombs_s(&convertedChars, nstring, origsize, lpszMessage, _TRUNCATE);
-
- StackTrace(hThread, nstring, file, eip, esp, ebp );
-}
-
-void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
+void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
{
STACKFRAME callStack;
BOOL bResult;
@@ -391,9 +384,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO
etfprint(file, "Call stack info: \n");
etfprint(file, lpszMessage);
- GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
- GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo );
- etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
+ PrintFunctionAndSourceInfo(file, callStack);
for( ULONG index = 0; ; index++ )
{
@@ -414,10 +405,7 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO
if( !bResult || callStack.AddrFrame.Offset == 0 )
break;
- GetFunctionInfoFromAddresses( (ULONG)callStack.AddrPC.Offset, (ULONG)callStack.AddrFrame.Offset, symInfo );
- GetSourceInfoFromAddress( (UINT)callStack.AddrPC.Offset, srcInfo );
- etfprint(file, string(" ") + srcInfo + string(" : ") + symInfo + string("\n"));
-
+ PrintFunctionAndSourceInfo(file, callStack);
}
if ( hThread != GetCurrentThread() )
@@ -426,7 +414,8 @@ void StackTrace( HANDLE hThread, LPCTSTR lpszMessage, FILE *file, DWORD eip, DWO
char g_uefbuf[2048];
-void etfprintf(FILE *file, const char *format, ...) {
+void etfprintf(FILE *file, const char *format, ...)
+{
va_list ap;
va_start(ap, format);
int len = vsprintf(g_uefbuf, format, ap);
@@ -434,7 +423,8 @@ void etfprintf(FILE *file, const char *format, ...) {
va_end(ap);
}
-void etfprint(FILE *file, const std::string &text) {
+void etfprint(FILE *file, const std::string &text)
+{
size_t len = text.length();
fwrite(text.data(), 1, len, file);
}
diff --git a/Source/Core/Common/Src/ExtendedTrace.h b/Source/Core/Common/Src/ExtendedTrace.h
index 12e7ed41fa..6d33eb632d 100644
--- a/Source/Core/Common/Src/ExtendedTrace.h
+++ b/Source/Core/Common/Src/ExtendedTrace.h
@@ -25,16 +25,15 @@
#pragma comment( lib, "imagehlp.lib" )
#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) InitSymInfo( IniSymbolPath )
-#define EXTENDEDTRACEUNINITIALIZE() UninitSymInfo()
-#define STACKTRACE(file) StackTrace( GetCurrentThread(), _T(""), file)
-#define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), _T(""), file, eip, esp, ebp)
+#define EXTENDEDTRACEUNINITIALIZE() UninitSymInfo()
+#define STACKTRACE(file) StackTrace( GetCurrentThread(), "", file)
+#define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), "", file, eip, esp, ebp)
// class File;
BOOL InitSymInfo( PCSTR );
BOOL UninitSymInfo();
-void StackTrace( HANDLE, LPCTSTR, FILE *file);
-void StackTrace( HANDLE, LPCTSTR, FILE *file, DWORD eip, DWORD esp, DWORD ebp);
-void StackTrace( HANDLE hThread, wchar_t const* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp);
+void StackTrace(HANDLE, char const* msg, FILE *file);
+void StackTrace(HANDLE, char const* msg, FILE *file, DWORD eip, DWORD esp, DWORD ebp);
// functions by Masken
void etfprintf(FILE *file, const char *format, ...);
@@ -44,10 +43,10 @@ extern char g_uefbuf[UEFBUFSIZE];
#else // not WIN32
-#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) ((void)0)
-#define EXTENDEDTRACEUNINITIALIZE() ((void)0)
-#define STACKTRACE(file) ((void)0)
-#define STACKTRACE2(file, eip, esp, ebp) ((void)0)
+#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) ((void)0)
+#define EXTENDEDTRACEUNINITIALIZE() ((void)0)
+#define STACKTRACE(file) ((void)0)
+#define STACKTRACE2(file, eip, esp, ebp) ((void)0)
#endif // WIN32
diff --git a/Source/Core/Common/Src/FPURoundMode.h b/Source/Core/Common/Src/FPURoundMode.h
new file mode 100644
index 0000000000..2e26047689
--- /dev/null
+++ b/Source/Core/Common/Src/FPURoundMode.h
@@ -0,0 +1,52 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+#ifndef FPU_ROUND_MODE_H_
+#define FPU_ROUND_MODE_H_
+#include "Common.h"
+
+namespace FPURoundMode
+{
+ enum RoundModes
+ {
+ ROUND_NEAR = 0,
+ ROUND_CHOP,
+ ROUND_UP,
+ ROUND_DOWN
+ };
+ enum PrecisionModes {
+ PREC_24 = 0,
+ PREC_53,
+ PREC_64
+ };
+ void SetRoundMode(u32 mode);
+
+ void SetPrecisionMode(u32 mode);
+
+ void SetSIMDMode(u32 mode);
+
+/*
+ * There are two different flavors of float to int conversion:
+ * _mm_cvtps_epi32() and _mm_cvttps_epi32().
+ *
+ * The first rounds according to the MXCSR rounding bits.
+ * The second one always uses round towards zero.
+ */
+ void SaveSIMDState();
+ void LoadSIMDState();
+ void LoadDefaultSIMDState();
+}
+#endif
diff --git a/Source/Core/Common/Src/FileSearch.cpp b/Source/Core/Common/Src/FileSearch.cpp
index 595dfe7000..674cf0e1d5 100644
--- a/Source/Core/Common/Src/FileSearch.cpp
+++ b/Source/Core/Common/Src/FileSearch.cpp
@@ -51,7 +51,7 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string&
BuildCompleteFilename(GCMSearchPath, _strPath, _searchString);
#ifdef _WIN32
WIN32_FIND_DATA findData;
- HANDLE FindFirst = FindFirstFile(GCMSearchPath.c_str(), &findData);
+ HANDLE FindFirst = FindFirstFile(UTF8ToTStr(GCMSearchPath).c_str(), &findData);
if (FindFirst != INVALID_HANDLE_VALUE)
{
@@ -62,7 +62,7 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string&
if (findData.cFileName[0] != '.')
{
std::string strFilename;
- BuildCompleteFilename(strFilename, _strPath, findData.cFileName);
+ BuildCompleteFilename(strFilename, _strPath, TStrToUTF8(findData.cFileName));
m_FileNames.push_back(strFilename);
}
@@ -112,7 +112,6 @@ void CFileSearch::FindFiles(const std::string& _searchString, const std::string&
#endif
}
-
const CFileSearch::XStringVector& CFileSearch::GetFileNames() const
{
return m_FileNames;
diff --git a/Source/Core/Common/Src/FileUtil.cpp b/Source/Core/Common/Src/FileUtil.cpp
index b46b2498fe..bf7edb0844 100644
--- a/Source/Core/Common/Src/FileUtil.cpp
+++ b/Source/Core/Common/Src/FileUtil.cpp
@@ -41,10 +41,11 @@
#include <CoreFoundation/CFBundle.h>
#endif
-#include <fstream>
#include <algorithm>
#include <sys/stat.h>
+#include "StringUtil.h"
+
#ifndef S_ISDIR
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
#endif
@@ -81,7 +82,11 @@ bool Exists(const std::string &filename)
std::string copy(filename);
StripTailDirSlashes(copy);
+#ifdef _WIN32
+ int result = _tstat64(UTF8ToTStr(copy).c_str(), &file_info);
+#else
int result = stat64(copy.c_str(), &file_info);
+#endif
return (result == 0);
}
@@ -94,7 +99,11 @@ bool IsDirectory(const std::string &filename)
std::string copy(filename);
StripTailDirSlashes(copy);
+#ifdef _WIN32
+ int result = _tstat64(UTF8ToTStr(copy).c_str(), &file_info);
+#else
int result = stat64(copy.c_str(), &file_info);
+#endif
if (result < 0) {
WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s",
@@ -127,7 +136,7 @@ bool Delete(const std::string &filename)
}
#ifdef _WIN32
- if (!DeleteFile(filename.c_str()))
+ if (!DeleteFile(UTF8ToTStr(filename).c_str()))
{
WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s",
filename.c_str(), GetLastErrorMsg());
@@ -149,7 +158,7 @@ bool CreateDir(const std::string &path)
{
INFO_LOG(COMMON, "CreateDir: directory %s", path.c_str());
#ifdef _WIN32
- if (::CreateDirectory(path.c_str(), NULL))
+ if (::CreateDirectory(UTF8ToTStr(path).c_str(), NULL))
return true;
DWORD error = GetLastError();
if (error == ERROR_ALREADY_EXISTS)
@@ -181,7 +190,7 @@ bool CreateFullPath(const std::string &fullPath)
{
int panicCounter = 100;
INFO_LOG(COMMON, "CreateFullPath: path %s", fullPath.c_str());
-
+
if (File::Exists(fullPath))
{
INFO_LOG(COMMON, "CreateFullPath: path exists %s", fullPath.c_str());
@@ -197,7 +206,7 @@ bool CreateFullPath(const std::string &fullPath)
// we're done, yay!
if (position == fullPath.npos)
return true;
-
+
// Include the '/' so the first call is CreateDir("/") rather than CreateDir("")
std::string const subPath(fullPath.substr(0, position + 1));
if (!File::IsDirectory(subPath))
@@ -228,7 +237,7 @@ bool DeleteDir(const std::string &filename)
}
#ifdef _WIN32
- if (::RemoveDirectory(filename.c_str()))
+ if (::RemoveDirectory(UTF8ToTStr(filename).c_str()))
return true;
#else
if (rmdir(filename.c_str()) == 0)
@@ -257,7 +266,7 @@ bool Copy(const std::string &srcFilename, const std::string &destFilename)
INFO_LOG(COMMON, "Copy: %s --> %s",
srcFilename.c_str(), destFilename.c_str());
#ifdef _WIN32
- if (CopyFile(srcFilename.c_str(), destFilename.c_str(), FALSE))
+ if (CopyFile(UTF8ToTStr(srcFilename).c_str(), UTF8ToTStr(destFilename).c_str(), FALSE))
return true;
ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s",
@@ -342,8 +351,13 @@ u64 GetSize(const std::string &filename)
WARN_LOG(COMMON, "GetSize: failed %s: is a directory", filename.c_str());
return 0;
}
+
struct stat64 buf;
+#ifdef _WIN32
+ if (_tstat64(UTF8ToTStr(filename).c_str(), &buf) == 0)
+#else
if (stat64(filename.c_str(), &buf) == 0)
+#endif
{
DEBUG_LOG(COMMON, "GetSize: %s: %lld",
filename.c_str(), (long long)buf.st_size);
@@ -391,13 +405,13 @@ bool CreateEmptyFile(const std::string &filename)
{
INFO_LOG(COMMON, "CreateEmptyFile: %s", filename.c_str());
- FILE *pFile = fopen(filename.c_str(), "wb");
- if (!pFile) {
+ if (!File::IOFile(filename, "wb"))
+ {
ERROR_LOG(COMMON, "CreateEmptyFile: failed %s: %s",
filename.c_str(), GetLastErrorMsg());
return false;
}
- fclose(pFile);
+
return true;
}
@@ -413,7 +427,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
- HANDLE hFind = FindFirstFile((directory + "\\*").c_str(), &ffd);
+ HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE)
{
FindClose(hFind);
@@ -423,7 +437,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
do
{
FSTEntry entry;
- const std::string virtualName(ffd.cFileName);
+ const std::string virtualName(TStrToUTF8(ffd.cFileName));
#else
struct dirent dirent, *result = NULL;
@@ -472,7 +486,7 @@ u32 ScanDirectoryTree(const std::string &directory, FSTEntry& parentEntry)
return foundEntries;
}
-
+
// Deletes the given directory and anything under it. Returns true on success.
bool DeleteDirRecursively(const std::string &directory)
{
@@ -480,18 +494,18 @@ bool DeleteDirRecursively(const std::string &directory)
#ifdef _WIN32
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
- HANDLE hFind = FindFirstFile((directory + "\\*").c_str(), &ffd);
+ HANDLE hFind = FindFirstFile(UTF8ToTStr(directory + "\\*").c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE)
{
FindClose(hFind);
return false;
}
-
+
// windows loop
do
{
- const std::string virtualName = ffd.cFileName;
+ const std::string virtualName(TStrToUTF8(ffd.cFileName));
#else
struct dirent dirent, *result = NULL;
DIR *dirp = opendir(directory.c_str());
@@ -518,7 +532,7 @@ bool DeleteDirRecursively(const std::string &directory)
#ifndef _WIN32
closedir(dirp);
#endif
-
+
return false;
}
}
@@ -529,7 +543,7 @@ bool DeleteDirRecursively(const std::string &directory)
#ifndef _WIN32
closedir(dirp);
#endif
-
+
return false;
}
}
@@ -591,7 +605,7 @@ std::string GetCurrentDir()
if (!(dir = __getcwd(NULL, 0))) {
ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s",
- GetLastErrorMsg());
+ GetLastErrorMsg());
return NULL;
}
std::string strDir = dir;
@@ -622,14 +636,14 @@ std::string GetBundleDirectory()
#endif
#ifdef _WIN32
-std::string &GetExeDirectory()
+std::string& GetExeDirectory()
{
static std::string DolphinPath;
if (DolphinPath.empty())
{
- char Dolphin_exe_Path[2048];
- GetModuleFileNameA(NULL, Dolphin_exe_Path, 2048);
- DolphinPath = Dolphin_exe_Path;
+ TCHAR Dolphin_exe_Path[2048];
+ GetModuleFileName(NULL, Dolphin_exe_Path, 2048);
+ DolphinPath = TStrToUTF8(Dolphin_exe_Path);
DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\'));
}
return DolphinPath;
@@ -668,9 +682,10 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath)
if (File::Exists(ROOT_DIR DIR_SEP USERDATA_DIR))
paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP;
else
- paths[D_USER_IDX] = std::string(getenv("HOME") ? getenv("HOME") : getenv("PWD")) + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP;
+ paths[D_USER_IDX] = std::string(getenv("HOME") ?
+ getenv("HOME") : getenv("PWD") ?
+ getenv("PWD") : "") + DIR_SEP DOLPHIN_DATA_DIR DIR_SEP;
#endif
- INFO_LOG(COMMON, "GetUserPath: Setting user directory to %s:", paths[D_USER_IDX].c_str());
paths[D_GCUSER_IDX] = paths[D_USER_IDX] + GC_USER_DIR DIR_SEP;
paths[D_WIIROOT_IDX] = paths[D_USER_IDX] + WII_USER_DIR;
@@ -731,31 +746,19 @@ std::string &GetUserPath(const unsigned int DirIDX, const std::string &newPath)
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename)
{
- FILE *f = fopen(filename, text_file ? "w" : "wb");
- if (!f)
- return false;
- size_t len = str.size();
- if (len != fwrite(str.data(), 1, str.size(), f)) // TODO: string::data() may not be contiguous
- {
- fclose(f);
- return false;
- }
- fclose(f);
- return true;
+ return File::IOFile(filename, text_file ? "w" : "wb").WriteBytes(str.data(), str.size());
}
bool ReadFileToString(bool text_file, const char *filename, std::string &str)
{
- FILE *f = fopen(filename, text_file ? "r" : "rb");
+ File::IOFile file(filename, text_file ? "r" : "rb");
+ auto const f = file.GetHandle();
+
if (!f)
return false;
- size_t len = (size_t)GetSize(f);
- char *buf = new char[len + 1];
- buf[fread(buf, 1, len, f)] = 0;
- str = std::string(buf, len);
- fclose(f);
- delete [] buf;
- return true;
+
+ str.resize(GetSize(f));
+ return file.ReadArray(&str[0], str.size());
}
IOFile::IOFile()
@@ -799,7 +802,7 @@ bool IOFile::Open(const std::string& filename, const char openmode[])
{
Close();
#ifdef _WIN32
- fopen_s(&m_file, filename.c_str(), openmode);
+ _tfopen_s(&m_file, UTF8ToTStr(filename).c_str(), UTF8ToTStr(openmode).c_str());
#else
m_file = fopen(filename.c_str(), openmode);
#endif
@@ -848,7 +851,7 @@ bool IOFile::Seek(s64 off, int origin)
}
u64 IOFile::Tell()
-{
+{
if (IsOpen())
return ftello(m_file);
else
diff --git a/Source/Core/Common/Src/FileUtil.h b/Source/Core/Common/Src/FileUtil.h
index 2bc55285ed..523e756307 100644
--- a/Source/Core/Common/Src/FileUtil.h
+++ b/Source/Core/Common/Src/FileUtil.h
@@ -25,6 +25,7 @@
#include <string.h>
#include "Common.h"
+#include "StringUtil.h"
// User directory indices for GetUserPath
enum {
@@ -227,4 +228,15 @@ private:
} // namespace
+// To deal with Windows being dumb at unicode:
+template <typename T>
+void OpenFStream(T& fstream, const std::string& filename, std::ios_base::openmode openmode)
+{
+#ifdef _WIN32
+ fstream.open(UTF8ToTStr(filename).c_str(), openmode);
+#else
+ fstream.open(filename.c_str(), openmode);
+#endif
+}
+
#endif
diff --git a/Source/Core/Common/Src/GenericFPURoundMode.cpp b/Source/Core/Common/Src/GenericFPURoundMode.cpp
new file mode 100644
index 0000000000..cc878291a1
--- /dev/null
+++ b/Source/Core/Common/Src/GenericFPURoundMode.cpp
@@ -0,0 +1,41 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "FPURoundMode.h"
+
+// Generic, do nothing
+namespace FPURoundMode
+{
+ void SetRoundMode(u32 mode)
+ {
+ }
+ void SetPrecisionMode(u32 mode)
+ {
+ }
+ void SetSIMDMode(u32 mode)
+ {
+ }
+ void SaveSIMDState()
+ {
+ }
+ void LoadSIMDState()
+ {
+ }
+ void LoadDefaultSIMDState()
+ {
+ }
+}
diff --git a/Source/Core/Common/Src/Hash.cpp b/Source/Core/Common/Src/Hash.cpp
index 8e8d6f85bd..bc72b16f2a 100644
--- a/Source/Core/Common/Src/Hash.cpp
+++ b/Source/Core/Common/Src/Hash.cpp
@@ -119,7 +119,7 @@ u32 HashEctor(const u8* ptr, int length)
inline u64 getblock(const u64 * p, int i)
{
- return p[i];
+ return p[i];
}
//----------
@@ -127,25 +127,25 @@ inline u64 getblock(const u64 * p, int i)
inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2)
{
- k1 *= c1;
- k1 = _rotl64(k1,23);
- k1 *= c2;
- h1 ^= k1;
- h1 += h2;
+ k1 *= c1;
+ k1 = _rotl64(k1,23);
+ k1 *= c2;
+ h1 ^= k1;
+ h1 += h2;
- h2 = _rotl64(h2,41);
+ h2 = _rotl64(h2,41);
- k2 *= c2;
- k2 = _rotl64(k2,23);
- k2 *= c1;
- h2 ^= k2;
- h2 += h1;
+ k2 *= c2;
+ k2 = _rotl64(k2,23);
+ k2 *= c1;
+ h2 ^= k2;
+ h2 += h1;
- h1 = h1*3+0x52dce729;
- h2 = h2*3+0x38495ab5;
+ h1 = h1*3+0x52dce729;
+ h2 = h2*3+0x38495ab5;
- c1 = c1*5+0x7b7d159c;
- c2 = c2*5+0x6bce6396;
+ c1 = c1*5+0x7b7d159c;
+ c2 = c2*5+0x6bce6396;
}
//----------
@@ -153,87 +153,87 @@ inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2)
inline u64 fmix64(u64 k)
{
- k ^= k >> 33;
- k *= 0xff51afd7ed558ccd;
- k ^= k >> 33;
- k *= 0xc4ceb9fe1a85ec53;
- k ^= k >> 33;
+ k ^= k >> 33;
+ k *= 0xff51afd7ed558ccd;
+ k ^= k >> 33;
+ k *= 0xc4ceb9fe1a85ec53;
+ k ^= k >> 33;
- return k;
+ return k;
}
u64 GetMurmurHash3(const u8 *src, int len, u32 samples)
{
- const u8 * data = (const u8*)src;
- const int nblocks = len / 16;
+ const u8 * data = (const u8*)src;
+ const int nblocks = len / 16;
u32 Step = (len / 8);
if(samples == 0) samples = max(Step, 1u);
Step = Step / samples;
if(Step < 1) Step = 1;
- u64 h1 = 0x9368e53c2f6af274;
- u64 h2 = 0x586dcd208f7cd3fd;
+ u64 h1 = 0x9368e53c2f6af274;
+ u64 h2 = 0x586dcd208f7cd3fd;
- u64 c1 = 0x87c37b91114253d5;
- u64 c2 = 0x4cf5ad432745937f;
+ u64 c1 = 0x87c37b91114253d5;
+ u64 c2 = 0x4cf5ad432745937f;
- //----------
- // body
-
- const u64 * blocks = (const u64 *)(data);
+ //----------
+ // body
- for(int i = 0; i < nblocks; i+=Step)
- {
- u64 k1 = getblock(blocks,i*2+0);
- u64 k2 = getblock(blocks,i*2+1);
+ const u64 * blocks = (const u64 *)(data);
- bmix64(h1,h2,k1,k2,c1,c2);
- }
+ for(int i = 0; i < nblocks; i+=Step)
+ {
+ u64 k1 = getblock(blocks,i*2+0);
+ u64 k2 = getblock(blocks,i*2+1);
- //----------
- // tail
+ bmix64(h1,h2,k1,k2,c1,c2);
+ }
- const u8 * tail = (const u8*)(data + nblocks*16);
+ //----------
+ // tail
- u64 k1 = 0;
- u64 k2 = 0;
+ const u8 * tail = (const u8*)(data + nblocks*16);
- switch(len & 15)
- {
- case 15: k2 ^= u64(tail[14]) << 48;
- case 14: k2 ^= u64(tail[13]) << 40;
- case 13: k2 ^= u64(tail[12]) << 32;
- case 12: k2 ^= u64(tail[11]) << 24;
- case 11: k2 ^= u64(tail[10]) << 16;
- case 10: k2 ^= u64(tail[ 9]) << 8;
- case 9: k2 ^= u64(tail[ 8]) << 0;
+ u64 k1 = 0;
+ u64 k2 = 0;
- case 8: k1 ^= u64(tail[ 7]) << 56;
- case 7: k1 ^= u64(tail[ 6]) << 48;
- case 6: k1 ^= u64(tail[ 5]) << 40;
- case 5: k1 ^= u64(tail[ 4]) << 32;
- case 4: k1 ^= u64(tail[ 3]) << 24;
- case 3: k1 ^= u64(tail[ 2]) << 16;
- case 2: k1 ^= u64(tail[ 1]) << 8;
- case 1: k1 ^= u64(tail[ 0]) << 0;
- bmix64(h1,h2,k1,k2,c1,c2);
- };
+ switch(len & 15)
+ {
+ case 15: k2 ^= u64(tail[14]) << 48;
+ case 14: k2 ^= u64(tail[13]) << 40;
+ case 13: k2 ^= u64(tail[12]) << 32;
+ case 12: k2 ^= u64(tail[11]) << 24;
+ case 11: k2 ^= u64(tail[10]) << 16;
+ case 10: k2 ^= u64(tail[ 9]) << 8;
+ case 9: k2 ^= u64(tail[ 8]) << 0;
+
+ case 8: k1 ^= u64(tail[ 7]) << 56;
+ case 7: k1 ^= u64(tail[ 6]) << 48;
+ case 6: k1 ^= u64(tail[ 5]) << 40;
+ case 5: k1 ^= u64(tail[ 4]) << 32;
+ case 4: k1 ^= u64(tail[ 3]) << 24;
+ case 3: k1 ^= u64(tail[ 2]) << 16;
+ case 2: k1 ^= u64(tail[ 1]) << 8;
+ case 1: k1 ^= u64(tail[ 0]) << 0;
+ bmix64(h1,h2,k1,k2,c1,c2);
+ };
- //----------
- // finalization
+ //----------
+ // finalization
- h2 ^= len;
+ h2 ^= len;
- h1 += h2;
- h2 += h1;
+ h1 += h2;
+ h2 += h1;
- h1 = fmix64(h1);
- h2 = fmix64(h2);
+ h1 = fmix64(h1);
+ h2 = fmix64(h2);
- h1 += h2;
+ h1 += h2;
- return h1;
+ return h1;
}
@@ -262,11 +262,13 @@ u64 GetCRC32(const u8 *src, int len, u32 samples)
}
-/* NOTE: This hash function is used for custom texture loading/dumping, so
- it should not be changed, which would require all custom textures to be
- recalculated for their new hash values. If the hashing function is
- changed, make sure this one is still used when the legacy parameter is
- true. */
+/*
+ * NOTE: This hash function is used for custom texture loading/dumping, so
+ * it should not be changed, which would require all custom textures to be
+ * recalculated for their new hash values. If the hashing function is
+ * changed, make sure this one is still used when the legacy parameter is
+ * true.
+ */
u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
{
const u64 m = 0xc6a4a7935bd1e995;
@@ -282,11 +284,11 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
{
u64 k = data[0];
data+=Step;
- k *= m;
+ k *= m;
k ^= k >> r;
- k *= m;
+ k *= m;
h ^= k;
- h *= m;
+ h *= m;
}
const u8 * data2 = (const u8*)end;
@@ -453,9 +455,11 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples)
return *((u64 *)&out);
}
-/* FIXME: The old 32-bit version of this hash made different hashes than the
- 64-bit version. Until someone can make a new version of the 32-bit one that
- makes identical hashes, this is just a c/p of the 64-bit one. */
+/*
+ * FIXME: The old 32-bit version of this hash made different hashes than the
+ * 64-bit version. Until someone can make a new version of the 32-bit one that
+ * makes identical hashes, this is just a c/p of the 64-bit one.
+ */
u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
{
const u64 m = 0xc6a4a7935bd1e995ULL;
@@ -473,7 +477,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
data+=Step;
k *= m;
k ^= k >> r;
- k *= m;
+ k *= m;
h ^= k;
h *= m;
}
@@ -502,7 +506,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
u64 GetHash64(const u8 *src, int len, u32 samples)
{
- return ptrHashFunction(src, len, samples);
+ return ptrHashFunction(src, len, samples);
}
// sets the hash function used for the texture cache
diff --git a/Source/Core/Common/Src/IniFile.cpp b/Source/Core/Common/Src/IniFile.cpp
index acad498106..da44855941 100644
--- a/Source/Core/Common/Src/IniFile.cpp
+++ b/Source/Core/Common/Src/IniFile.cpp
@@ -25,6 +25,7 @@
#include <fstream>
#include <algorithm>
+#include "FileUtil.h"
#include "StringUtil.h"
#include "IniFile.h"
@@ -400,7 +401,7 @@ bool IniFile::Load(const char* filename)
// Open file
std::ifstream in;
- in.open(filename, std::ios::in);
+ OpenFStream(in, filename, std::ios::in);
if (in.fail()) return false;
@@ -452,7 +453,7 @@ bool IniFile::Load(const char* filename)
bool IniFile::Save(const char* filename)
{
std::ofstream out;
- out.open(filename, std::ios::out);
+ OpenFStream(out, filename, std::ios::out);
if (out.fail())
{
diff --git a/Source/Core/Common/Src/LinearDiskCache.h b/Source/Core/Common/Src/LinearDiskCache.h
index 9755c996bd..b60c849c8e 100644
--- a/Source/Core/Common/Src/LinearDiskCache.h
+++ b/Source/Core/Common/Src/LinearDiskCache.h
@@ -21,11 +21,8 @@
#include "Common.h"
#include <fstream>
-// Increment this every time you change shader generation code.
-enum
-{
- LINEAR_DISKCACHE_VER = 6979
-};
+// defined in Version.cpp
+extern const char *scm_rev_git_str;
// On disk format:
//header{
@@ -74,7 +71,7 @@ public:
m_num_entries = 0;
// try opening for reading/writing
- m_file.open(filename, ios_base::in | ios_base::out | ios_base::binary);
+ OpenFStream(m_file, 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();
@@ -187,13 +184,15 @@ private:
{
Header()
: id(*(u32*)"DCAC")
- , ver(LINEAR_DISKCACHE_VER)
, key_t_size(sizeof(K))
, value_t_size(sizeof(V))
- {}
+ {
+ memcpy(ver, scm_rev_git_str, 40);
+ }
- const u32 id, ver;
+ const u32 id;
const u16 key_t_size, value_t_size;
+ char ver[40];
} m_header;
diff --git a/Source/Core/Common/Src/LogManager.cpp b/Source/Core/Common/Src/LogManager.cpp
index 26db5cbfc1..d5416fcd7d 100644
--- a/Source/Core/Common/Src/LogManager.cpp
+++ b/Source/Core/Common/Src/LogManager.cpp
@@ -17,6 +17,9 @@
#include <algorithm>
+#ifdef ANDROID
+#include "Host.h"
+#endif
#include "LogManager.h"
#include "ConsoleListener.h"
#include "Timer.h"
@@ -42,9 +45,9 @@ LogManager::LogManager()
m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot");
m_Log[LogTypes::COMMON] = new LogContainer("COMMON", "Common");
- m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO");
+ m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO");
m_Log[LogTypes::FILEMON] = new LogContainer("FileMon", "File Monitor");
- m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad");
+ m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad");
m_Log[LogTypes::PIXELENGINE] = new LogContainer("PE", "PixelEngine");
m_Log[LogTypes::COMMANDPROCESSOR] = new LogContainer("CP", "CommandProc");
m_Log[LogTypes::VIDEOINTERFACE] = new LogContainer("VI", "VideoInt");
@@ -61,15 +64,15 @@ LogManager::LogManager()
m_Log[LogTypes::AUDIO_INTERFACE] = new LogContainer("AI", "AudioInt");
m_Log[LogTypes::POWERPC] = new LogContainer("PowerPC", "IBM CPU");
m_Log[LogTypes::OSHLE] = new LogContainer("HLE", "HLE");
- m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE");
- m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE");
- m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails");
- m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend");
- m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator");
+ m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE");
+ m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE");
+ m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails");
+ m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend");
+ m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator");
m_Log[LogTypes::DYNA_REC] = new LogContainer("JIT", "Dynamic Recompiler");
m_Log[LogTypes::CONSOLE] = new LogContainer("CONSOLE", "Dolphin Console");
- m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport");
- m_Log[LogTypes::WIIMOTE] = new LogContainer("Wiimote", "Wiimote");
+ m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport");
+ m_Log[LogTypes::WIIMOTE] = new LogContainer("Wiimote", "Wiimote");
m_Log[LogTypes::WII_IOB] = new LogContainer("WII_IOB", "WII IO Bridge");
m_Log[LogTypes::WII_IPC] = new LogContainer("WII_IPC", "WII IPC");
m_Log[LogTypes::WII_IPC_HID] = new LogContainer("WII_IPC_HID", "WII IPC HID");
@@ -83,7 +86,7 @@ LogManager::LogManager()
m_Log[LogTypes::WII_IPC_WC24] = new LogContainer("WII_IPC_WC24", "WII IPC WC24");
m_Log[LogTypes::WII_IPC_SSL] = new LogContainer("WII_IPC_SSL", "WII IPC SSL");
m_Log[LogTypes::WII_IPC_WIIMOTE] = new LogContainer("WII_IPC_WIIMOTE","WII IPC WIIMOTE");
- m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
+ m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager");
m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay");
@@ -136,7 +139,9 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
Common::Timer::GetTimeFormatted().c_str(),
file, line, level_to_char[(int)level],
log->GetShortName(), temp);
-
+#ifdef ANDROID
+ Host_SysMessage(msg);
+#endif
log->Trigger(level, msg);
}
@@ -185,7 +190,7 @@ void LogContainer::Trigger(LogTypes::LOG_LEVELS level, const char *msg)
FileLogListener::FileLogListener(const char *filename)
{
- m_logfile.open(filename, std::ios::app);
+ OpenFStream(m_logfile, filename, std::ios::app);
SetEnable(true);
}
diff --git a/Source/Core/Common/Src/LogManager.h b/Source/Core/Common/Src/LogManager.h
index 1722c0b1bf..f7ccb15034 100644
--- a/Source/Core/Common/Src/LogManager.h
+++ b/Source/Core/Common/Src/LogManager.h
@@ -26,7 +26,7 @@
#include <set>
#include <string.h>
-#define MAX_MESSAGES 8000
+#define MAX_MESSAGES 8000
#define MAX_MSGLEN 1024
diff --git a/Source/Core/Common/Src/MathUtil.cpp b/Source/Core/Common/Src/MathUtil.cpp
index e078db2e9d..d5be1c3bb1 100644
--- a/Source/Core/Common/Src/MathUtil.cpp
+++ b/Source/Core/Common/Src/MathUtil.cpp
@@ -21,13 +21,6 @@
#include <cmath>
#include <numeric>
-namespace {
-
-static u32 saved_sse_state = _mm_getcsr();
-static const u32 default_sse_state = _mm_getcsr();
-
-}
-
namespace MathUtil
{
@@ -95,7 +88,7 @@ u32 ClassifyFloat(float fvalue)
else
{
// Denormalized number.
- return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
+ return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
}
}
else if (exp)
@@ -108,43 +101,26 @@ u32 ClassifyFloat(float fvalue)
//Zero
return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
}
- }
+ }
}
} // namespace
-void LoadDefaultSSEState()
-{
- _mm_setcsr(default_sse_state);
-}
-
-
-void LoadSSEState()
-{
- _mm_setcsr(saved_sse_state);
-}
-
-
-void SaveSSEState()
-{
- saved_sse_state = _mm_getcsr();
-}
-
inline void MatrixMul(int n, const float *a, const float *b, float *result)
-{
- for (int i = 0; i < n; ++i)
+{
+ for (int i = 0; i < n; ++i)
{
- for (int j = 0; j < n; ++j)
+ for (int j = 0; j < n; ++j)
{
- float temp = 0;
- for (int k = 0; k < n; ++k)
+ float temp = 0;
+ for (int k = 0; k < n; ++k)
{
- temp += a[i * n + k] * b[k * n + j];
- }
- result[i * n + j] = temp;
- }
- }
+ temp += a[i * n + k] * b[k * n + j];
+ }
+ result[i * n + j] = temp;
+ }
+ }
}
// Calculate sum of a float list
@@ -155,94 +131,94 @@ float MathFloatVectorSum(const std::vector<float>& Vec)
void Matrix33::LoadIdentity(Matrix33 &mtx)
{
- memset(mtx.data, 0, sizeof(mtx.data));
- mtx.data[0] = 1.0f;
- mtx.data[4] = 1.0f;
- mtx.data[8] = 1.0f;
+ memset(mtx.data, 0, sizeof(mtx.data));
+ mtx.data[0] = 1.0f;
+ mtx.data[4] = 1.0f;
+ mtx.data[8] = 1.0f;
}
void Matrix33::RotateX(Matrix33 &mtx, float rad)
{
- float s = sin(rad);
- float c = cos(rad);
- memset(mtx.data, 0, sizeof(mtx.data));
- mtx.data[0] = 1;
- mtx.data[4] = c;
- mtx.data[5] = -s;
- mtx.data[7] = s;
- mtx.data[8] = c;
+ float s = sin(rad);
+ float c = cos(rad);
+ memset(mtx.data, 0, sizeof(mtx.data));
+ mtx.data[0] = 1;
+ mtx.data[4] = c;
+ mtx.data[5] = -s;
+ mtx.data[7] = s;
+ mtx.data[8] = c;
}
void Matrix33::RotateY(Matrix33 &mtx, float rad)
{
- float s = sin(rad);
- float c = cos(rad);
- memset(mtx.data, 0, sizeof(mtx.data));
- mtx.data[0] = c;
- mtx.data[2] = s;
- mtx.data[4] = 1;
- mtx.data[6] = -s;
- mtx.data[8] = c;
+ float s = sin(rad);
+ float c = cos(rad);
+ memset(mtx.data, 0, sizeof(mtx.data));
+ mtx.data[0] = c;
+ mtx.data[2] = s;
+ mtx.data[4] = 1;
+ mtx.data[6] = -s;
+ mtx.data[8] = c;
}
void Matrix33::Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result)
{
- MatrixMul(3, a.data, b.data, result.data);
+ MatrixMul(3, a.data, b.data, result.data);
}
void Matrix33::Multiply(const Matrix33 &a, const float vec[3], float result[3])
{
- for (int i = 0; i < 3; ++i) {
- result[i] = 0;
- for (int k = 0; k < 3; ++k) {
- result[i] += a.data[i * 3 + k] * vec[k];
- }
- }
+ for (int i = 0; i < 3; ++i) {
+ result[i] = 0;
+ for (int k = 0; k < 3; ++k) {
+ result[i] += a.data[i * 3 + k] * vec[k];
+ }
+ }
}
void Matrix44::LoadIdentity(Matrix44 &mtx)
{
- memset(mtx.data, 0, sizeof(mtx.data));
- mtx.data[0] = 1.0f;
- mtx.data[5] = 1.0f;
- mtx.data[10] = 1.0f;
- mtx.data[15] = 1.0f;
+ memset(mtx.data, 0, sizeof(mtx.data));
+ mtx.data[0] = 1.0f;
+ mtx.data[5] = 1.0f;
+ mtx.data[10] = 1.0f;
+ mtx.data[15] = 1.0f;
}
void Matrix44::LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33)
{
- for (int i = 0; i < 3; ++i)
+ for (int i = 0; i < 3; ++i)
{
- for (int j = 0; j < 3; ++j)
+ for (int j = 0; j < 3; ++j)
{
- mtx.data[i * 4 + j] = m33.data[i * 3 + j];
- }
- }
+ mtx.data[i * 4 + j] = m33.data[i * 3 + j];
+ }
+ }
- for (int i = 0; i < 3; ++i)
+ for (int i = 0; i < 3; ++i)
{
- mtx.data[i * 4 + 3] = 0;
- mtx.data[i + 12] = 0;
- }
- mtx.data[15] = 1.0f;
+ mtx.data[i * 4 + 3] = 0;
+ mtx.data[i + 12] = 0;
+ }
+ mtx.data[15] = 1.0f;
}
void Matrix44::Set(Matrix44 &mtx, const float mtxArray[16])
{
- for(int i = 0; i < 16; ++i) {
- mtx.data[i] = mtxArray[i];
- }
+ for(int i = 0; i < 16; ++i) {
+ mtx.data[i] = mtxArray[i];
+ }
}
void Matrix44::Translate(Matrix44 &mtx, const float vec[3])
{
- LoadIdentity(mtx);
- mtx.data[3] = vec[0];
- mtx.data[7] = vec[1];
- mtx.data[11] = vec[2];
+ LoadIdentity(mtx);
+ mtx.data[3] = vec[0];
+ mtx.data[7] = vec[1];
+ mtx.data[11] = vec[2];
}
void Matrix44::Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result)
{
- MatrixMul(4, a.data, b.data, result.data);
+ MatrixMul(4, a.data, b.data, result.data);
}
diff --git a/Source/Core/Common/Src/MathUtil.h b/Source/Core/Common/Src/MathUtil.h
index a6290ff602..ccb9a95e81 100644
--- a/Source/Core/Common/Src/MathUtil.h
+++ b/Source/Core/Common/Src/MathUtil.h
@@ -20,8 +20,8 @@
#include "Common.h"
-#include <xmmintrin.h>
#include <vector>
+#include "FPURoundMode.h"
namespace MathUtil
{
@@ -117,6 +117,8 @@ struct Rectangle
Rectangle(T theLeft, T theTop, T theRight, T theBottom)
: left(theLeft), top(theTop), right(theRight), bottom(theBottom)
{ }
+
+ bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; }
T GetWidth() const { return abs(right - left); }
T GetHeight() const { return abs(bottom - top); }
@@ -147,22 +149,32 @@ struct Rectangle
inline float pow2f(float x) {return x * x;}
inline double pow2(double x) {return x * x;}
-
-/*
- There are two different flavors of float to int conversion:
- _mm_cvtps_epi32() and _mm_cvttps_epi32(). The first rounds
- according to the MXCSR rounding bits. The second one always
- uses round towards zero.
- */
-
-void SaveSSEState();
-void LoadSSEState();
-void LoadDefaultSSEState();
float MathFloatVectorSum(const std::vector<float>&);
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define ROUND_DOWN(x, a) ((x) & ~((a) - 1))
+// Rounds down. 0 -> undefined
+inline u64 Log2(u64 val)
+{
+#if defined(__GNUC__)
+ return 63 - __builtin_clzll(val);
+
+#elif defined(_MSC_VER) && defined(_M_X64)
+ unsigned long result = -1;
+ _BitScanReverse64(&result, val);
+ return result;
+
+#else
+ u64 result = -1;
+ while (val != 0)
+ {
+ val >>= 1;
+ ++result;
+ }
+ return result;
+#endif
+}
// Tiny matrix/vector library.
// Used for things like Free-Look in the gfx backend.
@@ -170,32 +182,32 @@ float MathFloatVectorSum(const std::vector<float>&);
class Matrix33
{
public:
- static void LoadIdentity(Matrix33 &mtx);
+ static void LoadIdentity(Matrix33 &mtx);
- // set mtx to be a rotation matrix around the x axis
- static void RotateX(Matrix33 &mtx, float rad);
- // set mtx to be a rotation matrix around the y axis
- static void RotateY(Matrix33 &mtx, float rad);
+ // set mtx to be a rotation matrix around the x axis
+ static void RotateX(Matrix33 &mtx, float rad);
+ // set mtx to be a rotation matrix around the y axis
+ static void RotateY(Matrix33 &mtx, float rad);
- // set result = a x b
- static void Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result);
- static void Multiply(const Matrix33 &a, const float vec[3], float result[3]);
+ // set result = a x b
+ static void Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result);
+ static void Multiply(const Matrix33 &a, const float vec[3], float result[3]);
- float data[9];
+ float data[9];
};
class Matrix44
{
public:
- static void LoadIdentity(Matrix44 &mtx);
- static void LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33);
- static void Set(Matrix44 &mtx, const float mtxArray[16]);
+ static void LoadIdentity(Matrix44 &mtx);
+ static void LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33);
+ static void Set(Matrix44 &mtx, const float mtxArray[16]);
- static void Translate(Matrix44 &mtx, const float vec[3]);
+ static void Translate(Matrix44 &mtx, const float vec[3]);
- static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result);
+ static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result);
- float data[16];
+ float data[16];
};
#endif // _MATH_UTIL_H_
diff --git a/Source/Core/Common/Src/MemArena.cpp b/Source/Core/Common/Src/MemArena.cpp
index 1dcdef6672..26ce81f578 100644
--- a/Source/Core/Common/Src/MemArena.cpp
+++ b/Source/Core/Common/Src/MemArena.cpp
@@ -27,6 +27,10 @@
#include <unistd.h>
#include <cerrno>
#include <cstring>
+#ifdef ANDROID
+#include <sys/ioctl.h>
+#include <linux/ashmem.h>
+#endif
#endif
#if defined(__APPLE__)
@@ -34,11 +38,41 @@ static const char* ram_temp_file = "/tmp/gc_mem.tmp";
#elif !defined(_WIN32) // non OSX unixes
static const char* ram_temp_file = "/dev/shm/gc_mem.tmp";
#endif
+#ifdef ANDROID
+#define ASHMEM_DEVICE "/dev/ashmem"
+
+int AshmemCreateFileMapping(const char *name, size_t size)
+{
+ int fd, ret;
+ fd = open(ASHMEM_DEVICE, O_RDWR);
+ if (fd < 0)
+ return fd;
+
+ // We don't really care if we can't set the name, it is optional
+ ret = ioctl(fd, ASHMEM_SET_NAME, name);
+
+ ret = ioctl(fd, ASHMEM_SET_SIZE, size);
+ if (ret < 0)
+ {
+ close(fd);
+ NOTICE_LOG(MEMMAP, "Ashmem returned error: 0x%08x", ret);
+ return ret;
+ }
+ return fd;
+}
+#endif
void MemArena::GrabLowMemSpace(size_t size)
{
#ifdef _WIN32
hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (DWORD)(size), NULL);
+#elif defined(ANDROID)
+ fd = AshmemCreateFileMapping("Dolphin-emu", size);
+ if (fd < 0)
+ {
+ NOTICE_LOG(MEMMAP, "Ashmem allocation failed");
+ return;
+ }
#else
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
fd = open(ram_temp_file, O_RDWR | O_CREAT, mode);
diff --git a/Source/Core/Common/Src/MemoryUtil.cpp b/Source/Core/Common/Src/MemoryUtil.cpp
index 0888746d42..d788783c5a 100644
--- a/Source/Core/Common/Src/MemoryUtil.cpp
+++ b/Source/Core/Common/Src/MemoryUtil.cpp
@@ -117,9 +117,12 @@ void* AllocateAlignedMemory(size_t size,size_t alignment)
void* ptr = _aligned_malloc(size,alignment);
#else
void* ptr = NULL;
+#ifdef ANDROID
+ ptr = memalign(alignment, size);
+#else
if (posix_memalign(&ptr, alignment, size) != 0)
ERROR_LOG(MEMMAP, "Failed to allocate aligned memory");
-;
+#endif
#endif
// printf("Mapped memory at %p (size %ld)\n", ptr,
@@ -152,9 +155,7 @@ void FreeAlignedMemory(void* ptr)
if (ptr)
{
#ifdef _WIN32
-
- _aligned_free(ptr);
-
+ _aligned_free(ptr);
#else
free(ptr);
#endif
diff --git a/Source/Core/Common/Src/Misc.cpp b/Source/Core/Common/Src/Misc.cpp
index aafe37886f..8364bda48d 100644
--- a/Source/Core/Common/Src/Misc.cpp
+++ b/Source/Core/Common/Src/Misc.cpp
@@ -31,7 +31,7 @@ const char* GetLastErrorMsg()
#ifdef _WIN32
static __declspec(thread) char err_str[buff_size] = {};
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
err_str, buff_size, NULL);
#else
diff --git a/Source/Core/Common/Src/MsgHandler.cpp b/Source/Core/Common/Src/MsgHandler.cpp
index 7c666227aa..90369df1ae 100644
--- a/Source/Core/Common/Src/MsgHandler.cpp
+++ b/Source/Core/Common/Src/MsgHandler.cpp
@@ -102,15 +102,14 @@ bool MsgAlert(bool yes_no, int Style, const char* format, ...)
bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style)
{
#ifdef _WIN32
- int STYLE = MB_ICONINFORMATION;
- if (Style == QUESTION) STYLE = MB_ICONQUESTION;
- if (Style == WARNING) STYLE = MB_ICONWARNING;
-
- return IDYES == MessageBox(0, text, caption, STYLE | (yes_no ? MB_YESNO : MB_OK));
-
+ int STYLE = MB_ICONINFORMATION;
+ if (Style == QUESTION) STYLE = MB_ICONQUESTION;
+ if (Style == WARNING) STYLE = MB_ICONWARNING;
+
+ return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK));
#else
- printf("%s\n", text);
- return true;
+ printf("%s\n", text);
+ return true;
#endif
}
diff --git a/Source/Core/Common/Src/NandPaths.cpp b/Source/Core/Common/Src/NandPaths.cpp
index cec79414a7..eb0673afe0 100644
--- a/Source/Core/Common/Src/NandPaths.cpp
+++ b/Source/Core/Common/Src/NandPaths.cpp
@@ -86,7 +86,8 @@ bool CheckTitleTIK(u64 _titleID)
static void CreateReplacementFile(std::string &filename)
{
- std::ofstream replace(filename.c_str());
+ std::ofstream replace;
+ OpenFStream(replace, filename, std::ios_base::out);
replace <<"\" __22__\n";
replace << "* __2a__\n";
//replace << "/ __2f__\n";
@@ -108,7 +109,8 @@ void ReadReplacements(replace_v& replacements)
if (!File::Exists(filename))
CreateReplacementFile(filename);
- std::ifstream f(filename.c_str());
+ std::ifstream f;
+ OpenFStream(f, filename, std::ios_base::in);
char letter;
std::string replacement;
diff --git a/Source/Core/Common/Src/SDCardUtil.cpp b/Source/Core/Common/Src/SDCardUtil.cpp
index 0f2ad08607..cf37ffff3e 100644
--- a/Source/Core/Common/Src/SDCardUtil.cpp
+++ b/Source/Core/Common/Src/SDCardUtil.cpp
@@ -29,6 +29,7 @@
// Modified for Dolphin.
#include "SDCardUtil.h"
+#include "FileUtil.h"
#include <time.h>
#include <stdio.h>
@@ -190,7 +191,6 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename)
{
u32 sectors_per_fat;
u32 sectors_per_disk;
- FILE* f;
// Convert MB to bytes
disk_size *= 1024 * 1024;
@@ -207,7 +207,8 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename)
boot_sector_init(s_boot_sector, s_fsinfo_sector, disk_size, nullptr);
fat_init(s_fat_head);
- f = fopen(filename, "wb");
+ File::IOFile file(filename, "wb");
+ FILE* const f = file.GetHandle();
if (!f)
{
ERROR_LOG(COMMON, "Could not create file '%s', aborting...\n", filename);
@@ -247,13 +248,11 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename)
if (write_empty(f, sectors_per_disk - RESERVED_SECTORS - 2*sectors_per_fat)) goto FailWrite;
- fclose(f);
return true;
FailWrite:
ERROR_LOG(COMMON, "Could not write to '%s', aborting...\n", filename);
if (unlink(filename) < 0)
ERROR_LOG(COMMON, "unlink(%s) failed\n%s", filename, GetLastErrorMsg());
- fclose(f);
return false;
}
diff --git a/Source/Core/Common/Src/StdConditionVariable.h b/Source/Core/Common/Src/StdConditionVariable.h
index 1b81766ee0..6530712c8f 100644
--- a/Source/Core/Common/Src/StdConditionVariable.h
+++ b/Source/Core/Common/Src/StdConditionVariable.h
@@ -5,7 +5,7 @@
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
-#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
+#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
// GCC 4.4 provides <condition_variable>
#include <condition_variable>
#else
@@ -133,7 +133,7 @@ public:
// bool wait_for(unique_lock<mutex>& lock,
// const chrono::duration<Rep, Period>& rel_time,
// Predicate pred);
-
+
native_handle_type native_handle()
{
#ifdef USE_EVENTS
diff --git a/Source/Core/Common/Src/StdMutex.h b/Source/Core/Common/Src/StdMutex.h
index 8949e905ac..8a5d22f928 100644
--- a/Source/Core/Common/Src/StdMutex.h
+++ b/Source/Core/Common/Src/StdMutex.h
@@ -5,7 +5,7 @@
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
-#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
+#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
// GCC 4.4 provides <mutex>
#include <mutex>
#else
diff --git a/Source/Core/Common/Src/StdThread.h b/Source/Core/Common/Src/StdThread.h
index fea058c874..8893c36204 100644
--- a/Source/Core/Common/Src/StdThread.h
+++ b/Source/Core/Common/Src/StdThread.h
@@ -5,7 +5,7 @@
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
-#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
+#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
// GCC 4.4 provides <thread>
#ifndef _GLIBCXX_USE_SCHED_YIELD
#define _GLIBCXX_USE_SCHED_YIELD
@@ -88,7 +88,7 @@ public:
{
return !(*this == rhs);
}
-
+
bool operator<(const id& rhs) const
{
return m_thread < rhs.m_thread;
diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp
index e5c70b2c6b..43c4aebf12 100644
--- a/Source/Core/Common/Src/StringUtil.cpp
+++ b/Source/Core/Common/Src/StringUtil.cpp
@@ -17,11 +17,21 @@
#include <stdlib.h>
#include <stdio.h>
+#include <algorithm>
#include "Common.h"
#include "CommonPaths.h"
#include "StringUtil.h"
+#ifdef _WIN32
+ #include <Windows.h>
+#elif defined(ANDROID)
+
+#else
+ #include <iconv.h>
+ #include <errno.h>
+#endif
+
// faster than sscanf
bool AsciiToHex(const char* _szValue, u32& result)
{
@@ -263,25 +273,25 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
const char HEX2DEC[256] =
{
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
- /* 0 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* 1 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* 2 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1,
-
- /* 4 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* 5 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* 6 */ -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* 7 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-
- /* 8 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* 9 */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* A */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* B */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-
- /* C */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* D */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* E */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
- /* F */ -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
+ /* 0 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* 1 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* 2 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,16,16, 16,16,16,16,
+
+ /* 4 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16,
+ /* 5 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* 6 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16,
+ /* 7 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+
+ /* 8 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* 9 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* A */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* B */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+
+ /* C */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* D */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* E */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
+ /* F */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16
};
std::string UriDecode(const std::string & sSrc)
@@ -303,8 +313,8 @@ std::string UriDecode(const std::string & sSrc)
if (*pSrc == '%')
{
char dec1, dec2;
- if (-1 != (dec1 = HEX2DEC[*(pSrc + 1)])
- && -1 != (dec2 = HEX2DEC[*(pSrc + 2)]))
+ if (16 != (dec1 = HEX2DEC[*(pSrc + 1)])
+ && 16 != (dec2 = HEX2DEC[*(pSrc + 2)]))
{
*pEnd++ = (dec1 << 4) + dec2;
pSrc += 3;
@@ -375,3 +385,137 @@ std::string UriEncode(const std::string & sSrc)
delete [] pStart;
return sResult;
}
+
+#ifdef _WIN32
+
+std::string UTF16ToUTF8(const std::wstring& input)
+{
+ auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), nullptr, 0, nullptr, nullptr);
+
+ std::string output;
+ output.resize(size);
+
+ if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size(), nullptr, nullptr))
+ output.clear();
+
+ return output;
+}
+
+std::wstring CPToUTF16(u32 code_page, const std::string& input)
+{
+ auto const size = MultiByteToWideChar(code_page, 0, input.data(), input.size(), nullptr, 0);
+
+ std::wstring output;
+ output.resize(size);
+
+ if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), input.size(), &output[0], output.size()))
+ output.clear();
+
+ return output;
+}
+
+std::wstring UTF8ToUTF16(const std::string& input)
+{
+ return CPToUTF16(CP_UTF8, input);
+}
+
+std::string SHIFTJISToUTF8(const std::string& input)
+{
+ return UTF16ToUTF8(CPToUTF16(932, input));
+}
+
+std::string CP1252ToUTF8(const std::string& input)
+{
+ return UTF16ToUTF8(CPToUTF16(1252, input));
+}
+
+#else
+
+template <typename T>
+std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input)
+{
+ std::string result;
+
+#if defined(ANDROID)
+ result = "Not implemented on Android!";
+
+#else
+ iconv_t const conv_desc = iconv_open("UTF-8", fromcode);
+ if ((iconv_t)-1 == conv_desc)
+ {
+ ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
+ }
+ else
+ {
+ size_t const in_bytes = sizeof(T) * input.size();
+ size_t const out_buffer_size = 4 * in_bytes;
+
+ std::string out_buffer;
+ out_buffer.resize(out_buffer_size);
+
+ auto src_buffer = &input[0];
+ size_t src_bytes = in_bytes;
+ auto dst_buffer = &out_buffer[0];
+ size_t dst_bytes = out_buffer.size();
+
+ while (src_bytes != 0)
+ {
+ size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes,
+ &dst_buffer, &dst_bytes);
+
+ if ((size_t)-1 == iconv_result)
+ {
+ if (EILSEQ == errno || EINVAL == errno)
+ {
+ // Try to skip the bad character
+ if (src_bytes != 0)
+ {
+ --src_bytes;
+ ++src_buffer;
+ }
+ }
+ else
+ {
+ ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno));
+ break;
+ }
+ }
+ }
+
+ out_buffer.resize(out_buffer_size - dst_bytes);
+ out_buffer.swap(result);
+
+ iconv_close(conv_desc);
+ }
+
+#endif
+ return result;
+}
+
+std::string CP1252ToUTF8(const std::string& input)
+{
+ //return CodeToUTF8("CP1252//TRANSLIT", input);
+ //return CodeToUTF8("CP1252//IGNORE", input);
+ return CodeToUTF8("CP1252", input);
+}
+
+std::string SHIFTJISToUTF8(const std::string& input)
+{
+ //return CodeToUTF8("CP932", input);
+ return CodeToUTF8("SJIS", input);
+}
+
+std::string UTF16ToUTF8(const std::wstring& input)
+{
+ std::string result =
+ // CodeToUTF8("UCS-2", input);
+ // CodeToUTF8("UCS-2LE", input);
+ // CodeToUTF8("UTF-16", input);
+ CodeToUTF8("UTF-16LE", input);
+
+ // TODO: why is this needed?
+ result.erase(std::remove(result.begin(), result.end(), 0x00), result.end());
+ return result;
+}
+
+#endif
diff --git a/Source/Core/Common/Src/StringUtil.h b/Source/Core/Common/Src/StringUtil.h
index 102ae2d5fb..9463db5bb1 100644
--- a/Source/Core/Common/Src/StringUtil.h
+++ b/Source/Core/Common/Src/StringUtil.h
@@ -97,4 +97,28 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
std::string UriDecode(const std::string & sSrc);
std::string UriEncode(const std::string & sSrc);
+std::string CP1252ToUTF8(const std::string& str);
+std::string SHIFTJISToUTF8(const std::string& str);
+std::string UTF16ToUTF8(const std::wstring& str);
+
+#ifdef _WIN32
+
+std::wstring UTF8ToUTF16(const std::string& str);
+
+#ifdef _UNICODE
+inline std::string TStrToUTF8(const std::wstring& str)
+{ return UTF16ToUTF8(str); }
+
+inline std::wstring UTF8ToTStr(const std::string& str)
+{ return UTF8ToUTF16(str); }
+#else
+inline std::string TStrToUTF8(const std::string& str)
+{ return str; }
+
+inline std::string UTF8ToTStr(const std::string& str)
+{ return str; }
+#endif
+
+#endif
+
#endif // _STRINGUTIL_H_
diff --git a/Source/Core/Common/Src/Thread.cpp b/Source/Core/Common/Src/Thread.cpp
index 73f83c204f..3e8440b74f 100644
--- a/Source/Core/Common/Src/Thread.cpp
+++ b/Source/Core/Common/Src/Thread.cpp
@@ -105,7 +105,7 @@ void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
#ifdef __APPLE__
thread_policy_set(pthread_mach_thread_np(thread),
THREAD_AFFINITY_POLICY, (integer_t *)&mask, 1);
-#elif defined __linux__ || defined BSD4_4
+#elif (defined __linux__ || defined BSD4_4) && !(defined ANDROID)
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h
index e711fcab5c..b5f899c43b 100644
--- a/Source/Core/Common/Src/Thread.h
+++ b/Source/Core/Common/Src/Thread.h
@@ -33,8 +33,6 @@
#define INFINITE 0xffffffff
#endif
-#include <xmmintrin.h>
-
//for gettimeofday and struct time(spec|val)
#include <time.h>
#include <sys/time.h>
@@ -64,7 +62,7 @@ public:
m_condvar.notify_one();
}
}
-
+
void Wait()
{
std::unique_lock<std::mutex> lk(m_mutex);
diff --git a/Source/Core/Common/Src/Version.cpp b/Source/Core/Common/Src/Version.cpp
index 97e232785d..a668d24e1b 100644
--- a/Source/Core/Common/Src/Version.cpp
+++ b/Source/Core/Common/Src/Version.cpp
@@ -50,3 +50,5 @@ const char *netplay_dolphin_ver = SCM_DESC_STR " M" NP_ARCH;
#else
const char *netplay_dolphin_ver = SCM_DESC_STR " L" NP_ARCH;
#endif
+
+const char *scm_rev_git_str = SCM_REV_STR;
diff --git a/Source/Core/Common/Src/VideoBackendBase.cpp b/Source/Core/Common/Src/VideoBackendBase.cpp
index 62bb42997f..a5aa572039 100644
--- a/Source/Core/Common/Src/VideoBackendBase.cpp
+++ b/Source/Core/Common/Src/VideoBackendBase.cpp
@@ -29,6 +29,7 @@
std::vector<VideoBackend*> g_available_video_backends;
VideoBackend* g_video_backend = NULL;
+static VideoBackend* s_default_backend = NULL;
#ifdef _WIN32
// http://msdn.microsoft.com/en-us/library/ms725491.aspx
@@ -49,17 +50,27 @@ static bool IsGteVista()
void VideoBackend::PopulateList()
{
+ VideoBackend* backends[4] = { NULL };
+
+ // D3D11 > OGL > D3D9 > SW
#ifdef _WIN32
- g_available_video_backends.push_back(new DX9::VideoBackend);
+ g_available_video_backends.push_back(backends[2] = new DX9::VideoBackend);
if (IsGteVista())
- g_available_video_backends.push_back(new DX11::VideoBackend);
+ g_available_video_backends.push_back(backends[0] = new DX11::VideoBackend);
#endif
#ifndef USE_GLES
- g_available_video_backends.push_back(new OGL::VideoBackend);
+ g_available_video_backends.push_back(backends[1] = new OGL::VideoBackend);
#endif
- g_available_video_backends.push_back(new SW::VideoSoftware);
+ g_available_video_backends.push_back(backends[3] = new SW::VideoSoftware);
- g_video_backend = g_available_video_backends.front();
+ for (int i = 0; i < 4; ++i)
+ {
+ if (backends[i])
+ {
+ s_default_backend = g_video_backend = backends[i];
+ break;
+ }
+ }
}
void VideoBackend::ClearList()
@@ -73,8 +84,8 @@ void VideoBackend::ClearList()
void VideoBackend::ActivateBackend(const std::string& name)
{
- if (name.length() == 0) // If NULL, set it to the first one in the list. Expected behavior
- g_video_backend = g_available_video_backends.front();
+ if (name.length() == 0) // If NULL, set it to the default backend (expected behavior)
+ g_video_backend = s_default_backend;
for (std::vector<VideoBackend*>::const_iterator it = g_available_video_backends.begin(); it != g_available_video_backends.end(); ++it)
if (name == (*it)->GetName())
diff --git a/Source/Core/Common/Src/VideoBackendBase.h b/Source/Core/Common/Src/VideoBackendBase.h
index 311fa66104..c4455b3234 100644
--- a/Source/Core/Common/Src/VideoBackendBase.h
+++ b/Source/Core/Common/Src/VideoBackendBase.h
@@ -22,6 +22,7 @@
#include <vector>
#include "ChunkFile.h"
+#include "../../VideoCommon/Src/PerfQueryBase.h"
typedef void (*writeFn16)(const u16,const u32);
typedef void (*writeFn32)(const u32,const u32);
@@ -96,17 +97,20 @@ public:
virtual void RunLoop(bool enable) = 0;
virtual std::string GetName() = 0;
+ virtual std::string GetDisplayName() { return GetName(); }
virtual void ShowConfig(void*) {}
virtual void Video_Prepare() = 0;
virtual void Video_EnterLoop() = 0;
virtual void Video_ExitLoop() = 0;
+ virtual void Video_Cleanup() = 0; // called from gl/d3d thread
virtual void Video_BeginField(u32, FieldType, u32, u32) = 0;
virtual void Video_EndField() = 0;
virtual u32 Video_AccessEFB(EFBAccessType, u32, u32, u32) = 0;
+ virtual u32 Video_GetQueryResult(PerfQueryType type) = 0;
virtual void Video_AddMessage(const char* pstr, unsigned int milliseconds) = 0;
virtual void Video_ClearMessages() = 0;
@@ -156,8 +160,10 @@ class VideoBackendHardware : public VideoBackend
void Video_ExitLoop();
void Video_BeginField(u32, FieldType, u32, u32);
void Video_EndField();
- u32 Video_AccessEFB(EFBAccessType, u32, u32, u32);
+ u32 Video_AccessEFB(EFBAccessType, u32, u32, u32);
+ u32 Video_GetQueryResult(PerfQueryType type);
+
void Video_AddMessage(const char* pstr, unsigned int milliseconds);
void Video_ClearMessages();
bool Video_Screenshot(const char* filename);
diff --git a/Source/Core/Common/Src/ABI.cpp b/Source/Core/Common/Src/x64ABI.cpp
index 63a8e76934..468d02d9b9 100644
--- a/Source/Core/Common/Src/ABI.cpp
+++ b/Source/Core/Common/Src/x64ABI.cpp
@@ -17,7 +17,7 @@
#include "Common.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
using namespace Gen;
@@ -226,11 +226,11 @@ void XEmitter::ABI_CallFunction(void *func) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -239,11 +239,11 @@ void XEmitter::ABI_CallFunctionC16(void *func, u16 param1) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -266,11 +266,11 @@ void XEmitter::ABI_CallFunctionC(void *func, u32 param1) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -280,11 +280,11 @@ void XEmitter::ABI_CallFunctionCC(void *func, u32 param1, u32 param2) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -295,11 +295,11 @@ void XEmitter::ABI_CallFunctionCCC(void *func, u32 param1, u32 param2, u32 param
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -310,11 +310,11 @@ void XEmitter::ABI_CallFunctionCCP(void *func, u32 param1, u32 param2, void *par
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -326,11 +326,11 @@ void XEmitter::ABI_CallFunctionCCCP(void *func, u32 param1, u32 param2, u32 para
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -341,11 +341,11 @@ void XEmitter::ABI_CallFunctionPPC(void *func, void *param1, void *param2, u32 p
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -356,11 +356,11 @@ void XEmitter::ABI_CallFunctionR(void *func, X64Reg reg1) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -380,11 +380,11 @@ void XEmitter::ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2) {
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -396,11 +396,11 @@ void XEmitter::ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
@@ -411,11 +411,11 @@ void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1)
u64 distance = u64(func) - (u64(code) + 5);
if (distance >= 0x0000000080000000ULL
&& distance < 0xFFFFFFFF80000000ULL) {
- // Far call
- MOV(64, R(RAX), Imm64((u64)func));
- CALLptr(R(RAX));
+ // Far call
+ MOV(64, R(RAX), Imm64((u64)func));
+ CALLptr(R(RAX));
} else {
- CALL(func);
+ CALL(func);
}
}
diff --git a/Source/Core/Common/Src/ABI.h b/Source/Core/Common/Src/x64ABI.h
index 7226870e58..7226870e58 100644
--- a/Source/Core/Common/Src/ABI.h
+++ b/Source/Core/Common/Src/x64ABI.h
diff --git a/Source/Core/Common/Src/x64Analyzer.cpp b/Source/Core/Common/Src/x64Analyzer.cpp
index 66a2fe217f..37a9030a4b 100644
--- a/Source/Core/Common/Src/x64Analyzer.cpp
+++ b/Source/Core/Common/Src/x64Analyzer.cpp
@@ -60,18 +60,18 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
codeByte = *codePtr++;
- // Skip two-byte opcode byte
- bool twoByte = false;
- if(codeByte == 0x0F)
- {
- twoByte = true;
+ // Skip two-byte opcode byte
+ bool twoByte = false;
+ if(codeByte == 0x0F)
+ {
+ twoByte = true;
codeByte2 = *codePtr++;
- }
+ }
if (!twoByte)
{
- if ((codeByte & 0xF0) == 0x80 ||
- ((codeByte & 0xF8) == 0xC0 && (codeByte & 0x0E) != 0x02))
+ if ((codeByte & 0xF0) == 0x80 ||
+ ((codeByte & 0xF8) == 0xC0 && (codeByte & 0x0E) != 0x02))
{
modRMbyte = *codePtr++;
hasModRM = true;
@@ -79,20 +79,20 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
}
else
{
- if (((codeByte2 & 0xF0) == 0x00 && (codeByte2 & 0x0F) >= 0x04 && (codeByte2 & 0x0D) != 0x0D) ||
- (codeByte2 & 0xF0) == 0x30 ||
- codeByte2 == 0x77 ||
- (codeByte2 & 0xF0) == 0x80 ||
- ((codeByte2 & 0xF0) == 0xA0 && (codeByte2 & 0x07) <= 0x02) ||
- (codeByte2 & 0xF8) == 0xC8)
- {
- // No mod R/M byte
- }
- else
- {
+ if (((codeByte2 & 0xF0) == 0x00 && (codeByte2 & 0x0F) >= 0x04 && (codeByte2 & 0x0D) != 0x0D) ||
+ (codeByte2 & 0xF0) == 0x30 ||
+ codeByte2 == 0x77 ||
+ (codeByte2 & 0xF0) == 0x80 ||
+ ((codeByte2 & 0xF0) == 0xA0 && (codeByte2 & 0x07) <= 0x02) ||
+ (codeByte2 & 0xF8) == 0xC8)
+ {
+ // No mod R/M byte
+ }
+ else
+ {
modRMbyte = *codePtr++;
hasModRM = true;
- }
+ }
}
if (hasModRM)
@@ -130,7 +130,7 @@ bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int acc
info.displacement = *((s32 *)codePtr);
codePtr += displacementSize;
-
+
if (accessType == 1)
{
info.isMemoryWrite = true;
diff --git a/Source/Core/Common/Src/x64Analyzer.h b/Source/Core/Common/Src/x64Analyzer.h
index 8b13ca94aa..e9676ec250 100644
--- a/Source/Core/Common/Src/x64Analyzer.h
+++ b/Source/Core/Common/Src/x64Analyzer.h
@@ -51,7 +51,7 @@ enum{
MOVZX_SHORT = 0xB7, //movzx on short
MOVSX_BYTE = 0xBE, //movsx on byte
MOVSX_SHORT = 0xBF, //movsx on short
- MOVE_8BIT = 0xC6, //move 8-bit immediate
+ MOVE_8BIT = 0xC6, //move 8-bit immediate
MOVE_16_32BIT = 0xC7, //move 16 or 32-bit immediate
MOVE_REG_TO_MEM = 0x89, //move reg to memory
};
diff --git a/Source/Core/Common/Src/CPUDetect.cpp b/Source/Core/Common/Src/x64CPUDetect.cpp
index 282929e7b2..dcde313630 100644
--- a/Source/Core/Common/Src/CPUDetect.cpp
+++ b/Source/Core/Common/Src/x64CPUDetect.cpp
@@ -30,16 +30,20 @@
#else
//#include <config/i386/cpuid.h>
+#ifndef _M_GENERIC
#include <xmmintrin.h>
+#endif
#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)
+ unsigned int *ecx, unsigned int *edx)
{
-#ifdef _LP64
+#if defined _M_GENERIC
+ (*eax) = (*ebx) = (*ecx) = (*edx) = 0;
+#elif defined _LP64
// 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__ (
diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp
index 5f8d0a66f1..1a74eaef80 100644
--- a/Source/Core/Common/Src/x64Emitter.cpp
+++ b/Source/Core/Common/Src/x64Emitter.cpp
@@ -17,7 +17,7 @@
#include "Common.h"
#include "x64Emitter.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "CPUDetect.h"
namespace Gen
@@ -51,13 +51,13 @@ static const NormalOpDef nops[11] =
enum NormalSSEOps
{
- sseCMP = 0xC2,
- sseADD = 0x58, //ADD
+ sseCMP = 0xC2,
+ sseADD = 0x58, //ADD
sseSUB = 0x5C, //SUB
sseAND = 0x54, //AND
sseANDN = 0x55, //ANDN
- sseOR = 0x56,
- sseXOR = 0x57,
+ sseOR = 0x56,
+ sseXOR = 0x57,
sseMUL = 0x59, //MUL,
sseDIV = 0x5E, //DIV
sseMIN = 0x5D, //MIN
@@ -143,18 +143,18 @@ void OpArg::WriteRex(XEmitter *emit, int opBits, int bits, int customOp) const
if (indexReg & 8) op |= 2;
if (offsetOrBaseReg & 8) op |= 1; //TODO investigate if this is dangerous
if (op != 0x40 ||
- (bits == 8 && (offsetOrBaseReg & 0x10c) == 4) ||
- (opBits == 8 && (customOp & 0x10c) == 4)) {
+ (bits == 8 && (offsetOrBaseReg & 0x10c) == 4) ||
+ (opBits == 8 && (customOp & 0x10c) == 4)) {
emit->Write8(op);
_dbg_assert_(DYNA_REC, (offsetOrBaseReg & 0x100) == 0 || bits != 8);
_dbg_assert_(DYNA_REC, (customOp & 0x100) == 0 || opBits != 8);
} else {
_dbg_assert_(DYNA_REC, (offsetOrBaseReg & 0x10c) == 0 ||
- (offsetOrBaseReg & 0x10c) == 0x104 ||
- bits != 8);
+ (offsetOrBaseReg & 0x10c) == 0x104 ||
+ bits != 8);
_dbg_assert_(DYNA_REC, (customOp & 0x10c) == 0 ||
- (customOp & 0x10c) == 0x104 ||
- opBits != 8);
+ (customOp & 0x10c) == 0x104 ||
+ opBits != 8);
}
#else
@@ -969,15 +969,15 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &o
immToWrite = 8;
}
else if ((operand.scale == SCALE_IMM16 && bits == 16) ||
- (operand.scale == SCALE_IMM32 && bits == 32) ||
- (operand.scale == SCALE_IMM32 && bits == 64))
+ (operand.scale == SCALE_IMM32 && bits == 32) ||
+ (operand.scale == SCALE_IMM32 && bits == 64))
{
emit->Write8(nops[op].imm32);
immToWrite = bits == 16 ? 16 : 32;
}
else if ((operand.scale == SCALE_IMM8 && bits == 16) ||
- (operand.scale == SCALE_IMM8 && bits == 32) ||
- (operand.scale == SCALE_IMM8 && bits == 64))
+ (operand.scale == SCALE_IMM8 && bits == 32) ||
+ (operand.scale == SCALE_IMM8 && bits == 64))
{
emit->Write8(nops[op].simm8);
immToWrite = 8;
@@ -1471,142 +1471,142 @@ void XEmitter::RTDSC() { Write8(0x0F); Write8(0x31); }
// helper routines for setting pointers
void XEmitter::CallCdeclFunction3(void* fnptr, u32 arg0, u32 arg1, u32 arg2)
{
- using namespace Gen;
+ using namespace Gen;
#ifdef _M_X64
#ifdef _MSC_VER
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
- CALL(fnptr);
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
+ CALL(fnptr);
#else
- MOV(32, R(RDI), Imm32(arg0));
- MOV(32, R(RSI), Imm32(arg1));
- MOV(32, R(RDX), Imm32(arg2));
- CALL(fnptr);
+ MOV(32, R(RDI), Imm32(arg0));
+ MOV(32, R(RSI), Imm32(arg1));
+ MOV(32, R(RDX), Imm32(arg2));
+ CALL(fnptr);
#endif
#else
- ABI_AlignStack(3 * 4);
- PUSH(32, Imm32(arg2));
- PUSH(32, Imm32(arg1));
- PUSH(32, Imm32(arg0));
- CALL(fnptr);
+ ABI_AlignStack(3 * 4);
+ PUSH(32, Imm32(arg2));
+ PUSH(32, Imm32(arg1));
+ PUSH(32, Imm32(arg0));
+ CALL(fnptr);
#ifdef _WIN32
- // don't inc stack
+ // don't inc stack
#else
- ABI_RestoreStack(3 * 4);
+ ABI_RestoreStack(3 * 4);
#endif
#endif
}
void XEmitter::CallCdeclFunction4(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3)
{
- using namespace Gen;
+ using namespace Gen;
#ifdef _M_X64
#ifdef _MSC_VER
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
- MOV(32, R(R9), Imm32(arg3));
- CALL(fnptr);
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
+ MOV(32, R(R9), Imm32(arg3));
+ CALL(fnptr);
#else
- MOV(32, R(RDI), Imm32(arg0));
- MOV(32, R(RSI), Imm32(arg1));
- MOV(32, R(RDX), Imm32(arg2));
- MOV(32, R(RCX), Imm32(arg3));
- CALL(fnptr);
+ MOV(32, R(RDI), Imm32(arg0));
+ MOV(32, R(RSI), Imm32(arg1));
+ MOV(32, R(RDX), Imm32(arg2));
+ MOV(32, R(RCX), Imm32(arg3));
+ CALL(fnptr);
#endif
#else
- ABI_AlignStack(4 * 4);
- PUSH(32, Imm32(arg3));
- PUSH(32, Imm32(arg2));
- PUSH(32, Imm32(arg1));
- PUSH(32, Imm32(arg0));
- CALL(fnptr);
+ ABI_AlignStack(4 * 4);
+ PUSH(32, Imm32(arg3));
+ PUSH(32, Imm32(arg2));
+ PUSH(32, Imm32(arg1));
+ PUSH(32, Imm32(arg0));
+ CALL(fnptr);
#ifdef _WIN32
- // don't inc stack
+ // don't inc stack
#else
- ABI_RestoreStack(4 * 4);
+ ABI_RestoreStack(4 * 4);
#endif
#endif
}
void XEmitter::CallCdeclFunction5(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
{
- using namespace Gen;
+ using namespace Gen;
#ifdef _M_X64
#ifdef _MSC_VER
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
- MOV(32, R(R9), Imm32(arg3));
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
+ MOV(32, R(R9), Imm32(arg3));
MOV(32, MDisp(RSP, 0x20), Imm32(arg4));
- CALL(fnptr);
+ CALL(fnptr);
#else
- MOV(32, R(RDI), Imm32(arg0));
- MOV(32, R(RSI), Imm32(arg1));
- MOV(32, R(RDX), Imm32(arg2));
- MOV(32, R(RCX), Imm32(arg3));
- MOV(32, R(R8), Imm32(arg4));
- CALL(fnptr);
+ MOV(32, R(RDI), Imm32(arg0));
+ MOV(32, R(RSI), Imm32(arg1));
+ MOV(32, R(RDX), Imm32(arg2));
+ MOV(32, R(RCX), Imm32(arg3));
+ MOV(32, R(R8), Imm32(arg4));
+ CALL(fnptr);
#endif
#else
- ABI_AlignStack(5 * 4);
- PUSH(32, Imm32(arg4));
- PUSH(32, Imm32(arg3));
- PUSH(32, Imm32(arg2));
- PUSH(32, Imm32(arg1));
- PUSH(32, Imm32(arg0));
- CALL(fnptr);
+ ABI_AlignStack(5 * 4);
+ PUSH(32, Imm32(arg4));
+ PUSH(32, Imm32(arg3));
+ PUSH(32, Imm32(arg2));
+ PUSH(32, Imm32(arg1));
+ PUSH(32, Imm32(arg0));
+ CALL(fnptr);
#ifdef _WIN32
- // don't inc stack
+ // don't inc stack
#else
- ABI_RestoreStack(5 * 4);
+ ABI_RestoreStack(5 * 4);
#endif
#endif
}
void XEmitter::CallCdeclFunction6(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
{
- using namespace Gen;
+ using namespace Gen;
#ifdef _M_X64
#ifdef _MSC_VER
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
- MOV(32, R(R9), Imm32(arg3));
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
+ MOV(32, R(R9), Imm32(arg3));
MOV(32, MDisp(RSP, 0x20), Imm32(arg4));
MOV(32, MDisp(RSP, 0x28), Imm32(arg5));
- CALL(fnptr);
+ CALL(fnptr);
#else
- MOV(32, R(RDI), Imm32(arg0));
- MOV(32, R(RSI), Imm32(arg1));
- MOV(32, R(RDX), Imm32(arg2));
- MOV(32, R(RCX), Imm32(arg3));
- MOV(32, R(R8), Imm32(arg4));
- MOV(32, R(R9), Imm32(arg5));
- CALL(fnptr);
+ MOV(32, R(RDI), Imm32(arg0));
+ MOV(32, R(RSI), Imm32(arg1));
+ MOV(32, R(RDX), Imm32(arg2));
+ MOV(32, R(RCX), Imm32(arg3));
+ MOV(32, R(R8), Imm32(arg4));
+ MOV(32, R(R9), Imm32(arg5));
+ CALL(fnptr);
#endif
#else
- ABI_AlignStack(6 * 4);
- PUSH(32, Imm32(arg5));
- PUSH(32, Imm32(arg4));
- PUSH(32, Imm32(arg3));
- PUSH(32, Imm32(arg2));
- PUSH(32, Imm32(arg1));
- PUSH(32, Imm32(arg0));
- CALL(fnptr);
+ ABI_AlignStack(6 * 4);
+ PUSH(32, Imm32(arg5));
+ PUSH(32, Imm32(arg4));
+ PUSH(32, Imm32(arg3));
+ PUSH(32, Imm32(arg2));
+ PUSH(32, Imm32(arg1));
+ PUSH(32, Imm32(arg0));
+ CALL(fnptr);
#ifdef _WIN32
- // don't inc stack
+ // don't inc stack
#else
- ABI_RestoreStack(6 * 4);
+ ABI_RestoreStack(6 * 4);
#endif
#endif
}
@@ -1615,31 +1615,31 @@ void XEmitter::CallCdeclFunction6(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32
// See header
void XEmitter::___CallCdeclImport3(void* impptr, u32 arg0, u32 arg1, u32 arg2) {
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
CALLptr(M(impptr));
}
void XEmitter::___CallCdeclImport4(void* impptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3) {
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
- MOV(32, R(R9), Imm32(arg3));
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
+ MOV(32, R(R9), Imm32(arg3));
CALLptr(M(impptr));
}
void XEmitter::___CallCdeclImport5(void* impptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4) {
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
- MOV(32, R(R9), Imm32(arg3));
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
+ MOV(32, R(R9), Imm32(arg3));
MOV(32, MDisp(RSP, 0x20), Imm32(arg4));
CALLptr(M(impptr));
}
void XEmitter::___CallCdeclImport6(void* impptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 arg5) {
- MOV(32, R(RCX), Imm32(arg0));
- MOV(32, R(RDX), Imm32(arg1));
- MOV(32, R(R8), Imm32(arg2));
- MOV(32, R(R9), Imm32(arg3));
+ MOV(32, R(RCX), Imm32(arg0));
+ MOV(32, R(RDX), Imm32(arg1));
+ MOV(32, R(R8), Imm32(arg2));
+ MOV(32, R(R9), Imm32(arg3));
MOV(32, MDisp(RSP, 0x20), Imm32(arg4));
MOV(32, MDisp(RSP, 0x28), Imm32(arg5));
CALLptr(M(impptr));
diff --git a/Source/Core/Common/Src/x64Emitter.h b/Source/Core/Common/Src/x64Emitter.h
index 3b699c81a0..97ba080790 100644
--- a/Source/Core/Common/Src/x64Emitter.h
+++ b/Source/Core/Common/Src/x64Emitter.h
@@ -757,7 +757,7 @@ public:
region_size = 0;
}
- bool IsInCodeSpace(u8 *ptr)
+ bool IsInSpace(u8 *ptr)
{
return ptr >= region && ptr < region + region_size;
}
@@ -766,7 +766,7 @@ public:
// Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()).
void WriteProtect()
{
- WriteProtectMemory(region, region_size, true);
+ WriteProtectMemory(region, region_size, true);
}
void ResetCodePtr()
diff --git a/Source/Core/Common/Src/x64FPURoundMode.cpp b/Source/Core/Common/Src/x64FPURoundMode.cpp
new file mode 100644
index 0000000000..41363f7999
--- /dev/null
+++ b/Source/Core/Common/Src/x64FPURoundMode.cpp
@@ -0,0 +1,120 @@
+// Copyright (C) 2003 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Common.h"
+#include "FPURoundMode.h"
+
+#ifndef _WIN32
+static const unsigned short FPU_ROUND_NEAR = 0 << 10;
+static const unsigned short FPU_ROUND_DOWN = 1 << 10;
+static const unsigned short FPU_ROUND_UP = 2 << 10;
+static const unsigned short FPU_ROUND_CHOP = 3 << 10;
+static const unsigned short FPU_ROUND_MASK = 3 << 10;
+#include <xmmintrin.h>
+#endif
+
+const u32 MASKS = 0x1F80; // mask away the interrupts.
+const u32 DAZ = 0x40;
+const u32 FTZ = 0x8000;
+
+namespace FPURoundMode
+{
+ // Get the default SSE states here.
+ static u32 saved_sse_state = _mm_getcsr();
+ static const u32 default_sse_state = _mm_getcsr();
+
+ void SetRoundMode(u32 mode)
+ {
+ // Set FPU rounding mode to mimic the PowerPC's
+ #ifdef _M_IX86
+ // This shouldn't really be needed anymore since we use SSE
+ #ifdef _WIN32
+ const int table[4] =
+ {
+ _RC_NEAR,
+ _RC_CHOP,
+ _RC_UP,
+ _RC_DOWN
+ };
+ _set_controlfp(_MCW_RC, table[mode]);
+ #else
+ const unsigned short table[4] =
+ {
+ FPU_ROUND_NEAR,
+ FPU_ROUND_CHOP,
+ FPU_ROUND_UP,
+ FPU_ROUND_DOWN
+ };
+ unsigned short _mode;
+ asm ("fstcw %0" : "=m" (_mode) : );
+ _mode = (_mode & ~FPU_ROUND_MASK) | table[mode];
+ asm ("fldcw %0" : : "m" (_mode));
+ #endif
+ #endif
+ }
+
+ void SetPrecisionMode(u32 mode)
+ {
+ #ifdef _M_IX86
+ // sets the floating-point lib to 53-bit
+ // PowerPC has a 53bit floating pipeline only
+ // eg: sscanf is very sensitive
+ #ifdef _WIN32
+ _control87(_PC_53, MCW_PC);
+ #else
+ const unsigned short table[4] = {
+ 0 << 8, // FPU_PREC_24
+ 2 << 8, // FPU_PREC_53
+ 3 << 8, // FPU_PREC_64
+ 3 << 8, // FPU_PREC_MASK
+ };
+ unsigned short _mode;
+ asm ("fstcw %0" : : "m" (_mode));
+ _mode = (_mode & ~table[3]) | table[mode];
+ asm ("fldcw %0" : : "m" (_mode));
+ #endif
+ #else
+ //x64 doesn't need this - fpu is done with SSE
+ //but still - set any useful sse options here
+ #endif
+ }
+ void SetSIMDMode(u32 mode)
+ {
+ static const u32 ssetable[4] =
+ {
+ (0 << 13) | MASKS,
+ (3 << 13) | MASKS,
+ (2 << 13) | MASKS,
+ (1 << 13) | MASKS,
+ };
+ u32 csr = ssetable[mode];
+ _mm_setcsr(csr);
+ }
+
+ void SaveSIMDState()
+ {
+ saved_sse_state = _mm_getcsr();
+ }
+ void LoadSIMDState()
+ {
+ _mm_setcsr(saved_sse_state);
+ }
+ void LoadDefaultSIMDState()
+ {
+ _mm_setcsr(default_sse_state);
+ }
+}
diff --git a/Source/Core/Common/Src/Thunk.cpp b/Source/Core/Common/Src/x64Thunk.cpp
index 1792df3e77..b9fd54f354 100644
--- a/Source/Core/Common/Src/Thunk.cpp
+++ b/Source/Core/Common/Src/x64Thunk.cpp
@@ -18,9 +18,8 @@
#include <map>
#include "Common.h"
-#include "x64Emitter.h"
#include "MemoryUtil.h"
-#include "ABI.h"
+#include "x64ABI.h"
#include "Thunk.h"
#define THUNK_ARENA_SIZE 1024*1024*1