summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt36
-rw-r--r--README.md2
-rw-r--r--appveyor.yml12
-rw-r--r--dist/citra.desktop14
-rw-r--r--dist/citra.svg80
-rw-r--r--dist/citra.xml59
-rw-r--r--src/citra/citra.cpp6
-rw-r--r--src/citra_qt/CMakeLists.txt36
-rw-r--r--src/citra_qt/debugger/callstack.cpp2
-rw-r--r--src/citra_qt/debugger/disassembler.cpp2
-rw-r--r--src/citra_qt/debugger/graphics_framebuffer.cpp2
-rw-r--r--src/citra_qt/debugger/ramview.cpp2
-rw-r--r--src/citra_qt/main.cpp10
-rw-r--r--src/common/CMakeLists.txt2
-rw-r--r--src/common/assert.h10
-rw-r--r--src/common/common_types.h26
-rw-r--r--src/common/concurrent_ring_buffer.h163
-rw-r--r--src/common/logging/backend.cpp56
-rw-r--r--src/common/logging/backend.h92
-rw-r--r--src/common/logging/filter.cpp41
-rw-r--r--src/common/logging/filter.h20
-rw-r--r--src/common/logging/log.h6
-rw-r--r--src/common/logging/text_formatter.cpp19
-rw-r--r--src/common/logging/text_formatter.h8
-rw-r--r--src/common/math_util.cpp211
-rw-r--r--src/common/math_util.h174
-rw-r--r--src/core/CMakeLists.txt6
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.cpp28
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp607
-rw-r--r--src/core/arm/interpreter/arminit.cpp1
-rw-r--r--src/core/arm/interpreter/armsupp.cpp2
-rw-r--r--src/core/arm/skyeye_common/armmmu.h2
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpdouble.cpp6
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp128
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp6
-rw-r--r--src/core/core.cpp1
-rw-r--r--src/core/file_sys/archive_backend.cpp2
-rw-r--r--src/core/hle/config_mem.cpp49
-rw-r--r--src/core/hle/config_mem.h38
-rw-r--r--src/core/hle/coprocessor.cpp33
-rw-r--r--src/core/hle/function_wrappers.h14
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp2
-rw-r--r--src/core/hle/kernel/kernel.cpp3
-rw-r--r--src/core/hle/kernel/kernel.h3
-rw-r--r--src/core/hle/kernel/process.cpp9
-rw-r--r--src/core/hle/kernel/process.h4
-rw-r--r--src/core/hle/kernel/resource_limit.cpp157
-rw-r--r--src/core/hle/kernel/resource_limit.h119
-rw-r--r--src/core/hle/kernel/session.h2
-rw-r--r--src/core/hle/kernel/shared_memory.cpp2
-rw-r--r--src/core/hle/kernel/thread.cpp4
-rw-r--r--src/core/hle/kernel/thread.h1
-rw-r--r--src/core/hle/service/apt/apt.cpp2
-rw-r--r--src/core/hle/service/fs/fs_user.cpp8
-rw-r--r--src/core/hle/service/gsp_gpu.cpp1
-rw-r--r--src/core/hle/shared_page.cpp57
-rw-r--r--src/core/hle/shared_page.h38
-rw-r--r--src/core/hle/svc.cpp63
-rw-r--r--src/core/hw/gpu.cpp2
-rw-r--r--src/core/loader/3dsx.cpp6
-rw-r--r--src/core/loader/elf.cpp6
-rw-r--r--src/core/loader/loader.cpp1
-rw-r--r--src/core/loader/ncch.cpp7
-rw-r--r--src/core/mem_map.cpp122
-rw-r--r--src/core/mem_map.h157
-rw-r--r--src/core/mem_map_funcs.cpp283
-rw-r--r--src/core/memory.cpp202
-rw-r--r--src/core/memory.h129
-rw-r--r--src/core/memory_setup.h29
-rw-r--r--src/video_core/command_processor.cpp44
-rw-r--r--src/video_core/pica.h4
-rw-r--r--src/video_core/rasterizer.cpp2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp2
-rw-r--r--src/video_core/vertex_shader.cpp2
74 files changed, 1680 insertions, 1807 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b0fe285db..fc742317c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,25 +15,32 @@ else()
# set up output paths for executable binaries (.exe-files, and .dll-files on DLL-capable platforms)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set(CMAKE_CONFIGURATION_TYPES Debug Release RelWithDebInfo CACHE STRING "" FORCE)
# Tweak optimization settings
# As far as I can tell, there's no way to override the CMake defaults while leaving user
# changes intact, so we'll just clobber everything and say sorry.
message(STATUS "Cache compiler flags ignored, please edit CMakeLists.txt to change the flags.")
- # /MP - Multi-threaded compilation
- # /MD - Multi-threaded runtime
- # /Ox - Full optimization
+ # /O2 - Optimization level 2
# /Oy- - Don't omit frame pointer
# /GR- - Disable RTTI
# /GS- - No stack buffer overflow checks
# /EHsc - C++-only exception handling semantics
- set(optimization_flags "/MP /MD /Ox /Oy- /GR- /GS- /EHsc")
+ set(optimization_flags "/O2 /Oy- /GR- /GS- /EHsc")
+ # /MP - Multi-threaded compilation
# /Zi - Output debugging information
# /Zo - enahnced debug info for optimized builds
- set(CMAKE_C_FLAGS_RELEASE "${optimization_flags} /Zi" CACHE STRING "" FORCE)
- set(CMAKE_CXX_FLAGS_RELEASE "${optimization_flags} /Zi" CACHE STRING "" FORCE)
- set(CMAKE_C_FLAGS_RELWITHDEBINFO "${optimization_flags} /Zi /Zo" CACHE STRING "" FORCE)
- set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${optimization_flags} /Zi /Zo" CACHE STRING "" FORCE)
+ # /MDd - Multi-threaded Debug Runtime DLL
+ set(CMAKE_C_FLAGS_DEBUG "/MP /MDd /Zi" CACHE STRING "" FORCE)
+ set(CMAKE_CXX_FLAGS_DEBUG "/MP /MDd /Zi" CACHE STRING "" FORCE)
+ # /MD - Multi-threaded runtime DLL
+ set(CMAKE_C_FLAGS_RELEASE "${optimization_flags} /MP /MD" CACHE STRING "" FORCE)
+ set(CMAKE_CXX_FLAGS_RELEASE "${optimization_flags} /MP /MD" CACHE STRING "" FORCE)
+ set(CMAKE_C_FLAGS_RELWITHDEBINFO "${optimization_flags} /MP /MD /Zi /Zo" CACHE STRING "" FORCE)
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${optimization_flags} /MP /MD /Zi /Zo" CACHE STRING "" FORCE)
+
+ set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG" CACHE STRING "" FORCE)
+ set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/DEBUG" CACHE STRING "" FORCE)
endif()
add_definitions(-DSINGLETHREADED)
@@ -193,3 +200,16 @@ if(ENABLE_QT)
add_subdirectory(externals/qhexedit)
endif()
add_subdirectory(src)
+
+# Install freedesktop.org metadata files, following those specifications:
+# http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html
+# http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html
+# http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html
+if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|FreeBSD|OpenBSD|NetBSD")
+ install(FILES "${CMAKE_SOURCE_DIR}/dist/citra.desktop"
+ DESTINATION "${CMAKE_INSTALL_PREFIX}/share/applications")
+ install(FILES "${CMAKE_SOURCE_DIR}/dist/citra.svg"
+ DESTINATION "${CMAKE_INSTALL_PREFIX}/share/pixmaps")
+ install(FILES "${CMAKE_SOURCE_DIR}/dist/citra.xml"
+ DESTINATION "${CMAKE_INSTALL_PREFIX}/share/mime/packages")
+endif()
diff --git a/README.md b/README.md
index af65f2b0e..f420beb09 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ For development discussion, please join us @ #citra on [freenode](http://webchat
### Development
-If you want to contribute please take a look at the [Contributor's Guide](CONTRIBUTING.md), [Roadmap](https://github.com/citra-emu/citra/wiki/Roadmap) and [Developer Information](https://github.com/citra-emu/citra/wiki/Developer-Information) pages. You should as well contact any of the developers in the forum in order to know about the current state of the emulator.
+If you want to contribute please take a look at the [Contributor's Guide](CONTRIBUTING.md), [TODO list](https://docs.google.com/document/d/1SWIop0uBI9IW8VGg97TAtoT_CHNoP42FzYmvG1F4QDA) and [Developer Information](https://github.com/citra-emu/citra/wiki/Developer-Information). You should as well contact any of the developers in the forum in order to know about the current state of the emulator.
### Building
diff --git a/appveyor.yml b/appveyor.yml
index 7886b905b..f2b656729 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -25,17 +25,7 @@ before_build:
- cd ..
after_build:
- # copy the qt dlls
- - copy C:\Qt\5.4\msvc2013_64_opengl\bin\icudt53.dll build\bin\release
- - copy C:\Qt\5.4\msvc2013_64_opengl\bin\icuin53.dll build\bin\release
- - copy C:\Qt\5.4\msvc2013_64_opengl\bin\icuuc53.dll build\bin\release
- - copy C:\Qt\5.4\msvc2013_64_opengl\bin\Qt5Core.dll build\bin\release
- - copy C:\Qt\5.4\msvc2013_64_opengl\bin\Qt5Gui.dll build\bin\release
- - copy C:\Qt\5.4\msvc2013_64_opengl\bin\Qt5OpenGL.dll build\bin\release
- - copy C:\Qt\5.4\msvc2013_64_opengl\bin\Qt5Widgets.dll build\bin\release
- - mkdir build\bin\release\platforms\
- - copy C:\Qt\5.4\msvc2013_64_opengl\plugins\platforms\qwindows.dll build\bin\release\platforms
-
+ # copying the needed QT Dlls is now done post build. See the CMakeLists.txt file in the citra-qt folder
- ps: >
if (!"$env:APPVEYOR_PULL_REQUEST_TITLE" -and ("$env:APPVEYOR_REPO_BRANCH" -eq "master"))
{
diff --git a/dist/citra.desktop b/dist/citra.desktop
new file mode 100644
index 000000000..1300d62c2
--- /dev/null
+++ b/dist/citra.desktop
@@ -0,0 +1,14 @@
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=Citra
+GenericName=3DS Emulator
+GenericName[fr]=Émulateur 3DS
+Comment=Nintendo 3DS video game console emulator
+Comment[fr]=Émulateur de console de jeu Nintendo 3DS
+Icon=citra
+TryExec=citra-qt
+Exec=citra-qt %f
+Categories=Game;Emulator;Qt;
+MimeType=application/x-ctr-3dsx;application/x-ctr-cci;application/x-ctr-cia;application/x-ctr-cxi;
+Keywords=3DS;Nintendo;
diff --git a/dist/citra.svg b/dist/citra.svg
new file mode 100644
index 000000000..7b299cd89
--- /dev/null
+++ b/dist/citra.svg
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2014 Citra Emulator Project
+ Licensed under GPLv2 or any later version
+ Refer to the license.txt file included.
+-->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 341.071 338.846">
+ <radialGradient id="a" cx="170.5356" cy="167.271" r="170.5332" gradientTransform="matrix(1 0 0 0.9935 0 3.2396)" gradientUnits="userSpaceOnUse">
+ <stop offset="0.5193" stop-color="#FFFFFF" stop-opacity="0.1"/>
+ <stop offset="0.9415" stop-color="#000000" stop-opacity="0.5"/>
+ <stop offset="1" stop-color="#1A1818" stop-opacity="0"/>
+ </radialGradient>
+ <ellipse fill="url(#a)" cx="170.535" cy="169.423" rx="170.535" ry="169.423"/>
+ <circle fill="#D16F17" cx="170.536" cy="167.885" r="161.557"/>
+ <linearGradient id="b" gradientUnits="userSpaceOnUse" x1="234.4458" y1="33.5771" x2="97.5655" y2="321.2358">
+ <stop offset="0" stop-color="#FFF8BD"/>
+ <stop offset="1" stop-color="#F6DCAE"/>
+ </linearGradient>
+ <circle fill="url(#b)" cx="170.536" cy="167.885" r="155.295"/>
+ <g>
+ <linearGradient id="c" gradientUnits="userSpaceOnUse" x1="332.436" y1="91.7446" x2="111.1593" y2="342.0988">
+ <stop offset="0" stop-color="#F7A076"/>
+ <stop offset="0.4455" stop-color="#F3816C"/>
+ <stop offset="1" stop-color="#F06878"/>
+ </linearGradient>
+ <path fill="url(#c)" stroke="#F06564" stroke-miterlimit="10" d="M309.704,123.138
+ c-5.9-7.802-128.517,44.681-128.517,44.681S303.803,221.01,309.704,212.5C322.434,194.142,323.182,140.957,309.704,123.138z"/>
+ <linearGradient id="d" gradientUnits="userSpaceOnUse" x1="285.5845" y1="50.3345" x2="64.3074" y2="300.6891">
+ <stop offset="0" stop-color="#9DC63B"/>
+ <stop offset="1" stop-color="#9BC183"/>
+ </linearGradient>
+ <path fill="url(#d)" stroke="#72AA42" stroke-miterlimit="10" d="M300.518,100.96c-3.98-21.983-41.059-60.12-63.189-63.188
+ c-9.688-1.345-59.28,122.469-59.28,122.469S302.364,111.149,300.518,100.96z"/>
+ <linearGradient id="e" gradientUnits="userSpaceOnUse" x1="229.4995" y1="0.7637" x2="8.2231" y2="251.1176">
+ <stop offset="0" stop-color="#D5DE26"/>
+ <stop offset="1" stop-color="#C5D94B"/>
+ </linearGradient>
+ <path fill="url(#e)" stroke="#BECD30" stroke-miterlimit="10" d="M215.151,28.584c-18.357-12.73-71.543-13.478-89.362,0.001
+ c-7.801,5.899,44.682,128.516,44.682,128.516S223.663,34.484,215.151,28.584z"/>
+ <linearGradient id="f" gradientUnits="userSpaceOnUse" x1="219.3823" y1="-8.1782" x2="-1.8941" y2="242.1756">
+ <stop offset="0" stop-color="#F2D200"/>
+ <stop offset="1" stop-color="#FDEF52"/>
+ </linearGradient>
+ <path fill="url(#f)" stroke="#E1BE29" stroke-miterlimit="10" d="M162.893,160.239c0,0-49.092-124.315-59.281-122.469
+ c-21.982,3.979-60.12,41.058-63.188,63.189C39.078,110.646,162.893,160.239,162.893,160.239z"/>
+ <linearGradient id="g" gradientUnits="userSpaceOnUse" x1="226.0718" y1="-2.2656" x2="4.7951" y2="248.0886">
+ <stop offset="0" stop-color="#FFCD10"/>
+ <stop offset="1" stop-color="#F29634"/>
+ </linearGradient>
+ <path fill="url(#g)" stroke="#F79421" stroke-miterlimit="10" d="M31.236,123.136c-12.73,18.357-13.479,71.543,0,89.362
+ c5.898,7.801,128.516-44.682,128.516-44.682S37.135,114.625,31.236,123.136z"/>
+ <linearGradient id="h" gradientUnits="userSpaceOnUse" x1="272.9214" y1="39.144" x2="51.6446" y2="289.4984">
+ <stop offset="0" stop-color="#F79F1C"/>
+ <stop offset="0.4455" stop-color="#F08021"/>
+ <stop offset="1" stop-color="#ED693C"/>
+ </linearGradient>
+ <path fill="url(#h)" stroke="#F16622" stroke-miterlimit="10" d="M40.422,234.676c3.979,21.982,41.057,60.12,63.188,63.188
+ c9.687,1.346,59.279-122.468,59.279-122.468S38.574,224.487,40.422,234.676z"/>
+ <linearGradient id="i" gradientUnits="userSpaceOnUse" x1="329.0083" y1="88.7129" x2="107.7311" y2="339.0677">
+ <stop offset="0" stop-color="#E47C26"/>
+ <stop offset="0.4455" stop-color="#DF5B27"/>
+ <stop offset="1" stop-color="#DD3A3A"/>
+ </linearGradient>
+ <path fill="url(#i)" stroke="#E03827" stroke-miterlimit="10" d="M125.787,307.051c18.357,12.73,71.543,13.48,89.362,0
+ c7.801-5.898-44.681-128.515-44.681-128.515S117.275,301.153,125.787,307.051z"/>
+ <linearGradient id="j" gradientUnits="userSpaceOnUse" x1="339.1245" y1="97.6562" x2="117.8478" y2="348.0104">
+ <stop offset="0" stop-color="#F3783C"/>
+ <stop offset="0.4455" stop-color="#EF5339"/>
+ <stop offset="1" stop-color="#ED294A"/>
+ </linearGradient>
+ <path fill="url(#j)" stroke="#ED2836" stroke-miterlimit="10" d="M178.047,175.398c0,0,49.09,124.315,59.28,122.467
+ c21.982-3.979,60.121-41.057,63.189-63.188C301.86,224.991,178.047,175.398,178.047,175.398z"/>
+ </g>
+ <linearGradient id="k" gradientUnits="userSpaceOnUse" x1="170.5352" y1="6.3281" x2="170.5351" y2="329.4424">
+ <stop offset="0" stop-color="#FFFFFF" stop-opacity="0.2"/>
+ <stop offset="0.4504" stop-color="#908E8E" stop-opacity="0.05"/>
+ <stop offset="1" stop-color="#030003" stop-opacity="0.2"/>
+ </linearGradient>
+ <circle fill="url(#k)" cx="170.536" cy="167.885" r="161.557"/>
+</svg>
diff --git a/dist/citra.xml b/dist/citra.xml
new file mode 100644
index 000000000..bcb9acd87
--- /dev/null
+++ b/dist/citra.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
+ <mime-type type="application/x-ctr-3dsx">
+ <comment>3DS homebrew executable</comment>
+ <comment xml:lang="fr">Exécutable 3DS homebrew</comment>
+ <acronym>3DSX</acronym>
+ <icon name="citra"/>
+ <glob pattern="*.3dsx"/>
+ <magic><match value="3DSX" type="string" offset="0"/></magic>
+ </mime-type>
+
+ <mime-type type="application/x-ctr-cci">
+ <comment>3DS cartridge image</comment>
+ <comment xml:lang="fr">Image de cartouche 3DS</comment>
+ <acronym>CCI</acronym>
+ <expanded-acronym>CTR Cart Image</expanded-acronym>
+ <icon name="citra"/>
+ <glob pattern="*.cci"/>
+ <glob pattern="*.3ds"/>
+ <magic><match value="NCSD" type="string" offset="256"/></magic>
+ </mime-type>
+
+ <mime-type type="application/x-ctr-cxi">
+ <comment>3DS executable</comment>
+ <comment xml:lang="fr">Exécutable 3DS</comment>
+ <acronym>CXI</acronym>
+ <expanded-acronym>CTR eXecutable Image</expanded-acronym>
+ <icon name="citra"/>
+ <glob pattern="*.cxi"/>
+ <magic><match value="NCCH" type="string" offset="256"/></magic>
+ </mime-type>
+
+ <mime-type type="application/x-ctr-cia">
+ <comment>3DS importable archive</comment>
+ <comment xml:lang="fr">Archive importable 3DS</comment>
+ <acronym>CIA</acronym>
+ <expanded-acronym>CTR Importable Archive</expanded-acronym>
+ <icon name="citra"/>
+ <glob pattern="*.cia"/>
+ </mime-type>
+
+ <mime-type type="application/x-ctr-smdh">
+ <comment>3DS icon</comment>
+ <comment xml:lang="fr">Icône 3DS</comment>
+ <acronym>SMDH</acronym>
+ <expanded-acronym>System Menu Data Header</expanded-acronym>
+ <glob pattern="*.smdh"/>
+ <magic><match value="SMDH" type="string" offset="0"/></magic>
+ </mime-type>
+
+ <mime-type type="application/x-ctr-cbmd">
+ <comment>3DS banner</comment>
+ <comment xml:lang="fr">Bannière 3DS</comment>
+ <acronym>CBMD</acronym>
+ <expanded-acronym>CTR Banner Model Data</expanded-acronym>
+ <glob pattern="*.cbmd"/>
+ <magic><match value="CBMD" type="string" offset="0"/></magic>
+ </mime-type>
+</mime-info>
diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp
index 1d7e7f270..ca93d5b91 100644
--- a/src/citra/citra.cpp
+++ b/src/citra/citra.cpp
@@ -20,14 +20,8 @@
/// Application entry point
int main(int argc, char **argv) {
- std::shared_ptr<Log::Logger> logger = Log::InitGlobalLogger();
Log::Filter log_filter(Log::Level::Debug);
Log::SetFilter(&log_filter);
- std::thread logging_thread(Log::TextLoggingLoop, logger);
- SCOPE_EXIT({
- logger->Close();
- logging_thread.join();
- });
if (argc < 2) {
LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified");
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt
index ff780cad4..efccdbec6 100644
--- a/src/citra_qt/CMakeLists.txt
+++ b/src/citra_qt/CMakeLists.txt
@@ -74,3 +74,39 @@ target_link_libraries(citra-qt ${OPENGL_gl_LIBRARY} ${CITRA_QT_LIBS})
target_link_libraries(citra-qt ${PLATFORM_LIBRARIES})
#install(TARGETS citra-qt RUNTIME DESTINATION ${bindir})
+
+if (Qt5_FOUND AND MSVC)
+ set(Qt5_DLL_DIR "${Qt5_DIR}/../../../bin")
+ set(Qt5_PLATFORMS_DIR "${Qt5_DIR}/../../../plugins/platforms/")
+ set(Qt5_DLLS
+ icudt*.dll
+ icuin*.dll
+ icuuc*.dll
+ Qt5Core$<$<CONFIG:Debug>:d>.*
+ Qt5Gui$<$<CONFIG:Debug>:d>.*
+ Qt5OpenGL$<$<CONFIG:Debug>:d>.*
+ Qt5Widgets$<$<CONFIG:Debug>:d>.*
+ )
+ set(DLL_DEST "${CMAKE_BINARY_DIR}/bin/$<CONFIG>/")
+ set(PLATFORMS ${DLL_DEST}platforms/)
+
+ # windows commandline expects the / to be \ so switch them
+ string(REPLACE "/" "\\" Qt5_DLL_DIR ${Qt5_DLL_DIR})
+ string(REPLACE "/" "\\" Qt5_PLATFORMS_DIR ${Qt5_PLATFORMS_DIR})
+ string(REPLACE "/" "\\" DLL_DEST ${DLL_DEST})
+ string(REPLACE "/" "\\" PLATFORMS ${PLATFORMS})
+
+ # /NJH /NJS /NDL /NFL /NC /NS /NP - Silence any output
+ # cmake adds an extra check for command success which doesn't work too well with robocopy
+ # so trick it into thinking the command was successful with the || cmd /c "exit /b 0"
+ add_custom_command(TARGET citra-qt POST_BUILD
+ COMMAND robocopy ${Qt5_DLL_DIR} ${DLL_DEST} ${Qt5_DLLS} /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0"
+ COMMAND if not exist ${PLATFORMS} mkdir ${PLATFORMS} 2> nul
+ COMMAND robocopy ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.* /NJH /NJS /NDL /NFL /NC /NS /NP || cmd /c "exit /b 0"
+ )
+ unset(Qt5_DLLS)
+ unset(Qt5_DLL_DIR)
+ unset(Qt5_PLATFORMS_DIR)
+ unset(DLL_DEST)
+ unset(PLATFORMS)
+endif()
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp
index 3742c2d38..94e204717 100644
--- a/src/citra_qt/debugger/callstack.cpp
+++ b/src/citra_qt/debugger/callstack.cpp
@@ -8,7 +8,7 @@
#include "core/core.h"
#include "core/arm/arm_interface.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
#include "common/symbols.h"
#include "core/arm/disassembler/arm_disasm.h"
diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp
index 780607e82..e99ec1b30 100644
--- a/src/citra_qt/debugger/disassembler.cpp
+++ b/src/citra_qt/debugger/disassembler.cpp
@@ -7,7 +7,7 @@
#include "../bootmanager.h"
#include "../hotkeys.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
#include "core/core.h"
#include "common/break_points.h"
diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp
index 3287b4706..0c1a3f47f 100644
--- a/src/citra_qt/debugger/graphics_framebuffer.cpp
+++ b/src/citra_qt/debugger/graphics_framebuffer.cpp
@@ -10,6 +10,8 @@
#include <QSpinBox>
#include "core/hw/gpu.h"
+#include "core/memory.h"
+
#include "video_core/color.h"
#include "video_core/pica.h"
#include "video_core/utils.h"
diff --git a/src/citra_qt/debugger/ramview.cpp b/src/citra_qt/debugger/ramview.cpp
index 7149a0485..b6ebc7fc4 100644
--- a/src/citra_qt/debugger/ramview.cpp
+++ b/src/citra_qt/debugger/ramview.cpp
@@ -4,8 +4,6 @@
#include "ramview.h"
-#include "core/mem_map.h"
-
GRamView::GRamView(QWidget* parent) : QHexEdit(parent)
{
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index f115c5b6a..24506deab 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -337,7 +337,9 @@ void GMainWindow::closeEvent(QCloseEvent* event)
settings.setValue("firstStart", false);
SaveHotkeys(settings);
- ShutdownGame();
+ // Shutdown session if the emu thread is active...
+ if (emu_thread != nullptr)
+ ShutdownGame();
render_window->close();
@@ -350,14 +352,8 @@ void GMainWindow::closeEvent(QCloseEvent* event)
int main(int argc, char* argv[])
{
- std::shared_ptr<Log::Logger> logger = Log::InitGlobalLogger();
Log::Filter log_filter(Log::Level::Info);
Log::SetFilter(&log_filter);
- std::thread logging_thread(Log::TextLoggingLoop, logger);
- SCOPE_EXIT({
- logger->Close();
- logging_thread.join();
- });
QApplication::setAttribute(Qt::AA_X11InitThreads);
QApplication app(argc, argv);
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 11659c3c5..dbaaac77b 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -9,7 +9,6 @@ set(SRCS
logging/filter.cpp
logging/text_formatter.cpp
logging/backend.cpp
- math_util.cpp
memory_util.cpp
misc.cpp
profiler.cpp
@@ -28,7 +27,6 @@ set(HEADERS
common_funcs.h
common_paths.h
common_types.h
- concurrent_ring_buffer.h
cpu_detect.h
debug_interface.h
emu_window.h
diff --git a/src/common/assert.h b/src/common/assert.h
index 4f26c63e9..7b7d8bf28 100644
--- a/src/common/assert.h
+++ b/src/common/assert.h
@@ -8,6 +8,7 @@
#include <cstdlib>
#include "common/common_funcs.h"
+#include "common/logging/log.h"
// For asserts we'd like to keep all the junk executed when an assert happens away from the
// important code in the function. One way of doing this is to put all the relevant code inside a
@@ -28,19 +29,14 @@ static void assert_noinline_call(const Fn& fn) {
exit(1); // Keeps GCC's mouth shut about this actually returning
}
-// TODO (yuriks) allow synchronous logging so we don't need printf
#define ASSERT(_a_) \
do if (!(_a_)) { assert_noinline_call([] { \
- fprintf(stderr, "Assertion Failed!\n\n Line: %d\n File: %s\n Time: %s\n", \
- __LINE__, __FILE__, __TIME__); \
+ LOG_CRITICAL(Debug, "Assertion Failed!"); \
}); } while (0)
#define ASSERT_MSG(_a_, ...) \
do if (!(_a_)) { assert_noinline_call([&] { \
- fprintf(stderr, "Assertion Failed!\n\n Line: %d\n File: %s\n Time: %s\n", \
- __LINE__, __FILE__, __TIME__); \
- fprintf(stderr, __VA_ARGS__); \
- fprintf(stderr, "\n"); \
+ LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); \
}); } while (0)
#define UNREACHABLE() ASSERT_MSG(false, "Unreachable code!")
diff --git a/src/common/common_types.h b/src/common/common_types.h
index 644709ba6..f6de0adfc 100644
--- a/src/common/common_types.h
+++ b/src/common/common_types.h
@@ -87,29 +87,3 @@ protected:
NonCopyable(NonCopyable&) = delete;
NonCopyable& operator=(NonCopyable&) = delete;
};
-
-namespace Common {
-/// Rectangle data structure
-class Rect {
-public:
- Rect(int x0=0, int y0=0, int x1=0, int y1=0) {
- x0_ = x0;
- y0_ = y0;
- x1_ = x1;
- y1_ = y1;
- }
- ~Rect() { }
-
- int x0_; ///< Rect top left X-coordinate
- int y0_; ///< Rect top left Y-coordinate
- int x1_; ///< Rect bottom left X-coordinate
- int y1_; ///< Rect bottom right Y-coordinate
-
- inline u32 width() const { return std::abs(x1_ - x0_); }
- inline u32 height() const { return std::abs(y1_ - y0_); }
-
- inline bool operator == (const Rect& val) const {
- return (x0_ == val.x0_ && y0_ == val.y0_ && x1_ == val.x1_ && y1_ == val.y1_);
- }
-};
-}
diff --git a/src/common/concurrent_ring_buffer.h b/src/common/concurrent_ring_buffer.h
deleted file mode 100644
index c5889513a..000000000
--- a/src/common/concurrent_ring_buffer.h
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <array>
-#include <condition_variable>
-#include <cstdint>
-#include <mutex>
-#include <thread>
-
-#include "common/common_types.h" // for NonCopyable
-
-namespace Common {
-
-/**
- * A MPMC (Multiple-Producer Multiple-Consumer) concurrent ring buffer. This data structure permits
- * multiple threads to push and pop from a queue of bounded size.
- */
-template <typename T, size_t ArraySize>
-class ConcurrentRingBuffer : private NonCopyable {
-public:
- /// Value returned by the popping functions when the queue has been closed.
- static const size_t QUEUE_CLOSED = -1;
-
- ConcurrentRingBuffer() {}
-
- ~ConcurrentRingBuffer() {
- // If for whatever reason the queue wasn't completely drained, destroy the left over items.
- for (size_t i = reader_index, end = writer_index; i != end; i = (i + 1) % ArraySize) {
- Data()[i].~T();
- }
- }
-
- /**
- * Pushes a value to the queue. If the queue is full, this method will block. Does nothing if
- * the queue is closed.
- */
- void Push(T val) {
- std::unique_lock<std::mutex> lock(mutex);
- if (closed) {
- return;
- }
-
- // If the buffer is full, wait
- writer.wait(lock, [&]{
- return (writer_index + 1) % ArraySize != reader_index;
- });
-
- T* item = &Data()[writer_index];
- new (item) T(std::move(val));
-
- writer_index = (writer_index + 1) % ArraySize;
-
- // Wake up waiting readers
- lock.unlock();
- reader.notify_one();
- }
-
- /**
- * Pops up to `dest_len` items from the queue, storing them in `dest`. This function will not
- * block, and might return 0 values if there are no elements in the queue when it is called.
- *
- * @return The number of elements stored in `dest`. If the queue has been closed, returns
- * `QUEUE_CLOSED`.
- */
- size_t Pop(T* dest, size_t dest_len) {
- std::unique_lock<std::mutex> lock(mutex);
- if (closed && !CanRead()) {
- return QUEUE_CLOSED;
- }
- return PopInternal(dest, dest_len);
- }
-
- /**
- * Pops up to `dest_len` items from the queue, storing them in `dest`. This function will block
- * if there are no elements in the queue when it is called.
- *
- * @return The number of elements stored in `dest`. If the queue has been closed, returns
- * `QUEUE_CLOSED`.
- */
- size_t BlockingPop(T* dest, size_t dest_len) {
- std::unique_lock<std::mutex> lock(mutex);
- if (closed && !CanRead()) {
- return QUEUE_CLOSED;
- }
-
- while (!CanRead()) {
- reader.wait(lock);
- if (closed && !CanRead()) {
- return QUEUE_CLOSED;
- }
- }
- DEBUG_ASSERT(CanRead());
- return PopInternal(dest, dest_len);
- }
-
- /**
- * Closes the queue. After calling this method, `Push` operations won't have any effect, and
- * `PopMany` and `PopManyBlock` will start returning `QUEUE_CLOSED`. This is intended to allow
- * a graceful shutdown of all consumers.
- */
- void Close() {
- std::unique_lock<std::mutex> lock(mutex);
- closed = true;
- // We need to wake up any reader that are waiting for an item that will never come.
- lock.unlock();
- reader.notify_all();
- }
-
- /// Returns true if `Close()` has been called.
- bool IsClosed() const {
- return closed;
- }
-
-private:
- size_t PopInternal(T* dest, size_t dest_len) {
- size_t output_count = 0;
- while (output_count < dest_len && CanRead()) {
- DEBUG_ASSERT(CanRead());
-
- T* item = &Data()[reader_index];
- T out_val = std::move(*item);
- item->~T();
-
- size_t prev_index = (reader_index + ArraySize - 1) % ArraySize;
- reader_index = (reader_index + 1) % ArraySize;
- if (writer_index == prev_index) {
- writer.notify_one();
- }
- dest[output_count++] = std::move(out_val);
- }
- return output_count;
- }
-
- bool CanRead() const {
- return reader_index != writer_index;
- }
-
- T* Data() {
- return static_cast<T*>(static_cast<void*>(&storage));
- }
-
- /// Storage for entries
- typename std::aligned_storage<ArraySize * sizeof(T),
- std::alignment_of<T>::value>::type storage;
-
- /// Data is valid in the half-open interval [reader, writer). If they are `QUEUE_CLOSED` then the
- /// queue has been closed.
- size_t writer_index = 0, reader_index = 0;
- // True if the queue has been closed.
- bool closed = false;
-
- /// Mutex that protects the entire data structure.
- std::mutex mutex;
- /// Signaling wakes up reader which is waiting for storage to be non-empty.
- std::condition_variable reader;
- /// Signaling wakes up writer which is waiting for storage to be non-full.
- std::condition_variable writer;
-};
-
-} // namespace
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 7d3534a43..bd2c6a153 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -3,17 +3,17 @@
// Refer to the license.txt file included.
#include <algorithm>
+#include <array>
+#include <cstdio>
-#include "common/assert.h"
-
+#include "common/common_funcs.h" // snprintf compatibility define
#include "common/logging/backend.h"
+#include "common/logging/filter.h"
#include "common/logging/log.h"
#include "common/logging/text_formatter.h"
namespace Log {
-static std::shared_ptr<Logger> global_logger;
-
/// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this.
#define ALL_LOG_CLASSES() \
CLS(Log) \
@@ -55,28 +55,8 @@ static std::shared_ptr<Logger> global_logger;
SUB(Render, OpenGL) \
CLS(Loader)
-Logger::Logger() {
- // Register logging classes so that they can be queried at runtime
- size_t parent_class;
- all_classes.reserve((size_t)Class::Count);
-
-#define CLS(x) \
- all_classes.push_back(Class::x); \
- parent_class = all_classes.size() - 1;
-#define SUB(x, y) \
- all_classes.push_back(Class::x##_##y); \
- all_classes[parent_class].num_children += 1;
-
- ALL_LOG_CLASSES()
-#undef CLS
-#undef SUB
-
- // Ensures that ALL_LOG_CLASSES isn't missing any entries.
- DEBUG_ASSERT(all_classes.size() == (size_t)Class::Count);
-}
-
// GetClassName is a macro defined by Windows.h, grrr...
-const char* Logger::GetLogClassName(Class log_class) {
+const char* GetLogClassName(Class log_class) {
switch (log_class) {
#define CLS(x) case Class::x: return #x;
#define SUB(x, y) case Class::x##_##y: return #x "." #y;
@@ -87,7 +67,7 @@ const char* Logger::GetLogClassName(Class log_class) {
return "Unknown";
}
-const char* Logger::GetLevelName(Level log_level) {
+const char* GetLevelName(Level log_level) {
#define LVL(x) case Level::x: return #x
switch (log_level) {
LVL(Trace);
@@ -101,19 +81,6 @@ const char* Logger::GetLevelName(Level log_level) {
#undef LVL
}
-void Logger::LogMessage(Entry entry) {
- ring_buffer.Push(std::move(entry));
-}
-
-size_t Logger::GetEntries(Entry* out_buffer, size_t buffer_len) {
- return ring_buffer.BlockingPop(out_buffer, buffer_len);
-}
-
-std::shared_ptr<Logger> InitGlobalLogger() {
- global_logger = std::make_shared<Logger>();
- return global_logger;
-}
-
Entry CreateEntry(Class log_class, Level log_level,
const char* filename, unsigned int line_nr, const char* function,
const char* format, va_list args) {
@@ -138,7 +105,7 @@ Entry CreateEntry(Class log_class, Level log_level,
return std::move(entry);
}
-static Filter* filter;
+static Filter* filter = nullptr;
void SetFilter(Filter* new_filter) {
filter = new_filter;
@@ -147,7 +114,7 @@ void SetFilter(Filter* new_filter) {
void LogMessage(Class log_class, Level log_level,
const char* filename, unsigned int line_nr, const char* function,
const char* format, ...) {
- if (!filter->CheckMessage(log_class, log_level))
+ if (filter != nullptr && !filter->CheckMessage(log_class, log_level))
return;
va_list args;
@@ -156,12 +123,7 @@ void LogMessage(Class log_class, Level log_level,
filename, line_nr, function, format, args);
va_end(args);
- if (global_logger != nullptr && !global_logger->IsClosed()) {
- global_logger->LogMessage(std::move(entry));
- } else {
- // Fall back to directly printing to stderr
- PrintMessage(entry);
- }
+ PrintColoredMessage(entry);
}
}
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h
index 3114f864c..c1f4d08e4 100644
--- a/src/common/logging/backend.h
+++ b/src/common/logging/backend.h
@@ -4,17 +4,17 @@
#pragma once
+#include <chrono>
#include <cstdarg>
-#include <memory>
-#include <vector>
+#include <string>
+#include <utility>
-#include "common/concurrent_ring_buffer.h"
-
-#include "common/logging/filter.h"
#include "common/logging/log.h"
namespace Log {
+class Filter;
+
/**
* A log entry. Log entries are store in a structured format to permit more varied output
* formatting on different frontends, as well as facilitating filtering and aggregation.
@@ -48,89 +48,21 @@ struct Entry {
}
};
-struct ClassInfo {
- Class log_class;
-
- /**
- * Total number of (direct or indirect) sub classes this class has. If any, they follow in
- * sequence after this class in the class list.
- */
- unsigned int num_children = 0;
-
- ClassInfo(Class log_class) : log_class(log_class) {}
-};
-
/**
- * Logging management class. This class has the dual purpose of acting as an exchange point between
- * the logging clients and the log outputter, as well as containing reflection info about available
- * log classes.
+ * Returns the name of the passed log class as a C-string. Subclasses are separated by periods
+ * instead of underscores as in the enumeration.
*/
-class Logger {
-private:
- using Buffer = Common::ConcurrentRingBuffer<Entry, 16 * 1024 / sizeof(Entry)>;
-
-public:
- static const size_t QUEUE_CLOSED = Buffer::QUEUE_CLOSED;
-
- Logger();
-
- /**
- * Returns a list of all vector classes and subclasses. The sequence returned is a pre-order of
- * classes and subclasses, which together with the `num_children` field in ClassInfo, allows
- * you to recover the hierarchy.
- */
- const std::vector<ClassInfo>& GetClasses() const { return all_classes; }
+const char* GetLogClassName(Class log_class);
- /**
- * Returns the name of the passed log class as a C-string. Subclasses are separated by periods
- * instead of underscores as in the enumeration.
- */
- static const char* GetLogClassName(Class log_class);
-
- /**
- * Returns the name of the passed log level as a C-string.
- */
- static const char* GetLevelName(Level log_level);
-
- /**
- * Appends a messages to the log buffer.
- * @note This function is thread safe.
- */
- void LogMessage(Entry entry);
-
- /**
- * Retrieves a batch of messages from the log buffer, blocking until they are available.
- * @note This function is thread safe.
- *
- * @param out_buffer Destination buffer that will receive the log entries.
- * @param buffer_len The maximum size of `out_buffer`.
- * @return The number of entries stored. In case the logger is shutting down, `QUEUE_CLOSED` is
- * returned, no entries are stored and the logger should shutdown.
- */
- size_t GetEntries(Entry* out_buffer, size_t buffer_len);
-
- /**
- * Initiates a shutdown of the logger. This will indicate to log output clients that they
- * should shutdown.
- */
- void Close() { ring_buffer.Close(); }
-
- /**
- * Returns true if Close() has already been called on the Logger.
- */
- bool IsClosed() const { return ring_buffer.IsClosed(); }
-
-private:
- Buffer ring_buffer;
- std::vector<ClassInfo> all_classes;
-};
+/**
+ * Returns the name of the passed log level as a C-string.
+ */
+const char* GetLevelName(Level log_level);
/// Creates a log entry by formatting the given source location, and message.
Entry CreateEntry(Class log_class, Level log_level,
const char* filename, unsigned int line_nr, const char* function,
const char* format, va_list args);
-/// Initializes the default Logger.
-std::shared_ptr<Logger> InitGlobalLogger();
void SetFilter(Filter* filter);
diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp
index 50f2e13f4..55cc8888a 100644
--- a/src/common/logging/filter.cpp
+++ b/src/common/logging/filter.cpp
@@ -22,16 +22,6 @@ void Filter::SetClassLevel(Class log_class, Level level) {
class_levels[static_cast<size_t>(log_class)] = level;
}
-void Filter::SetSubclassesLevel(const ClassInfo& log_class, Level level) {
- const size_t log_class_i = static_cast<size_t>(log_class.log_class);
-
- const size_t begin = log_class_i + 1;
- const size_t end = begin + log_class.num_children;
- for (size_t i = begin; begin < end; ++i) {
- class_levels[i] = level;
- }
-}
-
void Filter::ParseFilterString(const std::string& filter_str) {
auto clause_begin = filter_str.cbegin();
while (clause_begin != filter_str.cend()) {
@@ -53,7 +43,7 @@ void Filter::ParseFilterString(const std::string& filter_str) {
template <typename It>
static Level GetLevelByName(const It begin, const It end) {
for (u8 i = 0; i < static_cast<u8>(Level::Count); ++i) {
- const char* level_name = Logger::GetLevelName(static_cast<Level>(i));
+ const char* level_name = GetLevelName(static_cast<Level>(i));
if (Common::ComparePartialString(begin, end, level_name)) {
return static_cast<Level>(i);
}
@@ -64,7 +54,7 @@ static Level GetLevelByName(const It begin, const It end) {
template <typename It>
static Class GetClassByName(const It begin, const It end) {
for (ClassType i = 0; i < static_cast<ClassType>(Class::Count); ++i) {
- const char* level_name = Logger::GetLogClassName(static_cast<Class>(i));
+ const char* level_name = GetLogClassName(static_cast<Class>(i));
if (Common::ComparePartialString(begin, end, level_name)) {
return static_cast<Class>(i);
}
@@ -72,20 +62,6 @@ static Class GetClassByName(const It begin, const It end) {
return Class::Count;
}
-template <typename InputIt, typename T>
-static InputIt find_last(InputIt begin, const InputIt end, const T& value) {
- auto match = end;
- while (begin != end) {
- auto new_match = std::find(begin, end, value);
- if (new_match != end) {
- match = new_match;
- ++new_match;
- }
- begin = new_match;
- }
- return match;
-}
-
bool Filter::ParseFilterRule(const std::string::const_iterator begin,
const std::string::const_iterator end) {
auto level_separator = std::find(begin, end, ':');
@@ -106,22 +82,13 @@ bool Filter::ParseFilterRule(const std::string::const_iterator begin,
return true;
}
- auto class_name_end = find_last(begin, level_separator, '.');
- if (class_name_end != level_separator &&
- !Common::ComparePartialString(class_name_end + 1, level_separator, "*")) {
- class_name_end = level_separator;
- }
-
- const Class log_class = GetClassByName(begin, class_name_end);
+ const Class log_class = GetClassByName(begin, level_separator);
if (log_class == Class::Count) {
LOG_ERROR(Log, "Unknown log class in filter: %s", std::string(begin, end).c_str());
return false;
}
- if (class_name_end == level_separator) {
- SetClassLevel(log_class, level);
- }
- SetSubclassesLevel(log_class, level);
+ SetClassLevel(log_class, level);
return true;
}
diff --git a/src/common/logging/filter.h b/src/common/logging/filter.h
index b53e4e633..0b71ea3b2 100644
--- a/src/common/logging/filter.h
+++ b/src/common/logging/filter.h
@@ -11,8 +11,6 @@
namespace Log {
-struct ClassInfo;
-
/**
* Implements a log message filter which allows different log classes to have different minimum
* severity levels. The filter can be changed at runtime and can be parsed from a string to allow
@@ -27,29 +25,19 @@ public:
void ResetAll(Level level);
/// Sets the minimum level of `log_class` (and not of its subclasses) to `level`.
void SetClassLevel(Class log_class, Level level);
- /**
- * Sets the minimum level of all of `log_class` subclasses to `level`. The level of `log_class`
- * itself is not changed.
- */
- void SetSubclassesLevel(const ClassInfo& log_class, Level level);
/**
* Parses a filter string and applies it to this filter.
*
* A filter string consists of a space-separated list of filter rules, each of the format
* `<class>:<level>`. `<class>` is a log class name, with subclasses separated using periods.
- * A rule for a given class also affects all of its subclasses. `*` wildcards are allowed and
- * can be used to apply a rule to all classes or to all subclasses of a class without affecting
- * the parent class. `<level>` a severity level name which will be set as the minimum logging
- * level of the matched classes. Rules are applied left to right, with each rule overriding
- * previous ones in the sequence.
+ * `*` is allowed as a class name and will reset all filters to the specified level. `<level>`
+ * a severity level name which will be set as the minimum logging level of the matched classes.
+ * Rules are applied left to right, with each rule overriding previous ones in the sequence.
*
* A few examples of filter rules:
* - `*:Info` -- Resets the level of all classes to Info.
- * - `Service:Info` -- Sets the level of Service and all subclasses (Service.FS, Service.APT,
- * etc.) to Info.
- * - `Service.*:Debug` -- Sets the level of all Service subclasses to Debug, while leaving the
- * level of Service unchanged.
+ * - `Service:Info` -- Sets the level of Service to Info.
* - `Service.FS:Trace` -- Sets the level of the Service.FS class to Trace.
*/
void ParseFilterString(const std::string& filter_str);
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index 123641cb4..fd87ddbe6 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -78,11 +78,7 @@ enum class Class : ClassType {
Count ///< Total number of logging classes
};
-/**
- * Logs a message to the global logger. This proxy exists to avoid exposing the details of the
- * Logger class, including the ConcurrentRingBuffer template, to all files that desire to log
- * messages, reducing unecessary recompilations.
- */
+/// Logs a message to the global logger.
void LogMessage(Class log_class, Level log_level,
const char* filename, unsigned int line_nr, const char* function,
#ifdef _MSC_VER
diff --git a/src/common/logging/text_formatter.cpp b/src/common/logging/text_formatter.cpp
index 45be6d0a1..94f3dfc1f 100644
--- a/src/common/logging/text_formatter.cpp
+++ b/src/common/logging/text_formatter.cpp
@@ -46,8 +46,8 @@ void FormatLogMessage(const Entry& entry, char* out_text, size_t text_len) {
unsigned int time_seconds = static_cast<unsigned int>(entry.timestamp.count() / 1000000);
unsigned int time_fractional = static_cast<unsigned int>(entry.timestamp.count() % 1000000);
- const char* class_name = Logger::GetLogClassName(entry.log_class);
- const char* level_name = Logger::GetLevelName(entry.log_level);
+ const char* class_name = GetLogClassName(entry.log_class);
+ const char* level_name = GetLevelName(entry.log_level);
snprintf(out_text, text_len, "[%4u.%06u] %s <%s> %s: %s",
time_seconds, time_fractional, class_name, level_name,
@@ -116,19 +116,4 @@ void PrintColoredMessage(const Entry& entry) {
#endif
}
-void TextLoggingLoop(std::shared_ptr<Logger> logger) {
- std::array<Entry, 256> entry_buffer;
-
- while (true) {
- size_t num_entries = logger->GetEntries(entry_buffer.data(), entry_buffer.size());
- if (num_entries == Logger::QUEUE_CLOSED) {
- break;
- }
- for (size_t i = 0; i < num_entries; ++i) {
- const Entry& entry = entry_buffer[i];
- PrintColoredMessage(entry);
- }
- }
-}
-
}
diff --git a/src/common/logging/text_formatter.h b/src/common/logging/text_formatter.h
index 8474a1904..5b82f043f 100644
--- a/src/common/logging/text_formatter.h
+++ b/src/common/logging/text_formatter.h
@@ -5,11 +5,9 @@
#pragma once
#include <cstddef>
-#include <memory>
namespace Log {
-class Logger;
struct Entry;
/**
@@ -31,10 +29,4 @@ void PrintMessage(const Entry& entry);
/// Prints the same message as `PrintMessage`, but colored acoording to the severity level.
void PrintColoredMessage(const Entry& entry);
-/**
- * Logging loop that repeatedly reads messages from the provided logger and prints them to the
- * console. It is the baseline barebones log outputter.
- */
-void TextLoggingLoop(std::shared_ptr<Logger> logger);
-
}
diff --git a/src/common/math_util.cpp b/src/common/math_util.cpp
deleted file mode 100644
index bcb70cae5..000000000
--- a/src/common/math_util.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <cstring>
-#include <numeric> // Necessary on OS X, but not Linux
-
-#include "common/common_types.h"
-#include "common/math_util.h"
-
-namespace MathUtil
-{
-
-u32 ClassifyDouble(double dvalue)
-{
- // TODO: Optimize the below to be as fast as possible.
- IntDouble value;
- value.d = dvalue;
- u64 sign = value.i & DOUBLE_SIGN;
- u64 exp = value.i & DOUBLE_EXP;
- if (exp > DOUBLE_ZERO && exp < DOUBLE_EXP)
- {
- // Nice normalized number.
- return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
- }
- else
- {
- u64 mantissa = value.i & DOUBLE_FRAC;
- if (mantissa)
- {
- if (exp)
- {
- return PPC_FPCLASS_QNAN;
- }
- else
- {
- // Denormalized number.
- return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
- }
- }
- else if (exp)
- {
- //Infinite
- return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
- }
- else
- {
- //Zero
- return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
- }
- }
-}
-
-u32 ClassifyFloat(float fvalue)
-{
- // TODO: Optimize the below to be as fast as possible.
- IntFloat value;
- value.f = fvalue;
- u32 sign = value.i & FLOAT_SIGN;
- u32 exp = value.i & FLOAT_EXP;
- if (exp > FLOAT_ZERO && exp < FLOAT_EXP)
- {
- // Nice normalized number.
- return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
- }
- else
- {
- u32 mantissa = value.i & FLOAT_FRAC;
- if (mantissa)
- {
- if (exp)
- {
- return PPC_FPCLASS_QNAN; // Quiet NAN
- }
- else
- {
- // Denormalized number.
- return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
- }
- }
- else if (exp)
- {
- // Infinite
- return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
- }
- else
- {
- //Zero
- return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
- }
- }
-}
-
-
-} // namespace
-
-inline void MatrixMul(int n, const float *a, const float *b, float *result)
-{
- for (int i = 0; i < n; ++i)
- {
- for (int j = 0; j < n; ++j)
- {
- float temp = 0;
- for (int k = 0; k < n; ++k)
- {
- temp += a[i * n + k] * b[k * n + j];
- }
- result[i * n + j] = temp;
- }
- }
-}
-
-// Calculate sum of a float list
-float MathFloatVectorSum(const std::vector<float>& Vec)
-{
- return std::accumulate(Vec.begin(), Vec.end(), 0.0f);
-}
-
-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;
-}
-
-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;
-}
-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;
-}
-
-void Matrix33::Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result)
-{
- 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];
- }
- }
-}
-
-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;
-}
-
-void Matrix44::LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33)
-{
- for (int i = 0; i < 3; ++i)
- {
- for (int j = 0; j < 3; ++j)
- {
- mtx.data[i * 4 + j] = m33.data[i * 3 + j];
- }
- }
-
- for (int i = 0; i < 3; ++i)
- {
- 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];
- }
-}
-
-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];
-}
-
-void Matrix44::Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result)
-{
- MatrixMul(4, a.data, b.data, result.data);
-}
-
diff --git a/src/common/math_util.h b/src/common/math_util.h
index 52f579cf7..0b1400b41 100644
--- a/src/common/math_util.h
+++ b/src/common/math_util.h
@@ -4,11 +4,9 @@
#pragma once
-#include "common/common_types.h"
-
#include <algorithm>
+#include <cstdlib>
#include <type_traits>
-#include <vector>
namespace MathUtil
{
@@ -19,83 +17,6 @@ inline T Clamp(const T val, const T& min, const T& max)
return std::max(min, std::min(max, val));
}
-static const u64 DOUBLE_SIGN = 0x8000000000000000ULL,
- DOUBLE_EXP = 0x7FF0000000000000ULL,
- DOUBLE_FRAC = 0x000FFFFFFFFFFFFFULL,
- DOUBLE_ZERO = 0x0000000000000000ULL;
-
-static const u32 FLOAT_SIGN = 0x80000000,
- FLOAT_EXP = 0x7F800000,
- FLOAT_FRAC = 0x007FFFFF,
- FLOAT_ZERO = 0x00000000;
-
-union IntDouble {
- double d;
- u64 i;
-};
-union IntFloat {
- float f;
- u32 i;
-};
-
-inline bool IsNAN(double d)
-{
- IntDouble x; x.d = d;
- return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
- ((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) );
-}
-
-inline bool IsQNAN(double d)
-{
- IntDouble x; x.d = d;
- return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
- ((x.i & 0x0007fffffffffffULL) == 0x000000000000000ULL) &&
- ((x.i & 0x000800000000000ULL) == 0x000800000000000ULL) );
-}
-
-inline bool IsSNAN(double d)
-{
- IntDouble x; x.d = d;
- return( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
- ((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) &&
- ((x.i & 0x0008000000000000ULL) == DOUBLE_ZERO) );
-}
-
-inline float FlushToZero(float f)
-{
- IntFloat x; x.f = f;
- if ((x.i & FLOAT_EXP) == 0)
- x.i &= FLOAT_SIGN; // turn into signed zero
- return x.f;
-}
-
-inline double FlushToZeroAsFloat(double d)
-{
- IntDouble x; x.d = d;
- if ((x.i & DOUBLE_EXP) < 0x3800000000000000ULL)
- x.i &= DOUBLE_SIGN; // turn into signed zero
- return x.d;
-}
-
-enum PPCFpClass
-{
- PPC_FPCLASS_QNAN = 0x11,
- PPC_FPCLASS_NINF = 0x9,
- PPC_FPCLASS_NN = 0x8,
- PPC_FPCLASS_ND = 0x18,
- PPC_FPCLASS_NZ = 0x12,
- PPC_FPCLASS_PZ = 0x2,
- PPC_FPCLASS_PD = 0x14,
- PPC_FPCLASS_PN = 0x4,
- PPC_FPCLASS_PINF = 0x5,
-};
-
-// Uses PowerPC conventions for the return value, so it can be easily
-// used directly in CPU emulation.
-u32 ClassifyDouble(double dvalue);
-// More efficient float version.
-u32 ClassifyFloat(float fvalue);
-
template<class T>
struct Rectangle
{
@@ -104,101 +25,12 @@ struct Rectangle
T right;
T bottom;
- Rectangle()
- { }
+ 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; }
+ Rectangle(T left, T top, T right, T bottom) : left(left), top(top), right(right), bottom(bottom) {}
T GetWidth() const { return std::abs(static_cast<typename std::make_signed<T>::type>(right - left)); }
T GetHeight() const { return std::abs(static_cast<typename std::make_signed<T>::type>(bottom - top)); }
-
- // If the rectangle is in a coordinate system with a lower-left origin, use
- // this Clamp.
- void ClampLL(T x1, T y1, T x2, T y2)
- {
- if (left < x1) left = x1;
- if (right > x2) right = x2;
- if (top > y1) top = y1;
- if (bottom < y2) bottom = y2;
- }
-
- // If the rectangle is in a coordinate system with an upper-left origin,
- // use this Clamp.
- void ClampUL(T x1, T y1, T x2, T y2)
- {
- if (left < x1) left = x1;
- if (right > x2) right = x2;
- if (top < y1) top = y1;
- if (bottom > y2) bottom = y2;
- }
};
} // namespace MathUtil
-
-inline float pow2f(float x) {return x * x;}
-inline double pow2(double x) {return x * x;}
-
-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.
-
-class Matrix33
-{
-public:
- 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 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];
-};
-
-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 Translate(Matrix44 &mtx, const float vec[3]);
-
- static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result);
-
- float data[16];
-};
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index ebedcb710..5caaee474 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -30,6 +30,7 @@ set(SRCS
hle/kernel/kernel.cpp
hle/kernel/mutex.cpp
hle/kernel/process.cpp
+ hle/kernel/resource_limit.cpp
hle/kernel/semaphore.cpp
hle/kernel/session.cpp
hle/kernel/shared_memory.cpp
@@ -99,7 +100,7 @@ set(SRCS
loader/loader.cpp
loader/ncch.cpp
mem_map.cpp
- mem_map_funcs.cpp
+ memory.cpp
settings.cpp
system.cpp
)
@@ -141,6 +142,7 @@ set(HEADERS
hle/kernel/kernel.h
hle/kernel/mutex.h
hle/kernel/process.h
+ hle/kernel/resource_limit.h
hle/kernel/semaphore.h
hle/kernel/session.h
hle/kernel/shared_memory.h
@@ -211,6 +213,8 @@ set(HEADERS
loader/loader.h
loader/ncch.h
mem_map.h
+ memory.h
+ memory_setup.h
settings.h
system.h
)
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp
index 12181d0ec..3887189f1 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp
@@ -181,7 +181,11 @@ const ISEITEM arm_instruction[] = {
{ "ldrt", 3, 0, 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000003 },
{ "mrc", 3, 6, 24, 27, 0x0000000e, 20, 20, 0x00000001, 4, 4, 0x00000001 },
{ "mcr", 3, 0, 24, 27, 0x0000000e, 20, 20, 0x00000000, 4, 4, 0x00000001 },
- { "msr", 2, 0, 23, 27, 0x00000006, 20, 21, 0x00000002 },
+ { "msr", 3, 0, 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000001 },
+ { "msr", 4, 0, 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 16, 19, 0x00000004 },
+ { "msr", 5, 0, 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 19, 19, 0x00000001, 16, 17, 0x00000000 },
+ { "msr", 4, 0, 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 16, 17, 0x00000001 },
+ { "msr", 4, 0, 23, 27, 0x00000006, 20, 21, 0x00000002, 22, 22, 0x00000000, 17, 17, 0x00000001 },
{ "ldrb", 3, 0, 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000001 },
{ "strb", 3, 0, 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000000 },
{ "ldr", 4, 0, 28, 31, 0x0000000e, 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001 },
@@ -190,12 +194,17 @@ const ISEITEM arm_instruction[] = {
{ "cdp", 2, 0, 24, 27, 0x0000000e, 4, 4, 0x00000000 },
{ "stc", 2, 0, 25, 27, 0x00000006, 20, 20, 0x00000000 },
{ "ldc", 2, 0, 25, 27, 0x00000006, 20, 20, 0x00000001 },
- { "swi", 1, 0, 24, 27, 0x0000000f },
- { "bbl", 1, 0, 25, 27, 0x00000005 },
{ "ldrexd", 2, ARMV6K, 20, 27, 0x0000001B, 4, 7, 0x00000009 },
{ "strexd", 2, ARMV6K, 20, 27, 0x0000001A, 4, 7, 0x00000009 },
{ "ldrexh", 2, ARMV6K, 20, 27, 0x0000001F, 4, 7, 0x00000009 },
{ "strexh", 2, ARMV6K, 20, 27, 0x0000001E, 4, 7, 0x00000009 },
+ { "nop", 5, ARMV6K, 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000000 },
+ { "yield", 5, ARMV6K, 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000001 },
+ { "wfe", 5, ARMV6K, 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000002 },
+ { "wfi", 5, ARMV6K, 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000003 },
+ { "sev", 5, ARMV6K, 23, 27, 0x00000006, 22, 22, 0x00000000, 20, 21, 0x00000002, 16, 19, 0x00000000, 0, 7, 0x00000004 },
+ { "swi", 1, 0, 24, 27, 0x0000000f },
+ { "bbl", 1, 0, 25, 27, 0x00000005 },
};
const ISEITEM arm_exclusion_code[] = {
@@ -375,6 +384,10 @@ const ISEITEM arm_exclusion_code[] = {
{ "mrc", 0, 6, 0 },
{ "mcr", 0, 0, 0 },
{ "msr", 0, 0, 0 },
+ { "msr", 0, 0, 0 },
+ { "msr", 0, 0, 0 },
+ { "msr", 0, 0, 0 },
+ { "msr", 0, 0, 0 },
{ "ldrb", 0, 0, 0 },
{ "strb", 0, 0, 0 },
{ "ldr", 0, 0, 0 },
@@ -383,12 +396,17 @@ const ISEITEM arm_exclusion_code[] = {
{ "cdp", 0, 0, 0 },
{ "stc", 0, 0, 0 },
{ "ldc", 0, 0, 0 },
- { "swi", 0, 0, 0 },
- { "bbl", 0, 0, 0 },
{ "ldrexd", 0, ARMV6K, 0 },
{ "strexd", 0, ARMV6K, 0 },
{ "ldrexh", 0, ARMV6K, 0 },
{ "strexh", 0, ARMV6K, 0 },
+ { "nop", 0, ARMV6K, 0 },
+ { "yield", 0, ARMV6K, 0 },
+ { "wfe", 0, ARMV6K, 0 },
+ { "wfi", 0, ARMV6K, 0 },
+ { "sev", 0, ARMV6K, 0 },
+ { "swi", 0, 0, 0 },
+ { "bbl", 0, 0, 0 },
{ "bl_1_thumb", 0, INVALID, 0 }, // Should be table[-4]
{ "bl_2_thumb", 0, INVALID, 0 }, // Should be located at the end of the table[-3]
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 315b4cc91..66282a7e6 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -10,9 +10,10 @@
#include "common/logging/log.h"
#include "common/profiler.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
#include "core/hle/svc.h"
#include "core/arm/disassembler/arm_disasm.h"
+#include "core/arm/dyncom/arm_dyncom_dec.h"
#include "core/arm/dyncom/arm_dyncom_interpreter.h"
#include "core/arm/dyncom/arm_dyncom_thumb.h"
#include "core/arm/dyncom/arm_dyncom_run.h"
@@ -68,6 +69,67 @@ static void remove_exclusive(ARMul_State* state, ARMword addr){
state->exclusive_tag = 0xFFFFFFFF;
}
+static int CondPassed(ARMul_State* cpu, unsigned int cond) {
+ const u32 NFLAG = cpu->NFlag;
+ const u32 ZFLAG = cpu->ZFlag;
+ const u32 CFLAG = cpu->CFlag;
+ const u32 VFLAG = cpu->VFlag;
+
+ int temp = 0;
+
+ switch (cond) {
+ case 0x0:
+ temp = ZFLAG;
+ break;
+ case 0x1: // NE
+ temp = !ZFLAG;
+ break;
+ case 0x2: // CS
+ temp = CFLAG;
+ break;
+ case 0x3: // CC
+ temp = !CFLAG;
+ break;
+ case 0x4: // MI
+ temp = NFLAG;
+ break;
+ case 0x5: // PL
+ temp = !NFLAG;
+ break;
+ case 0x6: // VS
+ temp = VFLAG;
+ break;
+ case 0x7: // VC
+ temp = !VFLAG;
+ break;
+ case 0x8: // HI
+ temp = (CFLAG && !ZFLAG);
+ break;
+ case 0x9: // LS
+ temp = (!CFLAG || ZFLAG);
+ break;
+ case 0xa: // GE
+ temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
+ break;
+ case 0xb: // LT
+ temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
+ break;
+ case 0xc: // GT
+ temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG));
+ break;
+ case 0xd: // LE
+ temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
+ break;
+ case 0xe: // AL
+ temp = 1;
+ break;
+ case 0xf:
+ temp = 1;
+ break;
+ }
+ return temp;
+}
+
static unsigned int DPO(Immediate)(ARMul_State* cpu, unsigned int sht_oper) {
unsigned int immed_8 = BITS(sht_oper, 0, 7);
unsigned int rotate_imm = BITS(sht_oper, 8, 11);
@@ -224,14 +286,12 @@ static unsigned int DPO(RotateRightByRegister)(ARMul_State* cpu, unsigned int sh
typedef void (*get_addr_fp_t)(ARMul_State *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int rw);
-typedef struct _ldst_inst {
+struct ldst_inst {
unsigned int inst;
get_addr_fp_t get_addr;
-} ldst_inst;
+};
#define DEBUG_MSG LOG_DEBUG(Core_ARM11, "inst is %x", inst); CITRA_IGNORE_EXIT(0)
-int CondPassed(ARMul_State* cpu, unsigned int cond);
-
#define LnSWoUB(s) glue(LnSWoUB, s)
#define MLnS(s) glue(MLnS, s)
#define LdnStM(s) glue(LdnStM, s)
@@ -647,255 +707,248 @@ static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst, u
virt_addr = addr;
}
-typedef struct _arm_inst {
+struct arm_inst {
unsigned int idx;
unsigned int cond;
int br;
int load_r15;
char component[0];
-} arm_inst;
+};
-typedef struct generic_arm_inst {
+struct generic_arm_inst {
u32 Ra;
u32 Rm;
u32 Rn;
u32 Rd;
u8 op1;
u8 op2;
-} generic_arm_inst;
+};
-typedef struct _adc_inst {
+struct adc_inst {
unsigned int I;
unsigned int S;
unsigned int Rn;
unsigned int Rd;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} adc_inst;
+};
-typedef struct _add_inst {
+struct add_inst {
unsigned int I;
unsigned int S;
unsigned int Rn;
unsigned int Rd;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} add_inst;
+};
-typedef struct _orr_inst {
+struct orr_inst {
unsigned int I;
unsigned int S;
unsigned int Rn;
unsigned int Rd;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} orr_inst;
+};
-typedef struct _and_inst {
+struct and_inst {
unsigned int I;
unsigned int S;
unsigned int Rn;
unsigned int Rd;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} and_inst;
+};
-typedef struct _eor_inst {
+struct eor_inst {
unsigned int I;
unsigned int S;
unsigned int Rn;
unsigned int Rd;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} eor_inst;
+};
-typedef struct _bbl_inst {
+struct bbl_inst {
unsigned int L;
int signed_immed_24;
unsigned int next_addr;
unsigned int jmp_addr;
-} bbl_inst;
+};
-typedef struct _bx_inst {
+struct bx_inst {
unsigned int Rm;
-} bx_inst;
+};
-typedef struct _blx_inst {
+struct blx_inst {
union {
int32_t signed_immed_24;
uint32_t Rm;
} val;
unsigned int inst;
-} blx_inst;
+};
-typedef struct _clz_inst {
+struct clz_inst {
unsigned int Rm;
unsigned int Rd;
-} clz_inst;
+};
-typedef struct _cps_inst {
+struct cps_inst {
unsigned int imod0;
unsigned int imod1;
unsigned int mmod;
unsigned int A, I, F;
unsigned int mode;
-} cps_inst;
+};
-typedef struct _clrex_inst {
-} clrex_inst;
+struct clrex_inst {
+};
-typedef struct _cpy_inst {
+struct cpy_inst {
unsigned int Rm;
unsigned int Rd;
-} cpy_inst;
+};
-typedef struct _bic_inst {
+struct bic_inst {
unsigned int I;
unsigned int S;
unsigned int Rn;
unsigned int Rd;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} bic_inst;
+};
-typedef struct _sub_inst {
+struct sub_inst {
unsigned int I;
unsigned int S;
unsigned int Rn;
unsigned int Rd;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} sub_inst;
+};
-typedef struct _tst_inst {
+struct tst_inst {
unsigned int I;
unsigned int S;
unsigned int Rn;
unsigned int Rd;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} tst_inst;
+};
-typedef struct _cmn_inst {
+struct cmn_inst {
unsigned int I;
unsigned int Rn;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} cmn_inst;
+};
-typedef struct _teq_inst {
+struct teq_inst {
unsigned int I;
unsigned int Rn;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} teq_inst;
+};
-typedef struct _stm_inst {
+struct stm_inst {
unsigned int inst;
-} stm_inst;
+};
struct bkpt_inst {
u32 imm;
};
-struct blx1_inst {
- unsigned int addr;
+struct stc_inst {
};
-struct blx2_inst {
- unsigned int Rm;
+struct ldc_inst {
};
-typedef struct _stc_inst {
-} stc_inst;
-
-typedef struct _ldc_inst {
-} ldc_inst;
-
-typedef struct _swi_inst {
+struct swi_inst {
unsigned int num;
-} swi_inst;
+};
-typedef struct _cmp_inst {
+struct cmp_inst {
unsigned int I;
unsigned int Rn;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} cmp_inst;
+};
-typedef struct _mov_inst {
+struct mov_inst {
unsigned int I;
unsigned int S;
unsigned int Rd;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} mov_inst;
+};
-typedef struct _mvn_inst {
+struct mvn_inst {
unsigned int I;
unsigned int S;
unsigned int Rd;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} mvn_inst;
+};
-typedef struct _rev_inst {
+struct rev_inst {
unsigned int Rd;
unsigned int Rm;
unsigned int op1;
unsigned int op2;
-} rev_inst;
+};
-typedef struct _rsb_inst {
+struct rsb_inst {
unsigned int I;
unsigned int S;
unsigned int Rn;
unsigned int Rd;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} rsb_inst;
+};
-typedef struct _rsc_inst {
+struct rsc_inst {
unsigned int I;
unsigned int S;
unsigned int Rn;
unsigned int Rd;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} rsc_inst;
+};
-typedef struct _sbc_inst {
+struct sbc_inst {
unsigned int I;
unsigned int S;
unsigned int Rn;
unsigned int Rd;
unsigned int shifter_operand;
shtop_fp_t shtop_func;
-} sbc_inst;
+};
-typedef struct _mul_inst {
+struct mul_inst {
unsigned int S;
unsigned int Rd;
unsigned int Rs;
unsigned int Rm;
-} mul_inst;
+};
-typedef struct _smul_inst {
+struct smul_inst {
unsigned int Rd;
unsigned int Rs;
unsigned int Rm;
unsigned int x;
unsigned int y;
-} smul_inst;
+};
-typedef struct _umull_inst {
+struct umull_inst {
unsigned int S;
unsigned int RdHi;
unsigned int RdLo;
unsigned int Rs;
unsigned int Rm;
-} umull_inst;
-typedef struct _smlad_inst {
+};
+
+struct smlad_inst {
unsigned int m;
unsigned int Rm;
unsigned int Rd;
@@ -903,58 +956,58 @@ typedef struct _smlad_inst {
unsigned int Rn;
unsigned int op1;
unsigned int op2;
-} smlad_inst;
+};
-typedef struct _smla_inst {
+struct smla_inst {
unsigned int x;
unsigned int y;
unsigned int Rm;
unsigned int Rd;
unsigned int Rs;
unsigned int Rn;
-} smla_inst;
+};
-typedef struct smlalxy_inst {
+struct smlalxy_inst {
unsigned int x;
unsigned int y;
unsigned int RdLo;
unsigned int RdHi;
unsigned int Rm;
unsigned int Rn;
-} smlalxy_inst;
+};
-typedef struct ssat_inst {
+struct ssat_inst {
unsigned int Rn;
unsigned int Rd;
unsigned int imm5;
unsigned int sat_imm;
unsigned int shift_type;
-} ssat_inst;
+};
-typedef struct umaal_inst {
+struct umaal_inst {
unsigned int Rn;
unsigned int Rm;
unsigned int RdHi;
unsigned int RdLo;
-} umaal_inst;
+};
-typedef struct _umlal_inst {
+struct umlal_inst {
unsigned int S;
unsigned int Rm;
unsigned int Rs;
unsigned int RdHi;
unsigned int RdLo;
-} umlal_inst;
+};
-typedef struct _smlal_inst {
+struct smlal_inst {
unsigned int S;
unsigned int Rm;
unsigned int Rs;
unsigned int RdHi;
unsigned int RdLo;
-} smlal_inst;
+};
-typedef struct smlald_inst {
+struct smlald_inst {
unsigned int RdLo;
unsigned int RdHi;
unsigned int Rm;
@@ -962,17 +1015,17 @@ typedef struct smlald_inst {
unsigned int swap;
unsigned int op1;
unsigned int op2;
-} smlald_inst;
+};
-typedef struct _mla_inst {
+struct mla_inst {
unsigned int S;
unsigned int Rn;
unsigned int Rd;
unsigned int Rs;
unsigned int Rm;
-} mla_inst;
+};
-typedef struct _mrc_inst {
+struct mrc_inst {
unsigned int opcode_1;
unsigned int opcode_2;
unsigned int cp_num;
@@ -980,9 +1033,9 @@ typedef struct _mrc_inst {
unsigned int crm;
unsigned int Rd;
unsigned int inst;
-} mrc_inst;
+};
-typedef struct _mcr_inst {
+struct mcr_inst {
unsigned int opcode_1;
unsigned int opcode_2;
unsigned int cp_num;
@@ -990,77 +1043,77 @@ typedef struct _mcr_inst {
unsigned int crm;
unsigned int Rd;
unsigned int inst;
-} mcr_inst;
+};
-typedef struct mcrr_inst {
+struct mcrr_inst {
unsigned int opcode_1;
unsigned int cp_num;
unsigned int crm;
unsigned int rt;
unsigned int rt2;
-} mcrr_inst;
+};
-typedef struct _mrs_inst {
+struct mrs_inst {
unsigned int R;
unsigned int Rd;
-} mrs_inst;
+};
-typedef struct _msr_inst {
+struct msr_inst {
unsigned int field_mask;
unsigned int R;
unsigned int inst;
-} msr_inst;
+};
-typedef struct _pld_inst {
-} pld_inst;
+struct pld_inst {
+};
-typedef struct _sxtb_inst {
+struct sxtb_inst {
unsigned int Rd;
unsigned int Rm;
unsigned int rotate;
-} sxtb_inst;
+};
-typedef struct _sxtab_inst {
+struct sxtab_inst {
unsigned int Rd;
unsigned int Rn;
unsigned int Rm;
unsigned rotate;
-} sxtab_inst;
+};
-typedef struct _sxtah_inst {
+struct sxtah_inst {
unsigned int Rd;
unsigned int Rn;
unsigned int Rm;
unsigned int rotate;
-} sxtah_inst;
+};
-typedef struct _sxth_inst {
+struct sxth_inst {
unsigned int Rd;
unsigned int Rm;
unsigned int rotate;
-} sxth_inst;
+};
-typedef struct _uxtab_inst {
+struct uxtab_inst {
unsigned int Rn;
unsigned int Rd;
unsigned int rotate;
unsigned int Rm;
-} uxtab_inst;
+};
-typedef struct _uxtah_inst {
+struct uxtah_inst {
unsigned int Rn;
unsigned int Rd;
unsigned int rotate;
unsigned int Rm;
-} uxtah_inst;
+};
-typedef struct _uxth_inst {
+struct uxth_inst {
unsigned int Rd;
unsigned int Rm;
unsigned int rotate;
-} uxth_inst;
+};
-typedef struct _cdp_inst {
+struct cdp_inst {
unsigned int opcode_1;
unsigned int CRn;
unsigned int CRd;
@@ -1068,56 +1121,56 @@ typedef struct _cdp_inst {
unsigned int opcode_2;
unsigned int CRm;
unsigned int inst;
-}cdp_inst;
+};
-typedef struct _uxtb_inst {
+struct uxtb_inst {
unsigned int Rd;
unsigned int Rm;
unsigned int rotate;
-} uxtb_inst;
+};
-typedef struct _swp_inst {
+struct swp_inst {
unsigned int Rn;
unsigned int Rd;
unsigned int Rm;
-} swp_inst;
+};
-typedef struct setend_inst {
+struct setend_inst {
unsigned int set_bigend;
-} setend_inst;
+};
-typedef struct _b_2_thumb {
+struct b_2_thumb {
unsigned int imm;
-}b_2_thumb;
-typedef struct _b_cond_thumb {
+};
+struct b_cond_thumb {
unsigned int imm;
unsigned int cond;
-}b_cond_thumb;
+};
-typedef struct _bl_1_thumb {
+struct bl_1_thumb {
unsigned int imm;
-}bl_1_thumb;
-typedef struct _bl_2_thumb {
+};
+struct bl_2_thumb {
unsigned int imm;
-}bl_2_thumb;
-typedef struct _blx_1_thumb {
+};
+struct blx_1_thumb {
unsigned int imm;
unsigned int instr;
-}blx_1_thumb;
+};
-typedef struct _pkh_inst {
+struct pkh_inst {
unsigned int Rm;
unsigned int Rn;
unsigned int Rd;
unsigned char imm;
-} pkh_inst;
+};
typedef arm_inst * ARM_INST_PTR;
#define CACHE_BUFFER_SIZE (64 * 1024 * 2000)
-char inst_buf[CACHE_BUFFER_SIZE];
-int top = 0;
-inline void *AllocBuffer(unsigned int size) {
+static char inst_buf[CACHE_BUFFER_SIZE];
+static int top = 0;
+static inline void *AllocBuffer(unsigned int size) {
int start = top;
top += size;
if (top > CACHE_BUFFER_SIZE) {
@@ -1127,74 +1180,6 @@ inline void *AllocBuffer(unsigned int size) {
return (void *)&inst_buf[start];
}
-int CondPassed(ARMul_State* cpu, unsigned int cond) {
- #define NFLAG cpu->NFlag
- #define ZFLAG cpu->ZFlag
- #define CFLAG cpu->CFlag
- #define VFLAG cpu->VFlag
-
- int temp = 0;
-
- switch (cond) {
- case 0x0:
- temp = ZFLAG;
- break;
- case 0x1: // NE
- temp = !ZFLAG;
- break;
- case 0x6: // VS
- temp = VFLAG;
- break;
- case 0x7: // VC
- temp = !VFLAG;
- break;
- case 0x4: // MI
- temp = NFLAG;
- break;
- case 0x5: // PL
- temp = !NFLAG;
- break;
- case 0x2: // CS
- temp = CFLAG;
- break;
- case 0x3: // CC
- temp = !CFLAG;
- break;
- case 0x8: // HI
- temp = (CFLAG && !ZFLAG);
- break;
- case 0x9: // LS
- temp = (!CFLAG || ZFLAG);
- break;
- case 0xa: // GE
- temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
- break;
- case 0xb: // LT
- temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
- break;
- case 0xc: // GT
- temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG));
- break;
- case 0xd: // LE
- temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
- break;
- case 0xe: // AL
- temp = 1;
- break;
- case 0xf:
- temp = 1;
- break;
- }
- return temp;
-}
-
-enum DECODE_STATUS {
- DECODE_SUCCESS,
- DECODE_FAILURE
-};
-
-int decode_arm_instr(uint32_t instr, int32_t *idx);
-
static shtop_fp_t get_shtop(unsigned int inst) {
if (BIT(inst, 25)) {
return DPO(Immediate);
@@ -1393,7 +1378,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index)
inst_base->br = NON_BRANCH;
inst_base->load_r15 = 0;
- inst_cream->imm = BITS(inst, 8, 19) | BITS(inst, 0, 3);
+ inst_cream->imm = (BITS(inst, 8, 19) << 4) | BITS(inst, 0, 3);
return inst_base;
}
@@ -2052,6 +2037,19 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index)
return inst_base;
}
+// NOP introduced in ARMv6K.
+static ARM_INST_PTR INTERPRETER_TRANSLATE(nop)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = NON_BRANCH;
+ inst_base->load_r15 = 0;
+
+ return inst_base;
+}
+
static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index)
{
arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pkh_inst));
@@ -2343,6 +2341,18 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index)
return inst_base;
}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(sev)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = NON_BRANCH;
+ inst_base->load_r15 = 0;
+
+ return inst_base;
+}
+
static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index)
{
arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
@@ -3347,6 +3357,40 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index)
return INTERPRETER_TRANSLATE(uxtab16)(inst, index);
}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(wfe)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = NON_BRANCH;
+ inst_base->load_r15 = 0;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(wfi)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = NON_BRANCH;
+ inst_base->load_r15 = 0;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(yield)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst));
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = NON_BRANCH;
+ inst_base->load_r15 = 0;
+
+ return inst_base;
+}
+
// Floating point VFPv3 structures and instructions
#define VFP_INTERPRETER_STRUCT
@@ -3536,6 +3580,10 @@ const transop_fp_t arm_instruction_trans[] = {
INTERPRETER_TRANSLATE(mrc),
INTERPRETER_TRANSLATE(mcr),
INTERPRETER_TRANSLATE(msr),
+ INTERPRETER_TRANSLATE(msr),
+ INTERPRETER_TRANSLATE(msr),
+ INTERPRETER_TRANSLATE(msr),
+ INTERPRETER_TRANSLATE(msr),
INTERPRETER_TRANSLATE(ldrb),
INTERPRETER_TRANSLATE(strb),
INTERPRETER_TRANSLATE(ldr),
@@ -3544,12 +3592,17 @@ const transop_fp_t arm_instruction_trans[] = {
INTERPRETER_TRANSLATE(cdp),
INTERPRETER_TRANSLATE(stc),
INTERPRETER_TRANSLATE(ldc),
- INTERPRETER_TRANSLATE(swi),
- INTERPRETER_TRANSLATE(bbl),
INTERPRETER_TRANSLATE(ldrexd),
INTERPRETER_TRANSLATE(strexd),
INTERPRETER_TRANSLATE(ldrexh),
INTERPRETER_TRANSLATE(strexh),
+ INTERPRETER_TRANSLATE(nop),
+ INTERPRETER_TRANSLATE(yield),
+ INTERPRETER_TRANSLATE(wfe),
+ INTERPRETER_TRANSLATE(wfi),
+ INTERPRETER_TRANSLATE(sev),
+ INTERPRETER_TRANSLATE(swi),
+ INTERPRETER_TRANSLATE(bbl),
// All the thumb instructions should be placed the end of table
INTERPRETER_TRANSLATE(b_2_thumb),
@@ -3723,7 +3776,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
#define FETCH_INST if (inst_base->br != NON_BRANCH) goto DISPATCH; \
inst_base = (arm_inst *)&inst_buf[ptr]
- #define INC_PC(l) ptr += sizeof(arm_inst) + l
+ #define INC_PC(l) ptr += sizeof(arm_inst) + l
+ #define INC_PC_STUB ptr += sizeof(arm_inst)
// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a
// clunky switch statement.
@@ -3912,28 +3966,37 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
case 172: goto MRC_INST; \
case 173: goto MCR_INST; \
case 174: goto MSR_INST; \
- case 175: goto LDRB_INST; \
- case 176: goto STRB_INST; \
- case 177: goto LDR_INST; \
- case 178: goto LDRCOND_INST ; \
- case 179: goto STR_INST; \
- case 180: goto CDP_INST; \
- case 181: goto STC_INST; \
- case 182: goto LDC_INST; \
- case 183: goto SWI_INST; \
- case 184: goto BBL_INST; \
- case 185: goto LDREXD_INST; \
- case 186: goto STREXD_INST; \
- case 187: goto LDREXH_INST; \
- case 188: goto STREXH_INST; \
- case 189: goto B_2_THUMB ; \
- case 190: goto B_COND_THUMB ; \
- case 191: goto BL_1_THUMB ; \
- case 192: goto BL_2_THUMB ; \
- case 193: goto BLX_1_THUMB ; \
- case 194: goto DISPATCH; \
- case 195: goto INIT_INST_LENGTH; \
- case 196: goto END; \
+ case 175: goto MSR_INST; \
+ case 176: goto MSR_INST; \
+ case 177: goto MSR_INST; \
+ case 178: goto MSR_INST; \
+ case 179: goto LDRB_INST; \
+ case 180: goto STRB_INST; \
+ case 181: goto LDR_INST; \
+ case 182: goto LDRCOND_INST ; \
+ case 183: goto STR_INST; \
+ case 184: goto CDP_INST; \
+ case 185: goto STC_INST; \
+ case 186: goto LDC_INST; \
+ case 187: goto LDREXD_INST; \
+ case 188: goto STREXD_INST; \
+ case 189: goto LDREXH_INST; \
+ case 190: goto STREXH_INST; \
+ case 191: goto NOP_INST; \
+ case 192: goto YIELD_INST; \
+ case 193: goto WFE_INST; \
+ case 194: goto WFI_INST; \
+ case 195: goto SEV_INST; \
+ case 196: goto SWI_INST; \
+ case 197: goto BBL_INST; \
+ case 198: goto B_2_THUMB ; \
+ case 199: goto B_COND_THUMB ; \
+ case 200: goto BL_1_THUMB ; \
+ case 201: goto BL_2_THUMB ; \
+ case 202: goto BLX_1_THUMB ; \
+ case 203: goto DISPATCH; \
+ case 204: goto INIT_INST_LENGTH; \
+ case 205: goto END; \
}
#endif
@@ -3979,9 +4042,11 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
&&MCRR_INST,&&MRRC_INST,&&CMP_INST,&&TST_INST,&&TEQ_INST,&&CMN_INST,&&SMULL_INST,&&UMULL_INST,&&UMLAL_INST,&&SMLAL_INST,&&MUL_INST,
&&MLA_INST,&&SSAT_INST,&&USAT_INST,&&MRS_INST,&&MSR_INST,&&AND_INST,&&BIC_INST,&&LDM_INST,&&EOR_INST,&&ADD_INST,&&RSB_INST,&&RSC_INST,
&&SBC_INST,&&ADC_INST,&&SUB_INST,&&ORR_INST,&&MVN_INST,&&MOV_INST,&&STM_INST,&&LDM_INST,&&LDRSH_INST,&&STM_INST,&&LDM_INST,&&LDRSB_INST,
- &&STRD_INST,&&LDRH_INST,&&STRH_INST,&&LDRD_INST,&&STRT_INST,&&STRBT_INST,&&LDRBT_INST,&&LDRT_INST,&&MRC_INST,&&MCR_INST,&&MSR_INST,
- &&LDRB_INST,&&STRB_INST,&&LDR_INST,&&LDRCOND_INST, &&STR_INST,&&CDP_INST,&&STC_INST,&&LDC_INST,&&SWI_INST,&&BBL_INST,&&LDREXD_INST,
- &&STREXD_INST,&&LDREXH_INST,&&STREXH_INST,&&B_2_THUMB, &&B_COND_THUMB,&&BL_1_THUMB, &&BL_2_THUMB, &&BLX_1_THUMB, &&DISPATCH,
+ &&STRD_INST,&&LDRH_INST,&&STRH_INST,&&LDRD_INST,&&STRT_INST,&&STRBT_INST,&&LDRBT_INST,&&LDRT_INST,&&MRC_INST,&&MCR_INST,
+ &&MSR_INST, &&MSR_INST, &&MSR_INST, &&MSR_INST, &&MSR_INST,
+ &&LDRB_INST,&&STRB_INST,&&LDR_INST,&&LDRCOND_INST, &&STR_INST,&&CDP_INST,&&STC_INST,&&LDC_INST, &&LDREXD_INST,
+ &&STREXD_INST,&&LDREXH_INST,&&STREXH_INST, &&NOP_INST, &&YIELD_INST, &&WFE_INST, &&WFI_INST, &&SEV_INST, &&SWI_INST,&&BBL_INST,
+ &&B_2_THUMB, &&B_COND_THUMB,&&BL_1_THUMB, &&BL_2_THUMB, &&BLX_1_THUMB, &&DISPATCH,
&&INIT_INST_LENGTH,&&END
};
#endif
@@ -5034,6 +5099,14 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
GOTO_NEXT_INST;
}
+ NOP_INST:
+ {
+ cpu->Reg[15] += GET_INST_SIZE(cpu);
+ INC_PC_STUB;
+ FETCH_INST;
+ GOTO_NEXT_INST;
+ }
+
PKHBT_INST:
{
if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
@@ -5517,6 +5590,19 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
GOTO_NEXT_INST;
}
+ SEV_INST:
+ {
+ // Stubbed, as SEV is a hint instruction.
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ LOG_TRACE(Core_ARM11, "SEV executed.");
+ }
+
+ cpu->Reg[15] += GET_INST_SIZE(cpu);
+ INC_PC_STUB;
+ FETCH_INST;
+ GOTO_NEXT_INST;
+ }
+
SHADD8_INST:
SHADD16_INST:
SHADDSUBX_INST:
@@ -6980,6 +7066,45 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
GOTO_NEXT_INST;
}
+ WFE_INST:
+ {
+ // Stubbed, as WFE is a hint instruction.
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ LOG_TRACE(Core_ARM11, "WFE executed.");
+ }
+
+ cpu->Reg[15] += GET_INST_SIZE(cpu);
+ INC_PC_STUB;
+ FETCH_INST;
+ GOTO_NEXT_INST;
+ }
+
+ WFI_INST:
+ {
+ // Stubbed, as WFI is a hint instruction.
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ LOG_TRACE(Core_ARM11, "WFI executed.");
+ }
+
+ cpu->Reg[15] += GET_INST_SIZE(cpu);
+ INC_PC_STUB;
+ FETCH_INST;
+ GOTO_NEXT_INST;
+ }
+
+ YIELD_INST:
+ {
+ // Stubbed, as YIELD is a hint instruction.
+ if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
+ LOG_TRACE(Core_ARM11, "YIELD executed.");
+ }
+
+ cpu->Reg[15] += GET_INST_SIZE(cpu);
+ INC_PC_STUB;
+ FETCH_INST;
+ GOTO_NEXT_INST;
+ }
+
#define VFP_INTERPRETER_IMPL
#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
#undef VFP_INTERPRETER_IMPL
diff --git a/src/core/arm/interpreter/arminit.cpp b/src/core/arm/interpreter/arminit.cpp
index 31b2bab06..680a94a39 100644
--- a/src/core/arm/interpreter/arminit.cpp
+++ b/src/core/arm/interpreter/arminit.cpp
@@ -16,7 +16,6 @@
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <cstring>
-#include "core/mem_map.h"
#include "core/arm/skyeye_common/armdefs.h"
#include "core/arm/skyeye_common/armemu.h"
#include "core/arm/skyeye_common/vfp/vfp.h"
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index 15c6f595b..1b078dc71 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -454,8 +454,6 @@ void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 c
}
else if (crn == 7 && opcode_1 == 0)
{
- LOG_WARNING(Core_ARM11, "Cache operations are not fully implemented.");
-
if (crm == 0 && opcode_2 == 4)
{
cpu->CP15[CP15_WAIT_FOR_INTERRUPT] = value;
diff --git a/src/core/arm/skyeye_common/armmmu.h b/src/core/arm/skyeye_common/armmmu.h
index 0463d83c8..c67d7209b 100644
--- a/src/core/arm/skyeye_common/armmmu.h
+++ b/src/core/arm/skyeye_common/armmmu.h
@@ -22,7 +22,7 @@
#include "common/swap.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
#include "core/arm/skyeye_common/armdefs.h"
// Register numbers in the MMU
diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
index ab9fec39d..f91049585 100644
--- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp
@@ -531,7 +531,7 @@ static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32
LOG_TRACE(Core_ARM11, "In %s\n", __FUNCTION__);
vdm.sign = (m & 0x80000000) >> 16;
vdm.exponent = 1023 + 63 - 1;
- vdm.significand = vdm.sign ? -m : m;
+ vdm.significand = vdm.sign ? (~m + 1) : m;
return vfp_double_normaliseround(state, dd, &vdm, fpscr, 0, "fsito");
}
@@ -669,7 +669,7 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32
exceptions |= FPSCR_IXC;
if (vdm.sign)
- d = -d;
+ d = (~d + 1);
} else {
d = 0;
if (vdm.exponent | vdm.significand) {
@@ -817,7 +817,7 @@ u32 vfp_double_add(struct vfp_double *vdd, struct vfp_double *vdn,struct vfp_dou
m_sig = vdn->significand - m_sig;
if ((s64)m_sig < 0) {
vdd->sign = vfp_sign_negate(vdd->sign);
- m_sig = -m_sig;
+ m_sig = (~m_sig + 1);
} else if (m_sig == 0) {
vdd->sign = (fpscr & FPSCR_RMODE_MASK) ==
FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
index 72afe2164..a04bf915c 100644
--- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
@@ -13,10 +13,10 @@
/* VMLA */
/* cond 1110 0D00 Vn-- Vd-- 101X N0M0 Vm-- */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vmla_inst {
+struct vmla_inst {
unsigned int instr;
unsigned int dp_operation;
-} vmla_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vmla)(unsigned int inst, int index)
@@ -63,10 +63,10 @@ VMLA_INST:
/* VNMLS */
/* cond 1110 0D00 Vn-- Vd-- 101X N1M0 Vm-- */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vmls_inst {
+struct vmls_inst {
unsigned int instr;
unsigned int dp_operation;
-} vmls_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index)
@@ -113,10 +113,10 @@ VMLS_INST:
/* VNMLA */
/* cond 1110 0D01 Vn-- Vd-- 101X N1M0 Vm-- */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vnmla_inst {
+struct vnmla_inst {
unsigned int instr;
unsigned int dp_operation;
-} vnmla_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index)
@@ -164,10 +164,10 @@ VNMLA_INST:
/* cond 1110 0D01 Vn-- Vd-- 101X N0M0 Vm-- */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vnmls_inst {
+struct vnmls_inst {
unsigned int instr;
unsigned int dp_operation;
-} vnmls_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index)
@@ -214,10 +214,10 @@ VNMLS_INST:
/* VNMUL */
/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vnmul_inst {
+struct vnmul_inst {
unsigned int instr;
unsigned int dp_operation;
-} vnmul_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index)
@@ -264,10 +264,10 @@ VNMUL_INST:
/* VMUL */
/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vmul_inst {
+struct vmul_inst {
unsigned int instr;
unsigned int dp_operation;
-} vmul_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index)
@@ -314,10 +314,10 @@ VMUL_INST:
/* VADD */
/* cond 1110 0D11 Vn-- Vd-- 101X N0M0 Vm-- */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vadd_inst {
+struct vadd_inst {
unsigned int instr;
unsigned int dp_operation;
-} vadd_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index)
@@ -364,10 +364,10 @@ VADD_INST:
/* VSUB */
/* cond 1110 0D11 Vn-- Vd-- 101X N1M0 Vm-- */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vsub_inst {
+struct vsub_inst {
unsigned int instr;
unsigned int dp_operation;
-} vsub_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index)
@@ -414,10 +414,10 @@ VSUB_INST:
/* VDIV */
/* cond 1110 1D00 Vn-- Vd-- 101X N0M0 Vm-- */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vdiv_inst {
+struct vdiv_inst {
unsigned int instr;
unsigned int dp_operation;
-} vdiv_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index)
@@ -465,11 +465,11 @@ VDIV_INST:
/* cond 1110 1D11 im4H Vd-- 101X 0000 im4L */
/* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vmovi_inst {
+struct vmovi_inst {
unsigned int single;
unsigned int d;
unsigned int imm;
-} vmovi_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovi)(unsigned int inst, int index)
@@ -514,11 +514,11 @@ VMOVI_INST:
/* cond 1110 1D11 0000 Vd-- 101X 01M0 Vm-- */
/* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vmovr_inst {
+struct vmovr_inst {
unsigned int single;
unsigned int d;
unsigned int m;
-} vmovr_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovr)(unsigned int inst, int index)
@@ -609,10 +609,10 @@ VABS_INST:
/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vneg_inst {
+struct vneg_inst {
unsigned int instr;
unsigned int dp_operation;
-} vneg_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index)
@@ -659,10 +659,10 @@ VNEG_INST:
/* VSQRT */
/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vsqrt_inst {
+struct vsqrt_inst {
unsigned int instr;
unsigned int dp_operation;
-} vsqrt_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index)
@@ -709,10 +709,10 @@ VSQRT_INST:
/* VCMP VCMPE */
/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 1 */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vcmp_inst {
+struct vcmp_inst {
unsigned int instr;
unsigned int dp_operation;
-} vcmp_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index)
@@ -759,10 +759,10 @@ VCMP_INST:
/* VCMP VCMPE */
/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 2 */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vcmp2_inst {
+struct vcmp2_inst {
unsigned int instr;
unsigned int dp_operation;
-} vcmp2_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index)
@@ -809,10 +809,10 @@ VCMP2_INST:
/* VCVTBDS between double and single */
/* cond 1110 1D11 0111 Vd-- 101X 11M0 Vm-- */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vcvtbds_inst {
+struct vcvtbds_inst {
unsigned int instr;
unsigned int dp_operation;
-} vcvtbds_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index)
@@ -859,10 +859,10 @@ VCVTBDS_INST:
/* VCVTBFF between floating point and fixed point */
/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vcvtbff_inst {
+struct vcvtbff_inst {
unsigned int instr;
unsigned int dp_operation;
-} vcvtbff_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index)
@@ -911,10 +911,10 @@ VCVTBFF_INST:
/* VCVTBFI between floating point and integer */
/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vcvtbfi_inst {
+struct vcvtbfi_inst {
unsigned int instr;
unsigned int dp_operation;
-} vcvtbfi_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index)
@@ -967,11 +967,11 @@ VCVTBFI_INST:
/* cond 1110 000o Vn-- Rt-- 1010 N001 0000 */
/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vmovbrs_inst {
+struct vmovbrs_inst {
unsigned int to_arm;
unsigned int t;
unsigned int n;
-} vmovbrs_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrs)(unsigned int inst, int index)
@@ -1013,10 +1013,10 @@ VMOVBRS_INST:
/* cond 1110 1110 reg- Rt-- 1010 0001 0000 */
/* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vmsr_inst {
+struct vmsr_inst {
unsigned int reg;
unsigned int Rd;
-} vmsr_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index)
@@ -1040,7 +1040,7 @@ VMSR_INST:
{
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
/* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled ,
- and in privilegied mode */
+ and in privileged mode */
/* Exceptions must be checked, according to v7 ref manual */
CHECK_VFP_ENABLED;
@@ -1060,12 +1060,12 @@ VMSR_INST:
/* cond 1110 0XX0 Vd-- Rt-- 1011 DXX1 0000 */
/* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vmovbrc_inst {
+struct vmovbrc_inst {
unsigned int esize;
unsigned int index;
unsigned int d;
unsigned int t;
-} vmovbrc_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index)
@@ -1109,10 +1109,10 @@ VMOVBRC_INST:
/* cond 1110 1111 CRn- Rt-- 1010 0001 0000 */
/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vmrs_inst {
+struct vmrs_inst {
unsigned int reg;
unsigned int Rt;
-} vmrs_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index)
@@ -1136,7 +1136,7 @@ VMRS_INST:
{
if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
/* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled,
- and in privilegied mode */
+ and in privileged mode */
/* Exceptions must be checked, according to v7 ref manual */
CHECK_VFP_ENABLED;
@@ -1191,12 +1191,12 @@ VMRS_INST:
/* cond 1110 XXX1 Vd-- Rt-- 1011 NXX1 0000 */
/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MCR */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vmovbcr_inst {
+struct vmovbcr_inst {
unsigned int esize;
unsigned int index;
unsigned int d;
unsigned int t;
-} vmovbcr_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index)
@@ -1245,12 +1245,12 @@ VMOVBCR_INST:
/* cond 1100 010X Rt2- Rt-- 1010 00X1 Vm-- */
/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vmovbrrss_inst {
+struct vmovbrrss_inst {
unsigned int to_arm;
unsigned int t;
unsigned int t2;
unsigned int m;
-} vmovbrrss_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrss)(unsigned int inst, int index)
@@ -1294,12 +1294,12 @@ VMOVBRRSS_INST:
/* cond 1100 010X Rt2- Rt-- 1011 00X1 Vm-- */
/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vmovbrrd_inst {
+struct vmovbrrd_inst {
unsigned int to_arm;
unsigned int t;
unsigned int t2;
unsigned int m;
-} vmovbrrd_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrd)(unsigned int inst, int index)
@@ -1347,13 +1347,13 @@ VMOVBRRD_INST:
/* VSTR */
/* cond 1101 UD00 Rn-- Vd-- 101X imm8 imm8 */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vstr_inst {
+struct vstr_inst {
unsigned int single;
unsigned int n;
unsigned int d;
unsigned int imm32;
unsigned int add;
-} vstr_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vstr)(unsigned int inst, int index)
@@ -1415,12 +1415,12 @@ VSTR_INST:
/* VPUSH */
/* cond 1101 0D10 1101 Vd-- 101X imm8 imm8 */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vpush_inst {
+struct vpush_inst {
unsigned int single;
unsigned int d;
unsigned int imm32;
unsigned int regs;
-} vpush_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vpush)(unsigned int inst, int index)
@@ -1488,7 +1488,7 @@ VPUSH_INST:
/* VSTM */
/* cond 110P UDW0 Rn-- Vd-- 101X imm8 imm8 */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vstm_inst {
+struct vstm_inst {
unsigned int single;
unsigned int add;
unsigned int wback;
@@ -1496,7 +1496,7 @@ typedef struct _vstm_inst {
unsigned int n;
unsigned int imm32;
unsigned int regs;
-} vstm_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index)
@@ -1570,12 +1570,12 @@ VSTM_INST: /* encoding 1 */
/* VPOP */
/* cond 1100 1D11 1101 Vd-- 101X imm8 imm8 */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vpop_inst {
+struct vpop_inst {
unsigned int single;
unsigned int d;
unsigned int imm32;
unsigned int regs;
-} vpop_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vpop)(unsigned int inst, int index)
@@ -1643,13 +1643,13 @@ VPOP_INST:
/* VLDR */
/* cond 1101 UD01 Rn-- Vd-- 101X imm8 imm8 */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vldr_inst {
+struct vldr_inst {
unsigned int single;
unsigned int n;
unsigned int d;
unsigned int imm32;
unsigned int add;
-} vldr_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vldr)(unsigned int inst, int index)
@@ -1711,7 +1711,7 @@ VLDR_INST:
/* VLDM */
/* cond 110P UDW1 Rn-- Vd-- 101X imm8 imm8 */
#ifdef VFP_INTERPRETER_STRUCT
-typedef struct _vldm_inst {
+struct vldm_inst {
unsigned int single;
unsigned int add;
unsigned int wback;
@@ -1719,7 +1719,7 @@ typedef struct _vldm_inst {
unsigned int n;
unsigned int imm32;
unsigned int regs;
-} vldm_inst;
+};
#endif
#ifdef VFP_INTERPRETER_TRANS
static ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index)
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
index 4dfe0254d..a692c1909 100644
--- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
@@ -388,7 +388,7 @@ sqrt_invalid:
} else {
u64 term;
s64 rem;
- vsm.significand <<= !(vsm.exponent & 1);
+ vsm.significand <<= static_cast<u32>((vsm.exponent & 1) == 0);
term = (u64)vsd.significand * vsd.significand;
rem = ((u64)vsm.significand << 32) - term;
@@ -691,7 +691,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f
exceptions |= FPSCR_IXC;
if (vsm.sign)
- d = 0-d;
+ d = (~d + 1);
} else {
d = 0;
if (vsm.exponent | vsm.significand) {
@@ -843,7 +843,7 @@ vfp_single_add(struct vfp_single *vsd, struct vfp_single *vsn,
m_sig = vsn->significand - m_sig;
if ((s32)m_sig < 0) {
vsd->sign = vfp_sign_negate(vsd->sign);
- m_sig = 0-m_sig;
+ m_sig = (~m_sig + 1);
} else if (m_sig == 0) {
vsd->sign = (fpscr & FPSCR_RMODE_MASK) ==
FPSCR_ROUND_MINUSINF ? 0x8000 : 0;
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 53aae8c2f..79038cd52 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -8,7 +8,6 @@
#include "core/core.h"
#include "core/core_timing.h"
-#include "core/mem_map.h"
#include "core/settings.h"
#include "core/arm/arm_interface.h"
#include "core/arm/disassembler/arm_disasm.h"
diff --git a/src/core/file_sys/archive_backend.cpp b/src/core/file_sys/archive_backend.cpp
index 0439868ab..45a559ce8 100644
--- a/src/core/file_sys/archive_backend.cpp
+++ b/src/core/file_sys/archive_backend.cpp
@@ -8,7 +8,7 @@
#include "common/string_util.h"
#include "core/file_sys/archive_backend.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
namespace FileSys {
diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp
index 35dc9cf58..aea936d2d 100644
--- a/src/core/hle/config_mem.cpp
+++ b/src/core/hle/config_mem.cpp
@@ -9,59 +9,14 @@
#include "common/common_funcs.h"
#include "core/core.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
#include "core/hle/config_mem.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace ConfigMem {
-struct ConfigMemDef {
- u8 kernel_unk; // 0
- u8 kernel_version_rev; // 1
- u8 kernel_version_min; // 2
- u8 kernel_version_maj; // 3
- u32 update_flag; // 4
- u64 ns_tid; // 8
- u32 sys_core_ver; // 10
- u8 unit_info; // 14
- u8 boot_firm; // 15
- u8 prev_firm; // 16
- INSERT_PADDING_BYTES(0x1); // 17
- u32 ctr_sdk_ver; // 18
- INSERT_PADDING_BYTES(0x30 - 0x1C); // 1C
- u32 app_mem_type; // 30
- INSERT_PADDING_BYTES(0x40 - 0x34); // 34
- u32 app_mem_alloc; // 40
- u32 sys_mem_alloc; // 44
- u32 base_mem_alloc; // 48
- INSERT_PADDING_BYTES(0x60 - 0x4C); // 4C
- u8 firm_unk; // 60
- u8 firm_version_rev; // 61
- u8 firm_version_min; // 62
- u8 firm_version_maj; // 63
- u32 firm_sys_core_ver; // 64
- u32 firm_ctr_sdk_ver; // 68
- INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C
-};
-
-static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE, "Config Memory structure size is wrong");
-
-static ConfigMemDef config_mem;
-
-template <typename T>
-inline void Read(T &var, const u32 addr) {
- u32 offset = addr - Memory::CONFIG_MEMORY_VADDR;
- ASSERT(offset < Memory::CONFIG_MEMORY_SIZE);
- var = *(reinterpret_cast<T*>(((uintptr_t)&config_mem) + offset));
-}
-
-// Explicitly instantiate template functions because we aren't defining this in the header:
-
-template void Read<u64>(u64 &var, const u32 addr);
-template void Read<u32>(u32 &var, const u32 addr);
-template void Read<u16>(u16 &var, const u32 addr);
-template void Read<u8>(u8 &var, const u32 addr);
+ConfigMemDef config_mem;
void Init() {
std::memset(&config_mem, 0, sizeof(config_mem));
diff --git a/src/core/hle/config_mem.h b/src/core/hle/config_mem.h
index cbb478fb3..9825a09e8 100644
--- a/src/core/hle/config_mem.h
+++ b/src/core/hle/config_mem.h
@@ -9,17 +9,49 @@
// bootrom. Because we're not emulating this, and essentially just "stubbing" the functionality, I'm
// putting this as a subset of HLE for now.
+#include "common/common_funcs.h"
#include "common/common_types.h"
+#include "common/swap.h"
+
+#include "core/memory.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace ConfigMem {
-template <typename T>
-void Read(T &var, const u32 addr);
+struct ConfigMemDef {
+ u8 kernel_unk; // 0
+ u8 kernel_version_rev; // 1
+ u8 kernel_version_min; // 2
+ u8 kernel_version_maj; // 3
+ u32_le update_flag; // 4
+ u64_le ns_tid; // 8
+ u32_le sys_core_ver; // 10
+ u8 unit_info; // 14
+ u8 boot_firm; // 15
+ u8 prev_firm; // 16
+ INSERT_PADDING_BYTES(0x1); // 17
+ u32_le ctr_sdk_ver; // 18
+ INSERT_PADDING_BYTES(0x30 - 0x1C); // 1C
+ u32_le app_mem_type; // 30
+ INSERT_PADDING_BYTES(0x40 - 0x34); // 34
+ u32_le app_mem_alloc; // 40
+ u32_le sys_mem_alloc; // 44
+ u32_le base_mem_alloc; // 48
+ INSERT_PADDING_BYTES(0x60 - 0x4C); // 4C
+ u8 firm_unk; // 60
+ u8 firm_version_rev; // 61
+ u8 firm_version_min; // 62
+ u8 firm_version_maj; // 63
+ u32_le firm_sys_core_ver; // 64
+ u32_le firm_ctr_sdk_ver; // 68
+ INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C
+};
+static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE, "Config Memory structure size is wrong");
+
+extern ConfigMemDef config_mem;
void Init();
-
void Shutdown();
} // namespace
diff --git a/src/core/hle/coprocessor.cpp b/src/core/hle/coprocessor.cpp
deleted file mode 100644
index 425959be4..000000000
--- a/src/core/hle/coprocessor.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include "core/hle/coprocessor.h"
-#include "core/hle/hle.h"
-#include "core/mem_map.h"
-
-namespace HLE {
-
-/// Returns the coprocessor (in this case, syscore) command buffer pointer
-Addr GetThreadCommandBuffer() {
- // Called on insruction: mrc p15, 0, r0, c13, c0, 3
- return Memory::KERNEL_MEMORY_VADDR;
-}
-
-/// Call an MRC (move to ARM register from coprocessor) instruction in HLE
-s32 CallMRC(u32 instruction) {
- CoprocessorOperation operation = (CoprocessorOperation)((instruction >> 20) & 0xFF);
-
- switch (operation) {
-
- case CALL_GET_THREAD_COMMAND_BUFFER:
- return GetThreadCommandBuffer();
-
- default:
- DEBUG_LOG(OSHLE, "unknown MRC call 0x%08X", instruction);
- break;
- }
- return -1;
-}
-
-} // namespace
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index be2626eef..23c86a72d 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -7,7 +7,7 @@
#include "common/common_types.h"
#include "core/arm/arm_interface.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
#include "core/hle/hle.h"
namespace HLE {
@@ -102,14 +102,14 @@ template<ResultCode func(u32)> void Wrap() {
FuncReturn(func(PARAM(0)).raw);
}
-template<ResultCode func(s64*, u32, void*, s32)> void Wrap(){
- FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)),
+template<ResultCode func(s64*, u32, u32*, s32)> void Wrap(){
+ FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), (u32*)Memory::GetPointer(PARAM(2)),
(s32)PARAM(3)).raw);
}
template<ResultCode func(u32*, const char*)> void Wrap() {
u32 param_1 = 0;
- u32 retval = func(&param_1, Memory::GetCharPointer(PARAM(1))).raw;
+ u32 retval = func(&param_1, (char*)Memory::GetPointer(PARAM(1))).raw;
Core::g_app_core->SetReg(1, param_1);
FuncReturn(retval);
}
@@ -163,7 +163,11 @@ template<void func(s64)> void Wrap() {
}
template<void func(const char*)> void Wrap() {
- func(Memory::GetCharPointer(PARAM(0)));
+ func((char*)Memory::GetPointer(PARAM(0)));
+}
+
+template<void func(u8)> void Wrap() {
+ func((u8)PARAM(0));
}
#undef PARAM
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 9d7f6b280..a1221766e 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -5,7 +5,7 @@
#include "common/common_types.h"
#include "common/logging/log.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
#include "core/hle/hle.h"
#include "core/hle/kernel/address_arbiter.h"
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index b5c98b249..726e4d2ff 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -10,6 +10,7 @@
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h"
@@ -134,6 +135,7 @@ void HandleTable::Clear() {
/// Initialize the kernel
void Init() {
+ Kernel::ResourceLimitsInit();
Kernel::ThreadingInit();
Kernel::TimersInit();
@@ -147,6 +149,7 @@ void Init() {
void Shutdown() {
Kernel::ThreadingShutdown();
Kernel::TimersShutdown();
+ Kernel::ResourceLimitsShutdown();
g_handle_table.Clear(); // Free all kernel objects
g_current_process = nullptr;
}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 7c106d37c..28748c8f5 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -46,7 +46,8 @@ enum class HandleType : u32 {
Process = 8,
AddressArbiter = 9,
Semaphore = 10,
- Timer = 11
+ Timer = 11,
+ ResourceLimit = 12,
};
enum {
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 1e439db9e..b0e75ba59 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -7,8 +7,9 @@
#include "common/logging/log.h"
#include "core/hle/kernel/process.h"
+#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/thread.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
namespace Kernel {
@@ -27,7 +28,7 @@ SharedPtr<Process> Process::Create(std::string name, u64 program_id) {
}
void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
- for (int i = 0; i < len; ++i) {
+ for (size_t i = 0; i < len; ++i) {
u32 descriptor = kernel_caps[i];
u32 type = descriptor >> 20;
@@ -64,8 +65,8 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
AddressMapping mapping;
mapping.address = descriptor << 12;
mapping.size = (end_desc << 12) - mapping.address;
- mapping.writable = descriptor & (1 << 20);
- mapping.unk_flag = end_desc & (1 << 20);
+ mapping.writable = (descriptor & (1 << 20)) != 0;
+ mapping.unk_flag = (end_desc & (1 << 20)) != 0;
address_mappings.push_back(mapping);
} else if ((type & 0xFFF) == 0xFFE) { // 0x000F
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 90881054c..7b8a68610 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -45,6 +45,8 @@ union ProcessFlags {
BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000).
};
+class ResourceLimit;
+
class Process final : public Object {
public:
static SharedPtr<Process> Create(std::string name, u64 program_id);
@@ -61,6 +63,8 @@ public:
std::string name;
/// Title ID corresponding to the process
u64 program_id;
+ /// Resource limit descriptor for this process
+ SharedPtr<ResourceLimit> resource_limit;
/// The process may only call SVCs which have the corresponding bit set.
std::bitset<0x80> svc_access_mask;
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
new file mode 100644
index 000000000..94b3e3298
--- /dev/null
+++ b/src/core/hle/kernel/resource_limit.cpp
@@ -0,0 +1,157 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <cstring>
+
+#include "common/logging/log.h"
+
+#include "core/mem_map.h"
+#include "core/hle/kernel/resource_limit.h"
+
+namespace Kernel {
+
+static SharedPtr<ResourceLimit> resource_limits[4];
+
+ResourceLimit::ResourceLimit() {}
+ResourceLimit::~ResourceLimit() {}
+
+SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) {
+ SharedPtr<ResourceLimit> resource_limit(new ResourceLimit);
+
+ resource_limit->name = std::move(name);
+ return resource_limit;
+}
+
+SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) {
+ switch (category)
+ {
+ case ResourceLimitCategory::APPLICATION:
+ case ResourceLimitCategory::SYS_APPLET:
+ case ResourceLimitCategory::LIB_APPLET:
+ case ResourceLimitCategory::OTHER:
+ return resource_limits[static_cast<u8>(category)];
+ default:
+ LOG_CRITICAL(Kernel, "Unknown resource limit category");
+ UNREACHABLE();
+ }
+}
+
+s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const {
+ switch (resource) {
+ case COMMIT:
+ return current_commit;
+ case THREAD:
+ return current_threads;
+ case EVENT:
+ return current_events;
+ case MUTEX:
+ return current_mutexes;
+ case SEMAPHORE:
+ return current_semaphores;
+ case TIMER:
+ return current_timers;
+ case SHARED_MEMORY:
+ return current_shared_mems;
+ case ADDRESS_ARBITER:
+ return current_address_arbiters;
+ case CPU_TIME:
+ return current_cpu_time;
+ default:
+ LOG_ERROR(Kernel, "Unknown resource type=%08X", resource);
+ UNIMPLEMENTED();
+ return 0;
+ }
+}
+
+s32 ResourceLimit::GetMaxResourceValue(u32 resource) const {
+ switch (resource) {
+ case COMMIT:
+ return max_commit;
+ case THREAD:
+ return max_threads;
+ case EVENT:
+ return max_events;
+ case MUTEX:
+ return max_mutexes;
+ case SEMAPHORE:
+ return max_semaphores;
+ case TIMER:
+ return max_timers;
+ case SHARED_MEMORY:
+ return max_shared_mems;
+ case ADDRESS_ARBITER:
+ return max_address_arbiters;
+ case CPU_TIME:
+ return max_cpu_time;
+ default:
+ LOG_ERROR(Kernel, "Unknown resource type=%08X", resource);
+ UNIMPLEMENTED();
+ return 0;
+ }
+}
+
+void ResourceLimitsInit() {
+ // Create the four resource limits that the system uses
+ // Create the APPLICATION resource limit
+ SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create("Applications");
+ resource_limit->max_priority = 0x18;
+ resource_limit->max_commit = 0x4000000;
+ resource_limit->max_threads = 0x20;
+ resource_limit->max_events = 0x20;
+ resource_limit->max_mutexes = 0x20;
+ resource_limit->max_semaphores = 0x8;
+ resource_limit->max_timers = 0x8;
+ resource_limit->max_shared_mems = 0x10;
+ resource_limit->max_address_arbiters = 0x2;
+ resource_limit->max_cpu_time = 0x1E;
+ resource_limits[static_cast<u8>(ResourceLimitCategory::APPLICATION)] = resource_limit;
+
+ // Create the SYS_APPLET resource limit
+ resource_limit = ResourceLimit::Create("System Applets");
+ resource_limit->max_priority = 0x4;
+ resource_limit->max_commit = 0x5E00000;
+ resource_limit->max_threads = 0x1D;
+ resource_limit->max_events = 0xB;
+ resource_limit->max_mutexes = 0x8;
+ resource_limit->max_semaphores = 0x4;
+ resource_limit->max_timers = 0x4;
+ resource_limit->max_shared_mems = 0x8;
+ resource_limit->max_address_arbiters = 0x3;
+ resource_limit->max_cpu_time = 0x2710;
+ resource_limits[static_cast<u8>(ResourceLimitCategory::SYS_APPLET)] = resource_limit;
+
+ // Create the LIB_APPLET resource limit
+ resource_limit = ResourceLimit::Create("Library Applets");
+ resource_limit->max_priority = 0x4;
+ resource_limit->max_commit = 0x600000;
+ resource_limit->max_threads = 0xE;
+ resource_limit->max_events = 0x8;
+ resource_limit->max_mutexes = 0x8;
+ resource_limit->max_semaphores = 0x4;
+ resource_limit->max_timers = 0x4;
+ resource_limit->max_shared_mems = 0x8;
+ resource_limit->max_address_arbiters = 0x1;
+ resource_limit->max_cpu_time = 0x2710;
+ resource_limits[static_cast<u8>(ResourceLimitCategory::LIB_APPLET)] = resource_limit;
+
+ // Create the OTHER resource limit
+ resource_limit = ResourceLimit::Create("Others");
+ resource_limit->max_priority = 0x4;
+ resource_limit->max_commit = 0x2180000;
+ resource_limit->max_threads = 0xE1;
+ resource_limit->max_events = 0x108;
+ resource_limit->max_mutexes = 0x25;
+ resource_limit->max_semaphores = 0x43;
+ resource_limit->max_timers = 0x2C;
+ resource_limit->max_shared_mems = 0x1F;
+ resource_limit->max_address_arbiters = 0x2D;
+ resource_limit->max_cpu_time = 0x3E8;
+ resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit;
+}
+
+void ResourceLimitsShutdown() {
+
+}
+
+} // namespace
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
new file mode 100644
index 000000000..201ec0db9
--- /dev/null
+++ b/src/core/hle/kernel/resource_limit.h
@@ -0,0 +1,119 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/common_types.h"
+
+#include "core/hle/kernel/kernel.h"
+
+namespace Kernel {
+
+enum class ResourceLimitCategory : u8 {
+ APPLICATION = 0,
+ SYS_APPLET = 1,
+ LIB_APPLET = 2,
+ OTHER = 3
+};
+
+enum ResourceTypes {
+ PRIORITY = 0,
+ COMMIT = 1,
+ THREAD = 2,
+ EVENT = 3,
+ MUTEX = 4,
+ SEMAPHORE = 5,
+ TIMER = 6,
+ SHARED_MEMORY = 7,
+ ADDRESS_ARBITER = 8,
+ CPU_TIME = 9,
+};
+
+class ResourceLimit final : public Object {
+public:
+ /**
+ * Creates a resource limit object.
+ */
+ static SharedPtr<ResourceLimit> Create(std::string name = "Unknown");
+
+ /**
+ * Retrieves the resource limit associated with the specified resource limit category.
+ * @param category The resource limit category
+ * @returns The resource limit associated with the category
+ */
+ static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category);
+
+ std::string GetTypeName() const override { return "ResourceLimit"; }
+ std::string GetName() const override { return name; }
+
+ static const HandleType HANDLE_TYPE = HandleType::ResourceLimit;
+ HandleType GetHandleType() const override { return HANDLE_TYPE; }
+
+ /**
+ * Gets the current value for the specified resource.
+ * @param resource Requested resource type
+ * @returns The current value of the resource type
+ */
+ s32 GetCurrentResourceValue(u32 resource) const;
+
+ /**
+ * Gets the max value for the specified resource.
+ * @param resource Requested resource type
+ * @returns The max value of the resource type
+ */
+ s32 GetMaxResourceValue(u32 resource) const;
+
+ /// Name of resource limit object.
+ std::string name;
+
+ /// Max thread priority that a process in this category can create
+ s32 max_priority = 0;
+
+ /// Max memory that processes in this category can use
+ s32 max_commit = 0;
+
+ ///< Max number of objects that can be collectively created by the processes in this category
+ s32 max_threads = 0;
+ s32 max_events = 0;
+ s32 max_mutexes = 0;
+ s32 max_semaphores = 0;
+ s32 max_timers = 0;
+ s32 max_shared_mems = 0;
+ s32 max_address_arbiters = 0;
+
+ /// Max CPU time that the processes in this category can utilize
+ s32 max_cpu_time = 0;
+
+ // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that
+ // APPLICATION resource limits should not be affected by the objects created by service modules.
+ // Currently we have no way of distinguishing if a Create was called by the running application,
+ // or by a service module. Approach this once we have separated the service modules into their own processes
+
+ /// Current memory that the processes in this category are using
+ s32 current_commit = 0;
+
+ ///< Current number of objects among all processes in this category
+ s32 current_threads = 0;
+ s32 current_events = 0;
+ s32 current_mutexes = 0;
+ s32 current_semaphores = 0;
+ s32 current_timers = 0;
+ s32 current_shared_mems = 0;
+ s32 current_address_arbiters = 0;
+
+ /// Current CPU time that the processes in this category are utilizing
+ s32 current_cpu_time = 0;
+
+private:
+ ResourceLimit();
+ ~ResourceLimit() override;
+};
+
+/// Initializes the resource limits
+void ResourceLimitsInit();
+
+// Destroys the resource limits
+void ResourceLimitsShutdown();
+
+} // namespace
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
index 8c3886ffd..54a062971 100644
--- a/src/core/hle/kernel/session.h
+++ b/src/core/hle/kernel/session.h
@@ -6,7 +6,7 @@
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/thread.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
namespace Kernel {
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 0c59f4876..4137683b5 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -6,7 +6,7 @@
#include "common/logging/log.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
#include "core/hle/kernel/shared_memory.h"
namespace Kernel {
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index afaf0cd5d..a5f1904d7 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -21,7 +21,7 @@
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/mutex.h"
#include "core/hle/result.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
namespace Kernel {
@@ -495,7 +495,7 @@ void Reschedule() {
LOG_TRACE(Kernel, "context switch %u -> %u", cur->GetObjectId(), next->GetObjectId());
} else if (cur) {
LOG_TRACE(Kernel, "context switch %u -> idle", cur->GetObjectId());
- } else {
+ } else if (next) {
LOG_TRACE(Kernel, "context switch idle -> %u", next->GetObjectId());
}
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 6b329c12a..389928178 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -12,7 +12,6 @@
#include "common/common_types.h"
#include "core/core.h"
-#include "core/mem_map.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/result.h"
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index 09d463dd5..3fd4cfb08 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -269,8 +269,6 @@ void GetAppCpuTimeLimit(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 value = cmd_buff[1];
- ASSERT(cpu_percent != 0);
-
if (value != 1) {
LOG_ERROR(Service_APT, "This value should be one, but is actually %u!", value);
}
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index 0d2a426b0..b25c8941d 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -650,7 +650,7 @@ static void SetPriority(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
- LOG_DEBUG(Service_FS, "called priority=0x%08X", priority);
+ LOG_DEBUG(Service_FS, "called priority=0x%X", priority);
}
/**
@@ -664,12 +664,14 @@ static void SetPriority(Service::Interface* self) {
static void GetPriority(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- ASSERT(priority != -1);
+ if (priority == -1) {
+ LOG_INFO(Service_FS, "priority was not set, priority=0x%X", priority);
+ }
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[2] = priority;
- LOG_DEBUG(Service_FS, "called priority=0x%08X", priority);
+ LOG_DEBUG(Service_FS, "called priority=0x%X", priority);
}
const Interface::FunctionInfo FunctionTable[] = {
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index c6252a03b..c11c5faba 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -5,6 +5,7 @@
#include "common/bit_field.h"
#include "core/mem_map.h"
+#include "core/memory.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/result.h"
diff --git a/src/core/hle/shared_page.cpp b/src/core/hle/shared_page.cpp
index 4f227a370..4014eee98 100644
--- a/src/core/hle/shared_page.cpp
+++ b/src/core/hle/shared_page.cpp
@@ -8,7 +8,7 @@
#include "common/common_funcs.h"
#include "core/core.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
#include "core/hle/config_mem.h"
#include "core/hle/shared_page.h"
@@ -16,63 +16,12 @@
namespace SharedPage {
-// see http://3dbrew.org/wiki/Configuration_Memory#Shared_Memory_Page_For_ARM11_Processes
+SharedPageDef shared_page;
-#pragma pack(1)
-struct DateTime {
- u64 date_time; // 0x0
- u64 update_tick; // 0x8
- INSERT_PADDING_BYTES(0x20 - 0x10); // 0x10
-};
-
-struct SharedPageDef {
- // most of these names are taken from the 3dbrew page linked above.
- u32 date_time_selector; // 0x0
- u8 running_hw; // 0x4
- u8 mcu_hw_info; // 0x5: don't know what the acronyms mean
- INSERT_PADDING_BYTES(0x20 - 0x6); // 0x6
- DateTime date_time_0; // 0x20
- DateTime date_time_1; // 0x40
- u8 wifi_macaddr[6]; // 0x60
- u8 wifi_unknown1; // 0x66: 3dbrew says these are "Likely wifi hardware related"
- u8 wifi_unknown2; // 0x67
- INSERT_PADDING_BYTES(0x80 - 0x68); // 0x68
- float sliderstate_3d; // 0x80
- u8 ledstate_3d; // 0x84
- INSERT_PADDING_BYTES(0xA0 - 0x85); // 0x85
- u64 menu_title_id; // 0xA0
- u64 active_menu_title_id; // 0xA8
- INSERT_PADDING_BYTES(0x1000 - 0xB0); // 0xB0
-};
-#pragma pack()
-
-static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong");
-static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, "Shared page structure size is wrong");
-
-static SharedPageDef shared_page;
-
-template <typename T>
-inline void Read(T &var, const u32 addr) {
- u32 offset = addr - Memory::SHARED_PAGE_VADDR;
- var = *(reinterpret_cast<T*>(((uintptr_t)&shared_page) + offset));
-}
-
-// Explicitly instantiate template functions because we aren't defining this in the header:
-template void Read<u64>(u64 &var, const u32 addr);
-template void Read<u32>(u32 &var, const u32 addr);
-template void Read<u16>(u16 &var, const u32 addr);
-template void Read<u8>(u8 &var, const u32 addr);
-
-void Set3DSlider(float amount) {
+void Init() {
std::memset(&shared_page, 0, sizeof(shared_page));
- shared_page.sliderstate_3d = amount;
- shared_page.ledstate_3d = (amount == 0.0f); // off when non-zero
-}
-
-void Init() {
shared_page.running_hw = 0x1; // product
- Set3DSlider(0.0f);
}
void Shutdown() {
diff --git a/src/core/hle/shared_page.h b/src/core/hle/shared_page.h
index 1b6e4e581..fd2ab66a2 100644
--- a/src/core/hle/shared_page.h
+++ b/src/core/hle/shared_page.h
@@ -11,18 +11,46 @@
*/
#include "common/common_types.h"
+#include "common/swap.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
namespace SharedPage {
-template <typename T>
-void Read(T &var, const u32 addr);
-
-void Set3DSlider(float amount);
+// See http://3dbrew.org/wiki/Configuration_Memory#Shared_Memory_Page_For_ARM11_Processes
+
+struct DateTime {
+ u64_le date_time; // 0
+ u64_le update_tick; // 8
+ INSERT_PADDING_BYTES(0x20 - 0x10); // 10
+};
+static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong");
+
+struct SharedPageDef {
+ // Most of these names are taken from the 3dbrew page linked above.
+ u32_le date_time_selector; // 0
+ u8 running_hw; // 4
+ /// "Microcontroller hardware info"
+ u8 mcu_hw_info; // 5
+ INSERT_PADDING_BYTES(0x20 - 0x6); // 6
+ DateTime date_time_0; // 20
+ DateTime date_time_1; // 40
+ u8 wifi_macaddr[6]; // 60
+ u8 wifi_unknown1; // 66
+ u8 wifi_unknown2; // 67
+ INSERT_PADDING_BYTES(0x80 - 0x68); // 68
+ float_le sliderstate_3d; // 80
+ u8 ledstate_3d; // 84
+ INSERT_PADDING_BYTES(0xA0 - 0x85); // 85
+ u64_le menu_title_id; // A0
+ u64_le active_menu_title_id; // A8
+ INSERT_PADDING_BYTES(0x1000 - 0xB0); // B0
+};
+static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, "Shared page structure size is wrong");
+
+extern SharedPageDef shared_page;
void Init();
-
void Shutdown();
} // namespace
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index e8159fbdb..22adf9595 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -17,6 +17,7 @@
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/mutex.h"
#include "core/hle/kernel/process.h"
+#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/semaphore.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/kernel/thread.h"
@@ -295,27 +296,65 @@ static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 val
return res;
}
+static void Break(u8 break_reason) {
+ LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!");
+ std::string reason_str;
+ switch (break_reason) {
+ case 0: reason_str = "PANIC"; break;
+ case 1: reason_str = "ASSERT"; break;
+ case 2: reason_str = "USER"; break;
+ default: reason_str = "UNKNOWN"; break;
+ }
+ LOG_CRITICAL(Debug_Emulated, "Break reason: %s", reason_str.c_str());
+}
+
/// Used to output a message on a debug hardware unit - does nothing on a retail unit
static void OutputDebugString(const char* string) {
LOG_DEBUG(Debug_Emulated, "%s", string);
}
/// Get resource limit
-static ResultCode GetResourceLimit(Handle* resource_limit, Handle process) {
- // With regards to proceess values:
- // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for
- // the current KThread.
- *resource_limit = 0xDEADBEEF;
- LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called process=0x%08X", process);
+static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) {
+ LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
+
+ SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle);
+ if (process == nullptr)
+ return ERR_INVALID_HANDLE;
+
+ CASCADE_RESULT(*resource_limit, Kernel::g_handle_table.Create(process->resource_limit));
+
return RESULT_SUCCESS;
}
/// Get resource limit current values
-static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names,
+static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, u32* names,
s32 name_count) {
- LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%p, name_count=%d",
- resource_limit, names, name_count);
- Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now
+ LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d",
+ resource_limit_handle, names, name_count);
+
+ SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle);
+ if (resource_limit == nullptr)
+ return ERR_INVALID_HANDLE;
+
+ for (unsigned int i = 0; i < name_count; ++i)
+ values[i] = resource_limit->GetCurrentResourceValue(names[i]);
+
+ return RESULT_SUCCESS;
+}
+
+/// Get resource limit max values
+static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names,
+ s32 name_count) {
+ LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d",
+ resource_limit_handle, names, name_count);
+
+ SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle);
+ if (resource_limit == nullptr)
+ return ERR_INVALID_HANDLE;
+
+ for (unsigned int i = 0; i < name_count; ++i)
+ values[i] = resource_limit->GetMaxResourceValue(names[i]);
+
return RESULT_SUCCESS;
}
@@ -707,10 +746,10 @@ static const FunctionDef SVC_Table[] = {
{0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"},
{0x37, HLE::Wrap<GetThreadId>, "GetThreadId"},
{0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"},
- {0x39, nullptr, "GetResourceLimitLimitValues"},
+ {0x39, HLE::Wrap<GetResourceLimitLimitValues>, "GetResourceLimitLimitValues"},
{0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"},
{0x3B, nullptr, "GetThreadContext"},
- {0x3C, nullptr, "Break"},
+ {0x3C, HLE::Wrap<Break>, "Break"},
{0x3D, HLE::Wrap<OutputDebugString>, "OutputDebugString"},
{0x3E, nullptr, "ControlPerformanceCounter"},
{0x3F, nullptr, "Unknown"},
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index e4a0e14c4..8ef1f70df 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -8,7 +8,7 @@
#include "core/settings.h"
#include "core/core.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
#include "core/core_timing.h"
#include "core/hle/hle.h"
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
index e28986085..ad5e929ce 100644
--- a/src/core/loader/3dsx.cpp
+++ b/src/core/loader/3dsx.cpp
@@ -9,10 +9,11 @@
#include "core/file_sys/archive_romfs.h"
#include "core/hle/kernel/process.h"
+#include "core/hle/kernel/resource_limit.h"
#include "core/hle/service/fs/archive.h"
#include "core/loader/elf.h"
#include "core/loader/ncch.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
#include "3dsx.h"
@@ -233,6 +234,9 @@ ResultStatus AppLoader_THREEDSX::Load() {
Kernel::g_current_process = Kernel::Process::Create(filename, 0);
Kernel::g_current_process->svc_access_mask.set();
Kernel::g_current_process->address_mappings = default_address_mappings;
+
+ // Attach the default resource limit (APPLICATION) to the process
+ Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
Load3DSXFile(*file, Memory::PROCESS_IMAGE_VADDR);
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index 47d4e8cea..f00753a79 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -11,8 +11,9 @@
#include "common/symbols.h"
#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/resource_limit.h"
#include "core/loader/elf.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
// ELF Header Constants
@@ -354,6 +355,9 @@ ResultStatus AppLoader_ELF::Load() {
Kernel::g_current_process->svc_access_mask.set();
Kernel::g_current_process->address_mappings = default_address_mappings;
+ // Attach the default resource limit (APPLICATION) to the process
+ Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
+
ElfReader elf_reader(&buffer[0]);
elf_reader.LoadInto(Memory::PROCESS_IMAGE_VADDR);
// TODO: Fill application title
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 4f881cf6f..8b14edf00 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -13,7 +13,6 @@
#include "core/loader/3dsx.h"
#include "core/loader/elf.h"
#include "core/loader/ncch.h"
-#include "core/mem_map.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index 3325a6ab8..08993c4fa 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -11,8 +11,9 @@
#include "common/swap.h"
#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/resource_limit.h"
#include "core/loader/ncch.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
// Loader namespace
@@ -126,6 +127,10 @@ ResultStatus AppLoader_NCCH::LoadExec() const {
u64 program_id = *reinterpret_cast<u64_le const*>(&ncch_header.program_id[0]);
Kernel::g_current_process = Kernel::Process::Create(process_name, program_id);
+ // Attach a resource limit to the process based on the resource limit category
+ Kernel::g_current_process->resource_limit = Kernel::ResourceLimit::GetForCategory(
+ static_cast<Kernel::ResourceLimitCategory>(exheader_header.arm11_system_local_caps.resource_limit_category));
+
// Copy data while converting endianess
std::array<u32, ARRAY_SIZE(exheader_header.arm11_kernel_caps.descriptors)> kernel_caps;
std::copy_n(exheader_header.arm11_kernel_caps.descriptors, kernel_caps.size(), begin(kernel_caps));
diff --git a/src/core/mem_map.cpp b/src/core/mem_map.cpp
index f99520464..5ecec9566 100644
--- a/src/core/mem_map.cpp
+++ b/src/core/mem_map.cpp
@@ -2,10 +2,16 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <map>
+
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "core/hle/config_mem.h"
+#include "core/hle/shared_page.h"
#include "core/mem_map.h"
+#include "core/memory.h"
+#include "core/memory_setup.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -23,33 +29,129 @@ namespace {
struct MemoryArea {
u8** ptr;
- size_t size;
+ u32 base;
+ u32 size;
};
// We don't declare the IO regions in here since its handled by other means.
static MemoryArea memory_areas[] = {
- {&g_exefs_code, PROCESS_IMAGE_MAX_SIZE},
- {&g_heap, HEAP_SIZE },
- {&g_shared_mem, SHARED_MEMORY_SIZE },
- {&g_heap_linear, LINEAR_HEAP_SIZE },
- {&g_vram, VRAM_SIZE },
- {&g_dsp_mem, DSP_RAM_SIZE },
- {&g_tls_mem, TLS_AREA_SIZE },
+ {&g_exefs_code, PROCESS_IMAGE_VADDR, PROCESS_IMAGE_MAX_SIZE},
+ {&g_heap, HEAP_VADDR, HEAP_SIZE },
+ {&g_shared_mem, SHARED_MEMORY_VADDR, SHARED_MEMORY_SIZE },
+ {&g_heap_linear, LINEAR_HEAP_VADDR, LINEAR_HEAP_SIZE },
+ {&g_vram, VRAM_VADDR, VRAM_SIZE },
+ {&g_dsp_mem, DSP_RAM_VADDR, DSP_RAM_SIZE },
+ {&g_tls_mem, TLS_AREA_VADDR, TLS_AREA_SIZE },
+};
+
+/// Represents a block of memory mapped by ControlMemory/MapMemoryBlock
+struct MemoryBlock {
+ MemoryBlock() : handle(0), base_address(0), address(0), size(0), operation(0), permissions(0) {
+ }
+ u32 handle;
+ u32 base_address;
+ u32 address;
+ u32 size;
+ u32 operation;
+ u32 permissions;
+
+ const u32 GetVirtualAddress() const{
+ return base_address + address;
+ }
};
+static std::map<u32, MemoryBlock> heap_map;
+static std::map<u32, MemoryBlock> heap_linear_map;
+
+}
+
+u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) {
+ MemoryBlock block;
+
+ block.base_address = HEAP_VADDR;
+ block.size = size;
+ block.operation = operation;
+ block.permissions = permissions;
+
+ if (heap_map.size() > 0) {
+ const MemoryBlock last_block = heap_map.rbegin()->second;
+ block.address = last_block.address + last_block.size;
+ }
+ heap_map[block.GetVirtualAddress()] = block;
+
+ return block.GetVirtualAddress();
+}
+
+u32 MapBlock_HeapLinear(u32 size, u32 operation, u32 permissions) {
+ MemoryBlock block;
+
+ block.base_address = LINEAR_HEAP_VADDR;
+ block.size = size;
+ block.operation = operation;
+ block.permissions = permissions;
+
+ if (heap_linear_map.size() > 0) {
+ const MemoryBlock last_block = heap_linear_map.rbegin()->second;
+ block.address = last_block.address + last_block.size;
+ }
+ heap_linear_map[block.GetVirtualAddress()] = block;
+
+ return block.GetVirtualAddress();
+}
+
+PAddr VirtualToPhysicalAddress(const VAddr addr) {
+ if (addr == 0) {
+ return 0;
+ } else if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) {
+ return addr - VRAM_VADDR + VRAM_PADDR;
+ } else if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) {
+ return addr - LINEAR_HEAP_VADDR + FCRAM_PADDR;
+ } else if (addr >= DSP_RAM_VADDR && addr < DSP_RAM_VADDR_END) {
+ return addr - DSP_RAM_VADDR + DSP_RAM_PADDR;
+ } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) {
+ return addr - IO_AREA_VADDR + IO_AREA_PADDR;
+ }
+
+ LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08x", addr);
+ // To help with debugging, set bit on address so that it's obviously invalid.
+ return addr | 0x80000000;
+}
+
+VAddr PhysicalToVirtualAddress(const PAddr addr) {
+ if (addr == 0) {
+ return 0;
+ } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
+ return addr - VRAM_PADDR + VRAM_VADDR;
+ } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) {
+ return addr - FCRAM_PADDR + LINEAR_HEAP_VADDR;
+ } else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) {
+ return addr - DSP_RAM_PADDR + DSP_RAM_VADDR;
+ } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) {
+ return addr - IO_AREA_PADDR + IO_AREA_VADDR;
+ }
+
+ LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08x", addr);
+ // To help with debugging, set bit on address so that it's obviously invalid.
+ return addr | 0x80000000;
}
void Init() {
+ InitMemoryMap();
+
for (MemoryArea& area : memory_areas) {
*area.ptr = new u8[area.size];
+ MapMemoryRegion(area.base, area.size, *area.ptr);
}
- MemBlock_Init();
+ MapMemoryRegion(CONFIG_MEMORY_VADDR, CONFIG_MEMORY_SIZE, (u8*)&ConfigMem::config_mem);
+ MapMemoryRegion(SHARED_PAGE_VADDR, SHARED_PAGE_SIZE, (u8*)&SharedPage::shared_page);
LOG_DEBUG(HW_Memory, "initialized OK, RAM at %p", g_heap);
}
void Shutdown() {
- MemBlock_Shutdown();
+ heap_map.clear();
+ heap_linear_map.clear();
+
for (MemoryArea& area : memory_areas) {
delete[] *area.ptr;
*area.ptr = nullptr;
diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index 71f90cb8a..945815cd6 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -8,121 +8,6 @@
namespace Memory {
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-const u32 PAGE_SIZE = 0x1000;
-
-/// Physical memory regions as seen from the ARM11
-enum : PAddr {
- /// IO register area
- IO_AREA_PADDR = 0x10100000,
- IO_AREA_SIZE = 0x01000000, ///< IO area size (16MB)
- IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE,
-
- /// MPCore internal memory region
- MPCORE_RAM_PADDR = 0x17E00000,
- MPCORE_RAM_SIZE = 0x00002000, ///< MPCore internal memory size (8KB)
- MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE,
-
- /// Video memory
- VRAM_PADDR = 0x18000000,
- VRAM_SIZE = 0x00600000, ///< VRAM size (6MB)
- VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE,
-
- /// DSP memory
- DSP_RAM_PADDR = 0x1FF00000,
- DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB)
- DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE,
-
- /// AXI WRAM
- AXI_WRAM_PADDR = 0x1FF80000,
- AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size (512KB)
- AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE,
-
- /// Main FCRAM
- FCRAM_PADDR = 0x20000000,
- FCRAM_SIZE = 0x08000000, ///< FCRAM size (128MB)
- FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE,
-};
-
-/// Virtual user-space memory regions
-enum : VAddr {
- /// Where the application text, data and bss reside.
- PROCESS_IMAGE_VADDR = 0x00100000,
- PROCESS_IMAGE_MAX_SIZE = 0x03F00000,
- PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE,
-
- /// Area where IPC buffers are mapped onto.
- IPC_MAPPING_VADDR = 0x04000000,
- IPC_MAPPING_SIZE = 0x04000000,
- IPC_MAPPING_VADDR_END = IPC_MAPPING_VADDR + IPC_MAPPING_SIZE,
-
- /// Application heap (includes stack).
- HEAP_VADDR = 0x08000000,
- HEAP_SIZE = 0x08000000,
- HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE,
-
- /// Area where shared memory buffers are mapped onto.
- SHARED_MEMORY_VADDR = 0x10000000,
- SHARED_MEMORY_SIZE = 0x04000000,
- SHARED_MEMORY_VADDR_END = SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE,
-
- /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical memory.
- LINEAR_HEAP_VADDR = 0x14000000,
- LINEAR_HEAP_SIZE = 0x08000000,
- LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE,
-
- /// Maps 1:1 to the IO register area.
- IO_AREA_VADDR = 0x1EC00000,
- IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE,
-
- /// Maps 1:1 to VRAM.
- VRAM_VADDR = 0x1F000000,
- VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE,
-
- /// Maps 1:1 to DSP memory.
- DSP_RAM_VADDR = 0x1FF00000,
- DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE,
-
- /// Read-only page containing kernel and system configuration values.
- CONFIG_MEMORY_VADDR = 0x1FF80000,
- CONFIG_MEMORY_SIZE = 0x00001000,
- CONFIG_MEMORY_VADDR_END = CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE,
-
- /// Usually read-only page containing mostly values read from hardware.
- SHARED_PAGE_VADDR = 0x1FF81000,
- SHARED_PAGE_SIZE = 0x00001000,
- SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE,
-
- // TODO(yuriks): The size of this area is dynamic, the kernel grows
- // it as more and more threads are created. For now we'll just use a
- // hardcoded value.
- /// Area where TLS (Thread-Local Storage) buffers are allocated.
- TLS_AREA_VADDR = 0x1FF82000,
- TLS_AREA_SIZE = 0x00030000, // Each TLS buffer is 0x200 bytes, allows for 300 threads
- TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE,
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/// Represents a block of memory mapped by ControlMemory/MapMemoryBlock
-struct MemoryBlock {
- MemoryBlock() : handle(0), base_address(0), address(0), size(0), operation(0), permissions(0) {
- }
- u32 handle;
- u32 base_address;
- u32 address;
- u32 size;
- u32 operation;
- u32 permissions;
-
- const u32 GetVirtualAddress() const{
- return base_address + address;
- }
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
extern u8* g_exefs_code; ///< ExeFS:/.code is loaded here
extern u8* g_heap; ///< Application heap (main memory)
extern u8* g_shared_mem; ///< Shared memory
@@ -134,29 +19,6 @@ extern u8* g_tls_mem; ///< TLS memory
void Init();
void Shutdown();
-template <typename T>
-inline void Read(T &var, VAddr addr);
-
-template <typename T>
-inline void Write(VAddr addr, T data);
-
-u8 Read8(VAddr addr);
-u16 Read16(VAddr addr);
-u32 Read32(VAddr addr);
-u64 Read64(VAddr addr);
-
-u32 Read8_ZX(VAddr addr);
-u32 Read16_ZX(VAddr addr);
-
-void Write8(VAddr addr, u8 data);
-void Write16(VAddr addr, u16 data);
-void Write32(VAddr addr, u32 data);
-void Write64(VAddr addr, u64 data);
-
-void WriteBlock(VAddr addr, const u8* data, size_t size);
-
-u8* GetPointer(VAddr virtual_address);
-
/**
* Maps a block of memory on the heap
* @param size Size of block in bytes
@@ -173,16 +35,6 @@ u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions);
*/
u32 MapBlock_HeapLinear(u32 size, u32 operation, u32 permissions);
-/// Initialize mapped memory blocks
-void MemBlock_Init();
-
-/// Shutdown mapped memory blocks
-void MemBlock_Shutdown();
-
-inline const char* GetCharPointer(const VAddr address) {
- return (const char *)GetPointer(address);
-}
-
/**
* Converts a virtual address inside a region with 1:1 mapping to physical memory to a physical
* address. This should be used by services to translate addresses for use by the hardware.
@@ -194,13 +46,4 @@ PAddr VirtualToPhysicalAddress(VAddr addr);
*/
VAddr PhysicalToVirtualAddress(PAddr addr);
-/**
- * Gets a pointer to the memory region beginning at the specified physical address.
- *
- * @note This is currently implemented using PhysicalToVirtualAddress().
- */
-inline u8* GetPhysicalPointer(PAddr address) {
- return GetPointer(PhysicalToVirtualAddress(address));
-}
-
} // namespace
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
deleted file mode 100644
index a8e0fed07..000000000
--- a/src/core/mem_map_funcs.cpp
+++ /dev/null
@@ -1,283 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <map>
-
-#include "common/common_types.h"
-#include "common/logging/log.h"
-#include "common/swap.h"
-
-#include "core/mem_map.h"
-#include "core/hw/hw.h"
-#include "hle/config_mem.h"
-#include "hle/shared_page.h"
-
-namespace Memory {
-
-static std::map<u32, MemoryBlock> heap_map;
-static std::map<u32, MemoryBlock> heap_linear_map;
-
-PAddr VirtualToPhysicalAddress(const VAddr addr) {
- if (addr == 0) {
- return 0;
- } else if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) {
- return addr - VRAM_VADDR + VRAM_PADDR;
- } else if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) {
- return addr - LINEAR_HEAP_VADDR + FCRAM_PADDR;
- } else if (addr >= DSP_RAM_VADDR && addr < DSP_RAM_VADDR_END) {
- return addr - DSP_RAM_VADDR + DSP_RAM_PADDR;
- } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) {
- return addr - IO_AREA_VADDR + IO_AREA_PADDR;
- }
-
- LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x%08x", addr);
- // To help with debugging, set bit on address so that it's obviously invalid.
- return addr | 0x80000000;
-}
-
-VAddr PhysicalToVirtualAddress(const PAddr addr) {
- if (addr == 0) {
- return 0;
- } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
- return addr - VRAM_PADDR + VRAM_VADDR;
- } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) {
- return addr - FCRAM_PADDR + LINEAR_HEAP_VADDR;
- } else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) {
- return addr - DSP_RAM_PADDR + DSP_RAM_VADDR;
- } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) {
- return addr - IO_AREA_PADDR + IO_AREA_VADDR;
- }
-
- LOG_ERROR(HW_Memory, "Unknown physical address @ 0x%08x", addr);
- // To help with debugging, set bit on address so that it's obviously invalid.
- return addr | 0x80000000;
-}
-
-template <typename T>
-inline void Read(T &var, const VAddr vaddr) {
- // TODO: Figure out the fastest order of tests for both read and write (they are probably different).
- // TODO: Make sure this represents the mirrors in a correct way.
- // Could just do a base-relative read, too.... TODO
-
- // Kernel memory command buffer
- if (vaddr >= TLS_AREA_VADDR && vaddr < TLS_AREA_VADDR_END) {
- var = *((const T*)&g_tls_mem[vaddr - TLS_AREA_VADDR]);
-
- // ExeFS:/.code is loaded here
- } else if ((vaddr >= PROCESS_IMAGE_VADDR) && (vaddr < PROCESS_IMAGE_VADDR_END)) {
- var = *((const T*)&g_exefs_code[vaddr - PROCESS_IMAGE_VADDR]);
-
- // FCRAM - linear heap
- } else if ((vaddr >= LINEAR_HEAP_VADDR) && (vaddr < LINEAR_HEAP_VADDR_END)) {
- var = *((const T*)&g_heap_linear[vaddr - LINEAR_HEAP_VADDR]);
-
- // FCRAM - application heap
- } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
- var = *((const T*)&g_heap[vaddr - HEAP_VADDR]);
-
- // Shared memory
- } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
- var = *((const T*)&g_shared_mem[vaddr - SHARED_MEMORY_VADDR]);
-
- // Config memory
- } else if ((vaddr >= CONFIG_MEMORY_VADDR) && (vaddr < CONFIG_MEMORY_VADDR_END)) {
- ConfigMem::Read<T>(var, vaddr);
-
- // Shared page
- } else if ((vaddr >= SHARED_PAGE_VADDR) && (vaddr < SHARED_PAGE_VADDR_END)) {
- SharedPage::Read<T>(var, vaddr);
-
- // DSP memory
- } else if ((vaddr >= DSP_RAM_VADDR) && (vaddr < DSP_RAM_VADDR_END)) {
- var = *((const T*)&g_dsp_mem[vaddr - DSP_RAM_VADDR]);
-
- // VRAM
- } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
- var = *((const T*)&g_vram[vaddr - VRAM_VADDR]);
-
- } else {
- LOG_ERROR(HW_Memory, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, vaddr);
- }
-}
-
-template <typename T>
-inline void Write(const VAddr vaddr, const T data) {
-
- // Kernel memory command buffer
- if (vaddr >= TLS_AREA_VADDR && vaddr < TLS_AREA_VADDR_END) {
- *(T*)&g_tls_mem[vaddr - TLS_AREA_VADDR] = data;
-
- // ExeFS:/.code is loaded here
- } else if ((vaddr >= PROCESS_IMAGE_VADDR) && (vaddr < PROCESS_IMAGE_VADDR_END)) {
- *(T*)&g_exefs_code[vaddr - PROCESS_IMAGE_VADDR] = data;
-
- // FCRAM - linear heap
- } else if ((vaddr >= LINEAR_HEAP_VADDR) && (vaddr < LINEAR_HEAP_VADDR_END)) {
- *(T*)&g_heap_linear[vaddr - LINEAR_HEAP_VADDR] = data;
-
- // FCRAM - application heap
- } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
- *(T*)&g_heap[vaddr - HEAP_VADDR] = data;
-
- // Shared memory
- } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
- *(T*)&g_shared_mem[vaddr - SHARED_MEMORY_VADDR] = data;
-
- // VRAM
- } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
- *(T*)&g_vram[vaddr - VRAM_VADDR] = data;
-
- // DSP memory
- } else if ((vaddr >= DSP_RAM_VADDR) && (vaddr < DSP_RAM_VADDR_END)) {
- *(T*)&g_dsp_mem[vaddr - DSP_RAM_VADDR] = data;
-
- //} else if ((vaddr & 0xFFFF0000) == 0x1FF80000) {
- // ASSERT_MSG(MEMMAP, false, "umimplemented write to Configuration Memory");
- //} else if ((vaddr & 0xFFFFF000) == 0x1FF81000) {
- // ASSERT_MSG(MEMMAP, false, "umimplemented write to shared page");
-
- // Error out...
- } else {
- LOG_ERROR(HW_Memory, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, vaddr);
- }
-}
-
-u8 *GetPointer(const VAddr vaddr) {
- // Kernel memory command buffer
- if (vaddr >= TLS_AREA_VADDR && vaddr < TLS_AREA_VADDR_END) {
- return g_tls_mem + (vaddr - TLS_AREA_VADDR);
-
- // ExeFS:/.code is loaded here
- } else if ((vaddr >= PROCESS_IMAGE_VADDR) && (vaddr < PROCESS_IMAGE_VADDR_END)) {
- return g_exefs_code + (vaddr - PROCESS_IMAGE_VADDR);
-
- // FCRAM - linear heap
- } else if ((vaddr >= LINEAR_HEAP_VADDR) && (vaddr < LINEAR_HEAP_VADDR_END)) {
- return g_heap_linear + (vaddr - LINEAR_HEAP_VADDR);
-
- // FCRAM - application heap
- } else if ((vaddr >= HEAP_VADDR) && (vaddr < HEAP_VADDR_END)) {
- return g_heap + (vaddr - HEAP_VADDR);
-
- // Shared memory
- } else if ((vaddr >= SHARED_MEMORY_VADDR) && (vaddr < SHARED_MEMORY_VADDR_END)) {
- return g_shared_mem + (vaddr - SHARED_MEMORY_VADDR);
-
- // VRAM
- } else if ((vaddr >= VRAM_VADDR) && (vaddr < VRAM_VADDR_END)) {
- return g_vram + (vaddr - VRAM_VADDR);
-
- } else {
- LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x%08x", vaddr);
- return 0;
- }
-}
-
-u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) {
- MemoryBlock block;
-
- block.base_address = HEAP_VADDR;
- block.size = size;
- block.operation = operation;
- block.permissions = permissions;
-
- if (heap_map.size() > 0) {
- const MemoryBlock last_block = heap_map.rbegin()->second;
- block.address = last_block.address + last_block.size;
- }
- heap_map[block.GetVirtualAddress()] = block;
-
- return block.GetVirtualAddress();
-}
-
-u32 MapBlock_HeapLinear(u32 size, u32 operation, u32 permissions) {
- MemoryBlock block;
-
- block.base_address = LINEAR_HEAP_VADDR;
- block.size = size;
- block.operation = operation;
- block.permissions = permissions;
-
- if (heap_linear_map.size() > 0) {
- const MemoryBlock last_block = heap_linear_map.rbegin()->second;
- block.address = last_block.address + last_block.size;
- }
- heap_linear_map[block.GetVirtualAddress()] = block;
-
- return block.GetVirtualAddress();
-}
-
-void MemBlock_Init() {
-}
-
-void MemBlock_Shutdown() {
- heap_map.clear();
- heap_linear_map.clear();
-}
-
-u8 Read8(const VAddr addr) {
- u8 data = 0;
- Read<u8>(data, addr);
- return data;
-}
-
-u16 Read16(const VAddr addr) {
- u16_le data = 0;
- Read<u16_le>(data, addr);
- return (u16)data;
-}
-
-u32 Read32(const VAddr addr) {
- u32_le data = 0;
- Read<u32_le>(data, addr);
- return (u32)data;
-}
-
-u64 Read64(const VAddr addr) {
- u64_le data = 0;
- Read<u64_le>(data, addr);
- return (u64)data;
-}
-
-u32 Read8_ZX(const VAddr addr) {
- return (u32)Read8(addr);
-}
-
-u32 Read16_ZX(const VAddr addr) {
- return (u32)Read16(addr);
-}
-
-void Write8(const VAddr addr, const u8 data) {
- Write<u8>(addr, data);
-}
-
-void Write16(const VAddr addr, const u16 data) {
- Write<u16_le>(addr, data);
-}
-
-void Write32(const VAddr addr, const u32 data) {
- Write<u32_le>(addr, data);
-}
-
-void Write64(const VAddr addr, const u64 data) {
- Write<u64_le>(addr, data);
-}
-
-void WriteBlock(const VAddr addr, const u8* data, const size_t size) {
- u32 offset = 0;
- while (offset < (size & ~3)) {
- Write32(addr + offset, *(u32*)&data[offset]);
- offset += 4;
- }
-
- if (size & 2) {
- Write16(addr + offset, *(u16*)&data[offset]);
- offset += 2;
- }
-
- if (size & 1)
- Write8(addr + offset, data[offset]);
-}
-
-} // namespace
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
new file mode 100644
index 000000000..5d8069acd
--- /dev/null
+++ b/src/core/memory.cpp
@@ -0,0 +1,202 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <array>
+
+#include "common/assert.h"
+#include "common/common_types.h"
+#include "common/logging/log.h"
+#include "common/swap.h"
+
+#include "core/hle/config_mem.h"
+#include "core/hle/shared_page.h"
+#include "core/hw/hw.h"
+#include "core/mem_map.h"
+#include "core/memory.h"
+
+namespace Memory {
+
+const u32 PAGE_MASK = PAGE_SIZE - 1;
+const int PAGE_BITS = 12;
+
+enum class PageType {
+ /// Page is unmapped and should cause an access error.
+ Unmapped,
+ /// Page is mapped to regular memory. This is the only type you can get pointers to.
+ Memory,
+ /// Page is mapped to a I/O region. Writing and reading to this page is handled by functions.
+ Special,
+};
+
+/**
+ * A (reasonably) fast way of allowing switchable and remmapable process address spaces. It loosely
+ * mimics the way a real CPU page table works, but instead is optimized for minimal decoding and
+ * fetching requirements when acessing. In the usual case of an access to regular memory, it only
+ * requires an indexed fetch and a check for NULL.
+ */
+struct PageTable {
+ static const size_t NUM_ENTRIES = 1 << (32 - PAGE_BITS);
+
+ /**
+ * Array of memory pointers backing each page. An entry can only be non-null if the
+ * corresponding entry in the `attributes` array is of type `Memory`.
+ */
+ std::array<u8*, NUM_ENTRIES> pointers;
+
+ /**
+ * Array of fine grained page attributes. If it is set to any value other than `Memory`, then
+ * the corresponding entry in `pointer` MUST be set to null.
+ */
+ std::array<PageType, NUM_ENTRIES> attributes;
+};
+
+/// Singular page table used for the singleton process
+static PageTable main_page_table;
+/// Currently active page table
+static PageTable* current_page_table = &main_page_table;
+
+static void MapPages(u32 base, u32 size, u8* memory, PageType type) {
+ LOG_DEBUG(HW_Memory, "Mapping %p onto %08X-%08X", memory, base * PAGE_SIZE, (base + size) * PAGE_SIZE);
+
+ u32 end = base + size;
+
+ while (base != end) {
+ ASSERT_MSG(base < PageTable::NUM_ENTRIES, "out of range mapping at %08X", base);
+
+ if (current_page_table->attributes[base] != PageType::Unmapped) {
+ LOG_ERROR(HW_Memory, "overlapping memory ranges at %08X", base * PAGE_SIZE);
+ }
+ current_page_table->attributes[base] = type;
+ current_page_table->pointers[base] = memory;
+
+ base += 1;
+ memory += PAGE_SIZE;
+ }
+}
+
+void InitMemoryMap() {
+ main_page_table.pointers.fill(nullptr);
+ main_page_table.attributes.fill(PageType::Unmapped);
+}
+
+void MapMemoryRegion(VAddr base, u32 size, u8* target) {
+ ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: %08X", size);
+ ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: %08X", base);
+ MapPages(base / PAGE_SIZE, size / PAGE_SIZE, target, PageType::Memory);
+}
+
+void MapIoRegion(VAddr base, u32 size) {
+ ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: %08X", size);
+ ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: %08X", base);
+ MapPages(base / PAGE_SIZE, size / PAGE_SIZE, nullptr, PageType::Special);
+}
+
+template <typename T>
+T Read(const VAddr vaddr) {
+ const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
+ if (page_pointer) {
+ return *reinterpret_cast<const T*>(page_pointer + (vaddr & PAGE_MASK));
+ }
+
+ PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
+ switch (type) {
+ case PageType::Unmapped:
+ LOG_ERROR(HW_Memory, "unmapped Read%lu @ 0x%08X", sizeof(T) * 8, vaddr);
+ return 0;
+ case PageType::Memory:
+ ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
+ case PageType::Special:
+ LOG_ERROR(HW_Memory, "I/O reads aren't implemented yet @ %08X", vaddr);
+ return 0;
+ default:
+ UNREACHABLE();
+ }
+}
+
+template <typename T>
+void Write(const VAddr vaddr, const T data) {
+ u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
+ if (page_pointer) {
+ *reinterpret_cast<T*>(page_pointer + (vaddr & PAGE_MASK)) = data;
+ return;
+ }
+
+ PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
+ switch (type) {
+ case PageType::Unmapped:
+ LOG_ERROR(HW_Memory, "unmapped Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32) data, vaddr);
+ return;
+ case PageType::Memory:
+ ASSERT_MSG(false, "Mapped memory page without a pointer @ %08X", vaddr);
+ case PageType::Special:
+ LOG_ERROR(HW_Memory, "I/O writes aren't implemented yet @ %08X", vaddr);
+ return;
+ default:
+ UNREACHABLE();
+ }
+}
+
+u8* GetPointer(const VAddr vaddr) {
+ u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
+ if (page_pointer) {
+ return page_pointer + (vaddr & PAGE_MASK);
+ }
+
+ LOG_ERROR(HW_Memory, "unknown GetPointer @ 0x%08x", vaddr);
+ return nullptr;
+}
+
+u8* GetPhysicalPointer(PAddr address) {
+ return GetPointer(PhysicalToVirtualAddress(address));
+}
+
+u8 Read8(const VAddr addr) {
+ return Read<u8>(addr);
+}
+
+u16 Read16(const VAddr addr) {
+ return Read<u16_le>(addr);
+}
+
+u32 Read32(const VAddr addr) {
+ return Read<u32_le>(addr);
+}
+
+u64 Read64(const VAddr addr) {
+ return Read<u64_le>(addr);
+}
+
+void Write8(const VAddr addr, const u8 data) {
+ Write<u8>(addr, data);
+}
+
+void Write16(const VAddr addr, const u16 data) {
+ Write<u16_le>(addr, data);
+}
+
+void Write32(const VAddr addr, const u32 data) {
+ Write<u32_le>(addr, data);
+}
+
+void Write64(const VAddr addr, const u64 data) {
+ Write<u64_le>(addr, data);
+}
+
+void WriteBlock(const VAddr addr, const u8* data, const size_t size) {
+ u32 offset = 0;
+ while (offset < (size & ~3)) {
+ Write32(addr + offset, *(u32*)&data[offset]);
+ offset += 4;
+ }
+
+ if (size & 2) {
+ Write16(addr + offset, *(u16*)&data[offset]);
+ offset += 2;
+ }
+
+ if (size & 1)
+ Write8(addr + offset, data[offset]);
+}
+
+} // namespace
diff --git a/src/core/memory.h b/src/core/memory.h
new file mode 100644
index 000000000..2d225801b
--- /dev/null
+++ b/src/core/memory.h
@@ -0,0 +1,129 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/common_types.h"
+
+namespace Memory {
+
+/**
+ * Page size used by the ARM architecture. This is the smallest granularity with which memory can
+ * be mapped.
+ */
+const u32 PAGE_SIZE = 0x1000;
+
+/// Physical memory regions as seen from the ARM11
+enum : PAddr {
+ /// IO register area
+ IO_AREA_PADDR = 0x10100000,
+ IO_AREA_SIZE = 0x01000000, ///< IO area size (16MB)
+ IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE,
+
+ /// MPCore internal memory region
+ MPCORE_RAM_PADDR = 0x17E00000,
+ MPCORE_RAM_SIZE = 0x00002000, ///< MPCore internal memory size (8KB)
+ MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE,
+
+ /// Video memory
+ VRAM_PADDR = 0x18000000,
+ VRAM_SIZE = 0x00600000, ///< VRAM size (6MB)
+ VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE,
+
+ /// DSP memory
+ DSP_RAM_PADDR = 0x1FF00000,
+ DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB)
+ DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE,
+
+ /// AXI WRAM
+ AXI_WRAM_PADDR = 0x1FF80000,
+ AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size (512KB)
+ AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE,
+
+ /// Main FCRAM
+ FCRAM_PADDR = 0x20000000,
+ FCRAM_SIZE = 0x08000000, ///< FCRAM size (128MB)
+ FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE,
+};
+
+/// Virtual user-space memory regions
+enum : VAddr {
+ /// Where the application text, data and bss reside.
+ PROCESS_IMAGE_VADDR = 0x00100000,
+ PROCESS_IMAGE_MAX_SIZE = 0x03F00000,
+ PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE,
+
+ /// Area where IPC buffers are mapped onto.
+ IPC_MAPPING_VADDR = 0x04000000,
+ IPC_MAPPING_SIZE = 0x04000000,
+ IPC_MAPPING_VADDR_END = IPC_MAPPING_VADDR + IPC_MAPPING_SIZE,
+
+ /// Application heap (includes stack).
+ HEAP_VADDR = 0x08000000,
+ HEAP_SIZE = 0x08000000,
+ HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE,
+
+ /// Area where shared memory buffers are mapped onto.
+ SHARED_MEMORY_VADDR = 0x10000000,
+ SHARED_MEMORY_SIZE = 0x04000000,
+ SHARED_MEMORY_VADDR_END = SHARED_MEMORY_VADDR + SHARED_MEMORY_SIZE,
+
+ /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical memory.
+ LINEAR_HEAP_VADDR = 0x14000000,
+ LINEAR_HEAP_SIZE = 0x08000000,
+ LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE,
+
+ /// Maps 1:1 to the IO register area.
+ IO_AREA_VADDR = 0x1EC00000,
+ IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE,
+
+ /// Maps 1:1 to VRAM.
+ VRAM_VADDR = 0x1F000000,
+ VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE,
+
+ /// Maps 1:1 to DSP memory.
+ DSP_RAM_VADDR = 0x1FF00000,
+ DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE,
+
+ /// Read-only page containing kernel and system configuration values.
+ CONFIG_MEMORY_VADDR = 0x1FF80000,
+ CONFIG_MEMORY_SIZE = 0x00001000,
+ CONFIG_MEMORY_VADDR_END = CONFIG_MEMORY_VADDR + CONFIG_MEMORY_SIZE,
+
+ /// Usually read-only page containing mostly values read from hardware.
+ SHARED_PAGE_VADDR = 0x1FF81000,
+ SHARED_PAGE_SIZE = 0x00001000,
+ SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE,
+
+ // TODO(yuriks): The size of this area is dynamic, the kernel grows
+ // it as more and more threads are created. For now we'll just use a
+ // hardcoded value.
+ /// Area where TLS (Thread-Local Storage) buffers are allocated.
+ TLS_AREA_VADDR = 0x1FF82000,
+ TLS_AREA_SIZE = 0x00030000, // Each TLS buffer is 0x200 bytes, allows for 300 threads
+ TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE,
+};
+
+u8 Read8(VAddr addr);
+u16 Read16(VAddr addr);
+u32 Read32(VAddr addr);
+u64 Read64(VAddr addr);
+
+void Write8(VAddr addr, u8 data);
+void Write16(VAddr addr, u16 data);
+void Write32(VAddr addr, u32 data);
+void Write64(VAddr addr, u64 data);
+
+void WriteBlock(VAddr addr, const u8* data, size_t size);
+
+u8* GetPointer(VAddr virtual_address);
+
+/**
+ * Gets a pointer to the memory region beginning at the specified physical address.
+ *
+ * @note This is currently implemented using PhysicalToVirtualAddress().
+ */
+u8* GetPhysicalPointer(PAddr address);
+
+}
diff --git a/src/core/memory_setup.h b/src/core/memory_setup.h
new file mode 100644
index 000000000..46263495f
--- /dev/null
+++ b/src/core/memory_setup.h
@@ -0,0 +1,29 @@
+// Copyright 2015 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/common_types.h"
+
+namespace Memory {
+
+void InitMemoryMap();
+
+/**
+ * Maps an allocated buffer onto a region of the emulated process address space.
+ *
+ * @param base The address to start mapping at. Must be page-aligned.
+ * @param size The amount of bytes to map. Must be page-aligned.
+ * @param target Buffer with the memory backing the mapping. Must be of length at least `size`.
+ */
+void MapMemoryRegion(VAddr base, u32 size, u8* target);
+
+/**
+ * Maps a region of the emulated process address space as a IO region.
+ * @note Currently this can only be used to mark a region as being IO, since actual memory-mapped
+ * IO isn't yet supported.
+ */
+void MapIoRegion(VAddr base, u32 size);
+
+}
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index 1ea7cad07..6121df8e3 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -74,11 +74,11 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
// Information about internal vertex attributes
u32 vertex_attribute_sources[16];
boost::fill(vertex_attribute_sources, 0xdeadbeef);
- u32 vertex_attribute_strides[16];
- Regs::VertexAttributeFormat vertex_attribute_formats[16];
+ u32 vertex_attribute_strides[16] = {};
+ Regs::VertexAttributeFormat vertex_attribute_formats[16] = {};
- u32 vertex_attribute_elements[16];
- u32 vertex_attribute_element_size[16];
+ u32 vertex_attribute_elements[16] = {};
+ u32 vertex_attribute_element_size[16] = {};
// Setup attribute data from loaders
for (int loader = 0; loader < 12; ++loader) {
@@ -127,29 +127,31 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
input.attr[0].w = debug_token;
for (int i = 0; i < attribute_config.GetNumTotalAttributes(); ++i) {
+ // Load the default attribute if we're configured to do so, this data will be overwritten by the loader data if it's set
if (attribute_config.IsDefaultAttribute(i)) {
input.attr[i] = VertexShader::GetDefaultAttribute(i);
LOG_TRACE(HW_GPU, "Loaded default attribute %x for vertex %x (index %x): (%f, %f, %f, %f)",
i, vertex, index,
input.attr[i][0].ToFloat32(), input.attr[i][1].ToFloat32(),
input.attr[i][2].ToFloat32(), input.attr[i][3].ToFloat32());
- } else {
- for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) {
- const u8* srcdata = Memory::GetPhysicalPointer(vertex_attribute_sources[i] + vertex_attribute_strides[i] * vertex + comp * vertex_attribute_element_size[i]);
-
- const float srcval = (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::BYTE) ? *(s8*)srcdata :
- (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::UBYTE) ? *(u8*)srcdata :
- (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::SHORT) ? *(s16*)srcdata :
- *(float*)srcdata;
-
- input.attr[i][comp] = float24::FromFloat32(srcval);
- LOG_TRACE(HW_GPU, "Loaded component %x of attribute %x for vertex %x (index %x) from 0x%08x + 0x%08lx + 0x%04lx: %f",
- comp, i, vertex, index,
- attribute_config.GetPhysicalBaseAddress(),
- vertex_attribute_sources[i] - base_address,
- vertex_attribute_strides[i] * vertex + comp * vertex_attribute_element_size[i],
- input.attr[i][comp].ToFloat32());
- }
+ }
+
+ // Load per-vertex data from the loader arrays
+ for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) {
+ const u8* srcdata = Memory::GetPhysicalPointer(vertex_attribute_sources[i] + vertex_attribute_strides[i] * vertex + comp * vertex_attribute_element_size[i]);
+
+ const float srcval = (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::BYTE) ? *(s8*)srcdata :
+ (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::UBYTE) ? *(u8*)srcdata :
+ (vertex_attribute_formats[i] == Regs::VertexAttributeFormat::SHORT) ? *(s16*)srcdata :
+ *(float*)srcdata;
+
+ input.attr[i][comp] = float24::FromFloat32(srcval);
+ LOG_TRACE(HW_GPU, "Loaded component %x of attribute %x for vertex %x (index %x) from 0x%08x + 0x%08lx + 0x%04lx: %f",
+ comp, i, vertex, index,
+ attribute_config.GetPhysicalBaseAddress(),
+ vertex_attribute_sources[i] - base_address,
+ vertex_attribute_strides[i] * vertex + comp * vertex_attribute_element_size[i],
+ input.attr[i][comp].ToFloat32());
}
}
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index a53429716..e9bc7fb3b 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -16,8 +16,6 @@
#include "common/common_types.h"
#include "common/logging/log.h"
-#include "core/mem_map.h"
-
namespace Pica {
// Returns index corresponding to the Regs member labeled by field_name
@@ -616,7 +614,7 @@ struct Regs {
}
inline bool IsDefaultAttribute(int id) const {
- return (id >= 12) || (attribute_mask & (1 << id)) != 0;
+ return (id >= 12) || (attribute_mask & (1ULL << id)) != 0;
}
inline int GetNumTotalAttributes() const {
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index 02a08b20e..59eff48f9 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -9,6 +9,8 @@
#include "common/profiler.h"
#include "core/hw/gpu.h"
+#include "core/memory.h"
+
#include "debug_utils/debug_utils.h"
#include "math.h"
#include "color.h"
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 0c072120d..71ceb021b 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -5,7 +5,7 @@
#include "core/hw/gpu.h"
#include "core/hw/hw.h"
#include "core/hw/lcd.h"
-#include "core/mem_map.h"
+#include "core/memory.h"
#include "core/settings.h"
#include "common/emu_window.h"
diff --git a/src/video_core/vertex_shader.cpp b/src/video_core/vertex_shader.cpp
index 4734e546a..981d1a356 100644
--- a/src/video_core/vertex_shader.cpp
+++ b/src/video_core/vertex_shader.cpp
@@ -8,8 +8,6 @@
#include <common/file_util.h>
-#include <core/mem_map.h>
-
#include <nihstro/shader_bytecode.h>
#include "common/profiler.h"