summaryrefslogtreecommitdiff
path: root/Source/Core/Common
diff options
context:
space:
mode:
authorskidau <skidau@gmail.com>2013-03-27 13:19:23 +1100
committerskidau <skidau@gmail.com>2013-03-27 13:19:23 +1100
commit7784fa4c67cc8d2545f45694d83805e7e89cd583 (patch)
tree7724133aabe971ec417d1dea0977a525bb8debfb /Source/Core/Common
parentd33c19b0cd2bae982c8d35e86a9d3551f9e5c72f (diff)
parent5cea0d9defeaa23e7af94adf7615a44fb2c9c173 (diff)
Merge branch 'master' into wii-network
# By Ryan Houdek (185) and others # Via degasus (12) and others * master: (625 commits) Revert "Don't open/close file for every file operation." as it was crashing PokePark in Windows builds. Array overrun fixed in VertexShaderCache for the DX11 plugin. Fixed DSPTool build. Windows build fix Go back to assuming every HID device is a wiimote on Windows. Fixed issue 6117. Unfixed issue 6031. VideoSoftware: Improve fog range adjustment by using less magic and more comments. revert RasterFont for VideoSoftware ogl: fix virtual xfb Windows build fix from web interface... Adjusted the audio loop criteria, using >= on the Wii and == on GC. This fixes the audio static that occurred in Wii games after hours of play. Forced the exception check only for ARAM DMA transfers. Removed the Eternal Darkness boot hack and replaced it with an exception check. VideoSoftware: Implement fog range adjustment, fixing issue 6147. implement 4xSSAA for OGL move ogl-only settings into backend Fix description of disable fog, and move it to enhancements tab. Reverted rd76ca5783743 as it was made obsolete by r1d550f4496e4. Removed the tracking of the FIFO Writes as it was made obsolete by r1d550f4496e4. Forced the external exception check to occur sooner by changing the downcount. Mark the Direct3D9 backend deprecated. Prefer D3D11 and OpenGL over D3D9 by default. ... Conflicts: CMakeLists.txt Source/Core/Common/Common.vcxproj.filters Source/Core/Common/Src/CommonPaths.h Source/Core/Core/Core.vcxproj.filters Source/Core/Core/Src/Core.cpp Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp Source/VSProps/Dolphin.Win32.props Source/VSProps/Dolphin.x64.props
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