From 7129611e65096ba2cbe8266f6cb068a9b18981d8 Mon Sep 17 00:00:00 2001 From: JamePeng Date: Wed, 20 Apr 2016 18:12:05 +0800 Subject: [PATCH 01/60] Implement CheckNew3DS and CheckNew3DSApp Append an item[is_new3ds] to config file[System] group Implement APT::SetNSStateField,it will update the unknown NS_state_field --- src/citra/config.cpp | 5 +-- src/citra_qt/config.cpp | 6 ++-- src/core/hle/service/apt/apt.cpp | 51 +++++++++++++++++++++++++++ src/core/hle/service/apt/apt.h | 44 +++++++++++++++++++++++ src/core/hle/service/apt/apt_a.cpp | 6 +++- src/core/hle/service/apt/apt_s.cpp | 8 +++-- src/core/hle/service/apt/apt_u.cpp | 8 +++-- src/core/hle/service/ptm/ptm.cpp | 16 ++++++++- src/core/hle/service/ptm/ptm.h | 8 +++++ src/core/hle/service/ptm/ptm_sysm.cpp | 4 +-- src/core/settings.h | 3 ++ 11 files changed, 145 insertions(+), 14 deletions(-) diff --git a/src/citra/config.cpp b/src/citra/config.cpp index 6b6617352..ebea5f840 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -73,8 +73,9 @@ void Config::ReadValues() { // Data Storage Settings::values.use_virtual_sd = sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); - // System Region - Settings::values.region_value = sdl2_config->GetInteger("System Region", "region_value", 1); + // System + Settings::values.is_new3ds = sdl2_config->GetBoolean("System", "is_new3ds", false); + Settings::values.region_value = sdl2_config->GetInteger("System", "region_value", 1); // Miscellaneous Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Info"); diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp index 8e247ff5c..66271aa7b 100644 --- a/src/citra_qt/config.cpp +++ b/src/citra_qt/config.cpp @@ -55,7 +55,8 @@ void Config::ReadValues() { Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool(); qt_config->endGroup(); - qt_config->beginGroup("System Region"); + qt_config->beginGroup("System"); + Settings::values.is_new3ds = qt_config->value("is_new3ds", false).toBool(); Settings::values.region_value = qt_config->value("region_value", 1).toInt(); qt_config->endGroup(); @@ -95,7 +96,8 @@ void Config::SaveValues() { qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd); qt_config->endGroup(); - qt_config->beginGroup("System Region"); + qt_config->beginGroup("System"); + qt_config->setValue("is_new3ds", Settings::values.is_new3ds); qt_config->setValue("region_value", Settings::values.region_value); qt_config->endGroup(); diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 6d72e8188..e6fcbc714 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -13,6 +13,7 @@ #include "core/hle/service/apt/apt_s.h" #include "core/hle/service/apt/apt_u.h" #include "core/hle/service/fs/archive.h" +#include "core/hle/service/ptm/ptm.h" #include "core/hle/kernel/event.h" #include "core/hle/kernel/mutex.h" @@ -41,6 +42,9 @@ static std::shared_ptr> shared_font; static u32 cpu_percent; ///< CPU time available to the running application +// APT::CheckNew3DSApp will check this unknown_ns_state_field to determine processing mode +static u8 unknown_ns_state_field; + /// Parameter data to be returned in the next call to Glance/ReceiveParameter static MessageParameter next_parameter; @@ -264,6 +268,10 @@ void PrepareToStartApplication(Service::Interface* self) { u32 title_info4 = cmd_buff[4]; u32 flags = cmd_buff[5]; + if (flags & 0x00000100) { + unknown_ns_state_field = 1; + } + cmd_buff[1] = RESULT_SUCCESS.raw; // No error LOG_WARNING(Service_APT, "(STUBBED) called title_info1=0x%08X, title_info2=0x%08X, title_info3=0x%08X," @@ -379,6 +387,25 @@ void StartLibraryApplet(Service::Interface* self) { cmd_buff[1] = applet->Start(parameter).raw; } +void SetNSStateField(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + unknown_ns_state_field = cmd_buff[1]; + + cmd_buff[0] = IPC::MakeHeader(0x55, 1, 0); + cmd_buff[1] = RESULT_SUCCESS.raw; + LOG_WARNING(Service_APT, "(STUBBED) unknown_ns_state_field=%u", unknown_ns_state_field); +} + +void GetNSStateField(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + cmd_buff[0] = IPC::MakeHeader(0x56, 2, 0); + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[8] = unknown_ns_state_field; + LOG_WARNING(Service_APT, "(STUBBED) unknown_ns_state_field=%u", unknown_ns_state_field); +} + void GetAppletInfo(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); auto app_id = static_cast(cmd_buff[1]); @@ -414,6 +441,29 @@ void GetStartupArgument(Service::Interface* self) { cmd_buff[2] = (parameter_size > 0) ? 1 : 0; } +void CheckNew3DSApp(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + if (unknown_ns_state_field) { + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[2] = 0; + } else { + PTM::CheckNew3DS(self); + } + + cmd_buff[0] = IPC::MakeHeader(0x101, 2, 0); + LOG_WARNING(Service_APT, "(STUBBED) called"); +} + +void CheckNew3DS(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + PTM::CheckNew3DS(self); + + cmd_buff[0] = IPC::MakeHeader(0x102, 2, 0); + LOG_WARNING(Service_APT, "(STUBBED) called"); +} + void Init() { AddService(new APT_A_Interface); AddService(new APT_S_Interface); @@ -449,6 +499,7 @@ void Init() { lock = Kernel::Mutex::Create(false, "APT_U:Lock"); cpu_percent = 0; + unknown_ns_state_field = 0; // TODO(bunnei): Check if these are created in Initialize or on APT process startup. notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification"); diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 668b4a66f..fd3c2bd37 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -361,6 +361,50 @@ void StartLibraryApplet(Service::Interface* self); */ void GetStartupArgument(Service::Interface* self); +/** + * APT::SetNSStateField service function + * Inputs: + * 1 : u8 NS state field + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * Note: + * This writes the input u8 to a NS state field. + */ +void SetNSStateField(Service::Interface* self); + +/** + * APT::GetNSStateField service function + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 8 : u8 NS state field + * Note: + * This returns a u8 NS state field(which can be set by cmd 0x00550040), at cmdreply+8. + */ +void GetNSStateField(Service::Interface* self); + +/** + * APT::CheckNew3DSApp service function + * Outputs: + * 1: Result code, 0 on success, otherwise error code + * 2: u8 output: 0 = Old3DS, 1 = New3DS. + * Note: + * This uses PTMSYSM:CheckNew3DS. + * When a certain NS state field is non-zero, the output value is zero, + * Otherwise the output is from PTMSYSM:CheckNew3DS. + * Normally this NS state field is zero, however this state field is set to 1 + * when APT:PrepareToStartApplication is used with flags bit8 is set. + */ +void CheckNew3DSApp(Service::Interface* self); + +/** + * Wrapper for PTMSYSM:CheckNew3DS + * APT::CheckNew3DS service function + * Outputs: + * 1: Result code, 0 on success, otherwise error code + * 2: u8 output: 0 = Old3DS, 1 = New3DS. + */ +void CheckNew3DS(Service::Interface* self); + /// Initialize the APT service void Init(); diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp index 9ff47701a..223c0a8bd 100644 --- a/src/core/hle/service/apt/apt_a.cpp +++ b/src/core/hle/service/apt/apt_a.cpp @@ -21,6 +21,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x000D0080, ReceiveParameter, "ReceiveParameter"}, {0x000E0080, GlanceParameter, "GlanceParameter"}, {0x000F0100, CancelParameter, "CancelParameter"}, + {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, @@ -32,7 +33,10 @@ const Interface::FunctionInfo FunctionTable[] = { {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, {0x00510080, GetStartupArgument, "GetStartupArgument"}, - {0x00550040, nullptr, "WriteInputToNsState?"}, + {0x00550040, SetNSStateField, "SetNSStateField?"}, + {0x00560000, GetNSStateField, "GetNSStateField?"}, + {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, + {0x01020000, CheckNew3DS, "CheckNew3DS"} }; APT_A_Interface::APT_A_Interface() { diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp index ca54e593c..f5c52fa3d 100644 --- a/src/core/hle/service/apt/apt_s.cpp +++ b/src/core/hle/service/apt/apt_s.cpp @@ -29,7 +29,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, {0x00130000, nullptr, "GetPreparationState"}, {0x00140040, nullptr, "SetPreparationState"}, - {0x00150140, nullptr, "PrepareToStartApplication"}, + {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, {0x00180040, PrepareToStartLibraryApplet,"PrepareToStartLibraryApplet"}, @@ -92,9 +92,11 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00510080, GetStartupArgument, "GetStartupArgument"}, {0x00520104, nullptr, "Wrap1"}, {0x00530104, nullptr, "Unwrap1"}, + {0x00550040, SetNSStateField, "SetNSStateField?" }, + {0x00560000, GetNSStateField, "GetNSStateField?" }, {0x00580002, nullptr, "GetProgramID"}, - {0x01010000, nullptr, "CheckNew3DSApp"}, - {0x01020000, nullptr, "CheckNew3DS"} + {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, + {0x01020000, CheckNew3DS, "CheckNew3DS"} }; APT_S_Interface::APT_S_Interface() { diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp index 0e85c6d08..0e60bd34f 100644 --- a/src/core/hle/service/apt/apt_u.cpp +++ b/src/core/hle/service/apt/apt_u.cpp @@ -29,7 +29,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, {0x00130000, nullptr, "GetPreparationState"}, {0x00140040, nullptr, "SetPreparationState"}, - {0x00150140, nullptr, "PrepareToStartApplication"}, + {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, @@ -92,9 +92,11 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00510080, GetStartupArgument, "GetStartupArgument"}, {0x00520104, nullptr, "Wrap1"}, {0x00530104, nullptr, "Unwrap1"}, + {0x00550040, SetNSStateField, "SetNSStateField?"}, + {0x00560000, GetNSStateField, "GetNSStateField?"}, {0x00580002, nullptr, "GetProgramID"}, - {0x01010000, nullptr, "CheckNew3DSApp"}, - {0x01020000, nullptr, "CheckNew3DS"} + {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, + {0x01020000, CheckNew3DS, "CheckNew3DS"} }; APT_U_Interface::APT_U_Interface() { diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index 94f494690..3a0331ee1 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp @@ -3,7 +3,7 @@ // Refer to the license.txt file included. #include "common/logging/log.h" - +#include "core/settings.h" #include "core/file_sys/file_backend.h" #include "core/hle/service/fs/archive.h" #include "core/hle/service/ptm/ptm.h" @@ -89,6 +89,20 @@ void IsLegacyPowerOff(Service::Interface* self) { LOG_WARNING(Service_PTM, "(STUBBED) called"); } +void CheckNew3DS(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + const bool is_new_3ds = Settings::values.is_new3ds; + + if (is_new_3ds) { + LOG_CRITICAL(Service_PTM, "The option 'is_new3ds' is enabled as part of the 'System' settings. Citra does not fully support New3DS emulation yet!"); + } + + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[2] = is_new_3ds ? 1 : 0; + + LOG_WARNING(Service_PTM, "(STUBBED) called isNew3DS = 0x%08x", static_cast(is_new_3ds)); +} + void Init() { AddService(new PTM_Play_Interface); AddService(new PTM_Sysm_Interface); diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h index 4cf7383d1..7ef8877c7 100644 --- a/src/core/hle/service/ptm/ptm.h +++ b/src/core/hle/service/ptm/ptm.h @@ -88,6 +88,14 @@ void GetTotalStepCount(Interface* self); */ void IsLegacyPowerOff(Interface* self); +/** + * PTM::CheckNew3DS service function + * Outputs: + * 1: Result code, 0 on success, otherwise error code + * 2: u8 output: 0 = Old3DS, 1 = New3DS. + */ +void CheckNew3DS(Interface* self); + /// Initialize the PTM service void Init(); diff --git a/src/core/hle/service/ptm/ptm_sysm.cpp b/src/core/hle/service/ptm/ptm_sysm.cpp index fe76dd108..cc4ef1101 100644 --- a/src/core/hle/service/ptm/ptm_sysm.cpp +++ b/src/core/hle/service/ptm/ptm_sysm.cpp @@ -18,7 +18,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x040700C0, nullptr, "ShutdownAsync"}, {0x04080000, nullptr, "Awake"}, {0x04090080, nullptr, "RebootAsync"}, - {0x040A0000, nullptr, "CheckNew3DS"}, + {0x040A0000, CheckNew3DS, "CheckNew3DS"}, {0x08010640, nullptr, "SetInfoLEDPattern"}, {0x08020040, nullptr, "SetInfoLEDPatternHeader"}, {0x08030000, nullptr, "GetInfoLEDStatus"}, @@ -35,7 +35,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x080E0140, nullptr, "NotifyPlayEvent"}, {0x080F0000, IsLegacyPowerOff, "IsLegacyPowerOff"}, {0x08100000, nullptr, "ClearLegacyPowerOff"}, - {0x08110000, nullptr, "GetShellStatus"}, + {0x08110000, GetShellState, "GetShellState"}, {0x08120000, nullptr, "IsShutdownByBatteryEmpty"}, {0x08130000, nullptr, "FormatSavedata"}, {0x08140000, nullptr, "GetLegacyJumpProhibitedFlag"}, diff --git a/src/core/settings.h b/src/core/settings.h index 97ddcdff9..4034b795a 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -40,6 +40,9 @@ static const std::array All = {{ struct Values { + // CheckNew3DS + bool is_new3ds; + // Controls std::array input_mappings; From 9b66e0dc8bec0bff0b211fb45c2c34cf93430be5 Mon Sep 17 00:00:00 2001 From: wwylele Date: Tue, 3 May 2016 19:27:47 +0300 Subject: [PATCH 02/60] clean up config block --- src/core/hle/service/cfg/cfg.cpp | 42 ++++++++++---------------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index b9322c55d..acc509cb0 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -47,6 +47,12 @@ struct UsernameBlock { }; static_assert(sizeof(UsernameBlock) == 0x1C, "UsernameBlock must be exactly 0x1C bytes"); +struct BirthdayBlock { + u8 month; ///< The month of the birthday + u8 day; ///< The day of the birthday +}; +static_assert(sizeof(BirthdayBlock) == 2, "BirthdayBlock must be exactly 2 bytes"); + struct ConsoleModelInfo { u8 model; ///< The console model (3DS, 2DS, etc) u8 unknown[3]; ///< Unknown data @@ -65,9 +71,8 @@ static const u64 CFG_SAVE_ID = 0x00010017; static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE; static const ConsoleModelInfo CONSOLE_MODEL = { NINTENDO_3DS_XL, { 0, 0, 0 } }; static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN; -static const char CONSOLE_USERNAME[0x14] = "CITRA"; -/// This will be initialized in Init, and will be used when creating the block -static UsernameBlock CONSOLE_USERNAME_BLOCK; +static const UsernameBlock CONSOLE_USERNAME_BLOCK = { u"CITRA", 0, 0 }; +static const BirthdayBlock PROFILE_BIRTHDAY = { 3, 25 }; // March 25th, 2014 /// TODO(Subv): Find out what this actually is static const u8 SOUND_OUTPUT_MODE = 2; static const u8 UNITED_STATES_COUNTRY_ID = 49; @@ -329,32 +334,22 @@ ResultCode FormatConfig() { res = CreateConfigInfoBlk(0x00050005, sizeof(STEREO_CAMERA_SETTINGS), 0xE, STEREO_CAMERA_SETTINGS.data()); if (!res.IsSuccess()) return res; + res = CreateConfigInfoBlk(0x00070001, sizeof(SOUND_OUTPUT_MODE), 0xE, &SOUND_OUTPUT_MODE); if (!res.IsSuccess()) return res; + res = CreateConfigInfoBlk(0x00090001, sizeof(CONSOLE_UNIQUE_ID), 0xE, &CONSOLE_UNIQUE_ID); if (!res.IsSuccess()) return res; + res = CreateConfigInfoBlk(0x000A0000, sizeof(CONSOLE_USERNAME_BLOCK), 0xE, &CONSOLE_USERNAME_BLOCK); if (!res.IsSuccess()) return res; - // 0x000A0000 - Profile username - struct { - u16_le username[10]; - u8 unused[4]; - u32_le wordfilter_version; // Unused by Citra - } profile_username = {}; - - std::u16string username_string = Common::UTF8ToUTF16("Citra"); - std::copy(username_string.cbegin(), username_string.cend(), profile_username.username); - res = CreateConfigInfoBlk(0x000A0000, sizeof(profile_username), 0xE, &profile_username); - if (!res.IsSuccess()) return res; - - // 0x000A0001 - Profile birthday - const u8 profile_birthday[2] = {3, 25}; // March 25th, 2014 - res = CreateConfigInfoBlk(0x000A0001, sizeof(profile_birthday), 0xE, profile_birthday); + res = CreateConfigInfoBlk(0x000A0001, sizeof(PROFILE_BIRTHDAY), 0xE, &PROFILE_BIRTHDAY); if (!res.IsSuccess()) return res; res = CreateConfigInfoBlk(0x000A0002, sizeof(CONSOLE_LANGUAGE), 0xE, &CONSOLE_LANGUAGE); if (!res.IsSuccess()) return res; + res = CreateConfigInfoBlk(0x000B0000, sizeof(COUNTRY_INFO), 0xE, &COUNTRY_INFO); if (!res.IsSuccess()) return res; @@ -435,17 +430,6 @@ void Init() { return; } - // Initialize the Username block - // TODO(Subv): Initialize this directly in the variable when MSVC supports char16_t string literals - memset(&CONSOLE_USERNAME_BLOCK, 0, sizeof(CONSOLE_USERNAME_BLOCK)); - CONSOLE_USERNAME_BLOCK.ng_word = 0; - CONSOLE_USERNAME_BLOCK.zero = 0; - - // Copy string to buffer and pad with zeros at the end - auto size = Common::UTF8ToUTF16(CONSOLE_USERNAME).copy(CONSOLE_USERNAME_BLOCK.username, 0x14); - std::fill(std::begin(CONSOLE_USERNAME_BLOCK.username) + size, - std::end(CONSOLE_USERNAME_BLOCK.username), 0); - FormatConfig(); } From 7d7849d71ade8585381abe9cbdc54ed3492979f0 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 9 Apr 2016 18:23:15 +0200 Subject: [PATCH 03/60] citra_qt: Replace 'Pica Framebuffer Debugger' with 'Pica Surface Viewer' --- src/citra_qt/CMakeLists.txt | 4 +- src/citra_qt/debugger/graphics_cmdlists.cpp | 125 +-- src/citra_qt/debugger/graphics_cmdlists.h | 22 - .../debugger/graphics_framebuffer.cpp | 356 --------- src/citra_qt/debugger/graphics_framebuffer.h | 76 -- src/citra_qt/debugger/graphics_surface.cpp | 736 ++++++++++++++++++ src/citra_qt/debugger/graphics_surface.h | 120 +++ src/citra_qt/main.cpp | 19 +- src/citra_qt/main.h | 1 + 9 files changed, 876 insertions(+), 583 deletions(-) delete mode 100644 src/citra_qt/debugger/graphics_framebuffer.cpp delete mode 100644 src/citra_qt/debugger/graphics_framebuffer.h create mode 100644 src/citra_qt/debugger/graphics_surface.cpp create mode 100644 src/citra_qt/debugger/graphics_surface.h diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index 3f0099200..2c7e80106 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -11,7 +11,7 @@ set(SRCS debugger/graphics_breakpoint_observer.cpp debugger/graphics_breakpoints.cpp debugger/graphics_cmdlists.cpp - debugger/graphics_framebuffer.cpp + debugger/graphics_surface.cpp debugger/graphics_tracing.cpp debugger/graphics_vertex_shader.cpp debugger/profiler.cpp @@ -42,7 +42,7 @@ set(HEADERS debugger/graphics_breakpoints.h debugger/graphics_breakpoints_p.h debugger/graphics_cmdlists.h - debugger/graphics_framebuffer.h + debugger/graphics_surface.h debugger/graphics_tracing.h debugger/graphics_vertex_shader.h debugger/profiler.h diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp index 5186d2b44..3e0a0a145 100644 --- a/src/citra_qt/debugger/graphics_cmdlists.cpp +++ b/src/citra_qt/debugger/graphics_cmdlists.cpp @@ -50,123 +50,6 @@ public: } }; -TextureInfoDockWidget::TextureInfoDockWidget(const Pica::DebugUtils::TextureInfo& info, QWidget* parent) - : QDockWidget(tr("Texture 0x%1").arg(info.physical_address, 8, 16, QLatin1Char('0'))), - info(info) { - - QWidget* main_widget = new QWidget; - - QLabel* image_widget = new QLabel; - - connect(this, SIGNAL(UpdatePixmap(const QPixmap&)), image_widget, SLOT(setPixmap(const QPixmap&))); - - CSpinBox* phys_address_spinbox = new CSpinBox; - phys_address_spinbox->SetBase(16); - phys_address_spinbox->SetRange(0, 0xFFFFFFFF); - phys_address_spinbox->SetPrefix("0x"); - phys_address_spinbox->SetValue(info.physical_address); - connect(phys_address_spinbox, SIGNAL(ValueChanged(qint64)), this, SLOT(OnAddressChanged(qint64))); - - QComboBox* format_choice = new QComboBox; - format_choice->addItem(tr("RGBA8")); - format_choice->addItem(tr("RGB8")); - format_choice->addItem(tr("RGB5A1")); - format_choice->addItem(tr("RGB565")); - format_choice->addItem(tr("RGBA4")); - format_choice->addItem(tr("IA8")); - format_choice->addItem(tr("RG8")); - format_choice->addItem(tr("I8")); - format_choice->addItem(tr("A8")); - format_choice->addItem(tr("IA4")); - format_choice->addItem(tr("I4")); - format_choice->addItem(tr("A4")); - format_choice->addItem(tr("ETC1")); - format_choice->addItem(tr("ETC1A4")); - format_choice->setCurrentIndex(static_cast(info.format)); - connect(format_choice, SIGNAL(currentIndexChanged(int)), this, SLOT(OnFormatChanged(int))); - - QSpinBox* width_spinbox = new QSpinBox; - width_spinbox->setMaximum(65535); - width_spinbox->setValue(info.width); - connect(width_spinbox, SIGNAL(valueChanged(int)), this, SLOT(OnWidthChanged(int))); - - QSpinBox* height_spinbox = new QSpinBox; - height_spinbox->setMaximum(65535); - height_spinbox->setValue(info.height); - connect(height_spinbox, SIGNAL(valueChanged(int)), this, SLOT(OnHeightChanged(int))); - - QSpinBox* stride_spinbox = new QSpinBox; - stride_spinbox->setMaximum(65535 * 4); - stride_spinbox->setValue(info.stride); - connect(stride_spinbox, SIGNAL(valueChanged(int)), this, SLOT(OnStrideChanged(int))); - - QVBoxLayout* main_layout = new QVBoxLayout; - main_layout->addWidget(image_widget); - - { - QHBoxLayout* sub_layout = new QHBoxLayout; - sub_layout->addWidget(new QLabel(tr("Source Address:"))); - sub_layout->addWidget(phys_address_spinbox); - main_layout->addLayout(sub_layout); - } - - { - QHBoxLayout* sub_layout = new QHBoxLayout; - sub_layout->addWidget(new QLabel(tr("Format"))); - sub_layout->addWidget(format_choice); - main_layout->addLayout(sub_layout); - } - - { - QHBoxLayout* sub_layout = new QHBoxLayout; - sub_layout->addWidget(new QLabel(tr("Width:"))); - sub_layout->addWidget(width_spinbox); - sub_layout->addStretch(); - sub_layout->addWidget(new QLabel(tr("Height:"))); - sub_layout->addWidget(height_spinbox); - sub_layout->addStretch(); - sub_layout->addWidget(new QLabel(tr("Stride:"))); - sub_layout->addWidget(stride_spinbox); - main_layout->addLayout(sub_layout); - } - - main_widget->setLayout(main_layout); - - emit UpdatePixmap(ReloadPixmap()); - - setWidget(main_widget); -} - -void TextureInfoDockWidget::OnAddressChanged(qint64 value) { - info.physical_address = value; - emit UpdatePixmap(ReloadPixmap()); -} - -void TextureInfoDockWidget::OnFormatChanged(int value) { - info.format = static_cast(value); - emit UpdatePixmap(ReloadPixmap()); -} - -void TextureInfoDockWidget::OnWidthChanged(int value) { - info.width = value; - emit UpdatePixmap(ReloadPixmap()); -} - -void TextureInfoDockWidget::OnHeightChanged(int value) { - info.height = value; - emit UpdatePixmap(ReloadPixmap()); -} - -void TextureInfoDockWidget::OnStrideChanged(int value) { - info.stride = value; - emit UpdatePixmap(ReloadPixmap()); -} - -QPixmap TextureInfoDockWidget::ReloadPixmap() const { - u8* src = Memory::GetPhysicalPointer(info.physical_address); - return QPixmap::fromImage(LoadTexture(src, info)); -} - GPUCommandListModel::GPUCommandListModel(QObject* parent) : QAbstractListModel(parent) { } @@ -249,16 +132,16 @@ void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) { index = 0; } else if (COMMAND_IN_RANGE(command_id, texture1)) { index = 1; - } else { + } else if (COMMAND_IN_RANGE(command_id, texture2)) { index = 2; + } else { + UNREACHABLE_MSG("Unknown texture command"); } auto config = Pica::g_state.regs.GetTextures()[index].config; auto format = Pica::g_state.regs.GetTextures()[index].format; auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config, format); - // TODO: Instead, emit a signal here to be caught by the main window widget. - auto main_window = static_cast(parent()); - main_window->tabifyDockWidget(this, new TextureInfoDockWidget(info, main_window)); + // TODO: Open a surface debugger } } diff --git a/src/citra_qt/debugger/graphics_cmdlists.h b/src/citra_qt/debugger/graphics_cmdlists.h index 586cc7239..8a2a294b9 100644 --- a/src/citra_qt/debugger/graphics_cmdlists.h +++ b/src/citra_qt/debugger/graphics_cmdlists.h @@ -61,25 +61,3 @@ private: QWidget* command_info_widget; QPushButton* toggle_tracing; }; - -class TextureInfoDockWidget : public QDockWidget { - Q_OBJECT - -public: - TextureInfoDockWidget(const Pica::DebugUtils::TextureInfo& info, QWidget* parent = nullptr); - -signals: - void UpdatePixmap(const QPixmap& pixmap); - -private slots: - void OnAddressChanged(qint64 value); - void OnFormatChanged(int value); - void OnWidthChanged(int value); - void OnHeightChanged(int value); - void OnStrideChanged(int value); - -private: - QPixmap ReloadPixmap() const; - - Pica::DebugUtils::TextureInfo info; -}; diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp deleted file mode 100644 index 68cff78b2..000000000 --- a/src/citra_qt/debugger/graphics_framebuffer.cpp +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include -#include -#include -#include -#include - -#include "citra_qt/debugger/graphics_framebuffer.h" -#include "citra_qt/util/spinbox.h" - -#include "common/color.h" - -#include "core/memory.h" -#include "core/hw/gpu.h" - -#include "video_core/pica.h" -#include "video_core/pica_state.h" -#include "video_core/utils.h" - -GraphicsFramebufferWidget::GraphicsFramebufferWidget(std::shared_ptr debug_context, - QWidget* parent) - : BreakPointObserverDock(debug_context, tr("Pica Framebuffer"), parent), - framebuffer_source(Source::PicaTarget) -{ - setObjectName("PicaFramebuffer"); - - framebuffer_source_list = new QComboBox; - framebuffer_source_list->addItem(tr("Active Render Target")); - framebuffer_source_list->addItem(tr("Active Depth Buffer")); - framebuffer_source_list->addItem(tr("Custom")); - framebuffer_source_list->setCurrentIndex(static_cast(framebuffer_source)); - - framebuffer_address_control = new CSpinBox; - framebuffer_address_control->SetBase(16); - framebuffer_address_control->SetRange(0, 0xFFFFFFFF); - framebuffer_address_control->SetPrefix("0x"); - - framebuffer_width_control = new QSpinBox; - framebuffer_width_control->setMinimum(1); - framebuffer_width_control->setMaximum(std::numeric_limits::max()); // TODO: Find actual maximum - - framebuffer_height_control = new QSpinBox; - framebuffer_height_control->setMinimum(1); - framebuffer_height_control->setMaximum(std::numeric_limits::max()); // TODO: Find actual maximum - - framebuffer_format_control = new QComboBox; - framebuffer_format_control->addItem(tr("RGBA8")); - framebuffer_format_control->addItem(tr("RGB8")); - framebuffer_format_control->addItem(tr("RGB5A1")); - framebuffer_format_control->addItem(tr("RGB565")); - framebuffer_format_control->addItem(tr("RGBA4")); - framebuffer_format_control->addItem(tr("D16")); - framebuffer_format_control->addItem(tr("D24")); - framebuffer_format_control->addItem(tr("D24X8")); - framebuffer_format_control->addItem(tr("X24S8")); - framebuffer_format_control->addItem(tr("(unknown)")); - - // TODO: This QLabel should shrink the image to the available space rather than just expanding... - framebuffer_picture_label = new QLabel; - - auto enlarge_button = new QPushButton(tr("Enlarge")); - - // Connections - connect(this, SIGNAL(Update()), this, SLOT(OnUpdate())); - connect(framebuffer_source_list, SIGNAL(currentIndexChanged(int)), this, SLOT(OnFramebufferSourceChanged(int))); - connect(framebuffer_address_control, SIGNAL(ValueChanged(qint64)), this, SLOT(OnFramebufferAddressChanged(qint64))); - connect(framebuffer_width_control, SIGNAL(valueChanged(int)), this, SLOT(OnFramebufferWidthChanged(int))); - connect(framebuffer_height_control, SIGNAL(valueChanged(int)), this, SLOT(OnFramebufferHeightChanged(int))); - connect(framebuffer_format_control, SIGNAL(currentIndexChanged(int)), this, SLOT(OnFramebufferFormatChanged(int))); - - auto main_widget = new QWidget; - auto main_layout = new QVBoxLayout; - { - auto sub_layout = new QHBoxLayout; - sub_layout->addWidget(new QLabel(tr("Source:"))); - sub_layout->addWidget(framebuffer_source_list); - main_layout->addLayout(sub_layout); - } - { - auto sub_layout = new QHBoxLayout; - sub_layout->addWidget(new QLabel(tr("Virtual Address:"))); - sub_layout->addWidget(framebuffer_address_control); - main_layout->addLayout(sub_layout); - } - { - auto sub_layout = new QHBoxLayout; - sub_layout->addWidget(new QLabel(tr("Width:"))); - sub_layout->addWidget(framebuffer_width_control); - main_layout->addLayout(sub_layout); - } - { - auto sub_layout = new QHBoxLayout; - sub_layout->addWidget(new QLabel(tr("Height:"))); - sub_layout->addWidget(framebuffer_height_control); - main_layout->addLayout(sub_layout); - } - { - auto sub_layout = new QHBoxLayout; - sub_layout->addWidget(new QLabel(tr("Format:"))); - sub_layout->addWidget(framebuffer_format_control); - main_layout->addLayout(sub_layout); - } - main_layout->addWidget(framebuffer_picture_label); - main_layout->addWidget(enlarge_button); - main_widget->setLayout(main_layout); - setWidget(main_widget); - - // Load current data - TODO: Make sure this works when emulation is not running - if (debug_context && debug_context->at_breakpoint) - emit Update(); - widget()->setEnabled(false); // TODO: Only enable if currently at breakpoint -} - -void GraphicsFramebufferWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) -{ - emit Update(); - widget()->setEnabled(true); -} - -void GraphicsFramebufferWidget::OnResumed() -{ - widget()->setEnabled(false); -} - -void GraphicsFramebufferWidget::OnFramebufferSourceChanged(int new_value) -{ - framebuffer_source = static_cast(new_value); - emit Update(); -} - -void GraphicsFramebufferWidget::OnFramebufferAddressChanged(qint64 new_value) -{ - if (framebuffer_address != new_value) { - framebuffer_address = static_cast(new_value); - - framebuffer_source_list->setCurrentIndex(static_cast(Source::Custom)); - emit Update(); - } -} - -void GraphicsFramebufferWidget::OnFramebufferWidthChanged(int new_value) -{ - if (framebuffer_width != static_cast(new_value)) { - framebuffer_width = static_cast(new_value); - - framebuffer_source_list->setCurrentIndex(static_cast(Source::Custom)); - emit Update(); - } -} - -void GraphicsFramebufferWidget::OnFramebufferHeightChanged(int new_value) -{ - if (framebuffer_height != static_cast(new_value)) { - framebuffer_height = static_cast(new_value); - - framebuffer_source_list->setCurrentIndex(static_cast(Source::Custom)); - emit Update(); - } -} - -void GraphicsFramebufferWidget::OnFramebufferFormatChanged(int new_value) -{ - if (framebuffer_format != static_cast(new_value)) { - framebuffer_format = static_cast(new_value); - - framebuffer_source_list->setCurrentIndex(static_cast(Source::Custom)); - emit Update(); - } -} - -void GraphicsFramebufferWidget::OnUpdate() -{ - QPixmap pixmap; - - switch (framebuffer_source) { - case Source::PicaTarget: - { - // TODO: Store a reference to the registers in the debug context instead of accessing them directly... - - const auto& framebuffer = Pica::g_state.regs.framebuffer; - - framebuffer_address = framebuffer.GetColorBufferPhysicalAddress(); - framebuffer_width = framebuffer.GetWidth(); - framebuffer_height = framebuffer.GetHeight(); - - switch (framebuffer.color_format) { - case Pica::Regs::ColorFormat::RGBA8: - framebuffer_format = Format::RGBA8; - break; - - case Pica::Regs::ColorFormat::RGB8: - framebuffer_format = Format::RGB8; - break; - - case Pica::Regs::ColorFormat::RGB5A1: - framebuffer_format = Format::RGB5A1; - break; - - case Pica::Regs::ColorFormat::RGB565: - framebuffer_format = Format::RGB565; - break; - - case Pica::Regs::ColorFormat::RGBA4: - framebuffer_format = Format::RGBA4; - break; - - default: - framebuffer_format = Format::Unknown; - break; - } - - break; - } - - case Source::DepthBuffer: - { - const auto& framebuffer = Pica::g_state.regs.framebuffer; - - framebuffer_address = framebuffer.GetDepthBufferPhysicalAddress(); - framebuffer_width = framebuffer.GetWidth(); - framebuffer_height = framebuffer.GetHeight(); - - switch (framebuffer.depth_format) { - case Pica::Regs::DepthFormat::D16: - framebuffer_format = Format::D16; - break; - - case Pica::Regs::DepthFormat::D24: - framebuffer_format = Format::D24; - break; - - case Pica::Regs::DepthFormat::D24S8: - framebuffer_format = Format::D24X8; - break; - - default: - framebuffer_format = Format::Unknown; - break; - } - - break; - } - - case Source::Custom: - { - // Keep user-specified values - break; - } - - default: - qDebug() << "Unknown framebuffer source " << static_cast(framebuffer_source); - break; - } - - // TODO: Implement a good way to visualize alpha components! - // TODO: Unify this decoding code with the texture decoder - u32 bytes_per_pixel = GraphicsFramebufferWidget::BytesPerPixel(framebuffer_format); - - QImage decoded_image(framebuffer_width, framebuffer_height, QImage::Format_ARGB32); - u8* buffer = Memory::GetPhysicalPointer(framebuffer_address); - - for (unsigned int y = 0; y < framebuffer_height; ++y) { - for (unsigned int x = 0; x < framebuffer_width; ++x) { - const u32 coarse_y = y & ~7; - u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * framebuffer_width * bytes_per_pixel; - const u8* pixel = buffer + offset; - Math::Vec4 color = { 0, 0, 0, 0 }; - - switch (framebuffer_format) { - case Format::RGBA8: - color = Color::DecodeRGBA8(pixel); - break; - case Format::RGB8: - color = Color::DecodeRGB8(pixel); - break; - case Format::RGB5A1: - color = Color::DecodeRGB5A1(pixel); - break; - case Format::RGB565: - color = Color::DecodeRGB565(pixel); - break; - case Format::RGBA4: - color = Color::DecodeRGBA4(pixel); - break; - case Format::D16: - { - u32 data = Color::DecodeD16(pixel); - color.r() = data & 0xFF; - color.g() = (data >> 8) & 0xFF; - break; - } - case Format::D24: - { - u32 data = Color::DecodeD24(pixel); - color.r() = data & 0xFF; - color.g() = (data >> 8) & 0xFF; - color.b() = (data >> 16) & 0xFF; - break; - } - case Format::D24X8: - { - Math::Vec2 data = Color::DecodeD24S8(pixel); - color.r() = data.x & 0xFF; - color.g() = (data.x >> 8) & 0xFF; - color.b() = (data.x >> 16) & 0xFF; - break; - } - case Format::X24S8: - { - Math::Vec2 data = Color::DecodeD24S8(pixel); - color.r() = color.g() = color.b() = data.y; - break; - } - default: - qDebug() << "Unknown fb color format " << static_cast(framebuffer_format); - break; - } - - decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), 255)); - } - } - pixmap = QPixmap::fromImage(decoded_image); - - framebuffer_address_control->SetValue(framebuffer_address); - framebuffer_width_control->setValue(framebuffer_width); - framebuffer_height_control->setValue(framebuffer_height); - framebuffer_format_control->setCurrentIndex(static_cast(framebuffer_format)); - framebuffer_picture_label->setPixmap(pixmap); -} - -u32 GraphicsFramebufferWidget::BytesPerPixel(GraphicsFramebufferWidget::Format format) { - switch (format) { - case Format::RGBA8: - case Format::D24X8: - case Format::X24S8: - return 4; - case Format::RGB8: - case Format::D24: - return 3; - case Format::RGB5A1: - case Format::RGB565: - case Format::RGBA4: - case Format::D16: - return 2; - default: - UNREACHABLE_MSG("GraphicsFramebufferWidget::BytesPerPixel: this " - "should not be reached as this function should " - "be given a format which is in " - "GraphicsFramebufferWidget::Format. Instead got %i", - static_cast(format)); - } -} diff --git a/src/citra_qt/debugger/graphics_framebuffer.h b/src/citra_qt/debugger/graphics_framebuffer.h deleted file mode 100644 index 5cd96f2e9..000000000 --- a/src/citra_qt/debugger/graphics_framebuffer.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "citra_qt/debugger/graphics_breakpoint_observer.h" - -class QComboBox; -class QLabel; -class QSpinBox; - -class CSpinBox; - -class GraphicsFramebufferWidget : public BreakPointObserverDock { - Q_OBJECT - - using Event = Pica::DebugContext::Event; - - enum class Source { - PicaTarget = 0, - DepthBuffer = 1, - Custom = 2, - - // TODO: Add GPU framebuffer sources! - }; - - enum class Format { - RGBA8 = 0, - RGB8 = 1, - RGB5A1 = 2, - RGB565 = 3, - RGBA4 = 4, - D16 = 5, - D24 = 6, - D24X8 = 7, - X24S8 = 8, - Unknown = 9 - }; - - static u32 BytesPerPixel(Format format); - -public: - GraphicsFramebufferWidget(std::shared_ptr debug_context, QWidget* parent = nullptr); - -public slots: - void OnFramebufferSourceChanged(int new_value); - void OnFramebufferAddressChanged(qint64 new_value); - void OnFramebufferWidthChanged(int new_value); - void OnFramebufferHeightChanged(int new_value); - void OnFramebufferFormatChanged(int new_value); - void OnUpdate(); - -private slots: - void OnBreakPointHit(Pica::DebugContext::Event event, void* data) override; - void OnResumed() override; - -signals: - void Update(); - -private: - - QComboBox* framebuffer_source_list; - CSpinBox* framebuffer_address_control; - QSpinBox* framebuffer_width_control; - QSpinBox* framebuffer_height_control; - QComboBox* framebuffer_format_control; - - QLabel* framebuffer_picture_label; - - Source framebuffer_source; - unsigned framebuffer_address; - unsigned framebuffer_width; - unsigned framebuffer_height; - Format framebuffer_format; -}; diff --git a/src/citra_qt/debugger/graphics_surface.cpp b/src/citra_qt/debugger/graphics_surface.cpp new file mode 100644 index 000000000..ac2d6f89b --- /dev/null +++ b/src/citra_qt/debugger/graphics_surface.cpp @@ -0,0 +1,736 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "citra_qt/debugger/graphics_surface.h" +#include "citra_qt/util/spinbox.h" + +#include "common/color.h" + +#include "core/memory.h" +#include "core/hw/gpu.h" + +#include "video_core/pica.h" +#include "video_core/pica_state.h" +#include "video_core/utils.h" + +SurfacePicture::SurfacePicture(QWidget* parent, GraphicsSurfaceWidget* surface_widget_) : QLabel(parent), surface_widget(surface_widget_) {} +SurfacePicture::~SurfacePicture() {} + +void SurfacePicture::mousePressEvent(QMouseEvent* event) +{ + // Only do something while the left mouse button is held down + if (!(event->buttons() & Qt::LeftButton)) + return; + + if (pixmap() == nullptr) + return; + + if (surface_widget) + surface_widget->Pick(event->x() * pixmap()->width() / width(), + event->y() * pixmap()->height() / height()); +} + +void SurfacePicture::mouseMoveEvent(QMouseEvent* event) +{ + // We also want to handle the event if the user moves the mouse while holding down the LMB + mousePressEvent(event); +} + + +GraphicsSurfaceWidget::GraphicsSurfaceWidget(std::shared_ptr debug_context, + QWidget* parent) + : BreakPointObserverDock(debug_context, tr("Pica Surface Viewer"), parent), + surface_source(Source::ColorBuffer) +{ + setObjectName("PicaSurface"); + + surface_source_list = new QComboBox; + surface_source_list->addItem(tr("Color Buffer")); + surface_source_list->addItem(tr("Depth Buffer")); + surface_source_list->addItem(tr("Stencil Buffer")); + surface_source_list->addItem(tr("Texture 0")); + surface_source_list->addItem(tr("Texture 1")); + surface_source_list->addItem(tr("Texture 2")); + surface_source_list->addItem(tr("Custom")); + surface_source_list->setCurrentIndex(static_cast(surface_source)); + + surface_address_control = new CSpinBox; + surface_address_control->SetBase(16); + surface_address_control->SetRange(0, 0xFFFFFFFF); + surface_address_control->SetPrefix("0x"); + + unsigned max_dimension = 16384; // TODO: Find actual maximum + + surface_width_control = new QSpinBox; + surface_width_control->setRange(0, max_dimension); + + surface_height_control = new QSpinBox; + surface_height_control->setRange(0, max_dimension); + + surface_picker_x_control = new QSpinBox; + surface_picker_x_control->setRange(0, max_dimension - 1); + + surface_picker_y_control = new QSpinBox; + surface_picker_y_control->setRange(0, max_dimension - 1); + + surface_format_control = new QComboBox; + + // Color formats sorted by Pica texture format index + surface_format_control->addItem(tr("RGBA8")); + surface_format_control->addItem(tr("RGB8")); + surface_format_control->addItem(tr("RGB5A1")); + surface_format_control->addItem(tr("RGB565")); + surface_format_control->addItem(tr("RGBA4")); + surface_format_control->addItem(tr("IA8")); + surface_format_control->addItem(tr("RG8")); + surface_format_control->addItem(tr("I8")); + surface_format_control->addItem(tr("A8")); + surface_format_control->addItem(tr("IA4")); + surface_format_control->addItem(tr("I4")); + surface_format_control->addItem(tr("A4")); + surface_format_control->addItem(tr("ETC1")); + surface_format_control->addItem(tr("ETC1A4")); + surface_format_control->addItem(tr("D16")); + surface_format_control->addItem(tr("D24")); + surface_format_control->addItem(tr("D24X8")); + surface_format_control->addItem(tr("X24S8")); + surface_format_control->addItem(tr("Unknown")); + + surface_info_label = new QLabel(); + surface_info_label->setWordWrap(true); + + surface_picture_label = new SurfacePicture(0, this); + surface_picture_label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + surface_picture_label->setAlignment(Qt::AlignLeft | Qt::AlignTop); + surface_picture_label->setScaledContents(false); + + auto scroll_area = new QScrollArea(); + scroll_area->setBackgroundRole(QPalette::Dark); + scroll_area->setWidgetResizable(false); + scroll_area->setWidget(surface_picture_label); + + save_surface = new QPushButton(QIcon::fromTheme("document-save"), tr("Save")); + + // Connections + connect(this, SIGNAL(Update()), this, SLOT(OnUpdate())); + connect(surface_source_list, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSurfaceSourceChanged(int))); + connect(surface_address_control, SIGNAL(ValueChanged(qint64)), this, SLOT(OnSurfaceAddressChanged(qint64))); + connect(surface_width_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfaceWidthChanged(int))); + connect(surface_height_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfaceHeightChanged(int))); + connect(surface_format_control, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSurfaceFormatChanged(int))); + connect(surface_picker_x_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfacePickerXChanged(int))); + connect(surface_picker_y_control, SIGNAL(valueChanged(int)), this, SLOT(OnSurfacePickerYChanged(int))); + connect(save_surface, SIGNAL(clicked()), this, SLOT(SaveSurface())); + + auto main_widget = new QWidget; + auto main_layout = new QVBoxLayout; + { + auto sub_layout = new QHBoxLayout; + sub_layout->addWidget(new QLabel(tr("Source:"))); + sub_layout->addWidget(surface_source_list); + main_layout->addLayout(sub_layout); + } + { + auto sub_layout = new QHBoxLayout; + sub_layout->addWidget(new QLabel(tr("Physical Address:"))); + sub_layout->addWidget(surface_address_control); + main_layout->addLayout(sub_layout); + } + { + auto sub_layout = new QHBoxLayout; + sub_layout->addWidget(new QLabel(tr("Width:"))); + sub_layout->addWidget(surface_width_control); + main_layout->addLayout(sub_layout); + } + { + auto sub_layout = new QHBoxLayout; + sub_layout->addWidget(new QLabel(tr("Height:"))); + sub_layout->addWidget(surface_height_control); + main_layout->addLayout(sub_layout); + } + { + auto sub_layout = new QHBoxLayout; + sub_layout->addWidget(new QLabel(tr("Format:"))); + sub_layout->addWidget(surface_format_control); + main_layout->addLayout(sub_layout); + } + main_layout->addWidget(scroll_area); + + auto info_layout = new QHBoxLayout; + { + auto xy_layout = new QVBoxLayout; + { + { + auto sub_layout = new QHBoxLayout; + sub_layout->addWidget(new QLabel(tr("X:"))); + sub_layout->addWidget(surface_picker_x_control); + xy_layout->addLayout(sub_layout); + } + { + auto sub_layout = new QHBoxLayout; + sub_layout->addWidget(new QLabel(tr("Y:"))); + sub_layout->addWidget(surface_picker_y_control); + xy_layout->addLayout(sub_layout); + } + } + info_layout->addLayout(xy_layout); + surface_info_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); + info_layout->addWidget(surface_info_label); + } + main_layout->addLayout(info_layout); + + main_layout->addWidget(save_surface); + main_widget->setLayout(main_layout); + setWidget(main_widget); + + // Load current data - TODO: Make sure this works when emulation is not running + if (debug_context && debug_context->at_breakpoint) { + emit Update(); + widget()->setEnabled(debug_context->at_breakpoint); + } else { + widget()->setEnabled(false); + } +} + +void GraphicsSurfaceWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) +{ + emit Update(); + widget()->setEnabled(true); +} + +void GraphicsSurfaceWidget::OnResumed() +{ + widget()->setEnabled(false); +} + +void GraphicsSurfaceWidget::OnSurfaceSourceChanged(int new_value) +{ + surface_source = static_cast(new_value); + emit Update(); +} + +void GraphicsSurfaceWidget::OnSurfaceAddressChanged(qint64 new_value) +{ + if (surface_address != new_value) { + surface_address = static_cast(new_value); + + surface_source_list->setCurrentIndex(static_cast(Source::Custom)); + emit Update(); + } +} + +void GraphicsSurfaceWidget::OnSurfaceWidthChanged(int new_value) +{ + if (surface_width != static_cast(new_value)) { + surface_width = static_cast(new_value); + + surface_source_list->setCurrentIndex(static_cast(Source::Custom)); + emit Update(); + } +} + +void GraphicsSurfaceWidget::OnSurfaceHeightChanged(int new_value) +{ + if (surface_height != static_cast(new_value)) { + surface_height = static_cast(new_value); + + surface_source_list->setCurrentIndex(static_cast(Source::Custom)); + emit Update(); + } +} + +void GraphicsSurfaceWidget::OnSurfaceFormatChanged(int new_value) +{ + if (surface_format != static_cast(new_value)) { + surface_format = static_cast(new_value); + + surface_source_list->setCurrentIndex(static_cast(Source::Custom)); + emit Update(); + } +} + +void GraphicsSurfaceWidget::OnSurfacePickerXChanged(int new_value) +{ + if (surface_picker_x != new_value) { + surface_picker_x = new_value; + Pick(surface_picker_x, surface_picker_y); + } +} + +void GraphicsSurfaceWidget::OnSurfacePickerYChanged(int new_value) +{ + if (surface_picker_y != new_value) { + surface_picker_y = new_value; + Pick(surface_picker_x, surface_picker_y); + } +} + +void GraphicsSurfaceWidget::Pick(int x, int y) +{ + surface_picker_x_control->setValue(x); + surface_picker_y_control->setValue(y); + + if (x < 0 || x >= surface_width || y < 0 || y >= surface_height) { + surface_info_label->setText(tr("Pixel out of bounds")); + surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); + return; + } + + u8* buffer = Memory::GetPhysicalPointer(surface_address); + if (buffer == nullptr) { + surface_info_label->setText(tr("(unable to access pixel data)")); + surface_info_label->setAlignment(Qt::AlignCenter); + return; + } + + unsigned nibbles_per_pixel = GraphicsSurfaceWidget::NibblesPerPixel(surface_format); + unsigned stride = nibbles_per_pixel * surface_width / 2; + + unsigned bytes_per_pixel; + bool nibble_mode = (nibbles_per_pixel == 1); + if (nibble_mode) { + // As nibbles are contained in a byte we still need to access one byte per nibble + bytes_per_pixel = 1; + } else { + bytes_per_pixel = nibbles_per_pixel / 2; + } + + const u32 coarse_y = y & ~7; + u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; + const u8* pixel = buffer + (nibble_mode ? (offset / 2) : offset); + + auto GetText = [offset](Format format, const u8* pixel) { + switch (format) { + case Format::RGBA8: + { + auto value = Color::DecodeRGBA8(pixel) / 255.0f; + return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4") + .arg(QString::number(value.r(), 'f', 2)) + .arg(QString::number(value.g(), 'f', 2)) + .arg(QString::number(value.b(), 'f', 2)) + .arg(QString::number(value.a(), 'f', 2)); + } + case Format::RGB8: + { + auto value = Color::DecodeRGB8(pixel) / 255.0f; + return QString("Red: %1, Green: %2, Blue: %3") + .arg(QString::number(value.r(), 'f', 2)) + .arg(QString::number(value.g(), 'f', 2)) + .arg(QString::number(value.b(), 'f', 2)); + } + case Format::RGB5A1: + { + auto value = Color::DecodeRGB5A1(pixel) / 255.0f; + return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4") + .arg(QString::number(value.r(), 'f', 2)) + .arg(QString::number(value.g(), 'f', 2)) + .arg(QString::number(value.b(), 'f', 2)) + .arg(QString::number(value.a(), 'f', 2)); + } + case Format::RGB565: + { + auto value = Color::DecodeRGB565(pixel) / 255.0f; + return QString("Red: %1, Green: %2, Blue: %3") + .arg(QString::number(value.r(), 'f', 2)) + .arg(QString::number(value.g(), 'f', 2)) + .arg(QString::number(value.b(), 'f', 2)); + } + case Format::RGBA4: + { + auto value = Color::DecodeRGBA4(pixel) / 255.0f; + return QString("Red: %1, Green: %2, Blue: %3, Alpha: %4") + .arg(QString::number(value.r(), 'f', 2)) + .arg(QString::number(value.g(), 'f', 2)) + .arg(QString::number(value.b(), 'f', 2)) + .arg(QString::number(value.a(), 'f', 2)); + } + case Format::IA8: + return QString("Index: %1, Alpha: %2") + .arg(pixel[0]) + .arg(pixel[1]); + case Format::RG8: { + auto value = Color::DecodeRG8(pixel) / 255.0f; + return QString("Red: %1, Green: %2") + .arg(QString::number(value.r(), 'f', 2)) + .arg(QString::number(value.g(), 'f', 2)); + } + case Format::I8: + return QString("Index: %1").arg(*pixel); + case Format::A8: + return QString("Alpha: %1").arg(QString::number(*pixel / 255.0f, 'f', 2)); + case Format::IA4: + return QString("Index: %1, Alpha: %2") + .arg(*pixel & 0xF) + .arg((*pixel & 0xF0) >> 4); + case Format::I4: + { + u8 i = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF; + return QString("Index: %1").arg(i); + } + case Format::A4: + { + u8 a = (*pixel >> ((offset % 2) ? 4 : 0)) & 0xF; + return QString("Alpha: %1").arg(QString::number(a / 15.0f, 'f', 2)); + } + case Format::ETC1: + case Format::ETC1A4: + // TODO: Display block information or channel values? + return QString("Compressed data"); + case Format::D16: + { + auto value = Color::DecodeD16(pixel); + return QString("Depth: %1").arg(QString::number(value / (float)0xFFFF, 'f', 4)); + } + case Format::D24: + { + auto value = Color::DecodeD24(pixel); + return QString("Depth: %1").arg(QString::number(value / (float)0xFFFFFF, 'f', 4)); + } + case Format::D24X8: + case Format::X24S8: + { + auto values = Color::DecodeD24S8(pixel); + return QString("Depth: %1, Stencil: %2").arg(QString::number(values[0] / (float)0xFFFFFF, 'f', 4)).arg(values[1]); + } + case Format::Unknown: + return QString("Unknown format"); + default: + return QString("Unhandled format"); + } + return QString(""); + }; + + QString nibbles = ""; + for (unsigned i = 0; i < nibbles_per_pixel; i++) { + unsigned nibble_index = i; + if (nibble_mode) { + nibble_index += (offset % 2) ? 0 : 1; + } + u8 byte = pixel[nibble_index / 2]; + u8 nibble = (byte >> ((nibble_index % 2) ? 0 : 4)) & 0xF; + nibbles.append(QString::number(nibble, 16).toUpper()); + } + + surface_info_label->setText(QString("Raw: 0x%3\n(%4)").arg(nibbles).arg(GetText(surface_format, pixel))); + surface_info_label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); +} + +void GraphicsSurfaceWidget::OnUpdate() +{ + QPixmap pixmap; + + switch (surface_source) { + case Source::ColorBuffer: + { + // TODO: Store a reference to the registers in the debug context instead of accessing them directly... + + const auto& framebuffer = Pica::g_state.regs.framebuffer; + + surface_address = framebuffer.GetColorBufferPhysicalAddress(); + surface_width = framebuffer.GetWidth(); + surface_height = framebuffer.GetHeight(); + + switch (framebuffer.color_format) { + case Pica::Regs::ColorFormat::RGBA8: + surface_format = Format::RGBA8; + break; + + case Pica::Regs::ColorFormat::RGB8: + surface_format = Format::RGB8; + break; + + case Pica::Regs::ColorFormat::RGB5A1: + surface_format = Format::RGB5A1; + break; + + case Pica::Regs::ColorFormat::RGB565: + surface_format = Format::RGB565; + break; + + case Pica::Regs::ColorFormat::RGBA4: + surface_format = Format::RGBA4; + break; + + default: + surface_format = Format::Unknown; + break; + } + + break; + } + + case Source::DepthBuffer: + { + const auto& framebuffer = Pica::g_state.regs.framebuffer; + + surface_address = framebuffer.GetDepthBufferPhysicalAddress(); + surface_width = framebuffer.GetWidth(); + surface_height = framebuffer.GetHeight(); + + switch (framebuffer.depth_format) { + case Pica::Regs::DepthFormat::D16: + surface_format = Format::D16; + break; + + case Pica::Regs::DepthFormat::D24: + surface_format = Format::D24; + break; + + case Pica::Regs::DepthFormat::D24S8: + surface_format = Format::D24X8; + break; + + default: + surface_format = Format::Unknown; + break; + } + + break; + } + + case Source::StencilBuffer: + { + const auto& framebuffer = Pica::g_state.regs.framebuffer; + + surface_address = framebuffer.GetDepthBufferPhysicalAddress(); + surface_width = framebuffer.GetWidth(); + surface_height = framebuffer.GetHeight(); + + switch (framebuffer.depth_format) { + case Pica::Regs::DepthFormat::D24S8: + surface_format = Format::X24S8; + break; + + default: + surface_format = Format::Unknown; + break; + } + + break; + } + + case Source::Texture0: + case Source::Texture1: + case Source::Texture2: + { + unsigned texture_index; + if (surface_source == Source::Texture0) texture_index = 0; + else if (surface_source == Source::Texture1) texture_index = 1; + else if (surface_source == Source::Texture2) texture_index = 2; + else { + qDebug() << "Unknown texture source " << static_cast(surface_source); + break; + } + + const auto texture = Pica::g_state.regs.GetTextures()[texture_index]; + auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(texture.config, texture.format); + + surface_address = info.physical_address; + surface_width = info.width; + surface_height = info.height; + surface_format = static_cast(info.format); + + if (surface_format > Format::MaxTextureFormat) { + qDebug() << "Unknown texture format " << static_cast(info.format); + } + break; + } + + case Source::Custom: + { + // Keep user-specified values + break; + } + + default: + qDebug() << "Unknown surface source " << static_cast(surface_source); + break; + } + + surface_address_control->SetValue(surface_address); + surface_width_control->setValue(surface_width); + surface_height_control->setValue(surface_height); + surface_format_control->setCurrentIndex(static_cast(surface_format)); + + // TODO: Implement a good way to visualize alpha components! + + QImage decoded_image(surface_width, surface_height, QImage::Format_ARGB32); + u8* buffer = Memory::GetPhysicalPointer(surface_address); + + if (buffer == nullptr) { + surface_picture_label->hide(); + surface_info_label->setText(tr("(invalid surface address)")); + surface_info_label->setAlignment(Qt::AlignCenter); + surface_picker_x_control->setEnabled(false); + surface_picker_y_control->setEnabled(false); + save_surface->setEnabled(false); + return; + } + + if (surface_format == Format::Unknown) { + surface_picture_label->hide(); + surface_info_label->setText(tr("(unknown surface format)")); + surface_info_label->setAlignment(Qt::AlignCenter); + surface_picker_x_control->setEnabled(false); + surface_picker_y_control->setEnabled(false); + save_surface->setEnabled(false); + return; + } + + surface_picture_label->show(); + + unsigned nibbles_per_pixel = GraphicsSurfaceWidget::NibblesPerPixel(surface_format); + unsigned stride = nibbles_per_pixel * surface_width / 2; + + // We handle depth formats here because DebugUtils only supports TextureFormats + if (surface_format <= Format::MaxTextureFormat) { + + // Generate a virtual texture + Pica::DebugUtils::TextureInfo info; + info.physical_address = surface_address; + info.width = surface_width; + info.height = surface_height; + info.format = static_cast(surface_format); + info.stride = stride; + + for (unsigned int y = 0; y < surface_height; ++y) { + for (unsigned int x = 0; x < surface_width; ++x) { + Math::Vec4 color = Pica::DebugUtils::LookupTexture(buffer, x, y, info, true); + decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), color.a())); + } + } + + } else { + + ASSERT_MSG(nibbles_per_pixel >= 2, "Depth decoder only supports formats with at least one byte per pixel"); + unsigned bytes_per_pixel = nibbles_per_pixel / 2; + + for (unsigned int y = 0; y < surface_height; ++y) { + for (unsigned int x = 0; x < surface_width; ++x) { + const u32 coarse_y = y & ~7; + u32 offset = VideoCore::GetMortonOffset(x, y, bytes_per_pixel) + coarse_y * stride; + const u8* pixel = buffer + offset; + Math::Vec4 color = { 0, 0, 0, 0 }; + + switch(surface_format) { + case Format::D16: + { + u32 data = Color::DecodeD16(pixel); + color.r() = data & 0xFF; + color.g() = (data >> 8) & 0xFF; + break; + } + case Format::D24: + { + u32 data = Color::DecodeD24(pixel); + color.r() = data & 0xFF; + color.g() = (data >> 8) & 0xFF; + color.b() = (data >> 16) & 0xFF; + break; + } + case Format::D24X8: + { + Math::Vec2 data = Color::DecodeD24S8(pixel); + color.r() = data.x & 0xFF; + color.g() = (data.x >> 8) & 0xFF; + color.b() = (data.x >> 16) & 0xFF; + break; + } + case Format::X24S8: + { + Math::Vec2 data = Color::DecodeD24S8(pixel); + color.r() = color.g() = color.b() = data.y; + break; + } + default: + qDebug() << "Unknown surface format " << static_cast(surface_format); + break; + } + + decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), 255)); + } + } + + } + + pixmap = QPixmap::fromImage(decoded_image); + surface_picture_label->setPixmap(pixmap); + surface_picture_label->resize(pixmap.size()); + + // Update the info with pixel data + surface_picker_x_control->setEnabled(true); + surface_picker_y_control->setEnabled(true); + Pick(surface_picker_x, surface_picker_y); + + // Enable saving the converted pixmap to file + save_surface->setEnabled(true); +} + +void GraphicsSurfaceWidget::SaveSurface() { + QString png_filter = tr("Portable Network Graphic (*.png)"); + QString bin_filter = tr("Binary data (*.bin)"); + + QString selectedFilter; + QString filename = QFileDialog::getSaveFileName(this, tr("Save Surface"), QString("texture-0x%1.png").arg(QString::number(surface_address, 16)), + QString("%1;;%2").arg(png_filter, bin_filter), &selectedFilter); + + if (filename.isEmpty()) { + // If the user canceled the dialog, don't save anything. + return; + } + + if (selectedFilter == png_filter) { + const QPixmap* pixmap = surface_picture_label->pixmap(); + ASSERT_MSG(pixmap != nullptr, "No pixmap set"); + + QFile file(filename); + file.open(QIODevice::WriteOnly); + if (pixmap) + pixmap->save(&file, "PNG"); + } else if (selectedFilter == bin_filter) { + const u8* buffer = Memory::GetPhysicalPointer(surface_address); + ASSERT_MSG(buffer != nullptr, "Memory not accessible"); + + QFile file(filename); + file.open(QIODevice::WriteOnly); + int size = surface_width * surface_height * NibblesPerPixel(surface_format) / 2; + QByteArray data(reinterpret_cast(buffer), size); + file.write(data); + } else { + UNREACHABLE_MSG("Unhandled filter selected"); + } +} + +unsigned int GraphicsSurfaceWidget::NibblesPerPixel(GraphicsSurfaceWidget::Format format) { + if (format <= Format::MaxTextureFormat) { + return Pica::Regs::NibblesPerPixel(static_cast(format)); + } + + switch (format) { + case Format::D24X8: + case Format::X24S8: + return 4 * 2; + case Format::D24: + return 3 * 2; + case Format::D16: + return 2 * 2; + default: + UNREACHABLE_MSG("GraphicsSurfaceWidget::BytesPerPixel: this " + "should not be reached as this function should " + "be given a format which is in " + "GraphicsSurfaceWidget::Format. Instead got %i", + static_cast(format)); + return 0; + } +} diff --git a/src/citra_qt/debugger/graphics_surface.h b/src/citra_qt/debugger/graphics_surface.h new file mode 100644 index 000000000..7c7f50e38 --- /dev/null +++ b/src/citra_qt/debugger/graphics_surface.h @@ -0,0 +1,120 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "citra_qt/debugger/graphics_breakpoint_observer.h" + +#include +#include + +class QComboBox; +class QSpinBox; +class CSpinBox; + +class GraphicsSurfaceWidget; + +class SurfacePicture : public QLabel +{ + Q_OBJECT + +public: + SurfacePicture(QWidget* parent = 0, GraphicsSurfaceWidget* surface_widget = nullptr); + ~SurfacePicture(); + +protected slots: + virtual void mouseMoveEvent(QMouseEvent* event); + virtual void mousePressEvent(QMouseEvent* event); + +private: + GraphicsSurfaceWidget* surface_widget; + +}; + +class GraphicsSurfaceWidget : public BreakPointObserverDock { + Q_OBJECT + + using Event = Pica::DebugContext::Event; + + enum class Source { + ColorBuffer = 0, + DepthBuffer = 1, + StencilBuffer = 2, + Texture0 = 3, + Texture1 = 4, + Texture2 = 5, + Custom = 6, + }; + + enum class Format { + // These must match the TextureFormat type! + RGBA8 = 0, + RGB8 = 1, + RGB5A1 = 2, + RGB565 = 3, + RGBA4 = 4, + IA8 = 5, + RG8 = 6, ///< @note Also called HILO8 in 3DBrew. + I8 = 7, + A8 = 8, + IA4 = 9, + I4 = 10, + A4 = 11, + ETC1 = 12, // compressed + ETC1A4 = 13, + MaxTextureFormat = 13, + D16 = 14, + D24 = 15, + D24X8 = 16, + X24S8 = 17, + Unknown = 18, + }; + + static unsigned int NibblesPerPixel(Format format); + +public: + GraphicsSurfaceWidget(std::shared_ptr debug_context, QWidget* parent = nullptr); + void Pick(int x, int y); + +public slots: + void OnSurfaceSourceChanged(int new_value); + void OnSurfaceAddressChanged(qint64 new_value); + void OnSurfaceWidthChanged(int new_value); + void OnSurfaceHeightChanged(int new_value); + void OnSurfaceFormatChanged(int new_value); + void OnSurfacePickerXChanged(int new_value); + void OnSurfacePickerYChanged(int new_value); + void OnUpdate(); + +private slots: + void OnBreakPointHit(Pica::DebugContext::Event event, void* data) override; + void OnResumed() override; + + void SaveSurface(); + +signals: + void Update(); + +private: + + QComboBox* surface_source_list; + CSpinBox* surface_address_control; + QSpinBox* surface_width_control; + QSpinBox* surface_height_control; + QComboBox* surface_format_control; + + SurfacePicture* surface_picture_label; + QSpinBox* surface_picker_x_control; + QSpinBox* surface_picker_y_control; + QLabel* surface_info_label; + QPushButton* save_surface; + + Source surface_source; + unsigned surface_address; + unsigned surface_width; + unsigned surface_height; + Format surface_format; + int surface_picker_x = 0; + int surface_picker_y = 0; +}; diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index f1ab29755..dfc7c0752 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -26,7 +26,7 @@ #include "citra_qt/debugger/graphics.h" #include "citra_qt/debugger/graphics_breakpoints.h" #include "citra_qt/debugger/graphics_cmdlists.h" -#include "citra_qt/debugger/graphics_framebuffer.h" +#include "citra_qt/debugger/graphics_surface.h" #include "citra_qt/debugger/graphics_tracing.h" #include "citra_qt/debugger/graphics_vertex_shader.h" #include "citra_qt/debugger/profiler.h" @@ -98,10 +98,6 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) addDockWidget(Qt::RightDockWidgetArea, graphicsBreakpointsWidget); graphicsBreakpointsWidget->hide(); - auto graphicsFramebufferWidget = new GraphicsFramebufferWidget(Pica::g_debug_context, this); - addDockWidget(Qt::RightDockWidgetArea, graphicsFramebufferWidget); - graphicsFramebufferWidget->hide(); - auto graphicsVertexShaderWidget = new GraphicsVertexShaderWidget(Pica::g_debug_context, this); addDockWidget(Qt::RightDockWidgetArea, graphicsVertexShaderWidget); graphicsVertexShaderWidget->hide(); @@ -110,7 +106,12 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) addDockWidget(Qt::RightDockWidgetArea, graphicsTracingWidget); graphicsTracingWidget->hide(); + auto graphicsSurfaceViewerAction = new QAction(tr("Create Pica surface viewer"), this); + connect(graphicsSurfaceViewerAction, SIGNAL(triggered()), this, SLOT(OnCreateGraphicsSurfaceViewer())); + QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging")); + debug_menu->addAction(graphicsSurfaceViewerAction); + debug_menu->addSeparator(); debug_menu->addAction(profilerWidget->toggleViewAction()); #if MICROPROFILE_ENABLED debug_menu->addAction(microProfileDialog->toggleViewAction()); @@ -121,7 +122,6 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) debug_menu->addAction(graphicsWidget->toggleViewAction()); debug_menu->addAction(graphicsCommandsWidget->toggleViewAction()); debug_menu->addAction(graphicsBreakpointsWidget->toggleViewAction()); - debug_menu->addAction(graphicsFramebufferWidget->toggleViewAction()); debug_menu->addAction(graphicsVertexShaderWidget->toggleViewAction()); debug_menu->addAction(graphicsTracingWidget->toggleViewAction()); @@ -498,6 +498,13 @@ void GMainWindow::OnConfigure() { } } +void GMainWindow::OnCreateGraphicsSurfaceViewer() { + auto graphicsSurfaceViewerWidget = new GraphicsSurfaceWidget(Pica::g_debug_context, this); + addDockWidget(Qt::RightDockWidgetArea, graphicsSurfaceViewerWidget); + // TODO: Maybe graphicsSurfaceViewerWidget->setFloating(true); + graphicsSurfaceViewerWidget->show(); +} + bool GMainWindow::ConfirmClose() { if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) return true; diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h index 477db5c5c..b836b13fb 100644 --- a/src/citra_qt/main.h +++ b/src/citra_qt/main.h @@ -108,6 +108,7 @@ private slots: void OnConfigure(); void OnDisplayTitleBars(bool); void ToggleWindowMode(); + void OnCreateGraphicsSurfaceViewer(); private: Ui::MainWindow ui; From a286b61f75f1b166c34079e6b8f85688bd522ca3 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 29 Apr 2016 10:57:06 -0400 Subject: [PATCH 04/60] vertex_loader: Correct header ordering --- src/video_core/vertex_loader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/vertex_loader.cpp b/src/video_core/vertex_loader.cpp index 21ae52949..ce1c8da59 100644 --- a/src/video_core/vertex_loader.cpp +++ b/src/video_core/vertex_loader.cpp @@ -2,8 +2,8 @@ #include -#include "common/assert.h" #include "common/alignment.h" +#include "common/assert.h" #include "common/bit_field.h" #include "common/common_types.h" #include "common/logging/log.h" From 8ea5e7dfb57ebda2ad2229e4e94dfd5e2c24c091 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 29 Apr 2016 11:06:03 -0400 Subject: [PATCH 05/60] vertex_loader: Use std::array instead of raw C arrays --- src/video_core/vertex_loader.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/video_core/vertex_loader.h b/src/video_core/vertex_loader.h index becf5a403..3b511945a 100644 --- a/src/video_core/vertex_loader.h +++ b/src/video_core/vertex_loader.h @@ -1,7 +1,8 @@ #pragma once -#include "common/common_types.h" +#include +#include "common/common_types.h" #include "video_core/pica.h" namespace Pica { @@ -22,11 +23,11 @@ public: int GetNumTotalAttributes() const { return num_total_attributes; } private: - u32 vertex_attribute_sources[16]; - u32 vertex_attribute_strides[16] = {}; - Regs::VertexAttributeFormat vertex_attribute_formats[16] = {}; - u32 vertex_attribute_elements[16] = {}; - bool vertex_attribute_is_default[16]; + std::array vertex_attribute_sources; + std::array vertex_attribute_strides{}; + std::array vertex_attribute_formats; + std::array vertex_attribute_elements{}; + std::array vertex_attribute_is_default; int num_total_attributes; }; From 769f4a7018e170448f7f1c307f2bcfa26f59ecba Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 29 Apr 2016 11:16:52 -0400 Subject: [PATCH 06/60] vertex_loader: initialize_num_total_attributes. Keeps the public API sane. --- src/video_core/vertex_loader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/vertex_loader.h b/src/video_core/vertex_loader.h index 3b511945a..4ed8cd3fd 100644 --- a/src/video_core/vertex_loader.h +++ b/src/video_core/vertex_loader.h @@ -28,7 +28,7 @@ private: std::array vertex_attribute_formats; std::array vertex_attribute_elements{}; std::array vertex_attribute_is_default; - int num_total_attributes; + int num_total_attributes = 0; }; } // namespace Pica From 1357724cd946f3a9f31dbe3ace55a9588f3c6f2f Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 29 Apr 2016 11:23:40 -0400 Subject: [PATCH 07/60] vertex_loader: Add constructors to facilitate immediate and two-step initialization --- src/video_core/command_processor.cpp | 3 +-- src/video_core/vertex_loader.h | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index dd1379503..941c5af9f 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -199,9 +199,8 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { // Processes information about internal vertex attributes to figure out how a vertex is loaded. // Later, these can be compiled and cached. - VertexLoader loader; const u32 base_address = regs.vertex_attributes.GetPhysicalBaseAddress(); - loader.Setup(regs); + VertexLoader loader(regs); // Load vertices bool is_indexed = (id == PICA_REG_INDEX(trigger_draw_indexed)); diff --git a/src/video_core/vertex_loader.h b/src/video_core/vertex_loader.h index 4ed8cd3fd..2a97b97c8 100644 --- a/src/video_core/vertex_loader.h +++ b/src/video_core/vertex_loader.h @@ -17,6 +17,11 @@ class InputVertex; class VertexLoader { public: + VertexLoader() = default; + explicit VertexLoader(const Pica::Regs& regs) { + Setup(regs); + } + void Setup(const Pica::Regs& regs); void LoadVertex(u32 base_address, int index, int vertex, Shader::InputVertex& input, DebugUtils::MemoryAccessTracker& memory_accesses); From 5587383eb72b02af79526d6fe5e662b281b4b32b Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 29 Apr 2016 11:27:15 -0400 Subject: [PATCH 08/60] vertex_loader: Provide an assertion for ensuring the loader has been setup Also adds an assert to ensure that Setup is not called more than once during a VertexLoader's lifetime. --- src/video_core/vertex_loader.cpp | 6 ++++++ src/video_core/vertex_loader.h | 1 + 2 files changed, 7 insertions(+) diff --git a/src/video_core/vertex_loader.cpp b/src/video_core/vertex_loader.cpp index ce1c8da59..18a7cf144 100644 --- a/src/video_core/vertex_loader.cpp +++ b/src/video_core/vertex_loader.cpp @@ -21,6 +21,8 @@ namespace Pica { void VertexLoader::Setup(const Pica::Regs& regs) { + ASSERT_MSG(!is_setup, "VertexLoader is not intended to be setup more than once."); + const auto& attribute_config = regs.vertex_attributes; num_total_attributes = attribute_config.GetNumTotalAttributes(); @@ -60,9 +62,13 @@ void VertexLoader::Setup(const Pica::Regs& regs) { } } } + + is_setup = true; } void VertexLoader::LoadVertex(u32 base_address, int index, int vertex, Shader::InputVertex& input, DebugUtils::MemoryAccessTracker& memory_accesses) { + ASSERT_MSG(is_setup, "A VertexLoader needs to be setup before loading vertices."); + for (int i = 0; i < num_total_attributes; ++i) { if (vertex_attribute_elements[i] != 0) { // Load per-vertex data from the loader arrays diff --git a/src/video_core/vertex_loader.h b/src/video_core/vertex_loader.h index 2a97b97c8..7192120a5 100644 --- a/src/video_core/vertex_loader.h +++ b/src/video_core/vertex_loader.h @@ -34,6 +34,7 @@ private: std::array vertex_attribute_elements{}; std::array vertex_attribute_is_default; int num_total_attributes = 0; + bool is_setup = false; }; } // namespace Pica From 6d5f2a3cff519ca2811033d8381fac2515a74af8 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 8 May 2016 23:04:42 -0400 Subject: [PATCH 09/60] vertex_loader: Correct forward declaration of InputVertex It's actually a struct, not a class. --- src/video_core/vertex_loader.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/vertex_loader.h b/src/video_core/vertex_loader.h index 7192120a5..ac162c254 100644 --- a/src/video_core/vertex_loader.h +++ b/src/video_core/vertex_loader.h @@ -12,7 +12,7 @@ class MemoryAccessTracker; } namespace Shader { -class InputVertex; +struct InputVertex; } class VertexLoader { From 03631f9b8fe75cf1c3a70a3094aeddcebffa4cf9 Mon Sep 17 00:00:00 2001 From: wwylele Date: Thu, 12 May 2016 13:09:36 +0300 Subject: [PATCH 10/60] Refactor input subsystem --- src/citra/config.cpp | 5 +- src/citra/default_ini.h | 8 +- src/citra/emu_window/emu_window_sdl2.cpp | 7 +- src/citra_qt/bootmanager.cpp | 7 +- src/citra_qt/config.cpp | 5 +- src/common/emu_window.cpp | 24 ++++- src/common/emu_window.h | 46 ++++++++-- src/common/key_map.cpp | 112 +++++++++++++++++++++-- src/common/key_map.h | 51 ++++++++++- src/core/hle/service/hid/hid.cpp | 64 +++++++------ src/core/hle/service/hid/hid.h | 3 - src/core/settings.h | 18 +++- 12 files changed, 277 insertions(+), 73 deletions(-) diff --git a/src/citra/config.cpp b/src/citra/config.cpp index c5cb4fb38..4f6d0a464 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -44,12 +44,15 @@ bool Config::LoadINI(const std::string& default_contents, bool retry) { } static const std::array defaults = { + // directly mapped keys SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_Q, SDL_SCANCODE_W, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_M, SDL_SCANCODE_N, SDL_SCANCODE_B, SDL_SCANCODE_T, SDL_SCANCODE_G, SDL_SCANCODE_F, SDL_SCANCODE_H, + SDL_SCANCODE_I, SDL_SCANCODE_K, SDL_SCANCODE_J, SDL_SCANCODE_L, + + // indirectly mapped keys SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, - SDL_SCANCODE_I, SDL_SCANCODE_K, SDL_SCANCODE_J, SDL_SCANCODE_L }; void Config::ReadValues() { diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index 49126356f..d0b258cab 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -23,14 +23,14 @@ pad_l = pad_r = pad_zl = pad_zr = -pad_sup = -pad_sdown = -pad_sleft = -pad_sright = pad_cup = pad_cdown = pad_cleft = pad_cright = +pad_circle_up = +pad_circle_down = +pad_circle_left = +pad_circle_right = [Core] # The applied frameskip amount. Must be a power of two. diff --git a/src/citra/emu_window/emu_window_sdl2.cpp b/src/citra/emu_window/emu_window_sdl2.cpp index 12cdd9d95..591f68aa4 100644 --- a/src/citra/emu_window/emu_window_sdl2.cpp +++ b/src/citra/emu_window/emu_window_sdl2.cpp @@ -40,9 +40,9 @@ void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { if (state == SDL_PRESSED) { - KeyPressed({ key, keyboard_id }); + KeyMap::PressKey(*this, { key, keyboard_id }); } else if (state == SDL_RELEASED) { - KeyReleased({ key, keyboard_id }); + KeyMap::ReleaseKey(*this, { key, keyboard_id }); } } @@ -168,8 +168,9 @@ void EmuWindow_SDL2::DoneCurrent() { } void EmuWindow_SDL2::ReloadSetKeymaps() { + KeyMap::ClearKeyMapping(keyboard_id); for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { - KeyMap::SetKeyMapping({ Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id }, Service::HID::pad_mapping[i]); + KeyMap::SetKeyMapping({ Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id }, KeyMap::mapping_targets[i]); } } diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index 01b81c11c..414b2f8af 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp @@ -235,12 +235,12 @@ void GRenderWindow::closeEvent(QCloseEvent* event) { void GRenderWindow::keyPressEvent(QKeyEvent* event) { - this->KeyPressed({event->key(), keyboard_id}); + KeyMap::PressKey(*this, { event->key(), keyboard_id }); } void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { - this->KeyReleased({event->key(), keyboard_id}); + KeyMap::ReleaseKey(*this, { event->key(), keyboard_id }); } void GRenderWindow::mousePressEvent(QMouseEvent *event) @@ -270,8 +270,9 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent *event) void GRenderWindow::ReloadSetKeymaps() { + KeyMap::ClearKeyMapping(keyboard_id); for (int i = 0; i < Settings::NativeInput::NUM_INPUTS; ++i) { - KeyMap::SetKeyMapping({Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id}, Service::HID::pad_mapping[i]); + KeyMap::SetKeyMapping({ Settings::values.input_mappings[Settings::NativeInput::All[i]], keyboard_id }, KeyMap::mapping_targets[i]); } } diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp index b5bb75537..ebee8c821 100644 --- a/src/citra_qt/config.cpp +++ b/src/citra_qt/config.cpp @@ -22,12 +22,15 @@ Config::Config() { } static const std::array defaults = { + // directly mapped keys Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_Q, Qt::Key_W, Qt::Key_1, Qt::Key_2, Qt::Key_M, Qt::Key_N, Qt::Key_B, Qt::Key_T, Qt::Key_G, Qt::Key_F, Qt::Key_H, + Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L, + + // indirectly mapped keys Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, - Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L }; void Config::ReadValues() { diff --git a/src/common/emu_window.cpp b/src/common/emu_window.cpp index b2807354a..08270dd88 100644 --- a/src/common/emu_window.cpp +++ b/src/common/emu_window.cpp @@ -11,12 +11,28 @@ #include "emu_window.h" #include "video_core/video_core.h" -void EmuWindow::KeyPressed(KeyMap::HostDeviceKey key) { - pad_state.hex |= KeyMap::GetPadKey(key).hex; +void EmuWindow::ButtonPressed(Service::HID::PadState pad) { + pad_state.hex |= pad.hex; } -void EmuWindow::KeyReleased(KeyMap::HostDeviceKey key) { - pad_state.hex &= ~KeyMap::GetPadKey(key).hex; +void EmuWindow::ButtonReleased(Service::HID::PadState pad) { + pad_state.hex &= ~pad.hex; +} + +void EmuWindow::CirclePadUpdated(float x, float y) { + constexpr int MAX_CIRCLEPAD_POS = 0x9C; // Max value for a circle pad position + + // Make sure the coordinates are in the unit circle, + // otherwise normalize it. + float r = x * x + y * y; + if (r > 1) { + r = std::sqrt(r); + x /= r; + y /= r; + } + + circle_pad_x = static_cast(x * MAX_CIRCLEPAD_POS); + circle_pad_y = static_cast(y * MAX_CIRCLEPAD_POS); } /** diff --git a/src/common/emu_window.h b/src/common/emu_window.h index 7c3486dea..0ae3ea2af 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h @@ -12,10 +12,6 @@ #include "core/hle/service/hid/hid.h" -namespace KeyMap { -struct HostDeviceKey; -} - /** * Abstraction class used to provide an interface between emulation code and the frontend * (e.g. SDL, QGLWidget, GLFW, etc...). @@ -76,11 +72,27 @@ public: virtual void ReloadSetKeymaps() = 0; - /// Signals a key press action to the HID module - void KeyPressed(KeyMap::HostDeviceKey key); + /** + * Signals a button press action to the HID module. + * @param pad_state indicates which button to press + * @note only handle real buttons (A/B/X/Y/...), excluding analog input like circle pad. + */ + void ButtonPressed(Service::HID::PadState pad_state); - /// Signals a key release action to the HID module - void KeyReleased(KeyMap::HostDeviceKey key); + /** + * Signals a button release action to the HID module. + * @param pad_state indicates which button to press + * @note only handle real buttons (A/B/X/Y/...), excluding analog input like circle pad. + */ + void ButtonReleased(Service::HID::PadState pad_state); + + /** + * Signals a circle pad change action to the HID module. + * @param x new x-coordinate of the circle pad, in the range [-1.0, 1.0] + * @param y new y-coordinate of the circle pad, in the range [-1.0, 1.0] + * @note the coordinates will be normalized if the radius is larger than 1 + */ + void CirclePadUpdated(float x, float y); /** * Signal that a touch pressed event has occurred (e.g. mouse click pressed) @@ -100,8 +112,9 @@ public: void TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y); /** - * Gets the current pad state (which buttons are pressed and the circle pad direction). + * Gets the current pad state (which buttons are pressed). * @note This should be called by the core emu thread to get a state set by the window thread. + * @note This doesn't include analog input like circle pad direction * @todo Fix this function to be thread-safe. * @return PadState object indicating the current pad state */ @@ -109,6 +122,16 @@ public: return pad_state; } + /** + * Gets the current cirle pad state. + * @note This should be called by the core emu thread to get a state set by the window thread. + * @todo Fix this function to be thread-safe. + * @return std::tuple of (x, y), where `x` and `y` are the circle pad coordinates + */ + std::tuple GetCirclePadState() const { + return std::make_tuple(circle_pad_x, circle_pad_y); + } + /** * Gets the current touch screen state (touch X/Y coordinates and whether or not it is pressed). * @note This should be called by the core emu thread to get a state set by the window thread. @@ -200,6 +223,8 @@ protected: pad_state.hex = 0; touch_x = 0; touch_y = 0; + circle_pad_x = 0; + circle_pad_y = 0; touch_pressed = false; } virtual ~EmuWindow() {} @@ -260,6 +285,9 @@ private: u16 touch_x; ///< Touchpad X-position in native 3DS pixel coordinates (0-320) u16 touch_y; ///< Touchpad Y-position in native 3DS pixel coordinates (0-240) + s16 circle_pad_x; ///< Circle pad X-position in native 3DS pixel coordinates (-156 - 156) + s16 circle_pad_y; ///< Circle pad Y-position in native 3DS pixel coordinates (-156 - 156) + /** * Clip the provided coordinates to be inside the touchscreen area. */ diff --git a/src/common/key_map.cpp b/src/common/key_map.cpp index 844d5df68..c8f168aa1 100644 --- a/src/common/key_map.cpp +++ b/src/common/key_map.cpp @@ -2,24 +2,124 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "key_map.h" #include +#include "common/emu_window.h" +#include "common/key_map.h" + namespace KeyMap { -static std::map key_map; +// TODO (wwylele): currently we treat c-stick as four direction buttons +// and map it directly to EmuWindow::ButtonPressed. +// It should go the analog input way like circle pad does. +const std::array mapping_targets = {{ + Service::HID::PAD_A, Service::HID::PAD_B, Service::HID::PAD_X, Service::HID::PAD_Y, + Service::HID::PAD_L, Service::HID::PAD_R, Service::HID::PAD_ZL, Service::HID::PAD_ZR, + Service::HID::PAD_START, Service::HID::PAD_SELECT, Service::HID::PAD_NONE, + Service::HID::PAD_UP, Service::HID::PAD_DOWN, Service::HID::PAD_LEFT, Service::HID::PAD_RIGHT, + Service::HID::PAD_C_UP, Service::HID::PAD_C_DOWN, Service::HID::PAD_C_LEFT, Service::HID::PAD_C_RIGHT, + + IndirectTarget::CIRCLE_PAD_UP, + IndirectTarget::CIRCLE_PAD_DOWN, + IndirectTarget::CIRCLE_PAD_LEFT, + IndirectTarget::CIRCLE_PAD_RIGHT, +}}; + +static std::map key_map; static int next_device_id = 0; +static bool circle_pad_up = false, circle_pad_down = false, circle_pad_left = false, circle_pad_right = false; + +static void UpdateCirclePad(EmuWindow& emu_window) { + constexpr float SQRT_HALF = 0.707106781; + int x = 0, y = 0; + + if (circle_pad_right) + ++x; + if (circle_pad_left) + --x; + if (circle_pad_up) + ++y; + if (circle_pad_down) + --y; + // TODO: apply modifier here + emu_window.CirclePadUpdated(x * (y == 0 ? 1.0 : SQRT_HALF), y * (x == 0 ? 1.0 : SQRT_HALF)); +} + int NewDeviceId() { return next_device_id++; } -void SetKeyMapping(HostDeviceKey key, Service::HID::PadState padState) { - key_map[key].hex = padState.hex; +void SetKeyMapping(HostDeviceKey key, KeyTarget target) { + key_map[key] = target; } -Service::HID::PadState GetPadKey(HostDeviceKey key) { - return key_map[key]; +void ClearKeyMapping(int device_id) { + auto iter = key_map.begin(); + while (iter != key_map.end()) { + if (iter->first.device_id == device_id) + key_map.erase(iter++); + else + ++iter; + } +} + +void PressKey(EmuWindow& emu_window, HostDeviceKey key) { + auto target = key_map.find(key); + if (target == key_map.end()) + return; + + if (target->second.direct) { + emu_window.ButtonPressed({{target->second.target.direct_target_hex}}); + } else { + switch (target->second.target.indirect_target) { + case IndirectTarget::CIRCLE_PAD_UP: + circle_pad_up = true; + UpdateCirclePad(emu_window); + break; + case IndirectTarget::CIRCLE_PAD_DOWN: + circle_pad_down = true; + UpdateCirclePad(emu_window); + break; + case IndirectTarget::CIRCLE_PAD_LEFT: + circle_pad_left = true; + UpdateCirclePad(emu_window); + break; + case IndirectTarget::CIRCLE_PAD_RIGHT: + circle_pad_right = true; + UpdateCirclePad(emu_window); + break; + } + } +} + +void ReleaseKey(EmuWindow& emu_window,HostDeviceKey key) { + auto target = key_map.find(key); + if (target == key_map.end()) + return; + + if (target->second.direct) { + emu_window.ButtonReleased({{target->second.target.direct_target_hex}}); + } else { + switch (target->second.target.indirect_target) { + case IndirectTarget::CIRCLE_PAD_UP: + circle_pad_up = false; + UpdateCirclePad(emu_window); + break; + case IndirectTarget::CIRCLE_PAD_DOWN: + circle_pad_down = false; + UpdateCirclePad(emu_window); + break; + case IndirectTarget::CIRCLE_PAD_LEFT: + circle_pad_left = false; + UpdateCirclePad(emu_window); + break; + case IndirectTarget::CIRCLE_PAD_RIGHT: + circle_pad_right = false; + UpdateCirclePad(emu_window); + break; + } + } } } diff --git a/src/common/key_map.h b/src/common/key_map.h index 68f7e2f99..0438a14e0 100644 --- a/src/common/key_map.h +++ b/src/common/key_map.h @@ -4,11 +4,42 @@ #pragma once +#include #include #include "core/hle/service/hid/hid.h" +class EmuWindow; + namespace KeyMap { +enum class IndirectTarget { + CIRCLE_PAD_UP, CIRCLE_PAD_DOWN, CIRCLE_PAD_LEFT, CIRCLE_PAD_RIGHT, +}; + +/** + * Represents a key mapping target. It can be a PadState that represents 3DS real buttons, + * or an IndirectTarget. + */ +struct KeyTarget { + bool direct; + union { + u32 direct_target_hex; + IndirectTarget indirect_target; + } target; + + KeyTarget() : direct(true) { + target.direct_target_hex = 0; + } + + KeyTarget(Service::HID::PadState pad) : direct(true) { + target.direct_target_hex = pad.hex; + } + + KeyTarget(IndirectTarget i) : direct(false) { + target.indirect_target = i; + } +}; + /** * Represents a key for a specific host device. */ @@ -27,19 +58,31 @@ struct HostDeviceKey { } }; +extern const std::array mapping_targets; + /** * Generates a new device id, which uniquely identifies a host device within KeyMap. */ int NewDeviceId(); /** - * Maps a device-specific key to a PadState. + * Maps a device-specific key to a target (a PadState or an IndirectTarget). */ -void SetKeyMapping(HostDeviceKey key, Service::HID::PadState padState); +void SetKeyMapping(HostDeviceKey key, KeyTarget target); /** - * Gets the PadState that's mapped to the provided device-specific key. + * Clears all key mappings belonging to one device. */ -Service::HID::PadState GetPadKey(HostDeviceKey key); +void ClearKeyMapping(int device_id); + +/** + * Maps a key press actions and call the corresponding function in EmuWindow + */ +void PressKey(EmuWindow& emu_window, HostDeviceKey key); + +/** + * Maps a key release actions and call the corresponding function in EmuWindow + */ +void ReleaseKey(EmuWindow& emu_window, HostDeviceKey key); } diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index d216cecb4..a48184495 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -19,8 +19,6 @@ namespace Service { namespace HID { -static const int MAX_CIRCLEPAD_POS = 0x9C; ///< Max value for a circle pad position - // Handle to shared memory region designated to HID_User service static Kernel::SharedPtr shared_mem; @@ -39,38 +37,48 @@ static u32 next_gyroscope_index; static int enable_accelerometer_count = 0; // positive means enabled static int enable_gyroscope_count = 0; // positive means enabled -const std::array pad_mapping = {{ - Service::HID::PAD_A, Service::HID::PAD_B, Service::HID::PAD_X, Service::HID::PAD_Y, - Service::HID::PAD_L, Service::HID::PAD_R, Service::HID::PAD_ZL, Service::HID::PAD_ZR, - Service::HID::PAD_START, Service::HID::PAD_SELECT, Service::HID::PAD_NONE, - Service::HID::PAD_UP, Service::HID::PAD_DOWN, Service::HID::PAD_LEFT, Service::HID::PAD_RIGHT, - Service::HID::PAD_CIRCLE_UP, Service::HID::PAD_CIRCLE_DOWN, Service::HID::PAD_CIRCLE_LEFT, Service::HID::PAD_CIRCLE_RIGHT, - Service::HID::PAD_C_UP, Service::HID::PAD_C_DOWN, Service::HID::PAD_C_LEFT, Service::HID::PAD_C_RIGHT -}}; +static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) { + constexpr float TAN30 = 0.577350269, TAN60 = 1 / TAN30; // 30 degree and 60 degree are angular thresholds for directions + constexpr int CIRCLE_PAD_THRESHOLD_SQUARE = 40 * 40; // a circle pad radius greater than 40 will trigger circle pad direction + PadState state; + state.hex = 0; + if (circle_pad_x * circle_pad_x + circle_pad_y * circle_pad_y > CIRCLE_PAD_THRESHOLD_SQUARE) { + float t = std::abs(static_cast(circle_pad_y) / circle_pad_x); -// TODO(peachum): -// Add a method for setting analog input from joystick device for the circle Pad. -// -// This method should: -// * Be called after both PadButton(). -// * Be called before PadUpdateComplete() -// * Set current PadEntry.circle_pad_ using analog data -// * Set PadData.raw_circle_pad_data -// * Set PadData.current_state.circle_right = 1 if current PadEntry.circle_pad_x >= 41 -// * Set PadData.current_state.circle_up = 1 if current PadEntry.circle_pad_y >= 41 -// * Set PadData.current_state.circle_left = 1 if current PadEntry.circle_pad_x <= -41 -// * Set PadData.current_state.circle_right = 1 if current PadEntry.circle_pad_y <= -41 + if (circle_pad_x != 0 && t < TAN60) { + if (circle_pad_x > 0) + state.circle_right.Assign(1); + else + state.circle_left.Assign(1); + } + + if (circle_pad_x == 0 || t > TAN30) { + if (circle_pad_y > 0) + state.circle_up.Assign(1); + else + state.circle_down.Assign(1); + } + } + + return state; +} void Update() { SharedMem* mem = reinterpret_cast(shared_mem->GetPointer()); - const PadState state = VideoCore::g_emu_window->GetPadState(); if (mem == nullptr) { LOG_DEBUG(Service_HID, "Cannot update HID prior to mapping shared memory!"); return; } + PadState state = VideoCore::g_emu_window->GetPadState(); + + // Get current circle pad positon and update circle pad direction + s16 circle_pad_x, circle_pad_y; + std::tie(circle_pad_x, circle_pad_y) = VideoCore::g_emu_window->GetCirclePadState(); + state.hex |= GetCirclePadDirectionState(circle_pad_x, circle_pad_y).hex; + mem->pad.current_state.hex = state.hex; mem->pad.index = next_pad_index; next_pad_index = (next_pad_index + 1) % mem->pad.entries.size(); @@ -88,13 +96,9 @@ void Update() { // Update entry properties pad_entry.current_state.hex = state.hex; pad_entry.delta_additions.hex = changed.hex & state.hex; - pad_entry.delta_removals.hex = changed.hex & old_state.hex;; - - // Set circle Pad - pad_entry.circle_pad_x = state.circle_left ? -MAX_CIRCLEPAD_POS : - state.circle_right ? MAX_CIRCLEPAD_POS : 0x0; - pad_entry.circle_pad_y = state.circle_down ? -MAX_CIRCLEPAD_POS : - state.circle_up ? MAX_CIRCLEPAD_POS : 0x0; + pad_entry.delta_removals.hex = changed.hex & old_state.hex; + pad_entry.circle_pad_x = circle_pad_x; + pad_entry.circle_pad_y = circle_pad_y; // If we just updated index 0, provide a new timestamp if (mem->pad.index == 0) { diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 170d19ea8..669b1f723 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -215,9 +215,6 @@ const PadState PAD_CIRCLE_LEFT = {{1u << 29}}; const PadState PAD_CIRCLE_UP = {{1u << 30}}; const PadState PAD_CIRCLE_DOWN = {{1u << 31}}; - -extern const std::array pad_mapping; - /** * HID::GetIPCHandles service function * Inputs: diff --git a/src/core/settings.h b/src/core/settings.h index ce2a31164..df5915442 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -13,29 +13,37 @@ namespace Settings { namespace NativeInput { enum Values { + // directly mapped keys A, B, X, Y, L, R, ZL, ZR, START, SELECT, HOME, DUP, DDOWN, DLEFT, DRIGHT, - SUP, SDOWN, SLEFT, SRIGHT, CUP, CDOWN, CLEFT, CRIGHT, + + // indirectly mapped keys + CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT, + NUM_INPUTS }; + static const std::array Mapping = {{ + // directly mapped keys "pad_a", "pad_b", "pad_x", "pad_y", "pad_l", "pad_r", "pad_zl", "pad_zr", "pad_start", "pad_select", "pad_home", "pad_dup", "pad_ddown", "pad_dleft", "pad_dright", - "pad_sup", "pad_sdown", "pad_sleft", "pad_sright", - "pad_cup", "pad_cdown", "pad_cleft", "pad_cright" + "pad_cup", "pad_cdown", "pad_cleft", "pad_cright", + + // indirectly mapped keys + "pad_circle_up", "pad_circle_down", "pad_circle_left", "pad_circle_right" }}; static const std::array All = {{ A, B, X, Y, L, R, ZL, ZR, START, SELECT, HOME, DUP, DDOWN, DLEFT, DRIGHT, - SUP, SDOWN, SLEFT, SRIGHT, - CUP, CDOWN, CLEFT, CRIGHT + CUP, CDOWN, CLEFT, CRIGHT, + CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT, }}; } From 416faa20d1156ac4e8646710e9c1f9565c0ed14b Mon Sep 17 00:00:00 2001 From: wwylele Date: Fri, 13 May 2016 18:32:43 +0300 Subject: [PATCH 11/60] implement circle pad modifier --- src/citra/config.cpp | 2 ++ src/citra/default_ini.h | 5 +++++ src/citra_qt/config.cpp | 3 +++ src/common/key_map.cpp | 20 +++++++++++++++++--- src/common/key_map.h | 6 +++++- src/core/settings.h | 6 +++++- 6 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/citra/config.cpp b/src/citra/config.cpp index 4f6d0a464..fb8dd9ba3 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -53,6 +53,7 @@ static const std::array defaults = { // indirectly mapped keys SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, + SDL_SCANCODE_D, }; void Config::ReadValues() { @@ -61,6 +62,7 @@ void Config::ReadValues() { Settings::values.input_mappings[Settings::NativeInput::All[i]] = sdl2_config->GetInteger("Controls", Settings::NativeInput::Mapping[i], defaults[i]); } + Settings::values.pad_circle_modifier_scale = (float)sdl2_config->GetReal("Controls", "pad_circle_modifier_scale", 0.5); // Core Settings::values.frame_skip = sdl2_config->GetInteger("Core", "frame_skip", 0); diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index d0b258cab..a9017dcb3 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -31,6 +31,11 @@ pad_circle_up = pad_circle_down = pad_circle_left = pad_circle_right = +pad_circle_modifier = + +# The applied modifier scale to circle pad. +# Must be in range of 0.0-1.0. Defaults to 0.5 +pad_circle_modifier_scale = [Core] # The applied frameskip amount. Must be a power of two. diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp index ebee8c821..539fafb6f 100644 --- a/src/citra_qt/config.cpp +++ b/src/citra_qt/config.cpp @@ -31,6 +31,7 @@ static const std::array defaults = // indirectly mapped keys Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, + Qt::Key_D, }; void Config::ReadValues() { @@ -39,6 +40,7 @@ void Config::ReadValues() { Settings::values.input_mappings[Settings::NativeInput::All[i]] = qt_config->value(QString::fromStdString(Settings::NativeInput::Mapping[i]), defaults[i]).toInt(); } + Settings::values.pad_circle_modifier_scale = qt_config->value("pad_circle_modifier_scale", 0.5).toFloat(); qt_config->endGroup(); qt_config->beginGroup("Core"); @@ -128,6 +130,7 @@ void Config::SaveValues() { qt_config->setValue(QString::fromStdString(Settings::NativeInput::Mapping[i]), Settings::values.input_mappings[Settings::NativeInput::All[i]]); } + qt_config->setValue("pad_circle_modifier_scale", (double)Settings::values.pad_circle_modifier_scale); qt_config->endGroup(); qt_config->beginGroup("Core"); diff --git a/src/common/key_map.cpp b/src/common/key_map.cpp index c8f168aa1..61572cde6 100644 --- a/src/common/key_map.cpp +++ b/src/common/key_map.cpp @@ -23,12 +23,17 @@ const std::array mapping_targets = IndirectTarget::CIRCLE_PAD_DOWN, IndirectTarget::CIRCLE_PAD_LEFT, IndirectTarget::CIRCLE_PAD_RIGHT, + IndirectTarget::CIRCLE_PAD_MODIFIER, }}; static std::map key_map; static int next_device_id = 0; -static bool circle_pad_up = false, circle_pad_down = false, circle_pad_left = false, circle_pad_right = false; +static bool circle_pad_up = false; +static bool circle_pad_down = false; +static bool circle_pad_left = false; +static bool circle_pad_right = false; +static bool circle_pad_modifier = false; static void UpdateCirclePad(EmuWindow& emu_window) { constexpr float SQRT_HALF = 0.707106781; @@ -42,8 +47,9 @@ static void UpdateCirclePad(EmuWindow& emu_window) { ++y; if (circle_pad_down) --y; - // TODO: apply modifier here - emu_window.CirclePadUpdated(x * (y == 0 ? 1.0 : SQRT_HALF), y * (x == 0 ? 1.0 : SQRT_HALF)); + + float modifier = circle_pad_modifier ? Settings::values.pad_circle_modifier_scale : 1.0; + emu_window.CirclePadUpdated(x * modifier * (y == 0 ? 1.0 : SQRT_HALF), y * modifier * (x == 0 ? 1.0 : SQRT_HALF)); } int NewDeviceId() { @@ -89,6 +95,10 @@ void PressKey(EmuWindow& emu_window, HostDeviceKey key) { circle_pad_right = true; UpdateCirclePad(emu_window); break; + case IndirectTarget::CIRCLE_PAD_MODIFIER: + circle_pad_modifier = true; + UpdateCirclePad(emu_window); + break; } } } @@ -118,6 +128,10 @@ void ReleaseKey(EmuWindow& emu_window,HostDeviceKey key) { circle_pad_right = false; UpdateCirclePad(emu_window); break; + case IndirectTarget::CIRCLE_PAD_MODIFIER: + circle_pad_modifier = false; + UpdateCirclePad(emu_window); + break; } } } diff --git a/src/common/key_map.h b/src/common/key_map.h index 0438a14e0..ec371bdde 100644 --- a/src/common/key_map.h +++ b/src/common/key_map.h @@ -13,7 +13,11 @@ class EmuWindow; namespace KeyMap { enum class IndirectTarget { - CIRCLE_PAD_UP, CIRCLE_PAD_DOWN, CIRCLE_PAD_LEFT, CIRCLE_PAD_RIGHT, + CIRCLE_PAD_UP, + CIRCLE_PAD_DOWN, + CIRCLE_PAD_LEFT, + CIRCLE_PAD_RIGHT, + CIRCLE_PAD_MODIFIER, }; /** diff --git a/src/core/settings.h b/src/core/settings.h index df5915442..d6f8f2ff3 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -22,6 +22,7 @@ enum Values { // indirectly mapped keys CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT, + CIRCLE_MODIFIER, NUM_INPUTS }; @@ -35,7 +36,8 @@ static const std::array Mapping = {{ "pad_cup", "pad_cdown", "pad_cleft", "pad_cright", // indirectly mapped keys - "pad_circle_up", "pad_circle_down", "pad_circle_left", "pad_circle_right" + "pad_circle_up", "pad_circle_down", "pad_circle_left", "pad_circle_right", + "pad_circle_modifier", }}; static const std::array All = {{ A, B, X, Y, @@ -44,6 +46,7 @@ static const std::array All = {{ DUP, DDOWN, DLEFT, DRIGHT, CUP, CDOWN, CLEFT, CRIGHT, CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT, + CIRCLE_MODIFIER, }}; } @@ -51,6 +54,7 @@ static const std::array All = {{ struct Values { // Controls std::array input_mappings; + float pad_circle_modifier_scale; // Core int frame_skip; From 6d49e4621c7ea7565262998782ff52910940fcd9 Mon Sep 17 00:00:00 2001 From: wwylele Date: Sun, 15 May 2016 13:35:45 +0300 Subject: [PATCH 12/60] fixup! Refactor input system --- src/common/key_map.cpp | 30 +++++++++++++++--------------- src/common/key_map.h | 14 +++++++++----- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/common/key_map.cpp b/src/common/key_map.cpp index 61572cde6..ad311d66b 100644 --- a/src/common/key_map.cpp +++ b/src/common/key_map.cpp @@ -19,11 +19,11 @@ const std::array mapping_targets = Service::HID::PAD_UP, Service::HID::PAD_DOWN, Service::HID::PAD_LEFT, Service::HID::PAD_RIGHT, Service::HID::PAD_C_UP, Service::HID::PAD_C_DOWN, Service::HID::PAD_C_LEFT, Service::HID::PAD_C_RIGHT, - IndirectTarget::CIRCLE_PAD_UP, - IndirectTarget::CIRCLE_PAD_DOWN, - IndirectTarget::CIRCLE_PAD_LEFT, - IndirectTarget::CIRCLE_PAD_RIGHT, - IndirectTarget::CIRCLE_PAD_MODIFIER, + IndirectTarget::CirclePadUp, + IndirectTarget::CirclePadDown, + IndirectTarget::CirclePadLeft, + IndirectTarget::CirclePadRight, + IndirectTarget::CirclePadModifier, }}; static std::map key_map; @@ -79,23 +79,23 @@ void PressKey(EmuWindow& emu_window, HostDeviceKey key) { emu_window.ButtonPressed({{target->second.target.direct_target_hex}}); } else { switch (target->second.target.indirect_target) { - case IndirectTarget::CIRCLE_PAD_UP: + case IndirectTarget::CirclePadUp: circle_pad_up = true; UpdateCirclePad(emu_window); break; - case IndirectTarget::CIRCLE_PAD_DOWN: + case IndirectTarget::CirclePadDown: circle_pad_down = true; UpdateCirclePad(emu_window); break; - case IndirectTarget::CIRCLE_PAD_LEFT: + case IndirectTarget::CirclePadLeft: circle_pad_left = true; UpdateCirclePad(emu_window); break; - case IndirectTarget::CIRCLE_PAD_RIGHT: + case IndirectTarget::CirclePadRight: circle_pad_right = true; UpdateCirclePad(emu_window); break; - case IndirectTarget::CIRCLE_PAD_MODIFIER: + case IndirectTarget::CirclePadModifier: circle_pad_modifier = true; UpdateCirclePad(emu_window); break; @@ -112,23 +112,23 @@ void ReleaseKey(EmuWindow& emu_window,HostDeviceKey key) { emu_window.ButtonReleased({{target->second.target.direct_target_hex}}); } else { switch (target->second.target.indirect_target) { - case IndirectTarget::CIRCLE_PAD_UP: + case IndirectTarget::CirclePadUp: circle_pad_up = false; UpdateCirclePad(emu_window); break; - case IndirectTarget::CIRCLE_PAD_DOWN: + case IndirectTarget::CirclePadDown: circle_pad_down = false; UpdateCirclePad(emu_window); break; - case IndirectTarget::CIRCLE_PAD_LEFT: + case IndirectTarget::CirclePadLeft: circle_pad_left = false; UpdateCirclePad(emu_window); break; - case IndirectTarget::CIRCLE_PAD_RIGHT: + case IndirectTarget::CirclePadRight: circle_pad_right = false; UpdateCirclePad(emu_window); break; - case IndirectTarget::CIRCLE_PAD_MODIFIER: + case IndirectTarget::CirclePadModifier: circle_pad_modifier = false; UpdateCirclePad(emu_window); break; diff --git a/src/common/key_map.h b/src/common/key_map.h index ec371bdde..4b585c1b9 100644 --- a/src/common/key_map.h +++ b/src/common/key_map.h @@ -12,12 +12,16 @@ class EmuWindow; namespace KeyMap { +/** + * Represents a key mapping target that are not 3DS real buttons. + * They will be handled by KeyMap and translated to 3DS input. + */ enum class IndirectTarget { - CIRCLE_PAD_UP, - CIRCLE_PAD_DOWN, - CIRCLE_PAD_LEFT, - CIRCLE_PAD_RIGHT, - CIRCLE_PAD_MODIFIER, + CirclePadUp, + CirclePadDown, + CirclePadLeft, + CirclePadRight, + CirclePadModifier, }; /** From 6cccdcacd2c8dc442db5a8ece5e754b0ed655d8b Mon Sep 17 00:00:00 2001 From: wwylele Date: Sun, 15 May 2016 19:35:06 +0300 Subject: [PATCH 13/60] fixup! fixup! Refactor input system --- src/common/emu_window.h | 6 +++--- src/common/key_map.h | 8 ++++---- src/core/hle/service/hid/hid.cpp | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/common/emu_window.h b/src/common/emu_window.h index 0ae3ea2af..57e303b6d 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h @@ -75,14 +75,14 @@ public: /** * Signals a button press action to the HID module. * @param pad_state indicates which button to press - * @note only handle real buttons (A/B/X/Y/...), excluding analog input like circle pad. + * @note only handles real buttons (A/B/X/Y/...), excluding analog inputs like the circle pad. */ void ButtonPressed(Service::HID::PadState pad_state); /** * Signals a button release action to the HID module. * @param pad_state indicates which button to press - * @note only handle real buttons (A/B/X/Y/...), excluding analog input like circle pad. + * @note only handles real buttons (A/B/X/Y/...), excluding analog inputs like the circle pad. */ void ButtonReleased(Service::HID::PadState pad_state); @@ -123,7 +123,7 @@ public: } /** - * Gets the current cirle pad state. + * Gets the current circle pad state. * @note This should be called by the core emu thread to get a state set by the window thread. * @todo Fix this function to be thread-safe. * @return std::tuple of (x, y), where `x` and `y` are the circle pad coordinates diff --git a/src/common/key_map.h b/src/common/key_map.h index 4b585c1b9..b62f017c6 100644 --- a/src/common/key_map.h +++ b/src/common/key_map.h @@ -13,7 +13,7 @@ class EmuWindow; namespace KeyMap { /** - * Represents a key mapping target that are not 3DS real buttons. + * Represents key mapping targets that are not real 3DS buttons. * They will be handled by KeyMap and translated to 3DS input. */ enum class IndirectTarget { @@ -25,7 +25,7 @@ enum class IndirectTarget { }; /** - * Represents a key mapping target. It can be a PadState that represents 3DS real buttons, + * Represents a key mapping target. It can be a PadState that represents real 3DS buttons, * or an IndirectTarget. */ struct KeyTarget { @@ -84,12 +84,12 @@ void SetKeyMapping(HostDeviceKey key, KeyTarget target); void ClearKeyMapping(int device_id); /** - * Maps a key press actions and call the corresponding function in EmuWindow + * Maps a key press action and call the corresponding function in EmuWindow */ void PressKey(EmuWindow& emu_window, HostDeviceKey key); /** - * Maps a key release actions and call the corresponding function in EmuWindow + * Maps a key release action and call the corresponding function in EmuWindow */ void ReleaseKey(EmuWindow& emu_window, HostDeviceKey key); diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index a48184495..c975433f4 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -74,7 +74,7 @@ void Update() { PadState state = VideoCore::g_emu_window->GetPadState(); - // Get current circle pad positon and update circle pad direction + // Get current circle pad position and update circle pad direction s16 circle_pad_x, circle_pad_y; std::tie(circle_pad_x, circle_pad_y) = VideoCore::g_emu_window->GetCirclePadState(); state.hex |= GetCirclePadDirectionState(circle_pad_x, circle_pad_y).hex; From 1643786c04738d1dab9604e98cc1d815a2ca027b Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sun, 15 May 2016 16:32:42 +0200 Subject: [PATCH 14/60] Disable VFP3 instructions --- src/core/arm/dyncom/arm_dyncom_dec.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp index 8cd6755cb..247d379e3 100644 --- a/src/core/arm/dyncom/arm_dyncom_dec.cpp +++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp @@ -422,6 +422,10 @@ ARMDecodeStatus DecodeARMInstruction(u32 instr, s32* idx) { n = arm_instruction[i].attribute_value; base = 0; + // 3DS has no VFP3 support + if (arm_instruction[i].version == ARMVFP3) + continue; + while (n) { if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) { // clrex From 6fe0cb671df9daf29314be9cbe754606f8cb1ed1 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 16 May 2016 10:47:01 +0200 Subject: [PATCH 15/60] Respect fpscr in ftoiz --- src/core/arm/skyeye_common/vfp/vfpdouble.cpp | 4 ++-- src/core/arm/skyeye_common/vfp/vfpsingle.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp index 45914d479..5215d48eb 100644 --- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp @@ -615,7 +615,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 static u32 vfp_double_ftouiz(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) { LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - return vfp_double_ftoui(state, sd, unused, dm, FPSCR_ROUND_TOZERO); + return vfp_double_ftoui(state, sd, unused, dm, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); } static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) @@ -692,7 +692,7 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 static u32 vfp_double_ftosiz(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - return vfp_double_ftosi(state, dd, unused, dm, FPSCR_ROUND_TOZERO); + return vfp_double_ftosi(state, dd, unused, dm, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); } static struct op fops_ext[] = { diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp index e47ad2760..e15a95716 100644 --- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp @@ -638,7 +638,7 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f static u32 vfp_single_ftouiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { - return vfp_single_ftoui(state, sd, unused, m, FPSCR_ROUND_TOZERO); + return vfp_single_ftoui(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); } static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) @@ -717,7 +717,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f static u32 vfp_single_ftosiz(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { - return vfp_single_ftosi(state, sd, unused, m, FPSCR_ROUND_TOZERO); + return vfp_single_ftosi(state, sd, unused, m, (fpscr & ~FPSCR_RMODE_MASK) | FPSCR_ROUND_TOZERO); } static struct op fops_ext[] = { From 501d0bc5edd9091c7c831a710e6ebff9839fad36 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sun, 15 May 2016 16:33:36 +0200 Subject: [PATCH 16/60] Fix ftoi behaviour --- src/core/arm/skyeye_common/vfp/vfpdouble.cpp | 37 +++++++++++++------ src/core/arm/skyeye_common/vfp/vfpsingle.cpp | 38 ++++++++++++++------ 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp index 5215d48eb..a2a625abc 100644 --- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp @@ -560,7 +560,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 if (vdm.exponent >= 1023 + 32) { d = vdm.sign ? 0 : 0xffffffff; exceptions = FPSCR_IOC; - } else if (vdm.exponent >= 1023 - 1) { + } else if (vdm.exponent >= 1023) { int shift = 1023 + 63 - vdm.exponent; u64 rem, incr = 0; @@ -595,12 +595,20 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 } else { d = 0; if (vdm.exponent | vdm.significand) { - exceptions |= FPSCR_IXC; - if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) + if (rmode == FPSCR_ROUND_NEAREST) { + if (vdm.exponent >= 1022) { + d = vdm.sign ? 0 : 1; + exceptions |= vdm.sign ? FPSCR_IOC : FPSCR_IXC; + } else { + exceptions |= FPSCR_IXC; + } + } else if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) { d = 1; - else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) { - d = 0; - exceptions |= FPSCR_IOC; + exceptions |= FPSCR_IXC; + } else if (rmode == FPSCR_ROUND_MINUSINF) { + exceptions |= vdm.sign ? FPSCR_IOC : FPSCR_IXC; + } else { + exceptions |= FPSCR_IXC; } } } @@ -639,12 +647,12 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 if (tm & VFP_NAN) { d = 0; exceptions |= FPSCR_IOC; - } else if (vdm.exponent >= 1023 + 32) { + } else if (vdm.exponent >= 1023 + 31) { d = 0x7fffffff; if (vdm.sign) d = ~d; exceptions |= FPSCR_IOC; - } else if (vdm.exponent >= 1023 - 1) { + } else if (vdm.exponent >= 1023) { int shift = 1023 + 63 - vdm.exponent; /* 58 */ u64 rem, incr = 0; @@ -675,10 +683,17 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 d = 0; if (vdm.exponent | vdm.significand) { exceptions |= FPSCR_IXC; - if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) + if (rmode == FPSCR_ROUND_NEAREST) { + if (vdm.exponent >= 1022) { + d = vdm.sign ? 0xffffffff : 1; + } else { + d = 0; + } + } else if (rmode == FPSCR_ROUND_PLUSINF && vdm.sign == 0) { d = 1; - else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) - d = -1; + } else if (rmode == FPSCR_ROUND_MINUSINF && vdm.sign) { + d = 0xffffffff; + } } } diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp index e15a95716..6f6e0ca31 100644 --- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp @@ -592,7 +592,11 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f * 2^0 <= m < 2^32-2^8 */ d = (vsm.significand << 1) >> shift; - rem = vsm.significand << (33 - shift); + if (shift > 0) { + rem = (vsm.significand << 1) << (32 - shift); + } else { + rem = 0; + } if (rmode == FPSCR_ROUND_NEAREST) { incr = 0x80000000; @@ -619,12 +623,20 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f } else { d = 0; if (vsm.exponent | vsm.significand) { - exceptions |= FPSCR_IXC; - if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) + if (rmode == FPSCR_ROUND_NEAREST) { + if (vsm.exponent >= 126) { + d = vsm.sign ? 0 : 1; + exceptions |= vsm.sign ? FPSCR_IOC : FPSCR_IXC; + } else { + exceptions |= FPSCR_IXC; + } + } else if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) { d = 1; - else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) { - d = 0; - exceptions |= FPSCR_IOC; + exceptions |= FPSCR_IXC; + } else if (rmode == FPSCR_ROUND_MINUSINF) { + exceptions |= vsm.sign ? FPSCR_IOC : FPSCR_IXC; + } else { + exceptions |= FPSCR_IXC; } } } @@ -661,7 +673,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f if (tm & VFP_NAN) { d = 0; exceptions |= FPSCR_IOC; - } else if (vsm.exponent >= 127 + 32) { + } else if (vsm.exponent >= 127 + 31) { /* * m >= 2^31-2^7: invalid */ @@ -675,7 +687,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f /* 2^0 <= m <= 2^31-2^7 */ d = (vsm.significand << 1) >> shift; - rem = vsm.significand << (33 - shift); + rem = (vsm.significand << 1) << (32 - shift); if (rmode == FPSCR_ROUND_NEAREST) { incr = 0x80000000; @@ -701,10 +713,14 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f d = 0; if (vsm.exponent | vsm.significand) { exceptions |= FPSCR_IXC; - if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) + if (rmode == FPSCR_ROUND_NEAREST) { + if (vsm.exponent >= 126) + d = vsm.sign ? 0xffffffff : 1; + } else if (rmode == FPSCR_ROUND_PLUSINF && vsm.sign == 0) { d = 1; - else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) - d = -1; + } else if (rmode == FPSCR_ROUND_MINUSINF && vsm.sign) { + d = 0xffffffff; + } } } From ff0fa86b17e8133263bb54c1338ade8ecd97e5d9 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Fri, 13 May 2016 08:49:20 +0200 Subject: [PATCH 17/60] Retrieve shader result from new OutputRegisters-type --- src/video_core/command_processor.cpp | 21 ++-- src/video_core/shader/shader.cpp | 103 ++++++++++--------- src/video_core/shader/shader.h | 17 ++- src/video_core/shader/shader_interpreter.cpp | 4 +- 4 files changed, 81 insertions(+), 64 deletions(-) diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index ad0da796e..c29a3fe51 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -149,7 +149,8 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { // Send to vertex shader if (g_debug_context) g_debug_context->OnEvent(DebugContext::Event::VertexShaderInvocation, static_cast(&immediate_input)); - Shader::OutputVertex output = g_state.vs.Run(shader_unit, immediate_input, regs.vs.num_input_attributes+1); + g_state.vs.Run(shader_unit, immediate_input, regs.vs.num_input_attributes+1); + Shader::OutputVertex output_vertex = shader_unit.output_registers.ToVertex(regs.vs); // Send to renderer using Pica::Shader::OutputVertex; @@ -157,7 +158,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { VideoCore::g_renderer->Rasterizer()->AddTriangle(v0, v1, v2); }; - g_state.primitive_assembler.SubmitVertex(output, AddTriangle); + g_state.primitive_assembler.SubmitVertex(output_vertex, AddTriangle); } } } @@ -231,7 +232,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { // The size has been tuned for optimal balance between hit-rate and the cost of lookup const size_t VERTEX_CACHE_SIZE = 32; std::array vertex_cache_ids; - std::array vertex_cache; + std::array vertex_cache; unsigned int vertex_cache_pos = 0; vertex_cache_ids.fill(-1); @@ -249,7 +250,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { ASSERT(vertex != -1); bool vertex_cache_hit = false; - Shader::OutputVertex output; + Shader::OutputRegisters output_registers; if (is_indexed) { if (g_debug_context && Pica::g_debug_context->recorder) { @@ -259,7 +260,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { for (unsigned int i = 0; i < VERTEX_CACHE_SIZE; ++i) { if (vertex == vertex_cache_ids[i]) { - output = vertex_cache[i]; + output_registers = vertex_cache[i]; vertex_cache_hit = true; break; } @@ -274,15 +275,19 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { // Send to vertex shader if (g_debug_context) g_debug_context->OnEvent(DebugContext::Event::VertexShaderInvocation, (void*)&input); - output = g_state.vs.Run(shader_unit, input, loader.GetNumTotalAttributes()); + g_state.vs.Run(shader_unit, input, loader.GetNumTotalAttributes()); + output_registers = shader_unit.output_registers; if (is_indexed) { - vertex_cache[vertex_cache_pos] = output; + vertex_cache[vertex_cache_pos] = output_registers; vertex_cache_ids[vertex_cache_pos] = vertex; vertex_cache_pos = (vertex_cache_pos + 1) % VERTEX_CACHE_SIZE; } } + // Retreive vertex from register data + Shader::OutputVertex output_vertex = output_registers.ToVertex(regs.vs); + // Send to renderer using Pica::Shader::OutputVertex; auto AddTriangle = []( @@ -290,7 +295,7 @@ static void WritePicaReg(u32 id, u32 value, u32 mask) { VideoCore::g_renderer->Rasterizer()->AddTriangle(v0, v1, v2); }; - primitive_assembler.SubmitVertex(output, AddTriangle); + primitive_assembler.SubmitVertex(output_vertex, AddTriangle); } for (auto& range : memory_accesses.ranges) { diff --git a/src/video_core/shader/shader.cpp b/src/video_core/shader/shader.cpp index 161097610..f565e2c91 100644 --- a/src/video_core/shader/shader.cpp +++ b/src/video_core/shader/shader.cpp @@ -30,6 +30,58 @@ namespace Pica { namespace Shader { +OutputVertex OutputRegisters::ToVertex(const Regs::ShaderConfig& config) { + // Setup output data + OutputVertex ret; + // TODO(neobrain): Under some circumstances, up to 16 attributes may be output. We need to + // figure out what those circumstances are and enable the remaining outputs then. + unsigned index = 0; + for (unsigned i = 0; i < 7; ++i) { + + if (index >= g_state.regs.vs_output_total) + break; + + if ((config.output_mask & (1 << i)) == 0) + continue; + + const auto& output_register_map = g_state.regs.vs_output_attributes[index]; + + u32 semantics[4] = { + output_register_map.map_x, output_register_map.map_y, + output_register_map.map_z, output_register_map.map_w + }; + + for (unsigned comp = 0; comp < 4; ++comp) { + float24* out = ((float24*)&ret) + semantics[comp]; + if (semantics[comp] != Regs::VSOutputAttributes::INVALID) { + *out = value[i][comp]; + } else { + // Zero output so that attributes which aren't output won't have denormals in them, + // which would slow us down later. + memset(out, 0, sizeof(*out)); + } + } + + index++; + } + + // The hardware takes the absolute and saturates vertex colors like this, *before* doing interpolation + for (unsigned i = 0; i < 4; ++i) { + ret.color[i] = float24::FromFloat32( + std::fmin(std::fabs(ret.color[i].ToFloat32()), 1.0f)); + } + + LOG_TRACE(HW_GPU, "Output vertex: pos(%.2f, %.2f, %.2f, %.2f), quat(%.2f, %.2f, %.2f, %.2f), " + "col(%.2f, %.2f, %.2f, %.2f), tc0(%.2f, %.2f), view(%.2f, %.2f, %.2f)", + ret.pos.x.ToFloat32(), ret.pos.y.ToFloat32(), ret.pos.z.ToFloat32(), ret.pos.w.ToFloat32(), + ret.quat.x.ToFloat32(), ret.quat.y.ToFloat32(), ret.quat.z.ToFloat32(), ret.quat.w.ToFloat32(), + ret.color.x.ToFloat32(), ret.color.y.ToFloat32(), ret.color.z.ToFloat32(), ret.color.w.ToFloat32(), + ret.tc0.u().ToFloat32(), ret.tc0.v().ToFloat32(), + ret.view.x.ToFloat32(), ret.view.y.ToFloat32(), ret.view.z.ToFloat32()); + + return ret; +} + #ifdef ARCHITECTURE_x86_64 static std::unordered_map> shader_map; static const JitShader* jit_shader; @@ -62,7 +114,7 @@ void ShaderSetup::Setup() { MICROPROFILE_DEFINE(GPU_Shader, "GPU", "Shader", MP_RGB(50, 50, 240)); -OutputVertex ShaderSetup::Run(UnitState& state, const InputVertex& input, int num_attributes) { +void ShaderSetup::Run(UnitState& state, const InputVertex& input, int num_attributes) { auto& config = g_state.regs.vs; auto& setup = g_state.vs; @@ -89,55 +141,6 @@ OutputVertex ShaderSetup::Run(UnitState& state, const InputVertex& input, RunInterpreter(setup, state, config.main_offset); #endif // ARCHITECTURE_x86_64 - // Setup output data - OutputVertex ret; - // TODO(neobrain): Under some circumstances, up to 16 attributes may be output. We need to - // figure out what those circumstances are and enable the remaining outputs then. - unsigned index = 0; - for (unsigned i = 0; i < 7; ++i) { - - if (index >= g_state.regs.vs_output_total) - break; - - if ((g_state.regs.vs.output_mask & (1 << i)) == 0) - continue; - - const auto& output_register_map = g_state.regs.vs_output_attributes[index]; // TODO: Don't hardcode VS here - - u32 semantics[4] = { - output_register_map.map_x, output_register_map.map_y, - output_register_map.map_z, output_register_map.map_w - }; - - for (unsigned comp = 0; comp < 4; ++comp) { - float24* out = ((float24*)&ret) + semantics[comp]; - if (semantics[comp] != Regs::VSOutputAttributes::INVALID) { - *out = state.registers.output[i][comp]; - } else { - // Zero output so that attributes which aren't output won't have denormals in them, - // which would slow us down later. - memset(out, 0, sizeof(*out)); - } - } - - index++; - } - - // The hardware takes the absolute and saturates vertex colors like this, *before* doing interpolation - for (unsigned i = 0; i < 4; ++i) { - ret.color[i] = float24::FromFloat32( - std::fmin(std::fabs(ret.color[i].ToFloat32()), 1.0f)); - } - - LOG_TRACE(HW_GPU, "Output vertex: pos(%.2f, %.2f, %.2f, %.2f), quat(%.2f, %.2f, %.2f, %.2f), " - "col(%.2f, %.2f, %.2f, %.2f), tc0(%.2f, %.2f), view(%.2f, %.2f, %.2f)", - ret.pos.x.ToFloat32(), ret.pos.y.ToFloat32(), ret.pos.z.ToFloat32(), ret.pos.w.ToFloat32(), - ret.quat.x.ToFloat32(), ret.quat.y.ToFloat32(), ret.quat.z.ToFloat32(), ret.quat.w.ToFloat32(), - ret.color.x.ToFloat32(), ret.color.y.ToFloat32(), ret.color.z.ToFloat32(), ret.color.w.ToFloat32(), - ret.tc0.u().ToFloat32(), ret.tc0.v().ToFloat32(), - ret.view.x.ToFloat32(), ret.view.y.ToFloat32(), ret.view.z.ToFloat32()); - - return ret; } DebugData ShaderSetup::ProduceDebugInfo(const InputVertex& input, int num_attributes, const Regs::ShaderConfig& config, const ShaderSetup& setup) { diff --git a/src/video_core/shader/shader.h b/src/video_core/shader/shader.h index 84898f21c..fee16df62 100644 --- a/src/video_core/shader/shader.h +++ b/src/video_core/shader/shader.h @@ -84,6 +84,15 @@ struct OutputVertex { static_assert(std::is_pod::value, "Structure is not POD"); static_assert(sizeof(OutputVertex) == 32 * sizeof(float), "OutputVertex has invalid size"); +struct OutputRegisters { + OutputRegisters() = default; + + alignas(16) Math::Vec4 value[16]; + + OutputVertex ToVertex(const Regs::ShaderConfig& config); +}; +static_assert(std::is_pod::value, "Structure is not POD"); + // Helper structure used to keep track of data useful for inspection of shader emulation template struct DebugData; @@ -267,11 +276,12 @@ struct UnitState { // The registers are accessed by the shader JIT using SSE instructions, and are therefore // required to be 16-byte aligned. alignas(16) Math::Vec4 input[16]; - alignas(16) Math::Vec4 output[16]; alignas(16) Math::Vec4 temporary[16]; } registers; static_assert(std::is_pod::value, "Structure is not POD"); + OutputRegisters output_registers; + bool conditional_code[2]; // Two Address registers and one loop counter @@ -297,7 +307,7 @@ struct UnitState { static size_t OutputOffset(const DestRegister& reg) { switch (reg.GetRegisterType()) { case RegisterType::Output: - return offsetof(UnitState, registers.output) + reg.GetIndex()*sizeof(Math::Vec4); + return offsetof(UnitState, output_registers.value) + reg.GetIndex()*sizeof(Math::Vec4); case RegisterType::Temporary: return offsetof(UnitState, registers.temporary) + reg.GetIndex()*sizeof(Math::Vec4); @@ -354,9 +364,8 @@ struct ShaderSetup { * @param state Shader unit state, must be setup per shader and per shader unit * @param input Input vertex into the shader * @param num_attributes The number of vertex shader attributes - * @return The output vertex, after having been processed by the vertex shader */ - OutputVertex Run(UnitState& state, const InputVertex& input, int num_attributes); + void Run(UnitState& state, const InputVertex& input, int num_attributes); /** * Produce debug information based on the given shader and input vertex diff --git a/src/video_core/shader/shader_interpreter.cpp b/src/video_core/shader/shader_interpreter.cpp index 714e8bfd5..b1eadc071 100644 --- a/src/video_core/shader/shader_interpreter.cpp +++ b/src/video_core/shader/shader_interpreter.cpp @@ -144,7 +144,7 @@ void RunInterpreter(const ShaderSetup& setup, UnitState& state, unsigned src2[3] = src2[3] * float24::FromFloat32(-1); } - float24* dest = (instr.common.dest.Value() < 0x10) ? &state.registers.output[instr.common.dest.Value().GetIndex()][0] + float24* dest = (instr.common.dest.Value() < 0x10) ? &state.output_registers.value[instr.common.dest.Value().GetIndex()][0] : (instr.common.dest.Value() < 0x20) ? &state.registers.temporary[instr.common.dest.Value().GetIndex()][0] : dummy_vec4_float24; @@ -483,7 +483,7 @@ void RunInterpreter(const ShaderSetup& setup, UnitState& state, unsigned src3[3] = src3[3] * float24::FromFloat32(-1); } - float24* dest = (instr.mad.dest.Value() < 0x10) ? &state.registers.output[instr.mad.dest.Value().GetIndex()][0] + float24* dest = (instr.mad.dest.Value() < 0x10) ? &state.output_registers.value[instr.mad.dest.Value().GetIndex()][0] : (instr.mad.dest.Value() < 0x20) ? &state.registers.temporary[instr.mad.dest.Value().GetIndex()][0] : dummy_vec4_float24; From 7dde13f87544c59807436e2eefe0f1b65fad841c Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 16 May 2016 10:55:00 +0200 Subject: [PATCH 18/60] Fix exception propagation for VFP double precision --- src/core/arm/skyeye_common/vfp/vfp_helper.h | 8 ++- src/core/arm/skyeye_common/vfp/vfpdouble.cpp | 65 ++++++++++---------- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h index 210972917..c1cc4fd7e 100644 --- a/src/core/arm/skyeye_common/vfp/vfp_helper.h +++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h @@ -357,8 +357,9 @@ inline int vfp_double_type(const vfp_double* s) // Unpack a double-precision float. Note that this returns the magnitude // of the double-precision float mantissa with the 1. if necessary, // aligned to bit 62. -inline void vfp_double_unpack(vfp_double* s, s64 val, u32* fpscr) +inline u32 vfp_double_unpack(vfp_double* s, s64 val, u32 fpscr) { + u32 exceptions = 0; s->sign = vfp_double_packed_sign(val) >> 48; s->exponent = vfp_double_packed_exponent(val); @@ -369,12 +370,13 @@ inline void vfp_double_unpack(vfp_double* s, s64 val, u32* fpscr) // If flush-to-zero mode is enabled, turn the denormal into zero. // On a VFPv2 architecture, the sign of the zero is always positive. - if ((*fpscr & FPSCR_FLUSH_TO_ZERO) != 0 && (vfp_double_type(s) & VFP_DENORMAL) != 0) { + if ((fpscr & FPSCR_FLUSH_TO_ZERO) != 0 && (vfp_double_type(s) & VFP_DENORMAL) != 0) { s->sign = 0; s->exponent = 0; s->significand = 0; - *fpscr |= FPSCR_IDC; + exceptions |= FPSCR_IDC; } + return exceptions; } // Re-pack a double-precision float. This assumes that the float is diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp index 45914d479..0182b90b8 100644 --- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp @@ -291,8 +291,9 @@ static u32 vfp_double_fsqrt(ARMul_State* state, int dd, int unused, int dm, u32 LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); vfp_double vdm, vdd, *vdp; int ret, tm; + u32 exceptions = 0; - vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr); + exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); tm = vfp_double_type(&vdm); if (tm & (VFP_NAN|VFP_INFINITY)) { @@ -369,7 +370,9 @@ sqrt_invalid: } vdd.significand = vfp_shiftright64jamming(vdd.significand, 1); - return vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fsqrt"); + exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fsqrt"); + + return exceptions; } /* @@ -475,7 +478,7 @@ static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 u32 exceptions = 0; LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr); + exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); tm = vfp_double_type(&vdm); @@ -545,7 +548,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 int tm; LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr); + exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); /* * Do we have a denormalised number? @@ -626,7 +629,7 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 int tm; LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr); + exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); vfp_double_dump("VDM", &vdm); /* @@ -892,21 +895,21 @@ static u32 vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 fpscr, u32 negate, const char *func) { struct vfp_double vdd, vdp, vdn, vdm; - u32 exceptions; + u32 exceptions = 0; - vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr); + exceptions |= vfp_double_unpack(&vdn, vfp_get_double(state, dn), fpscr); if (vdn.exponent == 0 && vdn.significand) vfp_double_normalise_denormal(&vdn); - vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr); + exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); if (vdm.exponent == 0 && vdm.significand) vfp_double_normalise_denormal(&vdm); - exceptions = vfp_double_multiply(&vdp, &vdn, &vdm, fpscr); + exceptions |= vfp_double_multiply(&vdp, &vdn, &vdm, fpscr); if (negate & NEG_MULTIPLY) vdp.sign = vfp_sign_negate(vdp.sign); - vfp_double_unpack(&vdn, vfp_get_double(state, dd), &fpscr); + exceptions |= vfp_double_unpack(&vdn, vfp_get_double(state, dd), fpscr); if (vdn.exponent == 0 && vdn.significand != 0) vfp_double_normalise_denormal(&vdn); @@ -964,18 +967,18 @@ static u32 vfp_double_fnmsc(ARMul_State* state, int dd, int dn, int dm, u32 fpsc static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) { struct vfp_double vdd, vdn, vdm; - u32 exceptions; + u32 exceptions = 0; LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr); + exceptions |= vfp_double_unpack(&vdn, vfp_get_double(state, dn), fpscr); if (vdn.exponent == 0 && vdn.significand) vfp_double_normalise_denormal(&vdn); - vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr); + exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); if (vdm.exponent == 0 && vdm.significand) vfp_double_normalise_denormal(&vdm); - exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr); + exceptions |= vfp_double_multiply(&vdd, &vdn, &vdm, fpscr); return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fmul"); } @@ -985,18 +988,18 @@ static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) { struct vfp_double vdd, vdn, vdm; - u32 exceptions; + u32 exceptions = 0; LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr); + exceptions |= vfp_double_unpack(&vdn, vfp_get_double(state, dn), fpscr); if (vdn.exponent == 0 && vdn.significand) vfp_double_normalise_denormal(&vdn); - vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr); + exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); if (vdm.exponent == 0 && vdm.significand) vfp_double_normalise_denormal(&vdm); - exceptions = vfp_double_multiply(&vdd, &vdn, &vdm, fpscr); + exceptions |= vfp_double_multiply(&vdd, &vdn, &vdm, fpscr); vdd.sign = vfp_sign_negate(vdd.sign); return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fnmul"); @@ -1008,18 +1011,18 @@ static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpsc static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) { struct vfp_double vdd, vdn, vdm; - u32 exceptions; + u32 exceptions = 0; LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr); + exceptions |= vfp_double_unpack(&vdn, vfp_get_double(state, dn), fpscr); if (vdn.exponent == 0 && vdn.significand) vfp_double_normalise_denormal(&vdn); - vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr); + exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); if (vdm.exponent == 0 && vdm.significand) vfp_double_normalise_denormal(&vdm); - exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr); + exceptions |= vfp_double_add(&vdd, &vdn, &vdm, fpscr); return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fadd"); } @@ -1030,14 +1033,14 @@ static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr) { struct vfp_double vdd, vdn, vdm; - u32 exceptions; + u32 exceptions = 0; LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr); + exceptions |= vfp_double_unpack(&vdn, vfp_get_double(state, dn), fpscr); if (vdn.exponent == 0 && vdn.significand) vfp_double_normalise_denormal(&vdn); - vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr); + exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); if (vdm.exponent == 0 && vdm.significand) vfp_double_normalise_denormal(&vdm); @@ -1046,7 +1049,7 @@ static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr */ vdm.sign = vfp_sign_negate(vdm.sign); - exceptions = vfp_double_add(&vdd, &vdn, &vdm, fpscr); + exceptions |= vfp_double_add(&vdd, &vdn, &vdm, fpscr); return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fsub"); } @@ -1061,8 +1064,8 @@ static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr int tm, tn; LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); - vfp_double_unpack(&vdn, vfp_get_double(state, dn), &fpscr); - vfp_double_unpack(&vdm, vfp_get_double(state, dm), &fpscr); + exceptions |= vfp_double_unpack(&vdn, vfp_get_double(state, dn), fpscr); + exceptions |= vfp_double_unpack(&vdm, vfp_get_double(state, dm), fpscr); vdd.sign = vdn.sign ^ vdm.sign; @@ -1134,13 +1137,13 @@ static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr return vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fdiv"); vdn_nan: - exceptions = vfp_propagate_nan(&vdd, &vdn, &vdm, fpscr); + exceptions |= vfp_propagate_nan(&vdd, &vdn, &vdm, fpscr); pack: vfp_put_double(state, vfp_double_pack(&vdd), dd); return exceptions; vdm_nan: - exceptions = vfp_propagate_nan(&vdd, &vdm, &vdn, fpscr); + exceptions |= vfp_propagate_nan(&vdd, &vdm, &vdn, fpscr); goto pack; zero: @@ -1149,7 +1152,7 @@ zero: goto pack; divzero: - exceptions = FPSCR_DZC; + exceptions |= FPSCR_DZC; infinity: vdd.exponent = 2047; vdd.significand = 0; From 693cca8f1f069ddd88a3f47f94fae5e53712ded4 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 16 May 2016 11:11:16 +0200 Subject: [PATCH 19/60] Fix exception propagation for VFP single precision --- src/core/arm/skyeye_common/vfp/vfp_helper.h | 8 ++- src/core/arm/skyeye_common/vfp/vfpsingle.cpp | 63 ++++++++++---------- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h index c1cc4fd7e..c66a3fad4 100644 --- a/src/core/arm/skyeye_common/vfp/vfp_helper.h +++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h @@ -271,8 +271,9 @@ inline int vfp_single_type(const vfp_single* s) // Unpack a single-precision float. Note that this returns the magnitude // of the single-precision float mantissa with the 1. if necessary, // aligned to bit 30. -inline void vfp_single_unpack(vfp_single* s, s32 val, u32* fpscr) +inline u32 vfp_single_unpack(vfp_single* s, s32 val, u32 fpscr) { + u32 exceptions = 0; s->sign = vfp_single_packed_sign(val) >> 16, s->exponent = vfp_single_packed_exponent(val); @@ -283,12 +284,13 @@ inline void vfp_single_unpack(vfp_single* s, s32 val, u32* fpscr) // If flush-to-zero mode is enabled, turn the denormal into zero. // On a VFPv2 architecture, the sign of the zero is always positive. - if ((*fpscr & FPSCR_FLUSH_TO_ZERO) != 0 && (vfp_single_type(s) & VFP_DENORMAL) != 0) { + if ((fpscr & FPSCR_FLUSH_TO_ZERO) != 0 && (vfp_single_type(s) & VFP_DENORMAL) != 0) { s->sign = 0; s->exponent = 0; s->significand = 0; - *fpscr |= FPSCR_IDC; + exceptions |= FPSCR_IDC; } + return exceptions; } // Re-pack a single-precision float. This assumes that the float is diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp index e47ad2760..5fb6b51ec 100644 --- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp @@ -334,8 +334,9 @@ static u32 vfp_single_fsqrt(ARMul_State* state, int sd, int unused, s32 m, u32 f { struct vfp_single vsm, vsd, *vsp; int ret, tm; + u32 exceptions = 0; - vfp_single_unpack(&vsm, m, &fpscr); + exceptions |= vfp_single_unpack(&vsm, m, fpscr); tm = vfp_single_type(&vsm); if (tm & (VFP_NAN|VFP_INFINITY)) { vsp = &vsd; @@ -408,7 +409,9 @@ sqrt_invalid: } vsd.significand = vfp_shiftright32jamming(vsd.significand, 1); - return vfp_single_normaliseround(state, sd, &vsd, fpscr, 0, "fsqrt"); + exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, 0, "fsqrt"); + + return exceptions; } /* @@ -503,7 +506,7 @@ static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 f int tm; u32 exceptions = 0; - vfp_single_unpack(&vsm, m, &fpscr); + exceptions |= vfp_single_unpack(&vsm, m, fpscr); tm = vfp_single_type(&vsm); @@ -511,7 +514,7 @@ static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 f * If we have a signalling NaN, signal invalid operation. */ if (tm == VFP_SNAN) - exceptions = FPSCR_IOC; + exceptions |= FPSCR_IOC; if (tm & VFP_DENORMAL) vfp_single_normalise_denormal(&vsm); @@ -568,7 +571,7 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f int rmode = fpscr & FPSCR_RMODE_MASK; int tm; - vfp_single_unpack(&vsm, m, &fpscr); + exceptions |= vfp_single_unpack(&vsm, m, fpscr); vfp_single_dump("VSM", &vsm); /* @@ -583,7 +586,7 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f if (vsm.exponent >= 127 + 32) { d = vsm.sign ? 0 : 0xffffffff; - exceptions = FPSCR_IOC; + exceptions |= FPSCR_IOC; } else if (vsm.exponent >= 127) { int shift = 127 + 31 - vsm.exponent; u32 rem, incr = 0; @@ -648,7 +651,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f int rmode = fpscr & FPSCR_RMODE_MASK; int tm; - vfp_single_unpack(&vsm, m, &fpscr); + exceptions |= vfp_single_unpack(&vsm, m, fpscr); vfp_single_dump("VSM", &vsm); /* @@ -774,7 +777,7 @@ vfp_single_fadd_nonnumber(struct vfp_single *vsd, struct vfp_single *vsn, /* * different signs -> invalid */ - exceptions = FPSCR_IOC; + exceptions |= FPSCR_IOC; vsp = &vfp_single_default_qnan; } else { /* @@ -921,27 +924,27 @@ static u32 vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr, u32 negate, const char *func) { vfp_single vsd, vsp, vsn, vsm; - u32 exceptions; + u32 exceptions = 0; s32 v; v = vfp_get_float(state, sn); LOG_TRACE(Core_ARM11, "s%u = %08x", sn, v); - vfp_single_unpack(&vsn, v, &fpscr); + exceptions |= vfp_single_unpack(&vsn, v, fpscr); if (vsn.exponent == 0 && vsn.significand) vfp_single_normalise_denormal(&vsn); - vfp_single_unpack(&vsm, m, &fpscr); + exceptions |= vfp_single_unpack(&vsm, m, fpscr); if (vsm.exponent == 0 && vsm.significand) vfp_single_normalise_denormal(&vsm); - exceptions = vfp_single_multiply(&vsp, &vsn, &vsm, fpscr); + exceptions |= vfp_single_multiply(&vsp, &vsn, &vsm, fpscr); if (negate & NEG_MULTIPLY) vsp.sign = vfp_sign_negate(vsp.sign); v = vfp_get_float(state, sd); LOG_TRACE(Core_ARM11, "s%u = %08x", sd, v); - vfp_single_unpack(&vsn, v, &fpscr); + exceptions |= vfp_single_unpack(&vsn, v, fpscr); if (vsn.exponent == 0 && vsn.significand != 0) vfp_single_normalise_denormal(&vsn); @@ -1000,20 +1003,20 @@ static u32 vfp_single_fnmsc(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) { struct vfp_single vsd, vsn, vsm; - u32 exceptions; + u32 exceptions = 0; s32 n = vfp_get_float(state, sn); LOG_TRACE(Core_ARM11, "s%u = %08x", sn, n); - vfp_single_unpack(&vsn, n, &fpscr); + exceptions |= vfp_single_unpack(&vsn, n, fpscr); if (vsn.exponent == 0 && vsn.significand) vfp_single_normalise_denormal(&vsn); - vfp_single_unpack(&vsm, m, &fpscr); + exceptions |= vfp_single_unpack(&vsm, m, fpscr); if (vsm.exponent == 0 && vsm.significand) vfp_single_normalise_denormal(&vsm); - exceptions = vfp_single_multiply(&vsd, &vsn, &vsm, fpscr); + exceptions |= vfp_single_multiply(&vsd, &vsn, &vsm, fpscr); return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fmul"); } @@ -1023,20 +1026,20 @@ static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) { struct vfp_single vsd, vsn, vsm; - u32 exceptions; + u32 exceptions = 0; s32 n = vfp_get_float(state, sn); LOG_TRACE(Core_ARM11, "s%u = %08x", sn, n); - vfp_single_unpack(&vsn, n, &fpscr); + exceptions |= vfp_single_unpack(&vsn, n, fpscr); if (vsn.exponent == 0 && vsn.significand) vfp_single_normalise_denormal(&vsn); - vfp_single_unpack(&vsm, m, &fpscr); + exceptions |= vfp_single_unpack(&vsm, m, fpscr); if (vsm.exponent == 0 && vsm.significand) vfp_single_normalise_denormal(&vsm); - exceptions = vfp_single_multiply(&vsd, &vsn, &vsm, fpscr); + exceptions |= vfp_single_multiply(&vsd, &vsn, &vsm, fpscr); vsd.sign = vfp_sign_negate(vsd.sign); return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fnmul"); } @@ -1047,7 +1050,7 @@ static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) { struct vfp_single vsd, vsn, vsm; - u32 exceptions; + u32 exceptions = 0; s32 n = vfp_get_float(state, sn); LOG_TRACE(Core_ARM11, "s%u = %08x", sn, n); @@ -1055,15 +1058,15 @@ static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) /* * Unpack and normalise denormals. */ - vfp_single_unpack(&vsn, n, &fpscr); + exceptions |= vfp_single_unpack(&vsn, n, fpscr); if (vsn.exponent == 0 && vsn.significand) vfp_single_normalise_denormal(&vsn); - vfp_single_unpack(&vsm, m, &fpscr); + exceptions |= vfp_single_unpack(&vsm, m, fpscr); if (vsm.exponent == 0 && vsm.significand) vfp_single_normalise_denormal(&vsm); - exceptions = vfp_single_add(&vsd, &vsn, &vsm, fpscr); + exceptions |= vfp_single_add(&vsd, &vsn, &vsm, fpscr); return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fadd"); } @@ -1095,8 +1098,8 @@ static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) LOG_TRACE(Core_ARM11, "s%u = %08x", sn, n); - vfp_single_unpack(&vsn, n, &fpscr); - vfp_single_unpack(&vsm, m, &fpscr); + exceptions |= vfp_single_unpack(&vsn, n, fpscr); + exceptions |= vfp_single_unpack(&vsm, m, fpscr); vsd.sign = vsn.sign ^ vsm.sign; @@ -1165,13 +1168,13 @@ static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) return vfp_single_normaliseround(state, sd, &vsd, fpscr, 0, "fdiv"); vsn_nan: - exceptions = vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr); + exceptions |= vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr); pack: vfp_put_float(state, vfp_single_pack(&vsd), sd); return exceptions; vsm_nan: - exceptions = vfp_propagate_nan(&vsd, &vsm, &vsn, fpscr); + exceptions |= vfp_propagate_nan(&vsd, &vsm, &vsn, fpscr); goto pack; zero: @@ -1180,7 +1183,7 @@ zero: goto pack; divzero: - exceptions = FPSCR_DZC; + exceptions |= FPSCR_DZC; infinity: vsd.exponent = 255; vsd.significand = 0; From edf30d84cc0e8299d61c98f5bb40a6428d1576bc Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Wed, 18 May 2016 15:12:31 +0200 Subject: [PATCH 20/60] Remove `exceptions` parameter from `normaliseround` VFP functions --- src/core/arm/skyeye_common/vfp/vfp_helper.h | 4 +- src/core/arm/skyeye_common/vfp/vfpdouble.cpp | 40 ++++++++++++------- src/core/arm/skyeye_common/vfp/vfpsingle.cpp | 41 +++++++++++++------- 3 files changed, 57 insertions(+), 28 deletions(-) diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h index c66a3fad4..68714800c 100644 --- a/src/core/arm/skyeye_common/vfp/vfp_helper.h +++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h @@ -304,7 +304,7 @@ inline s32 vfp_single_pack(const vfp_single* s) } -u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single* vs, u32 fpscr, u32 exceptions, const char* func); +u32 vfp_single_normaliseround(ARMul_State* state, int sd, vfp_single* vs, u32 fpscr, const char* func); // Double-precision struct vfp_double { @@ -451,4 +451,4 @@ inline u32 fls(u32 x) u32 vfp_double_multiply(vfp_double* vdd, vfp_double* vdn, vfp_double* vdm, u32 fpscr); u32 vfp_double_add(vfp_double* vdd, vfp_double* vdn, vfp_double *vdm, u32 fpscr); -u32 vfp_double_normaliseround(ARMul_State* state, int dd, vfp_double* vd, u32 fpscr, u32 exceptions, const char* func); +u32 vfp_double_normaliseround(ARMul_State* state, int dd, vfp_double* vd, u32 fpscr, const char* func); diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp index 0182b90b8..580e60c85 100644 --- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp @@ -85,11 +85,12 @@ static void vfp_double_normalise_denormal(struct vfp_double *vd) vfp_double_dump("normalise_denormal: out", vd); } -u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, u32 exceptions, const char *func) +u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, u32 fpscr, const char *func) { u64 significand, incr; int exponent, shift, underflow; u32 rmode; + u32 exceptions = 0; vfp_double_dump("pack: in", vd); @@ -370,8 +371,7 @@ sqrt_invalid: } vdd.significand = vfp_shiftright64jamming(vdd.significand, 1); - exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fsqrt"); - + exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, "fsqrt"); return exceptions; } @@ -507,7 +507,8 @@ static u32 vfp_double_fcvts(ARMul_State* state, int sd, int unused, int dm, u32 else vsd.exponent = vdm.exponent - (1023 - 127); - return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fcvts"); + exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, "fcvts"); + return exceptions; pack_nan: vfp_put_float(state, vfp_single_pack(&vsd), sd); @@ -517,6 +518,7 @@ pack_nan: static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { struct vfp_double vdm; + u32 exceptions = 0; u32 m = vfp_get_float(state, dm); LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); @@ -524,12 +526,14 @@ static u32 vfp_double_fuito(ARMul_State* state, int dd, int unused, int dm, u32 vdm.exponent = 1023 + 63 - 1; vdm.significand = (u64)m; - return vfp_double_normaliseround(state, dd, &vdm, fpscr, 0, "fuito"); + exceptions |= vfp_double_normaliseround(state, dd, &vdm, fpscr, "fuito"); + return exceptions; } static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32 fpscr) { struct vfp_double vdm; + u32 exceptions = 0; u32 m = vfp_get_float(state, dm); LOG_TRACE(Core_ARM11, "In %s", __FUNCTION__); @@ -537,7 +541,8 @@ static u32 vfp_double_fsito(ARMul_State* state, int dd, int unused, int dm, u32 vdm.exponent = 1023 + 63 - 1; vdm.significand = vdm.sign ? (~m + 1) : m; - return vfp_double_normaliseround(state, dd, &vdm, fpscr, 0, "fsito"); + exceptions |= vfp_double_normaliseround(state, dd, &vdm, fpscr, "fsito"); + return exceptions; } static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 fpscr) @@ -918,7 +923,8 @@ vfp_double_multiply_accumulate(ARMul_State* state, int dd, int dn, int dm, u32 f exceptions |= vfp_double_add(&vdd, &vdn, &vdp, fpscr); - return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, func); + exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, func); + return exceptions; } /* @@ -979,7 +985,9 @@ static u32 vfp_double_fmul(ARMul_State* state, int dd, int dn, int dm, u32 fpscr vfp_double_normalise_denormal(&vdm); exceptions |= vfp_double_multiply(&vdd, &vdn, &vdm, fpscr); - return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fmul"); + + exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, "fmul"); + return exceptions; } /* @@ -1002,7 +1010,8 @@ static u32 vfp_double_fnmul(ARMul_State* state, int dd, int dn, int dm, u32 fpsc exceptions |= vfp_double_multiply(&vdd, &vdn, &vdm, fpscr); vdd.sign = vfp_sign_negate(vdd.sign); - return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fnmul"); + exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, "fnmul"); + return exceptions; } /* @@ -1024,7 +1033,8 @@ static u32 vfp_double_fadd(ARMul_State* state, int dd, int dn, int dm, u32 fpscr exceptions |= vfp_double_add(&vdd, &vdn, &vdm, fpscr); - return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fadd"); + exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, "fadd"); + return exceptions; } /* @@ -1051,7 +1061,8 @@ static u32 vfp_double_fsub(ARMul_State* state, int dd, int dn, int dm, u32 fpscr exceptions |= vfp_double_add(&vdd, &vdn, &vdm, fpscr); - return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fsub"); + exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, "fsub"); + return exceptions; } /* @@ -1134,7 +1145,9 @@ static u32 vfp_double_fdiv(ARMul_State* state, int dd, int dn, int dm, u32 fpscr } vdd.significand |= (reml != 0); } - return vfp_double_normaliseround(state, dd, &vdd, fpscr, 0, "fdiv"); + + exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, "fdiv"); + return exceptions; vdn_nan: exceptions |= vfp_propagate_nan(&vdd, &vdn, &vdm, fpscr); @@ -1160,7 +1173,8 @@ infinity: invalid: vfp_put_double(state, vfp_double_pack(&vfp_double_default_qnan), dd); - return FPSCR_IOC; + exceptions |= FPSCR_IOC; + return exceptions; } static struct op fops[] = { diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp index 5fb6b51ec..23e0cdf26 100644 --- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp @@ -89,10 +89,11 @@ static void vfp_single_normalise_denormal(struct vfp_single *vs) } -u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs, u32 fpscr, u32 exceptions, const char *func) +u32 vfp_single_normaliseround(ARMul_State* state, int sd, struct vfp_single *vs, u32 fpscr, const char *func) { u32 significand, incr, rmode; int exponent, shift, underflow; + u32 exceptions = 0; vfp_single_dump("pack: in", vs); @@ -409,8 +410,7 @@ sqrt_invalid: } vsd.significand = vfp_shiftright32jamming(vsd.significand, 1); - exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, 0, "fsqrt"); - + exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, "fsqrt"); return exceptions; } @@ -535,7 +535,8 @@ static u32 vfp_single_fcvtd(ARMul_State* state, int dd, int unused, s32 m, u32 f else vdd.exponent = vsm.exponent + (1023 - 127); - return vfp_double_normaliseround(state, dd, &vdd, fpscr, exceptions, "fcvtd"); + exceptions |= vfp_double_normaliseround(state, dd, &vdd, fpscr, "fcvtd"); + return exceptions; pack_nan: vfp_put_double(state, vfp_double_pack(&vdd), dd); @@ -545,23 +546,27 @@ pack_nan: static u32 vfp_single_fuito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { struct vfp_single vs; + u32 exceptions = 0; vs.sign = 0; vs.exponent = 127 + 31 - 1; vs.significand = (u32)m; - return vfp_single_normaliseround(state, sd, &vs, fpscr, 0, "fuito"); + exceptions |= vfp_single_normaliseround(state, sd, &vs, fpscr, "fuito"); + return exceptions; } static u32 vfp_single_fsito(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) { struct vfp_single vs; + u32 exceptions = 0; vs.sign = (m & 0x80000000) >> 16; vs.exponent = 127 + 31 - 1; vs.significand = vs.sign ? -m : m; - return vfp_single_normaliseround(state, sd, &vs, fpscr, 0, "fsito"); + exceptions |= vfp_single_normaliseround(state, sd, &vs, fpscr, "fsito"); + return exceptions; } static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 fpscr) @@ -953,7 +958,8 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp exceptions |= vfp_single_add(&vsd, &vsn, &vsp, fpscr); - return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, func); + exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, func); + return exceptions; } /* @@ -965,8 +971,10 @@ vfp_single_multiply_accumulate(ARMul_State* state, int sd, int sn, s32 m, u32 fp */ static u32 vfp_single_fmac(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) { + u32 exceptions = 0; LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); - return vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac"); + exceptions |= vfp_single_multiply_accumulate(state, sd, sn, m, fpscr, 0, "fmac"); + return exceptions; } /* @@ -1017,7 +1025,9 @@ static u32 vfp_single_fmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) vfp_single_normalise_denormal(&vsm); exceptions |= vfp_single_multiply(&vsd, &vsn, &vsm, fpscr); - return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fmul"); + + exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, "fmul"); + return exceptions; } /* @@ -1041,7 +1051,9 @@ static u32 vfp_single_fnmul(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr exceptions |= vfp_single_multiply(&vsd, &vsn, &vsm, fpscr); vsd.sign = vfp_sign_negate(vsd.sign); - return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fnmul"); + + exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, "fnmul"); + return exceptions; } /* @@ -1068,7 +1080,8 @@ static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) exceptions |= vfp_single_add(&vsd, &vsn, &vsm, fpscr); - return vfp_single_normaliseround(state, sd, &vsd, fpscr, exceptions, "fadd"); + exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, "fadd"); + return exceptions; } /* @@ -1165,7 +1178,8 @@ static u32 vfp_single_fdiv(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) if ((vsd.significand & 0x3f) == 0) vsd.significand |= ((u64)vsm.significand * vsd.significand != (u64)vsn.significand << 32); - return vfp_single_normaliseround(state, sd, &vsd, fpscr, 0, "fdiv"); + exceptions |= vfp_single_normaliseround(state, sd, &vsd, fpscr, "fdiv"); + return exceptions; vsn_nan: exceptions |= vfp_propagate_nan(&vsd, &vsn, &vsm, fpscr); @@ -1191,7 +1205,8 @@ infinity: invalid: vfp_put_float(state, vfp_single_pack(&vfp_single_default_qnan), sd); - return FPSCR_IOC; + exceptions |= FPSCR_IOC; + return exceptions; } static struct op fops[] = { From 86ea7995ad6a6cb24fc02025e1a1241c00565809 Mon Sep 17 00:00:00 2001 From: wwylele Date: Sat, 21 May 2016 17:45:18 +0300 Subject: [PATCH 21/60] SVC::WaitSynchronizationN: Reschedule at the end --- src/core/hle/svc.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 2bf122a6d..0ce72de87 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -6,6 +6,7 @@ #include "common/logging/log.h" #include "common/microprofile.h" +#include "common/scope_exit.h" #include "common/string_util.h" #include "common/symbols.h" @@ -326,9 +327,9 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou } } - HLE::Reschedule(__func__); + SCOPE_EXIT({HLE::Reschedule("WaitSynchronizationN");}); // Reschedule after putting the threads to sleep. - // If thread should wait, then set its state to waiting and then reschedule... + // If thread should wait, then set its state to waiting if (wait_thread) { // Actually wait the current thread on each object if we decided to wait... From 8ab6f26c09e5b77a051fa545570ca2986c45bf4a Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sun, 6 Sep 2015 07:59:04 +0100 Subject: [PATCH 22/60] Common: Make recursive FileUtil functions take a maximum recursion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #1115. Also improves the performances of DiskArchive’s directory implementation a lot, simply by not going through the entire tree instead of just listing the first level files. Thanks to JayRoxFox for rebasing this on current master! --- src/citra_qt/game_list.cpp | 11 +++++---- src/citra_qt/game_list_p.h | 2 +- src/common/file_util.cpp | 48 ++++++++++++++++++++++---------------- src/common/file_util.h | 12 ++++++---- 4 files changed, 43 insertions(+), 30 deletions(-) diff --git a/src/citra_qt/game_list.cpp b/src/citra_qt/game_list.cpp index d4ac9c96e..adbcf24e8 100644 --- a/src/citra_qt/game_list.cpp +++ b/src/citra_qt/game_list.cpp @@ -118,19 +118,20 @@ void GameList::LoadInterfaceLayout() item_model->sort(header->sortIndicatorSection(), header->sortIndicatorOrder()); } -void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, bool deep_scan) +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) -> bool { + const std::string& virtual_name, + unsigned int recursion) -> bool { std::string physical_name = directory + DIR_SEP + virtual_name; if (stop_processing) return false; // Breaks the callback loop. - if (deep_scan && FileUtil::IsDirectory(physical_name)) { - AddFstEntriesToGameList(physical_name, true); + if (recursion > 0 && FileUtil::IsDirectory(physical_name)) { + AddFstEntriesToGameList(physical_name, recursion - 1); } else { std::string filename_filename, filename_extension; Common::SplitPath(physical_name, nullptr, &filename_filename, &filename_extension); @@ -169,7 +170,7 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, bool d void GameListWorker::run() { stop_processing = false; - AddFstEntriesToGameList(dir_path.toStdString(), deep_scan); + AddFstEntriesToGameList(dir_path.toStdString(), deep_scan ? 256 : 0); emit Finished(); } diff --git a/src/citra_qt/game_list_p.h b/src/citra_qt/game_list_p.h index 284f5da81..2d6b8aae0 100644 --- a/src/citra_qt/game_list_p.h +++ b/src/citra_qt/game_list_p.h @@ -212,5 +212,5 @@ private: bool deep_scan; std::atomic_bool stop_processing; - void AddFstEntriesToGameList(const std::string& dir_path, bool deep_scan); + void AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion = 0); }; diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 6e2867658..17af7c385 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) +bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directory, DirectoryEntryCallable callback, unsigned int recursion) { 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)) { + if (!callback(&ret_entries, directory, virtual_name, recursion)) { callback_error = true; break; } @@ -486,30 +486,34 @@ bool ForeachDirectoryEntry(unsigned* num_entries_out, const std::string &directo closedir(dirp); #endif - if (!callback_error) { - // num_entries_out is allowed to be specified nullptr, in which case we shouldn't try to set it - if (num_entries_out != nullptr) - *num_entries_out = found_entries; - return true; - } else { + if (callback_error) return false; - } + + // num_entries_out is allowed to be specified nullptr, in which case we shouldn't try to set it + if (num_entries_out != nullptr) + *num_entries_out = found_entries; + return true; } -unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry) +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) -> bool { + const std::string& virtual_name, + unsigned int recursion) -> bool { FSTEntry entry; entry.virtualName = virtual_name; entry.physicalName = directory + DIR_SEP + virtual_name; if (IsDirectory(entry.physicalName)) { entry.isDirectory = true; - // is a directory, lets go inside - entry.size = ScanDirectoryTree(entry.physicalName, entry); - *num_entries_out += (int)entry.size; + // is a directory, lets go inside if we didn't recurse to often + if (recursion > 0) { + entry.size = ScanDirectoryTree(entry.physicalName, entry, recursion - 1); + *num_entries_out += (int)entry.size; + } else { + entry.size = 0; + } } else { // is a file entry.isDirectory = false; entry.size = GetSize(entry.physicalName); @@ -522,23 +526,27 @@ unsigned ScanDirectoryTree(const std::string &directory, FSTEntry& parent_entry) }; unsigned num_entries; - return ForeachDirectoryEntry(&num_entries, directory, callback) ? num_entries : 0; + return ForeachDirectoryEntry(&num_entries, directory, callback, recursion) ? num_entries : 0; } -bool DeleteDirRecursively(const std::string &directory) +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) -> bool { + const std::string& virtual_name, + unsigned int recursion) -> bool { std::string new_path = directory + DIR_SEP_CHR + virtual_name; - if (IsDirectory(new_path)) - return DeleteDirRecursively(new_path); + if (IsDirectory(new_path)) { + if (recursion == 0) + return false; + return DeleteDirRecursively(new_path, recursion - 1); + } return Delete(new_path); }; - if (!ForeachDirectoryEntry(nullptr, directory, callback)) + if (!ForeachDirectoryEntry(nullptr, directory, callback, recursion)) return false; // Delete the outermost directory diff --git a/src/common/file_util.h b/src/common/file_util.h index c6a8694ce..32ae2dc57 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h @@ -105,11 +105,13 @@ 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; + const std::string& virtual_name, + unsigned int recursion)>; /** * Scans a directory, calling the callback for each file/directory contained within. @@ -117,20 +119,22 @@ using DirectoryEntryCallable = std::function Date: Tue, 17 May 2016 23:06:33 +0100 Subject: [PATCH 23/60] Loader, Frontends: Refactor loader creation and game loading This allows frontends to keep a single loader and use it multiple times e.g. for code loading and SMDH parsing. --- src/citra/citra.cpp | 8 +++++- src/citra_qt/main.cpp | 10 +++++++- src/core/loader/3dsx.cpp | 3 +++ src/core/loader/loader.cpp | 50 ++++++-------------------------------- src/core/loader/loader.h | 6 ++--- src/core/loader/ncch.cpp | 9 ++++++- 6 files changed, 37 insertions(+), 49 deletions(-) diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp index b4501eb2e..aa3bf94ca 100644 --- a/src/citra/citra.cpp +++ b/src/citra/citra.cpp @@ -114,7 +114,13 @@ int main(int argc, char **argv) { System::Init(emu_window.get()); SCOPE_EXIT({ System::Shutdown(); }); - Loader::ResultStatus load_result = Loader::LoadFile(boot_filename); + std::unique_ptr loader = Loader::GetFileLoader(boot_filename); + if (!loader) { + LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", boot_filename.c_str()); + return -1; + } + + Loader::ResultStatus load_result = loader->Load(); if (Loader::ResultStatus::Success != load_result) { LOG_CRITICAL(Frontend, "Failed to load ROM (Error %i)!", load_result); return -1; diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index a85c94a4b..9d47014aa 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -272,7 +272,15 @@ bool GMainWindow::InitializeSystem() { } bool GMainWindow::LoadROM(const std::string& filename) { - Loader::ResultStatus result = Loader::LoadFile(filename); + std::unique_ptr app_loader = Loader::GetFileLoader(filename); + if (!app_loader) { + LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filename.c_str()); + QMessageBox::critical(this, tr("Error while loading ROM!"), + tr("The ROM format is not supported.")); + return false; + } + + Loader::ResultStatus result = app_loader->Load(); if (Loader::ResultStatus::Success != result) { LOG_CRITICAL(Frontend, "Failed to load ROM!"); System::Shutdown(); diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp index 98e7ab48f..a16411e14 100644 --- a/src/core/loader/3dsx.cpp +++ b/src/core/loader/3dsx.cpp @@ -10,6 +10,7 @@ #include "core/file_sys/archive_romfs.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/resource_limit.h" +#include "core/hle/service/fs/archive.h" #include "core/loader/3dsx.h" #include "core/memory.h" @@ -263,6 +264,8 @@ ResultStatus AppLoader_THREEDSX::Load() { Kernel::g_current_process->Run(48, Kernel::DEFAULT_STACK_SIZE); + Service::FS::RegisterArchiveType(std::make_unique(*this), Service::FS::ArchiveIdCode::RomFS); + is_loaded = true; return ResultStatus::Success; } diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index af3f62248..c82688026 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -8,9 +8,7 @@ #include "common/logging/log.h" #include "common/string_util.h" -#include "core/file_sys/archive_romfs.h" #include "core/hle/kernel/process.h" -#include "core/hle/service/fs/archive.h" #include "core/loader/3dsx.h" #include "core/loader/elf.h" #include "core/loader/ncch.h" @@ -67,6 +65,9 @@ FileType GuessFromExtension(const std::string& extension_) { if (extension == ".3dsx") return FileType::THREEDSX; + if (extension == ".cia") + return FileType::CIA; + return FileType::Unknown; } @@ -108,15 +109,15 @@ std::unique_ptr GetLoader(FileUtil::IOFile&& file, FileType type, return std::make_unique(std::move(file), filepath); default: - return std::unique_ptr(); + return nullptr; } } -ResultStatus LoadFile(const std::string& filename) { +std::unique_ptr GetFileLoader(const std::string& filename) { FileUtil::IOFile file(filename, "rb"); if (!file.IsOpen()) { LOG_ERROR(Loader, "Failed to load file %s", filename.c_str()); - return ResultStatus::Error; + return nullptr; } std::string filename_filename, filename_extension; @@ -133,44 +134,7 @@ ResultStatus LoadFile(const std::string& filename) { LOG_INFO(Loader, "Loading file %s as %s...", filename.c_str(), GetFileTypeString(type)); - std::unique_ptr app_loader = GetLoader(std::move(file), type, filename_filename, filename); - - switch (type) { - - // 3DSX file format... - // or NCCH/NCSD container formats... - case FileType::THREEDSX: - case FileType::CXI: - case FileType::CCI: - { - // Load application and RomFS - ResultStatus result = app_loader->Load(); - if (ResultStatus::Success == result) { - Service::FS::RegisterArchiveType(std::make_unique(*app_loader), Service::FS::ArchiveIdCode::RomFS); - return ResultStatus::Success; - } - return result; - } - - // Standard ELF file format... - case FileType::ELF: - return app_loader->Load(); - - // CIA file format... - case FileType::CIA: - return ResultStatus::ErrorNotImplemented; - - // Error occurred durring IdentifyFile... - case FileType::Error: - - // IdentifyFile could know identify file type... - case FileType::Unknown: - { - LOG_CRITICAL(Loader, "File %s is of unknown type.", filename.c_str()); - return ResultStatus::ErrorInvalidFormat; - } - } - return ResultStatus::Error; + return GetLoader(std::move(file), type, filename_filename, filename); } } // namespace Loader diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 9d3e9ed3b..4a4bd7c77 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -207,10 +207,10 @@ extern const std::initializer_list default_address_mappi std::unique_ptr GetLoader(FileUtil::IOFile&& file, FileType type, const std::string& filename, const std::string& filepath); /** - * Identifies and loads a bootable file + * Identifies a bootable file and return a suitable loader * @param filename String filename of bootable file - * @return ResultStatus result of function + * @return best loader for this file */ -ResultStatus LoadFile(const std::string& filename); +std::unique_ptr GetFileLoader(const std::string& filename); } // namespace diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 7391bdb26..fca091ff9 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -10,8 +10,10 @@ #include "common/string_util.h" #include "common/swap.h" +#include "core/file_sys/archive_romfs.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/resource_limit.h" +#include "core/hle/service/fs/archive.h" #include "core/loader/ncch.h" #include "core/memory.h" @@ -303,7 +305,12 @@ ResultStatus AppLoader_NCCH::Load() { is_loaded = true; // Set state to loaded - return LoadExec(); // Load the executable into memory for booting + result = LoadExec(); // Load the executable into memory for booting + if (ResultStatus::Success != result) + return result; + + Service::FS::RegisterArchiveType(std::make_unique(*this), Service::FS::ArchiveIdCode::RomFS); + return ResultStatus::Success; } ResultStatus AppLoader_NCCH::ReadCode(std::vector& buffer) { From 9a35d1fb4ac1c1e37d02bb3826c2c0bfd2a1554f Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 17 May 2016 23:30:44 +0100 Subject: [PATCH 24/60] Loader: Add a GetFileType method to get the type of a loaded file --- src/core/loader/3dsx.h | 8 ++++++++ src/core/loader/elf.h | 8 ++++++++ src/core/loader/loader.h | 6 ++++++ src/core/loader/ncch.h | 8 ++++++++ 4 files changed, 30 insertions(+) diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h index 3ee686703..90b20c61c 100644 --- a/src/core/loader/3dsx.h +++ b/src/core/loader/3dsx.h @@ -27,6 +27,14 @@ public: */ static FileType IdentifyType(FileUtil::IOFile& file); + /** + * Returns the type of this file + * @return FileType corresponding to the loaded file + */ + FileType GetFileType() override { + return IdentifyType(file); + } + /** * Load the bootable file * @return ResultStatus result of function diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h index c6a5ebe99..cb3724f9d 100644 --- a/src/core/loader/elf.h +++ b/src/core/loader/elf.h @@ -27,6 +27,14 @@ public: */ static FileType IdentifyType(FileUtil::IOFile& file); + /** + * Returns the type of this file + * @return FileType corresponding to the loaded file + */ + FileType GetFileType() override { + return IdentifyType(file); + } + /** * Load the bootable file * @return ResultStatus result of function diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 4a4bd7c77..08bab84e5 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -131,6 +131,12 @@ public: AppLoader(FileUtil::IOFile&& file) : file(std::move(file)) { } virtual ~AppLoader() { } + /** + * Returns the type of this file + * @return FileType corresponding to the loaded file + */ + virtual FileType GetFileType() = 0; + /** * Load the application * @return ResultStatus result of function diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h index fd852c3de..75609ee57 100644 --- a/src/core/loader/ncch.h +++ b/src/core/loader/ncch.h @@ -173,6 +173,14 @@ public: */ static FileType IdentifyType(FileUtil::IOFile& file); + /** + * Returns the type of this file + * @return FileType corresponding to the loaded file + */ + FileType GetFileType() override { + return IdentifyType(file); + } + /** * Load the application * @return ResultStatus result of function From 314ce5e505aca066ad4d0385be46d7e8de9f6dfb Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 18 May 2016 22:06:50 +0100 Subject: [PATCH 25/60] CitraQt: Simplify the game list loader code --- src/citra/citra.cpp | 2 +- src/citra_qt/game_list.cpp | 22 ++++------------------ src/citra_qt/main.cpp | 2 +- src/core/loader/loader.cpp | 14 +++++++++++--- src/core/loader/loader.h | 12 +----------- 5 files changed, 18 insertions(+), 34 deletions(-) diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp index aa3bf94ca..e01216734 100644 --- a/src/citra/citra.cpp +++ b/src/citra/citra.cpp @@ -114,7 +114,7 @@ int main(int argc, char **argv) { System::Init(emu_window.get()); SCOPE_EXIT({ System::Shutdown(); }); - std::unique_ptr loader = Loader::GetFileLoader(boot_filename); + std::unique_ptr loader = Loader::GetLoader(boot_filename); if (!loader) { LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", boot_filename.c_str()); return -1; diff --git a/src/citra_qt/game_list.cpp b/src/citra_qt/game_list.cpp index d4ac9c96e..570647539 100644 --- a/src/citra_qt/game_list.cpp +++ b/src/citra_qt/game_list.cpp @@ -132,30 +132,16 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, bool d if (deep_scan && FileUtil::IsDirectory(physical_name)) { AddFstEntriesToGameList(physical_name, true); } else { - std::string filename_filename, filename_extension; - Common::SplitPath(physical_name, nullptr, &filename_filename, &filename_extension); - - Loader::FileType guessed_filetype = Loader::GuessFromExtension(filename_extension); - if (guessed_filetype == Loader::FileType::Unknown) + std::unique_ptr loader = Loader::GetLoader(physical_name); + if (!loader) return true; - Loader::FileType filetype = Loader::IdentifyFile(physical_name); - if (filetype == Loader::FileType::Unknown) { - LOG_WARNING(Frontend, "File %s is of indeterminate type and is possibly corrupted.", physical_name.c_str()); - return true; - } - if (guessed_filetype != filetype) { - LOG_WARNING(Frontend, "Filetype and extension of file %s do not match.", physical_name.c_str()); - } std::vector smdh; - std::unique_ptr loader = Loader::GetLoader(FileUtil::IOFile(physical_name, "rb"), filetype, filename_filename, physical_name); - - if (loader) - loader->ReadIcon(smdh); + loader->ReadIcon(smdh); emit EntryReady({ new GameListItemPath(QString::fromStdString(physical_name), smdh), - new GameListItem(QString::fromStdString(Loader::GetFileTypeString(filetype))), + new GameListItem(QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), new GameListItemSize(FileUtil::GetSize(physical_name)), }); } diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 9d47014aa..6239160bc 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -272,7 +272,7 @@ bool GMainWindow::InitializeSystem() { } bool GMainWindow::LoadROM(const std::string& filename) { - std::unique_ptr app_loader = Loader::GetFileLoader(filename); + std::unique_ptr app_loader = Loader::GetLoader(filename); if (!app_loader) { LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filename.c_str()); QMessageBox::critical(this, tr("Error while loading ROM!"), diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index c82688026..9719d30d5 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -91,7 +91,15 @@ const char* GetFileTypeString(FileType type) { return "unknown"; } -std::unique_ptr GetLoader(FileUtil::IOFile&& file, FileType type, +/** + * Get a loader for a file with a specific type + * @param file The file to load + * @param type The type of the file + * @param filename the file name (without path) + * @param filepath the file full path (with name) + * @return std::unique_ptr a pointer to a loader object; nullptr for unsupported type + */ +static std::unique_ptr GetFileLoader(FileUtil::IOFile&& file, FileType type, const std::string& filename, const std::string& filepath) { switch (type) { @@ -113,7 +121,7 @@ std::unique_ptr GetLoader(FileUtil::IOFile&& file, FileType type, } } -std::unique_ptr GetFileLoader(const std::string& filename) { +std::unique_ptr GetLoader(const std::string& filename) { FileUtil::IOFile file(filename, "rb"); if (!file.IsOpen()) { LOG_ERROR(Loader, "Failed to load file %s", filename.c_str()); @@ -134,7 +142,7 @@ std::unique_ptr GetFileLoader(const std::string& filename) { LOG_INFO(Loader, "Loading file %s as %s...", filename.c_str(), GetFileTypeString(type)); - return GetLoader(std::move(file), type, filename_filename, filename); + return GetFileLoader(std::move(file), type, filename_filename, filename); } } // namespace Loader diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 08bab84e5..39aedfeeb 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -202,21 +202,11 @@ protected: */ extern const std::initializer_list default_address_mappings; -/** - * Get a loader for a file with a specific type - * @param file The file to load - * @param type The type of the file - * @param filename the file name (without path) - * @param filepath the file full path (with name) - * @return std::unique_ptr a pointer to a loader object; nullptr for unsupported type - */ -std::unique_ptr GetLoader(FileUtil::IOFile&& file, FileType type, const std::string& filename, const std::string& filepath); - /** * Identifies a bootable file and return a suitable loader * @param filename String filename of bootable file * @return best loader for this file */ -std::unique_ptr GetFileLoader(const std::string& filename); +std::unique_ptr GetLoader(const std::string& filename); } // namespace From c084fc824cf4e076bb83e41af64f5cfaa9204dcb Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 08:46:11 +0100 Subject: [PATCH 26/60] Memory: IsValidVirtualAddress/IsValidPhysicalAddress --- src/core/memory.cpp | 21 +++++++++++++++++++++ src/core/memory.h | 3 +++ src/core/mmio.h | 2 ++ 3 files changed, 26 insertions(+) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index ee9b69f81..68a29b154 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -246,6 +246,26 @@ void Write(const VAddr vaddr, const T data) { } } +bool IsValidVirtualAddress(const VAddr vaddr) { + const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; + if (page_pointer) + return true; + + if (current_page_table->attributes[vaddr >> PAGE_BITS] != PageType::Special) + return false; + + MMIORegionPointer mmio_region = GetMMIOHandler(vaddr); + if (mmio_region) { + return mmio_region->IsValidAddress(vaddr); + } + + return false; +} + +bool IsValidPhysicalAddress(const PAddr paddr) { + return IsValidVirtualAddress(PhysicalToVirtualAddress(paddr)); +} + u8* GetPointer(const VAddr vaddr) { u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; if (page_pointer) { @@ -261,6 +281,7 @@ u8* GetPointer(const VAddr vaddr) { } u8* GetPhysicalPointer(PAddr address) { + // TODO(Subv): This call should not go through the application's memory mapping. return GetPointer(PhysicalToVirtualAddress(address)); } diff --git a/src/core/memory.h b/src/core/memory.h index 126d60471..9ada78fc8 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -110,6 +110,9 @@ enum : VAddr { NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, }; +bool IsValidVirtualAddress(const VAddr addr); +bool IsValidPhysicalAddress(const PAddr addr); + u8 Read8(VAddr addr); u16 Read16(VAddr addr); u32 Read32(VAddr addr); diff --git a/src/core/mmio.h b/src/core/mmio.h index 06b555e98..cb644f51b 100644 --- a/src/core/mmio.h +++ b/src/core/mmio.h @@ -18,6 +18,8 @@ class MMIORegion { public: virtual ~MMIORegion() = default; + virtual bool IsValidAddress(VAddr addr) = 0; + virtual u8 Read8(VAddr addr) = 0; virtual u16 Read16(VAddr addr) = 0; virtual u32 Read32(VAddr addr) = 0; From 3873b36db333547152280b741e85aa54c69d8199 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 09:14:18 +0100 Subject: [PATCH 27/60] Memory: ReadBlock/WriteBlock --- src/core/memory.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++-- src/core/memory.h | 4 ++- src/core/mmio.h | 4 +++ 3 files changed, 81 insertions(+), 4 deletions(-) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 68a29b154..c7b99a467 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -364,6 +364,45 @@ u64 Read64(const VAddr addr) { return Read(addr); } +void ReadBlock(const VAddr src_addr, u8* dest_buffer, const size_t size) { + size_t remaining_size = size; + size_t page_index = src_addr >> PAGE_BITS; + size_t page_offset = src_addr & PAGE_MASK; + + while (remaining_size > 0) { + const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); + const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; + + switch (current_page_table->attributes[page_index]) { + case PageType::Unmapped: { + LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); + std::memset(dest_buffer, 0, copy_amount); + break; + } + case PageType::Memory: { + DEBUG_ASSERT(current_page_table->pointers[page_index]); + + const u8* src_ptr = current_page_table->pointers[page_index] + page_offset; + std::memcpy(dest_buffer, src_ptr, copy_amount); + break; + } + case PageType::Special: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); + break; + } + default: + UNREACHABLE(); + } + + page_index++; + page_offset = 0; + dest_buffer += copy_amount; + remaining_size -= copy_amount; + } +} + void Write8(const VAddr addr, const u8 data) { Write(addr, data); } @@ -380,9 +419,41 @@ void Write64(const VAddr addr, const u64 data) { Write(addr, data); } -void WriteBlock(const VAddr addr, const u8* data, const size_t size) { - for (u32 offset = 0; offset < size; offset++) { - Write8(addr + offset, data[offset]); +void WriteBlock(const VAddr dest_addr, const u8* src_buffer, const size_t size) { + size_t remaining_size = size; + size_t page_index = dest_addr >> PAGE_BITS; + size_t page_offset = dest_addr & PAGE_MASK; + + while (remaining_size > 0) { + const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); + const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; + + switch (current_page_table->attributes[page_index]) { + case PageType::Unmapped: { + LOG_ERROR(HW_Memory, "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); + break; + } + case PageType::Memory: { + DEBUG_ASSERT(current_page_table->pointers[page_index]); + + u8* dest_ptr = current_page_table->pointers[page_index] + page_offset; + std::memcpy(dest_ptr, src_buffer, copy_amount); + break; + } + case PageType::Special: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); + break; + } + default: + UNREACHABLE(); + } + + page_index++; + page_offset = 0; + src_buffer += copy_amount; + remaining_size -= copy_amount; } } diff --git a/src/core/memory.h b/src/core/memory.h index 9ada78fc8..35bd5eb0c 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -118,12 +118,14 @@ u16 Read16(VAddr addr); u32 Read32(VAddr addr); u64 Read64(VAddr addr); +void ReadBlock(const VAddr src_addr, u8* dest_buffer, size_t size); + void Write8(VAddr addr, u8 data); void Write16(VAddr addr, u16 data); void Write32(VAddr addr, u32 data); void Write64(VAddr addr, u64 data); -void WriteBlock(VAddr addr, const u8* data, size_t size); +void WriteBlock(const VAddr dest_addr, const u8* src_buffer, size_t size); u8* GetPointer(VAddr virtual_address); diff --git a/src/core/mmio.h b/src/core/mmio.h index cb644f51b..35b73b061 100644 --- a/src/core/mmio.h +++ b/src/core/mmio.h @@ -25,10 +25,14 @@ public: virtual u32 Read32(VAddr addr) = 0; virtual u64 Read64(VAddr addr) = 0; + virtual bool ReadBlock(VAddr src_addr, u8* dest_buffer, size_t size) = 0; + virtual void Write8(VAddr addr, u8 data) = 0; virtual void Write16(VAddr addr, u16 data) = 0; virtual void Write32(VAddr addr, u32 data) = 0; virtual void Write64(VAddr addr, u64 data) = 0; + + virtual bool WriteBlock(VAddr dest_addr, const u8* src_buffer, size_t size) = 0; }; using MMIORegionPointer = std::shared_ptr; From b3b3dd7591416319ee0d6c4d32065bb5a7b1209f Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 09:48:46 +0100 Subject: [PATCH 28/60] Debugger/Callstack: Replace Memory::GetPointer with Memory::IsValidVirtualAddress --- src/citra_qt/debugger/callstack.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp index 793944639..1a3077495 100644 --- a/src/citra_qt/debugger/callstack.cpp +++ b/src/citra_qt/debugger/callstack.cpp @@ -37,10 +37,13 @@ void CallstackWidget::OnDebugModeEntered() int counter = 0; for (u32 addr = 0x10000000; addr >= sp; addr -= 4) { + if (!Memory::IsValidVirtualAddress(addr)) + break; + const u32 ret_addr = Memory::Read32(addr); const u32 call_addr = ret_addr - 4; //get call address??? - if (Memory::GetPointer(call_addr) == nullptr) + if (!Memory::IsValidVirtualAddress(call_addr)) break; /* TODO (mattvail) clean me, move to debugger interface */ From 2be17a0c6e0a386b78e09dc6341182d3fe605d41 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 10:01:43 +0100 Subject: [PATCH 29/60] FileSys/Path: Replace Memory::GetPointer with Memory::ReadBlock --- src/core/file_sys/archive_backend.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/file_sys/archive_backend.cpp b/src/core/file_sys/archive_backend.cpp index 97adf0e12..cc0aa7022 100644 --- a/src/core/file_sys/archive_backend.cpp +++ b/src/core/file_sys/archive_backend.cpp @@ -19,22 +19,22 @@ Path::Path(LowPathType type, u32 size, u32 pointer) : type(type) { switch (type) { case Binary: { - u8* data = Memory::GetPointer(pointer); - binary = std::vector(data, data + size); + binary.resize(size); + Memory::ReadBlock(pointer, binary.data(), binary.size()); break; } case Char: { - const char* data = reinterpret_cast(Memory::GetPointer(pointer)); - string = std::string(data, size - 1); // Data is always null-terminated. + string.resize(size - 1); // Data is always null-terminated. + Memory::ReadBlock(pointer, &string[0], string.size()); break; } case Wchar: { - const char16_t* data = reinterpret_cast(Memory::GetPointer(pointer)); - u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated. + u16str.resize(size / 2 - 1); // Data is always null-terminated. + Memory::ReadBlock(pointer, &u16str[0], u16str.size() * sizeof(char16_t)); break; } From ca17df5757f08c7bb673aec19e0fdd4698dd904f Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 10:21:41 +0100 Subject: [PATCH 30/60] Memory: ZeroBlock --- src/core/memory.cpp | 38 ++++++++++++++++++++++++++++++++++++++ src/core/memory.h | 1 + 2 files changed, 39 insertions(+) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index c7b99a467..1604a7da5 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -457,6 +457,44 @@ void WriteBlock(const VAddr dest_addr, const u8* src_buffer, const size_t size) } } +void ZeroBlock(const VAddr dest_addr, const size_t size) { + size_t remaining_size = size; + size_t page_index = dest_addr >> PAGE_BITS; + size_t page_offset = dest_addr & PAGE_MASK; + + while (remaining_size > 0) { + const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); + const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; + + switch (current_page_table->attributes[page_index]) { + case PageType::Unmapped: { + LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); + break; + } + case PageType::Memory: { + DEBUG_ASSERT(current_page_table->pointers[page_index]); + + u8* dest_ptr = current_page_table->pointers[page_index] + page_offset; + std::memset(dest_ptr, 0, copy_amount); + break; + } + case PageType::Special: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + static const std::array zeros = {}; + GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); + break; + } + default: + UNREACHABLE(); + } + + page_index++; + page_offset = 0; + remaining_size -= copy_amount; + } +} + template<> u8 ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr) { return mmio_handler->Read8(addr); diff --git a/src/core/memory.h b/src/core/memory.h index 35bd5eb0c..713cdfb2f 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -126,6 +126,7 @@ void Write32(VAddr addr, u32 data); void Write64(VAddr addr, u64 data); void WriteBlock(const VAddr dest_addr, const u8* src_buffer, size_t size); +void ZeroBlock(const VAddr dest_addr, const size_t size); u8* GetPointer(VAddr virtual_address); From aa84cab4e9c27c947192d055dd06941415d6e590 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 10:11:10 +0100 Subject: [PATCH 31/60] Applets/swkdb: Remove use of Memory::GetPointer --- src/core/hle/applets/swkbd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp index 90c6adc65..3ad950692 100644 --- a/src/core/hle/applets/swkbd.cpp +++ b/src/core/hle/applets/swkbd.cpp @@ -99,7 +99,7 @@ void SoftwareKeyboard::DrawScreenKeyboard() { auto info = bottom_screen->framebuffer_info[bottom_screen->index]; // TODO(Subv): Draw the HLE keyboard, for now just zero-fill the framebuffer - memset(Memory::GetPointer(info.address_left), 0, info.stride * 320); + Memory::ZeroBlock(info.address_left, info.stride * 320); GSP_GPU::SetBufferSwap(1, info); } From 1ebaaf9bb1f5f663f53edaeac026fb465a8c576e Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 10:27:32 +0100 Subject: [PATCH 32/60] Kernel/Thread: Remove use of Memory::GetPointer --- src/core/hle/kernel/thread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 43def6146..3f6bec5fa 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -403,7 +403,7 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, priority = new_priority; } - if (!Memory::GetPointer(entry_point)) { + if (!Memory::IsValidVirtualAddress(entry_point)) { LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); // TODO: Verify error return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, From fddd243b17edb0fe03ef1a85c2abdf95353a534d Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 11:18:49 +0100 Subject: [PATCH 33/60] APT: Remove use of Memory::GetPointer --- src/core/hle/applets/mii_selector.cpp | 21 +++++++++++---------- src/core/hle/applets/mii_selector.h | 4 +++- src/core/hle/applets/swkbd.cpp | 15 +++++++-------- src/core/hle/service/apt/apt.cpp | 25 +++++++++++++------------ src/core/hle/service/apt/apt.h | 6 ++---- 5 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp index bf39eca22..77f01d208 100644 --- a/src/core/hle/applets/mii_selector.cpp +++ b/src/core/hle/applets/mii_selector.cpp @@ -32,9 +32,9 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p // 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); + ASSERT(sizeof(capture_info) == parameter.buffer.size()); - memcpy(&capture_info, parameter.data, sizeof(capture_info)); + memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info)); using Kernel::MemoryPermission; // Allocate a heap block of the required size for this applet. @@ -47,8 +47,7 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p // Send the response message with the newly created SharedMemory Service::APT::MessageParameter result; result.signal = static_cast(Service::APT::SignalType::LibAppFinished); - result.data = nullptr; - result.buffer_size = 0; + result.buffer.clear(); result.destination_id = static_cast(Service::APT::AppletId::Application); result.sender_id = static_cast(id); result.object = framebuffer_memory; @@ -63,15 +62,17 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. // TODO(Subv): Reverse the parameter format for the Mii Selector - if(parameter.buffer_size >= sizeof(u32)) { - // TODO: defaults return no error, but garbage in other unknown fields - memset(parameter.data, 0, sizeof(u32)); - } + memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); + + // TODO(Subv): Find more about this structure, result code 0 is enough to let most games continue. + MiiResult result; + memset(&result, 0, sizeof(result)); + result.result_code = 0; // Let the application know that we're closing Service::APT::MessageParameter message; - message.buffer_size = parameter.buffer_size; - message.data = parameter.data; + message.buffer.resize(sizeof(MiiResult)); + std::memcpy(message.buffer.data(), &result, message.buffer.size()); message.signal = static_cast(Service::APT::SignalType::LibAppClosed); message.destination_id = static_cast(Service::APT::AppletId::Application); message.sender_id = static_cast(id); diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h index be6b04642..24e8e721d 100644 --- a/src/core/hle/applets/mii_selector.h +++ b/src/core/hle/applets/mii_selector.h @@ -24,7 +24,7 @@ struct MiiConfig { u8 unk_004; INSERT_PADDING_BYTES(3); u16 unk_008; - INSERT_PADDING_BYTES(0x8C - 0xA); + INSERT_PADDING_BYTES(0x82); u8 unk_08C; INSERT_PADDING_BYTES(3); u16 unk_090; @@ -75,6 +75,8 @@ public: /// Whether this applet is currently running instead of the host application or not. bool started; + + MiiConfig config; }; } diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp index 3ad950692..d87bf3d57 100644 --- a/src/core/hle/applets/swkbd.cpp +++ b/src/core/hle/applets/swkbd.cpp @@ -35,9 +35,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con // 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); + ASSERT(sizeof(capture_info) == parameter.buffer.size()); - memcpy(&capture_info, parameter.data, sizeof(capture_info)); + memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info)); using Kernel::MemoryPermission; // Allocate a heap block of the required size for this applet. @@ -50,8 +50,7 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con // Send the response message with the newly created SharedMemory Service::APT::MessageParameter result; result.signal = static_cast(Service::APT::SignalType::LibAppFinished); - result.data = nullptr; - result.buffer_size = 0; + result.buffer.clear(); result.destination_id = static_cast(Service::APT::AppletId::Application); result.sender_id = static_cast(id); result.object = framebuffer_memory; @@ -61,9 +60,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con } ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) { - ASSERT_MSG(parameter.buffer_size == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong"); + ASSERT_MSG(parameter.buffer.size() == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong"); - memcpy(&config, parameter.data, parameter.buffer_size); + memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); text_memory = boost::static_pointer_cast(parameter.object); // TODO(Subv): Verify if this is the correct behavior @@ -107,8 +106,8 @@ void SoftwareKeyboard::DrawScreenKeyboard() { void SoftwareKeyboard::Finalize() { // Let the application know that we're closing Service::APT::MessageParameter message; - message.buffer_size = sizeof(SoftwareKeyboardConfig); - message.data = reinterpret_cast(&config); + message.buffer.resize(sizeof(SoftwareKeyboardConfig)); + std::memcpy(message.buffer.data(), &config, message.buffer.size()); message.signal = static_cast(Service::APT::SignalType::LibAppClosed); message.destination_id = static_cast(Service::APT::AppletId::Application); message.sender_id = static_cast(id); diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 73fce6079..e2304fa54 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -176,12 +176,12 @@ void SendParameter(Service::Interface* self) { } MessageParameter param; - param.buffer_size = buffer_size; param.destination_id = dst_app_id; param.sender_id = src_app_id; param.object = Kernel::g_handle_table.GetGeneric(handle); param.signal = signal_type; - param.data = Memory::GetPointer(buffer); + param.buffer.resize(buffer_size); + Memory::ReadBlock(buffer, param.buffer.data(), param.buffer.size()); cmd_buff[1] = dest_applet->ReceiveParameter(param).raw; @@ -199,16 +199,15 @@ void ReceiveParameter(Service::Interface* self) { cmd_buff[1] = RESULT_SUCCESS.raw; // No error cmd_buff[2] = next_parameter.sender_id; cmd_buff[3] = next_parameter.signal; // Signal type - cmd_buff[4] = next_parameter.buffer_size; // Parameter buffer size + cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size cmd_buff[5] = 0x10; cmd_buff[6] = 0; if (next_parameter.object != nullptr) cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); - cmd_buff[7] = (next_parameter.buffer_size << 14) | 2; + cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; cmd_buff[8] = buffer; - if (next_parameter.data) - memcpy(Memory::GetPointer(buffer), next_parameter.data, std::min(buffer_size, next_parameter.buffer_size)); + Memory::WriteBlock(buffer, next_parameter.buffer.data(), next_parameter.buffer.size()); LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); } @@ -222,16 +221,15 @@ void GlanceParameter(Service::Interface* self) { cmd_buff[1] = RESULT_SUCCESS.raw; // No error cmd_buff[2] = next_parameter.sender_id; cmd_buff[3] = next_parameter.signal; // Signal type - cmd_buff[4] = next_parameter.buffer_size; // Parameter buffer size + cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size cmd_buff[5] = 0x10; cmd_buff[6] = 0; if (next_parameter.object != nullptr) cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); - cmd_buff[7] = (next_parameter.buffer_size << 14) | 2; + cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; cmd_buff[8] = buffer; - if (next_parameter.data) - memcpy(Memory::GetPointer(buffer), next_parameter.data, std::min(buffer_size, next_parameter.buffer_size)); + Memory::WriteBlock(buffer, next_parameter.buffer.data(), std::min(static_cast(buffer_size), next_parameter.buffer.size())); LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); } @@ -365,10 +363,13 @@ void StartLibraryApplet(Service::Interface* self) { return; } + size_t buffer_size = cmd_buff[2]; + VAddr buffer_addr = cmd_buff[6]; + AppletStartupParameter parameter; - parameter.buffer_size = cmd_buff[2]; parameter.object = Kernel::g_handle_table.GetGeneric(cmd_buff[4]); - parameter.data = Memory::GetPointer(cmd_buff[6]); + parameter.buffer.resize(buffer_size); + Memory::ReadBlock(buffer_addr, parameter.buffer.data(), parameter.buffer.size()); cmd_buff[1] = applet->Start(parameter).raw; } diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 1a1034fcc..66cda1d4c 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -20,16 +20,14 @@ struct MessageParameter { u32 sender_id = 0; u32 destination_id = 0; u32 signal = 0; - u32 buffer_size = 0; Kernel::SharedPtr object = nullptr; - u8* data = nullptr; + std::vector buffer; }; /// Holds information about the parameters used in StartLibraryApplet struct AppletStartupParameter { - u32 buffer_size = 0; Kernel::SharedPtr object = nullptr; - u8* data = nullptr; + std::vector buffer; }; /// Used by the application to pass information about the current framebuffer to applets. From 64068583fbefb7268a1138828611d735eae1e212 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 11:51:48 +0100 Subject: [PATCH 34/60] CFG: Remove use of Memory::GetPointer --- src/core/hle/service/cfg/cfg.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index b9322c55d..3921653e5 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -191,28 +191,32 @@ void GetConfigInfoBlk2(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 size = cmd_buff[1]; u32 block_id = cmd_buff[2]; - u8* data_pointer = Memory::GetPointer(cmd_buff[4]); + VAddr data_pointer = cmd_buff[4]; - if (data_pointer == nullptr) { + if (!Memory::IsValidVirtualAddress(data_pointer)) { cmd_buff[1] = -1; // TODO(Subv): Find the right error code return; } - cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data_pointer).raw; + std::vector data(size); + cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data.data()).raw; + Memory::WriteBlock(data_pointer, data.data(), data.size()); } void GetConfigInfoBlk8(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 size = cmd_buff[1]; u32 block_id = cmd_buff[2]; - u8* data_pointer = Memory::GetPointer(cmd_buff[4]); + VAddr data_pointer = cmd_buff[4]; - if (data_pointer == nullptr) { + if (!Memory::IsValidVirtualAddress(data_pointer)) { cmd_buff[1] = -1; // TODO(Subv): Find the right error code return; } - cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data_pointer).raw; + std::vector data(size); + cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data.data()).raw; + Memory::WriteBlock(data_pointer, data.data(), data.size()); } void UpdateConfigNANDSavegame(Service::Interface* self) { From 080a2d719ca825961ec2db5f26ad22e43d456c5a Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Wed, 18 May 2016 00:42:45 +0100 Subject: [PATCH 35/60] Loader: Split SMDH into its own header and import helpers from QGameList Also rewrite Qt wrappers to use those. --- src/citra_qt/game_list_p.h | 53 +++++------------------- src/core/CMakeLists.txt | 2 + src/core/loader/loader.h | 47 ---------------------- src/core/loader/smdh.cpp | 54 +++++++++++++++++++++++++ src/core/loader/smdh.h | 82 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 149 insertions(+), 89 deletions(-) create mode 100644 src/core/loader/smdh.cpp create mode 100644 src/core/loader/smdh.h diff --git a/src/citra_qt/game_list_p.h b/src/citra_qt/game_list_p.h index 284f5da81..121f90b0c 100644 --- a/src/citra_qt/game_list_p.h +++ b/src/citra_qt/game_list_p.h @@ -15,52 +15,21 @@ #include "common/string_util.h" #include "common/color.h" -#include "core/loader/loader.h" +#include "core/loader/smdh.h" #include "video_core/utils.h" -/** - * Tests if data is a valid SMDH by its length and magic number. - * @param smdh_data data buffer to test - * @return bool test result - */ -static bool IsValidSMDH(const std::vector& smdh_data) { - if (smdh_data.size() < sizeof(Loader::SMDH)) - return false; - - u32 magic; - memcpy(&magic, smdh_data.data(), 4); - - return Loader::MakeMagic('S', 'M', 'D', 'H') == magic; -} - /** * Gets game icon from SMDH * @param sdmh SMDH data * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24) * @return QPixmap game icon */ -static QPixmap GetIconFromSMDH(const Loader::SMDH& smdh, bool large) { - u32 size; - const u8* icon_data; - - if (large) { - size = 48; - icon_data = smdh.large_icon.data(); - } else { - size = 24; - icon_data = smdh.small_icon.data(); - } - - QImage icon(size, size, QImage::Format::Format_RGB888); - for (u32 x = 0; x < size; ++x) { - for (u32 y = 0; y < size; ++y) { - u32 coarse_y = y & ~7; - auto v = Color::DecodeRGB565( - icon_data + VideoCore::GetMortonOffset(x, y, 2) + coarse_y * size * 2); - icon.setPixel(x, y, qRgb(v.r(), v.g(), v.b())); - } - } +static QPixmap GetQPixmapFromSMDH(const Loader::SMDH& smdh, bool large) { + std::vector icon_data = smdh.GetIcon(large); + const uchar* data = reinterpret_cast(icon_data.data()); + int size = large ? 48 : 24; + QImage icon(data, size, size, QImage::Format::Format_RGB16); return QPixmap::fromImage(icon); } @@ -82,8 +51,8 @@ static QPixmap GetDefaultIcon(bool large) { * @param language title language * @return QString short title */ -static QString GetShortTitleFromSMDH(const Loader::SMDH& smdh, Loader::SMDH::TitleLanguage language) { - return QString::fromUtf16(smdh.titles[static_cast(language)].short_title.data()); +static QString GetQStringShortTitleFromSMDH(const Loader::SMDH& smdh, Loader::SMDH::TitleLanguage language) { + return QString::fromUtf16(smdh.GetShortTitle(language).data()); } class GameListItem : public QStandardItem { @@ -112,7 +81,7 @@ public: { setData(game_path, FullPathRole); - if (!IsValidSMDH(smdh_data)) { + if (!Loader::IsValidSMDH(smdh_data)) { // SMDH is not valid, set a default icon setData(GetDefaultIcon(true), Qt::DecorationRole); return; @@ -122,10 +91,10 @@ public: memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH)); // Get icon from SMDH - setData(GetIconFromSMDH(smdh, true), Qt::DecorationRole); + setData(GetQPixmapFromSMDH(smdh, true), Qt::DecorationRole); // Get title form SMDH - setData(GetShortTitleFromSMDH(smdh, Loader::SMDH::TitleLanguage::English), TitleRole); + setData(GetQStringShortTitleFromSMDH(smdh, Loader::SMDH::TitleLanguage::English), TitleRole); } QVariant data(int role) const override { diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 12080a802..ed80cf0e4 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -121,6 +121,7 @@ set(SRCS loader/elf.cpp loader/loader.cpp loader/ncch.cpp + loader/smdh.cpp tracer/recorder.cpp memory.cpp settings.cpp @@ -256,6 +257,7 @@ set(HEADERS loader/elf.h loader/loader.h loader/ncch.h + loader/smdh.h tracer/recorder.h tracer/citrace.h memory.h diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 39aedfeeb..77d87afe1 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -10,10 +10,8 @@ #include #include -#include "common/common_funcs.h" #include "common/common_types.h" #include "common/file_util.h" -#include "common/swap.h" namespace Kernel { struct AddressMapping; @@ -80,51 +78,6 @@ constexpr u32 MakeMagic(char a, char b, char c, char d) { return a | b << 8 | c << 16 | d << 24; } -/// SMDH data structure that contains titles, icons etc. See https://www.3dbrew.org/wiki/SMDH -struct SMDH { - u32_le magic; - u16_le version; - INSERT_PADDING_BYTES(2); - - struct Title { - std::array short_title; - std::array long_title; - std::array publisher; - }; - std::array titles; - - std::array ratings; - u32_le region_lockout; - u32_le match_maker_id; - u64_le match_maker_bit_id; - u32_le flags; - u16_le eula_version; - INSERT_PADDING_BYTES(2); - float_le banner_animation_frame; - u32_le cec_id; - INSERT_PADDING_BYTES(8); - - std::array small_icon; - std::array large_icon; - - /// indicates the language used for each title entry - enum class TitleLanguage { - Japanese = 0, - English = 1, - French = 2, - German = 3, - Italian = 4, - Spanish = 5, - SimplifiedChinese = 6, - Korean= 7, - Dutch = 8, - Portuguese = 9, - Russian = 10, - TraditionalChinese = 11 - }; -}; -static_assert(sizeof(SMDH) == 0x36C0, "SMDH structure size is wrong"); - /// Interface for loading an application class AppLoader : NonCopyable { public: diff --git a/src/core/loader/smdh.cpp b/src/core/loader/smdh.cpp new file mode 100644 index 000000000..2d014054a --- /dev/null +++ b/src/core/loader/smdh.cpp @@ -0,0 +1,54 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include + +#include "common/common_types.h" + +#include "core/loader/loader.h" +#include "core/loader/smdh.h" + +#include "video_core/utils.h" + +namespace Loader { + +bool IsValidSMDH(const std::vector& smdh_data) { + if (smdh_data.size() < sizeof(Loader::SMDH)) + return false; + + u32 magic; + memcpy(&magic, smdh_data.data(), sizeof(u32)); + + return Loader::MakeMagic('S', 'M', 'D', 'H') == magic; +} + +std::vector SMDH::GetIcon(bool large) const { + u32 size; + const u8* icon_data; + + if (large) { + size = 48; + icon_data = large_icon.data(); + } else { + size = 24; + icon_data = small_icon.data(); + } + + std::vector icon(size * size); + for (u32 x = 0; x < size; ++x) { + for (u32 y = 0; y < size; ++y) { + u32 coarse_y = y & ~7; + const u8* pixel = icon_data + VideoCore::GetMortonOffset(x, y, 2) + coarse_y * size * 2; + icon[x + size * y] = (pixel[1] << 8) + pixel[0]; + } + } + return icon; +} + +std::array SMDH::GetShortTitle(Loader::SMDH::TitleLanguage language) const { + return titles[static_cast(language)].short_title; +} + +} // namespace diff --git a/src/core/loader/smdh.h b/src/core/loader/smdh.h new file mode 100644 index 000000000..2011abda2 --- /dev/null +++ b/src/core/loader/smdh.h @@ -0,0 +1,82 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "common/swap.h" + +namespace Loader { + +/** + * Tests if data is a valid SMDH by its length and magic number. + * @param smdh_data data buffer to test + * @return bool test result + */ +bool IsValidSMDH(const std::vector& smdh_data); + +/// SMDH data structure that contains titles, icons etc. See https://www.3dbrew.org/wiki/SMDH +struct SMDH { + u32_le magic; + u16_le version; + INSERT_PADDING_BYTES(2); + + struct Title { + std::array short_title; + std::array long_title; + std::array publisher; + }; + std::array titles; + + std::array ratings; + u32_le region_lockout; + u32_le match_maker_id; + u64_le match_maker_bit_id; + u32_le flags; + u16_le eula_version; + INSERT_PADDING_BYTES(2); + float_le banner_animation_frame; + u32_le cec_id; + INSERT_PADDING_BYTES(8); + + std::array small_icon; + std::array large_icon; + + /// indicates the language used for each title entry + enum class TitleLanguage { + Japanese = 0, + English = 1, + French = 2, + German = 3, + Italian = 4, + Spanish = 5, + SimplifiedChinese = 6, + Korean= 7, + Dutch = 8, + Portuguese = 9, + Russian = 10, + TraditionalChinese = 11 + }; + + /** + * Gets game icon from SMDH + * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24) + * @return vector of RGB565 data + */ + std::vector GetIcon(bool large) const; + + /** + * Gets the short game title from SMDH + * @param language title language + * @return UTF-16 array of the short title + */ + std::array GetShortTitle(Loader::SMDH::TitleLanguage language) const; +}; +static_assert(sizeof(SMDH) == 0x36C0, "SMDH structure size is wrong"); + +} // namespace From 068bd6f7286e551ac13853dea5a28377b3d286d9 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 23 May 2016 22:53:53 +0200 Subject: [PATCH 36/60] OpenGL: Use uniforms for dist_atten_bias and dist_atten_scale --- .../renderer_opengl/gl_rasterizer.cpp | 72 +++++++++++++++++++ .../renderer_opengl/gl_rasterizer.h | 14 ++-- .../renderer_opengl/gl_shader_gen.cpp | 6 +- 3 files changed, 84 insertions(+), 8 deletions(-) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index bcd1ae78d..a2a314c6b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -518,6 +518,58 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { SyncLightPosition(7); break; + // Fragment lighting distance attenuation bias + case PICA_REG_INDEX_WORKAROUND(lighting.light[0].dist_atten_bias, 0x014A + 0 * 0x10): + SyncLightDistanceAttenuationBias(0); + break; + case PICA_REG_INDEX_WORKAROUND(lighting.light[1].dist_atten_bias, 0x014A + 1 * 0x10): + SyncLightDistanceAttenuationBias(1); + break; + case PICA_REG_INDEX_WORKAROUND(lighting.light[2].dist_atten_bias, 0x014A + 2 * 0x10): + SyncLightDistanceAttenuationBias(2); + break; + case PICA_REG_INDEX_WORKAROUND(lighting.light[3].dist_atten_bias, 0x014A + 3 * 0x10): + SyncLightDistanceAttenuationBias(3); + break; + case PICA_REG_INDEX_WORKAROUND(lighting.light[4].dist_atten_bias, 0x014A + 4 * 0x10): + SyncLightDistanceAttenuationBias(4); + break; + case PICA_REG_INDEX_WORKAROUND(lighting.light[5].dist_atten_bias, 0x014A + 5 * 0x10): + SyncLightDistanceAttenuationBias(5); + break; + case PICA_REG_INDEX_WORKAROUND(lighting.light[6].dist_atten_bias, 0x014A + 6 * 0x10): + SyncLightDistanceAttenuationBias(6); + break; + case PICA_REG_INDEX_WORKAROUND(lighting.light[7].dist_atten_bias, 0x014A + 7 * 0x10): + SyncLightDistanceAttenuationBias(7); + break; + + // Fragment lighting distance attenuation scale + case PICA_REG_INDEX_WORKAROUND(lighting.light[0].dist_atten_scale, 0x014B + 0 * 0x10): + SyncLightDistanceAttenuationScale(0); + break; + case PICA_REG_INDEX_WORKAROUND(lighting.light[1].dist_atten_scale, 0x014B + 1 * 0x10): + SyncLightDistanceAttenuationScale(1); + break; + case PICA_REG_INDEX_WORKAROUND(lighting.light[2].dist_atten_scale, 0x014B + 2 * 0x10): + SyncLightDistanceAttenuationScale(2); + break; + case PICA_REG_INDEX_WORKAROUND(lighting.light[3].dist_atten_scale, 0x014B + 3 * 0x10): + SyncLightDistanceAttenuationScale(3); + break; + case PICA_REG_INDEX_WORKAROUND(lighting.light[4].dist_atten_scale, 0x014B + 4 * 0x10): + SyncLightDistanceAttenuationScale(4); + break; + case PICA_REG_INDEX_WORKAROUND(lighting.light[5].dist_atten_scale, 0x014B + 5 * 0x10): + SyncLightDistanceAttenuationScale(5); + break; + case PICA_REG_INDEX_WORKAROUND(lighting.light[6].dist_atten_scale, 0x014B + 6 * 0x10): + SyncLightDistanceAttenuationScale(6); + break; + case PICA_REG_INDEX_WORKAROUND(lighting.light[7].dist_atten_scale, 0x014B + 7 * 0x10): + SyncLightDistanceAttenuationScale(7); + break; + // Fragment lighting global ambient color (emission + ambient * ambient) case PICA_REG_INDEX_WORKAROUND(lighting.global_ambient, 0x1c0): SyncGlobalAmbient(); @@ -896,6 +948,8 @@ void RasterizerOpenGL::SetShader() { SyncLightDiffuse(light_index); SyncLightAmbient(light_index); SyncLightPosition(light_index); + SyncLightDistanceAttenuationBias(light_index); + SyncLightDistanceAttenuationScale(light_index); } } } @@ -1105,3 +1159,21 @@ void RasterizerOpenGL::SyncLightPosition(int light_index) { uniform_block_data.dirty = true; } } + +void RasterizerOpenGL::SyncLightDistanceAttenuationBias(int light_index) { + GLfloat dist_atten_bias = Pica::float20::FromRaw(Pica::g_state.regs.lighting.light[light_index].dist_atten_bias).ToFloat32(); + + if (dist_atten_bias != uniform_block_data.data.light_src[light_index].dist_atten_bias) { + uniform_block_data.data.light_src[light_index].dist_atten_bias = dist_atten_bias; + uniform_block_data.dirty = true; + } +} + +void RasterizerOpenGL::SyncLightDistanceAttenuationScale(int light_index) { + GLfloat dist_atten_scale = Pica::float20::FromRaw(Pica::g_state.regs.lighting.light[light_index].dist_atten_scale).ToFloat32(); + + if (dist_atten_scale != uniform_block_data.data.light_src[light_index].dist_atten_scale) { + uniform_block_data.data.light_src[light_index].dist_atten_scale = dist_atten_scale; + uniform_block_data.dirty = true; + } +} diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index d70369400..052aad139 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -92,8 +92,6 @@ union PicaShaderConfig { state.lighting.light[light_index].directional = light.directional != 0; state.lighting.light[light_index].two_sided_diffuse = light.two_sided_diffuse != 0; state.lighting.light[light_index].dist_atten_enable = !regs.lighting.IsDistAttenDisabled(num); - state.lighting.light[light_index].dist_atten_bias = Pica::float20::FromRaw(light.dist_atten_bias).ToFloat32(); - state.lighting.light[light_index].dist_atten_scale = Pica::float20::FromRaw(light.dist_atten_scale).ToFloat32(); } state.lighting.lut_d0.enable = regs.lighting.disable_lut_d0 == 0; @@ -184,8 +182,6 @@ union PicaShaderConfig { bool directional; bool two_sided_diffuse; bool dist_atten_enable; - GLfloat dist_atten_scale; - GLfloat dist_atten_bias; } light[8]; bool enable; @@ -316,6 +312,8 @@ private: alignas(16) GLvec3 diffuse; alignas(16) GLvec3 ambient; alignas(16) GLvec3 position; + GLfloat dist_atten_bias; + GLfloat dist_atten_scale; }; /// Uniform structure for the Uniform Buffer Object, all members must be 16-byte aligned @@ -330,7 +328,7 @@ private: LightSrc light_src[8]; }; - static_assert(sizeof(UniformData) == 0x310, "The size of the UniformData structure has changed, update the structure in the shader"); + static_assert(sizeof(UniformData) == 0x390, "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 @@ -402,6 +400,12 @@ private: /// Syncs the specified light's position to match the PICA register void SyncLightPosition(int light_index); + /// Syncs the specified light's distance attenuation bias to match the PICA register + void SyncLightDistanceAttenuationBias(int light_index); + + /// Syncs the specified light's distance attenuation scale to match the PICA register + void SyncLightDistanceAttenuationScale(int light_index); + OpenGLState state; RasterizerCacheOpenGL res_cache; diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp index 71d60e69c..8332e722d 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.cpp +++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp @@ -439,9 +439,7 @@ static void WriteLighting(std::string& out, const PicaShaderConfig& config) { // If enabled, compute distance attenuation value std::string dist_atten = "1.0"; if (light_config.dist_atten_enable) { - std::string scale = std::to_string(light_config.dist_atten_scale); - std::string bias = std::to_string(light_config.dist_atten_bias); - std::string index = "(" + scale + " * length(-view - " + light_src + ".position) + " + bias + ")"; + std::string index = "(" + light_src + ".dist_atten_scale * length(-view - " + light_src + ".position) + " + light_src + ".dist_atten_bias)"; index = "((clamp(" + index + ", 0.0, FLOAT_255)))"; const unsigned lut_num = ((unsigned)Regs::LightingSampler::DistanceAttenuation + light_config.num); dist_atten = GetLutValue((Regs::LightingSampler)lut_num, index); @@ -549,6 +547,8 @@ struct LightSrc { vec3 diffuse; vec3 ambient; vec3 position; + float dist_atten_bias; + float dist_atten_scale; }; layout (std140) uniform shader_data { From 8e905b3af6c6f53cacadc3817c2f7707e09ada31 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 23 May 2016 23:06:31 +0200 Subject: [PATCH 37/60] Pica: Name lighting.config0 and .config1 registers --- src/video_core/pica.h | 12 +++++----- .../renderer_opengl/gl_rasterizer.h | 24 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 86c0a0096..88cb306c9 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h @@ -824,7 +824,7 @@ struct Regs { BitField<27, 1, u32> clamp_highlights; BitField<28, 2, LightingBumpMode> bump_mode; BitField<30, 1, u32> disable_bump_renorm; - }; + } config0; union { BitField<16, 1, u32> disable_lut_d0; @@ -845,13 +845,13 @@ struct Regs { BitField<29, 1, u32> disable_dist_atten_light_5; BitField<30, 1, u32> disable_dist_atten_light_6; BitField<31, 1, u32> disable_dist_atten_light_7; - }; + } config1; bool IsDistAttenDisabled(unsigned index) const { - const unsigned disable[] = { disable_dist_atten_light_0, disable_dist_atten_light_1, - disable_dist_atten_light_2, disable_dist_atten_light_3, - disable_dist_atten_light_4, disable_dist_atten_light_5, - disable_dist_atten_light_6, disable_dist_atten_light_7 }; + const unsigned disable[] = { config1.disable_dist_atten_light_0, config1.disable_dist_atten_light_1, + config1.disable_dist_atten_light_2, config1.disable_dist_atten_light_3, + config1.disable_dist_atten_light_4, config1.disable_dist_atten_light_5, + config1.disable_dist_atten_light_6, config1.disable_dist_atten_light_7 }; return disable[index] != 0; } diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 052aad139..96ee4b1dc 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -94,42 +94,42 @@ union PicaShaderConfig { state.lighting.light[light_index].dist_atten_enable = !regs.lighting.IsDistAttenDisabled(num); } - state.lighting.lut_d0.enable = regs.lighting.disable_lut_d0 == 0; + state.lighting.lut_d0.enable = regs.lighting.config1.disable_lut_d0 == 0; state.lighting.lut_d0.abs_input = regs.lighting.abs_lut_input.disable_d0 == 0; state.lighting.lut_d0.type = regs.lighting.lut_input.d0.Value(); state.lighting.lut_d0.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d0); - state.lighting.lut_d1.enable = regs.lighting.disable_lut_d1 == 0; + state.lighting.lut_d1.enable = regs.lighting.config1.disable_lut_d1 == 0; state.lighting.lut_d1.abs_input = regs.lighting.abs_lut_input.disable_d1 == 0; state.lighting.lut_d1.type = regs.lighting.lut_input.d1.Value(); state.lighting.lut_d1.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.d1); - state.lighting.lut_fr.enable = regs.lighting.disable_lut_fr == 0; + state.lighting.lut_fr.enable = regs.lighting.config1.disable_lut_fr == 0; state.lighting.lut_fr.abs_input = regs.lighting.abs_lut_input.disable_fr == 0; state.lighting.lut_fr.type = regs.lighting.lut_input.fr.Value(); state.lighting.lut_fr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.fr); - state.lighting.lut_rr.enable = regs.lighting.disable_lut_rr == 0; + state.lighting.lut_rr.enable = regs.lighting.config1.disable_lut_rr == 0; state.lighting.lut_rr.abs_input = regs.lighting.abs_lut_input.disable_rr == 0; state.lighting.lut_rr.type = regs.lighting.lut_input.rr.Value(); state.lighting.lut_rr.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rr); - state.lighting.lut_rg.enable = regs.lighting.disable_lut_rg == 0; + state.lighting.lut_rg.enable = regs.lighting.config1.disable_lut_rg == 0; state.lighting.lut_rg.abs_input = regs.lighting.abs_lut_input.disable_rg == 0; state.lighting.lut_rg.type = regs.lighting.lut_input.rg.Value(); state.lighting.lut_rg.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rg); - state.lighting.lut_rb.enable = regs.lighting.disable_lut_rb == 0; + state.lighting.lut_rb.enable = regs.lighting.config1.disable_lut_rb == 0; state.lighting.lut_rb.abs_input = regs.lighting.abs_lut_input.disable_rb == 0; state.lighting.lut_rb.type = regs.lighting.lut_input.rb.Value(); state.lighting.lut_rb.scale = regs.lighting.lut_scale.GetScale(regs.lighting.lut_scale.rb); - state.lighting.config = regs.lighting.config; - state.lighting.fresnel_selector = regs.lighting.fresnel_selector; - state.lighting.bump_mode = regs.lighting.bump_mode; - state.lighting.bump_selector = regs.lighting.bump_selector; - state.lighting.bump_renorm = regs.lighting.disable_bump_renorm == 0; - state.lighting.clamp_highlights = regs.lighting.clamp_highlights != 0; + state.lighting.config = regs.lighting.config0.config; + state.lighting.fresnel_selector = regs.lighting.config0.fresnel_selector; + state.lighting.bump_mode = regs.lighting.config0.bump_mode; + state.lighting.bump_selector = regs.lighting.config0.bump_selector; + state.lighting.bump_renorm = regs.lighting.config0.disable_bump_renorm == 0; + state.lighting.clamp_highlights = regs.lighting.config0.clamp_highlights != 0; return res; } From 30a01584f200df1a71d322bad10a02f60d17aa22 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 23 May 2016 23:11:06 +0200 Subject: [PATCH 38/60] Pica: Name LightSrc.config register --- src/video_core/pica.h | 30 +++++++++---------- .../renderer_opengl/gl_rasterizer.h | 4 +-- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 88cb306c9..544ea037f 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h @@ -787,23 +787,21 @@ struct Regs { LightColor diffuse; // material.diffuse * light.diffuse LightColor ambient; // material.ambient * light.ambient - struct { - // Encoded as 16-bit floating point - union { - BitField< 0, 16, u32> x; - BitField<16, 16, u32> y; - }; - union { - BitField< 0, 16, u32> z; - }; - - INSERT_PADDING_WORDS(0x3); - - union { - BitField<0, 1, u32> directional; - BitField<1, 1, u32> two_sided_diffuse; // When disabled, clamp dot-product to 0 - }; + // Encoded as 16-bit floating point + union { + BitField< 0, 16, u32> x; + BitField<16, 16, u32> y; }; + union { + BitField< 0, 16, u32> z; + }; + + INSERT_PADDING_WORDS(0x3); + + union { + BitField<0, 1, u32> directional; + BitField<1, 1, u32> two_sided_diffuse; // When disabled, clamp dot-product to 0 + } config; BitField<0, 20, u32> dist_atten_bias; BitField<0, 20, u32> dist_atten_scale; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 96ee4b1dc..bb7f20161 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -89,8 +89,8 @@ union PicaShaderConfig { unsigned num = regs.lighting.light_enable.GetNum(light_index); const auto& light = regs.lighting.light[num]; state.lighting.light[light_index].num = num; - state.lighting.light[light_index].directional = light.directional != 0; - state.lighting.light[light_index].two_sided_diffuse = light.two_sided_diffuse != 0; + state.lighting.light[light_index].directional = light.config.directional != 0; + state.lighting.light[light_index].two_sided_diffuse = light.config.two_sided_diffuse != 0; state.lighting.light[light_index].dist_atten_enable = !regs.lighting.IsDistAttenDisabled(num); } From 6a28f46844e697b8e33f0ec14fa2fa0938d6a075 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 23 May 2016 19:09:28 +0200 Subject: [PATCH 39/60] OpenGL: Set shader_dirty on lighting changes --- .../renderer_opengl/gl_rasterizer.cpp | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index a2a314c6b..931c34a37 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -380,6 +380,17 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { SyncCombinerColor(); break; + // Fragment lighting switches + case PICA_REG_INDEX(lighting.disable): + case PICA_REG_INDEX(lighting.num_lights): + case PICA_REG_INDEX(lighting.config0): + case PICA_REG_INDEX(lighting.config1): + case PICA_REG_INDEX(lighting.abs_lut_input): + case PICA_REG_INDEX(lighting.lut_input): + case PICA_REG_INDEX(lighting.lut_scale): + case PICA_REG_INDEX(lighting.light_enable): + break; + // Fragment lighting specular 0 color case PICA_REG_INDEX_WORKAROUND(lighting.light[0].specular_0, 0x140 + 0 * 0x10): SyncLightSpecular0(0); @@ -518,6 +529,18 @@ void RasterizerOpenGL::NotifyPicaRegisterChanged(u32 id) { SyncLightPosition(7); break; + // Fragment lighting light source config + case PICA_REG_INDEX_WORKAROUND(lighting.light[0].config, 0x149 + 0 * 0x10): + case PICA_REG_INDEX_WORKAROUND(lighting.light[1].config, 0x149 + 1 * 0x10): + case PICA_REG_INDEX_WORKAROUND(lighting.light[2].config, 0x149 + 2 * 0x10): + case PICA_REG_INDEX_WORKAROUND(lighting.light[3].config, 0x149 + 3 * 0x10): + case PICA_REG_INDEX_WORKAROUND(lighting.light[4].config, 0x149 + 4 * 0x10): + case PICA_REG_INDEX_WORKAROUND(lighting.light[5].config, 0x149 + 5 * 0x10): + case PICA_REG_INDEX_WORKAROUND(lighting.light[6].config, 0x149 + 6 * 0x10): + case PICA_REG_INDEX_WORKAROUND(lighting.light[7].config, 0x149 + 7 * 0x10): + shader_dirty = true; + break; + // Fragment lighting distance attenuation bias case PICA_REG_INDEX_WORKAROUND(lighting.light[0].dist_atten_bias, 0x014A + 0 * 0x10): SyncLightDistanceAttenuationBias(0); From c106f71bebdc6fffc03967f5a57618cfbe2ebaed Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 24 May 2016 17:22:44 -0400 Subject: [PATCH 40/60] New3DS: Minor style cleanup to #1520. --- src/citra/config.cpp | 2 +- src/citra_qt/config.cpp | 4 ++-- src/core/hle/service/ptm/ptm.cpp | 4 ++-- src/core/settings.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/citra/config.cpp b/src/citra/config.cpp index 4d170dec8..c64de8e22 100644 --- a/src/citra/config.cpp +++ b/src/citra/config.cpp @@ -78,7 +78,7 @@ void Config::ReadValues() { Settings::values.use_virtual_sd = sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); // System - Settings::values.is_new3ds = sdl2_config->GetBoolean("System", "is_new3ds", false); + Settings::values.is_new_3ds = sdl2_config->GetBoolean("System", "is_new_3ds", false); Settings::values.region_value = sdl2_config->GetInteger("System", "region_value", 1); // Miscellaneous diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp index f6e498128..6e4ba3907 100644 --- a/src/citra_qt/config.cpp +++ b/src/citra_qt/config.cpp @@ -61,7 +61,7 @@ void Config::ReadValues() { qt_config->endGroup(); qt_config->beginGroup("System"); - Settings::values.is_new3ds = qt_config->value("is_new3ds", false).toBool(); + Settings::values.is_new_3ds = qt_config->value("is_new_3ds", false).toBool(); Settings::values.region_value = qt_config->value("region_value", 1).toInt(); qt_config->endGroup(); @@ -152,7 +152,7 @@ void Config::SaveValues() { qt_config->endGroup(); qt_config->beginGroup("System"); - qt_config->setValue("is_new3ds", Settings::values.is_new3ds); + qt_config->setValue("is_new_3ds", Settings::values.is_new_3ds); qt_config->setValue("region_value", Settings::values.region_value); qt_config->endGroup(); diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index 3a0331ee1..e2c17d93b 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp @@ -91,10 +91,10 @@ void IsLegacyPowerOff(Service::Interface* self) { void CheckNew3DS(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - const bool is_new_3ds = Settings::values.is_new3ds; + const bool is_new_3ds = Settings::values.is_new_3ds; if (is_new_3ds) { - LOG_CRITICAL(Service_PTM, "The option 'is_new3ds' is enabled as part of the 'System' settings. Citra does not fully support New3DS emulation yet!"); + LOG_CRITICAL(Service_PTM, "The option 'is_new_3ds' is enabled as part of the 'System' settings. Citra does not fully support New 3DS emulation yet!"); } cmd_buff[1] = RESULT_SUCCESS.raw; diff --git a/src/core/settings.h b/src/core/settings.h index a61f25cbe..ea72f4d9c 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -42,7 +42,7 @@ static const std::array All = {{ struct Values { // CheckNew3DS - bool is_new3ds; + bool is_new_3ds; // Controls std::array input_mappings; From 80abe6eb08c9b409de2da718ffcca16fb3d95173 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Thu, 26 May 2016 18:53:30 +0100 Subject: [PATCH 41/60] Memory: Added necessary headers and removed unnecessary header --- src/core/hle/kernel/vm_manager.cpp | 1 + src/core/memory_setup.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 1e289f38a..066146cff 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -7,6 +7,7 @@ #include "common/assert.h" #include "core/hle/kernel/vm_manager.h" +#include "core/memory.h" #include "core/memory_setup.h" #include "core/mmio.h" diff --git a/src/core/memory_setup.h b/src/core/memory_setup.h index 05f70a1fe..ee8ea7857 100644 --- a/src/core/memory_setup.h +++ b/src/core/memory_setup.h @@ -6,7 +6,7 @@ #include "common/common_types.h" -#include "core/memory.h" +#include "core/mmio.h" namespace Memory { From 8e1768cf1dc6aeb827018a652a218f6da2f4a3c3 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Fri, 27 May 2016 10:40:01 +0100 Subject: [PATCH 42/60] common_funcs: Provide rotr and rotl for MSVC --- src/common/common_funcs.h | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index ab3515683..4633897ce 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h @@ -72,18 +72,24 @@ inline u64 _rotr64(u64 x, unsigned int shift){ } #else // _MSC_VER - #if (_MSC_VER < 1900) - // Function Cross-Compatibility - #define snprintf _snprintf - #endif - // Locale Cross-Compatibility - #define locale_t _locale_t +#if (_MSC_VER < 1900) + // Function Cross-Compatibility + #define snprintf _snprintf +#endif + +// Locale Cross-Compatibility +#define locale_t _locale_t + +extern "C" { + __declspec(dllimport) void __stdcall DebugBreak(void); +} +#define Crash() {DebugBreak();} + +// cstdlib provides these on MSVC +#define rotr _rotr +#define rotl _rotl - extern "C" { - __declspec(dllimport) void __stdcall DebugBreak(void); - } - #define Crash() {DebugBreak();} #endif // _MSC_VER ndef // Generic function to get last error message. From 896e5009aeec0603ee3dd77e34462a503253b75f Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 12:49:35 +0100 Subject: [PATCH 43/60] FS/Archive: Remove use of Memory::GetPointer --- src/core/hle/service/fs/archive.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index cc51ede0c..a7ebfde25 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -108,11 +108,13 @@ ResultVal File::SyncRequest() { offset, length, backend->GetSize()); } - ResultVal read = backend->Read(offset, length, Memory::GetPointer(address)); + std::vector data(length); + ResultVal read = backend->Read(offset, data.size(), data.data()); if (read.Failed()) { cmd_buff[1] = read.Code().raw; return read.Code(); } + Memory::WriteBlock(address, data.data(), *read); cmd_buff[2] = static_cast(*read); Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(address), length); break; @@ -128,7 +130,9 @@ ResultVal File::SyncRequest() { LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x", GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); - ResultVal written = backend->Write(offset, length, flush != 0, Memory::GetPointer(address)); + std::vector data(length); + Memory::ReadBlock(address, data.data(), data.size()); + ResultVal written = backend->Write(offset, data.size(), flush != 0, data.data()); if (written.Failed()) { cmd_buff[1] = written.Code().raw; return written.Code(); @@ -216,12 +220,14 @@ ResultVal Directory::SyncRequest() { { u32 count = cmd_buff[1]; u32 address = cmd_buff[3]; - auto entries = reinterpret_cast(Memory::GetPointer(address)); + std::vector entries(count); LOG_TRACE(Service_FS, "Read %s %s: count=%d", GetTypeName().c_str(), GetName().c_str(), count); // Number of entries actually read - cmd_buff[2] = backend->Read(count, entries); + u32 read = backend->Read(entries.size(), entries.data()); + cmd_buff[2] = read; + Memory::WriteBlock(address, entries.data(), read * sizeof(FileSys::Entry)); break; } @@ -456,11 +462,12 @@ ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon if (result.IsError()) return result; - u8* smdh_icon = Memory::GetPointer(icon_buffer); - if (!smdh_icon) + if (!Memory::IsValidVirtualAddress(icon_buffer)) return ResultCode(-1); // TODO(Subv): Find the right error code - ext_savedata->WriteIcon(path, smdh_icon, icon_size); + std::vector smdh_icon(icon_size); + Memory::ReadBlock(icon_buffer, smdh_icon.data(), smdh_icon.size()); + ext_savedata->WriteIcon(path, smdh_icon.data(), smdh_icon.size()); return RESULT_SUCCESS; } From e936f5952cd1de5db2758747396666a380843d9d Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 12:54:33 +0100 Subject: [PATCH 44/60] DSP_DSP: Remove use of Memory::GetPointer --- src/core/hle/service/dsp_dsp.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index 10730d7ac..c8aadd9db 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -140,12 +140,15 @@ static void LoadComponent(Service::Interface* self) { // TODO(bunnei): Implement real DSP firmware loading - ASSERT(Memory::GetPointer(buffer) != nullptr); - ASSERT(size > 0x37C); + ASSERT(Memory::IsValidVirtualAddress(buffer)); - LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(Memory::GetPointer(buffer), size)); + std::vector component_data(size); + Memory::ReadBlock(buffer, component_data.data(), component_data.size()); + + LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(component_data.data(), component_data.size())); // Some versions of the firmware have the location of DSP structures listed here. - LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(Memory::GetPointer(buffer) + 0x340, 60)); + ASSERT(size > 0x37C); + LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(component_data.data() + 0x340, 60)); LOG_WARNING(Service_DSP, "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X", size, prog_mask, data_mask, buffer); @@ -285,7 +288,7 @@ static void WriteProcessPipe(Service::Interface* self) { return; } - ASSERT_MSG(Memory::GetPointer(buffer) != nullptr, "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe_index, size, buffer); + ASSERT_MSG(Memory::IsValidVirtualAddress(buffer), "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer); std::vector message(size); for (u32 i = 0; i < size; i++) { @@ -324,7 +327,7 @@ static void ReadPipeIfPossible(Service::Interface* self) { DSP::HLE::DspPipe pipe = static_cast(pipe_index); - ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe_index, unknown, size, addr); + ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2); cmd_buff[1] = RESULT_SUCCESS.raw; // No error @@ -364,7 +367,7 @@ static void ReadPipe(Service::Interface* self) { DSP::HLE::DspPipe pipe = static_cast(pipe_index); - ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe_index, unknown, size, addr); + ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); if (DSP::HLE::GetPipeReadableSize(pipe) >= size) { std::vector response = DSP::HLE::PipeRead(pipe, size); From 31d49e01094068519850bbfa414f314fdb27beee Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 15:22:45 +0100 Subject: [PATCH 45/60] Memory: CopyBlock --- src/core/memory.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ src/core/memory.h | 4 ++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 1604a7da5..bf2493270 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -495,6 +495,47 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) { } } +void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) { + size_t remaining_size = size; + size_t page_index = src_addr >> PAGE_BITS; + size_t page_offset = src_addr & PAGE_MASK; + + while (remaining_size > 0) { + const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); + const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; + + switch (current_page_table->attributes[page_index]) { + case PageType::Unmapped: { + LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); + ZeroBlock(dest_addr, copy_amount); + break; + } + case PageType::Memory: { + DEBUG_ASSERT(current_page_table->pointers[page_index]); + const u8* src_ptr = current_page_table->pointers[page_index] + page_offset; + WriteBlock(dest_addr, src_ptr, copy_amount); + break; + } + case PageType::Special: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + std::vector buffer(copy_amount); + GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size()); + WriteBlock(dest_addr, buffer.data(), buffer.size()); + break; + } + default: + UNREACHABLE(); + } + + page_index++; + page_offset = 0; + dest_addr += copy_amount; + src_addr += copy_amount; + remaining_size -= copy_amount; + } +} + template<> u8 ReadMMIO(MMIORegionPointer mmio_handler, VAddr addr) { return mmio_handler->Read8(addr); diff --git a/src/core/memory.h b/src/core/memory.h index 713cdfb2f..bb5dd0d15 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -118,15 +118,15 @@ u16 Read16(VAddr addr); u32 Read32(VAddr addr); u64 Read64(VAddr addr); -void ReadBlock(const VAddr src_addr, u8* dest_buffer, size_t size); - void Write8(VAddr addr, u8 data); void Write16(VAddr addr, u16 data); void Write32(VAddr addr, u32 data); void Write64(VAddr addr, u64 data); +void ReadBlock(const VAddr src_addr, u8* dest_buffer, size_t size); void WriteBlock(const VAddr dest_addr, const u8* src_buffer, size_t size); void ZeroBlock(const VAddr dest_addr, const size_t size); +void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size); u8* GetPointer(VAddr virtual_address); From 5f33d2cf07d94af5304ec64371a404e709a9805f Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 15:24:14 +0100 Subject: [PATCH 46/60] GSP_GPU: Remove use of Memory::GetPointer --- src/core/hle/service/gsp_gpu.cpp | 85 +++++++++++++++++++------------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 8ded9b09b..f3c7b7df3 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -65,15 +65,27 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { return reinterpret_cast(ptr); } +/** + * Writes a single GSP GPU hardware registers with a single u32 value + * (For internal use.) + * + * @param base_address The address of the register in question + * @param data Data to be written + */ +static void WriteSingleHWReg(u32 base_address, u32 data) { + DEBUG_ASSERT_MSG((base_address & 3) == 0 && base_address < 0x420000, "Write address out of range or misaligned"); + HW::Write(base_address + REGS_BEGIN, data); +} + /** * Writes sequential GSP GPU hardware registers using an array of source data * * @param base_address The address of the first register in the sequence * @param size_in_bytes The number of registers to update (size of data) - * @param data A pointer to the source data + * @param data_vaddr A pointer to the source data * @return RESULT_SUCCESS if the parameters are valid, error code otherwise */ -static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { +static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_vaddr) { // This magic number is verified to be done by the gsp module const u32 max_size_in_bytes = 0x80; @@ -87,10 +99,10 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* da return ERR_GSP_REGS_MISALIGNED; } else { while (size_in_bytes > 0) { - HW::Write(base_address + REGS_BEGIN, *data); + WriteSingleHWReg(base_address, Memory::Read32(data_vaddr)); size_in_bytes -= 4; - ++data; + data_vaddr += 4; base_address += 4; } return RESULT_SUCCESS; @@ -112,7 +124,7 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* da * @param masks A pointer to the masks * @return RESULT_SUCCESS if the parameters are valid, error code otherwise */ -static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32* data, const u32* masks) { +static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr data_vaddr, VAddr masks_vaddr) { // This magic number is verified to be done by the gsp module const u32 max_size_in_bytes = 0x80; @@ -131,14 +143,17 @@ static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32 reg_value; HW::Read(reg_value, reg_address); - // Update the current value of the register only for set mask bits - reg_value = (reg_value & ~*masks) | (*data | *masks); + u32 data = Memory::Read32(data_vaddr); + u32 mask = Memory::Read32(masks_vaddr); - HW::Write(reg_address, reg_value); + // Update the current value of the register only for set mask bits + reg_value = (reg_value & ~mask) | (data | mask); + + WriteSingleHWReg(base_address, reg_value); size_in_bytes -= 4; - ++data; - ++masks; + data_vaddr += 4; + masks_vaddr += 4; base_address += 4; } return RESULT_SUCCESS; @@ -164,8 +179,7 @@ static void WriteHWRegs(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 reg_addr = cmd_buff[1]; u32 size = cmd_buff[2]; - - u32* src = (u32*)Memory::GetPointer(cmd_buff[4]); + VAddr src = cmd_buff[4]; cmd_buff[1] = WriteHWRegs(reg_addr, size, src).raw; } @@ -186,8 +200,8 @@ static void WriteHWRegsWithMask(Service::Interface* self) { u32 reg_addr = cmd_buff[1]; u32 size = cmd_buff[2]; - u32* src_data = (u32*)Memory::GetPointer(cmd_buff[4]); - u32* mask_data = (u32*)Memory::GetPointer(cmd_buff[6]); + VAddr src_data = cmd_buff[4]; + VAddr mask_data = cmd_buff[6]; cmd_buff[1] = WriteHWRegsWithMask(reg_addr, size, src_data, mask_data).raw; } @@ -210,13 +224,16 @@ static void ReadHWRegs(Service::Interface* self) { return; } - u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]); + VAddr dst_vaddr = cmd_buff[0x41]; while (size > 0) { - HW::Read(*dst, reg_addr + REGS_BEGIN); + u32 value; + HW::Read(value, reg_addr + REGS_BEGIN); + + Memory::Write32(dst_vaddr, value); size -= 4; - ++dst; + dst_vaddr += 4; reg_addr += 4; } } @@ -226,22 +243,22 @@ ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left); PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right); if (info.active_fb == 0) { - WriteHWRegs(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), - 4, &phys_address_left); - WriteHWRegs(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), - 4, &phys_address_right); + WriteSingleHWReg(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), + phys_address_left); + WriteSingleHWReg(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), + phys_address_right); } else { - WriteHWRegs(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), - 4, &phys_address_left); - WriteHWRegs(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), - 4, &phys_address_right); + WriteSingleHWReg(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), + phys_address_left); + WriteSingleHWReg(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), + phys_address_right); } - WriteHWRegs(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), - 4, &info.stride); - WriteHWRegs(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), - 4, &info.format); - WriteHWRegs(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), - 4, &info.shown_fb); + WriteSingleHWReg(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), + info.stride); + WriteSingleHWReg(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), + info.format); + WriteSingleHWReg(base_address + 4 * static_cast(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), + info.shown_fb); if (Pica::g_debug_context) Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); @@ -432,9 +449,9 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), command.dma_request.size); - memcpy(Memory::GetPointer(command.dma_request.dest_address), - Memory::GetPointer(command.dma_request.source_address), - command.dma_request.size); + // TODO(Subv): These memory accesses should not go through the application's memory mapping. + // They should go through the GSP module's memory mapping. + Memory::CopyBlock(command.dma_request.dest_address, command.dma_request.source_address, command.dma_request.size); SignalInterrupt(InterruptId::DMA); break; } From 59b268de35d7ed9db55e2aadc449e945e896b937 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sat, 16 Apr 2016 15:24:39 +0100 Subject: [PATCH 47/60] SSL_C: Remove use of Memory::GetPointer --- src/core/hle/service/ssl_c.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp index 14a4e98ec..a8aff1abf 100644 --- a/src/core/hle/service/ssl_c.cpp +++ b/src/core/hle/service/ssl_c.cpp @@ -31,7 +31,6 @@ static void GenerateRandomData(Service::Interface* self) { u32 size = cmd_buff[1]; VAddr address = cmd_buff[3]; - u8* output_buff = Memory::GetPointer(address); // Fill the output buffer with random data. u32 data = 0; @@ -44,13 +43,13 @@ static void GenerateRandomData(Service::Interface* self) { if (size > 4) { // Use up the entire 4 bytes of the random data for as long as possible - *(u32*)(output_buff + i) = data; + Memory::Write32(address + i, data); i += 4; } else if (size == 2) { - *(u16*)(output_buff + i) = (u16)(data & 0xffff); + Memory::Write16(address + i, static_cast(data & 0xffff)); i += 2; } else { - *(u8*)(output_buff + i) = (u8)(data & 0xff); + Memory::Write8(address + i, static_cast(data & 0xff)); i++; } } From 99695d03d2ecce9bb6f8dbf23e763378b89b6759 Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 19 Apr 2016 01:08:16 -0500 Subject: [PATCH 48/60] SOC_U: Remove usage of GetPointer --- src/core/hle/service/soc_u.cpp | 102 ++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 28 deletions(-) diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp index d3e5d4bca..a7404085b 100644 --- a/src/core/hle/service/soc_u.cpp +++ b/src/core/hle/service/soc_u.cpp @@ -373,14 +373,18 @@ static void Bind(Service::Interface* self) { u32* cmd_buffer = Kernel::GetCommandBuffer(); u32 socket_handle = cmd_buffer[1]; u32 len = cmd_buffer[2]; - CTRSockAddr* ctr_sock_addr = reinterpret_cast(Memory::GetPointer(cmd_buffer[6])); - if (ctr_sock_addr == nullptr) { + // Virtual address of the sock_addr structure + VAddr sock_addr_addr = cmd_buffer[6]; + if (!Memory::IsValidVirtualAddress(sock_addr_addr)) { cmd_buffer[1] = -1; // TODO(Subv): Correct code return; } - sockaddr sock_addr = CTRSockAddr::ToPlatform(*ctr_sock_addr); + CTRSockAddr ctr_sock_addr; + Memory::ReadBlock(sock_addr_addr, reinterpret_cast(&ctr_sock_addr), sizeof(CTRSockAddr)); + + sockaddr sock_addr = CTRSockAddr::ToPlatform(ctr_sock_addr); int res = ::bind(socket_handle, &sock_addr, std::max(sizeof(sock_addr), len)); @@ -496,7 +500,7 @@ static void Accept(Service::Interface* self) { result = TranslateError(GET_ERRNO); } else { CTRSockAddr ctr_addr = CTRSockAddr::FromPlatform(addr); - Memory::WriteBlock(cmd_buffer[0x104 >> 2], (const u8*)&ctr_addr, max_addr_len); + Memory::WriteBlock(cmd_buffer[0x104 >> 2], &ctr_addr, sizeof(ctr_addr)); } cmd_buffer[0] = IPC::MakeHeader(4, 2, 2); @@ -547,20 +551,31 @@ static void SendTo(Service::Interface* self) { u32 flags = cmd_buffer[3]; u32 addr_len = cmd_buffer[4]; - u8* input_buff = Memory::GetPointer(cmd_buffer[8]); - CTRSockAddr* ctr_dest_addr = reinterpret_cast(Memory::GetPointer(cmd_buffer[10])); - - if (ctr_dest_addr == nullptr) { + VAddr input_buff_address = cmd_buffer[8]; + if (!Memory::IsValidVirtualAddress(input_buff_address)) { cmd_buffer[1] = -1; // TODO(Subv): Find the right error code return; } + // Memory address of the dest_addr structure + VAddr dest_addr_addr = cmd_buffer[10]; + if (!Memory::IsValidVirtualAddress(dest_addr_addr)) { + cmd_buffer[1] = -1; // TODO(Subv): Find the right error code + return; + } + + std::vector input_buff(len); + Memory::ReadBlock(input_buff_address, input_buff.data(), input_buff.size()); + + CTRSockAddr ctr_dest_addr; + Memory::ReadBlock(dest_addr_addr, reinterpret_cast(&ctr_dest_addr), sizeof(ctr_dest_addr)); + int ret = -1; if (addr_len > 0) { - sockaddr dest_addr = CTRSockAddr::ToPlatform(*ctr_dest_addr); - ret = ::sendto(socket_handle, (const char*)input_buff, len, flags, &dest_addr, sizeof(dest_addr)); + sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr); + ret = ::sendto(socket_handle, reinterpret_cast(input_buff.data()), len, flags, &dest_addr, sizeof(dest_addr)); } else { - ret = ::sendto(socket_handle, (const char*)input_buff, len, flags, nullptr, 0); + ret = ::sendto(socket_handle, reinterpret_cast(input_buff.data()), len, flags, nullptr, 0); } int result = 0; @@ -591,14 +606,24 @@ static void RecvFrom(Service::Interface* self) { std::memcpy(&buffer_parameters, &cmd_buffer[64], sizeof(buffer_parameters)); - u8* output_buff = Memory::GetPointer(buffer_parameters.output_buffer_addr); + if (!Memory::IsValidVirtualAddress(buffer_parameters.output_buffer_addr)) { + cmd_buffer[1] = -1; // TODO(Subv): Find the right error code + return; + } + + if (!Memory::IsValidVirtualAddress(buffer_parameters.output_src_address_buffer)) { + cmd_buffer[1] = -1; // TODO(Subv): Find the right error code + return; + } + + std::vector output_buff(len); sockaddr src_addr; socklen_t src_addr_len = sizeof(src_addr); - int ret = ::recvfrom(socket_handle, (char*)output_buff, len, flags, &src_addr, &src_addr_len); + int ret = ::recvfrom(socket_handle, reinterpret_cast(output_buff.data()), len, flags, &src_addr, &src_addr_len); if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) { - CTRSockAddr* ctr_src_addr = reinterpret_cast(Memory::GetPointer(buffer_parameters.output_src_address_buffer)); - *ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); + CTRSockAddr ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); + Memory::WriteBlock(buffer_parameters.output_src_address_buffer, reinterpret_cast(&ctr_src_addr), sizeof(ctr_src_addr)); } int result = 0; @@ -606,6 +631,9 @@ static void RecvFrom(Service::Interface* self) { if (ret == SOCKET_ERROR_VALUE) { result = TranslateError(GET_ERRNO); total_received = 0; + } else { + // Write only the data we received to avoid overwriting parts of the buffer with zeros + Memory::WriteBlock(buffer_parameters.output_buffer_addr, output_buff.data(), total_received); } cmd_buffer[1] = result; @@ -617,18 +645,28 @@ static void Poll(Service::Interface* self) { u32* cmd_buffer = Kernel::GetCommandBuffer(); u32 nfds = cmd_buffer[1]; int timeout = cmd_buffer[2]; - CTRPollFD* input_fds = reinterpret_cast(Memory::GetPointer(cmd_buffer[6])); - CTRPollFD* output_fds = reinterpret_cast(Memory::GetPointer(cmd_buffer[0x104 >> 2])); + + VAddr input_fds_addr = cmd_buffer[6]; + VAddr output_fds_addr = cmd_buffer[0x104 >> 2]; + if (!Memory::IsValidVirtualAddress(input_fds_addr) || !Memory::IsValidVirtualAddress(output_fds_addr)) { + cmd_buffer[1] = -1; // TODO(Subv): Find correct error code. + return; + } + + std::vector ctr_fds(nfds); + Memory::ReadBlock(input_fds_addr, reinterpret_cast(ctr_fds.data()), nfds * sizeof(CTRPollFD)); // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes) // so we have to copy the data std::vector platform_pollfd(nfds); - std::transform(input_fds, input_fds + nfds, platform_pollfd.begin(), CTRPollFD::ToPlatform); + std::transform(ctr_fds.begin(), ctr_fds.end(), platform_pollfd.begin(), CTRPollFD::ToPlatform); const int ret = ::poll(platform_pollfd.data(), nfds, timeout); // Now update the output pollfd structure - std::transform(platform_pollfd.begin(), platform_pollfd.end(), output_fds, CTRPollFD::FromPlatform); + std::transform(platform_pollfd.begin(), platform_pollfd.end(), ctr_fds.begin(), CTRPollFD::FromPlatform); + + Memory::WriteBlock(output_fds_addr, reinterpret_cast(ctr_fds.data()), nfds * sizeof(CTRPollFD)); int result = 0; if (ret == SOCKET_ERROR_VALUE) @@ -643,14 +681,16 @@ static void GetSockName(Service::Interface* self) { u32 socket_handle = cmd_buffer[1]; socklen_t ctr_len = cmd_buffer[2]; - CTRSockAddr* ctr_dest_addr = reinterpret_cast(Memory::GetPointer(cmd_buffer[0x104 >> 2])); + // Memory address of the ctr_dest_addr structure + VAddr ctr_dest_addr_addr = cmd_buffer[0x104 >> 2]; sockaddr dest_addr; socklen_t dest_addr_len = sizeof(dest_addr); int ret = ::getsockname(socket_handle, &dest_addr, &dest_addr_len); - if (ctr_dest_addr != nullptr) { - *ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); + if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) { + CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); + Memory::WriteBlock(ctr_dest_addr_addr, reinterpret_cast(&ctr_dest_addr), sizeof(ctr_dest_addr)); } else { cmd_buffer[1] = -1; // TODO(Subv): Verify error return; @@ -682,14 +722,16 @@ static void GetPeerName(Service::Interface* self) { u32 socket_handle = cmd_buffer[1]; socklen_t len = cmd_buffer[2]; - CTRSockAddr* ctr_dest_addr = reinterpret_cast(Memory::GetPointer(cmd_buffer[0x104 >> 2])); + // Memory address of the ctr_dest_addr structure + VAddr ctr_dest_addr_addr = cmd_buffer[0x104 >> 2]; sockaddr dest_addr; socklen_t dest_addr_len = sizeof(dest_addr); int ret = ::getpeername(socket_handle, &dest_addr, &dest_addr_len); - if (ctr_dest_addr != nullptr) { - *ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); + if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) { + CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); + Memory::WriteBlock(ctr_dest_addr_addr, reinterpret_cast(&ctr_dest_addr), sizeof(ctr_dest_addr)); } else { cmd_buffer[1] = -1; return; @@ -711,13 +753,17 @@ static void Connect(Service::Interface* self) { u32 socket_handle = cmd_buffer[1]; socklen_t len = cmd_buffer[2]; - CTRSockAddr* ctr_input_addr = reinterpret_cast(Memory::GetPointer(cmd_buffer[6])); - if (ctr_input_addr == nullptr) { + // Memory address of the ctr_input_addr structure + VAddr ctr_input_addr_addr = cmd_buffer[6]; + if (!Memory::IsValidVirtualAddress(ctr_input_addr_addr)) { cmd_buffer[1] = -1; // TODO(Subv): Verify error return; } - sockaddr input_addr = CTRSockAddr::ToPlatform(*ctr_input_addr); + CTRSockAddr ctr_input_addr; + Memory::ReadBlock(ctr_input_addr_addr, reinterpret_cast(&ctr_input_addr), sizeof(ctr_input_addr)); + + sockaddr input_addr = CTRSockAddr::ToPlatform(ctr_input_addr); int ret = ::connect(socket_handle, &input_addr, sizeof(input_addr)); int result = 0; if (ret != 0) From 660499ac01b9244301a0642f4a0209ef8309ace4 Mon Sep 17 00:00:00 2001 From: Subv Date: Tue, 19 Apr 2016 14:08:02 -0500 Subject: [PATCH 49/60] Memory: Make ReadBlock and WriteBlock accept void pointers. --- src/core/hle/service/frd/frd.cpp | 10 ++++------ src/core/hle/service/soc_u.cpp | 14 +++++++------- src/core/memory.cpp | 8 ++++---- src/core/memory.h | 4 ++-- src/core/mmio.h | 4 ++-- 5 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp index 15d604bb6..29d144365 100644 --- a/src/core/hle/service/frd/frd.cpp +++ b/src/core/hle/service/frd/frd.cpp @@ -23,7 +23,7 @@ void GetMyPresence(Service::Interface* self) { ASSERT(shifted_out_size == ((sizeof(MyPresence) << 14) | 2)); - Memory::WriteBlock(my_presence_addr, reinterpret_cast(&my_presence), sizeof(MyPresence)); + Memory::WriteBlock(my_presence_addr, &my_presence, sizeof(MyPresence)); cmd_buff[1] = RESULT_SUCCESS.raw; // No error @@ -39,8 +39,7 @@ void GetFriendKeyList(Service::Interface* self) { FriendKey zero_key = {}; for (u32 i = 0; i < frd_count; ++i) { - Memory::WriteBlock(frd_key_addr + i * sizeof(FriendKey), - reinterpret_cast(&zero_key), sizeof(FriendKey)); + Memory::WriteBlock(frd_key_addr + i * sizeof(FriendKey), &zero_key, sizeof(FriendKey)); } cmd_buff[1] = RESULT_SUCCESS.raw; // No error @@ -58,8 +57,7 @@ void GetFriendProfile(Service::Interface* self) { Profile zero_profile = {}; for (u32 i = 0; i < count; ++i) { - Memory::WriteBlock(profiles_addr + i * sizeof(Profile), - reinterpret_cast(&zero_profile), sizeof(Profile)); + Memory::WriteBlock(profiles_addr + i * sizeof(Profile), &zero_profile, sizeof(Profile)); } cmd_buff[1] = RESULT_SUCCESS.raw; // No error @@ -88,7 +86,7 @@ void GetMyFriendKey(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); cmd_buff[1] = RESULT_SUCCESS.raw; // No error - Memory::WriteBlock(cmd_buff[2], reinterpret_cast(&my_friend_key), sizeof(FriendKey)); + Memory::WriteBlock(cmd_buff[2], &my_friend_key, sizeof(FriendKey)); LOG_WARNING(Service_FRD, "(STUBBED) called"); } diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp index a7404085b..9b285567b 100644 --- a/src/core/hle/service/soc_u.cpp +++ b/src/core/hle/service/soc_u.cpp @@ -568,7 +568,7 @@ static void SendTo(Service::Interface* self) { Memory::ReadBlock(input_buff_address, input_buff.data(), input_buff.size()); CTRSockAddr ctr_dest_addr; - Memory::ReadBlock(dest_addr_addr, reinterpret_cast(&ctr_dest_addr), sizeof(ctr_dest_addr)); + Memory::ReadBlock(dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); int ret = -1; if (addr_len > 0) { @@ -623,7 +623,7 @@ static void RecvFrom(Service::Interface* self) { if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) { CTRSockAddr ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); - Memory::WriteBlock(buffer_parameters.output_src_address_buffer, reinterpret_cast(&ctr_src_addr), sizeof(ctr_src_addr)); + Memory::WriteBlock(buffer_parameters.output_src_address_buffer, &ctr_src_addr, sizeof(ctr_src_addr)); } int result = 0; @@ -654,7 +654,7 @@ static void Poll(Service::Interface* self) { } std::vector ctr_fds(nfds); - Memory::ReadBlock(input_fds_addr, reinterpret_cast(ctr_fds.data()), nfds * sizeof(CTRPollFD)); + Memory::ReadBlock(input_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes) // so we have to copy the data @@ -666,7 +666,7 @@ static void Poll(Service::Interface* self) { // Now update the output pollfd structure std::transform(platform_pollfd.begin(), platform_pollfd.end(), ctr_fds.begin(), CTRPollFD::FromPlatform); - Memory::WriteBlock(output_fds_addr, reinterpret_cast(ctr_fds.data()), nfds * sizeof(CTRPollFD)); + Memory::WriteBlock(output_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); int result = 0; if (ret == SOCKET_ERROR_VALUE) @@ -690,7 +690,7 @@ static void GetSockName(Service::Interface* self) { if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) { CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); - Memory::WriteBlock(ctr_dest_addr_addr, reinterpret_cast(&ctr_dest_addr), sizeof(ctr_dest_addr)); + Memory::WriteBlock(ctr_dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); } else { cmd_buffer[1] = -1; // TODO(Subv): Verify error return; @@ -731,7 +731,7 @@ static void GetPeerName(Service::Interface* self) { if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) { CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); - Memory::WriteBlock(ctr_dest_addr_addr, reinterpret_cast(&ctr_dest_addr), sizeof(ctr_dest_addr)); + Memory::WriteBlock(ctr_dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); } else { cmd_buffer[1] = -1; return; @@ -761,7 +761,7 @@ static void Connect(Service::Interface* self) { } CTRSockAddr ctr_input_addr; - Memory::ReadBlock(ctr_input_addr_addr, reinterpret_cast(&ctr_input_addr), sizeof(ctr_input_addr)); + Memory::ReadBlock(ctr_input_addr_addr, &ctr_input_addr, sizeof(ctr_input_addr)); sockaddr input_addr = CTRSockAddr::ToPlatform(ctr_input_addr); int ret = ::connect(socket_handle, &input_addr, sizeof(input_addr)); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index bf2493270..2ac3e7de4 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -364,7 +364,7 @@ u64 Read64(const VAddr addr) { return Read(addr); } -void ReadBlock(const VAddr src_addr, u8* dest_buffer, const size_t size) { +void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) { size_t remaining_size = size; size_t page_index = src_addr >> PAGE_BITS; size_t page_offset = src_addr & PAGE_MASK; @@ -398,7 +398,7 @@ void ReadBlock(const VAddr src_addr, u8* dest_buffer, const size_t size) { page_index++; page_offset = 0; - dest_buffer += copy_amount; + dest_buffer = static_cast(dest_buffer) + copy_amount; remaining_size -= copy_amount; } } @@ -419,7 +419,7 @@ void Write64(const VAddr addr, const u64 data) { Write(addr, data); } -void WriteBlock(const VAddr dest_addr, const u8* src_buffer, const size_t size) { +void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size) { size_t remaining_size = size; size_t page_index = dest_addr >> PAGE_BITS; size_t page_offset = dest_addr & PAGE_MASK; @@ -452,7 +452,7 @@ void WriteBlock(const VAddr dest_addr, const u8* src_buffer, const size_t size) page_index++; page_offset = 0; - src_buffer += copy_amount; + src_buffer = static_cast(src_buffer) + copy_amount; remaining_size -= copy_amount; } } diff --git a/src/core/memory.h b/src/core/memory.h index bb5dd0d15..ae5588dee 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -123,8 +123,8 @@ void Write16(VAddr addr, u16 data); void Write32(VAddr addr, u32 data); void Write64(VAddr addr, u64 data); -void ReadBlock(const VAddr src_addr, u8* dest_buffer, size_t size); -void WriteBlock(const VAddr dest_addr, const u8* src_buffer, size_t size); +void ReadBlock(const VAddr src_addr, void* dest_buffer, size_t size); +void WriteBlock(const VAddr dest_addr, const void* src_buffer, size_t size); void ZeroBlock(const VAddr dest_addr, const size_t size); void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size); diff --git a/src/core/mmio.h b/src/core/mmio.h index 35b73b061..d76f005d8 100644 --- a/src/core/mmio.h +++ b/src/core/mmio.h @@ -25,14 +25,14 @@ public: virtual u32 Read32(VAddr addr) = 0; virtual u64 Read64(VAddr addr) = 0; - virtual bool ReadBlock(VAddr src_addr, u8* dest_buffer, size_t size) = 0; + virtual bool ReadBlock(VAddr src_addr, void* dest_buffer, size_t size) = 0; virtual void Write8(VAddr addr, u8 data) = 0; virtual void Write16(VAddr addr, u16 data) = 0; virtual void Write32(VAddr addr, u32 data) = 0; virtual void Write64(VAddr addr, u64 data) = 0; - virtual bool WriteBlock(VAddr dest_addr, const u8* src_buffer, size_t size) = 0; + virtual bool WriteBlock(VAddr dest_addr, const void* src_buffer, size_t size) = 0; }; using MMIORegionPointer = std::shared_ptr; From 0aef634a54f786c49241c24b8d0c7aa3555b0fa1 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 15 May 2016 12:43:52 -0500 Subject: [PATCH 50/60] Memory: Handle RasterizerCachedMemory and RasterizerCachedSpecial page types in the memory block manipulation functions. --- src/core/hle/service/fs/archive.cpp | 1 - src/core/memory.cpp | 61 ++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index a7ebfde25..81b9abe4c 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -116,7 +116,6 @@ ResultVal File::SyncRequest() { } Memory::WriteBlock(address, data.data(), *read); cmd_buff[2] = static_cast(*read); - Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(address), length); break; } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 2ac3e7de4..8c9e5d46d 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -392,6 +392,20 @@ void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) { GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); break; } + case PageType::RasterizerCachedMemory: { + RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + + std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount); + break; + } + case PageType::RasterizerCachedSpecial: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + + GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); + break; + } default: UNREACHABLE(); } @@ -446,6 +460,20 @@ void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); break; } + case PageType::RasterizerCachedMemory: { + RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + + std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount); + break; + } + case PageType::RasterizerCachedSpecial: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + + GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); + break; + } default: UNREACHABLE(); } @@ -462,6 +490,8 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) { size_t page_index = dest_addr >> PAGE_BITS; size_t page_offset = dest_addr & PAGE_MASK; + static const std::array zeros = {}; + while (remaining_size > 0) { const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; @@ -481,7 +511,20 @@ void ZeroBlock(const VAddr dest_addr, const size_t size) { case PageType::Special: { DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); - static const std::array zeros = {}; + GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); + break; + } + case PageType::RasterizerCachedMemory: { + RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + + std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount); + break; + } + case PageType::RasterizerCachedSpecial: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); break; } @@ -524,6 +567,22 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) { WriteBlock(dest_addr, buffer.data(), buffer.size()); break; } + case PageType::RasterizerCachedMemory: { + RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + + WriteBlock(dest_addr, GetPointerFromVMA(current_vaddr), copy_amount); + break; + } + case PageType::RasterizerCachedSpecial: { + DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); + + RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); + + std::vector buffer(copy_amount); + GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size()); + WriteBlock(dest_addr, buffer.data(), buffer.size()); + break; + } default: UNREACHABLE(); } From d24d047d4571bd2a2583cbaffe974f32a3c04acb Mon Sep 17 00:00:00 2001 From: LFsWang Date: Wed, 1 Jun 2016 14:04:58 +0800 Subject: [PATCH 51/60] AddFstEntriesToGameList - prevent loading a directory --- src/citra_qt/game_list.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/citra_qt/game_list.cpp b/src/citra_qt/game_list.cpp index 49cb98e70..15484fae3 100644 --- a/src/citra_qt/game_list.cpp +++ b/src/citra_qt/game_list.cpp @@ -130,9 +130,7 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign if (stop_processing) return false; // Breaks the callback loop. - if (recursion > 0 && FileUtil::IsDirectory(physical_name)) { - AddFstEntriesToGameList(physical_name, recursion - 1); - } else { + if (!FileUtil::IsDirectory(physical_name)) { std::unique_ptr loader = Loader::GetLoader(physical_name); if (!loader) return true; @@ -145,6 +143,8 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign new GameListItem(QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), new GameListItemSize(FileUtil::GetSize(physical_name)), }); + } else if (recursion > 0) { + AddFstEntriesToGameList(physical_name, recursion - 1); } return true; From 07cc7811636360d042282a12e6a570337f20e3fc Mon Sep 17 00:00:00 2001 From: mailwl Date: Sat, 28 May 2016 14:42:40 +0300 Subject: [PATCH 52/60] gsp::gpu: Reset g_thread_id in UnregisterInterruptRelayQueue --- src/core/hle/result.h | 1 + src/core/hle/service/gsp_gpu.cpp | 36 +++++++++++-------- .../renderer_opengl/renderer_opengl.cpp | 2 +- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/core/hle/result.h b/src/core/hle/result.h index bfb3327ce..57dedcb22 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -26,6 +26,7 @@ enum class ErrorDescription : u32 { FS_NotAFile = 250, FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive OutofRangeOrMisalignedAddress = 513, // TODO(purpasmart): Check if this name fits its actual usage + GPU_FirstInitialization = 519, FS_InvalidPath = 702, InvalidSection = 1000, TooLarge = 1001, diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index f3c7b7df3..ec565f46d 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -44,7 +44,7 @@ Kernel::SharedPtr g_shared_memory; u32 g_thread_id = 0; static bool gpu_right_acquired = false; - +static bool first_initialization = true; /// Gets a pointer to a thread command buffer in GSP shared memory static inline u8* GetCommandBuffer(u32 thread_id) { return g_shared_memory->GetPointer(0x800 + (thread_id * sizeof(CommandBuffer))); @@ -347,24 +347,25 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { u32 flags = cmd_buff[1]; g_interrupt_event = Kernel::g_handle_table.Get(cmd_buff[3]); + // TODO(mailwl): return right error code instead assert ASSERT_MSG((g_interrupt_event != nullptr), "handle is not valid!"); g_interrupt_event->name = "GSP_GPU::interrupt_event"; - using Kernel::MemoryPermission; - g_shared_memory = Kernel::SharedMemory::Create(nullptr, 0x1000, - MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, - 0, Kernel::MemoryRegion::BASE, "GSP:SharedMemory"); - - Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); - - // This specific code is required for a successful initialization, rather than 0 - cmd_buff[1] = ResultCode((ErrorDescription)519, ErrorModule::GX, - ErrorSummary::Success, ErrorLevel::Success).raw; + if (first_initialization) { + // This specific code is required for a successful initialization, rather than 0 + first_initialization = false; + cmd_buff[1] = ResultCode(ErrorDescription::GPU_FirstInitialization, ErrorModule::GX, + ErrorSummary::Success, ErrorLevel::Success).raw; + } else { + cmd_buff[1] = RESULT_SUCCESS.raw; + } cmd_buff[2] = g_thread_id++; // Thread ID - cmd_buff[4] = shmem_handle; // GSP shared memory + cmd_buff[4] = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); // GSP shared memory g_interrupt_event->Signal(); // TODO(bunnei): Is this correct? + + LOG_WARNING(Service_GSP, "called, flags=0x%08X", flags); } /** @@ -375,12 +376,12 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { static void UnregisterInterruptRelayQueue(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - g_shared_memory = nullptr; + g_thread_id = 0; g_interrupt_event = nullptr; cmd_buff[1] = RESULT_SUCCESS.raw; - LOG_WARNING(Service_GSP, "called"); + LOG_WARNING(Service_GSP, "(STUBBED) called"); } /** @@ -718,10 +719,15 @@ Interface::Interface() { Register(FunctionTable); g_interrupt_event = nullptr; - g_shared_memory = nullptr; + + using Kernel::MemoryPermission; + g_shared_memory = Kernel::SharedMemory::Create(nullptr, 0x1000, + MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, + 0, Kernel::MemoryRegion::BASE, "GSP:SharedMemory"); g_thread_id = 0; gpu_right_acquired = false; + first_initialization = true; } Interface::~Interface() { diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 8f424a435..8410e0a64 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -450,7 +450,7 @@ static const char* GetType(GLenum type) { #undef RET } -static void DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, +static void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* user_param) { Log::Level level; switch (severity) { From 3a4a424b705210a54b05f23ddf661222fdd036ff Mon Sep 17 00:00:00 2001 From: archshift Date: Wed, 1 Jun 2016 20:48:26 -0700 Subject: [PATCH 53/60] Remove unused and bitrotted "controller config" files --- src/citra_qt/CMakeLists.txt | 5 - src/citra_qt/config/controller_config.cpp | 95 ------ src/citra_qt/config/controller_config.h | 56 ---- src/citra_qt/config/controller_config.ui | 308 ------------------ .../config/controller_config_util.cpp | 125 ------- src/citra_qt/config/controller_config_util.h | 82 ----- 6 files changed, 671 deletions(-) delete mode 100644 src/citra_qt/config/controller_config.cpp delete mode 100644 src/citra_qt/config/controller_config.h delete mode 100644 src/citra_qt/config/controller_config.ui delete mode 100644 src/citra_qt/config/controller_config_util.cpp delete mode 100644 src/citra_qt/config/controller_config_util.h diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index 0a5d4624b..585686627 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -2,8 +2,6 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(SRCS - config/controller_config.cpp - config/controller_config_util.cpp config.cpp debugger/callstack.cpp debugger/disassembler.cpp @@ -33,8 +31,6 @@ set(SRCS ) set(HEADERS - config/controller_config.h - config/controller_config_util.h config.h debugger/callstack.h debugger/disassembler.h @@ -65,7 +61,6 @@ set(HEADERS ) set(UIS - config/controller_config.ui debugger/callstack.ui debugger/disassembler.ui debugger/profiler.ui diff --git a/src/citra_qt/config/controller_config.cpp b/src/citra_qt/config/controller_config.cpp deleted file mode 100644 index 512879f1b..000000000 --- a/src/citra_qt/config/controller_config.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include - -#include "controller_config.h" -#include "controller_config_util.h" - -/* TODO(bunnei): ImplementMe - -using common::Config; - -GControllerConfig::GControllerConfig(common::Config::ControllerPort* initial_config, QWidget* parent) : QWidget(parent) -{ - ui.setupUi(this); - ((QGridLayout*)ui.mainStickTab->layout())->addWidget(new GStickConfig(Config::ANALOG_LEFT, Config::ANALOG_RIGHT, Config::ANALOG_UP, Config::ANALOG_DOWN, this, this), 1, 1); - ((QGridLayout*)ui.cStickTab->layout())->addWidget(new GStickConfig(Config::C_LEFT, Config::C_RIGHT, Config::C_UP, Config::C_DOWN, this, this), 1, 1); - ((QGridLayout*)ui.dPadTab->layout())->addWidget(new GStickConfig(Config::DPAD_LEFT, Config::DPAD_RIGHT, Config::DPAD_UP, Config::DPAD_DOWN, this, this), 1, 1); - - // TODO: Arrange these more compactly? - QVBoxLayout* layout = (QVBoxLayout*)ui.buttonsTab->layout(); - layout->addWidget(new GButtonConfigGroup("A Button", Config::BUTTON_A, this, ui.buttonsTab)); - layout->addWidget(new GButtonConfigGroup("B Button", Config::BUTTON_B, this, ui.buttonsTab)); - layout->addWidget(new GButtonConfigGroup("X Button", Config::BUTTON_X, this, ui.buttonsTab)); - layout->addWidget(new GButtonConfigGroup("Y Button", Config::BUTTON_Y, this, ui.buttonsTab)); - layout->addWidget(new GButtonConfigGroup("Z Button", Config::BUTTON_Z, this, ui.buttonsTab)); - layout->addWidget(new GButtonConfigGroup("L Trigger", Config::TRIGGER_L, this, ui.buttonsTab)); - layout->addWidget(new GButtonConfigGroup("R Trigger", Config::TRIGGER_R, this, ui.buttonsTab)); - layout->addWidget(new GButtonConfigGroup("Start Button", Config::BUTTON_START, this, ui.buttonsTab)); - - memcpy(config, initial_config, sizeof(config)); - - emit ActivePortChanged(config[0]); -} - -void GControllerConfig::OnKeyConfigChanged(common::Config::Control id, int key, const QString& name) -{ - if (InputSourceJoypad()) - { - config[GetActiveController()].pads.key_code[id] = key; - } - else - { - config[GetActiveController()].keys.key_code[id] = key; - } - emit ActivePortChanged(config[GetActiveController()]); -} - -int GControllerConfig::GetActiveController() -{ - return ui.activeControllerCB->currentIndex(); -} - -bool GControllerConfig::InputSourceJoypad() -{ - return ui.inputSourceCB->currentIndex() == 1; -} - -GControllerConfigDialog::GControllerConfigDialog(common::Config::ControllerPort* controller_ports, QWidget* parent) : QDialog(parent), config_ptr(controller_ports) -{ - setWindowTitle(tr("Input configuration")); - - QVBoxLayout* layout = new QVBoxLayout(this); - config_widget = new GControllerConfig(controller_ports, this); - layout->addWidget(config_widget); - - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - layout->addWidget(buttons); - - connect(buttons, SIGNAL(rejected()), this, SLOT(reject())); - connect(buttons, SIGNAL(accepted()), this, SLOT(accept())); - - connect(this, SIGNAL(accepted()), this, SLOT(EnableChanges())); - - layout->setSizeConstraint(QLayout::SetFixedSize); - setLayout(layout); - setModal(true); - show(); -} - -void GControllerConfigDialog::EnableChanges() -{ - for (unsigned int i = 0; i < 4; ++i) - { - memcpy(&config_ptr[i], &config_widget->GetControllerConfig(i), sizeof(common::Config::ControllerPort)); - - if (common::g_config) { - // Apply changes if running a game - memcpy(&common::g_config->controller_ports(i), &config_widget->GetControllerConfig(i), sizeof(common::Config::ControllerPort)); - } - } -} - -*/ diff --git a/src/citra_qt/config/controller_config.h b/src/citra_qt/config/controller_config.h deleted file mode 100644 index 451593de1..000000000 --- a/src/citra_qt/config/controller_config.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#ifndef _CONTROLLER_CONFIG_HXX_ -#define _CONTROLLER_CONFIG_HXX_ - -#include - -//#include "ui_controller_config.h" - -/* TODO(bunnei): ImplementMe - -#include "config.h" - -class GControllerConfig : public QWidget -{ - Q_OBJECT - -public: - GControllerConfig(common::Config::ControllerPort* initial_config, QWidget* parent = NULL); - - const common::Config::ControllerPort& GetControllerConfig(int index) const { return config[index]; } - -signals: - void ActivePortChanged(const common::Config::ControllerPort&); - -public slots: - void OnKeyConfigChanged(common::Config::Control id, int key, const QString& name); - -private: - int GetActiveController(); - bool InputSourceJoypad(); - - Ui::ControllerConfig ui; - common::Config::ControllerPort config[4]; -}; - -class GControllerConfigDialog : public QDialog -{ - Q_OBJECT - -public: - GControllerConfigDialog(common::Config::ControllerPort* controller_ports, QWidget* parent = NULL); - -public slots: - void EnableChanges(); - -private: - GControllerConfig* config_widget; - common::Config::ControllerPort* config_ptr; -}; - -*/ - -#endif // _CONTROLLER_CONFIG_HXX_ diff --git a/src/citra_qt/config/controller_config.ui b/src/citra_qt/config/controller_config.ui deleted file mode 100644 index 9f650047b..000000000 --- a/src/citra_qt/config/controller_config.ui +++ /dev/null @@ -1,308 +0,0 @@ - - - ControllerConfig - - - - 0 - 0 - 503 - 293 - - - - - 0 - 0 - - - - Controller Configuration - - - - QLayout::SetFixedSize - - - - - - - - Controller 1 - - - - - Controller 2 - - - - - Controller 3 - - - - - Controller 4 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Enabled - - - - - - - - Keyboard - - - - - Joypad - - - - - - - - Active Controller: - - - - - - - Input Source: - - - - - - - - - 0 - - - - Main Stick - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - C-Stick - - - - - - Qt::Horizontal - - - - 40 - 0 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - D-Pad - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - Buttons - - - - - - - - - - - ControlsChanged() - MainStickCleared() - CStickCleared() - DPadCleared() - ButtonsCleared() - OnControlsChanged() - OnMainStickCleared() - OnCStickCleared() - OnDPadCleared() - OnButtonsCleared() - - diff --git a/src/citra_qt/config/controller_config_util.cpp b/src/citra_qt/config/controller_config_util.cpp deleted file mode 100644 index d68b119df..000000000 --- a/src/citra_qt/config/controller_config_util.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include -#include -#include -#include -#include -#include - -#include "controller_config_util.h" - -/* TODO(bunnei): ImplementMe -GStickConfig::GStickConfig(common::Config::Control leftid, common::Config::Control rightid, common::Config::Control upid, common::Config::Control downid, QObject* change_receiver, QWidget* parent) : QWidget(parent) -{ - left = new GKeyConfigButton(leftid, style()->standardIcon(QStyle::SP_ArrowLeft), QString(), change_receiver, this); - right = new GKeyConfigButton(rightid, style()->standardIcon(QStyle::SP_ArrowRight), QString(), change_receiver, this); - up = new GKeyConfigButton(upid, style()->standardIcon(QStyle::SP_ArrowUp), QString(), change_receiver, this); - down = new GKeyConfigButton(downid, style()->standardIcon(QStyle::SP_ArrowDown), QString(), change_receiver, this); - clear = new QPushButton(tr("Clear"), this); - - QGridLayout* layout = new QGridLayout(this); - layout->addWidget(left, 1, 0); - layout->addWidget(right, 1, 2); - layout->addWidget(up, 0, 1); - layout->addWidget(down, 2, 1); - layout->addWidget(clear, 1, 1); - - setLayout(layout); -} - -GKeyConfigButton::GKeyConfigButton(common::Config::Control id, const QIcon& icon, const QString& text, QObject* change_receiver, QWidget* parent) : QPushButton(icon, text, parent), id(id), inputGrabbed(false) -{ - connect(this, SIGNAL(clicked()), this, SLOT(OnClicked())); - connect(this, SIGNAL(KeyAssigned(common::Config::Control, int, const QString&)), change_receiver, SLOT(OnKeyConfigChanged(common::Config::Control, int, const QString&))); - connect(change_receiver, SIGNAL(ActivePortChanged(const common::Config::ControllerPort&)), this, SLOT(OnActivePortChanged(const common::Config::ControllerPort&))); -} - -GKeyConfigButton::GKeyConfigButton(common::Config::Control id, const QString& text, QObject* change_receiver, QWidget* parent) : QPushButton(text, parent), id(id), inputGrabbed(false) -{ - connect(this, SIGNAL(clicked()), this, SLOT(OnClicked())); - connect(this, SIGNAL(KeyAssigned(common::Config::Control, int, const QString&)), change_receiver, SLOT(OnKeyConfigChanged(common::Config::Control, int, const QString&))); - connect(change_receiver, SIGNAL(ActivePortChanged(const common::Config::ControllerPort&)), this, SLOT(OnActivePortChanged(const common::Config::ControllerPort&))); -} - -void GKeyConfigButton::OnActivePortChanged(const common::Config::ControllerPort& config) -{ - // TODO: Doesn't use joypad struct if that's the input source... - QString text = QKeySequence(config.keys.key_code[id]).toString(); // has a nicer format - if (config.keys.key_code[id] == Qt::Key_Shift) text = tr("Shift"); - else if (config.keys.key_code[id] == Qt::Key_Control) text = tr("Control"); - else if (config.keys.key_code[id] == Qt::Key_Alt) text = tr("Alt"); - else if (config.keys.key_code[id] == Qt::Key_Meta) text = tr("Meta"); - setText(text); -} - -void GKeyConfigButton::OnClicked() -{ - grabKeyboard(); - grabMouse(); - inputGrabbed = true; - - old_text = text(); - setText(tr("Input...")); -} - -void GKeyConfigButton::keyPressEvent(QKeyEvent* event) -{ - if (inputGrabbed) - { - releaseKeyboard(); - releaseMouse(); - setText(QString()); - - // TODO: Doesn't capture "return" key - // TODO: This doesn't quite work well, yet... find a better way - QString text = QKeySequence(event->key()).toString(); // has a nicer format than event->text() - int key = event->key(); - if (event->modifiers() == Qt::ShiftModifier) { text = tr("Shift"); key = Qt::Key_Shift; } - else if (event->modifiers() == Qt::ControlModifier) { text = tr("Ctrl"); key = Qt::Key_Control; } - else if (event->modifiers() == Qt::AltModifier) { text = tr("Alt"); key = Qt::Key_Alt; } - else if (event->modifiers() == Qt::MetaModifier) { text = tr("Meta"); key = Qt::Key_Meta; } - - setText(old_text); - emit KeyAssigned(id, key, text); - - inputGrabbed = false; - - // TODO: Keys like "return" cause another keyPressEvent to be generated after this one... - } - - QPushButton::keyPressEvent(event); // TODO: Necessary? -} - -void GKeyConfigButton::mousePressEvent(QMouseEvent* event) -{ - // Abort key assignment - if (inputGrabbed) - { - releaseKeyboard(); - releaseMouse(); - setText(old_text); - inputGrabbed = false; - } - - QAbstractButton::mousePressEvent(event); -} - -GButtonConfigGroup::GButtonConfigGroup(const QString& name, common::Config::Control id, QObject* change_receiver, QWidget* parent) : QWidget(parent), id(id) -{ - QHBoxLayout* layout = new QHBoxLayout(this); - - QPushButton* clear_button = new QPushButton(tr("Clear")); - - layout->addWidget(new QLabel(name, this)); - layout->addWidget(config_button = new GKeyConfigButton(id, QString(), change_receiver, this)); - layout->addWidget(clear_button); - - // TODO: connect config_button, clear_button - - setLayout(layout); -} - -*/ diff --git a/src/citra_qt/config/controller_config_util.h b/src/citra_qt/config/controller_config_util.h deleted file mode 100644 index 15e025b57..000000000 --- a/src/citra_qt/config/controller_config_util.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#ifndef _CONTROLLER_CONFIG_UTIL_HXX_ -#define _CONTROLLER_CONFIG_UTIL_HXX_ - -#include -#include - -/* TODO(bunnei): ImplementMe - -#include "config.h" - -class GStickConfig : public QWidget -{ - Q_OBJECT - -public: - // change_receiver needs to have a OnKeyConfigChanged(common::Config::Control, int, const QString&) slot! - GStickConfig(common::Config::Control leftid, common::Config::Control rightid, common::Config::Control upid, common::Config::Control downid, QObject* change_receiver, QWidget* parent = NULL); - -signals: - void LeftChanged(); - void RightChanged(); - void UpChanged(); - void DownChanged(); - -private: - QPushButton* left; - QPushButton* right; - QPushButton* up; - QPushButton* down; - - QPushButton* clear; -}; - -class GKeyConfigButton : public QPushButton -{ - Q_OBJECT - -public: - // TODO: change_receiver also needs to have an ActivePortChanged(const common::Config::ControllerPort&) signal - // change_receiver needs to have a OnKeyConfigChanged(common::Config::Control, int, const QString&) slot! - GKeyConfigButton(common::Config::Control id, const QIcon& icon, const QString& text, QObject* change_receiver, QWidget* parent); - GKeyConfigButton(common::Config::Control id, const QString& text, QObject* change_receiver, QWidget* parent); - -signals: - void KeyAssigned(common::Config::Control id, int key, const QString& text); - -private slots: - void OnActivePortChanged(const common::Config::ControllerPort& config); - - void OnClicked(); - - void keyPressEvent(QKeyEvent* event); // TODO: bGrabbed? - void mousePressEvent(QMouseEvent* event); - -private: - common::Config::Control id; - bool inputGrabbed; - - QString old_text; -}; - -class GButtonConfigGroup : public QWidget -{ - Q_OBJECT - -public: - // change_receiver needs to have a OnKeyConfigChanged(common::Config::Control, int, const QString&) slot! - GButtonConfigGroup(const QString& name, common::Config::Control id, QObject* change_receiver, QWidget* parent = NULL); - -private: - GKeyConfigButton* config_button; - - common::Config::Control id; -}; - -*/ - -#endif // _CONTROLLER_CONFIG_HXX_ From 64b6a7c0062d0b68cd4c3ca3dc6126e1e6891a70 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 4 Jun 2016 19:38:54 -0400 Subject: [PATCH 54/60] service: Add other DLP services Specifically, dlp::CLNT and dlp::FKCL Moves them to their own folder like with other services. --- src/core/CMakeLists.txt | 10 +++++++-- src/core/hle/service/dlp/dlp.cpp | 24 +++++++++++++++++++++ src/core/hle/service/dlp/dlp.h | 15 +++++++++++++ src/core/hle/service/dlp/dlp_clnt.cpp | 20 +++++++++++++++++ src/core/hle/service/dlp/dlp_clnt.h | 22 +++++++++++++++++++ src/core/hle/service/dlp/dlp_fkcl.cpp | 20 +++++++++++++++++ src/core/hle/service/dlp/dlp_fkcl.h | 22 +++++++++++++++++++ src/core/hle/service/{ => dlp}/dlp_srvr.cpp | 22 +++++++++---------- src/core/hle/service/{ => dlp}/dlp_srvr.h | 13 ++++++----- src/core/hle/service/service.cpp | 5 +++-- 10 files changed, 150 insertions(+), 23 deletions(-) create mode 100644 src/core/hle/service/dlp/dlp.cpp create mode 100644 src/core/hle/service/dlp/dlp.h create mode 100644 src/core/hle/service/dlp/dlp_clnt.cpp create mode 100644 src/core/hle/service/dlp/dlp_clnt.h create mode 100644 src/core/hle/service/dlp/dlp_fkcl.cpp create mode 100644 src/core/hle/service/dlp/dlp_fkcl.h rename src/core/hle/service/{ => dlp}/dlp_srvr.cpp (57%) rename src/core/hle/service/{ => dlp}/dlp_srvr.h (55%) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ed80cf0e4..e9b04098b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -70,7 +70,10 @@ set(SRCS hle/service/cfg/cfg_s.cpp hle/service/cfg/cfg_u.cpp hle/service/csnd_snd.cpp - hle/service/dlp_srvr.cpp + hle/service/dlp/dlp.cpp + hle/service/dlp/dlp_clnt.cpp + hle/service/dlp/dlp_fkcl.cpp + hle/service/dlp/dlp_srvr.cpp hle/service/dsp_dsp.cpp hle/service/err_f.cpp hle/service/frd/frd.cpp @@ -206,7 +209,10 @@ set(HEADERS hle/service/cfg/cfg_s.h hle/service/cfg/cfg_u.h hle/service/csnd_snd.h - hle/service/dlp_srvr.h + hle/service/dlp/dlp.h + hle/service/dlp/dlp_clnt.h + hle/service/dlp/dlp_fkcl.h + hle/service/dlp/dlp_srvr.h hle/service/dsp_dsp.h hle/service/err_f.h hle/service/frd/frd.h diff --git a/src/core/hle/service/dlp/dlp.cpp b/src/core/hle/service/dlp/dlp.cpp new file mode 100644 index 000000000..7c8db794b --- /dev/null +++ b/src/core/hle/service/dlp/dlp.cpp @@ -0,0 +1,24 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/service.h" +#include "core/hle/service/dlp/dlp.h" +#include "core/hle/service/dlp/dlp_clnt.h" +#include "core/hle/service/dlp/dlp_fkcl.h" +#include "core/hle/service/dlp/dlp_srvr.h" + +namespace Service { +namespace DLP { + +void Init() { + AddService(new DLP_CLNT_Interface); + AddService(new DLP_FKCL_Interface); + AddService(new DLP_SRVR_Interface); +} + +void Shutdown() { +} + +} // namespace DLP +} // namespace Service diff --git a/src/core/hle/service/dlp/dlp.h b/src/core/hle/service/dlp/dlp.h new file mode 100644 index 000000000..ec2fe46e8 --- /dev/null +++ b/src/core/hle/service/dlp/dlp.h @@ -0,0 +1,15 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +namespace Service { +namespace DLP { + +/// Initializes the DLP services. +void Init(); + +/// Shuts down the DLP services. +void Shutdown(); + +} // namespace DLP +} // namespace Service diff --git a/src/core/hle/service/dlp/dlp_clnt.cpp b/src/core/hle/service/dlp/dlp_clnt.cpp new file mode 100644 index 000000000..0b31d47df --- /dev/null +++ b/src/core/hle/service/dlp/dlp_clnt.cpp @@ -0,0 +1,20 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/dlp/dlp_clnt.h" + +namespace Service { +namespace DLP { + +const Interface::FunctionInfo FunctionTable[] = { + {0x000100C3, nullptr, "Initialize"}, + {0x00110000, nullptr, "GetWirelessRebootPassphrase"}, +}; + +DLP_CLNT_Interface::DLP_CLNT_Interface() { + Register(FunctionTable); +} + +} // namespace DLP +} // namespace Service diff --git a/src/core/hle/service/dlp/dlp_clnt.h b/src/core/hle/service/dlp/dlp_clnt.h new file mode 100644 index 000000000..067f11e37 --- /dev/null +++ b/src/core/hle/service/dlp/dlp_clnt.h @@ -0,0 +1,22 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace DLP { + +class DLP_CLNT_Interface final : public Interface { +public: + DLP_CLNT_Interface(); + + std::string GetPortName() const override { + return "dlp:CLNT"; + } +}; + +} // namespace DLP +} // namespace Service diff --git a/src/core/hle/service/dlp/dlp_fkcl.cpp b/src/core/hle/service/dlp/dlp_fkcl.cpp new file mode 100644 index 000000000..a845260e5 --- /dev/null +++ b/src/core/hle/service/dlp/dlp_fkcl.cpp @@ -0,0 +1,20 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/dlp/dlp_fkcl.h" + +namespace Service { +namespace DLP { + +const Interface::FunctionInfo FunctionTable[] = { + {0x00010083, nullptr, "Initialize"}, + {0x000F0000, nullptr, "GetWirelessRebootPassphrase"}, +}; + +DLP_FKCL_Interface::DLP_FKCL_Interface() { + Register(FunctionTable); +} + +} // namespace DLP +} // namespace Service diff --git a/src/core/hle/service/dlp/dlp_fkcl.h b/src/core/hle/service/dlp/dlp_fkcl.h new file mode 100644 index 000000000..e4837a167 --- /dev/null +++ b/src/core/hle/service/dlp/dlp_fkcl.h @@ -0,0 +1,22 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace DLP { + +class DLP_FKCL_Interface final : public Interface { +public: + DLP_FKCL_Interface(); + + std::string GetPortName() const override { + return "dlp:FKCL"; + } +}; + +} // namespace DLP +} // namespace Service diff --git a/src/core/hle/service/dlp_srvr.cpp b/src/core/hle/service/dlp/dlp_srvr.cpp similarity index 57% rename from src/core/hle/service/dlp_srvr.cpp rename to src/core/hle/service/dlp/dlp_srvr.cpp index 1f30188da..da9b30f56 100644 --- a/src/core/hle/service/dlp_srvr.cpp +++ b/src/core/hle/service/dlp/dlp_srvr.cpp @@ -2,16 +2,15 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/common_types.h" #include "common/logging/log.h" -#include "core/hle/hle.h" -#include "core/hle/service/dlp_srvr.h" +#include "core/hle/result.h" +#include "core/hle/service/dlp/dlp_srvr.h" -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Namespace DLP_SRVR +namespace Service { +namespace DLP { -namespace DLP_SRVR { - -static void unk_0x000E0040(Service::Interface* self) { +static void unk_0x000E0040(Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); cmd_buff[1] = RESULT_SUCCESS.raw; @@ -23,14 +22,13 @@ static void unk_0x000E0040(Service::Interface* self) { const Interface::FunctionInfo FunctionTable[] = { {0x00010183, nullptr, "Initialize"}, {0x00020000, nullptr, "Finalize"}, + {0x000800C0, nullptr, "SendWirelessRebootPassphrase"}, {0x000E0040, unk_0x000E0040, "unk_0x000E0040"}, }; -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Interface class - -Interface::Interface() { +DLP_SRVR_Interface::DLP_SRVR_Interface() { Register(FunctionTable); } -} // namespace +} // namespace DLP +} // namespace Service diff --git a/src/core/hle/service/dlp_srvr.h b/src/core/hle/service/dlp/dlp_srvr.h similarity index 55% rename from src/core/hle/service/dlp_srvr.h rename to src/core/hle/service/dlp/dlp_srvr.h index d65d00814..19fe17840 100644 --- a/src/core/hle/service/dlp_srvr.h +++ b/src/core/hle/service/dlp/dlp_srvr.h @@ -6,18 +6,17 @@ #include "core/hle/service/service.h" -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Namespace DLP_SRVR +namespace Service { +namespace DLP { -namespace DLP_SRVR { - -class Interface : public Service::Interface { +class DLP_SRVR_Interface final : public Interface { public: - Interface(); + DLP_SRVR_Interface(); std::string GetPortName() const override { return "dlp:SRVR"; } }; -} // namespace +} // namespace DLP +} // namespace Service diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index d7e7d4fe3..395880843 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -10,7 +10,6 @@ #include "core/hle/service/act_a.h" #include "core/hle/service/act_u.h" #include "core/hle/service/csnd_snd.h" -#include "core/hle/service/dlp_srvr.h" #include "core/hle/service/dsp_dsp.h" #include "core/hle/service/err_f.h" #include "core/hle/service/gsp_gpu.h" @@ -31,6 +30,7 @@ #include "core/hle/service/boss/boss.h" #include "core/hle/service/cam/cam.h" #include "core/hle/service/cecd/cecd.h" +#include "core/hle/service/dlp/dlp.h" #include "core/hle/service/frd/frd.h" #include "core/hle/service/fs/archive.h" #include "core/hle/service/cfg/cfg.h" @@ -111,6 +111,7 @@ void Init() { Service::CAM::Init(); Service::CECD::Init(); Service::CFG::Init(); + Service::DLP::Init(); Service::FRD::Init(); Service::HID::Init(); Service::IR::Init(); @@ -123,7 +124,6 @@ void Init() { AddService(new ACT_A::Interface); AddService(new ACT_U::Interface); AddService(new CSND_SND::Interface); - AddService(new DLP_SRVR::Interface); AddService(new DSP_DSP::Interface); AddService(new GSP_GPU::Interface); AddService(new GSP_LCD::Interface); @@ -150,6 +150,7 @@ void Shutdown() { Service::IR::Shutdown(); Service::HID::Shutdown(); Service::FRD::Shutdown(); + Service::DLP::Shutdown(); Service::CFG::Shutdown(); Service::CECD::Shutdown(); Service::CAM::Shutdown(); From c6f87f7e2cd6036b9aa294392da35d476a4a5533 Mon Sep 17 00:00:00 2001 From: shinyquagsire23 Date: Wed, 8 Jun 2016 14:14:59 -0700 Subject: [PATCH 55/60] gdbstub: E0 should be E00 --- src/core/gdbstub/gdbstub.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 820b19e1a..28d403158 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -646,7 +646,7 @@ static void ReadMemory() { u8* data = Memory::GetPointer(addr); if (!data) { - return SendReply("E0"); + return SendReply("E00"); } MemToGdbHex(reply, data, len); From c7ffd8a920cb2504c7cb9ec7f06e1a95cba73953 Mon Sep 17 00:00:00 2001 From: archshift Date: Wed, 8 Jun 2016 20:59:24 -0700 Subject: [PATCH 56/60] arm_dyncom_interpreter.cpp: Split by translation and interpreter logic To facilitate the split, some small changes were made to names of various structures and functions. --- src/core/CMakeLists.txt | 2 + .../arm/dyncom/arm_dyncom_interpreter.cpp | 2719 +---------------- src/core/arm/dyncom/arm_dyncom_trans.cpp | 2181 +++++++++++++ src/core/arm/dyncom/arm_dyncom_trans.h | 492 +++ src/core/arm/skyeye_common/vfp/vfpinstr.cpp | 64 +- 5 files changed, 2731 insertions(+), 2727 deletions(-) create mode 100644 src/core/arm/dyncom/arm_dyncom_trans.cpp create mode 100644 src/core/arm/dyncom/arm_dyncom_trans.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e9b04098b..f356e4b48 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 @@ -140,6 +141,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 diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index cfc67287f..5f61b0ebb 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 get_shifter_op(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 get_calc_addr_op(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,2200 +717,20 @@ 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; +// Specialized for LDRT, LDRBT, STRT, and STRBT, which have specific addressing mode requirements +get_addr_fp_t get_calc_addr_op_loadstoret(unsigned int 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 { - DEBUG_MSG; + return LnSWoUB(ScaledRegisterPostIndexed); } - - 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; } -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; - 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); - } 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 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; -} - -// 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, @@ -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..8a0146531 --- /dev/null +++ b/src/core/arm/dyncom/arm_dyncom_trans.cpp @@ -0,0 +1,2181 @@ +#include + +#include "common/assert.h" +#include "common/common_funcs.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 FORCE_INLINE void* AllocBuffer(size_t size) { + size_t start = trans_cache_buf_top; + size_t end = trans_cache_buf_top + size; + ASSERT_MSG(end <= TRANS_CACHE_SIZE, "Translation cache is full!"); + return static_cast(&trans_cache_buf[start]); +} + +#define glue(x, y) x ## y +#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s) + +shtop_fp_t get_shifter_op(unsigned int inst); +get_addr_fp_t get_calc_addr_op(unsigned int inst); +get_addr_fp_t get_calc_addr_op_loadstoret(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 = get_shifter_op(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 = get_shifter_op(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 = get_shifter_op(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; + // if (BITS(inst, 28, 31) <= 0xe) + // inst_base->br |= TransExtData::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 = 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 = get_shifter_op(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 = get_shifter_op(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 = get_shifter_op(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 = get_shifter_op(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 = get_shifter_op(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 = get_calc_addr_op(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 = get_calc_addr_op(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 = get_calc_addr_op(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 = 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 = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op_loadstoret(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 = 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) ? 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 = 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 = TransExtData::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 = TransExtData::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 = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op_loadstoret(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 = get_shifter_op(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 = get_shifter_op(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 = get_shifter_op(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 = 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 = 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 = get_shifter_op(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 = get_shifter_op(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 = get_shifter_op(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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op_loadstoret(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 = 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 = 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 = 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 = TransExtData::NON_BRANCH; + + inst_cream->inst = inst; + inst_cream->get_addr = get_calc_addr_op_loadstoret(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 = get_shifter_op(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 = get_shifter_op(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 = get_shifter_op(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..39d93d928 --- /dev/null +++ b/src/core/arm/dyncom/arm_dyncom_trans.h @@ -0,0 +1,492 @@ +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; +}; + +#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); From a371744575bcec6a92c3bb8801b980530a4443a5 Mon Sep 17 00:00:00 2001 From: archshift Date: Wed, 8 Jun 2016 21:03:49 -0700 Subject: [PATCH 57/60] arm_dyncom_interpreter: rename operation functions to fit style guide --- .../arm/dyncom/arm_dyncom_interpreter.cpp | 6 +- src/core/arm/dyncom/arm_dyncom_trans.cpp | 78 +++++++++---------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 5f61b0ebb..01d5d478e 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -649,7 +649,7 @@ static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst, u virt_addr = addr; } -shtop_fp_t get_shifter_op(unsigned int inst) { +shtop_fp_t GetShifterOp(unsigned int inst) { if (BIT(inst, 25)) { return DPO(Immediate); } else if (BITS(inst, 4, 11) == 0) { @@ -674,7 +674,7 @@ shtop_fp_t get_shifter_op(unsigned int inst) { return nullptr; } -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) { @@ -718,7 +718,7 @@ get_addr_fp_t get_calc_addr_op(unsigned int inst) { } // Specialized for LDRT, LDRBT, STRT, and STRBT, which have specific addressing mode requirements -get_addr_fp_t get_calc_addr_op_loadstoret(unsigned int inst) { +get_addr_fp_t GetAddressingOpLoadStoreT(unsigned int inst) { if (BITS(inst, 25, 27) == 2) { return LnSWoUB(ImmediatePostIndexed); } else if (BITS(inst, 25, 27) == 3) { diff --git a/src/core/arm/dyncom/arm_dyncom_trans.cpp b/src/core/arm/dyncom/arm_dyncom_trans.cpp index 8a0146531..7f13ff836 100644 --- a/src/core/arm/dyncom/arm_dyncom_trans.cpp +++ b/src/core/arm/dyncom/arm_dyncom_trans.cpp @@ -23,9 +23,9 @@ static FORCE_INLINE void* AllocBuffer(size_t size) { #define glue(x, y) x ## y #define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s) -shtop_fp_t get_shifter_op(unsigned int inst); -get_addr_fp_t get_calc_addr_op(unsigned int inst); -get_addr_fp_t get_calc_addr_op_loadstoret(unsigned int inst); +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) { @@ -41,7 +41,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); if (inst_cream->Rd == 15) inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -62,7 +62,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); if (inst_cream->Rd == 15) inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -83,7 +83,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); if (inst_cream->Rd == 15) inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -126,7 +126,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); if (inst_cream->Rd == 15) inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -237,7 +237,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); return inst_base; } @@ -253,7 +253,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); return inst_base; } @@ -289,7 +289,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); if (inst_cream->Rd == 15) { inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -310,7 +310,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); if (inst_cream->Rd == 15) inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -336,7 +336,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); if (BIT(inst, 15)) { inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -368,7 +368,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); if (BITS(inst, 12, 15) == 15) inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -386,7 +386,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); if (BITS(inst, 12, 15) == 15) inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -435,7 +435,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); return inst_base; } @@ -449,7 +449,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op_loadstoret(inst); + inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); return inst_base; } @@ -463,7 +463,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); return inst_base; } @@ -503,7 +503,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); return inst_base; } @@ -517,7 +517,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); return inst_base; } @@ -531,7 +531,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); return inst_base; } @@ -545,7 +545,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op_loadstoret(inst); + inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); if (BITS(inst, 12, 15) == 15) { inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -618,7 +618,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); if (inst_cream->Rd == 15) { inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -706,7 +706,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); if (inst_cream->Rd == 15) { inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -728,7 +728,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); if (inst_cream->Rd == 15) inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -883,7 +883,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index) inst_base->br = TransExtData::INDIRECT_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); return inst_base; } @@ -902,7 +902,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); if (inst_cream->Rd == 15) inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -923,7 +923,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); if (inst_cream->Rd == 15) inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -982,7 +982,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); if (inst_cream->Rd == 15) inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -1292,7 +1292,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); return inst_base; } @@ -1349,7 +1349,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); return inst_base; } static ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index) @@ -1377,7 +1377,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); return inst_base; } @@ -1422,7 +1422,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); return inst_base; } @@ -1436,7 +1436,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op_loadstoret(inst); + inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); return inst_base; } @@ -1449,7 +1449,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){ inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); return inst_base; } @@ -1490,7 +1490,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op(inst); + inst_cream->get_addr = GetAddressingOp(inst); return inst_base; } @@ -1504,7 +1504,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index) inst_base->br = TransExtData::NON_BRANCH; inst_cream->inst = inst; - inst_cream->get_addr = get_calc_addr_op_loadstoret(inst); + inst_cream->get_addr = GetAddressingOpLoadStoreT(inst); return inst_base; } @@ -1522,7 +1522,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); if (inst_cream->Rd == 15) inst_base->br = TransExtData::INDIRECT_BRANCH; @@ -1635,7 +1635,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); return inst_base; } @@ -1653,7 +1653,7 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index) 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_shifter_op(inst); + inst_cream->shtop_func = GetShifterOp(inst); return inst_base; } From 0637dd93b5dedb505eaf9fcfa6c8e6d655a946a2 Mon Sep 17 00:00:00 2001 From: archshift Date: Fri, 10 Jun 2016 17:41:15 -0700 Subject: [PATCH 58/60] Revert "Split huge interpreter source file into translation info and interpreter (+ some tiny misc style fixes)" --- src/core/CMakeLists.txt | 2 - .../arm/dyncom/arm_dyncom_interpreter.cpp | 2725 ++++++++++++++++- src/core/arm/dyncom/arm_dyncom_trans.cpp | 2181 ------------- src/core/arm/dyncom/arm_dyncom_trans.h | 492 --- src/core/arm/skyeye_common/vfp/vfpinstr.cpp | 64 +- 5 files changed, 2730 insertions(+), 2734 deletions(-) delete mode 100644 src/core/arm/dyncom/arm_dyncom_trans.cpp delete mode 100644 src/core/arm/dyncom/arm_dyncom_trans.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index f356e4b48..e9b04098b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -5,7 +5,6 @@ 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 @@ -141,7 +140,6 @@ 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 diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 01d5d478e..cfc67287f 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -17,7 +17,6 @@ #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" @@ -25,6 +24,18 @@ #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) @@ -35,6 +46,8 @@ #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; @@ -232,6 +245,12 @@ 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) @@ -649,7 +668,479 @@ static void LnSWoUB(ScaledRegisterOffset)(ARMul_State* cpu, unsigned int inst, u virt_addr = addr; } -shtop_fp_t GetShifterOp(unsigned int inst) { +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) { if (BIT(inst, 25)) { return DPO(Immediate); } else if (BITS(inst, 4, 11) == 0) { @@ -674,7 +1165,7 @@ shtop_fp_t GetShifterOp(unsigned int inst) { return nullptr; } -get_addr_fp_t GetAddressingOp(unsigned int inst) { +static get_addr_fp_t get_calc_addr_op(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) { @@ -717,20 +1208,2200 @@ get_addr_fp_t GetAddressingOp(unsigned int inst) { return nullptr; } -// 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) { - return LnSWoUB(ImmediatePostIndexed); - } else if (BITS(inst, 25, 27) == 3) { - return LnSWoUB(ScaledRegisterPostIndexed); - } - // 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; +#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; + 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); + } 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 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; +} + +// 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, @@ -742,7 +3413,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 = arm_instruction_trans_len; + int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); u32 tinstr = GetThumbInstruction(inst, addr); switch ((tinstr & 0xF800) >> 11) { @@ -828,14 +3499,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; - TransExtData ret = TransExtData::NON_BRANCH; + int ret = NON_BRANCH; int size = 0; // instruction size of basic block - bb_start = trans_cache_buf_top; + bb_start = top; u32 phys_addr = addr; u32 pc_start = cpu->Reg[15]; - while (ret == TransExtData::NON_BRANCH) { + while (ret == NON_BRANCH) { unsigned int inst_size = InterpreterTranslateInstruction(cpu, phys_addr, inst_base); size++; @@ -843,7 +3514,7 @@ static int InterpreterTranslateBlock(ARMul_State* cpu, int& bb_start, u32 addr) phys_addr += inst_size; if ((phys_addr & 0xfff) == 0) { - inst_base->br = TransExtData::END_OF_PAGE; + inst_base->br = END_OF_PAGE; } ret = inst_base->br; }; @@ -857,15 +3528,15 @@ static int InterpreterTranslateSingle(ARMul_State* cpu, int& bb_start, u32 addr) MICROPROFILE_SCOPE(DynCom_Decode); ARM_INST_PTR inst_base = nullptr; - bb_start = trans_cache_buf_top; + bb_start = top; u32 phys_addr = addr; u32 pc_start = cpu->Reg[15]; InterpreterTranslateInstruction(cpu, phys_addr, inst_base); - if (inst_base->br == TransExtData::NON_BRANCH) { - inst_base->br = TransExtData::SINGLE_STEP; + if (inst_base->br == NON_BRANCH) { + inst_base->br = SINGLE_STEP; } cpu->instruction_cache[pc_start] = bb_start; @@ -910,8 +3581,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 != TransExtData::NON_BRANCH) goto DISPATCH; \ - inst_base = (arm_inst *)&trans_cache_buf[ptr] + #define FETCH_INST if (inst_base->br != NON_BRANCH) goto DISPATCH; \ + inst_base = (arm_inst *)&inst_buf[ptr] #define INC_PC(l) ptr += sizeof(arm_inst) + l #define INC_PC_STUB ptr += sizeof(arm_inst) @@ -1234,7 +3905,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { breakpoint_data = GDBStub::GetNextBreakpointFromAddress(cpu->Reg[15], GDBStub::BreakpointType::Execute); } - inst_base = (arm_inst *)&trans_cache_buf[ptr]; + inst_base = (arm_inst *)&inst_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 deleted file mode 100644 index 7f13ff836..000000000 --- a/src/core/arm/dyncom/arm_dyncom_trans.cpp +++ /dev/null @@ -1,2181 +0,0 @@ -#include - -#include "common/assert.h" -#include "common/common_funcs.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 FORCE_INLINE void* AllocBuffer(size_t size) { - size_t start = trans_cache_buf_top; - size_t end = trans_cache_buf_top + size; - ASSERT_MSG(end <= TRANS_CACHE_SIZE, "Translation cache is full!"); - return static_cast(&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; - // if (BITS(inst, 28, 31) <= 0xe) - // inst_base->br |= TransExtData::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 = 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 deleted file mode 100644 index 39d93d928..000000000 --- a/src/core/arm/dyncom/arm_dyncom_trans.h +++ /dev/null @@ -1,492 +0,0 @@ -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; -}; - -#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 1a98d0114..4f9083515 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = 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 = TransExtData::NON_BRANCH; + inst_base->br = NON_BRANCH; inst_cream->single = BIT(inst, 8) == 0; inst_cream->add = BIT(inst, 23); From a251b323a08ef55fa920d1e96e5bbe7c12134ab7 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 11 Jun 2016 02:19:51 +0100 Subject: [PATCH 59/60] SDL2: Add forgotten default config changes from 7129611e65096ba2cbe8266f6cb068a9b18981d8. --- src/citra/default_ini.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h index 49126356f..1164eda89 100644 --- a/src/citra/default_ini.h +++ b/src/citra/default_ini.h @@ -66,7 +66,11 @@ output_engine = # 1 (default): Yes, 0: No use_virtual_sd = -[System Region] +[System] +# The system model that Citra will try to emulate +# 0: Old 3DS (default), 1: New 3DS +is_new_3ds = + # The system region that Citra will use during emulation # 0: Japan, 1: USA (default), 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan region_value = From 43183db51f5aee430750fc4e208e58d3443976c9 Mon Sep 17 00:00:00 2001 From: wwylele Date: Sat, 11 Jun 2016 07:59:38 +0300 Subject: [PATCH 60/60] hid: add missing header --- src/core/hle/service/hid/hid.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index c975433f4..cdec11388 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include + #include "common/logging/log.h" #include "common/emu_window.h"