summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x.travis-build.sh6
-rwxr-xr-x.travis-deps.sh4
-rwxr-xr-x.travis-upload.sh4
-rw-r--r--.travis.yml20
-rw-r--r--CMakeLists.txt13
-rw-r--r--README.md2
-rw-r--r--appveyor.yml16
-rw-r--r--src/citra_qt/debugger/profiler.cpp13
-rw-r--r--src/citra_qt/game_list.cpp8
-rw-r--r--src/common/file_util.cpp22
-rw-r--r--src/common/file_util.h7
-rw-r--r--src/common/logging/backend.cpp2
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp2719
-rw-r--r--src/core/arm/dyncom/arm_dyncom_trans.cpp2178
-rw-r--r--src/core/arm/dyncom/arm_dyncom_trans.h493
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp64
-rw-r--r--src/core/hle/applets/applet.cpp5
-rw-r--r--src/core/hle/applets/erreula.cpp72
-rw-r--r--src/core/hle/applets/erreula.h31
-rw-r--r--src/core/hle/kernel/session.h4
-rw-r--r--src/core/hle/kernel/thread.cpp57
-rw-r--r--src/core/hle/result.h25
-rw-r--r--src/core/hle/service/apt/apt.h8
-rw-r--r--src/core/hle/service/srv.cpp136
-rw-r--r--src/video_core/command_processor.cpp14
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp2
-rw-r--r--src/video_core/pica.h77
-rw-r--r--src/video_core/pica_state.h16
-rw-r--r--src/video_core/rasterizer.cpp96
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp102
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h38
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp58
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_state.h4
-rw-r--r--src/video_core/renderer_opengl/pica_to_gl.h1
36 files changed, 3465 insertions, 2864 deletions
diff --git a/.travis-build.sh b/.travis-build.sh
index 511df04ac..8440b4f5c 100755
--- a/.travis-build.sh
+++ b/.travis-build.sh
@@ -11,12 +11,12 @@ fi
#if OS is linux or is not set
if [ "$TRAVIS_OS_NAME" = "linux" -o -z "$TRAVIS_OS_NAME" ]; then
- export CC=gcc-5
- export CXX=g++-5
+ export CC=gcc-6
+ export CXX=g++-6
export PKG_CONFIG_PATH=$HOME/.local/lib/pkgconfig:$PKG_CONFIG_PATH
mkdir build && cd build
- cmake -DCITRA_FORCE_QT4=ON ..
+ cmake ..
make -j4
ctest -VV -C Release
diff --git a/.travis-deps.sh b/.travis-deps.sh
index 4a79feb70..10b69f5c4 100755
--- a/.travis-deps.sh
+++ b/.travis-deps.sh
@@ -5,8 +5,8 @@ set -x
#if OS is linux or is not set
if [ "$TRAVIS_OS_NAME" = "linux" -o -z "$TRAVIS_OS_NAME" ]; then
- export CC=gcc-5
- export CXX=g++-5
+ export CC=gcc-6
+ export CXX=g++-6
mkdir -p $HOME/.local
curl -L http://www.cmake.org/files/v3.1/cmake-3.1.0-Linux-i386.tar.gz \
diff --git a/.travis-upload.sh b/.travis-upload.sh
index d86775cb9..1ad8f5e5e 100755
--- a/.travis-upload.sh
+++ b/.travis-upload.sh
@@ -25,6 +25,10 @@ if [ "$TRAVIS_BRANCH" = "master" ]; then
dylibbundler -b -x "${REV_NAME}/citra" -cd -d "${REV_NAME}/libs" -p "@executable_path/libs/"
fi
+ # Copy documentation
+ cp license.txt "$REV_NAME"
+ cp README.md "$REV_NAME"
+
ARCHIVE_NAME="${REV_NAME}.tar.xz"
tar -cJvf "$ARCHIVE_NAME" "$REV_NAME"
lftp -c "open -u citra-builds,$BUILD_PASSWORD sftp://builds.citra-emu.org; set sftp:auto-confirm yes; put -O '$UPLOAD_DIR' '$ARCHIVE_NAME'"
diff --git a/.travis.yml b/.travis.yml
index 8d86baece..8be395770 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,22 +1,26 @@
-os:
- - linux
- - osx
-
language: cpp
+matrix:
+ include:
+ - os: linux
+ sudo: true
+ dist: trusty
+ - os: osx
+ sudo: false
+
env:
global:
- secure: "AXHFIafTmbGDsHD3mUVj5a4I397DQjti/WoqAJGUp2PglxTcc04BwxZ9Z+xLuf5N2Hs5r9ojAJLT8OGxJCLBDXzneQTNSqXbFuYSLbqrEAiIRlA9eRIotWCg+wYcO+5e8MKX+cHVKwiIWasUB21AtCdq6msh6Y3pUshZp212VPg="
-sudo: false
-
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- - gcc-5
- - g++-5
+ - gcc-6
+ - g++-6
+ - qt5-default
+ - libqt5opengl5-dev
- xorg-dev
- lib32stdc++6 # For CMake
- lftp # To upload builds
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f7b0af115..9a436b981 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,7 +40,6 @@ option(CITRA_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" OFF)
option(ENABLE_QT "Enable the Qt frontend" ON)
option(CITRA_USE_BUNDLED_QT "Download bundled Qt binaries" OFF)
-option(CITRA_FORCE_QT4 "Use Qt4 even if Qt5 is available." OFF)
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git/hooks/pre-commit)
message(STATUS "Copying pre-commit hook")
@@ -201,16 +200,8 @@ if (ENABLE_QT)
set(QT_PREFIX_HINT)
endif()
- if (NOT CITRA_FORCE_QT4)
- find_package(Qt5 COMPONENTS Widgets OpenGL ${QT_PREFIX_HINT})
- set(CITRA_QT_LIBS Qt5::Widgets Qt5::OpenGL)
- endif()
-
- if (CITRA_FORCE_QT4 OR NOT Qt5_FOUND)
- # Try to fallback to Qt4
- find_package(Qt4 REQUIRED COMPONENTS QtGui QtOpenGL ${QT_PREFIX_HINT})
- set(CITRA_QT_LIBS Qt4::QtGui Qt4::QtOpenGL)
- endif()
+ find_package(Qt5 REQUIRED COMPONENTS Widgets OpenGL ${QT_PREFIX_HINT})
+ set(CITRA_QT_LIBS Qt5::Widgets Qt5::OpenGL)
endif()
# This function should be passed a list of all files in a target. It will automatically generate
diff --git a/README.md b/README.md
index a27acbc15..5463763ad 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,8 @@ For development discussion, please join us @ #citra on freenode.
### Development
+Most of the development happens on GitHub. It's also where [our central repository](https://github.com/citra-emu/citra) is hosted.
+
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 fa4134384..e82bdf0cf 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -39,17 +39,15 @@ on_success:
# Where are these spaces coming from? Regardless, let's remove them
$BUILD_NAME = "citra-${GITDATE}-${GITREV}-windows-amd64.7z" -replace " ",""
$BUILD_NAME_NOQT = "citra-noqt-${GITDATE}-${GITREV}-windows-amd64.7z" -replace " ",""
- # Zip up the build folder
- 7z a $BUILD_NAME .\build\bin\release\*
- # Do a second archive with only the binaries
- 7z a $BUILD_NAME_NOQT .\build\bin\release\*.exe
+ # Zip up the build folder and documentation
+ 7z a $BUILD_NAME .\build\bin\release\* .\license.txt .\README.md
+ # Do a second archive with only the binaries (excludes dlls) and documentation
+ 7z a $BUILD_NAME_NOQT .\build\bin\release\*.exe .\license.txt .\README.md
- # Download winscp
- Invoke-WebRequest "http://iweb.dl.sourceforge.net/project/winscp/WinSCP/5.7.3/winscp573.zip" -OutFile "winscp573.zip"
- 7z e -y winscp573.zip
- # Upload to server
- .\WinSCP.com /command `
+ # Download WinSCP and upload to server
+ choco install winscp.portable
+ WinSCP.exe /command `
"option batch abort" `
"option confirm off" `
"open sftp://citra-builds:${env:BUILD_PASSWORD}@builds.citra-emu.org -hostkey=*" `
diff --git a/src/citra_qt/debugger/profiler.cpp b/src/citra_qt/debugger/profiler.cpp
index 585ac049a..17898f54b 100644
--- a/src/citra_qt/debugger/profiler.cpp
+++ b/src/citra_qt/debugger/profiler.cpp
@@ -151,8 +151,8 @@ private:
/// This timer is used to redraw the widget's contents continuously. To save resources, it only
/// runs while the widget is visible.
QTimer update_timer;
- /// Scale the coordinate system appropriately when physical DPI != logical DPI.
- qreal x_scale, y_scale;
+ /// Scale the coordinate system appropriately when dpi != 96.
+ qreal x_scale = 1.0, y_scale = 1.0;
};
#endif
@@ -222,15 +222,14 @@ MicroProfileWidget::MicroProfileWidget(QWidget* parent) : QWidget(parent) {
MicroProfileInitUI();
connect(&update_timer, SIGNAL(timeout()), SLOT(update()));
-
- QPainter painter(this);
- x_scale = qreal(painter.device()->physicalDpiX()) / qreal(painter.device()->logicalDpiX());
- y_scale = qreal(painter.device()->physicalDpiY()) / qreal(painter.device()->logicalDpiY());
}
void MicroProfileWidget::paintEvent(QPaintEvent* ev) {
QPainter painter(this);
+ // The units used by Microprofile for drawing are based in pixels on a 96 dpi display.
+ x_scale = qreal(painter.device()->logicalDpiX()) / 96.0;
+ y_scale = qreal(painter.device()->logicalDpiY()) / 96.0;
painter.scale(x_scale, y_scale);
painter.setBackground(Qt::black);
@@ -241,7 +240,7 @@ void MicroProfileWidget::paintEvent(QPaintEvent* ev) {
painter.setFont(font);
mp_painter = &painter;
- MicroProfileDraw(rect().width(), rect().height());
+ MicroProfileDraw(rect().width() / x_scale, rect().height() / y_scale);
mp_painter = nullptr;
}
diff --git a/src/citra_qt/game_list.cpp b/src/citra_qt/game_list.cpp
index 15484fae3..1910da3ac 100644
--- a/src/citra_qt/game_list.cpp
+++ b/src/citra_qt/game_list.cpp
@@ -120,11 +120,9 @@ void GameList::LoadInterfaceLayout()
void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion)
{
- const auto callback = [&](unsigned* num_entries_out,
- const std::string& directory,
- const std::string& virtual_name,
- unsigned int recursion) -> bool {
-
+ const auto callback = [this, recursion](unsigned* num_entries_out,
+ const std::string& directory,
+ const std::string& virtual_name) -> bool {
std::string physical_name = directory + DIR_SEP + virtual_name;
if (stop_processing)
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 17af7c385..84fe95c8c 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -434,7 +434,7 @@ bool CreateEmptyFile(const std::string &filename)
}
-bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directory, DirectoryEntryCallable callback, unsigned int recursion)
+bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directory, DirectoryEntryCallable callback)
{
LOG_TRACE(Common_Filesystem, "directory %s", directory.c_str());
@@ -472,7 +472,7 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directo
continue;
unsigned ret_entries = 0;
- if (!callback(&ret_entries, directory, virtual_name, recursion)) {
+ if (!callback(&ret_entries, directory, virtual_name)) {
callback_error = true;
break;
}
@@ -497,10 +497,9 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directo
unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry, unsigned int recursion)
{
- const auto callback = [&parent_entry](unsigned* num_entries_out,
- const std::string& directory,
- const std::string& virtual_name,
- unsigned int recursion) -> bool {
+ const auto callback = [recursion, &parent_entry](unsigned* num_entries_out,
+ const std::string& directory,
+ const std::string& virtual_name) -> bool {
FSTEntry entry;
entry.virtualName = virtual_name;
entry.physicalName = directory + DIR_SEP + virtual_name;
@@ -526,16 +525,15 @@ unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry,
};
unsigned num_entries;
- return ForeachDirectoryEntry(&num_entries, directory, callback, recursion) ? num_entries : 0;
+ return ForeachDirectoryEntry(&num_entries, directory, callback) ? num_entries : 0;
}
bool DeleteDirRecursively(const std::string &directory, unsigned int recursion)
{
- const static auto callback = [](unsigned* num_entries_out,
- const std::string& directory,
- const std::string& virtual_name,
- unsigned int recursion) -> bool {
+ const auto callback = [recursion](unsigned* num_entries_out,
+ const std::string& directory,
+ const std::string& virtual_name) -> bool {
std::string new_path = directory + DIR_SEP_CHR + virtual_name;
if (IsDirectory(new_path)) {
@@ -546,7 +544,7 @@ bool DeleteDirRecursively(const std::string &directory, unsigned int recursion)
return Delete(new_path);
};
- if (!ForeachDirectoryEntry(nullptr, directory, callback, recursion))
+ if (!ForeachDirectoryEntry(nullptr, directory, callback))
return false;
// Delete the outermost directory
diff --git a/src/common/file_util.h b/src/common/file_util.h
index 32ae2dc57..7ad7ee829 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -105,13 +105,11 @@ bool CreateEmptyFile(const std::string &filename);
* @param num_entries_out to be assigned by the callable with the number of iterated directory entries, never null
* @param directory the path to the enclosing directory
* @param virtual_name the entry name, without any preceding directory info
- * @param recursion Number of children directory to read before giving up
* @return whether handling the entry succeeded
*/
using DirectoryEntryCallable = std::function<bool(unsigned* num_entries_out,
const std::string& directory,
- const std::string& virtual_name,
- unsigned int recursion)>;
+ const std::string& virtual_name)>;
/**
* Scans a directory, calling the callback for each file/directory contained within.
@@ -119,10 +117,9 @@ using DirectoryEntryCallable = std::function<bool(unsigned* num_entries_out,
* @param num_entries_out assigned by the function with the number of iterated directory entries, can be null
* @param directory the directory to scan
* @param callback The callback which will be called for each entry
- * @param recursion Number of children directories to read before giving up
* @return whether scanning the directory succeeded
*/
-bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directory, DirectoryEntryCallable callback, unsigned int recursion = 0);
+bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directory, DirectoryEntryCallable callback);
/**
* Scans the directory tree, storing the results.
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index d7008fc66..0b2fabec9 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -117,7 +117,7 @@ Entry CreateEntry(Class log_class, Level log_level,
vsnprintf(formatting_buffer.data(), formatting_buffer.size(), format, args);
entry.message = std::string(formatting_buffer.data());
- return std::move(entry);
+ return entry;
}
static Filter* filter = nullptr;
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 7d267fdcf..0773339a9 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -5,6 +5,7 @@ set(SRCS
arm/dyncom/arm_dyncom_dec.cpp
arm/dyncom/arm_dyncom_interpreter.cpp
arm/dyncom/arm_dyncom_thumb.cpp
+ arm/dyncom/arm_dyncom_trans.cpp
arm/skyeye_common/armstate.cpp
arm/skyeye_common/armsupp.cpp
arm/skyeye_common/vfp/vfp.cpp
@@ -26,6 +27,7 @@ set(SRCS
hle/config_mem.cpp
hle/hle.cpp
hle/applets/applet.cpp
+ hle/applets/erreula.cpp
hle/applets/mii_selector.cpp
hle/applets/swkbd.cpp
hle/kernel/address_arbiter.cpp
@@ -142,6 +144,7 @@ set(HEADERS
arm/dyncom/arm_dyncom_interpreter.h
arm/dyncom/arm_dyncom_run.h
arm/dyncom/arm_dyncom_thumb.h
+ arm/dyncom/arm_dyncom_trans.h
arm/skyeye_common/arm_regformat.h
arm/skyeye_common/armstate.h
arm/skyeye_common/armsupp.h
@@ -166,6 +169,7 @@ set(HEADERS
hle/function_wrappers.h
hle/hle.h
hle/applets/applet.h
+ hle/applets/erreula.h
hle/applets/mii_selector.h
hle/applets/swkbd.h
hle/kernel/address_arbiter.h
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index cfc67287f..01d5d478e 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -17,6 +17,7 @@
#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_trans.h"
#include "core/arm/dyncom/arm_dyncom_run.h"
#include "core/arm/skyeye_common/armstate.h"
#include "core/arm/skyeye_common/armsupp.h"
@@ -24,18 +25,6 @@
#include "core/gdbstub/gdbstub.h"
-enum {
- COND = (1 << 0),
- NON_BRANCH = (1 << 1),
- DIRECT_BRANCH = (1 << 2),
- INDIRECT_BRANCH = (1 << 3),
- CALL = (1 << 4),
- RET = (1 << 5),
- END_OF_PAGE = (1 << 6),
- THUMB = (1 << 7),
- SINGLE_STEP = (1 << 8)
-};
-
#define RM BITS(sht_oper, 0, 3)
#define RS BITS(sht_oper, 8, 11)
@@ -46,8 +35,6 @@ enum {
#define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32)
#define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32)
-typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper);
-
static bool CondPassed(const ARMul_State* cpu, unsigned int cond) {
const bool n_flag = cpu->NFlag != 0;
const bool z_flag = cpu->ZFlag != 0;
@@ -245,12 +232,6 @@ static unsigned int DPO(RotateRightByRegister)(ARMul_State* cpu, unsigned int sh
return shifter_operand;
}
-typedef void (*get_addr_fp_t)(ARMul_State *cpu, unsigned int inst, unsigned int &virt_addr);
-
-struct ldst_inst {
- unsigned int inst;
- get_addr_fp_t get_addr;
-};
#define DEBUG_MSG LOG_DEBUG(Core_ARM11, "inst is %x", inst); CITRA_IGNORE_EXIT(0)
#define LnSWoUB(s) glue(LnSWoUB, s)
@@ -668,479 +649,7 @@ static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst, u
virt_addr = addr;
}
-struct arm_inst {
- unsigned int idx;
- unsigned int cond;
- int br;
- char component[0];
-};
-
-struct generic_arm_inst {
- u32 Ra;
- u32 Rm;
- u32 Rn;
- u32 Rd;
- u8 op1;
- u8 op2;
-};
-
-struct adc_inst {
- unsigned int I;
- unsigned int S;
- unsigned int Rn;
- unsigned int Rd;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct add_inst {
- unsigned int I;
- unsigned int S;
- unsigned int Rn;
- unsigned int Rd;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct orr_inst {
- unsigned int I;
- unsigned int S;
- unsigned int Rn;
- unsigned int Rd;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct and_inst {
- unsigned int I;
- unsigned int S;
- unsigned int Rn;
- unsigned int Rd;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct eor_inst {
- unsigned int I;
- unsigned int S;
- unsigned int Rn;
- unsigned int Rd;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct bbl_inst {
- unsigned int L;
- int signed_immed_24;
- unsigned int next_addr;
- unsigned int jmp_addr;
-};
-
-struct bx_inst {
- unsigned int Rm;
-};
-
-struct blx_inst {
- union {
- s32 signed_immed_24;
- u32 Rm;
- } val;
- unsigned int inst;
-};
-
-struct clz_inst {
- unsigned int Rm;
- unsigned int Rd;
-};
-
-struct cps_inst {
- unsigned int imod0;
- unsigned int imod1;
- unsigned int mmod;
- unsigned int A, I, F;
- unsigned int mode;
-};
-
-struct clrex_inst {
-};
-
-struct cpy_inst {
- unsigned int Rm;
- unsigned int Rd;
-};
-
-struct bic_inst {
- unsigned int I;
- unsigned int S;
- unsigned int Rn;
- unsigned int Rd;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct sub_inst {
- unsigned int I;
- unsigned int S;
- unsigned int Rn;
- unsigned int Rd;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct tst_inst {
- unsigned int I;
- unsigned int S;
- unsigned int Rn;
- unsigned int Rd;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct cmn_inst {
- unsigned int I;
- unsigned int Rn;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct teq_inst {
- unsigned int I;
- unsigned int Rn;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct stm_inst {
- unsigned int inst;
-};
-
-struct bkpt_inst {
- u32 imm;
-};
-
-struct stc_inst {
-};
-
-struct ldc_inst {
-};
-
-struct swi_inst {
- unsigned int num;
-};
-
-struct cmp_inst {
- unsigned int I;
- unsigned int Rn;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct mov_inst {
- unsigned int I;
- unsigned int S;
- unsigned int Rd;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct mvn_inst {
- unsigned int I;
- unsigned int S;
- unsigned int Rd;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct rev_inst {
- unsigned int Rd;
- unsigned int Rm;
- unsigned int op1;
- unsigned int op2;
-};
-
-struct rsb_inst {
- unsigned int I;
- unsigned int S;
- unsigned int Rn;
- unsigned int Rd;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct rsc_inst {
- unsigned int I;
- unsigned int S;
- unsigned int Rn;
- unsigned int Rd;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct sbc_inst {
- unsigned int I;
- unsigned int S;
- unsigned int Rn;
- unsigned int Rd;
- unsigned int shifter_operand;
- shtop_fp_t shtop_func;
-};
-
-struct mul_inst {
- unsigned int S;
- unsigned int Rd;
- unsigned int Rs;
- unsigned int Rm;
-};
-
-struct smul_inst {
- unsigned int Rd;
- unsigned int Rs;
- unsigned int Rm;
- unsigned int x;
- unsigned int y;
-};
-
-struct umull_inst {
- unsigned int S;
- unsigned int RdHi;
- unsigned int RdLo;
- unsigned int Rs;
- unsigned int Rm;
-};
-
-struct smlad_inst {
- unsigned int m;
- unsigned int Rm;
- unsigned int Rd;
- unsigned int Ra;
- unsigned int Rn;
- unsigned int op1;
- unsigned int op2;
-};
-
-struct smla_inst {
- unsigned int x;
- unsigned int y;
- unsigned int Rm;
- unsigned int Rd;
- unsigned int Rs;
- unsigned int Rn;
-};
-
-struct smlalxy_inst {
- unsigned int x;
- unsigned int y;
- unsigned int RdLo;
- unsigned int RdHi;
- unsigned int Rm;
- unsigned int Rn;
-};
-
-struct ssat_inst {
- unsigned int Rn;
- unsigned int Rd;
- unsigned int imm5;
- unsigned int sat_imm;
- unsigned int shift_type;
-};
-
-struct umaal_inst {
- unsigned int Rn;
- unsigned int Rm;
- unsigned int RdHi;
- unsigned int RdLo;
-};
-
-struct umlal_inst {
- unsigned int S;
- unsigned int Rm;
- unsigned int Rs;
- unsigned int RdHi;
- unsigned int RdLo;
-};
-
-struct smlal_inst {
- unsigned int S;
- unsigned int Rm;
- unsigned int Rs;
- unsigned int RdHi;
- unsigned int RdLo;
-};
-
-struct smlald_inst {
- unsigned int RdLo;
- unsigned int RdHi;
- unsigned int Rm;
- unsigned int Rn;
- unsigned int swap;
- unsigned int op1;
- unsigned int op2;
-};
-
-struct mla_inst {
- unsigned int S;
- unsigned int Rn;
- unsigned int Rd;
- unsigned int Rs;
- unsigned int Rm;
-};
-
-struct mrc_inst {
- unsigned int opcode_1;
- unsigned int opcode_2;
- unsigned int cp_num;
- unsigned int crn;
- unsigned int crm;
- unsigned int Rd;
- unsigned int inst;
-};
-
-struct mcr_inst {
- unsigned int opcode_1;
- unsigned int opcode_2;
- unsigned int cp_num;
- unsigned int crn;
- unsigned int crm;
- unsigned int Rd;
- unsigned int inst;
-};
-
-struct mcrr_inst {
- unsigned int opcode_1;
- unsigned int cp_num;
- unsigned int crm;
- unsigned int rt;
- unsigned int rt2;
-};
-
-struct mrs_inst {
- unsigned int R;
- unsigned int Rd;
-};
-
-struct msr_inst {
- unsigned int field_mask;
- unsigned int R;
- unsigned int inst;
-};
-
-struct pld_inst {
-};
-
-struct sxtb_inst {
- unsigned int Rd;
- unsigned int Rm;
- unsigned int rotate;
-};
-
-struct sxtab_inst {
- unsigned int Rd;
- unsigned int Rn;
- unsigned int Rm;
- unsigned rotate;
-};
-
-struct sxtah_inst {
- unsigned int Rd;
- unsigned int Rn;
- unsigned int Rm;
- unsigned int rotate;
-};
-
-struct sxth_inst {
- unsigned int Rd;
- unsigned int Rm;
- unsigned int rotate;
-};
-
-struct uxtab_inst {
- unsigned int Rn;
- unsigned int Rd;
- unsigned int rotate;
- unsigned int Rm;
-};
-
-struct uxtah_inst {
- unsigned int Rn;
- unsigned int Rd;
- unsigned int rotate;
- unsigned int Rm;
-};
-
-struct uxth_inst {
- unsigned int Rd;
- unsigned int Rm;
- unsigned int rotate;
-};
-
-struct cdp_inst {
- unsigned int opcode_1;
- unsigned int CRn;
- unsigned int CRd;
- unsigned int cp_num;
- unsigned int opcode_2;
- unsigned int CRm;
- unsigned int inst;
-};
-
-struct uxtb_inst {
- unsigned int Rd;
- unsigned int Rm;
- unsigned int rotate;
-};
-
-struct swp_inst {
- unsigned int Rn;
- unsigned int Rd;
- unsigned int Rm;
-};
-
-struct setend_inst {
- unsigned int set_bigend;
-};
-
-struct b_2_thumb {
- unsigned int imm;
-};
-struct b_cond_thumb {
- unsigned int imm;
- unsigned int cond;
-};
-
-struct bl_1_thumb {
- unsigned int imm;
-};
-struct bl_2_thumb {
- unsigned int imm;
-};
-struct blx_1_thumb {
- unsigned int imm;
- unsigned int instr;
-};
-
-struct pkh_inst {
- unsigned int Rm;
- unsigned int Rn;
- unsigned int Rd;
- unsigned char imm;
-};
-
-typedef arm_inst * ARM_INST_PTR;
-
-#define CACHE_BUFFER_SIZE (64 * 1024 * 2000)
-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) {
- LOG_ERROR(Core_ARM11, "inst_buf is full");
- CITRA_IGNORE_EXIT(-1);
- }
- return (void *)&inst_buf[start];
-}
-
-static shtop_fp_t get_shtop(unsigned int inst) {
+shtop_fp_t GetShifterOp(unsigned int inst) {
if (BIT(inst, 25)) {
return DPO(Immediate);
} else if (BITS(inst, 4, 11) == 0) {
@@ -1165,7 +674,7 @@ static shtop_fp_t get_shtop(unsigned int inst) {
return nullptr;
}
-static get_addr_fp_t get_calc_addr_op(unsigned int inst) {
+get_addr_fp_t GetAddressingOp(unsigned int inst) {
if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 0) {
return LnSWoUB(ImmediateOffset);
} else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) {
@@ -1208,2201 +717,21 @@ static get_addr_fp_t get_calc_addr_op(unsigned int inst) {
return nullptr;
}
-#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s)
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst));
- adc_inst *inst_cream = (adc_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- if (inst_cream->Rd == 15)
- inst_base->br = INDIRECT_BRANCH;
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(add_inst));
- add_inst *inst_cream = (add_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- if (inst_cream->Rd == 15)
- inst_base->br = INDIRECT_BRANCH;
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(and_inst));
- and_inst *inst_cream = (and_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- if (inst_cream->Rd == 15)
- inst_base->br = INDIRECT_BRANCH;
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index)
-{
- #define POSBRANCH ((inst & 0x7fffff) << 2)
- #define NEGBRANCH ((0xff000000 |(inst & 0xffffff)) << 2)
-
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst));
- bbl_inst *inst_cream = (bbl_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = DIRECT_BRANCH;
-
- if (BIT(inst, 24))
- inst_base->br = CALL;
- if (BITS(inst, 28, 31) <= 0xe)
- inst_base->br |= COND;
-
- inst_cream->L = BIT(inst, 24);
- inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH;
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bic_inst));
- bic_inst *inst_cream = (bic_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- if (inst_cream->Rd == 15)
- inst_base->br = INDIRECT_BRANCH;
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bkpt_inst));
- bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->imm = (BITS(inst, 8, 19) << 4) | BITS(inst, 0, 3);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_inst));
- blx_inst *inst_cream = (blx_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = INDIRECT_BRANCH;
-
- inst_cream->inst = inst;
- if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
- inst_cream->val.Rm = BITS(inst, 0, 3);
- } else {
- inst_cream->val.signed_immed_24 = BITS(inst, 0, 23);
- }
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst));
- bx_inst *inst_cream = (bx_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = INDIRECT_BRANCH;
-
- inst_cream->Rm = BITS(inst, 0, 3);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(bx)(inst, index);
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index) {
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst));
- cdp_inst *inst_cream = (cdp_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->CRm = BITS(inst, 0, 3);
- inst_cream->CRd = BITS(inst, 12, 15);
- inst_cream->CRn = BITS(inst, 16, 19);
- inst_cream->cp_num = BITS(inst, 8, 11);
- inst_cream->opcode_2 = BITS(inst, 5, 7);
- inst_cream->opcode_1 = BITS(inst, 20, 23);
- inst_cream->inst = inst;
-
- LOG_TRACE(Core_ARM11, "inst %x index %x", inst, index);
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clrex_inst));
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clz_inst));
- clz_inst *inst_cream = (clz_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rd = BITS(inst, 12, 15);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmn_inst));
- cmn_inst *inst_cream = (cmn_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmp_inst));
- cmp_inst *inst_cream = (cmp_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cps_inst));
- cps_inst *inst_cream = (cps_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->imod0 = BIT(inst, 18);
- inst_cream->imod1 = BIT(inst, 19);
- inst_cream->mmod = BIT(inst, 17);
- inst_cream->A = BIT(inst, 8);
- inst_cream->I = BIT(inst, 7);
- inst_cream->F = BIT(inst, 6);
- inst_cream->mode = BITS(inst, 0, 4);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst));
- mov_inst *inst_cream = (mov_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- if (inst_cream->Rd == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(eor_inst));
- eor_inst *inst_cream = (eor_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- if (inst_cream->Rd == 15)
- inst_base->br = INDIRECT_BRANCH;
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldc_inst));
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
-
- if (BIT(inst, 15)) {
- inst_base->br = INDIRECT_BRANCH;
- }
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst));
- sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->rotate = BITS(inst, 10, 11);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
-
- if (BITS(inst, 12, 15) == 15)
- inst_base->br = INDIRECT_BRANCH;
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
-
- if (BITS(inst, 12, 15) == 15)
- inst_base->br = INDIRECT_BRANCH;
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst));
- uxth_inst *inst_cream = (uxth_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->rotate = BITS(inst, 10, 11);
- inst_cream->Rm = BITS(inst, 0, 3);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtah_inst));
- uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->rotate = BITS(inst, 10, 11);
- inst_cream->Rm = BITS(inst, 0, 3);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index)
-{
- arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- if (BITS(inst, 25, 27) == 2) {
- inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
- } else if (BITS(inst, 25, 27) == 3) {
- inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed);
- } else {
- DEBUG_MSG;
- }
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
- generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = (BITS(inst, 12, 15) == 15) ? INDIRECT_BRANCH : NON_BRANCH; // Branch if dest is R15
-
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(ldrex)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexh)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(ldrex)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexd)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(ldrex)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index)
-{
- arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
+// Specialized for LDRT, LDRBT, STRT, and STRBT, which have specific addressing mode requirements
+get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst) {
if (BITS(inst, 25, 27) == 2) {
- inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
- } else if (BITS(inst, 25, 27) == 3) {
- inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed);
- } else {
- // Reaching this would indicate the thumb version
- // of this instruction, however the 3DS CPU doesn't
- // support this variant (the 3DS CPU is only ARMv6K,
- // while this variant is added in ARMv6T2).
- // So it's sufficient for citra to not implement this.
- DEBUG_MSG;
- }
-
- if (BITS(inst, 12, 15) == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mcr_inst));
- mcr_inst *inst_cream = (mcr_inst *)inst_base->component;
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->crn = BITS(inst, 16, 19);
- inst_cream->crm = BITS(inst, 0, 3);
- inst_cream->opcode_1 = BITS(inst, 21, 23);
- inst_cream->opcode_2 = BITS(inst, 5, 7);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->cp_num = BITS(inst, 8, 11);
- inst_cream->inst = inst;
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcrr_inst));
- mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->crm = BITS(inst, 0, 3);
- inst_cream->opcode_1 = BITS(inst, 4, 7);
- inst_cream->cp_num = BITS(inst, 8, 11);
- inst_cream->rt = BITS(inst, 12, 15);
- inst_cream->rt2 = BITS(inst, 16, 19);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst));
- mla_inst *inst_cream = (mla_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rn = BITS(inst, 12, 15);
- inst_cream->Rd = BITS(inst, 16, 19);
- inst_cream->Rs = BITS(inst, 8, 11);
- inst_cream->Rm = BITS(inst, 0, 3);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst));
- mov_inst *inst_cream = (mov_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- if (inst_cream->Rd == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrc_inst));
- mrc_inst *inst_cream = (mrc_inst *)inst_base->component;
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->crn = BITS(inst, 16, 19);
- inst_cream->crm = BITS(inst, 0, 3);
- inst_cream->opcode_1 = BITS(inst, 21, 23);
- inst_cream->opcode_2 = BITS(inst, 5, 7);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->cp_num = BITS(inst, 8, 11);
- inst_cream->inst = inst;
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(mcrr)(inst, index);
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst));
- mrs_inst *inst_cream = (mrs_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->R = BIT(inst, 22);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(msr_inst));
- msr_inst *inst_cream = (msr_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->field_mask = BITS(inst, 16, 19);
- inst_cream->R = BIT(inst, 22);
- inst_cream->inst = inst;
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mul_inst));
- mul_inst *inst_cream = (mul_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rs = BITS(inst, 8, 11);
- inst_cream->Rd = BITS(inst, 16, 19);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mvn_inst));
- mvn_inst *inst_cream = (mvn_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- if (inst_cream->Rd == 15) {
- inst_base->br = INDIRECT_BRANCH;
- }
- return inst_base;
-
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(orr_inst));
- orr_inst *inst_cream = (orr_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- if (inst_cream->Rd == 15)
- inst_base->br = INDIRECT_BRANCH;
-
- 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;
-
- 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));
- pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->imm = BITS(inst, 7, 11);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(pkhbt)(inst, index);
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst));
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->op1 = BITS(inst, 21, 22);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(qadd)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(qadd)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(qadd)(inst, index);
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->op1 = BITS(inst, 20, 21);
- inst_cream->op2 = BITS(inst, 5, 7);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(qadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(qadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(qadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(qadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(qadd8)(inst, index);
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst));
- rev_inst* const inst_cream = (rev_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->op1 = BITS(inst, 20, 22);
- inst_cream->op2 = BITS(inst, 5, 7);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(rev)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(rev)(inst, index);
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
-
- inst_base->cond = AL;
- inst_base->idx = index;
- inst_base->br = INDIRECT_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsb_inst));
- rsb_inst *inst_cream = (rsb_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- if (inst_cream->Rd == 15)
- inst_base->br = INDIRECT_BRANCH;
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsc_inst));
- rsc_inst *inst_cream = (rsc_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- if (inst_cream->Rd == 15)
- inst_base->br = INDIRECT_BRANCH;
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->op1 = BITS(inst, 20, 21);
- inst_cream->op2 = BITS(inst, 5, 7);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(sadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(sadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(sadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(sadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(sadd8)(inst, index);
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sbc_inst));
- sbc_inst *inst_cream = (sbc_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- if (inst_cream->Rd == 15)
- inst_base->br = INDIRECT_BRANCH;
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->op1 = BITS(inst, 20, 22);
- inst_cream->op2 = BITS(inst, 5, 7);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(setend_inst));
- setend_inst* const inst_cream = (setend_inst*)inst_base->component;
-
- inst_base->cond = AL;
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->set_bigend = BIT(inst, 9);
-
- 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;
-
- 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));
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->op1 = BITS(inst, 20, 21);
- inst_cream->op2 = BITS(inst, 5, 7);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(shadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(shadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(shadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(shadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(shadd8)(inst, index);
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst));
- smla_inst *inst_cream = (smla_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->x = BIT(inst, 5);
- inst_cream->y = BIT(inst, 6);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rs = BITS(inst, 8, 11);
- inst_cream->Rd = BITS(inst, 16, 19);
- inst_cream->Rn = BITS(inst, 12, 15);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
- smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->m = BIT(inst, 5);
- inst_cream->Rn = BITS(inst, 0, 3);
- inst_cream->Rm = BITS(inst, 8, 11);
- inst_cream->Rd = BITS(inst, 16, 19);
- inst_cream->Ra = BITS(inst, 12, 15);
- inst_cream->op1 = BITS(inst, 20, 22);
- inst_cream->op2 = BITS(inst, 5, 7);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(smlad)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(smlad)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsd)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(smlad)(inst, index);
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst));
- umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rs = BITS(inst, 8, 11);
- inst_cream->RdHi = BITS(inst, 16, 19);
- inst_cream->RdLo = BITS(inst, 12, 15);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlalxy_inst));
- smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->x = BIT(inst, 5);
- inst_cream->y = BIT(inst, 6);
- inst_cream->RdLo = BITS(inst, 12, 15);
- inst_cream->RdHi = BITS(inst, 16, 19);
- inst_cream->Rn = BITS(inst, 0, 4);
- inst_cream->Rm = BITS(inst, 8, 11);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
- smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Ra = BITS(inst, 12, 15);
- inst_cream->Rm = BITS(inst, 8, 11);
- inst_cream->Rn = BITS(inst, 0, 3);
- inst_cream->Rd = BITS(inst, 16, 19);
- inst_cream->m = BIT(inst, 6);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlald_inst));
- smlald_inst* const inst_cream = (smlald_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rm = BITS(inst, 8, 11);
- inst_cream->Rn = BITS(inst, 0, 3);
- inst_cream->RdLo = BITS(inst, 12, 15);
- inst_cream->RdHi = BITS(inst, 16, 19);
- inst_cream->swap = BIT(inst, 5);
- inst_cream->op1 = BITS(inst, 20, 22);
- inst_cream->op2 = BITS(inst, 5, 7);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(smlald)(inst, index);
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
- smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->m = BIT(inst, 5);
- inst_cream->Ra = BITS(inst, 12, 15);
- inst_cream->Rm = BITS(inst, 8, 11);
- inst_cream->Rn = BITS(inst, 0, 3);
- inst_cream->Rd = BITS(inst, 16, 19);
- inst_cream->op1 = BITS(inst, 20, 22);
- inst_cream->op2 = BITS(inst, 5, 7);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smmls)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(smmla)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(smmla)(inst, index);
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smul_inst));
- smul_inst *inst_cream = (smul_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rd = BITS(inst, 16, 19);
- inst_cream->Rs = BITS(inst, 8, 11);
- inst_cream->Rm = BITS(inst, 0, 3);
-
- inst_cream->x = BIT(inst, 5);
- inst_cream->y = BIT(inst, 6);
-
- return inst_base;
-
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst));
- umull_inst *inst_cream = (umull_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rs = BITS(inst, 8, 11);
- inst_cream->RdHi = BITS(inst, 16, 19);
- inst_cream->RdLo = BITS(inst, 12, 15);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
- smlad_inst *inst_cream = (smlad_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->m = BIT(inst, 6);
- inst_cream->Rm = BITS(inst, 8, 11);
- inst_cream->Rn = BITS(inst, 0, 3);
- inst_cream->Rd = BITS(inst, 16, 19);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
-
- inst_base->cond = AL;
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst));
- ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rn = BITS(inst, 0, 3);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->imm5 = BITS(inst, 7, 11);
- inst_cream->sat_imm = BITS(inst, 16, 20);
- inst_cream->shift_type = BIT(inst, 6);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst));
- ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rn = BITS(inst, 0, 3);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->sat_imm = BITS(inst, 16, 19);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(stc_inst));
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst));
- sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->rotate = BITS(inst, 10, 11);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst));
- uxth_inst *inst_cream = (uxth_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->rotate = BITS(inst, 10, 11);
- inst_cream->Rm = BITS(inst, 0, 3);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst));
- uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->rotate = BITS(inst, 10, 11);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rn = BITS(inst, 16, 19);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index)
-{
- arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
-
- if (BITS(inst, 25, 27) == 2) {
- inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
- } else if (BITS(inst, 25, 27) == 3) {
- inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed);
- } else {
- DEBUG_MSG;
- }
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
- generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->Rm = BITS(inst, 0, 3);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(strex)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(strexh)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(strex)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(strexd)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(strex)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- inst_cream->get_addr = get_calc_addr_op(inst);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index)
-{
- arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
- ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->inst = inst;
- if (BITS(inst, 25, 27) == 2) {
- inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
+ return LnSWoUB(ImmediatePostIndexed);
} else if (BITS(inst, 25, 27) == 3) {
- inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed);
- } else {
- // Reaching this would indicate the thumb version
- // of this instruction, however the 3DS CPU doesn't
- // support this variant (the 3DS CPU is only ARMv6K,
- // while this variant is added in ARMv6T2).
- // So it's sufficient for citra to not implement this.
- DEBUG_MSG;
+ return LnSWoUB(ScaledRegisterPostIndexed);
}
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sub_inst));
- sub_inst *inst_cream = (sub_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- if (inst_cream->Rd == 15)
- inst_base->br = INDIRECT_BRANCH;
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swi_inst));
- swi_inst *inst_cream = (swi_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->num = BITS(inst, 0, 23);
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst));
- swp_inst *inst_cream = (swp_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->Rm = BITS(inst, 0, 3);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst));
- swp_inst *inst_cream = (swp_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->Rm = BITS(inst, 0, 3);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index){
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst));
- sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->rotate = BITS(inst, 10, 11);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rn = BITS(inst, 16, 19);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst));
- sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->rotate = BITS(inst, 10, 11);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(sxtab16)(inst, index);
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index) {
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtah_inst));
- sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->rotate = BITS(inst, 10, 11);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rn = BITS(inst, 16, 19);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(teq_inst));
- teq_inst *inst_cream = (teq_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(tst_inst));
- tst_inst *inst_cream = (tst_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->I = BIT(inst, 25);
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->shifter_operand = BITS(inst, 0, 11);
- inst_cream->shtop_func = get_shtop(inst);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->op1 = BITS(inst, 20, 21);
- inst_cream->op2 = BITS(inst, 5, 7);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uadd8)(inst, index);
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->op1 = BITS(inst, 20, 21);
- inst_cream->op2 = BITS(inst, 5, 7);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst));
- umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rm = BITS(inst, 8, 11);
- inst_cream->Rn = BITS(inst, 0, 3);
- inst_cream->RdLo = BITS(inst, 12, 15);
- inst_cream->RdHi = BITS(inst, 16, 19);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst));
- umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rs = BITS(inst, 8, 11);
- inst_cream->RdHi = BITS(inst, 16, 19);
- inst_cream->RdLo = BITS(inst, 12, 15);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst));
- umull_inst *inst_cream = (umull_inst *)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->S = BIT(inst, 20);
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rs = BITS(inst, 8, 11);
- inst_cream->RdHi = BITS(inst, 16, 19);
- inst_cream->RdLo = BITS(inst, 12, 15);
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_2_thumb));
- b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component;
-
- inst_cream->imm = ((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0);
-
- inst_base->idx = index;
- inst_base->br = DIRECT_BRANCH;
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_cond_thumb));
- b_cond_thumb *inst_cream = (b_cond_thumb *)inst_base->component;
-
- inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0));
- inst_cream->cond = ((tinst >> 8) & 0xf);
- inst_base->idx = index;
- inst_base->br = DIRECT_BRANCH;
-
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_1_thumb));
- bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component;
-
- inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0));
-
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_2_thumb));
- bl_2_thumb *inst_cream = (bl_2_thumb *)inst_base->component;
-
- inst_cream->imm = (tinst & 0x07FF) << 1;
-
- inst_base->idx = index;
- inst_base->br = DIRECT_BRANCH;
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index)
-{
- arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_1_thumb));
- blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component;
-
- inst_cream->imm = (tinst & 0x07FF) << 1;
- inst_cream->instr = tinst;
-
- inst_base->idx = index;
- inst_base->br = DIRECT_BRANCH;
- return inst_base;
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->op1 = BITS(inst, 20, 21);
- inst_cream->op2 = BITS(inst, 5, 7);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
- generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->op1 = BITS(inst, 20, 24);
- inst_cream->op2 = BITS(inst, 5, 7);
- inst_cream->Rd = BITS(inst, 16, 19);
- inst_cream->Rm = BITS(inst, 8, 11);
- inst_cream->Rn = BITS(inst, 0, 3);
- inst_cream->Ra = BITS(inst, 12, 15);
-
- return inst_base;
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(usada8)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(ssat)(inst, index);
-}
-static ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index)
-{
- return INTERPRETER_TRANSLATE(ssat16)(inst, index);
-}
-
-static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index)
-{
- arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst));
- uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
-
- inst_base->cond = BITS(inst, 28, 31);
- inst_base->idx = index;
- inst_base->br = NON_BRANCH;
-
- inst_cream->Rm = BITS(inst, 0, 3);
- inst_cream->Rn = BITS(inst, 16, 19);
- inst_cream->Rd = BITS(inst, 12, 15);
- inst_cream->rotate = BITS(inst, 10, 11);
-
- return inst_base;
-}
-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;
-
- 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;
-
- 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;
-
- return inst_base;
+ // Reaching this would indicate the thumb version
+ // of this instruction, however the 3DS CPU doesn't
+ // support this variant (the 3DS CPU is only ARMv6K,
+ // while this variant is added in ARMv6T2).
+ // So it's sufficient for citra to not implement this.
+ return nullptr;
}
-// Floating point VFPv3 structures and instructions
-
-#define VFP_INTERPRETER_STRUCT
-#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
-#undef VFP_INTERPRETER_STRUCT
-
-#define VFP_INTERPRETER_TRANS
-#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
-#undef VFP_INTERPRETER_TRANS
-
-typedef ARM_INST_PTR (*transop_fp_t)(unsigned int, int);
-
-const transop_fp_t arm_instruction_trans[] = {
- INTERPRETER_TRANSLATE(vmla),
- INTERPRETER_TRANSLATE(vmls),
- INTERPRETER_TRANSLATE(vnmla),
- INTERPRETER_TRANSLATE(vnmls),
- INTERPRETER_TRANSLATE(vnmul),
- INTERPRETER_TRANSLATE(vmul),
- INTERPRETER_TRANSLATE(vadd),
- INTERPRETER_TRANSLATE(vsub),
- INTERPRETER_TRANSLATE(vdiv),
- INTERPRETER_TRANSLATE(vmovi),
- INTERPRETER_TRANSLATE(vmovr),
- INTERPRETER_TRANSLATE(vabs),
- INTERPRETER_TRANSLATE(vneg),
- INTERPRETER_TRANSLATE(vsqrt),
- INTERPRETER_TRANSLATE(vcmp),
- INTERPRETER_TRANSLATE(vcmp2),
- INTERPRETER_TRANSLATE(vcvtbds),
- INTERPRETER_TRANSLATE(vcvtbff),
- INTERPRETER_TRANSLATE(vcvtbfi),
- INTERPRETER_TRANSLATE(vmovbrs),
- INTERPRETER_TRANSLATE(vmsr),
- INTERPRETER_TRANSLATE(vmovbrc),
- INTERPRETER_TRANSLATE(vmrs),
- INTERPRETER_TRANSLATE(vmovbcr),
- INTERPRETER_TRANSLATE(vmovbrrss),
- INTERPRETER_TRANSLATE(vmovbrrd),
- INTERPRETER_TRANSLATE(vstr),
- INTERPRETER_TRANSLATE(vpush),
- INTERPRETER_TRANSLATE(vstm),
- INTERPRETER_TRANSLATE(vpop),
- INTERPRETER_TRANSLATE(vldr),
- INTERPRETER_TRANSLATE(vldm),
-
- INTERPRETER_TRANSLATE(srs),
- INTERPRETER_TRANSLATE(rfe),
- INTERPRETER_TRANSLATE(bkpt),
- INTERPRETER_TRANSLATE(blx),
- INTERPRETER_TRANSLATE(cps),
- INTERPRETER_TRANSLATE(pld),
- INTERPRETER_TRANSLATE(setend),
- INTERPRETER_TRANSLATE(clrex),
- INTERPRETER_TRANSLATE(rev16),
- INTERPRETER_TRANSLATE(usad8),
- INTERPRETER_TRANSLATE(sxtb),
- INTERPRETER_TRANSLATE(uxtb),
- INTERPRETER_TRANSLATE(sxth),
- INTERPRETER_TRANSLATE(sxtb16),
- INTERPRETER_TRANSLATE(uxth),
- INTERPRETER_TRANSLATE(uxtb16),
- INTERPRETER_TRANSLATE(cpy),
- INTERPRETER_TRANSLATE(uxtab),
- INTERPRETER_TRANSLATE(ssub8),
- INTERPRETER_TRANSLATE(shsub8),
- INTERPRETER_TRANSLATE(ssubaddx),
- INTERPRETER_TRANSLATE(strex),
- INTERPRETER_TRANSLATE(strexb),
- INTERPRETER_TRANSLATE(swp),
- INTERPRETER_TRANSLATE(swpb),
- INTERPRETER_TRANSLATE(ssub16),
- INTERPRETER_TRANSLATE(ssat16),
- INTERPRETER_TRANSLATE(shsubaddx),
- INTERPRETER_TRANSLATE(qsubaddx),
- INTERPRETER_TRANSLATE(shaddsubx),
- INTERPRETER_TRANSLATE(shadd8),
- INTERPRETER_TRANSLATE(shadd16),
- INTERPRETER_TRANSLATE(sel),
- INTERPRETER_TRANSLATE(saddsubx),
- INTERPRETER_TRANSLATE(sadd8),
- INTERPRETER_TRANSLATE(sadd16),
- INTERPRETER_TRANSLATE(shsub16),
- INTERPRETER_TRANSLATE(umaal),
- INTERPRETER_TRANSLATE(uxtab16),
- INTERPRETER_TRANSLATE(usubaddx),
- INTERPRETER_TRANSLATE(usub8),
- INTERPRETER_TRANSLATE(usub16),
- INTERPRETER_TRANSLATE(usat16),
- INTERPRETER_TRANSLATE(usada8),
- INTERPRETER_TRANSLATE(uqsubaddx),
- INTERPRETER_TRANSLATE(uqsub8),
- INTERPRETER_TRANSLATE(uqsub16),
- INTERPRETER_TRANSLATE(uqaddsubx),
- INTERPRETER_TRANSLATE(uqadd8),
- INTERPRETER_TRANSLATE(uqadd16),
- INTERPRETER_TRANSLATE(sxtab),
- INTERPRETER_TRANSLATE(uhsubaddx),
- INTERPRETER_TRANSLATE(uhsub8),
- INTERPRETER_TRANSLATE(uhsub16),
- INTERPRETER_TRANSLATE(uhaddsubx),
- INTERPRETER_TRANSLATE(uhadd8),
- INTERPRETER_TRANSLATE(uhadd16),
- INTERPRETER_TRANSLATE(uaddsubx),
- INTERPRETER_TRANSLATE(uadd8),
- INTERPRETER_TRANSLATE(uadd16),
- INTERPRETER_TRANSLATE(sxtah),
- INTERPRETER_TRANSLATE(sxtab16),
- INTERPRETER_TRANSLATE(qadd8),
- INTERPRETER_TRANSLATE(bxj),
- INTERPRETER_TRANSLATE(clz),
- INTERPRETER_TRANSLATE(uxtah),
- INTERPRETER_TRANSLATE(bx),
- INTERPRETER_TRANSLATE(rev),
- INTERPRETER_TRANSLATE(blx),
- INTERPRETER_TRANSLATE(revsh),
- INTERPRETER_TRANSLATE(qadd),
- INTERPRETER_TRANSLATE(qadd16),
- INTERPRETER_TRANSLATE(qaddsubx),
- INTERPRETER_TRANSLATE(ldrex),
- INTERPRETER_TRANSLATE(qdadd),
- INTERPRETER_TRANSLATE(qdsub),
- INTERPRETER_TRANSLATE(qsub),
- INTERPRETER_TRANSLATE(ldrexb),
- INTERPRETER_TRANSLATE(qsub8),
- INTERPRETER_TRANSLATE(qsub16),
- INTERPRETER_TRANSLATE(smuad),
- INTERPRETER_TRANSLATE(smmul),
- INTERPRETER_TRANSLATE(smusd),
- INTERPRETER_TRANSLATE(smlsd),
- INTERPRETER_TRANSLATE(smlsld),
- INTERPRETER_TRANSLATE(smmla),
- INTERPRETER_TRANSLATE(smmls),
- INTERPRETER_TRANSLATE(smlald),
- INTERPRETER_TRANSLATE(smlad),
- INTERPRETER_TRANSLATE(smlaw),
- INTERPRETER_TRANSLATE(smulw),
- INTERPRETER_TRANSLATE(pkhtb),
- INTERPRETER_TRANSLATE(pkhbt),
- INTERPRETER_TRANSLATE(smul),
- INTERPRETER_TRANSLATE(smlalxy),
- INTERPRETER_TRANSLATE(smla),
- INTERPRETER_TRANSLATE(mcrr),
- INTERPRETER_TRANSLATE(mrrc),
- INTERPRETER_TRANSLATE(cmp),
- INTERPRETER_TRANSLATE(tst),
- INTERPRETER_TRANSLATE(teq),
- INTERPRETER_TRANSLATE(cmn),
- INTERPRETER_TRANSLATE(smull),
- INTERPRETER_TRANSLATE(umull),
- INTERPRETER_TRANSLATE(umlal),
- INTERPRETER_TRANSLATE(smlal),
- INTERPRETER_TRANSLATE(mul),
- INTERPRETER_TRANSLATE(mla),
- INTERPRETER_TRANSLATE(ssat),
- INTERPRETER_TRANSLATE(usat),
- INTERPRETER_TRANSLATE(mrs),
- INTERPRETER_TRANSLATE(msr),
- INTERPRETER_TRANSLATE(and),
- INTERPRETER_TRANSLATE(bic),
- INTERPRETER_TRANSLATE(ldm),
- INTERPRETER_TRANSLATE(eor),
- INTERPRETER_TRANSLATE(add),
- INTERPRETER_TRANSLATE(rsb),
- INTERPRETER_TRANSLATE(rsc),
- INTERPRETER_TRANSLATE(sbc),
- INTERPRETER_TRANSLATE(adc),
- INTERPRETER_TRANSLATE(sub),
- INTERPRETER_TRANSLATE(orr),
- INTERPRETER_TRANSLATE(mvn),
- INTERPRETER_TRANSLATE(mov),
- INTERPRETER_TRANSLATE(stm),
- INTERPRETER_TRANSLATE(ldm),
- INTERPRETER_TRANSLATE(ldrsh),
- INTERPRETER_TRANSLATE(stm),
- INTERPRETER_TRANSLATE(ldm),
- INTERPRETER_TRANSLATE(ldrsb),
- INTERPRETER_TRANSLATE(strd),
- INTERPRETER_TRANSLATE(ldrh),
- INTERPRETER_TRANSLATE(strh),
- INTERPRETER_TRANSLATE(ldrd),
- INTERPRETER_TRANSLATE(strt),
- INTERPRETER_TRANSLATE(strbt),
- INTERPRETER_TRANSLATE(ldrbt),
- INTERPRETER_TRANSLATE(ldrt),
- 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),
- INTERPRETER_TRANSLATE(ldrcond),
- INTERPRETER_TRANSLATE(str),
- INTERPRETER_TRANSLATE(cdp),
- INTERPRETER_TRANSLATE(stc),
- INTERPRETER_TRANSLATE(ldc),
- 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),
- INTERPRETER_TRANSLATE(b_cond_thumb),
- INTERPRETER_TRANSLATE(bl_1_thumb),
- INTERPRETER_TRANSLATE(bl_2_thumb),
- INTERPRETER_TRANSLATE(blx_1_thumb)
-};
-
enum {
FETCH_SUCCESS,
FETCH_FAILURE
@@ -3413,7 +742,7 @@ static ThumbDecodeStatus DecodeThumbInstruction(u32 inst, u32 addr, u32* arm_ins
ThumbDecodeStatus ret = TranslateThumbInstruction (addr, inst, arm_inst, inst_size);
if (ret == ThumbDecodeStatus::BRANCH) {
int inst_index;
- int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t);
+ int table_length = arm_instruction_trans_len;
u32 tinstr = GetThumbInstruction(inst, addr);
switch ((tinstr & 0xF800) >> 11) {
@@ -3499,14 +828,14 @@ static int InterpreterTranslateBlock(ARMul_State* cpu, int& bb_start, u32 addr)
// Go on next, until terminal instruction
// Save start addr of basicblock in CreamCache
ARM_INST_PTR inst_base = nullptr;
- int ret = NON_BRANCH;
+ TransExtData ret = TransExtData::NON_BRANCH;
int size = 0; // instruction size of basic block
- bb_start = top;
+ bb_start = trans_cache_buf_top;
u32 phys_addr = addr;
u32 pc_start = cpu->Reg[15];
- while (ret == NON_BRANCH) {
+ while (ret == TransExtData::NON_BRANCH) {
unsigned int inst_size = InterpreterTranslateInstruction(cpu, phys_addr, inst_base);
size++;
@@ -3514,7 +843,7 @@ static int InterpreterTranslateBlock(ARMul_State* cpu, int& bb_start, u32 addr)
phys_addr += inst_size;
if ((phys_addr & 0xfff) == 0) {
- inst_base->br = END_OF_PAGE;
+ inst_base->br = TransExtData::END_OF_PAGE;
}
ret = inst_base->br;
};
@@ -3528,15 +857,15 @@ static int InterpreterTranslateSingle(ARMul_State* cpu, int& bb_start, u32 addr)
MICROPROFILE_SCOPE(DynCom_Decode);
ARM_INST_PTR inst_base = nullptr;
- bb_start = top;
+ bb_start = trans_cache_buf_top;
u32 phys_addr = addr;
u32 pc_start = cpu->Reg[15];
InterpreterTranslateInstruction(cpu, phys_addr, inst_base);
- if (inst_base->br == NON_BRANCH) {
- inst_base->br = SINGLE_STEP;
+ if (inst_base->br == TransExtData::NON_BRANCH) {
+ inst_base->br = TransExtData::SINGLE_STEP;
}
cpu->instruction_cache[pc_start] = bb_start;
@@ -3581,8 +910,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
#define SET_PC (cpu->Reg[15] = cpu->Reg[15] + 8 + inst_cream->signed_immed_24)
#define SHIFTER_OPERAND inst_cream->shtop_func(cpu, inst_cream->shifter_operand)
- #define FETCH_INST if (inst_base->br != NON_BRANCH) goto DISPATCH; \
- inst_base = (arm_inst *)&inst_buf[ptr]
+ #define FETCH_INST if (inst_base->br != TransExtData::NON_BRANCH) goto DISPATCH; \
+ inst_base = (arm_inst *)&trans_cache_buf[ptr]
#define INC_PC(l) ptr += sizeof(arm_inst) + l
#define INC_PC_STUB ptr += sizeof(arm_inst)
@@ -3905,7 +1234,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
breakpoint_data = GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute);
}
- inst_base = (arm_inst *)&inst_buf[ptr];
+ inst_base = (arm_inst *)&trans_cache_buf[ptr];
GOTO_NEXT_INST;
}
ADC_INST:
diff --git a/src/core/arm/dyncom/arm_dyncom_trans.cpp b/src/core/arm/dyncom/arm_dyncom_trans.cpp
new file mode 100644
index 000000000..00b42c246
--- /dev/null
+++ b/src/core/arm/dyncom/arm_dyncom_trans.cpp
@@ -0,0 +1,2178 @@
+#include <cstdlib>
+
+#include "common/assert.h"
+#include "common/common_types.h"
+
+#include "core/arm/dyncom/arm_dyncom_interpreter.h"
+#include "core/arm/dyncom/arm_dyncom_trans.h"
+#include "core/arm/skyeye_common/armstate.h"
+#include "core/arm/skyeye_common/armsupp.h"
+#include "core/arm/skyeye_common/vfp/vfp.h"
+
+char trans_cache_buf[TRANS_CACHE_SIZE];
+size_t trans_cache_buf_top = 0;
+
+static void* AllocBuffer(size_t size) {
+ size_t start = trans_cache_buf_top;
+ trans_cache_buf_top += size;
+ ASSERT_MSG(trans_cache_buf_top <= TRANS_CACHE_SIZE, "Translation cache is full!");
+ return static_cast<void*>(&trans_cache_buf[start]);
+}
+
+#define glue(x, y) x ## y
+#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s)
+
+shtop_fp_t GetShifterOp(unsigned int inst);
+get_addr_fp_t GetAddressingOp(unsigned int inst);
+get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst);
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst));
+ adc_inst *inst_cream = (adc_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ if (inst_cream->Rd == 15)
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(add_inst));
+ add_inst *inst_cream = (add_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ if (inst_cream->Rd == 15)
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(and_inst));
+ and_inst *inst_cream = (and_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ if (inst_cream->Rd == 15)
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index)
+{
+ #define POSBRANCH ((inst & 0x7fffff) << 2)
+ #define NEGBRANCH ((0xff000000 |(inst & 0xffffff)) << 2)
+
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst));
+ bbl_inst *inst_cream = (bbl_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::DIRECT_BRANCH;
+
+ if (BIT(inst, 24))
+ inst_base->br = TransExtData::CALL;
+
+ inst_cream->L = BIT(inst, 24);
+ inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bic_inst));
+ bic_inst *inst_cream = (bic_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ if (inst_cream->Rd == 15)
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(bkpt_inst));
+ bkpt_inst* const inst_cream = (bkpt_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->imm = (BITS(inst, 8, 19) << 4) | BITS(inst, 0, 3);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_inst));
+ blx_inst *inst_cream = (blx_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+
+ inst_cream->inst = inst;
+ if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
+ inst_cream->val.Rm = BITS(inst, 0, 3);
+ } else {
+ inst_cream->val.signed_immed_24 = BITS(inst, 0, 23);
+ }
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst));
+ bx_inst *inst_cream = (bx_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+
+ inst_cream->Rm = BITS(inst, 0, 3);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(bx)(inst, index);
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index) {
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst));
+ cdp_inst *inst_cream = (cdp_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->CRm = BITS(inst, 0, 3);
+ inst_cream->CRd = BITS(inst, 12, 15);
+ inst_cream->CRn = BITS(inst, 16, 19);
+ inst_cream->cp_num = BITS(inst, 8, 11);
+ inst_cream->opcode_2 = BITS(inst, 5, 7);
+ inst_cream->opcode_1 = BITS(inst, 20, 23);
+ inst_cream->inst = inst;
+
+ LOG_TRACE(Core_ARM11, "inst %x index %x", inst, index);
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clrex_inst));
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clz_inst));
+ clz_inst *inst_cream = (clz_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rd = BITS(inst, 12, 15);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmn_inst));
+ cmn_inst *inst_cream = (cmn_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmp_inst));
+ cmp_inst *inst_cream = (cmp_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cps_inst));
+ cps_inst *inst_cream = (cps_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->imod0 = BIT(inst, 18);
+ inst_cream->imod1 = BIT(inst, 19);
+ inst_cream->mmod = BIT(inst, 17);
+ inst_cream->A = BIT(inst, 8);
+ inst_cream->I = BIT(inst, 7);
+ inst_cream->F = BIT(inst, 6);
+ inst_cream->mode = BITS(inst, 0, 4);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst));
+ mov_inst *inst_cream = (mov_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ if (inst_cream->Rd == 15) {
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+ }
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(eor_inst));
+ eor_inst *inst_cream = (eor_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ if (inst_cream->Rd == 15)
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldc_inst));
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+
+ if (BIT(inst, 15)) {
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+ }
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst));
+ sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->rotate = BITS(inst, 10, 11);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+
+ if (BITS(inst, 12, 15) == 15)
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+
+ if (BITS(inst, 12, 15) == 15)
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst));
+ uxth_inst *inst_cream = (uxth_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->rotate = BITS(inst, 10, 11);
+ inst_cream->Rm = BITS(inst, 0, 3);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtah_inst));
+ uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->rotate = BITS(inst, 10, 11);
+ inst_cream->Rm = BITS(inst, 0, 3);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index)
+{
+ arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
+ generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = (BITS(inst, 12, 15) == 15) ? TransExtData::INDIRECT_BRANCH : TransExtData::NON_BRANCH; // Branch if dest is R15
+
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(ldrex)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexh)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(ldrex)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexd)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(ldrex)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index)
+{
+ arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
+
+ if (BITS(inst, 12, 15) == 15) {
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+ }
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mcr_inst));
+ mcr_inst *inst_cream = (mcr_inst *)inst_base->component;
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->crn = BITS(inst, 16, 19);
+ inst_cream->crm = BITS(inst, 0, 3);
+ inst_cream->opcode_1 = BITS(inst, 21, 23);
+ inst_cream->opcode_2 = BITS(inst, 5, 7);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->cp_num = BITS(inst, 8, 11);
+ inst_cream->inst = inst;
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(mcrr_inst));
+ mcrr_inst* const inst_cream = (mcrr_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->crm = BITS(inst, 0, 3);
+ inst_cream->opcode_1 = BITS(inst, 4, 7);
+ inst_cream->cp_num = BITS(inst, 8, 11);
+ inst_cream->rt = BITS(inst, 12, 15);
+ inst_cream->rt2 = BITS(inst, 16, 19);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst));
+ mla_inst *inst_cream = (mla_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rn = BITS(inst, 12, 15);
+ inst_cream->Rd = BITS(inst, 16, 19);
+ inst_cream->Rs = BITS(inst, 8, 11);
+ inst_cream->Rm = BITS(inst, 0, 3);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst));
+ mov_inst *inst_cream = (mov_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ if (inst_cream->Rd == 15) {
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+ }
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrc_inst));
+ mrc_inst *inst_cream = (mrc_inst *)inst_base->component;
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->crn = BITS(inst, 16, 19);
+ inst_cream->crm = BITS(inst, 0, 3);
+ inst_cream->opcode_1 = BITS(inst, 21, 23);
+ inst_cream->opcode_2 = BITS(inst, 5, 7);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->cp_num = BITS(inst, 8, 11);
+ inst_cream->inst = inst;
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(mcrr)(inst, index);
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst));
+ mrs_inst *inst_cream = (mrs_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->R = BIT(inst, 22);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(msr_inst));
+ msr_inst *inst_cream = (msr_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->field_mask = BITS(inst, 16, 19);
+ inst_cream->R = BIT(inst, 22);
+ inst_cream->inst = inst;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mul_inst));
+ mul_inst *inst_cream = (mul_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rs = BITS(inst, 8, 11);
+ inst_cream->Rd = BITS(inst, 16, 19);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mvn_inst));
+ mvn_inst *inst_cream = (mvn_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ if (inst_cream->Rd == 15) {
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+ }
+ return inst_base;
+
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(orr_inst));
+ orr_inst *inst_cream = (orr_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ if (inst_cream->Rd == 15)
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+
+ 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 = TransExtData::NON_BRANCH;
+
+ 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));
+ pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->imm = BITS(inst, 7, 11);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(pkhbt)(inst, index);
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst));
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
+ generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->op1 = BITS(inst, 21, 22);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(qadd)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(qadd)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(qadd)(inst, index);
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
+ generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->op1 = BITS(inst, 20, 21);
+ inst_cream->op2 = BITS(inst, 5, 7);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(qadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(qadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(qadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(qadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(qadd8)(inst, index);
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst));
+ rev_inst* const inst_cream = (rev_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->op1 = BITS(inst, 20, 22);
+ inst_cream->op2 = BITS(inst, 5, 7);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(rev)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(rev)(inst, index);
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
+
+ inst_base->cond = AL;
+ inst_base->idx = index;
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsb_inst));
+ rsb_inst *inst_cream = (rsb_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ if (inst_cream->Rd == 15)
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsc_inst));
+ rsc_inst *inst_cream = (rsc_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ if (inst_cream->Rd == 15)
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
+ generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->op1 = BITS(inst, 20, 21);
+ inst_cream->op2 = BITS(inst, 5, 7);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(sadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(sadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(sadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(sadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(sadd8)(inst, index);
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sbc_inst));
+ sbc_inst *inst_cream = (sbc_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ if (inst_cream->Rd == 15)
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
+ generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->op1 = BITS(inst, 20, 22);
+ inst_cream->op2 = BITS(inst, 5, 7);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(setend_inst));
+ setend_inst* const inst_cream = (setend_inst*)inst_base->component;
+
+ inst_base->cond = AL;
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->set_bigend = BIT(inst, 9);
+
+ 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 = TransExtData::NON_BRANCH;
+
+ 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));
+ generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->op1 = BITS(inst, 20, 21);
+ inst_cream->op2 = BITS(inst, 5, 7);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(shadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(shaddsubx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(shadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(shadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(shsub16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(shadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(shadd8)(inst, index);
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst));
+ smla_inst *inst_cream = (smla_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->x = BIT(inst, 5);
+ inst_cream->y = BIT(inst, 6);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rs = BITS(inst, 8, 11);
+ inst_cream->Rd = BITS(inst, 16, 19);
+ inst_cream->Rn = BITS(inst, 12, 15);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
+ smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->m = BIT(inst, 5);
+ inst_cream->Rn = BITS(inst, 0, 3);
+ inst_cream->Rm = BITS(inst, 8, 11);
+ inst_cream->Rd = BITS(inst, 16, 19);
+ inst_cream->Ra = BITS(inst, 12, 15);
+ inst_cream->op1 = BITS(inst, 20, 22);
+ inst_cream->op2 = BITS(inst, 5, 7);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(smlad)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(smlad)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsd)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(smlad)(inst, index);
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst));
+ umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rs = BITS(inst, 8, 11);
+ inst_cream->RdHi = BITS(inst, 16, 19);
+ inst_cream->RdLo = BITS(inst, 12, 15);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlalxy_inst));
+ smlalxy_inst* const inst_cream = (smlalxy_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->x = BIT(inst, 5);
+ inst_cream->y = BIT(inst, 6);
+ inst_cream->RdLo = BITS(inst, 12, 15);
+ inst_cream->RdHi = BITS(inst, 16, 19);
+ inst_cream->Rn = BITS(inst, 0, 4);
+ inst_cream->Rm = BITS(inst, 8, 11);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smlaw)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
+ smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Ra = BITS(inst, 12, 15);
+ inst_cream->Rm = BITS(inst, 8, 11);
+ inst_cream->Rn = BITS(inst, 0, 3);
+ inst_cream->Rd = BITS(inst, 16, 19);
+ inst_cream->m = BIT(inst, 6);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlald_inst));
+ smlald_inst* const inst_cream = (smlald_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rm = BITS(inst, 8, 11);
+ inst_cream->Rn = BITS(inst, 0, 3);
+ inst_cream->RdLo = BITS(inst, 12, 15);
+ inst_cream->RdHi = BITS(inst, 16, 19);
+ inst_cream->swap = BIT(inst, 5);
+ inst_cream->op1 = BITS(inst, 20, 22);
+ inst_cream->op2 = BITS(inst, 5, 7);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smlsld)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(smlald)(inst, index);
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smmla)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
+ smlad_inst* const inst_cream = (smlad_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->m = BIT(inst, 5);
+ inst_cream->Ra = BITS(inst, 12, 15);
+ inst_cream->Rm = BITS(inst, 8, 11);
+ inst_cream->Rn = BITS(inst, 0, 3);
+ inst_cream->Rd = BITS(inst, 16, 19);
+ inst_cream->op1 = BITS(inst, 20, 22);
+ inst_cream->op2 = BITS(inst, 5, 7);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smmls)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(smmla)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(smmla)(inst, index);
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smul_inst));
+ smul_inst *inst_cream = (smul_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rd = BITS(inst, 16, 19);
+ inst_cream->Rs = BITS(inst, 8, 11);
+ inst_cream->Rm = BITS(inst, 0, 3);
+
+ inst_cream->x = BIT(inst, 5);
+ inst_cream->y = BIT(inst, 6);
+
+ return inst_base;
+
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst));
+ umull_inst *inst_cream = (umull_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rs = BITS(inst, 8, 11);
+ inst_cream->RdHi = BITS(inst, 16, 19);
+ inst_cream->RdLo = BITS(inst, 12, 15);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
+ smlad_inst *inst_cream = (smlad_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->m = BIT(inst, 6);
+ inst_cream->Rm = BITS(inst, 8, 11);
+ inst_cream->Rn = BITS(inst, 0, 3);
+ inst_cream->Rd = BITS(inst, 16, 19);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst* const inst_cream = (ldst_inst*)inst_base->component;
+
+ inst_base->cond = AL;
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst));
+ ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rn = BITS(inst, 0, 3);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->imm5 = BITS(inst, 7, 11);
+ inst_cream->sat_imm = BITS(inst, 16, 20);
+ inst_cream->shift_type = BIT(inst, 6);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ssat_inst));
+ ssat_inst* const inst_cream = (ssat_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rn = BITS(inst, 0, 3);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->sat_imm = BITS(inst, 16, 19);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(stc_inst));
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst));
+ sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->rotate = BITS(inst, 10, 11);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst));
+ uxth_inst *inst_cream = (uxth_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->rotate = BITS(inst, 10, 11);
+ inst_cream->Rm = BITS(inst, 0, 3);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst));
+ uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->rotate = BITS(inst, 10, 11);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index)
+{
+ arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
+ generic_arm_inst *inst_cream = (generic_arm_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->Rm = BITS(inst, 0, 3);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(strex)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(strexh)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(strex)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(strexd)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(strex)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOp(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index)
+{
+ arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
+ ldst_inst* inst_cream = (ldst_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->inst = inst;
+ inst_cream->get_addr = GetAddressingOpLoadStoreT(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sub_inst));
+ sub_inst *inst_cream = (sub_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ if (inst_cream->Rd == 15)
+ inst_base->br = TransExtData::INDIRECT_BRANCH;
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swi_inst));
+ swi_inst *inst_cream = (swi_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->num = BITS(inst, 0, 23);
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst));
+ swp_inst *inst_cream = (swp_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->Rm = BITS(inst, 0, 3);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst));
+ swp_inst *inst_cream = (swp_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->Rm = BITS(inst, 0, 3);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index){
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst));
+ sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->rotate = BITS(inst, 10, 11);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst));
+ sxtab_inst* const inst_cream = (sxtab_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->rotate = BITS(inst, 10, 11);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(sxtab16)(inst, index);
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index) {
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtah_inst));
+ sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->rotate = BITS(inst, 10, 11);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(teq_inst));
+ teq_inst *inst_cream = (teq_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(tst_inst));
+ tst_inst *inst_cream = (tst_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->I = BIT(inst, 25);
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->shifter_operand = BITS(inst, 0, 11);
+ inst_cream->shtop_func = GetShifterOp(inst);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
+ generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->op1 = BITS(inst, 20, 21);
+ inst_cream->op2 = BITS(inst, 5, 7);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uadd8)(inst, index);
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
+ generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->op1 = BITS(inst, 20, 21);
+ inst_cream->op2 = BITS(inst, 5, 7);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst));
+ umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rm = BITS(inst, 8, 11);
+ inst_cream->Rn = BITS(inst, 0, 3);
+ inst_cream->RdLo = BITS(inst, 12, 15);
+ inst_cream->RdHi = BITS(inst, 16, 19);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst));
+ umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rs = BITS(inst, 8, 11);
+ inst_cream->RdHi = BITS(inst, 16, 19);
+ inst_cream->RdLo = BITS(inst, 12, 15);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst));
+ umull_inst *inst_cream = (umull_inst *)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->S = BIT(inst, 20);
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rs = BITS(inst, 8, 11);
+ inst_cream->RdHi = BITS(inst, 16, 19);
+ inst_cream->RdLo = BITS(inst, 12, 15);
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_2_thumb));
+ b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component;
+
+ inst_cream->imm = ((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0);
+
+ inst_base->idx = index;
+ inst_base->br = TransExtData::DIRECT_BRANCH;
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_cond_thumb));
+ b_cond_thumb *inst_cream = (b_cond_thumb *)inst_base->component;
+
+ inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0));
+ inst_cream->cond = ((tinst >> 8) & 0xf);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::DIRECT_BRANCH;
+
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_1_thumb));
+ bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component;
+
+ inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0));
+
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_2_thumb));
+ bl_2_thumb *inst_cream = (bl_2_thumb *)inst_base->component;
+
+ inst_cream->imm = (tinst & 0x07FF) << 1;
+
+ inst_base->idx = index;
+ inst_base->br = TransExtData::DIRECT_BRANCH;
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index)
+{
+ arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_1_thumb));
+ blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component;
+
+ inst_cream->imm = (tinst & 0x07FF) << 1;
+ inst_cream->instr = tinst;
+
+ inst_base->idx = index;
+ inst_base->br = TransExtData::DIRECT_BRANCH;
+ return inst_base;
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
+ generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->op1 = BITS(inst, 20, 21);
+ inst_cream->op2 = BITS(inst, 5, 7);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
+ generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->op1 = BITS(inst, 20, 24);
+ inst_cream->op2 = BITS(inst, 5, 7);
+ inst_cream->Rd = BITS(inst, 16, 19);
+ inst_cream->Rm = BITS(inst, 8, 11);
+ inst_cream->Rn = BITS(inst, 0, 3);
+ inst_cream->Ra = BITS(inst, 12, 15);
+
+ return inst_base;
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(usada8)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(ssat)(inst, index);
+}
+static ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index)
+{
+ return INTERPRETER_TRANSLATE(ssat16)(inst, index);
+}
+
+static ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index)
+{
+ arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst));
+ uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
+
+ inst_base->cond = BITS(inst, 28, 31);
+ inst_base->idx = index;
+ inst_base->br = TransExtData::NON_BRANCH;
+
+ inst_cream->Rm = BITS(inst, 0, 3);
+ inst_cream->Rn = BITS(inst, 16, 19);
+ inst_cream->Rd = BITS(inst, 12, 15);
+ inst_cream->rotate = BITS(inst, 10, 11);
+
+ return inst_base;
+}
+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 = TransExtData::NON_BRANCH;
+
+ 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 = TransExtData::NON_BRANCH;
+
+ 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 = TransExtData::NON_BRANCH;
+
+ return inst_base;
+}
+
+// Floating point VFPv3 instructions
+#define VFP_INTERPRETER_TRANS
+#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
+#undef VFP_INTERPRETER_TRANS
+
+const transop_fp_t arm_instruction_trans[] = {
+ INTERPRETER_TRANSLATE(vmla),
+ INTERPRETER_TRANSLATE(vmls),
+ INTERPRETER_TRANSLATE(vnmla),
+ INTERPRETER_TRANSLATE(vnmls),
+ INTERPRETER_TRANSLATE(vnmul),
+ INTERPRETER_TRANSLATE(vmul),
+ INTERPRETER_TRANSLATE(vadd),
+ INTERPRETER_TRANSLATE(vsub),
+ INTERPRETER_TRANSLATE(vdiv),
+ INTERPRETER_TRANSLATE(vmovi),
+ INTERPRETER_TRANSLATE(vmovr),
+ INTERPRETER_TRANSLATE(vabs),
+ INTERPRETER_TRANSLATE(vneg),
+ INTERPRETER_TRANSLATE(vsqrt),
+ INTERPRETER_TRANSLATE(vcmp),
+ INTERPRETER_TRANSLATE(vcmp2),
+ INTERPRETER_TRANSLATE(vcvtbds),
+ INTERPRETER_TRANSLATE(vcvtbff),
+ INTERPRETER_TRANSLATE(vcvtbfi),
+ INTERPRETER_TRANSLATE(vmovbrs),
+ INTERPRETER_TRANSLATE(vmsr),
+ INTERPRETER_TRANSLATE(vmovbrc),
+ INTERPRETER_TRANSLATE(vmrs),
+ INTERPRETER_TRANSLATE(vmovbcr),
+ INTERPRETER_TRANSLATE(vmovbrrss),
+ INTERPRETER_TRANSLATE(vmovbrrd),
+ INTERPRETER_TRANSLATE(vstr),
+ INTERPRETER_TRANSLATE(vpush),
+ INTERPRETER_TRANSLATE(vstm),
+ INTERPRETER_TRANSLATE(vpop),
+ INTERPRETER_TRANSLATE(vldr),
+ INTERPRETER_TRANSLATE(vldm),
+
+ INTERPRETER_TRANSLATE(srs),
+ INTERPRETER_TRANSLATE(rfe),
+ INTERPRETER_TRANSLATE(bkpt),
+ INTERPRETER_TRANSLATE(blx),
+ INTERPRETER_TRANSLATE(cps),
+ INTERPRETER_TRANSLATE(pld),
+ INTERPRETER_TRANSLATE(setend),
+ INTERPRETER_TRANSLATE(clrex),
+ INTERPRETER_TRANSLATE(rev16),
+ INTERPRETER_TRANSLATE(usad8),
+ INTERPRETER_TRANSLATE(sxtb),
+ INTERPRETER_TRANSLATE(uxtb),
+ INTERPRETER_TRANSLATE(sxth),
+ INTERPRETER_TRANSLATE(sxtb16),
+ INTERPRETER_TRANSLATE(uxth),
+ INTERPRETER_TRANSLATE(uxtb16),
+ INTERPRETER_TRANSLATE(cpy),
+ INTERPRETER_TRANSLATE(uxtab),
+ INTERPRETER_TRANSLATE(ssub8),
+ INTERPRETER_TRANSLATE(shsub8),
+ INTERPRETER_TRANSLATE(ssubaddx),
+ INTERPRETER_TRANSLATE(strex),
+ INTERPRETER_TRANSLATE(strexb),
+ INTERPRETER_TRANSLATE(swp),
+ INTERPRETER_TRANSLATE(swpb),
+ INTERPRETER_TRANSLATE(ssub16),
+ INTERPRETER_TRANSLATE(ssat16),
+ INTERPRETER_TRANSLATE(shsubaddx),
+ INTERPRETER_TRANSLATE(qsubaddx),
+ INTERPRETER_TRANSLATE(shaddsubx),
+ INTERPRETER_TRANSLATE(shadd8),
+ INTERPRETER_TRANSLATE(shadd16),
+ INTERPRETER_TRANSLATE(sel),
+ INTERPRETER_TRANSLATE(saddsubx),
+ INTERPRETER_TRANSLATE(sadd8),
+ INTERPRETER_TRANSLATE(sadd16),
+ INTERPRETER_TRANSLATE(shsub16),
+ INTERPRETER_TRANSLATE(umaal),
+ INTERPRETER_TRANSLATE(uxtab16),
+ INTERPRETER_TRANSLATE(usubaddx),
+ INTERPRETER_TRANSLATE(usub8),
+ INTERPRETER_TRANSLATE(usub16),
+ INTERPRETER_TRANSLATE(usat16),
+ INTERPRETER_TRANSLATE(usada8),
+ INTERPRETER_TRANSLATE(uqsubaddx),
+ INTERPRETER_TRANSLATE(uqsub8),
+ INTERPRETER_TRANSLATE(uqsub16),
+ INTERPRETER_TRANSLATE(uqaddsubx),
+ INTERPRETER_TRANSLATE(uqadd8),
+ INTERPRETER_TRANSLATE(uqadd16),
+ INTERPRETER_TRANSLATE(sxtab),
+ INTERPRETER_TRANSLATE(uhsubaddx),
+ INTERPRETER_TRANSLATE(uhsub8),
+ INTERPRETER_TRANSLATE(uhsub16),
+ INTERPRETER_TRANSLATE(uhaddsubx),
+ INTERPRETER_TRANSLATE(uhadd8),
+ INTERPRETER_TRANSLATE(uhadd16),
+ INTERPRETER_TRANSLATE(uaddsubx),
+ INTERPRETER_TRANSLATE(uadd8),
+ INTERPRETER_TRANSLATE(uadd16),
+ INTERPRETER_TRANSLATE(sxtah),
+ INTERPRETER_TRANSLATE(sxtab16),
+ INTERPRETER_TRANSLATE(qadd8),
+ INTERPRETER_TRANSLATE(bxj),
+ INTERPRETER_TRANSLATE(clz),
+ INTERPRETER_TRANSLATE(uxtah),
+ INTERPRETER_TRANSLATE(bx),
+ INTERPRETER_TRANSLATE(rev),
+ INTERPRETER_TRANSLATE(blx),
+ INTERPRETER_TRANSLATE(revsh),
+ INTERPRETER_TRANSLATE(qadd),
+ INTERPRETER_TRANSLATE(qadd16),
+ INTERPRETER_TRANSLATE(qaddsubx),
+ INTERPRETER_TRANSLATE(ldrex),
+ INTERPRETER_TRANSLATE(qdadd),
+ INTERPRETER_TRANSLATE(qdsub),
+ INTERPRETER_TRANSLATE(qsub),
+ INTERPRETER_TRANSLATE(ldrexb),
+ INTERPRETER_TRANSLATE(qsub8),
+ INTERPRETER_TRANSLATE(qsub16),
+ INTERPRETER_TRANSLATE(smuad),
+ INTERPRETER_TRANSLATE(smmul),
+ INTERPRETER_TRANSLATE(smusd),
+ INTERPRETER_TRANSLATE(smlsd),
+ INTERPRETER_TRANSLATE(smlsld),
+ INTERPRETER_TRANSLATE(smmla),
+ INTERPRETER_TRANSLATE(smmls),
+ INTERPRETER_TRANSLATE(smlald),
+ INTERPRETER_TRANSLATE(smlad),
+ INTERPRETER_TRANSLATE(smlaw),
+ INTERPRETER_TRANSLATE(smulw),
+ INTERPRETER_TRANSLATE(pkhtb),
+ INTERPRETER_TRANSLATE(pkhbt),
+ INTERPRETER_TRANSLATE(smul),
+ INTERPRETER_TRANSLATE(smlalxy),
+ INTERPRETER_TRANSLATE(smla),
+ INTERPRETER_TRANSLATE(mcrr),
+ INTERPRETER_TRANSLATE(mrrc),
+ INTERPRETER_TRANSLATE(cmp),
+ INTERPRETER_TRANSLATE(tst),
+ INTERPRETER_TRANSLATE(teq),
+ INTERPRETER_TRANSLATE(cmn),
+ INTERPRETER_TRANSLATE(smull),
+ INTERPRETER_TRANSLATE(umull),
+ INTERPRETER_TRANSLATE(umlal),
+ INTERPRETER_TRANSLATE(smlal),
+ INTERPRETER_TRANSLATE(mul),
+ INTERPRETER_TRANSLATE(mla),
+ INTERPRETER_TRANSLATE(ssat),
+ INTERPRETER_TRANSLATE(usat),
+ INTERPRETER_TRANSLATE(mrs),
+ INTERPRETER_TRANSLATE(msr),
+ INTERPRETER_TRANSLATE(and),
+ INTERPRETER_TRANSLATE(bic),
+ INTERPRETER_TRANSLATE(ldm),
+ INTERPRETER_TRANSLATE(eor),
+ INTERPRETER_TRANSLATE(add),
+ INTERPRETER_TRANSLATE(rsb),
+ INTERPRETER_TRANSLATE(rsc),
+ INTERPRETER_TRANSLATE(sbc),
+ INTERPRETER_TRANSLATE(adc),
+ INTERPRETER_TRANSLATE(sub),
+ INTERPRETER_TRANSLATE(orr),
+ INTERPRETER_TRANSLATE(mvn),
+ INTERPRETER_TRANSLATE(mov),
+ INTERPRETER_TRANSLATE(stm),
+ INTERPRETER_TRANSLATE(ldm),
+ INTERPRETER_TRANSLATE(ldrsh),
+ INTERPRETER_TRANSLATE(stm),
+ INTERPRETER_TRANSLATE(ldm),
+ INTERPRETER_TRANSLATE(ldrsb),
+ INTERPRETER_TRANSLATE(strd),
+ INTERPRETER_TRANSLATE(ldrh),
+ INTERPRETER_TRANSLATE(strh),
+ INTERPRETER_TRANSLATE(ldrd),
+ INTERPRETER_TRANSLATE(strt),
+ INTERPRETER_TRANSLATE(strbt),
+ INTERPRETER_TRANSLATE(ldrbt),
+ INTERPRETER_TRANSLATE(ldrt),
+ 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),
+ INTERPRETER_TRANSLATE(ldrcond),
+ INTERPRETER_TRANSLATE(str),
+ INTERPRETER_TRANSLATE(cdp),
+ INTERPRETER_TRANSLATE(stc),
+ INTERPRETER_TRANSLATE(ldc),
+ 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),
+ INTERPRETER_TRANSLATE(b_cond_thumb),
+ INTERPRETER_TRANSLATE(bl_1_thumb),
+ INTERPRETER_TRANSLATE(bl_2_thumb),
+ INTERPRETER_TRANSLATE(blx_1_thumb)
+};
+
+const size_t arm_instruction_trans_len = sizeof(arm_instruction_trans) / sizeof(transop_fp_t);
diff --git a/src/core/arm/dyncom/arm_dyncom_trans.h b/src/core/arm/dyncom/arm_dyncom_trans.h
new file mode 100644
index 000000000..7af71f4e3
--- /dev/null
+++ b/src/core/arm/dyncom/arm_dyncom_trans.h
@@ -0,0 +1,493 @@
+struct ARMul_State;
+typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper);
+
+enum class TransExtData {
+ COND = (1 << 0),
+ NON_BRANCH = (1 << 1),
+ DIRECT_BRANCH = (1 << 2),
+ INDIRECT_BRANCH = (1 << 3),
+ CALL = (1 << 4),
+ RET = (1 << 5),
+ END_OF_PAGE = (1 << 6),
+ THUMB = (1 << 7),
+ SINGLE_STEP = (1 << 8)
+};
+
+struct arm_inst {
+ unsigned int idx;
+ unsigned int cond;
+ TransExtData br;
+ char component[0];
+};
+
+struct generic_arm_inst {
+ u32 Ra;
+ u32 Rm;
+ u32 Rn;
+ u32 Rd;
+ u8 op1;
+ u8 op2;
+};
+
+struct adc_inst {
+ unsigned int I;
+ unsigned int S;
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct add_inst {
+ unsigned int I;
+ unsigned int S;
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct orr_inst {
+ unsigned int I;
+ unsigned int S;
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct and_inst {
+ unsigned int I;
+ unsigned int S;
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct eor_inst {
+ unsigned int I;
+ unsigned int S;
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct bbl_inst {
+ unsigned int L;
+ int signed_immed_24;
+ unsigned int next_addr;
+ unsigned int jmp_addr;
+};
+
+struct bx_inst {
+ unsigned int Rm;
+};
+
+struct blx_inst {
+ union {
+ s32 signed_immed_24;
+ u32 Rm;
+ } val;
+ unsigned int inst;
+};
+
+struct clz_inst {
+ unsigned int Rm;
+ unsigned int Rd;
+};
+
+struct cps_inst {
+ unsigned int imod0;
+ unsigned int imod1;
+ unsigned int mmod;
+ unsigned int A, I, F;
+ unsigned int mode;
+};
+
+struct clrex_inst {
+};
+
+struct cpy_inst {
+ unsigned int Rm;
+ unsigned int Rd;
+};
+
+struct bic_inst {
+ unsigned int I;
+ unsigned int S;
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct sub_inst {
+ unsigned int I;
+ unsigned int S;
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct tst_inst {
+ unsigned int I;
+ unsigned int S;
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct cmn_inst {
+ unsigned int I;
+ unsigned int Rn;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct teq_inst {
+ unsigned int I;
+ unsigned int Rn;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct stm_inst {
+ unsigned int inst;
+};
+
+struct bkpt_inst {
+ u32 imm;
+};
+
+struct stc_inst {
+};
+
+struct ldc_inst {
+};
+
+struct swi_inst {
+ unsigned int num;
+};
+
+struct cmp_inst {
+ unsigned int I;
+ unsigned int Rn;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct mov_inst {
+ unsigned int I;
+ unsigned int S;
+ unsigned int Rd;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct mvn_inst {
+ unsigned int I;
+ unsigned int S;
+ unsigned int Rd;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct rev_inst {
+ unsigned int Rd;
+ unsigned int Rm;
+ unsigned int op1;
+ unsigned int op2;
+};
+
+struct rsb_inst {
+ unsigned int I;
+ unsigned int S;
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct rsc_inst {
+ unsigned int I;
+ unsigned int S;
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct sbc_inst {
+ unsigned int I;
+ unsigned int S;
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int shifter_operand;
+ shtop_fp_t shtop_func;
+};
+
+struct mul_inst {
+ unsigned int S;
+ unsigned int Rd;
+ unsigned int Rs;
+ unsigned int Rm;
+};
+
+struct smul_inst {
+ unsigned int Rd;
+ unsigned int Rs;
+ unsigned int Rm;
+ unsigned int x;
+ unsigned int y;
+};
+
+struct umull_inst {
+ unsigned int S;
+ unsigned int RdHi;
+ unsigned int RdLo;
+ unsigned int Rs;
+ unsigned int Rm;
+};
+
+struct smlad_inst {
+ unsigned int m;
+ unsigned int Rm;
+ unsigned int Rd;
+ unsigned int Ra;
+ unsigned int Rn;
+ unsigned int op1;
+ unsigned int op2;
+};
+
+struct smla_inst {
+ unsigned int x;
+ unsigned int y;
+ unsigned int Rm;
+ unsigned int Rd;
+ unsigned int Rs;
+ unsigned int Rn;
+};
+
+struct smlalxy_inst {
+ unsigned int x;
+ unsigned int y;
+ unsigned int RdLo;
+ unsigned int RdHi;
+ unsigned int Rm;
+ unsigned int Rn;
+};
+
+struct ssat_inst {
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int imm5;
+ unsigned int sat_imm;
+ unsigned int shift_type;
+};
+
+struct umaal_inst {
+ unsigned int Rn;
+ unsigned int Rm;
+ unsigned int RdHi;
+ unsigned int RdLo;
+};
+
+struct umlal_inst {
+ unsigned int S;
+ unsigned int Rm;
+ unsigned int Rs;
+ unsigned int RdHi;
+ unsigned int RdLo;
+};
+
+struct smlal_inst {
+ unsigned int S;
+ unsigned int Rm;
+ unsigned int Rs;
+ unsigned int RdHi;
+ unsigned int RdLo;
+};
+
+struct smlald_inst {
+ unsigned int RdLo;
+ unsigned int RdHi;
+ unsigned int Rm;
+ unsigned int Rn;
+ unsigned int swap;
+ unsigned int op1;
+ unsigned int op2;
+};
+
+struct mla_inst {
+ unsigned int S;
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int Rs;
+ unsigned int Rm;
+};
+
+struct mrc_inst {
+ unsigned int opcode_1;
+ unsigned int opcode_2;
+ unsigned int cp_num;
+ unsigned int crn;
+ unsigned int crm;
+ unsigned int Rd;
+ unsigned int inst;
+};
+
+struct mcr_inst {
+ unsigned int opcode_1;
+ unsigned int opcode_2;
+ unsigned int cp_num;
+ unsigned int crn;
+ unsigned int crm;
+ unsigned int Rd;
+ unsigned int inst;
+};
+
+struct mcrr_inst {
+ unsigned int opcode_1;
+ unsigned int cp_num;
+ unsigned int crm;
+ unsigned int rt;
+ unsigned int rt2;
+};
+
+struct mrs_inst {
+ unsigned int R;
+ unsigned int Rd;
+};
+
+struct msr_inst {
+ unsigned int field_mask;
+ unsigned int R;
+ unsigned int inst;
+};
+
+struct pld_inst {
+};
+
+struct sxtb_inst {
+ unsigned int Rd;
+ unsigned int Rm;
+ unsigned int rotate;
+};
+
+struct sxtab_inst {
+ unsigned int Rd;
+ unsigned int Rn;
+ unsigned int Rm;
+ unsigned rotate;
+};
+
+struct sxtah_inst {
+ unsigned int Rd;
+ unsigned int Rn;
+ unsigned int Rm;
+ unsigned int rotate;
+};
+
+struct sxth_inst {
+ unsigned int Rd;
+ unsigned int Rm;
+ unsigned int rotate;
+};
+
+struct uxtab_inst {
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int rotate;
+ unsigned int Rm;
+};
+
+struct uxtah_inst {
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int rotate;
+ unsigned int Rm;
+};
+
+struct uxth_inst {
+ unsigned int Rd;
+ unsigned int Rm;
+ unsigned int rotate;
+};
+
+struct cdp_inst {
+ unsigned int opcode_1;
+ unsigned int CRn;
+ unsigned int CRd;
+ unsigned int cp_num;
+ unsigned int opcode_2;
+ unsigned int CRm;
+ unsigned int inst;
+};
+
+struct uxtb_inst {
+ unsigned int Rd;
+ unsigned int Rm;
+ unsigned int rotate;
+};
+
+struct swp_inst {
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned int Rm;
+};
+
+struct setend_inst {
+ unsigned int set_bigend;
+};
+
+struct b_2_thumb {
+ unsigned int imm;
+};
+struct b_cond_thumb {
+ unsigned int imm;
+ unsigned int cond;
+};
+
+struct bl_1_thumb {
+ unsigned int imm;
+};
+struct bl_2_thumb {
+ unsigned int imm;
+};
+struct blx_1_thumb {
+ unsigned int imm;
+ unsigned int instr;
+};
+
+struct pkh_inst {
+ unsigned int Rm;
+ unsigned int Rn;
+ unsigned int Rd;
+ unsigned char imm;
+};
+
+// Floating point VFPv3 structures
+#define VFP_INTERPRETER_STRUCT
+#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
+#undef VFP_INTERPRETER_STRUCT
+
+typedef void (*get_addr_fp_t)(ARMul_State *cpu, unsigned int inst, unsigned int &virt_addr);
+
+struct ldst_inst {
+ unsigned int inst;
+ get_addr_fp_t get_addr;
+};
+
+typedef arm_inst* ARM_INST_PTR;
+typedef ARM_INST_PTR (*transop_fp_t)(unsigned int, int);
+
+extern const transop_fp_t arm_instruction_trans[];
+extern const size_t arm_instruction_trans_len;
+
+#define TRANS_CACHE_SIZE (64 * 1024 * 2000)
+extern char trans_cache_buf[TRANS_CACHE_SIZE];
+extern size_t trans_cache_buf_top;
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
index 4f9083515..1a98d0114 100644
--- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
@@ -26,7 +26,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmla)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -75,7 +75,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -124,7 +124,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -174,7 +174,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -223,7 +223,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -272,7 +272,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -321,7 +321,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -370,7 +370,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -419,7 +419,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -470,7 +470,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovi)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->single = BIT(inst, 8) == 0;
inst_cream->d = (inst_cream->single ? BITS(inst,12,15)<<1 | BIT(inst,22) : BITS(inst,12,15) | BIT(inst,22)<<4);
@@ -518,7 +518,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovr)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->single = BIT(inst, 8) == 0;
inst_cream->d = (inst_cream->single ? BITS(inst,12,15)<<1 | BIT(inst,22) : BITS(inst,12,15) | BIT(inst,22)<<4);
@@ -560,7 +560,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vabs)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -610,7 +610,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -659,7 +659,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -708,7 +708,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -757,7 +757,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -806,7 +806,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -857,7 +857,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -906,7 +906,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->dp_operation = BIT(inst, 8);
inst_cream->instr = inst;
@@ -962,7 +962,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrs)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->to_arm = BIT(inst, 20) == 1;
inst_cream->t = BITS(inst, 12, 15);
@@ -1006,7 +1006,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->reg = BITS(inst, 16, 19);
inst_cream->Rt = BITS(inst, 12, 15);
@@ -1069,7 +1069,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->d = BITS(inst, 16, 19)|BIT(inst, 7)<<4;
inst_cream->t = BITS(inst, 12, 15);
@@ -1115,7 +1115,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->reg = BITS(inst, 16, 19);
inst_cream->Rt = BITS(inst, 12, 15);
@@ -1200,7 +1200,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->d = BITS(inst, 16, 19)|BIT(inst, 7)<<4;
inst_cream->t = BITS(inst, 12, 15);
@@ -1253,7 +1253,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrss)(unsigned int inst, int inde
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->to_arm = BIT(inst, 20) == 1;
inst_cream->t = BITS(inst, 12, 15);
@@ -1301,7 +1301,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrd)(unsigned int inst, int index
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->to_arm = BIT(inst, 20) == 1;
inst_cream->t = BITS(inst, 12, 15);
@@ -1354,7 +1354,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vstr)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->single = BIT(inst, 8) == 0;
inst_cream->add = BIT(inst, 23);
@@ -1420,7 +1420,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vpush)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->single = BIT(inst, 8) == 0;
inst_cream->d = (inst_cream->single ? BITS(inst, 12, 15)<<1|BIT(inst, 22) : BITS(inst, 12, 15)|BIT(inst, 22)<<4);
@@ -1495,7 +1495,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->single = BIT(inst, 8) == 0;
inst_cream->add = BIT(inst, 23);
@@ -1580,7 +1580,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vpop)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->single = BIT(inst, 8) == 0;
inst_cream->d = (inst_cream->single ? (BITS(inst, 12, 15)<<1)|BIT(inst, 22) : BITS(inst, 12, 15)|(BIT(inst, 22)<<4));
@@ -1653,7 +1653,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vldr)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->single = BIT(inst, 8) == 0;
inst_cream->add = BIT(inst, 23);
@@ -1722,7 +1722,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index)
inst_base->cond = BITS(inst, 28, 31);
inst_base->idx = index;
- inst_base->br = NON_BRANCH;
+ inst_base->br = TransExtData::NON_BRANCH;
inst_cream->single = BIT(inst, 8) == 0;
inst_cream->add = BIT(inst, 23);
diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp
index 90e134437..ccf35fa07 100644
--- a/src/core/hle/applets/applet.cpp
+++ b/src/core/hle/applets/applet.cpp
@@ -12,6 +12,7 @@
#include "core/core_timing.h"
#include "core/hle/applets/applet.h"
+#include "core/hle/applets/erreula.h"
#include "core/hle/applets/mii_selector.h"
#include "core/hle/applets/swkbd.h"
#include "core/hle/result.h"
@@ -52,6 +53,10 @@ ResultCode Applet::Create(Service::APT::AppletId id) {
case Service::APT::AppletId::Ed2:
applets[id] = std::make_shared<MiiSelector>(id);
break;
+ case Service::APT::AppletId::Error:
+ case Service::APT::AppletId::Error2:
+ applets[id] = std::make_shared<ErrEula>(id);
+ break;
default:
LOG_ERROR(Service_APT, "Could not create applet %u", id);
// TODO(Subv): Find the right error code
diff --git a/src/core/hle/applets/erreula.cpp b/src/core/hle/applets/erreula.cpp
new file mode 100644
index 000000000..92a4b2323
--- /dev/null
+++ b/src/core/hle/applets/erreula.cpp
@@ -0,0 +1,72 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/string_util.h"
+
+#include "core/hle/applets/erreula.h"
+#include "core/hle/service/apt/apt.h"
+
+namespace HLE {
+namespace Applets {
+
+ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& parameter) {
+ if (parameter.signal != static_cast<u32>(Service::APT::SignalType::LibAppJustStarted)) {
+ LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal);
+ UNIMPLEMENTED();
+ // TODO(Subv): Find the right error code
+ return ResultCode(-1);
+ }
+
+ // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory.
+ // Create the SharedMemory that will hold the framebuffer data
+ Service::APT::CaptureBufferInfo capture_info;
+ ASSERT(sizeof(capture_info) == parameter.buffer.size());
+
+ memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info));
+
+ // TODO: allocated memory never released
+ using Kernel::MemoryPermission;
+ // Allocate a heap block of the required size for this applet.
+ heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
+ // Create a SharedMemory that directly points to this heap block.
+ framebuffer_memory = Kernel::SharedMemory::CreateForApplet(heap_memory, 0, heap_memory->size(),
+ MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
+ "ErrEula Memory");
+
+ // Send the response message with the newly created SharedMemory
+ Service::APT::MessageParameter result;
+ result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished);
+ result.buffer.clear();
+ result.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
+ result.sender_id = static_cast<u32>(id);
+ result.object = framebuffer_memory;
+
+ Service::APT::SendParameter(result);
+ return RESULT_SUCCESS;
+}
+
+ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parameter) {
+ started = true;
+
+ // TODO(Subv): Set the expected fields in the response buffer before resending it to the application.
+ // TODO(Subv): Reverse the parameter format for the ErrEula applet
+
+ // Let the application know that we're closing
+ Service::APT::MessageParameter message;
+ message.buffer.resize(parameter.buffer.size());
+ std::fill(message.buffer.begin(), message.buffer.end(), 0);
+ message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed);
+ message.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
+ message.sender_id = static_cast<u32>(id);
+ Service::APT::SendParameter(message);
+
+ started = false;
+ return RESULT_SUCCESS;
+}
+
+void ErrEula::Update() {
+}
+
+} // namespace Applets
+} // namespace HLE
diff --git a/src/core/hle/applets/erreula.h b/src/core/hle/applets/erreula.h
new file mode 100644
index 000000000..9fe72ae07
--- /dev/null
+++ b/src/core/hle/applets/erreula.h
@@ -0,0 +1,31 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/applets/applet.h"
+#include "core/hle/kernel/shared_memory.h"
+
+namespace HLE {
+namespace Applets {
+
+class ErrEula final : public Applet {
+public:
+ explicit ErrEula(Service::APT::AppletId id): Applet(id) { }
+
+ ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override;
+ ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
+ void Update() override;
+ bool IsRunning() const override { return started; }
+
+ /// This SharedMemory will be created when we receive the LibAppJustStarted message.
+ /// It holds the framebuffer info retrieved by the application with GSPGPU::ImportDisplayCaptureInfo
+ Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
+private:
+ /// Whether this applet is currently running instead of the host application or not.
+ bool started = false;
+};
+
+} // namespace Applets
+} // namespace HLE
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
index 6ddaf970e..26b086f87 100644
--- a/src/core/hle/kernel/session.h
+++ b/src/core/hle/kernel/session.h
@@ -32,6 +32,10 @@ constexpr u32 CallingPidDesc() {
return 0x20;
}
+constexpr u32 TransferHandleDesc() {
+ return 0x20;
+}
+
constexpr u32 StaticBufferDesc(u32 size, unsigned int buffer_id) {
return 0x2 | (size << 14) | ((buffer_id & 0xF) << 10);
}
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 3f6bec5fa..9dea995f4 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -182,6 +182,48 @@ static void PriorityBoostStarvedThreads() {
}
/**
+ * Gets the registers for timeout parameter of the next WaitSynchronization call.
+ * @param thread a pointer to the thread that is ready to call WaitSynchronization
+ * @returns a tuple of two register pointers to low and high part of the timeout parameter
+ */
+static std::tuple<u32*, u32*> GetWaitSynchTimeoutParameterRegister(Thread* thread) {
+ bool thumb_mode = (thread->context.cpsr & TBIT) != 0;
+ u16 thumb_inst = Memory::Read16(thread->context.pc & 0xFFFFFFFE);
+ u32 inst = Memory::Read32(thread->context.pc & 0xFFFFFFFC) & 0x0FFFFFFF;
+
+ if ((thumb_mode && thumb_inst == 0xDF24) || (!thumb_mode && inst == 0x0F000024)) {
+ // svc #0x24 (WaitSynchronization1)
+ return std::make_tuple(&thread->context.cpu_registers[2], &thread->context.cpu_registers[3]);
+ } else if ((thumb_mode && thumb_inst == 0xDF25) || (!thumb_mode && inst == 0x0F000025)) {
+ // svc #0x25 (WaitSynchronizationN)
+ return std::make_tuple(&thread->context.cpu_registers[0], &thread->context.cpu_registers[4]);
+ }
+
+ UNREACHABLE();
+}
+
+/**
+ * Updates the WaitSynchronization timeout paramter according to the difference
+ * between ticks of the last WaitSynchronization call and the incoming one.
+ * @param timeout_low a pointer to the register for the low part of the timeout parameter
+ * @param timeout_high a pointer to the register for the high part of the timeout parameter
+ * @param last_tick tick of the last WaitSynchronization call
+ */
+static void UpdateTimeoutParameter(u32* timeout_low, u32* timeout_high, u64 last_tick) {
+ s64 timeout = ((s64)*timeout_high << 32) | *timeout_low;
+
+ if (timeout != -1) {
+ timeout -= cyclesToUs(CoreTiming::GetTicks() - last_tick) * 1000; // in nanoseconds
+
+ if (timeout < 0)
+ timeout = 0;
+
+ *timeout_low = timeout & 0xFFFFFFFF;
+ *timeout_high = timeout >> 32;
+ }
+}
+
+/**
* Switches the CPU's active thread context to that of the specified thread
* @param new_thread The thread to switch to
*/
@@ -219,6 +261,13 @@ static void SwitchContext(Thread* new_thread) {
// SVC instruction is 2 bytes for THUMB, 4 bytes for ARM
new_thread->context.pc -= thumb_mode ? 2 : 4;
+
+ // Get the register for timeout parameter
+ u32* timeout_low, *timeout_high;
+ std::tie(timeout_low, timeout_high) = GetWaitSynchTimeoutParameterRegister(new_thread);
+
+ // Update the timeout parameter
+ UpdateTimeoutParameter(timeout_low, timeout_high, new_thread->last_running_ticks);
}
// Clean up the thread's wait_objects, they'll be restored if needed during
@@ -542,8 +591,12 @@ void Reschedule() {
HLE::DoneRescheduling();
- // Don't bother switching to the same thread
- if (next == cur)
+ // Don't bother switching to the same thread.
+ // But if the thread was waiting on objects, we still need to switch it
+ // to perform PC modification, change state to RUNNING, etc.
+ // This occurs in the case when an object the thread is waiting on immediately wakes up
+ // the current thread before Reschedule() is called.
+ if (next == cur && (next == nullptr || next->waitsynch_waited == false))
return;
if (cur && next) {
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 57dedcb22..68d6f5a87 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -135,15 +135,28 @@ enum class ErrorModule : u32 {
MCU = 72,
NS = 73,
News = 74,
- RO_1 = 75,
+ RO = 75,
GD = 76,
CardSPI = 77,
EC = 78,
- RO_2 = 79,
- WebBrowser = 80,
- Test = 81,
- ENC = 82,
- PIA = 83,
+ WebBrowser = 79,
+ Test = 80,
+ ENC = 81,
+ PIA = 82,
+ ACT = 83,
+ VCTL = 84,
+ OLV = 85,
+ NEIA = 86,
+ NPNS = 87,
+
+ AVD = 90,
+ L2B = 91,
+ MVD = 92,
+ NFC = 93,
+ UART = 94,
+ SPM = 95,
+ QTM = 96,
+ NFP = 97,
Application = 254,
InvalidResult = 255
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h
index 76b3a3807..53cee4867 100644
--- a/src/core/hle/service/apt/apt.h
+++ b/src/core/hle/service/apt/apt.h
@@ -66,6 +66,8 @@ enum class AppletId : u32 {
InstructionManual = 0x115,
Notifications = 0x116,
Miiverse = 0x117,
+ MiiversePost = 0x118,
+ AmiiboSettings = 0x119,
SoftwareKeyboard1 = 0x201,
Ed1 = 0x202,
PnoteApp = 0x204,
@@ -78,6 +80,12 @@ enum class AppletId : u32 {
AnyLibraryApplet = 0x400,
SoftwareKeyboard2 = 0x401,
Ed2 = 0x402,
+ PnoteApp2 = 0x404,
+ SnoteApp2 = 0x405,
+ Error2 = 0x406,
+ Mint2 = 0x407,
+ Extrapad2 = 0x408,
+ Memolib2 = 0x409,
};
enum class StartupArgumentType : u32 {
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index aae955bf8..8bd36d5ea 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -1,4 +1,4 @@
-// Copyright 2014 Citra Emulator Project
+// Copyright 2016 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -15,23 +15,64 @@ namespace SRV {
static Kernel::SharedPtr<Kernel::Event> event_handle;
-static void Initialize(Service::Interface* self) {
+/**
+ * SRV::RegisterClient service function
+ * Inputs:
+ * 0: 0x00010002
+ * 1: ProcessId Header (must be 0x20)
+ * Outputs:
+ * 0: 0x00010040
+ * 1: ResultCode
+ */
+static void RegisterClient(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- cmd_buff[1] = 0; // No error
+ if (cmd_buff[1] != IPC::CallingPidDesc()) {
+ cmd_buff[0] = IPC::MakeHeader(0x0, 0x1, 0); //0x40
+ cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
+ ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw;
+ return;
+ }
+ cmd_buff[0] = IPC::MakeHeader(0x1, 0x1, 0); //0x10040
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_SRV, "(STUBBED) called");
}
-static void GetProcSemaphore(Service::Interface* self) {
+/**
+ * SRV::EnableNotification service function
+ * Inputs:
+ * 0: 0x00020000
+ * Outputs:
+ * 0: 0x00020042
+ * 1: ResultCode
+ * 2: Translation descriptor: 0x20
+ * 3: Handle to semaphore signaled on process notification
+ */
+static void EnableNotification(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
// TODO(bunnei): Change to a semaphore once these have been implemented
event_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "SRV:Event");
event_handle->Clear();
- cmd_buff[1] = 0; // No error
+ cmd_buff[0] = IPC::MakeHeader(0x2, 0x1, 0x2); // 0x20042
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = IPC::TransferHandleDesc();
cmd_buff[3] = Kernel::g_handle_table.Create(event_handle).MoveFrom();
+ LOG_WARNING(Service_SRV, "(STUBBED) called");
}
+/**
+ * SRV::GetServiceHandle service function
+ * Inputs:
+ * 0: 0x00050100
+ * 1-2: 8-byte UTF-8 service name
+ * 3: Name length
+ * 4: Flags (bit0: if not set, return port-handle if session-handle unavailable)
+ * Outputs:
+ * 1: ResultCode
+ * 3: Service handle
+ */
static void GetServiceHandle(Service::Interface* self) {
ResultCode res = RESULT_SUCCESS;
u32* cmd_buff = Kernel::GetCommandBuffer();
@@ -49,16 +90,80 @@ static void GetServiceHandle(Service::Interface* self) {
cmd_buff[1] = res.raw;
}
+/**
+ * SRV::Subscribe service function
+ * Inputs:
+ * 0: 0x00090040
+ * 1: Notification ID
+ * Outputs:
+ * 0: 0x00090040
+ * 1: ResultCode
+ */
+static void Subscribe(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 notification_id = cmd_buff[1];
+
+ cmd_buff[0] = IPC::MakeHeader(0x9, 0x1, 0); // 0x90040
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id);
+}
+
+/**
+ * SRV::Unsubscribe service function
+ * Inputs:
+ * 0: 0x000A0040
+ * 1: Notification ID
+ * Outputs:
+ * 0: 0x000A0040
+ * 1: ResultCode
+ */
+static void Unsubscribe(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 notification_id = cmd_buff[1];
+
+ cmd_buff[0] = IPC::MakeHeader(0xA, 0x1, 0); // 0xA0040
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id);
+}
+
+/**
+ * SRV::PublishToSubscriber service function
+ * Inputs:
+ * 0: 0x000C0080
+ * 1: Notification ID
+ * 2: Flags (bit0: only fire if not fired, bit1: report errors)
+ * Outputs:
+ * 0: 0x000C0040
+ * 1: ResultCode
+ */
+static void PublishToSubscriber(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 notification_id = cmd_buff[1];
+ u8 flags = cmd_buff[2] & 0xFF;
+
+ cmd_buff[0] = IPC::MakeHeader(0xC, 0x1, 0); // 0xC0040
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X, flags=%u", notification_id, flags);
+}
+
const Interface::FunctionInfo FunctionTable[] = {
- {0x00010002, Initialize, "Initialize"},
- {0x00020000, GetProcSemaphore, "GetProcSemaphore"},
- {0x00030100, nullptr, "RegisterService"},
- {0x000400C0, nullptr, "UnregisterService"},
- {0x00050100, GetServiceHandle, "GetServiceHandle"},
- {0x000600C2, nullptr, "RegisterHandle"},
- {0x00090040, nullptr, "Subscribe"},
- {0x000B0000, nullptr, "ReceiveNotification"},
- {0x000C0080, nullptr, "PublishToSubscriber"},
+ {0x00010002, RegisterClient, "RegisterClient"},
+ {0x00020000, EnableNotification, "EnableNotification"},
+ {0x00030100, nullptr, "RegisterService"},
+ {0x000400C0, nullptr, "UnregisterService"},
+ {0x00050100, GetServiceHandle, "GetServiceHandle"},
+ {0x000600C2, nullptr, "RegisterPort"},
+ {0x000700C0, nullptr, "UnregisterPort"},
+ {0x00080100, nullptr, "GetPort"},
+ {0x00090040, Subscribe, "Subscribe"},
+ {0x000A0040, Unsubscribe, "Unsubscribe"},
+ {0x000B0000, nullptr, "ReceiveNotification"},
+ {0x000C0080, PublishToSubscriber, "PublishToSubscriber"},
+ {0x000D0040, nullptr, "PublishAndGetSubscriber"},
+ {0x000E00C0, nullptr, "IsServiceRegistered"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -66,10 +171,11 @@ const Interface::FunctionInfo FunctionTable[] = {
Interface::Interface() {
Register(FunctionTable);
+ event_handle = nullptr;
}
Interface::~Interface() {
event_handle = nullptr;
}
-} // namespace
+} // namespace SRV
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index 19e03adf4..689859049 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -423,6 +423,20 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) {
break;
}
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[0], 0xe8):
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[1], 0xe9):
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[2], 0xea):
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[3], 0xeb):
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[4], 0xec):
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[5], 0xed):
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[6], 0xee):
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[7], 0xef):
+ {
+ g_state.fog.lut[regs.fog_lut_offset % 128].raw = value;
+ regs.fog_lut_offset.Assign(regs.fog_lut_offset + 1);
+ break;
+ }
+
default:
break;
}
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index 871368323..bfa686380 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -328,7 +328,7 @@ std::unique_ptr<PicaTrace> FinishPicaTracing()
std::lock_guard<std::mutex> lock(pica_trace_mutex);
std::unique_ptr<PicaTrace> ret(std::move(pica_trace));
- return std::move(ret);
+ return ret;
}
const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info, bool disable_alpha) {
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index 544ea037f..7099c31a0 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -115,7 +115,28 @@ struct Regs {
BitField<24, 5, Semantic> map_w;
} vs_output_attributes[7];
- INSERT_PADDING_WORDS(0x11);
+ INSERT_PADDING_WORDS(0xe);
+
+ enum class ScissorMode : u32 {
+ Disabled = 0,
+ Exclude = 1, // Exclude pixels inside the scissor box
+
+ Include = 3 // Exclude pixels outside the scissor box
+ };
+
+ struct {
+ BitField<0, 2, ScissorMode> mode;
+
+ union {
+ BitField< 0, 16, u32> x1;
+ BitField<16, 16, u32> y1;
+ };
+
+ union {
+ BitField< 0, 16, u32> x2;
+ BitField<16, 16, u32> y2;
+ };
+ } scissor_test;
union {
BitField< 0, 10, s32> x;
@@ -401,22 +422,47 @@ struct Regs {
TevStageConfig tev_stage3;
INSERT_PADDING_WORDS(0x3);
+ enum class FogMode : u32 {
+ None = 0,
+ Fog = 5,
+ Gas = 7,
+ };
+
union {
- // Tev stages 0-3 write their output to the combiner buffer if the corresponding bit in
- // these masks are set
- BitField< 8, 4, u32> update_mask_rgb;
- BitField<12, 4, u32> update_mask_a;
+ BitField<0, 3, FogMode> fog_mode;
+ BitField<16, 1, u32> fog_flip;
- bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const {
- return (stage_index < 4) && (update_mask_rgb & (1 << stage_index));
- }
+ union {
+ // Tev stages 0-3 write their output to the combiner buffer if the corresponding bit in
+ // these masks are set
+ BitField< 8, 4, u32> update_mask_rgb;
+ BitField<12, 4, u32> update_mask_a;
- bool TevStageUpdatesCombinerBufferAlpha(unsigned stage_index) const {
- return (stage_index < 4) && (update_mask_a & (1 << stage_index));
- }
- } tev_combiner_buffer_input;
+ bool TevStageUpdatesCombinerBufferColor(unsigned stage_index) const {
+ return (stage_index < 4) && (update_mask_rgb & (1 << stage_index));
+ }
+
+ bool TevStageUpdatesCombinerBufferAlpha(unsigned stage_index) const {
+ return (stage_index < 4) && (update_mask_a & (1 << stage_index));
+ }
+ } tev_combiner_buffer_input;
+ };
+
+ union {
+ u32 raw;
+ BitField< 0, 8, u32> r;
+ BitField< 8, 8, u32> g;
+ BitField<16, 8, u32> b;
+ } fog_color;
+
+ INSERT_PADDING_WORDS(0x4);
+
+ BitField<0, 16, u32> fog_lut_offset;
+
+ INSERT_PADDING_WORDS(0x1);
+
+ u32 fog_lut_data[8];
- INSERT_PADDING_WORDS(0xf);
TevStageConfig tev_stage4;
INSERT_PADDING_WORDS(0x3);
TevStageConfig tev_stage5;
@@ -1303,6 +1349,7 @@ ASSERT_REG_POSITION(viewport_depth_range, 0x4d);
ASSERT_REG_POSITION(viewport_depth_near_plane, 0x4e);
ASSERT_REG_POSITION(vs_output_attributes[0], 0x50);
ASSERT_REG_POSITION(vs_output_attributes[1], 0x51);
+ASSERT_REG_POSITION(scissor_test, 0x65);
ASSERT_REG_POSITION(viewport_corner, 0x68);
ASSERT_REG_POSITION(depthmap_enable, 0x6D);
ASSERT_REG_POSITION(texture0_enable, 0x80);
@@ -1318,6 +1365,10 @@ ASSERT_REG_POSITION(tev_stage1, 0xc8);
ASSERT_REG_POSITION(tev_stage2, 0xd0);
ASSERT_REG_POSITION(tev_stage3, 0xd8);
ASSERT_REG_POSITION(tev_combiner_buffer_input, 0xe0);
+ASSERT_REG_POSITION(fog_mode, 0xe0);
+ASSERT_REG_POSITION(fog_color, 0xe1);
+ASSERT_REG_POSITION(fog_lut_offset, 0xe6);
+ASSERT_REG_POSITION(fog_lut_data, 0xe8);
ASSERT_REG_POSITION(tev_stage4, 0xf0);
ASSERT_REG_POSITION(tev_stage5, 0xf8);
ASSERT_REG_POSITION(tev_combiner_buffer_color, 0xfd);
diff --git a/src/video_core/pica_state.h b/src/video_core/pica_state.h
index 495174c25..01f4285a8 100644
--- a/src/video_core/pica_state.h
+++ b/src/video_core/pica_state.h
@@ -33,10 +33,10 @@ struct State {
u32 raw;
// LUT value, encoded as 12-bit fixed point, with 12 fraction bits
- BitField< 0, 12, u32> value;
+ BitField< 0, 12, u32> value; // 0.0.12 fixed point
// Used by HW for efficient interpolation, Citra does not use these
- BitField<12, 12, u32> difference;
+ BitField<12, 12, s32> difference; // 1.0.11 fixed point
float ToFloat() {
return static_cast<float>(value) / 4095.f;
@@ -46,6 +46,18 @@ struct State {
std::array<std::array<LutEntry, 256>, 24> luts;
} lighting;
+ struct {
+ union LutEntry {
+ // Used for raw access
+ u32 raw;
+
+ BitField< 0, 13, s32> difference; // 1.1.11 fixed point
+ BitField<13, 11, u32> value; // 0.0.11 fixed point
+ };
+
+ std::array<LutEntry, 128> lut;
+ } fog;
+
/// Current Pica command list
struct {
const u32* head_ptr;
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index 65168f05a..6f369a00e 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -338,12 +338,26 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
return;
}
- // TODO: Proper scissor rect test!
u16 min_x = std::min({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x});
u16 min_y = std::min({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y});
u16 max_x = std::max({vtxpos[0].x, vtxpos[1].x, vtxpos[2].x});
u16 max_y = std::max({vtxpos[0].y, vtxpos[1].y, vtxpos[2].y});
+ // Convert the scissor box coordinates to 12.4 fixed point
+ u16 scissor_x1 = (u16)( regs.scissor_test.x1 << 4);
+ u16 scissor_y1 = (u16)( regs.scissor_test.y1 << 4);
+ // x2,y2 have +1 added to cover the entire sub-pixel area
+ u16 scissor_x2 = (u16)((regs.scissor_test.x2 + 1) << 4);
+ u16 scissor_y2 = (u16)((regs.scissor_test.y2 + 1) << 4);
+
+ if (regs.scissor_test.mode == Regs::ScissorMode::Include) {
+ // Calculate the new bounds
+ min_x = std::max(min_x, scissor_x1);
+ min_y = std::max(min_y, scissor_y1);
+ max_x = std::min(max_x, scissor_x2);
+ max_y = std::min(max_y, scissor_y2);
+ }
+
min_x &= Fix12P4::IntMask();
min_y &= Fix12P4::IntMask();
max_x = ((max_x + Fix12P4::FracMask()) & Fix12P4::IntMask());
@@ -383,6 +397,13 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
for (u16 y = min_y + 8; y < max_y; y += 0x10) {
for (u16 x = min_x + 8; x < max_x; x += 0x10) {
+ // Do not process the pixel if it's inside the scissor box and the scissor mode is set to Exclude
+ if (regs.scissor_test.mode == Regs::ScissorMode::Exclude) {
+ if (x >= scissor_x1 && x < scissor_x2 &&
+ y >= scissor_y1 && y < scissor_y2)
+ continue;
+ }
+
// Calculate the barycentric coordinates w0, w1 and w2
int w0 = bias0 + SignedArea(vtxpos[1].xy(), vtxpos[2].xy(), {x, y});
int w1 = bias1 + SignedArea(vtxpos[2].xy(), vtxpos[0].xy(), {x, y});
@@ -398,6 +419,26 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
float24::FromFloat32(static_cast<float>(w2)));
float24 interpolated_w_inverse = float24::FromFloat32(1.0f) / Math::Dot(w_inverse, baricentric_coordinates);
+ // interpolated_z = z / w
+ float interpolated_z_over_w = (v0.screenpos[2].ToFloat32() * w0 +
+ v1.screenpos[2].ToFloat32() * w1 +
+ v2.screenpos[2].ToFloat32() * w2) / wsum;
+
+ // Not fully accurate. About 3 bits in precision are missing.
+ // Z-Buffer (z / w * scale + offset)
+ float depth_scale = float24::FromRaw(regs.viewport_depth_range).ToFloat32();
+ float depth_offset = float24::FromRaw(regs.viewport_depth_near_plane).ToFloat32();
+ float depth = interpolated_z_over_w * depth_scale + depth_offset;
+
+ // Potentially switch to W-Buffer
+ if (regs.depthmap_enable == Pica::Regs::DepthBuffering::WBuffering) {
+ // W-Buffer (z * scale + w * offset = (z / w * scale + offset) * w)
+ depth *= interpolated_w_inverse.ToFloat32() * wsum;
+ }
+
+ // Clamp the result
+ depth = MathUtil::Clamp(depth, 0.0f, 1.0f);
+
// Perspective correct attribute interpolation:
// Attribute values cannot be calculated by simple linear interpolation since
// they are not linear in screen space. For example, when interpolating a
@@ -833,6 +874,38 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
continue;
}
+ // Apply fog combiner
+ // Not fully accurate. We'd have to know what data type is used to
+ // store the depth etc. Using float for now until we know more
+ // about Pica datatypes
+ if (regs.fog_mode == Regs::FogMode::Fog) {
+ const Math::Vec3<u8> fog_color = {
+ static_cast<u8>(regs.fog_color.r.Value()),
+ static_cast<u8>(regs.fog_color.g.Value()),
+ static_cast<u8>(regs.fog_color.b.Value()),
+ };
+
+ // Get index into fog LUT
+ float fog_index;
+ if (g_state.regs.fog_flip) {
+ fog_index = (1.0f - depth) * 128.0f;
+ } else {
+ fog_index = depth * 128.0f;
+ }
+
+ // Generate clamped fog factor from LUT for given fog index
+ float fog_i = MathUtil::Clamp(floorf(fog_index), 0.0f, 127.0f);
+ float fog_f = fog_index - fog_i;
+ const auto& fog_lut_entry = g_state.fog.lut[static_cast<unsigned int>(fog_i)];
+ float fog_factor = (fog_lut_entry.value + fog_lut_entry.difference * fog_f) / 2047.0f; // This is signed fixed point 1.11
+ fog_factor = MathUtil::Clamp(fog_factor, 0.0f, 1.0f);
+
+ // Blend the fog
+ for (unsigned i = 0; i < 3; i++) {
+ combiner_output[i] = fog_factor * combiner_output[i] + (1.0f - fog_factor) * fog_color[i];
+ }
+ }
+
u8 old_stencil = 0;
auto UpdateStencil = [stencil_test, x, y, &old_stencil](Pica::Regs::StencilAction action) {
@@ -887,27 +960,6 @@ static void ProcessTriangleInternal(const Shader::OutputVertex& v0,
}
}
- // interpolated_z = z / w
- float interpolated_z_over_w = (v0.screenpos[2].ToFloat32() * w0 +
- v1.screenpos[2].ToFloat32() * w1 +
- v2.screenpos[2].ToFloat32() * w2) / wsum;
-
- // Not fully accurate. About 3 bits in precision are missing.
- // Z-Buffer (z / w * scale + offset)
- float depth_scale = float24::FromRaw(regs.viewport_depth_range).ToFloat32();
- float depth_offset = float24::FromRaw(regs.viewport_depth_near_plane).ToFloat32();
- float depth = interpolated_z_over_w * depth_scale + depth_offset;
-
- // Potentially switch to W-Buffer
- if (regs.depthmap_enable == Pica::Regs::DepthBuffering::WBuffering) {
-
- // W-Buffer (z * scale + w * offset = (z / w * scale + offset) * w)
- depth *= interpolated_w_inverse.ToFloat32() * wsum;
- }
-
- // Clamp the result
- depth = MathUtil::Clamp(depth, 0.0f, 1.0f);
-
// Convert float to integer
unsigned num_bits = Regs::DepthBitsPerPixel(regs.framebuffer.depth_format);
u32 z = (u32)(depth * ((1 << num_bits) - 1));
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 931c34a37..f8393c618 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -62,6 +62,8 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) {
uniform_block_data.lut_dirty[index] = true;
}
+ uniform_block_data.fog_lut_dirty = true;
+
// Set vertex attributes
glVertexAttribPointer(GLShader::ATTRIBUTE_POSITION, 4, GL_FLOAT, GL_FALSE, sizeof(HardwareVertex), (GLvoid*)offsetof(HardwareVertex, position));
glEnableVertexAttribArray(GLShader::ATTRIBUTE_POSITION);
@@ -102,6 +104,18 @@ RasterizerOpenGL::RasterizerOpenGL() : shader_dirty(true) {
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
+ // Setup the LUT for the fog
+ {
+ fog_lut.Create();
+ state.fog_lut.texture_1d = fog_lut.handle;
+ }
+ state.Apply();
+
+ glActiveTexture(GL_TEXTURE9);
+ glTexImage1D(GL_TEXTURE_1D, 0, GL_R32UI, 128, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, nullptr);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
// Sync fixed function OpenGL state
SyncCullMode();
SyncBlendEnabled();
@@ -182,6 +196,14 @@ void RasterizerOpenGL::DrawTriangles() {
(GLint)(rect.bottom + regs.viewport_corner.y * color_surface->res_scale_height),
(GLsizei)(viewport_width * color_surface->res_scale_width), (GLsizei)(viewport_height * color_surface->res_scale_height));
+ if (uniform_block_data.data.framebuffer_scale[0] != color_surface->res_scale_width ||
+ uniform_block_data.data.framebuffer_scale[1] != color_surface->res_scale_height) {
+
+ uniform_block_data.data.framebuffer_scale[0] = color_surface->res_scale_width;
+ uniform_block_data.data.framebuffer_scale[1] = color_surface->res_scale_height;
+ uniform_block_data.dirty = true;
+ }
+
// Sync and bind the texture surfaces
const auto pica_textures = regs.GetTextures();
for (unsigned texture_index = 0; texture_index < pica_textures.size(); ++texture_index) {
@@ -215,6 +237,12 @@ void RasterizerOpenGL::DrawTriangles() {
}
}
+ // Sync the fog lut
+ if (uniform_block_data.fog_lut_dirty) {
+ SyncFogLUT();
+ uniform_block_data.fog_lut_dirty = false;
+ }
+
// Sync the uniform data
if (uniform_block_data.dirty) {
glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformData), &uniform_block_data.data, GL_STATIC_DRAW);
@@ -280,6 +308,21 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
SyncBlendColor();
break;
+ // Fog state
+ case PICA_REG_INDEX(fog_color):
+ SyncFogColor();
+ break;
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[0], 0xe8):
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[1], 0xe9):
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[2], 0xea):
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[3], 0xeb):
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[4], 0xec):
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[5], 0xed):
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[6], 0xee):
+ case PICA_REG_INDEX_WORKAROUND(fog_lut_data[7], 0xef):
+ uniform_block_data.fog_lut_dirty = true;
+ break;
+
// Alpha test
case PICA_REG_INDEX(output_merger.alpha_test):
SyncAlphaTest();
@@ -318,6 +361,15 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
SyncColorWriteMask();
break;
+ // Scissor test
+ case PICA_REG_INDEX(scissor_test.mode):
+ shader_dirty = true;
+ break;
+ case PICA_REG_INDEX(scissor_test.x1): // and y1
+ case PICA_REG_INDEX(scissor_test.x2): // and y2
+ SyncScissorTest();
+ break;
+
// Logic op
case PICA_REG_INDEX(output_merger.logic_op):
SyncLogicOp();
@@ -329,6 +381,7 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) {
break;
// TEV stages
+ // (This also syncs fog_mode and fog_flip which are part of tev_combiner_buffer_input)
case PICA_REG_INDEX(tev_stage0.color_source1):
case PICA_REG_INDEX(tev_stage0.color_modifier1):
case PICA_REG_INDEX(tev_stage0.color_op):
@@ -950,9 +1003,15 @@ void RasterizerOpenGL::SetShader() {
uniform_lut = glGetUniformLocation(shader->shader.handle, "lut[5]");
if (uniform_lut != -1) { glUniform1i(uniform_lut, 8); }
+ GLuint uniform_fog_lut = glGetUniformLocation(shader->shader.handle, "fog_lut");
+ if (uniform_fog_lut != -1) { glUniform1i(uniform_fog_lut, 9); }
+
current_shader = shader_cache.emplace(config, std::move(shader)).first->second.get();
unsigned int block_index = glGetUniformBlockIndex(current_shader->shader.handle, "shader_data");
+ GLint block_size;
+ glGetActiveUniformBlockiv(current_shader->shader.handle, block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &block_size);
+ ASSERT_MSG(block_size == sizeof(UniformData), "Uniform block size did not match!");
glUniformBlockBinding(current_shader->shader.handle, block_index, 0);
// Update uniforms
@@ -960,6 +1019,7 @@ void RasterizerOpenGL::SetShader() {
SyncDepthOffset();
SyncAlphaTest();
SyncCombinerColor();
+ SyncScissorTest();
auto& tev_stages = Pica::g_state.regs.GetTevStages();
for (int index = 0; index < tev_stages.size(); ++index)
SyncTevConstColor(index, tev_stages[index]);
@@ -974,6 +1034,8 @@ void RasterizerOpenGL::SetShader() {
SyncLightDistanceAttenuationBias(light_index);
SyncLightDistanceAttenuationScale(light_index);
}
+
+ SyncFogColor();
}
}
@@ -1040,6 +1102,30 @@ void RasterizerOpenGL::SyncBlendColor() {
state.blend.color.alpha = blend_color[3];
}
+void RasterizerOpenGL::SyncFogColor() {
+ const auto& regs = Pica::g_state.regs;
+ uniform_block_data.data.fog_color = {
+ regs.fog_color.r.Value() / 255.0f,
+ regs.fog_color.g.Value() / 255.0f,
+ regs.fog_color.b.Value() / 255.0f
+ };
+ uniform_block_data.dirty = true;
+}
+
+void RasterizerOpenGL::SyncFogLUT() {
+ std::array<GLuint, 128> new_data;
+
+ std::transform(Pica::g_state.fog.lut.begin(), Pica::g_state.fog.lut.end(), new_data.begin(), [](const auto& entry) {
+ return entry.raw;
+ });
+
+ if (new_data != fog_lut_data) {
+ fog_lut_data = new_data;
+ glActiveTexture(GL_TEXTURE9);
+ glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 128, GL_RED_INTEGER, GL_UNSIGNED_INT, fog_lut_data.data());
+ }
+}
+
void RasterizerOpenGL::SyncAlphaTest() {
const auto& regs = Pica::g_state.regs;
if (regs.output_merger.alpha_test.ref != uniform_block_data.data.alphatest_ref) {
@@ -1098,6 +1184,22 @@ void RasterizerOpenGL::SyncDepthTest() {
PicaToGL::CompareFunc(regs.output_merger.depth_test_func) : GL_ALWAYS;
}
+void RasterizerOpenGL::SyncScissorTest() {
+ const auto& regs = Pica::g_state.regs;
+
+ if (uniform_block_data.data.scissor_x1 != regs.scissor_test.x1 ||
+ uniform_block_data.data.scissor_y1 != regs.scissor_test.y1 ||
+ uniform_block_data.data.scissor_x2 != regs.scissor_test.x2 ||
+ uniform_block_data.data.scissor_y2 != regs.scissor_test.y2) {
+
+ uniform_block_data.data.scissor_x1 = regs.scissor_test.x1;
+ uniform_block_data.data.scissor_y1 = regs.scissor_test.y1;
+ uniform_block_data.data.scissor_x2 = regs.scissor_test.x2;
+ uniform_block_data.data.scissor_y2 = regs.scissor_test.y2;
+ uniform_block_data.dirty = true;
+ }
+}
+
void RasterizerOpenGL::SyncCombinerColor() {
auto combiner_color = PicaToGL::ColorRGBA8(Pica::g_state.regs.tev_combiner_buffer_color.raw);
if (combiner_color != uniform_block_data.data.tev_combiner_buffer_color) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index bb7f20161..c5029432b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -56,6 +56,8 @@ union PicaShaderConfig {
const auto& regs = Pica::g_state.regs;
+ state.scissor_test_mode = regs.scissor_test.mode;
+
state.depthmap_enable = regs.depthmap_enable;
state.alpha_test_func = regs.output_merger.alpha_test.enable ?
@@ -76,6 +78,9 @@ union PicaShaderConfig {
state.tev_stages[i].scales_raw = tev_stage.scales_raw;
}
+ state.fog_mode = regs.fog_mode;
+ state.fog_flip = regs.fog_flip;
+
state.combiner_buffer_input =
regs.tev_combiner_buffer_input.update_mask_rgb.Value() |
regs.tev_combiner_buffer_input.update_mask_a.Value() << 4;
@@ -168,13 +173,15 @@ union PicaShaderConfig {
};
struct State {
-
Pica::Regs::CompareFunc alpha_test_func;
+ Pica::Regs::ScissorMode scissor_test_mode;
Pica::Regs::TextureConfig::TextureType texture0_type;
std::array<TevStageConfigRaw, 6> tev_stages;
u8 combiner_buffer_input;
Pica::Regs::DepthBuffering depthmap_enable;
+ Pica::Regs::FogMode fog_mode;
+ bool fog_flip;
struct {
struct {
@@ -316,19 +323,27 @@ private:
GLfloat dist_atten_scale;
};
- /// Uniform structure for the Uniform Buffer Object, all members must be 16-byte aligned
+ /// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned
+ // NOTE: Always keep a vec4 at the end. The GL spec is not clear wether the alignment at
+ // the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not.
+ // Not following that rule will cause problems on some AMD drivers.
struct UniformData {
- // A vec4 color for each of the six tev stages
- GLvec4 const_color[6];
- GLvec4 tev_combiner_buffer_color;
+ alignas(8) GLvec2 framebuffer_scale;
GLint alphatest_ref;
GLfloat depth_scale;
GLfloat depth_offset;
+ GLint scissor_x1;
+ GLint scissor_y1;
+ GLint scissor_x2;
+ GLint scissor_y2;
+ alignas(16) GLvec3 fog_color;
alignas(16) GLvec3 lighting_global_ambient;
LightSrc light_src[8];
+ alignas(16) GLvec4 const_color[6]; // A vec4 color for each of the six tev stages
+ alignas(16) GLvec4 tev_combiner_buffer_color;
};
- static_assert(sizeof(UniformData) == 0x390, "The size of the UniformData structure has changed, update the structure in the shader");
+ static_assert(sizeof(UniformData) == 0x3C0, "The size of the UniformData structure has changed, update the structure in the shader");
static_assert(sizeof(UniformData) < 16384, "UniformData structure must be less than 16kb as per the OpenGL spec");
/// Sets the OpenGL shader in accordance with the current PICA register state
@@ -352,6 +367,10 @@ private:
/// Syncs the blend color to match the PICA register
void SyncBlendColor();
+ /// Syncs the fog states to match the PICA register
+ void SyncFogColor();
+ void SyncFogLUT();
+
/// Syncs the alpha test states to match the PICA register
void SyncAlphaTest();
@@ -373,6 +392,9 @@ private:
/// Syncs the depth test states to match the PICA register
void SyncDepthTest();
+ /// Syncs the scissor test state to match the PICA register
+ void SyncScissorTest();
+
/// Syncs the TEV combiner color buffer to match the PICA register
void SyncCombinerColor();
@@ -419,6 +441,7 @@ private:
struct {
UniformData data;
bool lut_dirty[6];
+ bool fog_lut_dirty;
bool dirty;
} uniform_block_data = {};
@@ -430,4 +453,7 @@ private:
std::array<OGLTexture, 6> lighting_luts;
std::array<std::array<GLvec4, 256>, 6> lighting_lut_data{};
+
+ OGLTexture fog_lut;
+ std::array<GLuint, 128> fog_lut_data{};
};
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index 8332e722d..36513dedc 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -539,6 +539,8 @@ in float texcoord0_w;
in vec4 normquat;
in vec3 view;
+in vec4 gl_FragCoord;
+
out vec4 color;
struct LightSrc {
@@ -552,17 +554,24 @@ struct LightSrc {
};
layout (std140) uniform shader_data {
- vec4 const_color[NUM_TEV_STAGES];
- vec4 tev_combiner_buffer_color;
+ vec2 framebuffer_scale;
int alphatest_ref;
float depth_scale;
float depth_offset;
+ int scissor_x1;
+ int scissor_y1;
+ int scissor_x2;
+ int scissor_y2;
+ vec3 fog_color;
vec3 lighting_global_ambient;
LightSrc light_src[NUM_LIGHTS];
+ vec4 const_color[NUM_TEV_STAGES];
+ vec4 tev_combiner_buffer_color;
};
uniform sampler2D tex[3];
uniform sampler1D lut[6];
+uniform usampler1D fog_lut;
// Rotate the vector v by the quaternion q
vec3 quaternion_rotate(vec4 q, vec3 v) {
@@ -580,6 +589,25 @@ vec4 secondary_fragment_color = vec4(0.0);
return out;
}
+ // Append the scissor test
+ if (state.scissor_test_mode != Regs::ScissorMode::Disabled) {
+ out += "if (";
+ // Negate the condition if we have to keep only the pixels outside the scissor box
+ if (state.scissor_test_mode == Regs::ScissorMode::Include)
+ out += "!";
+ // x2,y2 have +1 added to cover the entire pixel area
+ out += "(gl_FragCoord.x >= scissor_x1 * framebuffer_scale.x && "
+ "gl_FragCoord.y >= scissor_y1 * framebuffer_scale.y && "
+ "gl_FragCoord.x < (scissor_x2 + 1) * framebuffer_scale.x && "
+ "gl_FragCoord.y < (scissor_y2 + 1) * framebuffer_scale.y)) discard;\n";
+ }
+
+ out += "float z_over_w = 1.0 - gl_FragCoord.z * 2.0;\n";
+ out += "float depth = z_over_w * depth_scale + depth_offset;\n";
+ if (state.depthmap_enable == Pica::Regs::DepthBuffering::WBuffering) {
+ out += "depth /= gl_FragCoord.w;\n";
+ }
+
if (state.lighting.enable)
WriteLighting(out, config);
@@ -596,14 +624,30 @@ vec4 secondary_fragment_color = vec4(0.0);
out += ") discard;\n";
}
- out += "color = last_tex_env_out;\n";
+ // Append fog combiner
+ if (state.fog_mode == Regs::FogMode::Fog) {
+ // Get index into fog LUT
+ if (state.fog_flip) {
+ out += "float fog_index = (1.0 - depth) * 128.0;\n";
+ } else {
+ out += "float fog_index = depth * 128.0;\n";
+ }
- out += "float z_over_w = 1.0 - gl_FragCoord.z * 2.0;\n";
- out += "float depth = z_over_w * depth_scale + depth_offset;\n";
- if (state.depthmap_enable == Pica::Regs::DepthBuffering::WBuffering) {
- out += "depth /= gl_FragCoord.w;\n";
+ // Generate clamped fog factor from LUT for given fog index
+ out += "float fog_i = clamp(floor(fog_index), 0.0, 127.0);\n";
+ out += "float fog_f = fog_index - fog_i;\n";
+ out += "uint fog_lut_entry = texelFetch(fog_lut, int(fog_i), 0).r;\n";
+ out += "float fog_lut_entry_difference = float(int((fog_lut_entry & 0x1FFFU) << 19U) >> 19);\n"; // Extract signed difference
+ out += "float fog_lut_entry_value = float((fog_lut_entry >> 13U) & 0x7FFU);\n";
+ out += "float fog_factor = (fog_lut_entry_value + fog_lut_entry_difference * fog_f) / 2047.0;\n";
+ out += "fog_factor = clamp(fog_factor, 0.0, 1.0);\n";
+
+ // Blend the fog
+ out += "last_tex_env_out.rgb = mix(fog_color.rgb, last_tex_env_out.rgb, fog_factor);\n";
}
+
out += "gl_FragDepth = depth;\n";
+ out += "color = last_tex_env_out;\n";
out += "}";
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index fa141fc9a..13ee986b9 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -58,6 +58,8 @@ OpenGLState::OpenGLState() {
lut.texture_1d = 0;
}
+ fog_lut.texture_1d = 0;
+
draw.read_framebuffer = 0;
draw.draw_framebuffer = 0;
draw.vertex_array = 0;
@@ -195,6 +197,12 @@ void OpenGLState::Apply() const {
}
}
+ // Fog LUT
+ if (fog_lut.texture_1d != cur_state.fog_lut.texture_1d) {
+ glActiveTexture(GL_TEXTURE9);
+ glBindTexture(GL_TEXTURE_1D, fog_lut.texture_1d);
+ }
+
// Framebuffer
if (draw.read_framebuffer != cur_state.draw.read_framebuffer) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer);
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 228727054..13c71b0a6 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -68,6 +68,10 @@ public:
} lighting_luts[6];
struct {
+ GLuint texture_1d; // GL_TEXTURE_BINDING_1D
+ } fog_lut;
+
+ struct {
GLuint read_framebuffer; // GL_READ_FRAMEBUFFER_BINDING
GLuint draw_framebuffer; // GL_DRAW_FRAMEBUFFER_BINDING
GLuint vertex_array; // GL_VERTEX_ARRAY_BINDING
diff --git a/src/video_core/renderer_opengl/pica_to_gl.h b/src/video_core/renderer_opengl/pica_to_gl.h
index 6dc2758c5..d9b9c9cc2 100644
--- a/src/video_core/renderer_opengl/pica_to_gl.h
+++ b/src/video_core/renderer_opengl/pica_to_gl.h
@@ -17,6 +17,7 @@
#include "video_core/pica.h"
+using GLvec2 = std::array<GLfloat, 2>;
using GLvec3 = std::array<GLfloat, 3>;
using GLvec4 = std::array<GLfloat, 4>;