summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/citra/CMakeLists.txt14
-rw-r--r--src/citra/citra.cpp2
-rw-r--r--src/citra/config.cpp5
-rw-r--r--src/citra/config.h2
-rw-r--r--src/citra/default_ini.h5
-rw-r--r--src/citra/emu_window/emu_window_glfw.cpp2
-rw-r--r--src/citra/emu_window/emu_window_glfw.h2
-rw-r--r--src/citra_qt/CMakeLists.txt4
-rw-r--r--src/citra_qt/config.cpp6
-rw-r--r--src/citra_qt/config.h2
-rw-r--r--src/citra_qt/debugger/callstack.cpp4
-rw-r--r--src/citra_qt/debugger/disassembler.cpp4
-rw-r--r--src/citra_qt/debugger/graphics.cpp2
-rw-r--r--src/citra_qt/debugger/graphics.hxx2
-rw-r--r--src/citra_qt/debugger/graphics_breakpoints.cpp16
-rw-r--r--src/citra_qt/debugger/graphics_breakpoints.hxx2
-rw-r--r--src/citra_qt/debugger/graphics_breakpoints_p.hxx2
-rw-r--r--src/citra_qt/debugger/graphics_cmdlists.cpp58
-rw-r--r--src/citra_qt/debugger/graphics_cmdlists.hxx2
-rw-r--r--src/citra_qt/debugger/graphics_framebuffer.cpp25
-rw-r--r--src/citra_qt/debugger/graphics_framebuffer.hxx2
-rw-r--r--src/citra_qt/main.cpp9
-rw-r--r--src/citra_qt/util/spinbox.cpp4
-rw-r--r--src/citra_qt/util/spinbox.hxx2
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/bit_field.h14
-rw-r--r--src/common/break_points.cpp4
-rw-r--r--src/common/break_points.h4
-rw-r--r--src/common/common.h4
-rw-r--r--src/common/common_funcs.h4
-rw-r--r--src/common/common_paths.h6
-rw-r--r--src/common/concurrent_ring_buffer.h2
-rw-r--r--src/common/cpu_detect.h4
-rw-r--r--src/common/emu_window.cpp2
-rw-r--r--src/common/emu_window.h2
-rw-r--r--src/common/file_search.cpp4
-rw-r--r--src/common/file_search.h4
-rw-r--r--src/common/file_util.cpp8
-rw-r--r--src/common/file_util.h6
-rw-r--r--src/common/hash.cpp4
-rw-r--r--src/common/hash.h4
-rw-r--r--src/common/key_map.cpp2
-rw-r--r--src/common/key_map.h2
-rw-r--r--src/common/linear_disk_cache.h4
-rw-r--r--src/common/log.h4
-rw-r--r--src/common/logging/backend.cpp2
-rw-r--r--src/common/logging/backend.h2
-rw-r--r--src/common/logging/filter.cpp2
-rw-r--r--src/common/logging/filter.h2
-rw-r--r--src/common/logging/log.h2
-rw-r--r--src/common/logging/text_formatter.cpp38
-rw-r--r--src/common/logging/text_formatter.h4
-rw-r--r--src/common/make_unique.h16
-rw-r--r--src/common/math_util.cpp4
-rw-r--r--src/common/math_util.h4
-rw-r--r--src/common/memory_util.cpp4
-rw-r--r--src/common/memory_util.h4
-rw-r--r--src/common/misc.cpp4
-rw-r--r--src/common/msg_handler.cpp4
-rw-r--r--src/common/msg_handler.h4
-rw-r--r--src/common/scm_rev.h2
-rw-r--r--src/common/scope_exit.h2
-rw-r--r--src/common/string_util.cpp4
-rw-r--r--src/common/string_util.h4
-rw-r--r--src/common/symbols.cpp2
-rw-r--r--src/common/symbols.h2
-rw-r--r--src/common/thread.cpp4
-rw-r--r--src/common/thread.h4
-rw-r--r--src/common/thread_queue_list.h2
-rw-r--r--src/common/thunk.h4
-rw-r--r--src/common/timer.cpp4
-rw-r--r--src/common/timer.h4
-rw-r--r--src/core/CMakeLists.txt53
-rw-r--r--src/core/arm/arm_interface.h8
-rw-r--r--src/core/arm/disassembler/load_symbol_map.cpp2
-rw-r--r--src/core/arm/disassembler/load_symbol_map.h2
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp51
-rw-r--r--src/core/arm/dyncom/arm_dyncom.h16
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.cpp817
-rw-r--r--src/core/arm/dyncom/arm_dyncom_dec.h2
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp10832
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.h2
-rw-r--r--src/core/arm/dyncom/arm_dyncom_run.cpp46
-rw-r--r--src/core/arm/dyncom/arm_dyncom_thumb.cpp863
-rw-r--r--src/core/arm/interpreter/arm_interpreter.cpp53
-rw-r--r--src/core/arm/interpreter/arm_interpreter.h8
-rw-r--r--src/core/arm/interpreter/armemu.cpp1408
-rw-r--r--src/core/arm/interpreter/armsupp.cpp123
-rw-r--r--src/core/arm/skyeye_common/armdefs.h489
-rw-r--r--src/core/arm/skyeye_common/armemu.h8
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.cpp663
-rw-r--r--src/core/arm/skyeye_common/vfp/vfp.h6
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp1957
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp14
-rw-r--r--src/core/core.cpp2
-rw-r--r--src/core/core.h2
-rw-r--r--src/core/core_timing.cpp4
-rw-r--r--src/core/core_timing.h4
-rw-r--r--src/core/file_sys/archive.h268
-rw-r--r--src/core/file_sys/archive_backend.h243
-rw-r--r--src/core/file_sys/archive_romfs.cpp97
-rw-r--r--src/core/file_sys/archive_romfs.h65
-rw-r--r--src/core/file_sys/archive_savedata.cpp33
-rw-r--r--src/core/file_sys/archive_savedata.h31
-rw-r--r--src/core/file_sys/archive_sdmc.cpp126
-rw-r--r--src/core/file_sys/archive_sdmc.h104
-rw-r--r--src/core/file_sys/archive_systemsavedata.cpp39
-rw-r--r--src/core/file_sys/archive_systemsavedata.h33
-rw-r--r--src/core/file_sys/directory_backend.h (renamed from src/core/file_sys/directory.h)8
-rw-r--r--src/core/file_sys/directory_romfs.cpp12
-rw-r--r--src/core/file_sys/directory_romfs.h6
-rw-r--r--src/core/file_sys/directory_sdmc.cpp88
-rw-r--r--src/core/file_sys/directory_sdmc.h55
-rw-r--r--src/core/file_sys/disk_archive.cpp188
-rw-r--r--src/core/file_sys/disk_archive.h103
-rw-r--r--src/core/file_sys/file_backend.h (renamed from src/core/file_sys/file.h)13
-rw-r--r--src/core/file_sys/file_romfs.cpp53
-rw-r--r--src/core/file_sys/file_romfs.h16
-rw-r--r--src/core/file_sys/file_sdmc.cpp110
-rw-r--r--src/core/file_sys/file_sdmc.h75
-rw-r--r--src/core/hle/config_mem.cpp2
-rw-r--r--src/core/hle/config_mem.h2
-rw-r--r--src/core/hle/coprocessor.cpp2
-rw-r--r--src/core/hle/function_wrappers.h16
-rw-r--r--src/core/hle/hle.cpp16
-rw-r--r--src/core/hle/hle.h2
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp9
-rw-r--r--src/core/hle/kernel/address_arbiter.h2
-rw-r--r--src/core/hle/kernel/archive.cpp435
-rw-r--r--src/core/hle/kernel/event.cpp17
-rw-r--r--src/core/hle/kernel/event.h2
-rw-r--r--src/core/hle/kernel/kernel.cpp134
-rw-r--r--src/core/hle/kernel/kernel.h212
-rw-r--r--src/core/hle/kernel/mutex.cpp13
-rw-r--r--src/core/hle/kernel/mutex.h2
-rw-r--r--src/core/hle/kernel/semaphore.cpp95
-rw-r--r--src/core/hle/kernel/semaphore.h32
-rw-r--r--src/core/hle/kernel/session.h58
-rw-r--r--src/core/hle/kernel/shared_memory.cpp13
-rw-r--r--src/core/hle/kernel/shared_memory.h16
-rw-r--r--src/core/hle/kernel/thread.cpp83
-rw-r--r--src/core/hle/kernel/thread.h3
-rw-r--r--src/core/hle/result.h4
-rw-r--r--src/core/hle/service/ac_u.cpp7
-rw-r--r--src/core/hle/service/ac_u.h8
-rw-r--r--src/core/hle/service/act_u.cpp24
-rw-r--r--src/core/hle/service/act_u.h23
-rw-r--r--src/core/hle/service/am_app.cpp24
-rw-r--r--src/core/hle/service/am_app.h23
-rw-r--r--src/core/hle/service/am_net.cpp5
-rw-r--r--src/core/hle/service/am_net.h8
-rw-r--r--src/core/hle/service/apt_a.cpp34
-rw-r--r--src/core/hle/service/apt_a.h23
-rw-r--r--src/core/hle/service/apt_u.cpp25
-rw-r--r--src/core/hle/service/apt_u.h9
-rw-r--r--src/core/hle/service/boss_u.cpp21
-rw-r--r--src/core/hle/service/boss_u.h22
-rw-r--r--src/core/hle/service/cecd_u.cpp24
-rw-r--r--src/core/hle/service/cecd_u.h23
-rw-r--r--src/core/hle/service/cfg/cfg.cpp202
-rw-r--r--src/core/hle/service/cfg/cfg.h144
-rw-r--r--src/core/hle/service/cfg/cfg_i.cpp110
-rw-r--r--src/core/hle/service/cfg/cfg_i.h (renamed from src/core/hle/service/cfg_i.h)8
-rw-r--r--src/core/hle/service/cfg/cfg_u.cpp (renamed from src/core/hle/service/cfg_u.cpp)88
-rw-r--r--src/core/hle/service/cfg/cfg_u.h (renamed from src/core/hle/service/cfg_u.h)8
-rw-r--r--src/core/hle/service/cfg_i.cpp59
-rw-r--r--src/core/hle/service/csnd_snd.cpp5
-rw-r--r--src/core/hle/service/csnd_snd.h8
-rw-r--r--src/core/hle/service/dsp_dsp.cpp17
-rw-r--r--src/core/hle/service/dsp_dsp.h8
-rw-r--r--src/core/hle/service/err_f.cpp20
-rw-r--r--src/core/hle/service/err_f.h22
-rw-r--r--src/core/hle/service/frd_u.cpp36
-rw-r--r--src/core/hle/service/frd_u.h22
-rw-r--r--src/core/hle/service/fs/archive.cpp442
-rw-r--r--src/core/hle/service/fs/archive.h (renamed from src/core/hle/kernel/archive.h)65
-rw-r--r--src/core/hle/service/fs/fs_user.cpp (renamed from src/core/hle/service/fs_user.cpp)274
-rw-r--r--src/core/hle/service/fs/fs_user.h (renamed from src/core/hle/service/fs_user.h)19
-rw-r--r--src/core/hle/service/gsp_gpu.cpp41
-rw-r--r--src/core/hle/service/gsp_gpu.h10
-rw-r--r--src/core/hle/service/hid_user.cpp8
-rw-r--r--src/core/hle/service/hid_user.h10
-rw-r--r--src/core/hle/service/http_c.cpp64
-rw-r--r--src/core/hle/service/http_c.h23
-rw-r--r--src/core/hle/service/ir_rst.cpp5
-rw-r--r--src/core/hle/service/ir_rst.h10
-rw-r--r--src/core/hle/service/ir_u.cpp5
-rw-r--r--src/core/hle/service/ir_u.h8
-rw-r--r--src/core/hle/service/ldr_ro.cpp29
-rw-r--r--src/core/hle/service/ldr_ro.h23
-rw-r--r--src/core/hle/service/mic_u.cpp5
-rw-r--r--src/core/hle/service/mic_u.h8
-rw-r--r--src/core/hle/service/ndm_u.cpp5
-rw-r--r--src/core/hle/service/ndm_u.h10
-rw-r--r--src/core/hle/service/news_u.cpp25
-rw-r--r--src/core/hle/service/news_u.h23
-rw-r--r--src/core/hle/service/nim_aoc.cpp31
-rw-r--r--src/core/hle/service/nim_aoc.h23
-rw-r--r--src/core/hle/service/nwm_uds.cpp5
-rw-r--r--src/core/hle/service/nwm_uds.h8
-rw-r--r--src/core/hle/service/pm_app.cpp5
-rw-r--r--src/core/hle/service/pm_app.h8
-rw-r--r--src/core/hle/service/ptm_u.cpp13
-rw-r--r--src/core/hle/service/ptm_u.h8
-rw-r--r--src/core/hle/service/service.cpp31
-rw-r--r--src/core/hle/service/service.h33
-rw-r--r--src/core/hle/service/soc_u.cpp5
-rw-r--r--src/core/hle/service/soc_u.h8
-rw-r--r--src/core/hle/service/srv.cpp11
-rw-r--r--src/core/hle/service/srv.h11
-rw-r--r--src/core/hle/service/ssl_c.cpp5
-rw-r--r--src/core/hle/service/ssl_c.h10
-rw-r--r--src/core/hle/svc.cpp68
-rw-r--r--src/core/hle/svc.h2
-rw-r--r--src/core/hw/gpu.cpp73
-rw-r--r--src/core/hw/gpu.h3
-rw-r--r--src/core/hw/hw.cpp2
-rw-r--r--src/core/hw/hw.h2
-rw-r--r--src/core/loader/3dsx.cpp8
-rw-r--r--src/core/loader/3dsx.h2
-rw-r--r--src/core/loader/elf.cpp4
-rw-r--r--src/core/loader/elf.h4
-rw-r--r--src/core/loader/loader.cpp11
-rw-r--r--src/core/loader/loader.h2
-rw-r--r--src/core/loader/ncch.cpp6
-rw-r--r--src/core/loader/ncch.h8
-rw-r--r--src/core/mem_map.cpp4
-rw-r--r--src/core/mem_map.h2
-rw-r--r--src/core/mem_map_funcs.cpp2
-rw-r--r--src/core/settings.cpp2
-rw-r--r--src/core/settings.h3
-rw-r--r--src/core/system.cpp14
-rw-r--r--src/core/system.h2
-rw-r--r--src/video_core/clipper.cpp79
-rw-r--r--src/video_core/clipper.h2
-rw-r--r--src/video_core/command_processor.cpp40
-rw-r--r--src/video_core/command_processor.h2
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp272
-rw-r--r--src/video_core/debug_utils/debug_utils.h15
-rw-r--r--src/video_core/gpu_debugger.h4
-rw-r--r--src/video_core/math.h2
-rw-r--r--src/video_core/pica.h144
-rw-r--r--src/video_core/primitive_assembly.cpp25
-rw-r--r--src/video_core/primitive_assembly.h3
-rw-r--r--src/video_core/rasterizer.cpp192
-rw-r--r--src/video_core/rasterizer.h2
-rw-r--r--src/video_core/renderer_base.h2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_util.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_util.h2
-rw-r--r--src/video_core/renderer_opengl/gl_shaders.h2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp6
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h2
-rw-r--r--src/video_core/utils.cpp2
-rw-r--r--src/video_core/utils.h2
-rw-r--r--src/video_core/vertex_shader.cpp344
-rw-r--r--src/video_core/vertex_shader.h225
-rw-r--r--src/video_core/video_core.cpp2
-rw-r--r--src/video_core/video_core.h2
258 files changed, 12670 insertions, 12088 deletions
diff --git a/src/citra/CMakeLists.txt b/src/citra/CMakeLists.txt
index f2add394f..b06259f5e 100644
--- a/src/citra/CMakeLists.txt
+++ b/src/citra/CMakeLists.txt
@@ -12,22 +12,20 @@ set(HEADERS
12 12
13create_directory_groups(${SRCS} ${HEADERS}) 13create_directory_groups(${SRCS} ${HEADERS})
14 14
15# NOTE: This is a workaround for CMake bug 0006976 (missing X11_xf86vmode_LIB variable)
16if (NOT X11_xf86vmode_LIB)
17 set(X11_xv86vmode_LIB Xxf86vm)
18endif()
19
20add_executable(citra ${SRCS} ${HEADERS}) 15add_executable(citra ${SRCS} ${HEADERS})
21target_link_libraries(citra core common video_core) 16target_link_libraries(citra core common video_core)
22target_link_libraries(citra ${OPENGL_gl_LIBRARY} ${GLFW_LIBRARIES} inih) 17target_link_libraries(citra ${OPENGL_gl_LIBRARY} ${GLFW_LIBRARIES} inih)
23 18
19if (UNIX)
20 target_link_libraries(citra -pthread)
21endif()
22
24if (APPLE) 23if (APPLE)
25 target_link_libraries(citra iconv pthread ${COREFOUNDATION_LIBRARY}) 24 target_link_libraries(citra iconv ${COREFOUNDATION_LIBRARY})
26elseif (WIN32) 25elseif (WIN32)
27 target_link_libraries(citra winmm) 26 target_link_libraries(citra winmm)
28else() # Unix 27else() # Unix
29 target_link_libraries(citra pthread rt) 28 target_link_libraries(citra rt)
30 target_link_libraries(citra ${X11_X11_LIB} ${X11_Xi_LIB} ${X11_Xcursor_LIB} ${X11_Xrandr_LIB} ${X11_xv86vmode_LIB})
31endif() 29endif()
32 30
33#install(TARGETS citra RUNTIME DESTINATION ${bindir}) 31#install(TARGETS citra RUNTIME DESTINATION ${bindir})
diff --git a/src/citra/citra.cpp b/src/citra/citra.cpp
index d6e8a4ec7..f6a52758b 100644
--- a/src/citra/citra.cpp
+++ b/src/citra/citra.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <thread> 5#include <thread>
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index 92764809e..2bf0dff35 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <GLFW/glfw3.h> 5#include <GLFW/glfw3.h>
@@ -58,7 +58,8 @@ void Config::ReadValues() {
58 58
59 // Core 59 // Core
60 Settings::values.cpu_core = glfw_config->GetInteger("Core", "cpu_core", Core::CPU_Interpreter); 60 Settings::values.cpu_core = glfw_config->GetInteger("Core", "cpu_core", Core::CPU_Interpreter);
61 Settings::values.gpu_refresh_rate = glfw_config->GetInteger("Core", "gpu_refresh_rate", 60); 61 Settings::values.gpu_refresh_rate = glfw_config->GetInteger("Core", "gpu_refresh_rate", 30);
62 Settings::values.frame_skip = glfw_config->GetInteger("Core", "frame_skip", 0);
62 63
63 // Data Storage 64 // Data Storage
64 Settings::values.use_virtual_sd = glfw_config->GetBoolean("Data Storage", "use_virtual_sd", true); 65 Settings::values.use_virtual_sd = glfw_config->GetBoolean("Data Storage", "use_virtual_sd", true);
diff --git a/src/citra/config.h b/src/citra/config.h
index 2b46fa8aa..0eb176c7d 100644
--- a/src/citra/config.h
+++ b/src/citra/config.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h
index 7cf543e07..f41020f7b 100644
--- a/src/citra/default_ini.h
+++ b/src/citra/default_ini.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -28,7 +28,8 @@ pad_sright =
28 28
29[Core] 29[Core]
30cpu_core = ## 0: Interpreter (default), 1: FastInterpreter (experimental) 30cpu_core = ## 0: Interpreter (default), 1: FastInterpreter (experimental)
31gpu_refresh_rate = ## 60 (default) 31gpu_refresh_rate = ## 30 (default)
32frame_skip = ## 0: No frameskip (default), 1 : 2x frameskip, 2 : 4x frameskip, etc.
32 33
33[Data Storage] 34[Data Storage]
34use_virtual_sd = 35use_virtual_sd =
diff --git a/src/citra/emu_window/emu_window_glfw.cpp b/src/citra/emu_window/emu_window_glfw.cpp
index 929e09f43..a6282809b 100644
--- a/src/citra/emu_window/emu_window_glfw.cpp
+++ b/src/citra/emu_window/emu_window_glfw.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <GLFW/glfw3.h> 5#include <GLFW/glfw3.h>
diff --git a/src/citra/emu_window/emu_window_glfw.h b/src/citra/emu_window/emu_window_glfw.h
index 5b04e87bb..5252fccc8 100644
--- a/src/citra/emu_window/emu_window_glfw.h
+++ b/src/citra/emu_window/emu_window_glfw.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt
index 90e5c6aa6..54d0a1271 100644
--- a/src/citra_qt/CMakeLists.txt
+++ b/src/citra_qt/CMakeLists.txt
@@ -60,6 +60,10 @@ add_executable(citra-qt ${SRCS} ${HEADERS} ${UI_HDRS})
60target_link_libraries(citra-qt core common video_core qhexedit) 60target_link_libraries(citra-qt core common video_core qhexedit)
61target_link_libraries(citra-qt ${OPENGL_gl_LIBRARY} ${CITRA_QT_LIBS}) 61target_link_libraries(citra-qt ${OPENGL_gl_LIBRARY} ${CITRA_QT_LIBS})
62 62
63if (UNIX)
64 target_link_libraries(citra-qt -pthread)
65endif()
66
63if (APPLE) 67if (APPLE)
64 target_link_libraries(citra-qt iconv ${COREFOUNDATION_LIBRARY}) 68 target_link_libraries(citra-qt iconv ${COREFOUNDATION_LIBRARY})
65elseif (WIN32) 69elseif (WIN32)
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index 0ae6b8b2d..1596c08d7 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <QString> 5#include <QString>
@@ -44,7 +44,8 @@ void Config::ReadValues() {
44 44
45 qt_config->beginGroup("Core"); 45 qt_config->beginGroup("Core");
46 Settings::values.cpu_core = qt_config->value("cpu_core", Core::CPU_Interpreter).toInt(); 46 Settings::values.cpu_core = qt_config->value("cpu_core", Core::CPU_Interpreter).toInt();
47 Settings::values.gpu_refresh_rate = qt_config->value("gpu_refresh_rate", 60).toInt(); 47 Settings::values.gpu_refresh_rate = qt_config->value("gpu_refresh_rate", 30).toInt();
48 Settings::values.frame_skip = qt_config->value("frame_skip", 0).toInt();
48 qt_config->endGroup(); 49 qt_config->endGroup();
49 50
50 qt_config->beginGroup("Data Storage"); 51 qt_config->beginGroup("Data Storage");
@@ -80,6 +81,7 @@ void Config::SaveValues() {
80 qt_config->beginGroup("Core"); 81 qt_config->beginGroup("Core");
81 qt_config->setValue("cpu_core", Settings::values.cpu_core); 82 qt_config->setValue("cpu_core", Settings::values.cpu_core);
82 qt_config->setValue("gpu_refresh_rate", Settings::values.gpu_refresh_rate); 83 qt_config->setValue("gpu_refresh_rate", Settings::values.gpu_refresh_rate);
84 qt_config->setValue("frame_skip", Settings::values.frame_skip);
83 qt_config->endGroup(); 85 qt_config->endGroup();
84 86
85 qt_config->beginGroup("Data Storage"); 87 qt_config->beginGroup("Data Storage");
diff --git a/src/citra_qt/config.h b/src/citra_qt/config.h
index 4c95d0cb9..4485cae73 100644
--- a/src/citra_qt/config.h
+++ b/src/citra_qt/config.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp
index 895851be3..a9ec2f7fe 100644
--- a/src/citra_qt/debugger/callstack.cpp
+++ b/src/citra_qt/debugger/callstack.cpp
@@ -27,10 +27,10 @@ void CallstackWidget::OnCPUStepped()
27 ARM_Interface* app_core = Core::g_app_core; 27 ARM_Interface* app_core = Core::g_app_core;
28 28
29 u32 sp = app_core->GetReg(13); //stack pointer 29 u32 sp = app_core->GetReg(13); //stack pointer
30 u32 addr, ret_addr, call_addr, func_addr; 30 u32 ret_addr, call_addr, func_addr;
31 31
32 int counter = 0; 32 int counter = 0;
33 for (int addr = 0x10000000; addr >= sp; addr -= 4) 33 for (u32 addr = 0x10000000; addr >= sp; addr -= 4)
34 { 34 {
35 ret_addr = Memory::Read32(addr); 35 ret_addr = Memory::Read32(addr);
36 call_addr = ret_addr - 4; //get call address??? 36 call_addr = ret_addr - 4; //get call address???
diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp
index 2ee877743..14745f3bb 100644
--- a/src/citra_qt/debugger/disassembler.cpp
+++ b/src/citra_qt/debugger/disassembler.cpp
@@ -220,7 +220,9 @@ void DisassemblerWidget::OnPause()
220 emu_thread.SetCpuRunning(false); 220 emu_thread.SetCpuRunning(false);
221 221
222 // TODO: By now, the CPU might not have actually stopped... 222 // TODO: By now, the CPU might not have actually stopped...
223 model->SetNextInstruction(Core::g_app_core->GetPC()); 223 if (Core::g_app_core) {
224 model->SetNextInstruction(Core::g_app_core->GetPC());
225 }
224} 226}
225 227
226void DisassemblerWidget::OnToggleStartStop() 228void DisassemblerWidget::OnToggleStartStop()
diff --git a/src/citra_qt/debugger/graphics.cpp b/src/citra_qt/debugger/graphics.cpp
index a86a55404..6ff4c290d 100644
--- a/src/citra_qt/debugger/graphics.cpp
+++ b/src/citra_qt/debugger/graphics.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "graphics.hxx" 5#include "graphics.hxx"
diff --git a/src/citra_qt/debugger/graphics.hxx b/src/citra_qt/debugger/graphics.hxx
index 72656f93c..8119b4c87 100644
--- a/src/citra_qt/debugger/graphics.hxx
+++ b/src/citra_qt/debugger/graphics.hxx
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp
index 53394b6e6..9486f06cc 100644
--- a/src/citra_qt/debugger/graphics_breakpoints.cpp
+++ b/src/citra_qt/debugger/graphics_breakpoints.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <QMetaType> 5#include <QMetaType>
@@ -39,15 +39,17 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const
39 switch (index.column()) { 39 switch (index.column()) {
40 case 0: 40 case 0:
41 { 41 {
42 std::map<Pica::DebugContext::Event, QString> map; 42 static const std::map<Pica::DebugContext::Event, QString> map = {
43 map.insert({Pica::DebugContext::Event::CommandLoaded, tr("Pica command loaded")}); 43 { Pica::DebugContext::Event::CommandLoaded, tr("Pica command loaded") },
44 map.insert({Pica::DebugContext::Event::CommandProcessed, tr("Pica command processed")}); 44 { Pica::DebugContext::Event::CommandProcessed, tr("Pica command processed") },
45 map.insert({Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch")}); 45 { Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch") },
46 map.insert({Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch")}); 46 { Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch") },
47 { Pica::DebugContext::Event::VertexLoaded, tr("Vertex Loaded") }
48 };
47 49
48 _dbg_assert_(Debug_GPU, map.size() == static_cast<size_t>(Pica::DebugContext::Event::NumEvents)); 50 _dbg_assert_(Debug_GPU, map.size() == static_cast<size_t>(Pica::DebugContext::Event::NumEvents));
49 51
50 return map[event]; 52 return (map.find(event) != map.end()) ? map.at(event) : QString();
51 } 53 }
52 54
53 case 1: 55 case 1:
diff --git a/src/citra_qt/debugger/graphics_breakpoints.hxx b/src/citra_qt/debugger/graphics_breakpoints.hxx
index 2142c6fa1..5b9ba324e 100644
--- a/src/citra_qt/debugger/graphics_breakpoints.hxx
+++ b/src/citra_qt/debugger/graphics_breakpoints.hxx
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/citra_qt/debugger/graphics_breakpoints_p.hxx b/src/citra_qt/debugger/graphics_breakpoints_p.hxx
index bf5daf73d..232bfc863 100644
--- a/src/citra_qt/debugger/graphics_breakpoints_p.hxx
+++ b/src/citra_qt/debugger/graphics_breakpoints_p.hxx
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp
index 7f97cf143..753cc25da 100644
--- a/src/citra_qt/debugger/graphics_cmdlists.cpp
+++ b/src/citra_qt/debugger/graphics_cmdlists.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <QLabel> 5#include <QLabel>
@@ -24,7 +24,7 @@ QImage LoadTexture(u8* src, const Pica::DebugUtils::TextureInfo& info) {
24 QImage decoded_image(info.width, info.height, QImage::Format_ARGB32); 24 QImage decoded_image(info.width, info.height, QImage::Format_ARGB32);
25 for (int y = 0; y < info.height; ++y) { 25 for (int y = 0; y < info.height; ++y) {
26 for (int x = 0; x < info.width; ++x) { 26 for (int x = 0; x < info.width; ++x) {
27 Math::Vec4<u8> color = Pica::DebugUtils::LookupTexture(src, x, y, info); 27 Math::Vec4<u8> color = Pica::DebugUtils::LookupTexture(src, x, y, info, true);
28 decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), color.a())); 28 decoded_image.setPixel(x, y, qRgba(color.r(), color.g(), color.b(), color.a()));
29 } 29 }
30 } 30 }
@@ -47,7 +47,7 @@ public:
47}; 47};
48 48
49TextureInfoDockWidget::TextureInfoDockWidget(const Pica::DebugUtils::TextureInfo& info, QWidget* parent) 49TextureInfoDockWidget::TextureInfoDockWidget(const Pica::DebugUtils::TextureInfo& info, QWidget* parent)
50 : QDockWidget(tr("Texture 0x%1").arg(info.address, 8, 16, QLatin1Char('0'))), 50 : QDockWidget(tr("Texture 0x%1").arg(info.physical_address, 8, 16, QLatin1Char('0'))),
51 info(info) { 51 info(info) {
52 52
53 QWidget* main_widget = new QWidget; 53 QWidget* main_widget = new QWidget;
@@ -60,7 +60,7 @@ TextureInfoDockWidget::TextureInfoDockWidget(const Pica::DebugUtils::TextureInfo
60 phys_address_spinbox->SetBase(16); 60 phys_address_spinbox->SetBase(16);
61 phys_address_spinbox->SetRange(0, 0xFFFFFFFF); 61 phys_address_spinbox->SetRange(0, 0xFFFFFFFF);
62 phys_address_spinbox->SetPrefix("0x"); 62 phys_address_spinbox->SetPrefix("0x");
63 phys_address_spinbox->SetValue(info.address); 63 phys_address_spinbox->SetValue(info.physical_address);
64 connect(phys_address_spinbox, SIGNAL(ValueChanged(qint64)), this, SLOT(OnAddressChanged(qint64))); 64 connect(phys_address_spinbox, SIGNAL(ValueChanged(qint64)), this, SLOT(OnAddressChanged(qint64)));
65 65
66 QComboBox* format_choice = new QComboBox; 66 QComboBox* format_choice = new QComboBox;
@@ -69,6 +69,13 @@ TextureInfoDockWidget::TextureInfoDockWidget(const Pica::DebugUtils::TextureInfo
69 format_choice->addItem(tr("RGBA5551")); 69 format_choice->addItem(tr("RGBA5551"));
70 format_choice->addItem(tr("RGB565")); 70 format_choice->addItem(tr("RGB565"));
71 format_choice->addItem(tr("RGBA4")); 71 format_choice->addItem(tr("RGBA4"));
72 format_choice->addItem(tr("IA8"));
73 format_choice->addItem(tr("UNK6"));
74 format_choice->addItem(tr("I8"));
75 format_choice->addItem(tr("A8"));
76 format_choice->addItem(tr("IA4"));
77 format_choice->addItem(tr("UNK10"));
78 format_choice->addItem(tr("A4"));
72 format_choice->setCurrentIndex(static_cast<int>(info.format)); 79 format_choice->setCurrentIndex(static_cast<int>(info.format));
73 connect(format_choice, SIGNAL(currentIndexChanged(int)), this, SLOT(OnFormatChanged(int))); 80 connect(format_choice, SIGNAL(currentIndexChanged(int)), this, SLOT(OnFormatChanged(int)));
74 81
@@ -125,7 +132,7 @@ TextureInfoDockWidget::TextureInfoDockWidget(const Pica::DebugUtils::TextureInfo
125} 132}
126 133
127void TextureInfoDockWidget::OnAddressChanged(qint64 value) { 134void TextureInfoDockWidget::OnAddressChanged(qint64 value) {
128 info.address = value; 135 info.physical_address = value;
129 emit UpdatePixmap(ReloadPixmap()); 136 emit UpdatePixmap(ReloadPixmap());
130} 137}
131 138
@@ -150,7 +157,7 @@ void TextureInfoDockWidget::OnStrideChanged(int value) {
150} 157}
151 158
152QPixmap TextureInfoDockWidget::ReloadPixmap() const { 159QPixmap TextureInfoDockWidget::ReloadPixmap() const {
153 u8* src = Memory::GetPointer(info.address); 160 u8* src = Memory::GetPointer(Pica::PAddrToVAddr(info.physical_address));
154 return QPixmap::fromImage(LoadTexture(src, info)); 161 return QPixmap::fromImage(LoadTexture(src, info));
155} 162}
156 163
@@ -223,9 +230,21 @@ void GPUCommandListModel::OnPicaTraceFinished(const Pica::DebugUtils::PicaTrace&
223 230
224void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) { 231void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) {
225 const int command_id = list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toInt(); 232 const int command_id = list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toInt();
226 if (COMMAND_IN_RANGE(command_id, texture0)) { 233 if (COMMAND_IN_RANGE(command_id, texture0) ||
227 auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(Pica::registers.texture0, 234 COMMAND_IN_RANGE(command_id, texture1) ||
228 Pica::registers.texture0_format); 235 COMMAND_IN_RANGE(command_id, texture2)) {
236
237 unsigned index;
238 if (COMMAND_IN_RANGE(command_id, texture0)) {
239 index = 0;
240 } else if (COMMAND_IN_RANGE(command_id, texture1)) {
241 index = 1;
242 } else {
243 index = 2;
244 }
245 auto config = Pica::registers.GetTextures()[index].config;
246 auto format = Pica::registers.GetTextures()[index].format;
247 auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config, format);
229 248
230 // TODO: Instead, emit a signal here to be caught by the main window widget. 249 // TODO: Instead, emit a signal here to be caught by the main window widget.
231 auto main_window = static_cast<QMainWindow*>(parent()); 250 auto main_window = static_cast<QMainWindow*>(parent());
@@ -237,10 +256,23 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
237 QWidget* new_info_widget; 256 QWidget* new_info_widget;
238 257
239 const int command_id = list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toInt(); 258 const int command_id = list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toInt();
240 if (COMMAND_IN_RANGE(command_id, texture0)) { 259 if (COMMAND_IN_RANGE(command_id, texture0) ||
241 u8* src = Memory::GetPointer(Pica::registers.texture0.GetPhysicalAddress()); 260 COMMAND_IN_RANGE(command_id, texture1) ||
242 auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(Pica::registers.texture0, 261 COMMAND_IN_RANGE(command_id, texture2)) {
243 Pica::registers.texture0_format); 262
263 unsigned index;
264 if (COMMAND_IN_RANGE(command_id, texture0)) {
265 index = 0;
266 } else if (COMMAND_IN_RANGE(command_id, texture1)) {
267 index = 1;
268 } else {
269 index = 2;
270 }
271 auto config = Pica::registers.GetTextures()[index].config;
272 auto format = Pica::registers.GetTextures()[index].format;
273
274 auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config, format);
275 u8* src = Memory::GetPointer(Pica::PAddrToVAddr(config.GetPhysicalAddress()));
244 new_info_widget = new TextureInfoWidget(src, info); 276 new_info_widget = new TextureInfoWidget(src, info);
245 } else { 277 } else {
246 new_info_widget = new QWidget; 278 new_info_widget = new QWidget;
diff --git a/src/citra_qt/debugger/graphics_cmdlists.hxx b/src/citra_qt/debugger/graphics_cmdlists.hxx
index a459bba64..a465d044c 100644
--- a/src/citra_qt/debugger/graphics_cmdlists.hxx
+++ b/src/citra_qt/debugger/graphics_cmdlists.hxx
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp
index ac47f298d..dd41c3880 100644
--- a/src/citra_qt/debugger/graphics_framebuffer.cpp
+++ b/src/citra_qt/debugger/graphics_framebuffer.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <QBoxLayout> 5#include <QBoxLayout>
@@ -125,7 +125,8 @@ GraphicsFramebufferWidget::GraphicsFramebufferWidget(std::shared_ptr<Pica::Debug
125 setWidget(main_widget); 125 setWidget(main_widget);
126 126
127 // Load current data - TODO: Make sure this works when emulation is not running 127 // Load current data - TODO: Make sure this works when emulation is not running
128 emit Update(); 128 if (debug_context && debug_context->at_breakpoint)
129 emit Update();
129 widget()->setEnabled(false); // TODO: Only enable if currently at breakpoint 130 widget()->setEnabled(false); // TODO: Only enable if currently at breakpoint
130} 131}
131 132
@@ -198,7 +199,7 @@ void GraphicsFramebufferWidget::OnUpdate()
198 auto framebuffer = Pica::registers.framebuffer; 199 auto framebuffer = Pica::registers.framebuffer;
199 using Framebuffer = decltype(framebuffer); 200 using Framebuffer = decltype(framebuffer);
200 201
201 framebuffer_address = framebuffer.GetColorBufferAddress(); 202 framebuffer_address = framebuffer.GetColorBufferPhysicalAddress();
202 framebuffer_width = framebuffer.GetWidth(); 203 framebuffer_width = framebuffer.GetWidth();
203 framebuffer_height = framebuffer.GetHeight(); 204 framebuffer_height = framebuffer.GetHeight();
204 framebuffer_format = static_cast<Format>(framebuffer.color_format); 205 framebuffer_format = static_cast<Format>(framebuffer.color_format);
@@ -223,9 +224,9 @@ void GraphicsFramebufferWidget::OnUpdate()
223 case Format::RGBA8: 224 case Format::RGBA8:
224 { 225 {
225 QImage decoded_image(framebuffer_width, framebuffer_height, QImage::Format_ARGB32); 226 QImage decoded_image(framebuffer_width, framebuffer_height, QImage::Format_ARGB32);
226 u32* color_buffer = (u32*)Memory::GetPointer(framebuffer_address); 227 u32* color_buffer = (u32*)Memory::GetPointer(Pica::PAddrToVAddr(framebuffer_address));
227 for (int y = 0; y < framebuffer_height; ++y) { 228 for (unsigned y = 0; y < framebuffer_height; ++y) {
228 for (int x = 0; x < framebuffer_width; ++x) { 229 for (unsigned x = 0; x < framebuffer_width; ++x) {
229 u32 value = *(color_buffer + x + y * framebuffer_width); 230 u32 value = *(color_buffer + x + y * framebuffer_width);
230 231
231 decoded_image.setPixel(x, y, qRgba((value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF, 255/*value >> 24*/)); 232 decoded_image.setPixel(x, y, qRgba((value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF, 255/*value >> 24*/));
@@ -238,9 +239,9 @@ void GraphicsFramebufferWidget::OnUpdate()
238 case Format::RGB8: 239 case Format::RGB8:
239 { 240 {
240 QImage decoded_image(framebuffer_width, framebuffer_height, QImage::Format_ARGB32); 241 QImage decoded_image(framebuffer_width, framebuffer_height, QImage::Format_ARGB32);
241 u8* color_buffer = Memory::GetPointer(framebuffer_address); 242 u8* color_buffer = Memory::GetPointer(Pica::PAddrToVAddr(framebuffer_address));
242 for (int y = 0; y < framebuffer_height; ++y) { 243 for (unsigned y = 0; y < framebuffer_height; ++y) {
243 for (int x = 0; x < framebuffer_width; ++x) { 244 for (unsigned x = 0; x < framebuffer_width; ++x) {
244 u8* pixel_pointer = color_buffer + x * 3 + y * 3 * framebuffer_width; 245 u8* pixel_pointer = color_buffer + x * 3 + y * 3 * framebuffer_width;
245 246
246 decoded_image.setPixel(x, y, qRgba(pixel_pointer[0], pixel_pointer[1], pixel_pointer[2], 255/*value >> 24*/)); 247 decoded_image.setPixel(x, y, qRgba(pixel_pointer[0], pixel_pointer[1], pixel_pointer[2], 255/*value >> 24*/));
@@ -253,9 +254,9 @@ void GraphicsFramebufferWidget::OnUpdate()
253 case Format::RGBA5551: 254 case Format::RGBA5551:
254 { 255 {
255 QImage decoded_image(framebuffer_width, framebuffer_height, QImage::Format_ARGB32); 256 QImage decoded_image(framebuffer_width, framebuffer_height, QImage::Format_ARGB32);
256 u32* color_buffer = (u32*)Memory::GetPointer(framebuffer_address); 257 u32* color_buffer = (u32*)Memory::GetPointer(Pica::PAddrToVAddr(framebuffer_address));
257 for (int y = 0; y < framebuffer_height; ++y) { 258 for (unsigned y = 0; y < framebuffer_height; ++y) {
258 for (int x = 0; x < framebuffer_width; ++x) { 259 for (unsigned x = 0; x < framebuffer_width; ++x) {
259 u16 value = *(u16*)(((u8*)color_buffer) + x * 2 + y * framebuffer_width * 2); 260 u16 value = *(u16*)(((u8*)color_buffer) + x * 2 + y * framebuffer_width * 2);
260 u8 r = (value >> 11) & 0x1F; 261 u8 r = (value >> 11) & 0x1F;
261 u8 g = (value >> 6) & 0x1F; 262 u8 g = (value >> 6) & 0x1F;
diff --git a/src/citra_qt/debugger/graphics_framebuffer.hxx b/src/citra_qt/debugger/graphics_framebuffer.hxx
index 1151ee7a1..56215761e 100644
--- a/src/citra_qt/debugger/graphics_framebuffer.hxx
+++ b/src/citra_qt/debugger/graphics_framebuffer.hxx
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp
index 1299338ac..b12e6a02b 100644
--- a/src/citra_qt/main.cpp
+++ b/src/citra_qt/main.cpp
@@ -157,12 +157,6 @@ void GMainWindow::BootGame(std::string filename)
157 LOG_INFO(Frontend, "Citra starting...\n"); 157 LOG_INFO(Frontend, "Citra starting...\n");
158 System::Init(render_window); 158 System::Init(render_window);
159 159
160 if (Core::Init()) {
161 LOG_CRITICAL(Frontend, "Core initialization failed, exiting...");
162 Core::Stop();
163 exit(1);
164 }
165
166 // Load a game or die... 160 // Load a game or die...
167 if (Loader::ResultStatus::Success != Loader::LoadFile(filename)) { 161 if (Loader::ResultStatus::Success != Loader::LoadFile(filename)) {
168 LOG_CRITICAL(Frontend, "Failed to load ROM!"); 162 LOG_CRITICAL(Frontend, "Failed to load ROM!");
@@ -236,12 +230,15 @@ void GMainWindow::ToggleWindowMode()
236 render_window->setParent(nullptr); 230 render_window->setParent(nullptr);
237 render_window->setVisible(true); 231 render_window->setVisible(true);
238 render_window->RestoreGeometry(); 232 render_window->RestoreGeometry();
233 render_window->setFocusPolicy(Qt::NoFocus);
239 } 234 }
240 else if (!enable && render_window->parent() == nullptr) 235 else if (!enable && render_window->parent() == nullptr)
241 { 236 {
242 render_window->BackupGeometry(); 237 render_window->BackupGeometry();
243 ui.horizontalLayout->addWidget(render_window); 238 ui.horizontalLayout->addWidget(render_window);
244 render_window->setVisible(true); 239 render_window->setVisible(true);
240 render_window->setFocusPolicy(Qt::ClickFocus);
241 render_window->setFocus();
245 } 242 }
246} 243}
247 244
diff --git a/src/citra_qt/util/spinbox.cpp b/src/citra_qt/util/spinbox.cpp
index 9672168f5..f9988409f 100644
--- a/src/citra_qt/util/spinbox.cpp
+++ b/src/citra_qt/util/spinbox.cpp
@@ -1,4 +1,4 @@
1// Licensed under GPLv2+ 1// Licensed under GPLv2 or any later version
2// Refer to the license.txt file included. 2// Refer to the license.txt file included.
3 3
4 4
@@ -238,7 +238,7 @@ QValidator::State CSpinBox::validate(QString& input, int& pos) const
238 if (!prefix.isEmpty() && input.left(prefix.length()) != prefix) 238 if (!prefix.isEmpty() && input.left(prefix.length()) != prefix)
239 return QValidator::Invalid; 239 return QValidator::Invalid;
240 240
241 unsigned strpos = prefix.length(); 241 int strpos = prefix.length();
242 242
243 // Empty "numbers" allowed as intermediate values 243 // Empty "numbers" allowed as intermediate values
244 if (strpos >= input.length() - HasSign() - suffix.length()) 244 if (strpos >= input.length() - HasSign() - suffix.length())
diff --git a/src/citra_qt/util/spinbox.hxx b/src/citra_qt/util/spinbox.hxx
index 68f5b9894..ee7f08ec2 100644
--- a/src/citra_qt/util/spinbox.hxx
+++ b/src/citra_qt/util/spinbox.hxx
@@ -1,4 +1,4 @@
1// Licensed under GPLv2+ 1// Licensed under GPLv2 or any later version
2// Refer to the license.txt file included. 2// Refer to the license.txt file included.
3 3
4 4
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 15989708d..3c3419bbc 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -49,6 +49,7 @@ set(HEADERS
49 logging/filter.h 49 logging/filter.h
50 logging/log.h 50 logging/log.h
51 logging/backend.h 51 logging/backend.h
52 make_unique.h
52 math_util.h 53 math_util.h
53 mem_arena.h 54 mem_arena.h
54 memory_util.h 55 memory_util.h
diff --git a/src/common/bit_field.h b/src/common/bit_field.h
index 9e02210f9..8eab054b8 100644
--- a/src/common/bit_field.h
+++ b/src/common/bit_field.h
@@ -1,4 +1,4 @@
1// Licensed under GPLv2 1// Licensed under GPLv2 or any later version
2// Refer to the license.txt file included. 2// Refer to the license.txt file included.
3 3
4 4
@@ -142,7 +142,7 @@ public:
142 142
143 __forceinline BitField& operator=(T val) 143 __forceinline BitField& operator=(T val)
144 { 144 {
145 storage = (storage & ~GetMask()) | (((StorageType)val << position) & GetMask()); 145 Assign(val);
146 return *this; 146 return *this;
147 } 147 }
148 148
@@ -151,6 +151,10 @@ public:
151 return Value(); 151 return Value();
152 } 152 }
153 153
154 __forceinline void Assign(const T& value) {
155 storage = (storage & ~GetMask()) | (((StorageType)value << position) & GetMask());
156 }
157
154 __forceinline T Value() const 158 __forceinline T Value() const
155 { 159 {
156 if (std::numeric_limits<T>::is_signed) 160 if (std::numeric_limits<T>::is_signed)
@@ -164,6 +168,12 @@ public:
164 } 168 }
165 } 169 }
166 170
171 // TODO: we may want to change this to explicit operator bool() if it's bug-free in VS2015
172 __forceinline bool ToBool() const
173 {
174 return Value() != 0;
175 }
176
167private: 177private:
168 // StorageType is T for non-enum types and the underlying type of T if 178 // StorageType is T for non-enum types and the underlying type of T if
169 // T is an enumeration. Note that T is wrapped within an enable_if in the 179 // T is an enumeration. Note that T is wrapped within an enable_if in the
diff --git a/src/common/break_points.cpp b/src/common/break_points.cpp
index 587dbf40a..6696935fa 100644
--- a/src/common/break_points.cpp
+++ b/src/common/break_points.cpp
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common.h" 5#include "common/common.h"
diff --git a/src/common/break_points.h b/src/common/break_points.h
index cf3884fbc..5557cd50e 100644
--- a/src/common/break_points.h
+++ b/src/common/break_points.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/common.h b/src/common/common.h
index 9f3016d34..66f0ccd0c 100644
--- a/src/common/common.h
+++ b/src/common/common.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index 67b3679b0..ca7abbea6 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/common_paths.h b/src/common/common_paths.h
index 42e1a29c1..9d62a8368 100644
--- a/src/common/common_paths.h
+++ b/src/common/common_paths.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -40,7 +40,9 @@
40#define MAPS_DIR "maps" 40#define MAPS_DIR "maps"
41#define CACHE_DIR "cache" 41#define CACHE_DIR "cache"
42#define SDMC_DIR "sdmc" 42#define SDMC_DIR "sdmc"
43#define SAVEDATA_DIR "savedata"
43#define SYSDATA_DIR "sysdata" 44#define SYSDATA_DIR "sysdata"
45#define SYSSAVEDATA_DIR "syssavedata"
44#define SHADERCACHE_DIR "shader_cache" 46#define SHADERCACHE_DIR "shader_cache"
45#define STATESAVES_DIR "state_saves" 47#define STATESAVES_DIR "state_saves"
46#define SCREENSHOTS_DIR "screenShots" 48#define SCREENSHOTS_DIR "screenShots"
diff --git a/src/common/concurrent_ring_buffer.h b/src/common/concurrent_ring_buffer.h
index 2951d93db..311bb01f4 100644
--- a/src/common/concurrent_ring_buffer.h
+++ b/src/common/concurrent_ring_buffer.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2+ 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/cpu_detect.h b/src/common/cpu_detect.h
index def6afdee..b585f9608 100644
--- a/src/common/cpu_detect.h
+++ b/src/common/cpu_detect.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5 5
diff --git a/src/common/emu_window.cpp b/src/common/emu_window.cpp
index 7a2c50ac8..4ec7b263a 100644
--- a/src/common/emu_window.cpp
+++ b/src/common/emu_window.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "emu_window.h" 5#include "emu_window.h"
diff --git a/src/common/emu_window.h b/src/common/emu_window.h
index 4cb94fed1..1ad4b82a3 100644
--- a/src/common/emu_window.h
+++ b/src/common/emu_window.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/file_search.cpp b/src/common/file_search.cpp
index bfb54ce72..b3a0a84fb 100644
--- a/src/common/file_search.cpp
+++ b/src/common/file_search.cpp
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5 5
diff --git a/src/common/file_search.h b/src/common/file_search.h
index f966a008d..55ca02638 100644
--- a/src/common/file_search.h
+++ b/src/common/file_search.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 88c46c117..bba830c70 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5 5
@@ -676,7 +676,9 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new
676 paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP; 676 paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP;
677 paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; 677 paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP;
678 paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; 678 paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP;
679 paths[D_SAVEDATA_IDX] = paths[D_USER_IDX] + SAVEDATA_DIR DIR_SEP;
679 paths[D_SYSDATA_IDX] = paths[D_USER_IDX] + SYSDATA_DIR DIR_SEP; 680 paths[D_SYSDATA_IDX] = paths[D_USER_IDX] + SYSDATA_DIR DIR_SEP;
681 paths[D_SYSSAVEDATA_IDX] = paths[D_USER_IDX] + SYSSAVEDATA_DIR DIR_SEP;
680 paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP; 682 paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP;
681 paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP; 683 paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP;
682 paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP; 684 paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP;
@@ -718,6 +720,8 @@ const std::string& GetUserPath(const unsigned int DirIDX, const std::string &new
718 paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP; 720 paths[D_MAPS_IDX] = paths[D_USER_IDX] + MAPS_DIR DIR_SEP;
719 paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; 721 paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP;
720 paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; 722 paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP;
723 paths[D_SAVEDATA_IDX] = paths[D_USER_IDX] + SAVEDATA_DIR DIR_SEP;
724 paths[D_SYSSAVEDATA_IDX] = paths[D_USER_IDX] + SYSSAVEDATA_DIR DIR_SEP;
721 paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP; 725 paths[D_SHADERCACHE_IDX] = paths[D_USER_IDX] + SHADERCACHE_DIR DIR_SEP;
722 paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP; 726 paths[D_SHADERS_IDX] = paths[D_USER_IDX] + SHADERS_DIR DIR_SEP;
723 paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP; 727 paths[D_STATESAVES_IDX] = paths[D_USER_IDX] + STATESAVES_DIR DIR_SEP;
diff --git a/src/common/file_util.h b/src/common/file_util.h
index a9d48cfe8..293c30941 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -27,7 +27,9 @@ enum {
27 D_STATESAVES_IDX, 27 D_STATESAVES_IDX,
28 D_SCREENSHOTS_IDX, 28 D_SCREENSHOTS_IDX,
29 D_SDMC_IDX, 29 D_SDMC_IDX,
30 D_SAVEDATA_IDX,
30 D_SYSDATA_IDX, 31 D_SYSDATA_IDX,
32 D_SYSSAVEDATA_IDX,
31 D_HIRESTEXTURES_IDX, 33 D_HIRESTEXTURES_IDX,
32 D_DUMP_IDX, 34 D_DUMP_IDX,
33 D_DUMPFRAMES_IDX, 35 D_DUMPFRAMES_IDX,
diff --git a/src/common/hash.cpp b/src/common/hash.cpp
index 2ddcfe6b7..fe2c9e636 100644
--- a/src/common/hash.cpp
+++ b/src/common/hash.cpp
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5 5
diff --git a/src/common/hash.h b/src/common/hash.h
index 29f699d7f..3ac42bc44 100644
--- a/src/common/hash.h
+++ b/src/common/hash.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/key_map.cpp b/src/common/key_map.cpp
index 309caab98..d8945bb13 100644
--- a/src/common/key_map.cpp
+++ b/src/common/key_map.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "key_map.h" 5#include "key_map.h"
diff --git a/src/common/key_map.h b/src/common/key_map.h
index bf72362c0..8d949b852 100644
--- a/src/common/key_map.h
+++ b/src/common/key_map.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/linear_disk_cache.h b/src/common/linear_disk_cache.h
index bb1b5174f..74ce74aba 100644
--- a/src/common/linear_disk_cache.h
+++ b/src/common/linear_disk_cache.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/log.h b/src/common/log.h
index 663eda9ad..96d97249f 100644
--- a/src/common/log.h
+++ b/src/common/log.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index e79b84604..816d1bb55 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2+ 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h
index ae270efe8..1c44c929e 100644
--- a/src/common/logging/backend.h
+++ b/src/common/logging/backend.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2+ 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp
index 0cf9b05e7..50f2e13f4 100644
--- a/src/common/logging/filter.cpp
+++ b/src/common/logging/filter.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2+ 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
diff --git a/src/common/logging/filter.h b/src/common/logging/filter.h
index 32b14b159..c3da9989f 100644
--- a/src/common/logging/filter.h
+++ b/src/common/logging/filter.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2+ 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array> 5#include <array>
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index 1eec34fbb..d1c391862 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2+ 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/logging/text_formatter.cpp b/src/common/logging/text_formatter.cpp
index 3fe435346..ef5739d84 100644
--- a/src/common/logging/text_formatter.cpp
+++ b/src/common/logging/text_formatter.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2+ 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array> 5#include <array>
@@ -54,12 +54,22 @@ void FormatLogMessage(const Entry& entry, char* out_text, size_t text_len) {
54 TrimSourcePath(entry.location.c_str()), entry.message.c_str()); 54 TrimSourcePath(entry.location.c_str()), entry.message.c_str());
55} 55}
56 56
57static void ChangeConsoleColor(Level level) { 57void PrintMessage(const Entry& entry) {
58 std::array<char, 4 * 1024> format_buffer;
59 FormatLogMessage(entry, format_buffer.data(), format_buffer.size());
60 fputs(format_buffer.data(), stderr);
61 fputc('\n', stderr);
62}
63
64void PrintColoredMessage(const Entry& entry) {
58#ifdef _WIN32 65#ifdef _WIN32
59 static HANDLE console_handle = GetStdHandle(STD_ERROR_HANDLE); 66 static HANDLE console_handle = GetStdHandle(STD_ERROR_HANDLE);
60 67
68 CONSOLE_SCREEN_BUFFER_INFO original_info = {0};
69 GetConsoleScreenBufferInfo(console_handle, &original_info);
70
61 WORD color = 0; 71 WORD color = 0;
62 switch (level) { 72 switch (entry.log_level) {
63 case Level::Trace: // Grey 73 case Level::Trace: // Grey
64 color = FOREGROUND_INTENSITY; break; 74 color = FOREGROUND_INTENSITY; break;
65 case Level::Debug: // Cyan 75 case Level::Debug: // Cyan
@@ -76,9 +86,9 @@ static void ChangeConsoleColor(Level level) {
76 86
77 SetConsoleTextAttribute(console_handle, color); 87 SetConsoleTextAttribute(console_handle, color);
78#else 88#else
79#define ESC "\x1b" 89# define ESC "\x1b"
80 const char* color = ""; 90 const char* color = "";
81 switch (level) { 91 switch (entry.log_level) {
82 case Level::Trace: // Grey 92 case Level::Trace: // Grey
83 color = ESC "[1;30m"; break; 93 color = ESC "[1;30m"; break;
84 case Level::Debug: // Cyan 94 case Level::Debug: // Cyan
@@ -92,18 +102,18 @@ static void ChangeConsoleColor(Level level) {
92 case Level::Critical: // Bright magenta 102 case Level::Critical: // Bright magenta
93 color = ESC "[1;35m"; break; 103 color = ESC "[1;35m"; break;
94 } 104 }
95#undef ESC
96 105
97 fputs(color, stderr); 106 fputs(color, stderr);
98#endif 107#endif
99}
100 108
101void PrintMessage(const Entry& entry) { 109 PrintMessage(entry);
102 ChangeConsoleColor(entry.log_level); 110
103 std::array<char, 4 * 1024> format_buffer; 111#ifdef _WIN32
104 FormatLogMessage(entry, format_buffer.data(), format_buffer.size()); 112 SetConsoleTextAttribute(console_handle, original_info.wAttributes);
105 fputs(format_buffer.data(), stderr); 113#else
106 fputc('\n', stderr); 114 fputs(ESC "[0m", stderr);
115# undef ESC
116#endif
107} 117}
108 118
109void TextLoggingLoop(std::shared_ptr<Logger> logger, const Filter* filter) { 119void TextLoggingLoop(std::shared_ptr<Logger> logger, const Filter* filter) {
@@ -117,7 +127,7 @@ void TextLoggingLoop(std::shared_ptr<Logger> logger, const Filter* filter) {
117 for (size_t i = 0; i < num_entries; ++i) { 127 for (size_t i = 0; i < num_entries; ++i) {
118 const Entry& entry = entry_buffer[i]; 128 const Entry& entry = entry_buffer[i];
119 if (filter->CheckMessage(entry.log_class, entry.log_level)) { 129 if (filter->CheckMessage(entry.log_class, entry.log_level)) {
120 PrintMessage(entry); 130 PrintColoredMessage(entry);
121 } 131 }
122 } 132 }
123 } 133 }
diff --git a/src/common/logging/text_formatter.h b/src/common/logging/text_formatter.h
index d7e298e28..2f05794f0 100644
--- a/src/common/logging/text_formatter.h
+++ b/src/common/logging/text_formatter.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2+ 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -29,6 +29,8 @@ const char* TrimSourcePath(const char* path, const char* root = "src");
29void FormatLogMessage(const Entry& entry, char* out_text, size_t text_len); 29void FormatLogMessage(const Entry& entry, char* out_text, size_t text_len);
30/// Formats and prints a log entry to stderr. 30/// Formats and prints a log entry to stderr.
31void PrintMessage(const Entry& entry); 31void PrintMessage(const Entry& entry);
32/// Prints the same message as `PrintMessage`, but colored acoording to the severity level.
33void PrintColoredMessage(const Entry& entry);
32 34
33/** 35/**
34 * Logging loop that repeatedly reads messages from the provided logger and prints them to the 36 * Logging loop that repeatedly reads messages from the provided logger and prints them to the
diff --git a/src/common/make_unique.h b/src/common/make_unique.h
new file mode 100644
index 000000000..2a7b76412
--- /dev/null
+++ b/src/common/make_unique.h
@@ -0,0 +1,16 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8
9namespace Common {
10
11template <typename T, typename... Args>
12std::unique_ptr<T> make_unique(Args&&... args) {
13 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
14}
15
16} // namespace
diff --git a/src/common/math_util.cpp b/src/common/math_util.cpp
index 3613e82a6..a83592dd2 100644
--- a/src/common/math_util.cpp
+++ b/src/common/math_util.cpp
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5 5
diff --git a/src/common/math_util.h b/src/common/math_util.h
index b10a25c13..43b0e0dc3 100644
--- a/src/common/math_util.h
+++ b/src/common/math_util.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/memory_util.cpp b/src/common/memory_util.cpp
index ca8a2a9e4..8f982da89 100644
--- a/src/common/memory_util.cpp
+++ b/src/common/memory_util.cpp
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5 5
diff --git a/src/common/memory_util.h b/src/common/memory_util.h
index 922bd44b2..9fdbf1f12 100644
--- a/src/common/memory_util.h
+++ b/src/common/memory_util.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/misc.cpp b/src/common/misc.cpp
index bc9d26188..e33055d10 100644
--- a/src/common/misc.cpp
+++ b/src/common/misc.cpp
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common.h" 5#include "common/common.h"
diff --git a/src/common/msg_handler.cpp b/src/common/msg_handler.cpp
index 7ffedc45a..4a47b518e 100644
--- a/src/common/msg_handler.cpp
+++ b/src/common/msg_handler.cpp
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstdio> 5#include <cstdio>
diff --git a/src/common/msg_handler.h b/src/common/msg_handler.h
index 9bfdf950e..7bb216e98 100644
--- a/src/common/msg_handler.h
+++ b/src/common/msg_handler.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/scm_rev.h b/src/common/scm_rev.h
index d34664614..0ef190afa 100644
--- a/src/common/scm_rev.h
+++ b/src/common/scm_rev.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/scope_exit.h b/src/common/scope_exit.h
index 1d3e59319..263beaf0e 100644
--- a/src/common/scope_exit.h
+++ b/src/common/scope_exit.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2+ 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index 6d9612fb5..d919b7a4c 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <boost/range/algorithm.hpp> 5#include <boost/range/algorithm.hpp>
diff --git a/src/common/string_util.h b/src/common/string_util.h
index 7d75691b1..74974263f 100644
--- a/src/common/string_util.h
+++ b/src/common/string_util.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/symbols.cpp b/src/common/symbols.cpp
index 63ad6218b..9e4dccfb3 100644
--- a/src/common/symbols.cpp
+++ b/src/common/symbols.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/symbols.h" 5#include "common/symbols.h"
diff --git a/src/common/symbols.h b/src/common/symbols.h
index 4560f5240..f76cb6b1e 100644
--- a/src/common/symbols.h
+++ b/src/common/symbols.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/thread.cpp b/src/common/thread.cpp
index dc153ba71..8c83d67b5 100644
--- a/src/common/thread.cpp
+++ b/src/common/thread.cpp
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/thread.h" 5#include "common/thread.h"
diff --git a/src/common/thread.h b/src/common/thread.h
index 8c36d3f07..eaf1ba00c 100644
--- a/src/common/thread.h
+++ b/src/common/thread.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/thread_queue_list.h b/src/common/thread_queue_list.h
index 7e3b620c7..4e1c0a215 100644
--- a/src/common/thread_queue_list.h
+++ b/src/common/thread_queue_list.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project / PPSSPP Project 1// Copyright 2014 Citra Emulator Project / PPSSPP Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/thunk.h b/src/common/thunk.h
index 90c8be888..4fb7c98e1 100644
--- a/src/common/thunk.h
+++ b/src/common/thunk.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/common/timer.cpp b/src/common/timer.cpp
index 4a797f751..a6682ea19 100644
--- a/src/common/timer.cpp
+++ b/src/common/timer.cpp
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <time.h> 5#include <time.h>
diff --git a/src/common/timer.h b/src/common/timer.h
index 86418e7a7..4b44c33a0 100644
--- a/src/common/timer.h
+++ b/src/common/timer.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 8f6792791..fdd97c184 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -18,35 +18,46 @@ set(SRCS
18 arm/skyeye_common/vfp/vfpinstr.cpp 18 arm/skyeye_common/vfp/vfpinstr.cpp
19 arm/skyeye_common/vfp/vfpsingle.cpp 19 arm/skyeye_common/vfp/vfpsingle.cpp
20 file_sys/archive_romfs.cpp 20 file_sys/archive_romfs.cpp
21 file_sys/archive_savedata.cpp
21 file_sys/archive_sdmc.cpp 22 file_sys/archive_sdmc.cpp
23 file_sys/archive_systemsavedata.cpp
24 file_sys/disk_archive.cpp
22 file_sys/file_romfs.cpp 25 file_sys/file_romfs.cpp
23 file_sys/file_sdmc.cpp
24 file_sys/directory_romfs.cpp 26 file_sys/directory_romfs.cpp
25 file_sys/directory_sdmc.cpp
26 hle/kernel/address_arbiter.cpp 27 hle/kernel/address_arbiter.cpp
27 hle/kernel/archive.cpp
28 hle/kernel/event.cpp 28 hle/kernel/event.cpp
29 hle/kernel/kernel.cpp 29 hle/kernel/kernel.cpp
30 hle/kernel/mutex.cpp 30 hle/kernel/mutex.cpp
31 hle/kernel/semaphore.cpp
31 hle/kernel/shared_memory.cpp 32 hle/kernel/shared_memory.cpp
32 hle/kernel/thread.cpp 33 hle/kernel/thread.cpp
33 hle/service/ac_u.cpp 34 hle/service/ac_u.cpp
35 hle/service/act_u.cpp
36 hle/service/am_app.cpp
34 hle/service/am_net.cpp 37 hle/service/am_net.cpp
38 hle/service/apt_a.cpp
35 hle/service/apt_u.cpp 39 hle/service/apt_u.cpp
36 hle/service/boss_u.cpp 40 hle/service/boss_u.cpp
37 hle/service/cfg_i.cpp 41 hle/service/cecd_u.cpp
38 hle/service/cfg_u.cpp 42 hle/service/cfg/cfg.cpp
43 hle/service/cfg/cfg_i.cpp
44 hle/service/cfg/cfg_u.cpp
39 hle/service/csnd_snd.cpp 45 hle/service/csnd_snd.cpp
40 hle/service/dsp_dsp.cpp 46 hle/service/dsp_dsp.cpp
41 hle/service/err_f.cpp 47 hle/service/err_f.cpp
42 hle/service/fs_user.cpp
43 hle/service/frd_u.cpp 48 hle/service/frd_u.cpp
49 hle/service/fs/archive.cpp
50 hle/service/fs/fs_user.cpp
44 hle/service/gsp_gpu.cpp 51 hle/service/gsp_gpu.cpp
45 hle/service/hid_user.cpp 52 hle/service/hid_user.cpp
53 hle/service/http_c.cpp
46 hle/service/ir_rst.cpp 54 hle/service/ir_rst.cpp
47 hle/service/ir_u.cpp 55 hle/service/ir_u.cpp
56 hle/service/ldr_ro.cpp
48 hle/service/mic_u.cpp 57 hle/service/mic_u.cpp
49 hle/service/ndm_u.cpp 58 hle/service/ndm_u.cpp
59 hle/service/news_u.cpp
60 hle/service/nim_aoc.cpp
50 hle/service/nwm_uds.cpp 61 hle/service/nwm_uds.cpp
51 hle/service/pm_app.cpp 62 hle/service/pm_app.cpp
52 hle/service/ptm_u.cpp 63 hle/service/ptm_u.cpp
@@ -92,39 +103,51 @@ set(HEADERS
92 arm/skyeye_common/vfp/vfp.h 103 arm/skyeye_common/vfp/vfp.h
93 arm/skyeye_common/vfp/vfp_helper.h 104 arm/skyeye_common/vfp/vfp_helper.h
94 arm/arm_interface.h 105 arm/arm_interface.h
95 file_sys/archive.h 106 file_sys/archive_backend.h
96 file_sys/archive_romfs.h 107 file_sys/archive_romfs.h
108 file_sys/archive_savedata.h
97 file_sys/archive_sdmc.h 109 file_sys/archive_sdmc.h
98 file_sys/file.h 110 file_sys/archive_systemsavedata.h
111 file_sys/disk_archive.h
112 file_sys/file_backend.h
99 file_sys/file_romfs.h 113 file_sys/file_romfs.h
100 file_sys/file_sdmc.h 114 file_sys/directory_backend.h
101 file_sys/directory.h
102 file_sys/directory_romfs.h 115 file_sys/directory_romfs.h
103 file_sys/directory_sdmc.h
104 hle/kernel/address_arbiter.h 116 hle/kernel/address_arbiter.h
105 hle/kernel/archive.h
106 hle/kernel/event.h 117 hle/kernel/event.h
107 hle/kernel/kernel.h 118 hle/kernel/kernel.h
108 hle/kernel/mutex.h 119 hle/kernel/mutex.h
120 hle/kernel/semaphore.h
121 hle/kernel/session.h
109 hle/kernel/shared_memory.h 122 hle/kernel/shared_memory.h
110 hle/kernel/thread.h 123 hle/kernel/thread.h
111 hle/service/ac_u.h 124 hle/service/ac_u.h
125 hle/service/act_u.h
126 hle/service/am_app.h
112 hle/service/am_net.h 127 hle/service/am_net.h
128 hle/service/apt_a.h
113 hle/service/apt_u.h 129 hle/service/apt_u.h
114 hle/service/boss_u.h 130 hle/service/boss_u.h
115 hle/service/cfg_i.h 131 hle/service/cecd_u.h
116 hle/service/cfg_u.h 132 hle/service/cfg/cfg.h
133 hle/service/cfg/cfg_i.h
134 hle/service/cfg/cfg_u.h
117 hle/service/csnd_snd.h 135 hle/service/csnd_snd.h
118 hle/service/dsp_dsp.h 136 hle/service/dsp_dsp.h
119 hle/service/err_f.h 137 hle/service/err_f.h
120 hle/service/fs_user.h
121 hle/service/frd_u.h 138 hle/service/frd_u.h
139 hle/service/fs/archive.h
140 hle/service/fs/fs_user.h
122 hle/service/gsp_gpu.h 141 hle/service/gsp_gpu.h
123 hle/service/hid_user.h 142 hle/service/hid_user.h
143 hle/service/http_c.h
124 hle/service/ir_rst.h 144 hle/service/ir_rst.h
125 hle/service/ir_u.h 145 hle/service/ir_u.h
146 hle/service/ldr_ro.h
126 hle/service/mic_u.h 147 hle/service/mic_u.h
127 hle/service/ndm_u.h 148 hle/service/ndm_u.h
149 hle/service/news_u.h
150 hle/service/nim_aoc.h
128 hle/service/nwm_uds.h 151 hle/service/nwm_uds.h
129 hle/service/pm_app.h 152 hle/service/pm_app.h
130 hle/service/ptm_u.h 153 hle/service/ptm_u.h
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 3ae528562..3b7209418 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -78,6 +78,12 @@ public:
78 virtual u64 GetTicks() const = 0; 78 virtual u64 GetTicks() const = 0;
79 79
80 /** 80 /**
81 * Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time)
82 * @param ticks Number of ticks to advance the CPU core
83 */
84 virtual void AddTicks(u64 ticks) = 0;
85
86 /**
81 * Saves the current CPU context 87 * Saves the current CPU context
82 * @param ctx Thread context to save 88 * @param ctx Thread context to save
83 */ 89 */
diff --git a/src/core/arm/disassembler/load_symbol_map.cpp b/src/core/arm/disassembler/load_symbol_map.cpp
index 55278474b..13d26d170 100644
--- a/src/core/arm/disassembler/load_symbol_map.cpp
+++ b/src/core/arm/disassembler/load_symbol_map.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string> 5#include <string>
diff --git a/src/core/arm/disassembler/load_symbol_map.h b/src/core/arm/disassembler/load_symbol_map.h
index 837cca99b..d28c551c3 100644
--- a/src/core/arm/disassembler/load_symbol_map.h
+++ b/src/core/arm/disassembler/load_symbol_map.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index 6c8ea211e..a838fd25a 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/arm/skyeye_common/armcpu.h" 5#include "core/arm/skyeye_common/armcpu.h"
@@ -47,68 +47,38 @@ ARM_DynCom::ARM_DynCom() : ticks(0) {
47ARM_DynCom::~ARM_DynCom() { 47ARM_DynCom::~ARM_DynCom() {
48} 48}
49 49
50/**
51 * Set the Program Counter to an address
52 * @param addr Address to set PC to
53 */
54void ARM_DynCom::SetPC(u32 pc) { 50void ARM_DynCom::SetPC(u32 pc) {
55 state->pc = state->Reg[15] = pc; 51 state->pc = state->Reg[15] = pc;
56} 52}
57 53
58/*
59 * Get the current Program Counter
60 * @return Returns current PC
61 */
62u32 ARM_DynCom::GetPC() const { 54u32 ARM_DynCom::GetPC() const {
63 return state->Reg[15]; 55 return state->Reg[15];
64} 56}
65 57
66/**
67 * Get an ARM register
68 * @param index Register index (0-15)
69 * @return Returns the value in the register
70 */
71u32 ARM_DynCom::GetReg(int index) const { 58u32 ARM_DynCom::GetReg(int index) const {
72 return state->Reg[index]; 59 return state->Reg[index];
73} 60}
74 61
75/**
76 * Set an ARM register
77 * @param index Register index (0-15)
78 * @param value Value to set register to
79 */
80void ARM_DynCom::SetReg(int index, u32 value) { 62void ARM_DynCom::SetReg(int index, u32 value) {
81 state->Reg[index] = value; 63 state->Reg[index] = value;
82} 64}
83 65
84/**
85 * Get the current CPSR register
86 * @return Returns the value of the CPSR register
87 */
88u32 ARM_DynCom::GetCPSR() const { 66u32 ARM_DynCom::GetCPSR() const {
89 return state->Cpsr; 67 return state->Cpsr;
90} 68}
91 69
92/**
93 * Set the current CPSR register
94 * @param cpsr Value to set CPSR to
95 */
96void ARM_DynCom::SetCPSR(u32 cpsr) { 70void ARM_DynCom::SetCPSR(u32 cpsr) {
97 state->Cpsr = cpsr; 71 state->Cpsr = cpsr;
98} 72}
99 73
100/**
101 * Returns the number of clock ticks since the last reset
102 * @return Returns number of clock ticks
103 */
104u64 ARM_DynCom::GetTicks() const { 74u64 ARM_DynCom::GetTicks() const {
105 return ticks; 75 return ticks;
106} 76}
107 77
108/** 78void ARM_DynCom::AddTicks(u64 ticks) {
109 * Executes the given number of instructions 79 this->ticks += ticks;
110 * @param num_instructions Number of instructions to executes 80}
111 */ 81
112void ARM_DynCom::ExecuteInstructions(int num_instructions) { 82void ARM_DynCom::ExecuteInstructions(int num_instructions) {
113 state->NumInstrsToExecute = num_instructions; 83 state->NumInstrsToExecute = num_instructions;
114 84
@@ -118,11 +88,6 @@ void ARM_DynCom::ExecuteInstructions(int num_instructions) {
118 ticks += InterpreterMainLoop(state.get()); 88 ticks += InterpreterMainLoop(state.get());
119} 89}
120 90
121/**
122 * Saves the current CPU context
123 * @param ctx Thread context to save
124 * @todo Do we need to save Reg[15] and NextInstr?
125 */
126void ARM_DynCom::SaveContext(ThreadContext& ctx) { 91void ARM_DynCom::SaveContext(ThreadContext& ctx) {
127 memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers)); 92 memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers));
128 memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers)); 93 memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers));
@@ -139,11 +104,6 @@ void ARM_DynCom::SaveContext(ThreadContext& ctx) {
139 ctx.mode = state->NextInstr; 104 ctx.mode = state->NextInstr;
140} 105}
141 106
142/**
143 * Loads a CPU context
144 * @param ctx Thread context to load
145 * @param Do we need to load Reg[15] and NextInstr?
146 */
147void ARM_DynCom::LoadContext(const ThreadContext& ctx) { 107void ARM_DynCom::LoadContext(const ThreadContext& ctx) {
148 memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers)); 108 memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers));
149 memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers)); 109 memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers));
@@ -160,7 +120,6 @@ void ARM_DynCom::LoadContext(const ThreadContext& ctx) {
160 state->NextInstr = ctx.mode; 120 state->NextInstr = ctx.mode;
161} 121}
162 122
163/// Prepare core for thread reschedule (if needed to correctly handle state)
164void ARM_DynCom::PrepareReschedule() { 123void ARM_DynCom::PrepareReschedule() {
165 state->NumInstrsToExecute = 0; 124 state->NumInstrsToExecute = 0;
166} 125}
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index 51eea41ed..7284dcd07 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -27,14 +27,14 @@ public:
27 * Get the current Program Counter 27 * Get the current Program Counter
28 * @return Returns current PC 28 * @return Returns current PC
29 */ 29 */
30 u32 GetPC() const; 30 u32 GetPC() const override;
31 31
32 /** 32 /**
33 * Get an ARM register 33 * Get an ARM register
34 * @param index Register index (0-15) 34 * @param index Register index (0-15)
35 * @return Returns the value in the register 35 * @return Returns the value in the register
36 */ 36 */
37 u32 GetReg(int index) const; 37 u32 GetReg(int index) const override;
38 38
39 /** 39 /**
40 * Set an ARM register 40 * Set an ARM register
@@ -47,7 +47,7 @@ public:
47 * Get the current CPSR register 47 * Get the current CPSR register
48 * @return Returns the value of the CPSR register 48 * @return Returns the value of the CPSR register
49 */ 49 */
50 u32 GetCPSR() const; 50 u32 GetCPSR() const override;
51 51
52 /** 52 /**
53 * Set the current CPSR register 53 * Set the current CPSR register
@@ -59,7 +59,13 @@ public:
59 * Returns the number of clock ticks since the last reset 59 * Returns the number of clock ticks since the last reset
60 * @return Returns number of clock ticks 60 * @return Returns number of clock ticks
61 */ 61 */
62 u64 GetTicks() const; 62 u64 GetTicks() const override;
63
64 /**
65 * Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time)
66 * @param ticks Number of ticks to advance the CPU core
67 */
68 void AddTicks(u64 ticks) override;
63 69
64 /** 70 /**
65 * Saves the current CPU context 71 * Saves the current CPU context
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.cpp b/src/core/arm/dyncom/arm_dyncom_dec.cpp
index 5d174a08f..333b40f54 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_dec.cpp
@@ -1,402 +1,443 @@
1/* Copyright (C) 1// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
2* 2012 - Michael.Kang blackfin.kang@gmail.com 2// Licensed under GPLv2 or any later version
3* This program is free software; you can redistribute it and/or 3// Refer to the license.txt file included.
4* modify it under the terms of the GNU General Public License
5* as published by the Free Software Foundation; either version 2
6* of the License, or (at your option) any later version.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program; if not, write to the Free Software
15* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16*
17*/
18/**
19* @file arm_dyncom_dec.cpp
20* @brief Some common utility for arm decoder
21* @author Michael.Kang blackfin.kang@gmail.com
22* @version 7849
23* @date 2012-03-15
24*/
25 4
26#include "core/arm/skyeye_common/arm_regformat.h" 5#include "core/arm/skyeye_common/arm_regformat.h"
27#include "core/arm/skyeye_common/armdefs.h" 6#include "core/arm/skyeye_common/armdefs.h"
28#include "core/arm/dyncom/arm_dyncom_dec.h" 7#include "core/arm/dyncom/arm_dyncom_dec.h"
29 8
30const ISEITEM arm_instruction[] = { 9const ISEITEM arm_instruction[] = {
31 #define VFP_DECODE 10 { "vmla", 4, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0 },
32 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 11 { "vmls", 7, ARMVFP2, 28, 31, 0xF, 25, 27, 0x1, 23, 23, 1, 11, 11, 0, 8, 9, 0x2, 6, 6, 1, 4, 4, 0 },
33 #undef VFP_DECODE 12 { "vnmla", 4, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0 },
34 {"srs" , 4 , 6 , 25, 31, 0x0000007c, 22, 22, 0x00000001, 16, 20, 0x0000000d, 8, 11, 0x00000005}, 13 { "vnmla", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 },
35 {"rfe" , 4 , 6 , 25, 31, 0x0000007c, 22, 22, 0x00000000, 20, 20, 0x00000001, 8, 11, 0x0000000a}, 14 { "vnmls", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x1, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 },
36 {"bkpt" , 2 , 3 , 20, 31, 0x00000e12, 4, 7, 0x00000007}, 15 { "vnmul", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 },
37 {"blx" , 1 , 3 , 25, 31, 0x0000007d}, 16 { "vmul", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 },
38 {"cps" , 3 , 6 , 20, 31, 0x00000f10, 16, 16, 0x00000000, 5, 5, 0x00000000}, 17 { "vadd", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 },
39 {"pld" , 4 , 4 , 26, 31, 0x0000003d, 24, 24, 0x00000001, 20, 22, 0x00000005, 12, 15, 0x0000000f}, 18 { "vsub", 5, ARMVFP2, 23, 27, 0x1C, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 },
40 {"setend" , 2 , 6 , 16, 31, 0x0000f101, 4, 7, 0x00000000}, 19 { "vdiv", 5, ARMVFP2, 23, 27, 0x1D, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0 },
41 {"clrex" , 1 , 6 , 0, 31, 0xf57ff01f}, 20 { "vmov(i)", 4, ARMVFP3, 23, 27, 0x1D, 20, 21, 0x3, 9, 11, 0x5, 4, 7, 0 },
42 {"rev16" , 2 , 6 , 16, 27, 0x000006bf, 4, 11, 0x000000fb}, 21 { "vmov(r)", 5, ARMVFP3, 23, 27, 0x1D, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 1, 4, 4, 0 },
43 {"usad8" , 3 , 6 , 20, 27, 0x00000078, 12, 15, 0x0000000f, 4, 7, 0x00000001}, 22 { "vabs", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 },
44 {"sxtb" , 2 , 6 , 16, 27, 0x000006af, 4, 7, 0x00000007}, 23 { "vneg", 5, ARMVFP2, 23, 27, 0x1D, 17, 21, 0x18, 9, 11, 0x5, 6, 7, 1, 4, 4, 0 },
45 {"uxtb" , 2 , 6 , 16, 27, 0x000006ef, 4, 7, 0x00000007}, 24 { "vsqrt", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x31, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 },
46 {"sxth" , 2 , 6 , 16, 27, 0x000006bf, 4, 7, 0x00000007}, 25 { "vcmp", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x34, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 },
47 {"sxtb16" , 2 , 6 , 16, 27, 0x0000068f, 4, 7, 0x00000007}, 26 { "vcmp2", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x35, 9, 11, 0x5, 0, 6, 0x40 },
48 {"uxth" , 2 , 6 , 16, 27, 0x000006ff, 4, 7, 0x00000007}, 27 { "vcvt(bds)", 5, ARMVFP2, 23, 27, 0x1D, 16, 21, 0x37, 9, 11, 0x5, 6, 7, 3, 4, 4, 0 },
49 {"uxtb16" , 2 , 6 , 16, 27, 0x000006cf, 4, 7, 0x00000007}, 28 { "vcvt(bff)", 6, ARMVFP3, 23, 27, 0x1D, 19, 21, 0x7, 17, 17, 0x1, 9, 11, 5, 6, 6, 1 },
50 {"cpy" , 2 , 6 , 20, 27, 0x0000001a, 4, 11, 0x00000000}, 29 { "vcvt(bfi)", 5, ARMVFP2, 23, 27, 0x1D, 19, 21, 0x7, 9, 11, 0x5, 6, 6, 1, 4, 4, 0 },
51 {"uxtab" , 2 , 6 , 20, 27, 0x0000006e, 4, 9, 0x00000007}, 30 { "vmovbrs", 3, ARMVFP2, 21, 27, 0x70, 8, 11, 0xA, 0, 6, 0x10 },
52 {"ssub8" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x0000000f}, 31 { "vmsr", 2, ARMVFP2, 20, 27, 0xEE, 0, 11, 0xA10 },
53 {"shsub8" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x0000000f}, 32 { "vmovbrc", 4, ARMVFP2, 23, 27, 0x1C, 20, 20, 0x0, 8, 11, 0xB, 0, 4, 0x10 },
54 {"ssubaddx" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000005}, 33 { "vmrs", 2, ARMVFP2, 20, 27, 0xEF, 0, 11, 0xA10 },
55 {"strex" , 2 , 6 , 20, 27, 0x00000018, 4, 7, 0x00000009}, 34 { "vmovbcr", 4, ARMVFP2, 24, 27, 0xE, 20, 20, 1, 8, 11, 0xB, 0, 4, 0x10 },
56 {"strexb" , 2 , 7 , 20, 27, 0x0000001c, 4, 7, 0x00000009}, 35 { "vmovbrrss", 3, ARMVFP2, 21, 27, 0x62, 8, 11, 0xA, 4, 4, 1 },
57 {"swp" , 2 , 0 , 20, 27, 0x00000010, 4, 7, 0x00000009}, 36 { "vmovbrrd", 3, ARMVFP2, 21, 27, 0x62, 6, 11, 0x2C, 4, 4, 1 },
58 {"swpb" , 2 , 0 , 20, 27, 0x00000014, 4, 7, 0x00000009}, 37 { "vstr", 3, ARMVFP2, 24, 27, 0xD, 20, 21, 0, 9, 11, 5 },
59 {"ssub16" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000007}, 38 { "vpush", 3, ARMVFP2, 23, 27, 0x1A, 16, 21, 0x2D, 9, 11, 5 },
60 {"ssat16" , 2 , 6 , 20, 27, 0x0000006a, 4, 7, 0x00000003}, 39 { "vstm", 3, ARMVFP2, 25, 27, 0x6, 20, 20, 0, 9, 11, 5 },
61 {"shsubaddx" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000005}, 40 { "vpop", 3, ARMVFP2, 23, 27, 0x19, 16, 21, 0x3D, 9, 11, 5 },
62 {"qsubaddx" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000005}, 41 { "vldr", 3, ARMVFP2, 24, 27, 0xD, 20, 21, 1, 9, 11, 5 },
63 {"shaddsubx" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000003}, 42 { "vldm", 3, ARMVFP2, 25, 27, 0x6, 20, 20, 1, 9, 11, 5 },
64 {"shadd8" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000009}, 43
65 {"shadd16" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000001}, 44 { "srs", 4, 6, 25, 31, 0x0000007c, 22, 22, 0x00000001, 16, 20, 0x0000000d, 8, 11, 0x00000005 },
66 {"sel" , 2 , 6 , 20, 27, 0x00000068, 4, 7, 0x0000000b}, 45 { "rfe", 4, 6, 25, 31, 0x0000007c, 22, 22, 0x00000000, 20, 20, 0x00000001, 8, 11, 0x0000000a },
67 {"saddsubx" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000003}, 46 { "bkpt", 2, 3, 20, 31, 0x00000e12, 4, 7, 0x00000007 },
68 {"sadd8" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000009}, 47 { "blx", 1, 3, 25, 31, 0x0000007d },
69 {"sadd16" , 2 , 6 , 20, 27, 0x00000061, 4, 7, 0x00000001}, 48 { "cps", 3, 6, 20, 31, 0x00000f10, 16, 16, 0x00000000, 5, 5, 0x00000000 },
70 {"shsub16" , 2 , 6 , 20, 27, 0x00000063, 4, 7, 0x00000007}, 49 { "pld", 4, 4, 26, 31, 0x0000003d, 24, 24, 0x00000001, 20, 22, 0x00000005, 12, 15, 0x0000000f },
71 {"umaal" , 2 , 6 , 20, 27, 0x00000004, 4, 7, 0x00000009}, 50 { "setend", 2, 6, 16, 31, 0x0000f101, 4, 7, 0x00000000 },
72 {"uxtab16" , 2 , 6 , 20, 27, 0x0000006c, 4, 7, 0x00000007}, 51 { "clrex", 1, 6, 0, 31, 0xf57ff01f },
73 {"usubaddx" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000005}, 52 { "rev16", 2, 6, 16, 27, 0x000006bf, 4, 11, 0x000000fb },
74 {"usub8" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x0000000f}, 53 { "usad8", 3, 6, 20, 27, 0x00000078, 12, 15, 0x0000000f, 4, 7, 0x00000001 },
75 {"usub16" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000007}, 54 { "sxtb", 2, 6, 16, 27, 0x000006af, 4, 7, 0x00000007 },
76 {"usat16" , 2 , 6 , 20, 27, 0x0000006e, 4, 7, 0x00000003}, 55 { "uxtb", 2, 6, 16, 27, 0x000006ef, 4, 7, 0x00000007 },
77 {"usada8" , 2 , 6 , 20, 27, 0x00000078, 4, 7, 0x00000001}, 56 { "sxth", 2, 6, 16, 27, 0x000006bf, 4, 7, 0x00000007 },
78 {"uqsubaddx" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000005}, 57 { "sxtb16", 2, 6, 16, 27, 0x0000068f, 4, 7, 0x00000007 },
79 {"uqsub8" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x0000000f}, 58 { "uxth", 2, 6, 16, 27, 0x000006ff, 4, 7, 0x00000007 },
80 {"uqsub16" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000007}, 59 { "uxtb16", 2, 6, 16, 27, 0x000006cf, 4, 7, 0x00000007 },
81 {"uqaddsubx" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000003}, 60 { "cpy", 2, 6, 20, 27, 0x0000001a, 4, 11, 0x00000000 },
82 {"uqadd8" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000009}, 61 { "uxtab", 2, 6, 20, 27, 0x0000006e, 4, 9, 0x00000007 },
83 {"uqadd16" , 2 , 6 , 20, 27, 0x00000066, 4, 7, 0x00000001}, 62 { "ssub8", 2, 6, 20, 27, 0x00000061, 4, 7, 0x0000000f },
84 {"sxtab" , 2 , 6 , 20, 27, 0x0000006a, 4, 7, 0x00000007}, 63 { "shsub8", 2, 6, 20, 27, 0x00000063, 4, 7, 0x0000000f },
85 {"uhsubaddx" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000005}, 64 { "ssubaddx", 2, 6, 20, 27, 0x00000061, 4, 7, 0x00000005 },
86 {"uhsub8" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x0000000f}, 65 { "strex", 2, 6, 20, 27, 0x00000018, 4, 7, 0x00000009 },
87 {"uhsub16" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000007}, 66 { "strexb", 2, 7, 20, 27, 0x0000001c, 4, 7, 0x00000009 },
88 {"uhaddsubx" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000003}, 67 { "swp", 2, 0, 20, 27, 0x00000010, 4, 7, 0x00000009 },
89 {"uhadd8" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000009}, 68 { "swpb", 2, 0, 20, 27, 0x00000014, 4, 7, 0x00000009 },
90 {"uhadd16" , 2 , 6 , 20, 27, 0x00000067, 4, 7, 0x00000001}, 69 { "ssub16", 2, 6, 20, 27, 0x00000061, 4, 7, 0x00000007 },
91 {"uaddsubx" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000003}, 70 { "ssat16", 2, 6, 20, 27, 0x0000006a, 4, 7, 0x00000003 },
92 {"uadd8" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000009}, 71 { "shsubaddx", 2, 6, 20, 27, 0x00000063, 4, 7, 0x00000005 },
93 {"uadd16" , 2 , 6 , 20, 27, 0x00000065, 4, 7, 0x00000001}, 72 { "qsubaddx", 2, 6, 20, 27, 0x00000062, 4, 7, 0x00000005 },
94 {"sxtah" , 2 , 6 , 20, 27, 0x0000006b, 4, 7, 0x00000007}, 73 { "shaddsubx", 2, 6, 20, 27, 0x00000063, 4, 7, 0x00000003 },
95 {"sxtab16" , 2 , 6 , 20, 27, 0x00000068, 4, 7, 0x00000007}, 74 { "shadd8", 2, 6, 20, 27, 0x00000063, 4, 7, 0x00000009 },
96 {"qadd8" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000009}, 75 { "shadd16", 2, 6, 20, 27, 0x00000063, 4, 7, 0x00000001 },
97 {"bxj" , 2 , 5 , 20, 27, 0x00000012, 4, 7, 0x00000002}, 76 { "sel", 2, 6, 20, 27, 0x00000068, 4, 7, 0x0000000b },
98 {"clz" , 2 , 3 , 20, 27, 0x00000016, 4, 7, 0x00000001}, 77 { "saddsubx", 2, 6, 20, 27, 0x00000061, 4, 7, 0x00000003 },
99 {"uxtah" , 2 , 6 , 20, 27, 0x0000006f, 4, 7, 0x00000007}, 78 { "sadd8", 2, 6, 20, 27, 0x00000061, 4, 7, 0x00000009 },
100 {"bx" , 2 , 2 , 20, 27, 0x00000012, 4, 7, 0x00000001}, 79 { "sadd16", 2, 6, 20, 27, 0x00000061, 4, 7, 0x00000001 },
101 {"rev" , 2 , 6 , 20, 27, 0x0000006b, 4, 7, 0x00000003}, 80 { "shsub16", 2, 6, 20, 27, 0x00000063, 4, 7, 0x00000007 },
102 {"blx" , 2 , 3 , 20, 27, 0x00000012, 4, 7, 0x00000003}, 81 { "umaal", 2, 6, 20, 27, 0x00000004, 4, 7, 0x00000009 },
103 {"revsh" , 2 , 6 , 20, 27, 0x0000006f, 4, 7, 0x0000000b}, 82 { "uxtab16", 2, 6, 20, 27, 0x0000006c, 4, 7, 0x00000007 },
104 {"qadd" , 2 , 4 , 20, 27, 0x00000010, 4, 7, 0x00000005}, 83 { "usubaddx", 2, 6, 20, 27, 0x00000065, 4, 7, 0x00000005 },
105 {"qadd16" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000001}, 84 { "usub8", 2, 6, 20, 27, 0x00000065, 4, 7, 0x0000000f },
106 {"qaddsubx" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000003}, 85 { "usub16", 2, 6, 20, 27, 0x00000065, 4, 7, 0x00000007 },
107 {"ldrex" , 2 , 0 , 20, 27, 0x00000019, 4, 7, 0x00000009}, 86 { "usat16", 2, 6, 20, 27, 0x0000006e, 4, 7, 0x00000003 },
108 {"qdadd" , 2 , 4 , 20, 27, 0x00000014, 4, 7, 0x00000005}, 87 { "usada8", 2, 6, 20, 27, 0x00000078, 4, 7, 0x00000001 },
109 {"qdsub" , 2 , 4 , 20, 27, 0x00000016, 4, 7, 0x00000005}, 88 { "uqsubaddx", 2, 6, 20, 27, 0x00000066, 4, 7, 0x00000005 },
110 {"qsub" , 2 , 4 , 20, 27, 0x00000012, 4, 7, 0x00000005}, 89 { "uqsub8", 2, 6, 20, 27, 0x00000066, 4, 7, 0x0000000f },
111 {"ldrexb" , 2 , 7 , 20, 27, 0x0000001d, 4, 7, 0x00000009}, 90 { "uqsub16", 2, 6, 20, 27, 0x00000066, 4, 7, 0x00000007 },
112 {"qsub8" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x0000000f}, 91 { "uqaddsubx", 2, 6, 20, 27, 0x00000066, 4, 7, 0x00000003 },
113 {"qsub16" , 2 , 6 , 20, 27, 0x00000062, 4, 7, 0x00000007}, 92 { "uqadd8", 2, 6, 20, 27, 0x00000066, 4, 7, 0x00000009 },
114 {"smuad" , 4 , 6 , 20, 27, 0x00000070, 12, 15, 0x0000000f, 6, 7, 0x00000000, 4, 4, 0x00000001}, 93 { "uqadd16", 2, 6, 20, 27, 0x00000066, 4, 7, 0x00000001 },
115 {"smmul" , 4 , 6 , 20, 27, 0x00000075, 12, 15, 0x0000000f, 6, 7, 0x00000000, 4, 4, 0x00000001}, 94 { "sxtab", 2, 6, 20, 27, 0x0000006a, 4, 7, 0x00000007 },
116 {"smusd" , 4 , 6 , 20, 27, 0x00000070, 12, 15, 0x0000000f, 6, 7, 0x00000001, 4, 4, 0x00000001}, 95 { "uhsubaddx", 2, 6, 20, 27, 0x00000067, 4, 7, 0x00000005 },
117 {"smlsd" , 3 , 6 , 20, 27, 0x00000070, 6, 7, 0x00000001, 4, 4, 0x00000001}, 96 { "uhsub8", 2, 6, 20, 27, 0x00000067, 4, 7, 0x0000000f },
118 {"smlsld" , 3 , 6 , 20, 27, 0x00000074, 6, 7, 0x00000001, 4, 4, 0x00000001}, 97 { "uhsub16", 2, 6, 20, 27, 0x00000067, 4, 7, 0x00000007 },
119 {"smmla" , 3 , 6 , 20, 27, 0x00000075, 6, 7, 0x00000000, 4, 4, 0x00000001}, 98 { "uhaddsubx", 2, 6, 20, 27, 0x00000067, 4, 7, 0x00000003 },
120 {"smmls" , 3 , 6 , 20, 27, 0x00000075, 6, 7, 0x00000003, 4, 4, 0x00000001}, 99 { "uhadd8", 2, 6, 20, 27, 0x00000067, 4, 7, 0x00000009 },
121 {"smlald" , 3 , 6 , 20, 27, 0x00000074, 6, 7, 0x00000000, 4, 4, 0x00000001}, 100 { "uhadd16", 2, 6, 20, 27, 0x00000067, 4, 7, 0x00000001 },
122 {"smlad" , 3 , 6 , 20, 27, 0x00000070, 6, 7, 0x00000000, 4, 4, 0x00000001}, 101 { "uaddsubx", 2, 6, 20, 27, 0x00000065, 4, 7, 0x00000003 },
123 {"smlaw" , 3 , 4 , 20, 27, 0x00000012, 7, 7, 0x00000001, 4, 5, 0x00000000}, 102 { "uadd8", 2, 6, 20, 27, 0x00000065, 4, 7, 0x00000009 },
124 {"smulw" , 3 , 4 , 20, 27, 0x00000012, 7, 7, 0x00000001, 4, 5, 0x00000002}, 103 { "uadd16", 2, 6, 20, 27, 0x00000065, 4, 7, 0x00000001 },
125 {"pkhtb" , 2 , 6 , 20, 27, 0x00000068, 4, 6, 0x00000005}, 104 { "sxtah", 2, 6, 20, 27, 0x0000006b, 4, 7, 0x00000007 },
126 {"pkhbt" , 2 , 6 , 20, 27, 0x00000068, 4, 6, 0x00000001}, 105 { "sxtab16", 2, 6, 20, 27, 0x00000068, 4, 7, 0x00000007 },
127 {"smul" , 3 , 4 , 20, 27, 0x00000016, 7, 7, 0x00000001, 4, 4, 0x00000000}, 106 { "qadd8", 2, 6, 20, 27, 0x00000062, 4, 7, 0x00000009 },
128 {"smlalxy" , 3 , 4 , 20, 27, 0x00000014, 7, 7, 0x00000001, 4, 4, 0x00000000}, 107 { "bxj", 2, 5, 20, 27, 0x00000012, 4, 7, 0x00000002 },
129// {"smlal" , 2 , 4 , 21, 27, 0x00000007, 4, 7, 0x00000009}, 108 { "clz", 2, 3, 20, 27, 0x00000016, 4, 7, 0x00000001 },
130 {"smla" , 3 , 4 , 20, 27, 0x00000010, 7, 7, 0x00000001, 4, 4, 0x00000000}, 109 { "uxtah", 2, 6, 20, 27, 0x0000006f, 4, 7, 0x00000007 },
131 {"mcrr" , 1 , 6 , 20, 27, 0x000000c4}, 110 { "bx", 2, 2, 20, 27, 0x00000012, 4, 7, 0x00000001 },
132 {"mrrc" , 1 , 6 , 20, 27, 0x000000c5}, 111 { "rev", 2, 6, 20, 27, 0x0000006b, 4, 7, 0x00000003 },
133 {"cmp" , 2 , 0 , 26, 27, 0x00000000, 20, 24, 0x00000015}, 112 { "blx", 2, 3, 20, 27, 0x00000012, 4, 7, 0x00000003 },
134 {"tst" , 2 , 0 , 26, 27, 0x00000000, 20, 24, 0x00000011}, 113 { "revsh", 2, 6, 20, 27, 0x0000006f, 4, 7, 0x0000000b },
135 {"teq" , 2 , 0 , 26, 27, 0x00000000, 20, 24, 0x00000013}, 114 { "qadd", 2, 4, 20, 27, 0x00000010, 4, 7, 0x00000005 },
136 {"cmn" , 2 , 0 , 26, 27, 0x00000000, 20, 24, 0x00000017}, 115 { "qadd16", 2, 6, 20, 27, 0x00000062, 4, 7, 0x00000001 },
137 {"smull" , 2 , 0 , 21, 27, 0x00000006, 4, 7, 0x00000009}, 116 { "qaddsubx", 2, 6, 20, 27, 0x00000062, 4, 7, 0x00000003 },
138 {"umull" , 2 , 0 , 21, 27, 0x00000004, 4, 7, 0x00000009}, 117 { "ldrex", 2, 0, 20, 27, 0x00000019, 4, 7, 0x00000009 },
139 {"umlal" , 2 , 0 , 21, 27, 0x00000005, 4, 7, 0x00000009}, 118 { "qdadd", 2, 4, 20, 27, 0x00000014, 4, 7, 0x00000005 },
140 {"smlal" , 2 , 0 , 21, 27, 0x00000007, 4, 7, 0x00000009}, 119 { "qdsub", 2, 4, 20, 27, 0x00000016, 4, 7, 0x00000005 },
141 {"mul" , 2 , 0 , 21, 27, 0x00000000, 4, 7, 0x00000009}, 120 { "qsub", 2, 4, 20, 27, 0x00000012, 4, 7, 0x00000005 },
142 {"mla" , 2 , 0 , 21, 27, 0x00000001, 4, 7, 0x00000009}, 121 { "ldrexb", 2, 7, 20, 27, 0x0000001d, 4, 7, 0x00000009 },
143 {"ssat" , 2 , 6 , 21, 27, 0x00000035, 4, 5, 0x00000001}, 122 { "qsub8", 2, 6, 20, 27, 0x00000062, 4, 7, 0x0000000f },
144 {"usat" , 2 , 6 , 21, 27, 0x00000037, 4, 5, 0x00000001}, 123 { "qsub16", 2, 6, 20, 27, 0x00000062, 4, 7, 0x00000007 },
145 {"mrs" , 4 , 0 , 23, 27, 0x00000002, 20, 21, 0x00000000, 16, 19, 0x0000000f, 0, 11, 0x00000000}, 124 { "smuad", 4, 6, 20, 27, 0x00000070, 12, 15, 0x0000000f, 6, 7, 0x00000000, 4, 4, 0x00000001 },
146 {"msr" , 3 , 0 , 23, 27, 0x00000002, 20, 21, 0x00000002, 4, 7, 0x00000000}, 125 { "smmul", 4, 6, 20, 27, 0x00000075, 12, 15, 0x0000000f, 6, 7, 0x00000000, 4, 4, 0x00000001 },
147 {"and" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000000}, 126 { "smusd", 4, 6, 20, 27, 0x00000070, 12, 15, 0x0000000f, 6, 7, 0x00000001, 4, 4, 0x00000001 },
148 {"bic" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x0000000e}, 127 { "smlsd", 3, 6, 20, 27, 0x00000070, 6, 7, 0x00000001, 4, 4, 0x00000001 },
149 {"ldm" , 3 , 0 , 25, 27, 0x00000004, 20, 22, 0x00000005, 15, 15, 0x00000000}, 128 { "smlsld", 3, 6, 20, 27, 0x00000074, 6, 7, 0x00000001, 4, 4, 0x00000001 },
150 {"eor" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000001}, 129 { "smmla", 3, 6, 20, 27, 0x00000075, 6, 7, 0x00000000, 4, 4, 0x00000001 },
151 {"add" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000004}, 130 { "smmls", 3, 6, 20, 27, 0x00000075, 6, 7, 0x00000003, 4, 4, 0x00000001 },
152 {"rsb" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000003}, 131 { "smlald", 3, 6, 20, 27, 0x00000074, 6, 7, 0x00000000, 4, 4, 0x00000001 },
153 {"rsc" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000007}, 132 { "smlad", 3, 6, 20, 27, 0x00000070, 6, 7, 0x00000000, 4, 4, 0x00000001 },
154 {"sbc" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000006}, 133 { "smlaw", 3, 4, 20, 27, 0x00000012, 7, 7, 0x00000001, 4, 5, 0x00000000 },
155 {"adc" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000005}, 134 { "smulw", 3, 4, 20, 27, 0x00000012, 7, 7, 0x00000001, 4, 5, 0x00000002 },
156 {"sub" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x00000002}, 135 { "pkhtb", 2, 6, 20, 27, 0x00000068, 4, 6, 0x00000005 },
157 {"orr" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x0000000c}, 136 { "pkhbt", 2, 6, 20, 27, 0x00000068, 4, 6, 0x00000001 },
158 {"mvn" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x0000000f}, 137 { "smul", 3, 4, 20, 27, 0x00000016, 7, 7, 0x00000001, 4, 4, 0x00000000 },
159 {"mov" , 2 , 0 , 26, 27, 0x00000000, 21, 24, 0x0000000d}, 138 { "smlalxy", 3, 4, 20, 27, 0x00000014, 7, 7, 0x00000001, 4, 4, 0x00000000 },
160 {"stm" , 2 , 0 , 25, 27, 0x00000004, 20, 22, 0x00000004}, 139 // {"smlal" , 2 , 4 , 21, 27, 0x00000007, 4, 7, 0x00000009},
161 {"ldm" , 4 , 0 , 25, 27, 0x00000004, 22, 22, 0x00000001, 20, 20, 0x00000001, 15, 15, 0x00000001}, 140 { "smla", 3, 4, 20, 27, 0x00000010, 7, 7, 0x00000001, 4, 4, 0x00000000 },
162 {"ldrsh" , 3 , 2 , 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000f}, 141 { "mcrr", 1, 6, 20, 27, 0x000000c4 },
163 {"stm" , 3 , 0 , 25, 27, 0x00000004, 22, 22, 0x00000000, 20, 20, 0x00000000}, 142 { "mrrc", 1, 6, 20, 27, 0x000000c5 },
164 {"ldm" , 3 , 0 , 25, 27, 0x00000004, 22, 22, 0x00000000, 20, 20, 0x00000001}, 143 { "cmp", 2, 0, 26, 27, 0x00000000, 20, 24, 0x00000015 },
165 {"ldrsb" , 3 , 2 , 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000d}, 144 { "tst", 2, 0, 26, 27, 0x00000000, 20, 24, 0x00000011 },
166 {"strd" , 3 , 4 , 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000f}, 145 { "teq", 2, 0, 26, 27, 0x00000000, 20, 24, 0x00000013 },
167 {"ldrh" , 3 , 0 , 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000b}, 146 { "cmn", 2, 0, 26, 27, 0x00000000, 20, 24, 0x00000017 },
168 {"strh" , 3 , 0 , 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000b}, 147 { "smull", 2, 0, 21, 27, 0x00000006, 4, 7, 0x00000009 },
169 {"ldrd" , 3 , 4 , 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000d}, 148 { "umull", 2, 0, 21, 27, 0x00000004, 4, 7, 0x00000009 },
170 {"strt" , 3 , 0 , 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000002}, 149 { "umlal", 2, 0, 21, 27, 0x00000005, 4, 7, 0x00000009 },
171 {"strbt" , 3 , 0 , 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000006}, 150 { "smlal", 2, 0, 21, 27, 0x00000007, 4, 7, 0x00000009 },
172 {"ldrbt" , 3 , 0 , 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000007}, 151 { "mul", 2, 0, 21, 27, 0x00000000, 4, 7, 0x00000009 },
173 {"ldrt" , 3 , 0 , 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000003}, 152 { "mla", 2, 0, 21, 27, 0x00000001, 4, 7, 0x00000009 },
174 {"mrc" , 3 , 6 , 24, 27, 0x0000000e, 20, 20, 0x00000001, 4, 4, 0x00000001}, 153 { "ssat", 2, 6, 21, 27, 0x00000035, 4, 5, 0x00000001 },
175 {"mcr" , 3 , 0 , 24, 27, 0x0000000e, 20, 20, 0x00000000, 4, 4, 0x00000001}, 154 { "usat", 2, 6, 21, 27, 0x00000037, 4, 5, 0x00000001 },
176 {"msr" , 2 , 0 , 23, 27, 0x00000006, 20, 21, 0x00000002}, 155 { "mrs", 4, 0, 23, 27, 0x00000002, 20, 21, 0x00000000, 16, 19, 0x0000000f, 0, 11, 0x00000000 },
177 {"ldrb" , 3 , 0 , 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000001}, 156 { "msr", 3, 0, 23, 27, 0x00000002, 20, 21, 0x00000002, 4, 7, 0x00000000 },
178 {"strb" , 3 , 0 , 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000000}, 157 { "and", 2, 0, 26, 27, 0x00000000, 21, 24, 0x00000000 },
179 {"ldr" , 4 , 0 , 28, 31, 0x0000000e, 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001}, 158 { "bic", 2, 0, 26, 27, 0x00000000, 21, 24, 0x0000000e },
180 {"ldrcond" , 3 , 0 , 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001}, 159 { "ldm", 3, 0, 25, 27, 0x00000004, 20, 22, 0x00000005, 15, 15, 0x00000000 },
181 {"str" , 3 , 0 , 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000000}, 160 { "eor", 2, 0, 26, 27, 0x00000000, 21, 24, 0x00000001 },
182 {"cdp" , 2 , 0 , 24, 27, 0x0000000e, 4, 4, 0x00000000}, 161 { "add", 2, 0, 26, 27, 0x00000000, 21, 24, 0x00000004 },
183 {"stc" , 2 , 0 , 25, 27, 0x00000006, 20, 20, 0x00000000}, 162 { "rsb", 2, 0, 26, 27, 0x00000000, 21, 24, 0x00000003 },
184 {"ldc" , 2 , 0 , 25, 27, 0x00000006, 20, 20, 0x00000001}, 163 { "rsc", 2, 0, 26, 27, 0x00000000, 21, 24, 0x00000007 },
185 {"swi" , 1 , 0 , 24, 27, 0x0000000f}, 164 { "sbc", 2, 0, 26, 27, 0x00000000, 21, 24, 0x00000006 },
186 {"bbl" , 1 , 0 , 25, 27, 0x00000005}, 165 { "adc", 2, 0, 26, 27, 0x00000000, 21, 24, 0x00000005 },
166 { "sub", 2, 0, 26, 27, 0x00000000, 21, 24, 0x00000002 },
167 { "orr", 2, 0, 26, 27, 0x00000000, 21, 24, 0x0000000c },
168 { "mvn", 2, 0, 26, 27, 0x00000000, 21, 24, 0x0000000f },
169 { "mov", 2, 0, 26, 27, 0x00000000, 21, 24, 0x0000000d },
170 { "stm", 2, 0, 25, 27, 0x00000004, 20, 22, 0x00000004 },
171 { "ldm", 4, 0, 25, 27, 0x00000004, 22, 22, 0x00000001, 20, 20, 0x00000001, 15, 15, 0x00000001 },
172 { "ldrsh", 3, 2, 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000f },
173 { "stm", 3, 0, 25, 27, 0x00000004, 22, 22, 0x00000000, 20, 20, 0x00000000 },
174 { "ldm", 3, 0, 25, 27, 0x00000004, 22, 22, 0x00000000, 20, 20, 0x00000001 },
175 { "ldrsb", 3, 2, 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000d },
176 { "strd", 3, 4, 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000f },
177 { "ldrh", 3, 0, 25, 27, 0x00000000, 20, 20, 0x00000001, 4, 7, 0x0000000b },
178 { "strh", 3, 0, 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000b },
179 { "ldrd", 3, 4, 25, 27, 0x00000000, 20, 20, 0x00000000, 4, 7, 0x0000000d },
180 { "strt", 3, 0, 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000002 },
181 { "strbt", 3, 0, 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000006 },
182 { "ldrbt", 3, 0, 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000007 },
183 { "ldrt", 3, 0, 26, 27, 0x00000001, 24, 24, 0x00000000, 20, 22, 0x00000003 },
184 { "mrc", 3, 6, 24, 27, 0x0000000e, 20, 20, 0x00000001, 4, 4, 0x00000001 },
185 { "mcr", 3, 0, 24, 27, 0x0000000e, 20, 20, 0x00000000, 4, 4, 0x00000001 },
186 { "msr", 2, 0, 23, 27, 0x00000006, 20, 21, 0x00000002 },
187 { "ldrb", 3, 0, 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000001 },
188 { "strb", 3, 0, 26, 27, 0x00000001, 22, 22, 0x00000001, 20, 20, 0x00000000 },
189 { "ldr", 4, 0, 28, 31, 0x0000000e, 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001 },
190 { "ldrcond", 3, 0, 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000001 },
191 { "str", 3, 0, 26, 27, 0x00000001, 22, 22, 0x00000000, 20, 20, 0x00000000 },
192 { "cdp", 2, 0, 24, 27, 0x0000000e, 4, 4, 0x00000000 },
193 { "stc", 2, 0, 25, 27, 0x00000006, 20, 20, 0x00000000 },
194 { "ldc", 2, 0, 25, 27, 0x00000006, 20, 20, 0x00000001 },
195 { "swi", 1, 0, 24, 27, 0x0000000f },
196 { "bbl", 1, 0, 25, 27, 0x00000005 },
187}; 197};
188 198
189const ISEITEM arm_exclusion_code[] = { 199const ISEITEM arm_exclusion_code[] = {
190 #define VFP_DECODE_EXCLUSION 200 { "vmla", 0, ARMVFP2, 0 },
191 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 201 { "vmls", 0, ARMVFP2, 0 },
192 #undef VFP_DECODE_EXCLUSION 202 { "vnmla", 0, ARMVFP2, 0 },
193 {"srs" , 0 , 6 , 0}, 203 { "vnmla", 0, ARMVFP2, 0 },
194 {"rfe" , 0 , 6 , 0}, 204 { "vnmls", 0, ARMVFP2, 0 },
195 {"bkpt" , 0 , 3 , 0}, 205 { "vnmul", 0, ARMVFP2, 0 },
196 {"blx" , 0 , 3 , 0}, 206 { "vmul", 0, ARMVFP2, 0 },
197 {"cps" , 0 , 6 , 0}, 207 { "vadd", 0, ARMVFP2, 0 },
198 {"pld" , 0 , 4 , 0}, 208 { "vsub", 0, ARMVFP2, 0 },
199 {"setend" , 0 , 6 , 0}, 209 { "vdiv", 0, ARMVFP2, 0 },
200 {"clrex" , 0 , 6 , 0}, 210 { "vmov(i)", 0, ARMVFP3, 0 },
201 {"rev16" , 0 , 6 , 0}, 211 { "vmov(r)", 0, ARMVFP3, 0 },
202 {"usad8" , 0 , 6 , 0}, 212 { "vabs", 0, ARMVFP2, 0 },
203 {"sxtb" , 0 , 6 , 0}, 213 { "vneg", 0, ARMVFP2, 0 },
204 {"uxtb" , 0 , 6 , 0}, 214 { "vsqrt", 0, ARMVFP2, 0 },
205 {"sxth" , 0 , 6 , 0}, 215 { "vcmp", 0, ARMVFP2, 0 },
206 {"sxtb16" , 0 , 6 , 0}, 216 { "vcmp2", 0, ARMVFP2, 0 },
207 {"uxth" , 0 , 6 , 0}, 217 { "vcvt(bff)", 0, ARMVFP3, 4, 4, 1 },
208 {"uxtb16" , 0 , 6 , 0}, 218 { "vcvt(bds)", 0, ARMVFP2, 0 },
209 {"cpy" , 0 , 6 , 0}, 219 { "vcvt(bfi)", 0, ARMVFP2, 0 },
210 {"uxtab" , 0 , 6 , 0}, 220 { "vmovbrs", 0, ARMVFP2, 0 },
211 {"ssub8" , 0 , 6 , 0}, 221 { "vmsr", 0, ARMVFP2, 0 },
212 {"shsub8" , 0 , 6 , 0}, 222 { "vmovbrc", 0, ARMVFP2, 0 },
213 {"ssubaddx" , 0 , 6 , 0}, 223 { "vmrs", 0, ARMVFP2, 0 },
214 {"strex" , 0 , 6 , 0}, 224 { "vmovbcr", 0, ARMVFP2, 0 },
215 {"strexb" , 0 , 7 , 0}, 225 { "vmovbrrss", 0, ARMVFP2, 0 },
216 {"swp" , 0 , 0 , 0}, 226 { "vmovbrrd", 0, ARMVFP2, 0 },
217 {"swpb" , 0 , 0 , 0}, 227 { "vstr", 0, ARMVFP2, 0 },
218 {"ssub16" , 0 , 6 , 0}, 228 { "vpush", 0, ARMVFP2, 0 },
219 {"ssat16" , 0 , 6 , 0}, 229 { "vstm", 0, ARMVFP2, 0 },
220 {"shsubaddx" , 0 , 6 , 0}, 230 { "vpop", 0, ARMVFP2, 0 },
221 {"qsubaddx" , 0 , 6 , 0}, 231 { "vldr", 0, ARMVFP2, 0 },
222 {"shaddsubx" , 0 , 6 , 0}, 232 { "vldm", 0, ARMVFP2, 0 },
223 {"shadd8" , 0 , 6 , 0}, 233
224 {"shadd16" , 0 , 6 , 0}, 234 { "srs", 0, 6, 0 },
225 {"sel" , 0 , 6 , 0}, 235 { "rfe", 0, 6, 0 },
226 {"saddsubx" , 0 , 6 , 0}, 236 { "bkpt", 0, 3, 0 },
227 {"sadd8" , 0 , 6 , 0}, 237 { "blx", 0, 3, 0 },
228 {"sadd16" , 0 , 6 , 0}, 238 { "cps", 0, 6, 0 },
229 {"shsub16" , 0 , 6 , 0}, 239 { "pld", 0, 4, 0 },
230 {"umaal" , 0 , 6 , 0}, 240 { "setend", 0, 6, 0 },
231 {"uxtab16" , 0 , 6 , 0}, 241 { "clrex", 0, 6, 0 },
232 {"usubaddx" , 0 , 6 , 0}, 242 { "rev16", 0, 6, 0 },
233 {"usub8" , 0 , 6 , 0}, 243 { "usad8", 0, 6, 0 },
234 {"usub16" , 0 , 6 , 0}, 244 { "sxtb", 0, 6, 0 },
235 {"usat16" , 0 , 6 , 0}, 245 { "uxtb", 0, 6, 0 },
236 {"usada8" , 0 , 6 , 0}, 246 { "sxth", 0, 6, 0 },
237 {"uqsubaddx" , 0 , 6 , 0}, 247 { "sxtb16", 0, 6, 0 },
238 {"uqsub8" , 0 , 6 , 0}, 248 { "uxth", 0, 6, 0 },
239 {"uqsub16" , 0 , 6 , 0}, 249 { "uxtb16", 0, 6, 0 },
240 {"uqaddsubx" , 0 , 6 , 0}, 250 { "cpy", 0, 6, 0 },
241 {"uqadd8" , 0 , 6 , 0}, 251 { "uxtab", 0, 6, 0 },
242 {"uqadd16" , 0 , 6 , 0}, 252 { "ssub8", 0, 6, 0 },
243 {"sxtab" , 0 , 6 , 0}, 253 { "shsub8", 0, 6, 0 },
244 {"uhsubaddx" , 0 , 6 , 0}, 254 { "ssubaddx", 0, 6, 0 },
245 {"uhsub8" , 0 , 6 , 0}, 255 { "strex", 0, 6, 0 },
246 {"uhsub16" , 0 , 6 , 0}, 256 { "strexb", 0, 7, 0 },
247 {"uhaddsubx" , 0 , 6 , 0}, 257 { "swp", 0, 0, 0 },
248 {"uhadd8" , 0 , 6 , 0}, 258 { "swpb", 0, 0, 0 },
249 {"uhadd16" , 0 , 6 , 0}, 259 { "ssub16", 0, 6, 0 },
250 {"uaddsubx" , 0 , 6 , 0}, 260 { "ssat16", 0, 6, 0 },
251 {"uadd8" , 0 , 6 , 0}, 261 { "shsubaddx", 0, 6, 0 },
252 {"uadd16" , 0 , 6 , 0}, 262 { "qsubaddx", 0, 6, 0 },
253 {"sxtah" , 0 , 6 , 0}, 263 { "shaddsubx", 0, 6, 0 },
254 {"sxtab16" , 0 , 6 , 0}, 264 { "shadd8", 0, 6, 0 },
255 {"qadd8" , 0 , 6 , 0}, 265 { "shadd16", 0, 6, 0 },
256 {"bxj" , 0 , 5 , 0}, 266 { "sel", 0, 6, 0 },
257 {"clz" , 0 , 3 , 0}, 267 { "saddsubx", 0, 6, 0 },
258 {"uxtah" , 0 , 6 , 0}, 268 { "sadd8", 0, 6, 0 },
259 {"bx" , 0 , 2 , 0}, 269 { "sadd16", 0, 6, 0 },
260 {"rev" , 0 , 6 , 0}, 270 { "shsub16", 0, 6, 0 },
261 {"blx" , 0 , 3 , 0}, 271 { "umaal", 0, 6, 0 },
262 {"revsh" , 0 , 6 , 0}, 272 { "uxtab16", 0, 6, 0 },
263 {"qadd" , 0 , 4 , 0}, 273 { "usubaddx", 0, 6, 0 },
264 {"qadd16" , 0 , 6 , 0}, 274 { "usub8", 0, 6, 0 },
265 {"qaddsubx" , 0 , 6 , 0}, 275 { "usub16", 0, 6, 0 },
266 {"ldrex" , 0 , 0 , 0}, 276 { "usat16", 0, 6, 0 },
267 {"qdadd" , 0 , 4 , 0}, 277 { "usada8", 0, 6, 0 },
268 {"qdsub" , 0 , 4 , 0}, 278 { "uqsubaddx", 0, 6, 0 },
269 {"qsub" , 0 , 4 , 0}, 279 { "uqsub8", 0, 6, 0 },
270 {"ldrexb" , 0 , 7 , 0}, 280 { "uqsub16", 0, 6, 0 },
271 {"qsub8" , 0 , 6 , 0}, 281 { "uqaddsubx", 0, 6, 0 },
272 {"qsub16" , 0 , 6 , 0}, 282 { "uqadd8", 0, 6, 0 },
273 {"smuad" , 0 , 6 , 0}, 283 { "uqadd16", 0, 6, 0 },
274 {"smmul" , 0 , 6 , 0}, 284 { "sxtab", 0, 6, 0 },
275 {"smusd" , 0 , 6 , 0}, 285 { "uhsubaddx", 0, 6, 0 },
276 {"smlsd" , 0 , 6 , 0}, 286 { "uhsub8", 0, 6, 0 },
277 {"smlsld" , 0 , 6 , 0}, 287 { "uhsub16", 0, 6, 0 },
278 {"smmla" , 0 , 6 , 0}, 288 { "uhaddsubx", 0, 6, 0 },
279 {"smmls" , 0 , 6 , 0}, 289 { "uhadd8", 0, 6, 0 },
280 {"smlald" , 0 , 6 , 0}, 290 { "uhadd16", 0, 6, 0 },
281 {"smlad" , 0 , 6 , 0}, 291 { "uaddsubx", 0, 6, 0 },
282 {"smlaw" , 0 , 4 , 0}, 292 { "uadd8", 0, 6, 0 },
283 {"smulw" , 0 , 4 , 0}, 293 { "uadd16", 0, 6, 0 },
284 {"pkhtb" , 0 , 6 , 0}, 294 { "sxtah", 0, 6, 0 },
285 {"pkhbt" , 0 , 6 , 0}, 295 { "sxtab16", 0, 6, 0 },
286 {"smul" , 0 , 4 , 0}, 296 { "qadd8", 0, 6, 0 },
287 {"smlal" , 0 , 4 , 0}, 297 { "bxj", 0, 5, 0 },
288 {"smla" , 0 , 4 , 0}, 298 { "clz", 0, 3, 0 },
289 {"mcrr" , 0 , 6 , 0}, 299 { "uxtah", 0, 6, 0 },
290 {"mrrc" , 0 , 6 , 0}, 300 { "bx", 0, 2, 0 },
291 {"cmp" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 301 { "rev", 0, 6, 0 },
292 {"tst" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 302 { "blx", 0, 3, 0 },
293 {"teq" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 303 { "revsh", 0, 6, 0 },
294 {"cmn" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 304 { "qadd", 0, 4, 0 },
295 {"smull" , 0 , 0 , 0}, 305 { "qadd16", 0, 6, 0 },
296 {"umull" , 0 , 0 , 0}, 306 { "qaddsubx", 0, 6, 0 },
297 {"umlal" , 0 , 0 , 0}, 307 { "ldrex", 0, 0, 0 },
298 {"smlal" , 0 , 0 , 0}, 308 { "qdadd", 0, 4, 0 },
299 {"mul" , 0 , 0 , 0}, 309 { "qdsub", 0, 4, 0 },
300 {"mla" , 0 , 0 , 0}, 310 { "qsub", 0, 4, 0 },
301 {"ssat" , 0 , 6 , 0}, 311 { "ldrexb", 0, 7, 0 },
302 {"usat" , 0 , 6 , 0}, 312 { "qsub8", 0, 6, 0 },
303 {"mrs" , 0 , 0 , 0}, 313 { "qsub16", 0, 6, 0 },
304 {"msr" , 0 , 0 , 0}, 314 { "smuad", 0, 6, 0 },
305 {"and" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 315 { "smmul", 0, 6, 0 },
306 {"bic" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 316 { "smusd", 0, 6, 0 },
307 {"ldm" , 0 , 0 , 0}, 317 { "smlsd", 0, 6, 0 },
308 {"eor" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 318 { "smlsld", 0, 6, 0 },
309 {"add" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 319 { "smmla", 0, 6, 0 },
310 {"rsb" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 320 { "smmls", 0, 6, 0 },
311 {"rsc" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 321 { "smlald", 0, 6, 0 },
312 {"sbc" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 322 { "smlad", 0, 6, 0 },
313 {"adc" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 323 { "smlaw", 0, 4, 0 },
314 {"sub" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 324 { "smulw", 0, 4, 0 },
315 {"orr" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 325 { "pkhtb", 0, 6, 0 },
316 {"mvn" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 326 { "pkhbt", 0, 6, 0 },
317 {"mov" , 3 , 0 , 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000}, 327 { "smul", 0, 4, 0 },
318 {"stm" , 0 , 0 , 0}, 328 { "smlal", 0, 4, 0 },
319 {"ldm" , 0 , 0 , 0}, 329 { "smla", 0, 4, 0 },
320 {"ldrsh" , 0 , 2 , 0}, 330 { "mcrr", 0, 6, 0 },
321 {"stm" , 0 , 0 , 0}, 331 { "mrrc", 0, 6, 0 },
322 {"ldm" , 0 , 0 , 0}, 332 { "cmp", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
323 {"ldrsb" , 0 , 2 , 0}, 333 { "tst", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
324 {"strd" , 0 , 4 , 0}, 334 { "teq", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
325 {"ldrh" , 0 , 0 , 0}, 335 { "cmn", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
326 {"strh" , 0 , 0 , 0}, 336 { "smull", 0, 0, 0 },
327 {"ldrd" , 0 , 4 , 0}, 337 { "umull", 0, 0, 0 },
328 {"strt" , 0 , 0 , 0}, 338 { "umlal", 0, 0, 0 },
329 {"strbt" , 0 , 0 , 0}, 339 { "smlal", 0, 0, 0 },
330 {"ldrbt" , 0 , 0 , 0}, 340 { "mul", 0, 0, 0 },
331 {"ldrt" , 0 , 0 , 0}, 341 { "mla", 0, 0, 0 },
332 {"mrc" , 0 , 6 , 0}, 342 { "ssat", 0, 6, 0 },
333 {"mcr" , 0 , 0 , 0}, 343 { "usat", 0, 6, 0 },
334 {"msr" , 0 , 0 , 0}, 344 { "mrs", 0, 0, 0 },
335 {"ldrb" , 0 , 0 , 0}, 345 { "msr", 0, 0, 0 },
336 {"strb" , 0 , 0 , 0}, 346 { "and", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
337 {"ldr" , 0 , 0 , 0}, 347 { "bic", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
338 {"ldrcond" , 1 , 0 , 28, 31, 0x0000000e}, 348 { "ldm", 0, 0, 0 },
339 {"str" , 0 , 0 , 0}, 349 { "eor", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
340 {"cdp" , 0 , 0 , 0}, 350 { "add", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
341 {"stc" , 0 , 0 , 0}, 351 { "rsb", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
342 {"ldc" , 0 , 0 , 0}, 352 { "rsc", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
343 {"swi" , 0 , 0 , 0}, 353 { "sbc", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
344 {"bbl" , 0 , 0 , 0}, 354 { "adc", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
345 {"bl_1_thumb", 0, INVALID, 0},/* should be table[-4] */ 355 { "sub", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
346 {"bl_2_thumb", 0, INVALID, 0}, /* should be located at the end of the table[-3] */ 356 { "orr", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
347 {"blx_1_thumb", 0, INVALID, 0}, /* should be located at table[-2] */ 357 { "mvn", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
348 {"invalid", 0, INVALID, 0} 358 { "mov", 3, 0, 4, 4, 0x00000001, 7, 7, 0x00000001, 25, 25, 0x00000000 },
359 { "stm", 0, 0, 0 },
360 { "ldm", 0, 0, 0 },
361 { "ldrsh", 0, 2, 0 },
362 { "stm", 0, 0, 0 },
363 { "ldm", 0, 0, 0 },
364 { "ldrsb", 0, 2, 0 },
365 { "strd", 0, 4, 0 },
366 { "ldrh", 0, 0, 0 },
367 { "strh", 0, 0, 0 },
368 { "ldrd", 0, 4, 0 },
369 { "strt", 0, 0, 0 },
370 { "strbt", 0, 0, 0 },
371 { "ldrbt", 0, 0, 0 },
372 { "ldrt", 0, 0, 0 },
373 { "mrc", 0, 6, 0 },
374 { "mcr", 0, 0, 0 },
375 { "msr", 0, 0, 0 },
376 { "ldrb", 0, 0, 0 },
377 { "strb", 0, 0, 0 },
378 { "ldr", 0, 0, 0 },
379 { "ldrcond", 1, 0, 28, 31, 0x0000000e },
380 { "str", 0, 0, 0 },
381 { "cdp", 0, 0, 0 },
382 { "stc", 0, 0, 0 },
383 { "ldc", 0, 0, 0 },
384 { "swi", 0, 0, 0 },
385 { "bbl", 0, 0, 0 },
386 { "bl_1_thumb", 0, INVALID, 0 }, // Should be table[-4]
387 { "bl_2_thumb", 0, INVALID, 0 }, // Should be located at the end of the table[-3]
388 { "blx_1_thumb", 0, INVALID, 0 }, // Should be located at table[-2]
389 { "invalid", 0, INVALID, 0 }
349}; 390};
350 391
351int decode_arm_instr(uint32_t instr, int32_t *idx) 392int decode_arm_instr(uint32_t instr, int32_t *idx) {
352{ 393 int n = 0;
353 int n = 0; 394 int base = 0;
354 int base = 0; 395 int ret = DECODE_FAILURE;
355 int ret = DECODE_FAILURE; 396 int i = 0;
356 int i = 0; 397 int instr_slots = sizeof(arm_instruction) / sizeof(ISEITEM);
357 int instr_slots = sizeof(arm_instruction)/sizeof(ISEITEM); 398 for (i = 0; i < instr_slots; i++) {
358 for (i = 0; i < instr_slots; i++) 399 n = arm_instruction[i].attribute_value;
359 { 400 base = 0;
360// ret = DECODE_SUCCESS;
361 n = arm_instruction[i].attribute_value;
362 base = 0;
363 while (n) {
364 if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) {
365 /* clrex */
366 if (instr != arm_instruction[i].content[base + 2]) {
367 break;
368 }
369 } else if (BITS(arm_instruction[i].content[base], arm_instruction[i].content[base + 1]) != arm_instruction[i].content[base + 2]) {
370 break;
371 }
372 base += 3;
373 n --;
374 }
375 //All conditions is satisfied.
376 if (n == 0)
377 ret = DECODE_SUCCESS;
378 401
379 if (ret == DECODE_SUCCESS) { 402 while (n) {
380 n = arm_exclusion_code[i].attribute_value; 403 if (arm_instruction[i].content[base + 1] == 31 && arm_instruction[i].content[base] == 0) {
381 if (n != 0) { 404 // clrex
382 base = 0; 405 if (instr != arm_instruction[i].content[base + 2]) {
383 while (n) { 406 break;
384 if (BITS(arm_exclusion_code[i].content[base], arm_exclusion_code[i].content[base + 1]) != arm_exclusion_code[i].content[base + 2]) { 407 }
385 break; } 408 } else if (BITS(arm_instruction[i].content[base], arm_instruction[i].content[base + 1]) != arm_instruction[i].content[base + 2]) {
386 base += 3; 409 break;
387 n --; 410 }
388 } 411 base += 3;
389 //All conditions is satisfied. 412 n--;
390 if (n == 0) 413 }
391 ret = DECODE_FAILURE;
392 }
393 }
394 414
395 if (ret == DECODE_SUCCESS) { 415 // All conditions is satisfied.
396 *idx = i; 416 if (n == 0)
397 return ret; 417 ret = DECODE_SUCCESS;
398 }
399 }
400 return ret;
401}
402 418
419 if (ret == DECODE_SUCCESS) {
420 n = arm_exclusion_code[i].attribute_value;
421 if (n != 0) {
422 base = 0;
423 while (n) {
424 if (BITS(arm_exclusion_code[i].content[base], arm_exclusion_code[i].content[base + 1]) != arm_exclusion_code[i].content[base + 2]) {
425 break;
426 }
427 base += 3;
428 n--;
429 }
430
431 // All conditions is satisfied.
432 if (n == 0)
433 ret = DECODE_FAILURE;
434 }
435 }
436
437 if (ret == DECODE_SUCCESS) {
438 *idx = i;
439 return ret;
440 }
441 }
442 return ret;
443}
diff --git a/src/core/arm/dyncom/arm_dyncom_dec.h b/src/core/arm/dyncom/arm_dyncom_dec.h
index 19d94f369..70eb96e93 100644
--- a/src/core/arm/dyncom/arm_dyncom_dec.h
+++ b/src/core/arm/dyncom/arm_dyncom_dec.h
@@ -56,8 +56,6 @@
56#define RN ((instr >> 16) & 0xF) 56#define RN ((instr >> 16) & 0xF)
57/*xxxx xxxx xxxx xxxx xxxx xxxx xxxx 1111 */ 57/*xxxx xxxx xxxx xxxx xxxx xxxx xxxx 1111 */
58#define RM (instr & 0xF) 58#define RM (instr & 0xF)
59#define BIT(n) ((instr >> (n)) & 1)
60#define BITS(a,b) ((instr >> (a)) & ((1 << (1+(b)-(a)))-1))
61 59
62/* CP15 registers */ 60/* CP15 registers */
63#define OPCODE_1 BITS(21, 23) 61#define OPCODE_1 BITS(21, 23)
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 68012bffd..0ee103c56 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -1,27 +1,6 @@
1/* Copyright (C) 1// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
2* 2012 - Michael.Kang blackfin.kang@gmail.com 2// Licensed under GPLv2 or any later version
3* This program is free software; you can redistribute it and/or 3// Refer to the license.txt file included.
4* modify it under the terms of the GNU General Public License
5* as published by the Free Software Foundation; either version 2
6* of the License, or (at your option) any later version.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program; if not, write to the Free Software
15* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16*
17*/
18/**
19* @file arm_dyncom_interpreter.cpp
20* @brief The fast interpreter for arm
21* @author Michael.Kang blackfin.kang@gmail.com
22* @version 7849
23* @date 2012-03-15
24*/
25 4
26#define CITRA_IGNORE_EXIT(x) 5#define CITRA_IGNORE_EXIT(x)
27 6
@@ -39,10 +18,6 @@ using namespace std;
39#include "arm_dyncom_thumb.h" 18#include "arm_dyncom_thumb.h"
40#include "arm_dyncom_run.h" 19#include "arm_dyncom_run.h"
41#include "core/arm/skyeye_common/vfp/vfp.h" 20#include "core/arm/skyeye_common/vfp/vfp.h"
42/* shenoubang 2012-6-14 */
43#ifdef __WIN32__
44#include "bank_defs.h"
45#endif
46 21
47#include "core/mem_map.h" 22#include "core/mem_map.h"
48#include "core/hle/hle.h" 23#include "core/hle/hle.h"
@@ -58,325 +33,243 @@ enum {
58 THUMB = (1 << 7) 33 THUMB = (1 << 7)
59}; 34};
60 35
61#define USER_MODE_OPT 1 36#define USER_MODE_OPT 1
62#define HYBRID_MODE 0 // Enable for JIT mode 37#define HYBRID_MODE 0 // Enable for JIT mode
63 38
64#define THRESHOLD 1000 39#define THRESHOLD 1000
65#define DURATION 500 40#define DURATION 500
66//#define PRINT_PROFILE_INFO
67 41
68#define CHECK_RS if(RS == 15) rs += 8 42#define CHECK_RS if(RS == 15) rs += 8
69#define CHECK_RM if(RM == 15) rm += 8 43#define CHECK_RM if(RM == 15) rm += 8
70 44
71//#define BITS(s, a, b) (((s) >> (a)) & ((1 << (1 + (b) - (a))) - 1))
72#undef BITS 45#undef BITS
73#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1)) 46#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1))
74#define BIT(s, n) ((s >> (n)) & 1) 47#define BIT(s, n) ((s >> (n)) & 1)
75#define RM BITS(sht_oper, 0, 3) 48#define RM BITS(sht_oper, 0, 3)
76#define RS BITS(sht_oper, 8, 11) 49#define RS BITS(sht_oper, 8, 11)
77 50
78#define glue(x, y) x ## y 51#define glue(x, y) x ## y
79#define DPO(s) glue(DataProcessingOperands, s) 52#define DPO(s) glue(DataProcessingOperands, s)
80#define ROTATE_RIGHT(n, i, l) ((n << (l - i)) | (n >> i)) 53#define ROTATE_RIGHT(n, i, l) ((n << (l - i)) | (n >> i))
81#define ROTATE_LEFT(n, i, l) ((n >> (l - i)) | (n << i)) 54#define ROTATE_LEFT(n, i, l) ((n >> (l - i)) | (n << i))
82#define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32) 55#define ROTATE_RIGHT_32(n, i) ROTATE_RIGHT(n, i, 32)
83#define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32) 56#define ROTATE_LEFT_32(n, i) ROTATE_LEFT(n, i, 32)
84 57
85//#define rotr(x,n) ((((x)>>(n))&((1<<(sizeof(x) * 8)-1))|(x<<(sizeof(x)*8-n))))
86//#define rotl(x,n) ((((x)<<(n))&(-(1<<(n))))|(((x)>>(sizeof(x)*8-n))&((1<<(n))-1)))
87#define rotr(x,n) ( (x >> n) | ((x & ((1 << (n + 1)) - 1)) << (32 - n)) ) 58#define rotr(x,n) ( (x >> n) | ((x & ((1 << (n + 1)) - 1)) << (32 - n)) )
88 59
89extern void switch_mode(arm_core_t *core, uint32_t mode); 60extern void switch_mode(arm_core_t *core, uint32_t mode);
90//extern bool InAPrivilegedMode(arm_core_t *core);
91 61
92typedef arm_core_t arm_processor; 62typedef arm_core_t arm_processor;
93typedef unsigned int (*shtop_fp_t)(arm_processor *cpu, unsigned int sht_oper); 63typedef unsigned int (*shtop_fp_t)(arm_processor *cpu, unsigned int sht_oper);
94 64
95/* exclusive memory access */ 65// Exclusive memory access
96static int exclusive_detect(ARMul_State* state, ARMword addr){ 66static int exclusive_detect(ARMul_State* state, ARMword addr){
97 #if 0 67 if(state->exclusive_tag == addr)
98 for(int i = 0; i < 128; i++){ 68 return 0;
99 if(state->exclusive_tag_array[i] == addr) 69 else
100 return 0; 70 return -1;
101 }
102 #endif
103 if(state->exclusive_tag == addr)
104 return 0;
105 else
106 return -1;
107} 71}
108 72
109static void add_exclusive_addr(ARMul_State* state, ARMword addr){ 73static void add_exclusive_addr(ARMul_State* state, ARMword addr){
110 #if 0 74 state->exclusive_tag = addr;
111 for(int i = 0; i < 128; i++){ 75 return;
112 if(state->exclusive_tag_array[i] == 0xffffffff){
113 state->exclusive_tag_array[i] = addr;
114 //DEBUG_LOG(ARM11, "In %s, add addr 0x%x\n", __func__, addr);
115 return;
116 }
117 }
118 DEBUG_LOG(ARM11, "In %s ,can not monitor the addr, out of array\n", __FUNCTION__);
119 #endif
120 state->exclusive_tag = addr;
121 return;
122} 76}
123 77
124static void remove_exclusive(ARMul_State* state, ARMword addr){ 78static void remove_exclusive(ARMul_State* state, ARMword addr){
125 #if 0 79 state->exclusive_tag = 0xFFFFFFFF;
126 int i; 80}
127 for(i = 0; i < 128; i++){ 81
128 if(state->exclusive_tag_array[i] == addr){ 82
129 state->exclusive_tag_array[i] = 0xffffffff; 83unsigned int DPO(Immediate)(arm_processor *cpu, unsigned int sht_oper) {
130 //DEBUG_LOG(ARM11, "In %s, remove addr 0x%x\n", __func__, addr); 84 unsigned int immed_8 = BITS(sht_oper, 0, 7);
131 return; 85 unsigned int rotate_imm = BITS(sht_oper, 8, 11);
132 } 86 unsigned int shifter_operand = ROTATE_RIGHT_32(immed_8, rotate_imm * 2);
133 } 87 if (rotate_imm == 0)
134 #endif 88 cpu->shifter_carry_out = cpu->CFlag;
135 state->exclusive_tag = 0xFFFFFFFF; 89 else
136} 90 cpu->shifter_carry_out = BIT(shifter_operand, 31);
137 91 return shifter_operand;
138 92}
139unsigned int DPO(Immediate)(arm_processor *cpu, unsigned int sht_oper) 93
140{ 94unsigned int DPO(Register)(arm_processor *cpu, unsigned int sht_oper) {
141// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); 95 unsigned int rm = CHECK_READ_REG15(cpu, RM);
142 unsigned int immed_8 = BITS(sht_oper, 0, 7); 96 unsigned int shifter_operand = rm;
143 unsigned int rotate_imm = BITS(sht_oper, 8, 11); 97 cpu->shifter_carry_out = cpu->CFlag;
144// DEBUG_LOG(ARM11, "immed_8 is %x\n", immed_8); 98 return shifter_operand;
145// DEBUG_LOG(ARM11, "rotate_imm is %x\n", rotate_imm); 99}
146 unsigned int shifter_operand = ROTATE_RIGHT_32(immed_8, rotate_imm * 2);//ROTATE_RIGHT_32(immed_8, rotate_imm * 2); 100
147// DEBUG_LOG(ARM11, "shifter_operand : %x\n", shifter_operand); 101unsigned int DPO(LogicalShiftLeftByImmediate)(arm_processor *cpu, unsigned int sht_oper) {
148 /* set c flag */ 102 int shift_imm = BITS(sht_oper, 7, 11);
149 if (rotate_imm == 0) 103 unsigned int rm = CHECK_READ_REG15(cpu, RM);
150 cpu->shifter_carry_out = cpu->CFlag; 104 unsigned int shifter_operand;
151 else 105 if (shift_imm == 0) {
152 cpu->shifter_carry_out = BIT(shifter_operand, 31); 106 shifter_operand = rm;
153 return shifter_operand; 107 cpu->shifter_carry_out = cpu->CFlag;
154} 108 } else {
155 109 shifter_operand = rm << shift_imm;
156unsigned int DPO(Register)(arm_processor *cpu, unsigned int sht_oper) 110 cpu->shifter_carry_out = BIT(rm, 32 - shift_imm);
157{ 111 }
158// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); 112 return shifter_operand;
159 unsigned int rm = CHECK_READ_REG15(cpu, RM); 113}
160 //if (RM == 15) rm += 8; 114
161 unsigned int shifter_operand = rm; 115unsigned int DPO(LogicalShiftLeftByRegister)(arm_processor *cpu, unsigned int sht_oper) {
162 cpu->shifter_carry_out = cpu->CFlag; 116 int shifter_operand;
163 return shifter_operand; 117 unsigned int rm = CHECK_READ_REG15(cpu, RM);
118 unsigned int rs = CHECK_READ_REG15(cpu, RS);
119 if (BITS(rs, 0, 7) == 0) {
120 shifter_operand = rm;
121 cpu->shifter_carry_out = cpu->CFlag;
122 } else if (BITS(rs, 0, 7) < 32) {
123 shifter_operand = rm << BITS(rs, 0, 7);
124 cpu->shifter_carry_out = BIT(rm, 32 - BITS(rs, 0, 7));
125 } else if (BITS(rs, 0, 7) == 32) {
126 shifter_operand = 0;
127 cpu->shifter_carry_out = BIT(rm, 0);
128 } else {
129 shifter_operand = 0;
130 cpu->shifter_carry_out = 0;
131 }
132 return shifter_operand;
133}
134
135unsigned int DPO(LogicalShiftRightByImmediate)(arm_processor *cpu, unsigned int sht_oper) {
136 unsigned int rm = CHECK_READ_REG15(cpu, RM);
137 unsigned int shifter_operand;
138 int shift_imm = BITS(sht_oper, 7, 11);
139 if (shift_imm == 0) {
140 shifter_operand = 0;
141 cpu->shifter_carry_out = BIT(rm, 31);
142 } else {
143 shifter_operand = rm >> shift_imm;
144 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
145 }
146 return shifter_operand;
147}
148
149unsigned int DPO(LogicalShiftRightByRegister)(arm_processor *cpu, unsigned int sht_oper) {
150 unsigned int rs = CHECK_READ_REG15(cpu, RS);
151 unsigned int rm = CHECK_READ_REG15(cpu, RM);
152 unsigned int shifter_operand;
153 if (BITS(rs, 0, 7) == 0) {
154 shifter_operand = rm;
155 cpu->shifter_carry_out = cpu->CFlag;
156 } else if (BITS(rs, 0, 7) < 32) {
157 shifter_operand = rm >> BITS(rs, 0, 7);
158 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 7) - 1);
159 } else if (BITS(rs, 0, 7) == 32) {
160 shifter_operand = 0;
161 cpu->shifter_carry_out = BIT(rm, 31);
162 } else {
163 shifter_operand = 0;
164 cpu->shifter_carry_out = 0;
165 }
166 return shifter_operand;
167}
168
169unsigned int DPO(ArithmeticShiftRightByImmediate)(arm_processor *cpu, unsigned int sht_oper) {
170 unsigned int rm = CHECK_READ_REG15(cpu, RM);
171 unsigned int shifter_operand;
172 int shift_imm = BITS(sht_oper, 7, 11);
173 if (shift_imm == 0) {
174 if (BIT(rm, 31)) {
175 shifter_operand = 0;
176 cpu->shifter_carry_out = BIT(rm, 31);
177 } else {
178 shifter_operand = 0xFFFFFFFF;
179 cpu->shifter_carry_out = BIT(rm, 31);
180 }
181 } else {
182 shifter_operand = static_cast<int>(rm) >> shift_imm;
183 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
184 }
185 return shifter_operand;
186}
187
188unsigned int DPO(ArithmeticShiftRightByRegister)(arm_processor *cpu, unsigned int sht_oper) {
189 unsigned int rs = CHECK_READ_REG15(cpu, RS);
190 unsigned int rm = CHECK_READ_REG15(cpu, RM);
191 unsigned int shifter_operand;
192 if (BITS(rs, 0, 7) == 0) {
193 shifter_operand = rm;
194 cpu->shifter_carry_out = cpu->CFlag;
195 } else if (BITS(rs, 0, 7) < 32) {
196 shifter_operand = static_cast<int>(rm) >> BITS(rs, 0, 7);
197 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 7) - 1);
198 } else {
199 if (BIT(rm, 31) == 0)
200 shifter_operand = 0;
201 else
202 shifter_operand = 0xffffffff;
203 cpu->shifter_carry_out = BIT(rm, 31);
204 }
205 return shifter_operand;
206}
207
208unsigned int DPO(RotateRightByImmediate)(arm_processor *cpu, unsigned int sht_oper) {
209 unsigned int shifter_operand;
210 unsigned int rm = CHECK_READ_REG15(cpu, RM);
211 int shift_imm = BITS(sht_oper, 7, 11);
212 if (shift_imm == 0) {
213 shifter_operand = (cpu->CFlag << 31) | (rm >> 1);
214 cpu->shifter_carry_out = BIT(rm, 0);
215 } else {
216 shifter_operand = ROTATE_RIGHT_32(rm, shift_imm);
217 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
218 }
219 return shifter_operand;
220}
221
222unsigned int DPO(RotateRightByRegister)(arm_processor *cpu, unsigned int sht_oper) {
223 unsigned int rm = CHECK_READ_REG15(cpu, RM);
224 unsigned int rs = CHECK_READ_REG15(cpu, RS);
225 unsigned int shifter_operand;
226 if (BITS(rs, 0, 7) == 0) {
227 shifter_operand = rm;
228 cpu->shifter_carry_out = cpu->CFlag;
229 } else if (BITS(rs, 0, 4) == 0) {
230 shifter_operand = rm;
231 cpu->shifter_carry_out = BIT(rm, 31);
232 } else {
233 shifter_operand = ROTATE_RIGHT_32(rm, BITS(rs, 0, 4));
234 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 4) - 1);
235 }
236 return shifter_operand;
164} 237}
165 238
166unsigned int DPO(LogicalShiftLeftByImmediate)(arm_processor *cpu, unsigned int sht_oper)
167{
168// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
169 int shift_imm = BITS(sht_oper, 7, 11);
170 unsigned int rm = CHECK_READ_REG15(cpu, RM);
171 //if (RM == 15) rm += 8;
172 unsigned int shifter_operand;
173 if (shift_imm == 0) {
174 shifter_operand = rm;
175 cpu->shifter_carry_out = cpu->CFlag;
176 } else {
177 shifter_operand = rm << shift_imm;
178 cpu->shifter_carry_out = BIT(rm, 32 - shift_imm);
179 }
180 return shifter_operand;
181}
182
183unsigned int DPO(LogicalShiftLeftByRegister)(arm_processor *cpu, unsigned int sht_oper)
184{
185// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
186 int shifter_operand;
187 unsigned int rm = CHECK_READ_REG15(cpu, RM);
188 unsigned int rs = CHECK_READ_REG15(cpu, RS);
189 //if (RM == 15) rm += 8;
190 //if (RS == 15) rs += 8;
191 if (BITS(rs, 0, 7) == 0) {
192 shifter_operand = rm;
193 cpu->shifter_carry_out = cpu->CFlag;
194 } else if (BITS(rs, 0, 7) < 32) {
195 shifter_operand = rm << BITS(rs, 0, 7);
196 cpu->shifter_carry_out = BIT(rm, 32 - BITS(rs, 0, 7));
197 } else if (BITS(rs, 0, 7) == 32) {
198 shifter_operand = 0;
199 cpu->shifter_carry_out = BIT(rm, 0);
200 } else {
201 shifter_operand = 0;
202 cpu->shifter_carry_out = 0;
203 }
204 return shifter_operand;
205}
206
207unsigned int DPO(LogicalShiftRightByImmediate)(arm_processor *cpu, unsigned int sht_oper)
208{
209// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
210 //unsigned int rm = cpu->Reg[RM];
211 unsigned int rm = CHECK_READ_REG15(cpu, RM);
212 //if (RM == 15) rm += 8;
213 unsigned int shifter_operand;
214 int shift_imm = BITS(sht_oper, 7, 11);
215 if (shift_imm == 0) {
216 shifter_operand = 0;
217 cpu->shifter_carry_out = BIT(rm, 31);
218 } else {
219 shifter_operand = rm >> shift_imm;
220 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
221 }
222 return shifter_operand;
223}
224
225unsigned int DPO(LogicalShiftRightByRegister)(arm_processor *cpu, unsigned int sht_oper)
226{
227// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
228 unsigned int rs = CHECK_READ_REG15(cpu, RS);
229 unsigned int rm = CHECK_READ_REG15(cpu, RM);
230 //if (RS == 15) rs += 8;
231 //if (RM == 15) rm += 8;
232 unsigned int shifter_operand;
233 if (BITS(rs, 0, 7) == 0) {
234 shifter_operand = rm;
235 cpu->shifter_carry_out = cpu->CFlag;
236 } else if (BITS(rs, 0, 7) < 32) {
237 shifter_operand = rm >> BITS(rs, 0, 7);
238 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 7) - 1);
239 } else if (BITS(rs, 0, 7) == 32) {
240 shifter_operand = 0;
241 cpu->shifter_carry_out = BIT(rm, 31);
242 } else {
243 shifter_operand = 0;
244 cpu->shifter_carry_out = 0;
245 }
246 return shifter_operand;
247}
248
249unsigned int DPO(ArithmeticShiftRightByImmediate)(arm_processor *cpu, unsigned int sht_oper)
250{
251// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
252 //unsigned int rm = cpu->Reg[RM];
253 unsigned int rm = CHECK_READ_REG15(cpu, RM);
254 //if (RM == 15) rm += 8;
255 unsigned int shifter_operand;
256 int shift_imm = BITS(sht_oper, 7, 11);
257 if (shift_imm == 0) {
258 if (BIT(rm, 31)) {
259 shifter_operand = 0;
260 cpu->shifter_carry_out = BIT(rm, 31);
261 } else {
262 shifter_operand = 0xFFFFFFFF;
263 cpu->shifter_carry_out = BIT(rm, 31);
264 }
265 } else {
266 shifter_operand = static_cast<int>(rm) >> shift_imm;
267 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
268 }
269 return shifter_operand;
270}
271
272unsigned int DPO(ArithmeticShiftRightByRegister)(arm_processor *cpu, unsigned int sht_oper)
273{
274// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
275 //unsigned int rs = cpu->Reg[RS];
276 unsigned int rs = CHECK_READ_REG15(cpu, RS);
277 //unsigned int rm = cpu->Reg[RM];
278 unsigned int rm = CHECK_READ_REG15(cpu, RM);
279 //if (RS == 15) rs += 8;
280 //if (RM == 15) rm += 8;
281 unsigned int shifter_operand;
282 if (BITS(rs, 0, 7) == 0) {
283 shifter_operand = rm;
284 cpu->shifter_carry_out = cpu->CFlag;
285 } else if (BITS(rs, 0, 7) < 32) {
286 shifter_operand = static_cast<int>(rm) >> BITS(rs, 0, 7);
287 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 7) - 1);
288 } else {
289 if (BIT(rm, 31) == 0) {
290 shifter_operand = 0;
291 } else
292 shifter_operand = 0xffffffff;
293 cpu->shifter_carry_out = BIT(rm, 31);
294 }
295 return shifter_operand;
296}
297
298unsigned int DPO(RotateRightByImmediate)(arm_processor *cpu, unsigned int sht_oper)
299{
300// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
301 unsigned int shifter_operand;
302 //unsigned int rm = cpu->Reg[RM];
303 unsigned int rm = CHECK_READ_REG15(cpu, RM);
304 //if (RM == 15) rm += 8;
305 int shift_imm = BITS(sht_oper, 7, 11);
306 if (shift_imm == 0) {
307 shifter_operand = (cpu->CFlag << 31) |
308 (rm >> 1);
309 cpu->shifter_carry_out = BIT(rm, 0);
310 } else {
311 shifter_operand = ROTATE_RIGHT_32(rm, shift_imm);
312 cpu->shifter_carry_out = BIT(rm, shift_imm - 1);
313 }
314 return shifter_operand;
315}
316
317unsigned int DPO(RotateRightByRegister)(arm_processor *cpu, unsigned int sht_oper)
318{
319// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
320 unsigned int rm = CHECK_READ_REG15(cpu, RM);
321 //if (RM == 15) rm += 8;
322 unsigned int rs = CHECK_READ_REG15(cpu, RS);
323 //if (RS == 15) rs += 8;
324 unsigned int shifter_operand;
325 if (BITS(rs, 0, 7) == 0) {
326 shifter_operand = rm;
327 cpu->shifter_carry_out = cpu->CFlag;
328 } else if (BITS(rs, 0, 4) == 0) {
329 shifter_operand = rm;
330 cpu->shifter_carry_out = BIT(rm, 31);
331 } else {
332 shifter_operand = ROTATE_RIGHT_32(rm, BITS(rs, 0, 4));
333 cpu->shifter_carry_out = BIT(rm, BITS(rs, 0, 4) - 1);
334 }
335 #if 0
336 if (cpu->icounter >= 20371544) {
337 DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__);
338 DEBUG_LOG(ARM11, "RM:%d\nRS:%d\n", RM, RS);
339 DEBUG_LOG(ARM11, "rm:0x%08x\nrs:0x%08x\n", cpu->Reg[RM], cpu->Reg[RS]);
340 }
341 #endif
342 return shifter_operand;
343}
344
345//typedef unsigned int (*get_addr_fp_t)(arm_processor *cpu);
346typedef struct _MiscImmeData { 239typedef struct _MiscImmeData {
347 unsigned int U; 240 unsigned int U;
348 unsigned int Rn; 241 unsigned int Rn;
349 unsigned int offset_8; 242 unsigned int offset_8;
350} MiscLSData; 243} MiscLSData;
351 244
352typedef struct _MiscRegData { 245typedef struct _MiscRegData {
353 unsigned int U; 246 unsigned int U;
354 unsigned int Rn; 247 unsigned int Rn;
355 unsigned int Rm; 248 unsigned int Rm;
356} MiscRegData; 249} MiscRegData;
357 250
358typedef struct _MiscImmePreIdx { 251typedef struct _MiscImmePreIdx {
359 unsigned int offset_8; 252 unsigned int offset_8;
360 unsigned int U; 253 unsigned int U;
361 unsigned int Rn; 254 unsigned int Rn;
362} MiscImmePreIdx; 255} MiscImmePreIdx;
363 256
364typedef struct _MiscRegPreIdx { 257typedef struct _MiscRegPreIdx {
365 unsigned int U; 258 unsigned int U;
366 unsigned int Rn; 259 unsigned int Rn;
367 unsigned int Rm; 260 unsigned int Rm;
368} MiscRegPreIdx; 261} MiscRegPreIdx;
369 262
370typedef struct _MiscImmePstIdx { 263typedef struct _MiscImmePstIdx {
371 unsigned int offset_8; 264 unsigned int offset_8;
372 unsigned int U; 265 unsigned int U;
373 unsigned int Rn; 266 unsigned int Rn;
374} MIscImmePstIdx; 267} MIscImmePstIdx;
375 268
376typedef struct _MiscRegPstIdx { 269typedef struct _MiscRegPstIdx {
377 unsigned int Rn; 270 unsigned int Rn;
378 unsigned int Rm; 271 unsigned int Rm;
379 unsigned int U; 272 unsigned int U;
380} MiscRegPstIdx; 273} MiscRegPstIdx;
381 274
382typedef struct _LSWordorUnsignedByte { 275typedef struct _LSWordorUnsignedByte {
@@ -384,40 +277,38 @@ typedef struct _LSWordorUnsignedByte {
384 277
385#if USER_MODE_OPT 278#if USER_MODE_OPT
386static inline fault_t interpreter_read_memory(addr_t virt_addr, addr_t phys_addr, uint32_t &value, uint32_t size){ 279static inline fault_t interpreter_read_memory(addr_t virt_addr, addr_t phys_addr, uint32_t &value, uint32_t size){
387 switch(size) { 280 switch(size) {
388 case 8: 281 case 8:
389 value = Memory::Read8(virt_addr); 282 value = Memory::Read8(virt_addr);
390 break; 283 break;
391 case 16: 284 case 16:
392 value = Memory::Read16(virt_addr); 285 value = Memory::Read16(virt_addr);
393 break; 286 break;
394 case 32: 287 case 32:
395 value = Memory::Read32(virt_addr); 288 value = Memory::Read32(virt_addr);
396 break; 289 break;
397 } 290 }
398 return NO_FAULT; 291 return NO_FAULT;
399} 292}
400 293
401//static inline void interpreter_write_memory(void *mem_ptr, uint32_t offset, uint32_t value, int size) 294static inline fault_t interpreter_write_memory(addr_t virt_addr, addr_t phys_addr, uint32_t value, uint32_t size) {
402static inline fault_t interpreter_write_memory(addr_t virt_addr, addr_t phys_addr, uint32_t value, uint32_t size) 295 switch(size) {
403{ 296 case 8:
404 switch(size) {
405 case 8:
406 Memory::Write8(virt_addr, value & 0xff); 297 Memory::Write8(virt_addr, value & 0xff);
407 break; 298 break;
408 case 16: 299 case 16:
409 Memory::Write16(virt_addr, value & 0xffff); 300 Memory::Write16(virt_addr, value & 0xffff);
410 break; 301 break;
411 case 32: 302 case 32:
412 Memory::Write32(virt_addr, value); 303 Memory::Write32(virt_addr, value);
413 break; 304 break;
414 } 305 }
415 return NO_FAULT; 306 return NO_FAULT;
416} 307}
417 308
418static inline fault_t check_address_validity(arm_core_t *core, addr_t virt_addr, addr_t *phys_addr, uint32_t rw){ 309static inline fault_t check_address_validity(arm_core_t *core, addr_t virt_addr, addr_t *phys_addr, uint32_t rw) {
419 *phys_addr = virt_addr; 310 *phys_addr = virt_addr;
420 return NO_FAULT; 311 return NO_FAULT;
421} 312}
422 313
423#else 314#else
@@ -430,736 +321,679 @@ fault_t check_address_validity(arm_core_t *core, addr_t virt_addr, addr_t *phys_
430typedef fault_t (*get_addr_fp_t)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw); 321typedef fault_t (*get_addr_fp_t)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw);
431 322
432typedef struct _ldst_inst { 323typedef struct _ldst_inst {
433 unsigned int inst; 324 unsigned int inst;
434 get_addr_fp_t get_addr; 325 get_addr_fp_t get_addr;
435} ldst_inst; 326} ldst_inst;
436#define DEBUG_MSG LOG_DEBUG(Core_ARM11, "inst is %x", inst); CITRA_IGNORE_EXIT(0) 327#define DEBUG_MSG LOG_DEBUG(Core_ARM11, "inst is %x", inst); CITRA_IGNORE_EXIT(0)
437 328
438int CondPassed(arm_processor *cpu, unsigned int cond); 329int CondPassed(arm_processor *cpu, unsigned int cond);
439#define LnSWoUB(s) glue(LnSWoUB, s) 330#define LnSWoUB(s) glue(LnSWoUB, s)
440#define MLnS(s) glue(MLnS, s) 331#define MLnS(s) glue(MLnS, s)
441#define LdnStM(s) glue(LdnStM, s) 332#define LdnStM(s) glue(LdnStM, s)
442 333
443#define W_BIT BIT(inst, 21) 334#define W_BIT BIT(inst, 21)
444#define U_BIT BIT(inst, 23) 335#define U_BIT BIT(inst, 23)
445#define I_BIT BIT(inst, 25) 336#define I_BIT BIT(inst, 25)
446#define P_BIT BIT(inst, 24) 337#define P_BIT BIT(inst, 24)
447#define OFFSET_12 BITS(inst, 0, 11) 338#define OFFSET_12 BITS(inst, 0, 11)
448fault_t LnSWoUB(ImmediateOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) 339fault_t LnSWoUB(ImmediateOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
449{ 340 unsigned int Rn = BITS(inst, 16, 19);
450 unsigned int Rn = BITS(inst, 16, 19); 341 unsigned int addr;
451 unsigned int addr; 342 fault_t fault;
452 fault_t fault; 343 if (U_BIT) {
453 if (U_BIT) { 344 addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12;
454 addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12; 345 } else {
455 } else { 346 addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12;
456 addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12; 347 }
457 } 348 virt_addr = addr;
458 //if (Rn == 15) rn += 8; 349 fault = check_address_validity(cpu, addr, &phys_addr, rw);
459 virt_addr = addr; 350 return fault;
460 fault = check_address_validity(cpu, addr, &phys_addr, rw); 351}
461 return fault; 352
462// return addr; 353fault_t LnSWoUB(RegisterOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
463} 354 fault_t fault;
464 355 unsigned int Rn = BITS(inst, 16, 19);
465fault_t LnSWoUB(RegisterOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) 356 unsigned int Rm = BITS(inst, 0, 3);
466{ 357 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
467 fault_t fault; 358 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
468 unsigned int Rn = BITS(inst, 16, 19); 359 unsigned int addr;
469 unsigned int Rm = BITS(inst, 0, 3); 360 if (U_BIT) {
470 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 361 addr = rn + rm;
471 //if (Rn == 15) rn += 8; 362 } else {
472 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 363 addr = rn - rm;
473 //if (Rm == 15) rm += 8; 364 }
474 unsigned int addr; 365 virt_addr = addr;
475 if (U_BIT) { 366 fault = check_address_validity(cpu, addr, &phys_addr, rw);
476 addr = rn + rm; 367 return fault;
477 } else { 368}
478 addr = rn - rm; 369
479 } 370fault_t LnSWoUB(ImmediatePostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
480 virt_addr = addr; 371 fault_t fault;
481 fault = check_address_validity(cpu, addr, &phys_addr, rw); 372 unsigned int Rn = BITS(inst, 16, 19);
482 return fault; 373 unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn);
483} 374
484 375 virt_addr = addr;
485fault_t LnSWoUB(ImmediatePostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) 376 fault = check_address_validity(cpu, addr, &phys_addr, rw);
486{ 377 if (fault) return fault;
487 fault_t fault; 378
488 unsigned int Rn = BITS(inst, 16, 19); 379 if (U_BIT) {
489 unsigned int addr = CHECK_READ_REG15_WA(cpu, Rn); 380 cpu->Reg[Rn] += OFFSET_12;
490 //if (Rn == 15) addr += 8; 381 } else {
382 cpu->Reg[Rn] -= OFFSET_12;
383 }
384 return fault;
385}
386
387fault_t LnSWoUB(ImmediatePreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
388 fault_t fault;
389 unsigned int Rn = BITS(inst, 16, 19);
390 unsigned int addr;
391 if (U_BIT) {
392 addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12;
393 } else {
394 addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12;
395 }
396
397 virt_addr = addr;
398 fault = check_address_validity(cpu, addr, &phys_addr, rw);
399 if (fault) return fault;
400
401 if (CondPassed(cpu, BITS(inst, 28, 31))) {
402 cpu->Reg[Rn] = addr;
403 }
404 return fault;
405}
406
407fault_t MLnS(RegisterPreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
408 fault_t fault;
409 unsigned int addr;
410 unsigned int Rn = BITS(inst, 16, 19);
411 unsigned int Rm = BITS(inst, 0, 3);
412 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
413 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
414
415 if (U_BIT) {
416 addr = rn + rm;
417 } else
418 addr = rn - rm;
419 if(BIT(inst, 20)){ // L BIT
420 }
421 if(BIT(inst, 6)){ // Sign Bit
422 }
423 if(BIT(inst, 5)){ // Half Bit
424 }
425
426 virt_addr = addr;
427 fault = check_address_validity(cpu, addr, &phys_addr, rw);
428 if (fault) return fault;
491 429
492 virt_addr = addr; 430 if (CondPassed(cpu, BITS(inst, 28, 31))) {
493 fault = check_address_validity(cpu, addr, &phys_addr, rw); 431 cpu->Reg[Rn] = addr;
494 if (fault) return fault; 432 }
433 return fault;
434}
435
436fault_t LnSWoUB(RegisterPreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
437 fault_t fault;
438 unsigned int Rn = BITS(inst, 16, 19);
439 unsigned int Rm = BITS(inst, 0, 3);
440 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
441 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
442 unsigned int addr;
443 if (U_BIT) {
444 addr = rn + rm;
445 } else {
446 addr = rn - rm;
447 }
448 virt_addr = addr;
449 fault = check_address_validity(cpu, addr, &phys_addr, rw);
450 if(fault)
451 return fault;
452 if (CondPassed(cpu, BITS(inst, 28, 31))) {
453 cpu->Reg[Rn] = addr;
454 }
455 return fault;
456}
457fault_t LnSWoUB(ScaledRegisterPreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
458 fault_t fault;
459 unsigned int shift = BITS(inst, 5, 6);
460 unsigned int shift_imm = BITS(inst, 7, 11);
461 unsigned int Rn = BITS(inst, 16, 19);
462 unsigned int Rm = BITS(inst, 0, 3);
463 unsigned int index;
464 unsigned int addr;
465
466 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
467 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
468
469 switch (shift) {
470 case 0:
471 index = rm << shift_imm;
472 break;
473 case 1:
474 if (shift_imm == 0) {
475 index = 0;
476 } else {
477 index = rm >> shift_imm;
478 }
479 break;
480 case 2:
481 DEBUG_MSG;
482 break;
483 case 3:
484 DEBUG_MSG;
485 break;
486 }
487 if (U_BIT) {
488 addr = rn + index;
489 } else
490 addr = rn - index;
491 virt_addr = addr;
492 fault = check_address_validity(cpu, addr, &phys_addr, rw);
493 if(fault)
494 return fault;
495 if (CondPassed(cpu, BITS(inst, 28, 31))) {
496 cpu->Reg[Rn] = addr;
497 }
498
499 return fault;
500}
501
502fault_t LnSWoUB(ScaledRegisterPostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
503 fault_t fault;
504 unsigned int shift = BITS(inst, 5, 6);
505 unsigned int shift_imm = BITS(inst, 7, 11);
506 unsigned int Rn = BITS(inst, 16, 19);
507 unsigned int Rm = BITS(inst, 0, 3);
508 unsigned int index;
509 unsigned int addr;
510
511 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
512 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
513 addr = rn;
514 switch (shift) {
515 case 0:
516 index = rm << shift_imm;
517 break;
518 case 1:
519 if (shift_imm == 0) {
520 index = 0;
521 } else {
522 index = rm >> shift_imm;
523 }
524 break;
525 case 2:
526 DEBUG_MSG;
527 break;
528 case 3:
529 DEBUG_MSG;
530 break;
531 }
532 virt_addr = addr;
533 fault = check_address_validity(cpu, addr, &phys_addr, rw);
534 if(fault)
535 return fault;
536 if (CondPassed(cpu, BITS(inst, 28, 31))) {
537 if (U_BIT)
538 cpu->Reg[Rn] += index;
539 else
540 cpu->Reg[Rn] -= index;
541 }
495 542
496 if (U_BIT) { 543 return fault;
497 cpu->Reg[Rn] += OFFSET_12;
498 } else {
499 cpu->Reg[Rn] -= OFFSET_12;
500 }
501 return fault;
502} 544}
503 545
504fault_t LnSWoUB(ImmediatePreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) 546fault_t LnSWoUB(RegisterPostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
505{ 547 fault_t fault;
506 fault_t fault; 548 unsigned int Rn = BITS(inst, 16, 19);
507 unsigned int Rn = BITS(inst, 16, 19); 549 unsigned int Rm = BITS(inst, 0, 3);
508 unsigned int addr; 550 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
509 if (U_BIT) { 551 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
510 addr = CHECK_READ_REG15_WA(cpu, Rn) + OFFSET_12; 552
511 } else { 553 unsigned int addr = rn;
512 addr = CHECK_READ_REG15_WA(cpu, Rn) - OFFSET_12; 554 virt_addr = addr;
513 } 555 fault = check_address_validity(cpu, addr, &phys_addr, rw);
514 #if 0 556 if (fault) return fault;
515 if (Rn == 15) { 557
516 addr += 8; 558 if (CondPassed(cpu, BITS(inst, 28, 31))) {
517 } 559 if (U_BIT) {
518 #endif 560 cpu->Reg[Rn] += rm;
519 561 } else {
520 virt_addr = addr; 562 cpu->Reg[Rn] -= rm;
521 fault = check_address_validity(cpu, addr, &phys_addr, rw); 563 }
522 if (fault) return fault; 564 }
523 565 return fault;
524 if (CondPassed(cpu, BITS(inst, 28, 31))) { 566}
525 cpu->Reg[Rn] = addr; 567
526 } 568fault_t MLnS(ImmediateOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
527 return fault; 569 fault_t fault;
528} 570 unsigned int immedL = BITS(inst, 0, 3);
529 571 unsigned int immedH = BITS(inst, 8, 11);
530fault_t MLnS(RegisterPreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) 572
531{ 573 unsigned int Rn = BITS(inst, 16, 19);
532 fault_t fault; 574 unsigned int addr;
533 unsigned int addr; 575
534 unsigned int Rn = BITS(inst, 16, 19); 576 unsigned int offset_8 = (immedH << 4) | immedL;
535 unsigned int Rm = BITS(inst, 0, 3); 577 if (U_BIT) {
536 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 578 addr = CHECK_READ_REG15_WA(cpu, Rn) + offset_8;
537 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 579 } else
538 //if (Rn == 15) rn += 8; 580 addr = CHECK_READ_REG15_WA(cpu, Rn) - offset_8;
539 //if (Rm == 15) rm += 8; 581
540 if (U_BIT) { 582 virt_addr = addr;
541 addr = rn + rm; 583 fault = check_address_validity(cpu, addr, &phys_addr, rw);
542 } else 584 return fault;
543 addr = rn - rm; 585}
544 if(BIT(inst, 20)){ /* L BIT */ 586
545 } 587fault_t MLnS(RegisterOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
546 if(BIT(inst, 6)){ /* Sign Bit */ 588 fault_t fault;
547 } 589 unsigned int addr;
548 if(BIT(inst, 5)){ /* Half Bit */ 590 unsigned int Rn = BITS(inst, 16, 19);
549 } 591 unsigned int Rm = BITS(inst, 0, 3);
550 592 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
551 virt_addr = addr; 593 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
552 fault = check_address_validity(cpu, addr, &phys_addr, rw); 594 if (U_BIT) {
553 if (fault) return fault; 595 addr = rn + rm;
554 596 } else
555 if (CondPassed(cpu, BITS(inst, 28, 31))) { 597 addr = rn - rm;
556 cpu->Reg[Rn] = addr; 598 if(BIT(inst, 20)){ // L BIT
557 } 599 }
558 return fault; 600 if(BIT(inst, 6)){ // Sign Bit
559} 601 }
560 602 if(BIT(inst, 5)){ // Half Bit
561fault_t LnSWoUB(RegisterPreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) 603 }
562{ 604 virt_addr = addr;
563 fault_t fault; 605 fault = check_address_validity(cpu, addr, &phys_addr, rw);
564 unsigned int Rn = BITS(inst, 16, 19); 606 return fault;
565 unsigned int Rm = BITS(inst, 0, 3); 607}
566 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 608
567 //if (Rn == 15) rn += 8; 609fault_t MLnS(ImmediatePreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
568 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 610 fault_t fault;
569 //if (Rm == 15) rm += 8; 611 unsigned int Rn = BITS(inst, 16, 19);
570 unsigned int addr; 612 unsigned int immedH = BITS(inst, 8, 11);
571 if (U_BIT) { 613 unsigned int immedL = BITS(inst, 0, 3);
572 addr = rn + rm; 614 unsigned int addr;
573 } else { 615 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
574 addr = rn - rm; 616 unsigned int offset_8 = (immedH << 4) | immedL;
575 } 617
576 virt_addr = addr; 618 if (U_BIT) {
577 fault = check_address_validity(cpu, addr, &phys_addr, rw); 619 addr = rn + offset_8;
578 if(fault) 620 } else
579 return fault; 621 addr = rn - offset_8;
580 if (CondPassed(cpu, BITS(inst, 28, 31))) { 622
581 cpu->Reg[Rn] = addr; 623 virt_addr = addr;
582 } 624 fault = check_address_validity(cpu, addr, &phys_addr, rw);
583 return fault; 625 if (fault) return fault;
584} 626
585fault_t LnSWoUB(ScaledRegisterPreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) 627 if (CondPassed(cpu, BITS(inst, 28, 31))) {
586{ 628 cpu->Reg[Rn] = addr;
587 fault_t fault; 629 }
588 unsigned int shift = BITS(inst, 5, 6); 630 return fault;
589 unsigned int shift_imm = BITS(inst, 7, 11); 631}
590 unsigned int Rn = BITS(inst, 16, 19); 632
591 unsigned int Rm = BITS(inst, 0, 3); 633fault_t MLnS(ImmediatePostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
592 unsigned int index; 634 fault_t fault;
593 unsigned int addr; 635 unsigned int Rn = BITS(inst, 16, 19);
594 636 unsigned int immedH = BITS(inst, 8, 11);
595 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 637 unsigned int immedL = BITS(inst, 0, 3);
596 //if (Rm == 15) rm += 8; 638 unsigned int addr;
597 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 639 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
598 //if (Rn == 15) rn += 8; 640 addr = rn;
599 switch (shift) { 641
600 case 0: 642 virt_addr = addr;
601 //DEBUG_MSG; 643 fault = check_address_validity(cpu, addr, &phys_addr, rw);
602 index = rm << shift_imm; 644 if (fault) return fault;
603 break; 645
604 case 1: 646 if (CondPassed(cpu, BITS(inst, 28, 31))) {
605// DEBUG_MSG; 647 unsigned int offset_8 = (immedH << 4) | immedL;
606 if (shift_imm == 0) { 648 if (U_BIT) {
607 index = 0; 649 rn += offset_8;
608 } else { 650 } else {
609 index = rm >> shift_imm; 651 rn -= offset_8;
610 } 652 }
611 break; 653 cpu->Reg[Rn] = rn;
612 case 2: 654 }
613 DEBUG_MSG; 655
614 break; 656 return fault;
615 case 3: 657}
616 DEBUG_MSG; 658fault_t MLnS(RegisterPostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
617 break; 659 fault_t fault;
618 } 660 unsigned int Rn = BITS(inst, 16, 19);
619 if (U_BIT) { 661 unsigned int Rm = BITS(inst, 0, 3);
620 addr = rn + index; 662 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
621 } else 663 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
622 addr = rn - index; 664 unsigned int addr = rn;
623 virt_addr = addr; 665
624 fault = check_address_validity(cpu, addr, &phys_addr, rw); 666 virt_addr = addr;
625 if(fault) 667 fault = check_address_validity(cpu, addr, &phys_addr, rw);
626 return fault; 668 if (fault) return fault;
627 if (CondPassed(cpu, BITS(inst, 28, 31))) { 669
628 cpu->Reg[Rn] = addr; 670 if (CondPassed(cpu, BITS(inst, 28, 31))) {
629 } 671 if (U_BIT) {
630 672 cpu->Reg[Rn] += rm;
631 return fault; 673 } else {
632} 674 cpu->Reg[Rn] -= rm;
633 675 }
634fault_t LnSWoUB(ScaledRegisterPostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) 676 }
635{ 677 return fault;
636 fault_t fault; 678}
637 unsigned int shift = BITS(inst, 5, 6); 679
638 unsigned int shift_imm = BITS(inst, 7, 11); 680fault_t LdnStM(DecrementBefore)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
639 unsigned int Rn = BITS(inst, 16, 19); 681 fault_t fault;
640 unsigned int Rm = BITS(inst, 0, 3); 682 unsigned int Rn = BITS(inst, 16, 19);
641 unsigned int index; 683 unsigned int i = BITS(inst, 0, 15);
642 unsigned int addr; 684 int count = 0;
643 685 while(i) {
644 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 686 if(i & 1) count ++;
645 //if (Rm == 15) rm += 8; 687 i = i >> 1;
646 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 688 }
647 //if (Rn == 15) rn += 8; 689 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
648 addr = rn; 690 unsigned int start_addr = rn - count * 4;
649 switch (shift) { 691 unsigned int end_addr = rn - 4;
650 case 0: 692
651 //DEBUG_MSG; 693 fault = check_address_validity(cpu, end_addr, &phys_addr, rw);
652 index = rm << shift_imm; 694 virt_addr = end_addr;
653 break; 695 if (fault) return fault;
654 case 1: 696
655// DEBUG_MSG; 697 fault = check_address_validity(cpu, start_addr, &phys_addr, rw);
656 if (shift_imm == 0) { 698 virt_addr = start_addr;
657 index = 0; 699 if (fault) return fault;
658 } else { 700
659 index = rm >> shift_imm; 701 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
660 } 702 cpu->Reg[Rn] -= count * 4;
661 break; 703 }
662 case 2: 704
663 DEBUG_MSG; 705 return fault;
664 break; 706}
665 case 3: 707
666 DEBUG_MSG; 708fault_t LdnStM(IncrementBefore)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
667 break; 709 fault_t fault;
668 } 710 unsigned int Rn = BITS(inst, 16, 19);
669 virt_addr = addr; 711 unsigned int i = BITS(inst, 0, 15);
670 fault = check_address_validity(cpu, addr, &phys_addr, rw); 712 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
671 if(fault) 713 int count = 0;
672 return fault; 714 while(i) {
673 if (CondPassed(cpu, BITS(inst, 28, 31))) { 715 if(i & 1) count ++;
674 if (U_BIT) 716 i = i >> 1;
675 cpu->Reg[Rn] += index; 717 }
676 else 718
677 cpu->Reg[Rn] -= index; 719 unsigned int start_addr = rn + 4;
678 } 720 unsigned int end_addr = rn + count * 4;
679 721
680 return fault; 722 fault = check_address_validity(cpu, end_addr, &phys_addr, rw);
681} 723 virt_addr = end_addr;
682 724 if (fault) return fault;
683fault_t LnSWoUB(RegisterPostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) 725
684{ 726 fault = check_address_validity(cpu, start_addr, &phys_addr, rw);
685 fault_t fault; 727 virt_addr = start_addr;
686 unsigned int Rn = BITS(inst, 16, 19); 728 if (fault) return fault;
687 unsigned int Rm = BITS(inst, 0, 3); 729
688 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 730 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
689 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 731 cpu->Reg[Rn] += count * 4;
690 732 }
691 unsigned int addr = rn; 733 return fault;
692 virt_addr = addr; 734}
693 fault = check_address_validity(cpu, addr, &phys_addr, rw); 735
694 if (fault) return fault; 736fault_t LdnStM(IncrementAfter)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
695 737 fault_t fault;
696 if (CondPassed(cpu, BITS(inst, 28, 31))) { 738 unsigned int Rn = BITS(inst, 16, 19);
697 if (U_BIT) { 739 unsigned int i = BITS(inst, 0, 15);
698 cpu->Reg[Rn] += rm; 740 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
699 } else { 741 int count = 0;
700 cpu->Reg[Rn] -= rm; 742 while(i) {
701 } 743 if(i & 1) count ++;
702 } 744 i = i >> 1;
703 return fault; 745 }
704} 746 unsigned int start_addr = rn;
705 747 unsigned int end_addr = rn + count * 4 - 4;
706fault_t MLnS(ImmediateOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) 748
707{ 749 fault = check_address_validity(cpu, end_addr, &phys_addr, rw);
708 fault_t fault; 750 virt_addr = end_addr;
709 unsigned int immedL = BITS(inst, 0, 3); 751 if (fault) return fault;
710 unsigned int immedH = BITS(inst, 8, 11); 752
711 753 fault = check_address_validity(cpu, start_addr, &phys_addr, rw);
712 unsigned int Rn = BITS(inst, 16, 19); 754 virt_addr = start_addr;
713 unsigned int addr; 755 if (fault) return fault;
714 756
715 unsigned int offset_8 = (immedH << 4) | immedL; 757 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
716 if (U_BIT) { 758 cpu->Reg[Rn] += count * 4;
717 addr = CHECK_READ_REG15_WA(cpu, Rn) + offset_8; 759 }
718 } else 760 return fault;
719 addr = CHECK_READ_REG15_WA(cpu, Rn) - offset_8; 761}
720 #if 0 762
721 if (Rn == 15) { 763fault_t LdnStM(DecrementAfter)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
722 addr += 8; 764 fault_t fault;
723 } 765 unsigned int Rn = BITS(inst, 16, 19);
724 #endif 766 unsigned int i = BITS(inst, 0, 15);
725 virt_addr = addr; 767 int count = 0;
726 fault = check_address_validity(cpu, addr, &phys_addr, rw); 768 while(i) {
727 return fault; 769 if(i & 1) count ++;
728} 770 i = i >> 1;
729 771 }
730fault_t MLnS(RegisterOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) 772 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
731{ 773 unsigned int start_addr = rn - count * 4 + 4;
732 fault_t fault; 774 unsigned int end_addr = rn;
733 unsigned int addr; 775
734 unsigned int Rn = BITS(inst, 16, 19); 776 fault = check_address_validity(cpu, end_addr, &phys_addr, rw);
735 unsigned int Rm = BITS(inst, 0, 3); 777 virt_addr = end_addr;
736 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 778 if (fault) return fault;
737 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm); 779
738 //if (Rn == 15) rn += 8; 780 fault = check_address_validity(cpu, start_addr, &phys_addr, rw);
739 //if (Rm == 15) rm += 8; 781 if (fault) return fault;
740 if (U_BIT) { 782 virt_addr = start_addr;
741 addr = rn + rm; 783
742 } else 784 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
743 addr = rn - rm; 785 cpu->Reg[Rn] -= count * 4;
744 if(BIT(inst, 20)){ /* L BIT */ 786 }
745 } 787 return fault;
746 if(BIT(inst, 6)){ /* Sign Bit */ 788}
747 } 789
748 if(BIT(inst, 5)){ /* Half Bit */ 790fault_t LnSWoUB(ScaledRegisterOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) {
749 } 791 fault_t fault;
750 virt_addr = addr; 792 unsigned int shift = BITS(inst, 5, 6);
751 fault = check_address_validity(cpu, addr, &phys_addr, rw); 793 unsigned int shift_imm = BITS(inst, 7, 11);
752 return fault; 794 unsigned int Rn = BITS(inst, 16, 19);
753} 795 unsigned int Rm = BITS(inst, 0, 3);
754 796 unsigned int index;
755fault_t MLnS(ImmediatePreIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) 797 unsigned int addr;
756{ 798
757 fault_t fault; 799 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
758 unsigned int Rn = BITS(inst, 16, 19); 800 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
759 unsigned int immedH = BITS(inst, 8, 11); 801 switch (shift) {
760 unsigned int immedL = BITS(inst, 0, 3); 802 case 0:
761 unsigned int addr; 803 index = rm << shift_imm;
762 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 804 break;
763 //if (Rn == 15) rn += 8; 805 case 1:
764 806 if (shift_imm == 0) {
765// DEBUG_LOG(ARM11, "in %s\n", __FUNCTION__); 807 index = 0;
766 unsigned int offset_8 = (immedH << 4) | immedL; 808 } else {
767 if (U_BIT) { 809 index = rm >> shift_imm;
768 addr = rn + offset_8; 810 }
769 } else 811 break;
770 addr = rn - offset_8; 812 case 2:
771 813 if (shift_imm == 0){ // ASR #32
772 virt_addr = addr; 814 if (rm >> 31)
773 fault = check_address_validity(cpu, addr, &phys_addr, rw); 815 index = 0xFFFFFFFF;
774 if (fault) return fault; 816 else
775 817 index = 0;
776 if (CondPassed(cpu, BITS(inst, 28, 31))) { 818 }
777 cpu->Reg[Rn] = addr; 819 else {
778 } 820 index = static_cast<int>(rm) >> shift_imm;
779 return fault; 821 }
780} 822 break;
781 823 case 3:
782fault_t MLnS(ImmediatePostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw) 824 DEBUG_MSG;
783{ 825 break;
784 fault_t fault; 826 }
785 unsigned int Rn = BITS(inst, 16, 19); 827 if (U_BIT) {
786 unsigned int immedH = BITS(inst, 8, 11); 828 addr = rn + index;
787 unsigned int immedL = BITS(inst, 0, 3); 829 } else
788 unsigned int addr; 830 addr = rn - index;
789 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn); 831
790 addr = rn; 832 virt_addr = addr;
791 833 fault = check_address_validity(cpu, addr, &phys_addr, rw);
792 virt_addr = addr; 834
793 fault = check_address_validity(cpu, addr, &phys_addr, rw); 835 return fault;
794 if (fault) return fault; 836}
795 837
796 if (CondPassed(cpu, BITS(inst, 28, 31))) { 838#define ISNEG(n) (n < 0)
797 unsigned int offset_8 = (immedH << 4) | immedL; 839#define ISPOS(n) (n >= 0)
798 if (U_BIT) {
799 rn += offset_8;
800 } else {
801 rn -= offset_8;
802 }
803 cpu->Reg[Rn] = rn;
804 }
805
806 return fault;
807}
808fault_t MLnS(RegisterPostIndexed)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
809{
810 fault_t fault;
811 unsigned int Rn = BITS(inst, 16, 19);
812 unsigned int Rm = BITS(inst, 0, 3);
813 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
814 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
815
816 unsigned int addr = rn;
817 virt_addr = addr;
818 fault = check_address_validity(cpu, addr, &phys_addr, rw);
819 if (fault) return fault;
820
821 if (CondPassed(cpu, BITS(inst, 28, 31))) {
822 if (U_BIT) {
823 cpu->Reg[Rn] += rm;
824 } else {
825 cpu->Reg[Rn] -= rm;
826 }
827 }
828 return fault;
829}
830
831fault_t LdnStM(DecrementBefore)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
832{
833 fault_t fault;
834 unsigned int Rn = BITS(inst, 16, 19);
835 unsigned int i = BITS(inst, 0, 15);
836 int count = 0;
837 while(i) {
838 if(i & 1) count ++;
839 i = i >> 1;
840 }
841 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
842 //if (Rn == 15) rn += 8;
843 unsigned int start_addr = rn - count * 4;
844 unsigned int end_addr = rn - 4;
845
846 fault = check_address_validity(cpu, end_addr, &phys_addr, rw);
847 virt_addr = end_addr;
848 if (fault) return fault;
849
850 fault = check_address_validity(cpu, start_addr, &phys_addr, rw);
851 virt_addr = start_addr;
852 if (fault) return fault;
853
854 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
855 cpu->Reg[Rn] -= count * 4;
856 }
857
858 return fault;
859}
860
861fault_t LdnStM(IncrementBefore)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
862{
863 fault_t fault;
864 unsigned int Rn = BITS(inst, 16, 19);
865 unsigned int i = BITS(inst, 0, 15);
866 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
867 //if (Rn == 15) rn += 8;
868 int count = 0;
869 while(i) {
870 if(i & 1) count ++;
871 i = i >> 1;
872 }
873
874 unsigned int start_addr = rn + 4;
875 unsigned int end_addr = rn + count * 4;
876
877 fault = check_address_validity(cpu, end_addr, &phys_addr, rw);
878 virt_addr = end_addr;
879 if (fault) return fault;
880
881 fault = check_address_validity(cpu, start_addr, &phys_addr, rw);
882 virt_addr = start_addr;
883 if (fault) return fault;
884
885 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
886 cpu->Reg[Rn] += count * 4;
887 }
888 return fault;
889}
890
891fault_t LdnStM(IncrementAfter)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
892{
893 fault_t fault;
894 unsigned int Rn = BITS(inst, 16, 19);
895 unsigned int i = BITS(inst, 0, 15);
896 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
897 int count = 0;
898 while(i) {
899 if(i & 1) count ++;
900 i = i >> 1;
901 }
902 //if (Rn == 15) rn += 8;
903 unsigned int start_addr = rn;
904 unsigned int end_addr = rn + count * 4 - 4;
905
906 fault = check_address_validity(cpu, end_addr, &phys_addr, rw);
907 virt_addr = end_addr;
908 if (fault) return fault;
909
910 fault = check_address_validity(cpu, start_addr, &phys_addr, rw);
911 virt_addr = start_addr;
912 if (fault) return fault;
913
914 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
915 cpu->Reg[Rn] += count * 4;
916 }
917 return fault;
918}
919
920fault_t LdnStM(DecrementAfter)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
921{
922 fault_t fault;
923 unsigned int Rn = BITS(inst, 16, 19);
924 unsigned int i = BITS(inst, 0, 15);
925 int count = 0;
926 while(i) {
927 if(i & 1) count ++;
928 i = i >> 1;
929 }
930 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
931 //if (Rn == 15) rn += 8;
932 unsigned int start_addr = rn - count * 4 + 4;
933 unsigned int end_addr = rn;
934
935 fault = check_address_validity(cpu, end_addr, &phys_addr, rw);
936 virt_addr = end_addr;
937 if (fault) return fault;
938
939 fault = check_address_validity(cpu, start_addr, &phys_addr, rw);
940 if (fault) return fault;
941 virt_addr = start_addr;
942
943 if (CondPassed(cpu, BITS(inst, 28, 31)) && BIT(inst, 21)) {
944 cpu->Reg[Rn] -= count * 4;
945 }
946 return fault;
947}
948
949fault_t LnSWoUB(ScaledRegisterOffset)(arm_processor *cpu, unsigned int inst, unsigned int &virt_addr, unsigned int &phys_addr, unsigned int rw)
950{
951 fault_t fault;
952 unsigned int shift = BITS(inst, 5, 6);
953 unsigned int shift_imm = BITS(inst, 7, 11);
954 unsigned int Rn = BITS(inst, 16, 19);
955 unsigned int Rm = BITS(inst, 0, 3);
956 unsigned int index;
957 unsigned int addr;
958
959 unsigned int rm = CHECK_READ_REG15_WA(cpu, Rm);
960 //if (Rm == 15) rm += 8;
961 unsigned int rn = CHECK_READ_REG15_WA(cpu, Rn);
962 //if (Rn == 15) rn += 8;
963 switch (shift) {
964 case 0:
965 //DEBUG_MSG;
966 index = rm << shift_imm;
967 break;
968 case 1:
969// DEBUG_MSG;
970 if (shift_imm == 0) {
971 index = 0;
972 } else {
973 index = rm >> shift_imm;
974 }
975 break;
976 case 2:
977 if (shift_imm == 0){ /* ASR #32 */
978 if (rm >> 31)
979 index = 0xFFFFFFFF;
980 else
981 index = 0;
982 }
983 else {
984 index = static_cast<int>(rm) >> shift_imm;
985 }
986 break;
987 case 3:
988 DEBUG_MSG;
989 break;
990 }
991 if (U_BIT) {
992 addr = rn + index;
993 } else
994 addr = rn - index;
995 virt_addr = addr;
996 fault = check_address_validity(cpu, addr, &phys_addr, rw);
997 return fault;
998}
999
1000#define ISNEG(n) (n < 0)
1001#define ISPOS(n) (n >= 0)
1002
1003//enum {
1004// COND = (1 << 0),
1005// NON_BRANCH = (1 << 1),
1006// DIRECT_BRANCH = (1 << 2),
1007// INDIRECT_BRANCH = (1 << 3),
1008// CALL = (1 << 4),
1009// RET = (1 << 5),
1010// END_OF_PAGE = (1 << 6),
1011// THUMB = (1 << 7)
1012//};
1013 840
1014typedef struct _arm_inst { 841typedef struct _arm_inst {
1015 unsigned int idx; 842 unsigned int idx;
1016 unsigned int cond; 843 unsigned int cond;
1017 int br; 844 int br;
1018 int load_r15; 845 int load_r15;
1019 char component[0]; 846 char component[0];
1020} arm_inst; 847} arm_inst;
1021 848
849typedef struct generic_arm_inst {
850 u32 Ra;
851 u32 Rm;
852 u32 Rn;
853 u32 Rd;
854 u8 op1;
855 u8 op2;
856} generic_arm_inst;
857
1022typedef struct _adc_inst { 858typedef struct _adc_inst {
1023 unsigned int I; 859 unsigned int I;
1024 unsigned int S; 860 unsigned int S;
1025 unsigned int Rn; 861 unsigned int Rn;
1026 unsigned int Rd; 862 unsigned int Rd;
1027 unsigned int shifter_operand; 863 unsigned int shifter_operand;
1028 shtop_fp_t shtop_func; 864 shtop_fp_t shtop_func;
1029} adc_inst; 865} adc_inst;
1030 866
1031typedef struct _add_inst { 867typedef struct _add_inst {
1032 unsigned int I; 868 unsigned int I;
1033 unsigned int S; 869 unsigned int S;
1034 unsigned int Rn; 870 unsigned int Rn;
1035 unsigned int Rd; 871 unsigned int Rd;
1036 unsigned int shifter_operand; 872 unsigned int shifter_operand;
1037 shtop_fp_t shtop_func; 873 shtop_fp_t shtop_func;
1038} add_inst; 874} add_inst;
1039 875
1040typedef struct _orr_inst { 876typedef struct _orr_inst {
1041 unsigned int I; 877 unsigned int I;
1042 unsigned int S; 878 unsigned int S;
1043 unsigned int Rn; 879 unsigned int Rn;
1044 unsigned int Rd; 880 unsigned int Rd;
1045 unsigned int shifter_operand; 881 unsigned int shifter_operand;
1046 shtop_fp_t shtop_func; 882 shtop_fp_t shtop_func;
1047} orr_inst; 883} orr_inst;
1048 884
1049typedef struct _and_inst { 885typedef struct _and_inst {
1050 unsigned int I; 886 unsigned int I;
1051 unsigned int S; 887 unsigned int S;
1052 unsigned int Rn; 888 unsigned int Rn;
1053 unsigned int Rd; 889 unsigned int Rd;
1054 unsigned int shifter_operand; 890 unsigned int shifter_operand;
1055 shtop_fp_t shtop_func; 891 shtop_fp_t shtop_func;
1056} and_inst; 892} and_inst;
1057 893
1058typedef struct _eor_inst { 894typedef struct _eor_inst {
1059 unsigned int I; 895 unsigned int I;
1060 unsigned int S; 896 unsigned int S;
1061 unsigned int Rn; 897 unsigned int Rn;
1062 unsigned int Rd; 898 unsigned int Rd;
1063 unsigned int shifter_operand; 899 unsigned int shifter_operand;
1064 shtop_fp_t shtop_func; 900 shtop_fp_t shtop_func;
1065} eor_inst; 901} eor_inst;
1066 902
1067typedef struct _bbl_inst { 903typedef struct _bbl_inst {
1068 unsigned int L; 904 unsigned int L;
1069 int signed_immed_24; 905 int signed_immed_24;
1070 unsigned int next_addr; 906 unsigned int next_addr;
1071 unsigned int jmp_addr; 907 unsigned int jmp_addr;
1072} bbl_inst; 908} bbl_inst;
1073 909
1074typedef struct _bx_inst { 910typedef struct _bx_inst {
1075 unsigned int Rm; 911 unsigned int Rm;
1076} bx_inst; 912} bx_inst;
1077 913
1078typedef struct _blx_inst { 914typedef struct _blx_inst {
1079 union { 915 union {
1080 int32_t signed_immed_24; 916 int32_t signed_immed_24;
1081 uint32_t Rm; 917 uint32_t Rm;
1082 } val; 918 } val;
1083 unsigned int inst; 919 unsigned int inst;
1084} blx_inst; 920} blx_inst;
1085 921
1086typedef struct _clz_inst { 922typedef struct _clz_inst {
1087 unsigned int Rm; 923 unsigned int Rm;
1088 unsigned int Rd; 924 unsigned int Rd;
1089} clz_inst; 925} clz_inst;
1090 926
1091typedef struct _cps_inst { 927typedef struct _cps_inst {
1092 unsigned int imod0; 928 unsigned int imod0;
1093 unsigned int imod1; 929 unsigned int imod1;
1094 unsigned int mmod; 930 unsigned int mmod;
1095 unsigned int A, I, F; 931 unsigned int A, I, F;
1096 unsigned int mode; 932 unsigned int mode;
1097} cps_inst; 933} cps_inst;
1098 934
1099typedef struct _clrex_inst { 935typedef struct _clrex_inst {
1100} clrex_inst; 936} clrex_inst;
1101 937
1102typedef struct _cpy_inst { 938typedef struct _cpy_inst {
1103 unsigned int Rm; 939 unsigned int Rm;
1104 unsigned int Rd; 940 unsigned int Rd;
1105} cpy_inst; 941} cpy_inst;
1106 942
1107typedef struct _bic_inst { 943typedef struct _bic_inst {
1108 unsigned int I; 944 unsigned int I;
1109 unsigned int S; 945 unsigned int S;
1110 unsigned int Rn; 946 unsigned int Rn;
1111 unsigned int Rd; 947 unsigned int Rd;
1112 unsigned int shifter_operand; 948 unsigned int shifter_operand;
1113 shtop_fp_t shtop_func; 949 shtop_fp_t shtop_func;
1114} bic_inst; 950} bic_inst;
1115 951
1116typedef struct _sub_inst { 952typedef struct _sub_inst {
1117 unsigned int I; 953 unsigned int I;
1118 unsigned int S; 954 unsigned int S;
1119 unsigned int Rn; 955 unsigned int Rn;
1120 unsigned int Rd; 956 unsigned int Rd;
1121 unsigned int shifter_operand; 957 unsigned int shifter_operand;
1122 shtop_fp_t shtop_func; 958 shtop_fp_t shtop_func;
1123} sub_inst; 959} sub_inst;
1124 960
1125typedef struct _tst_inst { 961typedef struct _tst_inst {
1126 unsigned int I; 962 unsigned int I;
1127 unsigned int S; 963 unsigned int S;
1128 unsigned int Rn; 964 unsigned int Rn;
1129 unsigned int Rd; 965 unsigned int Rd;
1130 unsigned int shifter_operand; 966 unsigned int shifter_operand;
1131 shtop_fp_t shtop_func; 967 shtop_fp_t shtop_func;
1132} tst_inst; 968} tst_inst;
1133 969
1134typedef struct _cmn_inst { 970typedef struct _cmn_inst {
1135 unsigned int I; 971 unsigned int I;
1136 //unsigned int S; 972 unsigned int Rn;
1137 unsigned int Rn; 973 unsigned int shifter_operand;
1138 //unsigned int Rd; 974 shtop_fp_t shtop_func;
1139 unsigned int shifter_operand;
1140 shtop_fp_t shtop_func;
1141} cmn_inst; 975} cmn_inst;
1142 976
1143typedef struct _teq_inst { 977typedef struct _teq_inst {
1144 unsigned int I; 978 unsigned int I;
1145 unsigned int Rn; 979 unsigned int Rn;
1146 unsigned int shifter_operand; 980 unsigned int shifter_operand;
1147 shtop_fp_t shtop_func; 981 shtop_fp_t shtop_func;
1148} teq_inst; 982} teq_inst;
1149 983
1150typedef struct _stm_inst { 984typedef struct _stm_inst {
1151 unsigned int inst; 985 unsigned int inst;
1152} stm_inst; 986} stm_inst;
1153 987
1154struct bkpt_inst { 988struct bkpt_inst {
1155}; 989};
1156 990
1157struct blx1_inst { 991struct blx1_inst {
1158 unsigned int addr; 992 unsigned int addr;
1159}; 993};
1160 994
1161struct blx2_inst { 995struct blx2_inst {
1162 unsigned int Rm; 996 unsigned int Rm;
1163}; 997};
1164 998
1165typedef struct _stc_inst { 999typedef struct _stc_inst {
@@ -1169,443 +1003,418 @@ typedef struct _ldc_inst {
1169} ldc_inst; 1003} ldc_inst;
1170 1004
1171typedef struct _swi_inst { 1005typedef struct _swi_inst {
1172 unsigned int num; 1006 unsigned int num;
1173} swi_inst; 1007} swi_inst;
1174 1008
1175typedef struct _cmp_inst { 1009typedef struct _cmp_inst {
1176 unsigned int I; 1010 unsigned int I;
1177 unsigned int Rn; 1011 unsigned int Rn;
1178 unsigned int shifter_operand; 1012 unsigned int shifter_operand;
1179 shtop_fp_t shtop_func; 1013 shtop_fp_t shtop_func;
1180} cmp_inst; 1014} cmp_inst;
1181 1015
1182typedef struct _mov_inst { 1016typedef struct _mov_inst {
1183 unsigned int I; 1017 unsigned int I;
1184 unsigned int S; 1018 unsigned int S;
1185 unsigned int Rd; 1019 unsigned int Rd;
1186 unsigned int shifter_operand; 1020 unsigned int shifter_operand;
1187 shtop_fp_t shtop_func; 1021 shtop_fp_t shtop_func;
1188} mov_inst; 1022} mov_inst;
1189 1023
1190typedef struct _mvn_inst { 1024typedef struct _mvn_inst {
1191 unsigned int I; 1025 unsigned int I;
1192 unsigned int S; 1026 unsigned int S;
1193 unsigned int Rd; 1027 unsigned int Rd;
1194 unsigned int shifter_operand; 1028 unsigned int shifter_operand;
1195 shtop_fp_t shtop_func; 1029 shtop_fp_t shtop_func;
1196} mvn_inst; 1030} mvn_inst;
1197 1031
1198typedef struct _rev_inst { 1032typedef struct _rev_inst {
1199 unsigned int Rd; 1033 unsigned int Rd;
1200 unsigned int Rm; 1034 unsigned int Rm;
1201} rev_inst; 1035} rev_inst;
1202 1036
1203typedef struct _rsb_inst { 1037typedef struct _rsb_inst {
1204 unsigned int I; 1038 unsigned int I;
1205 unsigned int S; 1039 unsigned int S;
1206 unsigned int Rn; 1040 unsigned int Rn;
1207 unsigned int Rd; 1041 unsigned int Rd;
1208 unsigned int shifter_operand; 1042 unsigned int shifter_operand;
1209 shtop_fp_t shtop_func; 1043 shtop_fp_t shtop_func;
1210} rsb_inst; 1044} rsb_inst;
1211 1045
1212typedef struct _rsc_inst { 1046typedef struct _rsc_inst {
1213 unsigned int I; 1047 unsigned int I;
1214 unsigned int S; 1048 unsigned int S;
1215 unsigned int Rn; 1049 unsigned int Rn;
1216 unsigned int Rd; 1050 unsigned int Rd;
1217 unsigned int shifter_operand; 1051 unsigned int shifter_operand;
1218 shtop_fp_t shtop_func; 1052 shtop_fp_t shtop_func;
1219} rsc_inst; 1053} rsc_inst;
1220 1054
1221typedef struct _sbc_inst { 1055typedef struct _sbc_inst {
1222 unsigned int I; 1056 unsigned int I;
1223 unsigned int S; 1057 unsigned int S;
1224 unsigned int Rn; 1058 unsigned int Rn;
1225 unsigned int Rd; 1059 unsigned int Rd;
1226 unsigned int shifter_operand; 1060 unsigned int shifter_operand;
1227 shtop_fp_t shtop_func; 1061 shtop_fp_t shtop_func;
1228} sbc_inst; 1062} sbc_inst;
1229 1063
1230typedef struct _mul_inst { 1064typedef struct _mul_inst {
1231 unsigned int S; 1065 unsigned int S;
1232 unsigned int Rd; 1066 unsigned int Rd;
1233 unsigned int Rs; 1067 unsigned int Rs;
1234 unsigned int Rm; 1068 unsigned int Rm;
1235} mul_inst; 1069} mul_inst;
1236 1070
1237typedef struct _smul_inst { 1071typedef struct _smul_inst {
1238 unsigned int Rd; 1072 unsigned int Rd;
1239 unsigned int Rs; 1073 unsigned int Rs;
1240 unsigned int Rm; 1074 unsigned int Rm;
1241 unsigned int x; 1075 unsigned int x;
1242 unsigned int y; 1076 unsigned int y;
1243} smul_inst; 1077} smul_inst;
1244 1078
1245typedef struct _umull_inst { 1079typedef struct _umull_inst {
1246 unsigned int S; 1080 unsigned int S;
1247 unsigned int RdHi; 1081 unsigned int RdHi;
1248 unsigned int RdLo; 1082 unsigned int RdLo;
1249 unsigned int Rs; 1083 unsigned int Rs;
1250 unsigned int Rm; 1084 unsigned int Rm;
1251} umull_inst; 1085} umull_inst;
1252typedef struct _smlad_inst { 1086typedef struct _smlad_inst {
1253 unsigned int m; 1087 unsigned int m;
1254 unsigned int Rm; 1088 unsigned int Rm;
1255 unsigned int Rd; 1089 unsigned int Rd;
1256 unsigned int Ra; 1090 unsigned int Ra;
1257 unsigned int Rn; 1091 unsigned int Rn;
1258} smlad_inst; 1092} smlad_inst;
1259 1093
1260typedef struct _smla_inst { 1094typedef struct _smla_inst {
1261 unsigned int x; 1095 unsigned int x;
1262 unsigned int y; 1096 unsigned int y;
1263 unsigned int Rm; 1097 unsigned int Rm;
1264 unsigned int Rd; 1098 unsigned int Rd;
1265 unsigned int Rs; 1099 unsigned int Rs;
1266 unsigned int Rn; 1100 unsigned int Rn;
1267} smla_inst; 1101} smla_inst;
1268 1102
1103typedef struct umaal_inst {
1104 unsigned int Rn;
1105 unsigned int Rm;
1106 unsigned int RdHi;
1107 unsigned int RdLo;
1108} umaal_inst;
1109
1269typedef struct _umlal_inst { 1110typedef struct _umlal_inst {
1270 unsigned int S; 1111 unsigned int S;
1271 unsigned int Rm; 1112 unsigned int Rm;
1272 unsigned int Rs; 1113 unsigned int Rs;
1273 unsigned int RdHi; 1114 unsigned int RdHi;
1274 unsigned int RdLo; 1115 unsigned int RdLo;
1275} umlal_inst; 1116} umlal_inst;
1276 1117
1277typedef struct _smlal_inst { 1118typedef struct _smlal_inst {
1278 unsigned int S; 1119 unsigned int S;
1279 unsigned int Rm; 1120 unsigned int Rm;
1280 unsigned int Rs; 1121 unsigned int Rs;
1281 unsigned int RdHi; 1122 unsigned int RdHi;
1282 unsigned int RdLo; 1123 unsigned int RdLo;
1283} smlal_inst; 1124} smlal_inst;
1284 1125
1285typedef struct _mla_inst { 1126typedef struct _mla_inst {
1286 unsigned int S; 1127 unsigned int S;
1287 unsigned int Rn; 1128 unsigned int Rn;
1288 unsigned int Rd; 1129 unsigned int Rd;
1289 unsigned int Rs; 1130 unsigned int Rs;
1290 unsigned int Rm; 1131 unsigned int Rm;
1291} mla_inst; 1132} mla_inst;
1292 1133
1293typedef struct _mrc_inst { 1134typedef struct _mrc_inst {
1294 unsigned int opcode_1; 1135 unsigned int opcode_1;
1295 unsigned int opcode_2; 1136 unsigned int opcode_2;
1296 unsigned int cp_num; 1137 unsigned int cp_num;
1297 unsigned int crn; 1138 unsigned int crn;
1298 unsigned int crm; 1139 unsigned int crm;
1299 unsigned int Rd; 1140 unsigned int Rd;
1300 unsigned int inst; 1141 unsigned int inst;
1301} mrc_inst; 1142} mrc_inst;
1302 1143
1303typedef struct _mcr_inst { 1144typedef struct _mcr_inst {
1304 unsigned int opcode_1; 1145 unsigned int opcode_1;
1305 unsigned int opcode_2; 1146 unsigned int opcode_2;
1306 unsigned int cp_num; 1147 unsigned int cp_num;
1307 unsigned int crn; 1148 unsigned int crn;
1308 unsigned int crm; 1149 unsigned int crm;
1309 unsigned int Rd; 1150 unsigned int Rd;
1310 unsigned int inst; 1151 unsigned int inst;
1311} mcr_inst; 1152} mcr_inst;
1312 1153
1313typedef struct _mrs_inst { 1154typedef struct _mrs_inst {
1314 unsigned int R; 1155 unsigned int R;
1315 unsigned int Rd; 1156 unsigned int Rd;
1316} mrs_inst; 1157} mrs_inst;
1317 1158
1318typedef struct _msr_inst { 1159typedef struct _msr_inst {
1319 unsigned int field_mask; 1160 unsigned int field_mask;
1320 unsigned int R; 1161 unsigned int R;
1321 unsigned int inst; 1162 unsigned int inst;
1322} msr_inst; 1163} msr_inst;
1323 1164
1324typedef struct _pld_inst { 1165typedef struct _pld_inst {
1325} pld_inst; 1166} pld_inst;
1326 1167
1327typedef struct _sxtb_inst { 1168typedef struct _sxtb_inst {
1328 unsigned int Rd; 1169 unsigned int Rd;
1329 unsigned int Rm; 1170 unsigned int Rm;
1330 unsigned int rotate; 1171 unsigned int rotate;
1331} sxtb_inst; 1172} sxtb_inst;
1332 1173
1333typedef struct _sxtab_inst { 1174typedef struct _sxtab_inst {
1334 unsigned int Rd; 1175 unsigned int Rd;
1335 unsigned int Rn; 1176 unsigned int Rn;
1336 unsigned int Rm; 1177 unsigned int Rm;
1337 unsigned rotate; 1178 unsigned rotate;
1338} sxtab_inst; 1179} sxtab_inst;
1339 1180
1340typedef struct _sxtah_inst { 1181typedef struct _sxtah_inst {
1341 unsigned int Rd; 1182 unsigned int Rd;
1342 unsigned int Rn; 1183 unsigned int Rn;
1343 unsigned int Rm; 1184 unsigned int Rm;
1344 unsigned int rotate; 1185 unsigned int rotate;
1345} sxtah_inst; 1186} sxtah_inst;
1346 1187
1347typedef struct _sxth_inst { 1188typedef struct _sxth_inst {
1348 unsigned int Rd; 1189 unsigned int Rd;
1349 unsigned int Rm; 1190 unsigned int Rm;
1350 unsigned int rotate; 1191 unsigned int rotate;
1351} sxth_inst; 1192} sxth_inst;
1352 1193
1353typedef struct _uxtab_inst { 1194typedef struct _uxtab_inst {
1354 unsigned int Rn; 1195 unsigned int Rn;
1355 unsigned int Rd; 1196 unsigned int Rd;
1356 unsigned int rotate; 1197 unsigned int rotate;
1357 unsigned int Rm; 1198 unsigned int Rm;
1358} uxtab_inst; 1199} uxtab_inst;
1359 1200
1360typedef struct _uxtah_inst { 1201typedef struct _uxtah_inst {
1361 unsigned int Rn; 1202 unsigned int Rn;
1362 unsigned int Rd; 1203 unsigned int Rd;
1363 unsigned int rotate; 1204 unsigned int rotate;
1364 unsigned int Rm; 1205 unsigned int Rm;
1365} uxtah_inst; 1206} uxtah_inst;
1366 1207
1367typedef struct _uxth_inst { 1208typedef struct _uxth_inst {
1368 unsigned int Rd; 1209 unsigned int Rd;
1369 unsigned int Rm; 1210 unsigned int Rm;
1370 unsigned int rotate; 1211 unsigned int rotate;
1371} uxth_inst; 1212} uxth_inst;
1372 1213
1373typedef struct _cdp_inst { 1214typedef struct _cdp_inst {
1374 unsigned int opcode_1; 1215 unsigned int opcode_1;
1375 unsigned int CRn; 1216 unsigned int CRn;
1376 unsigned int CRd; 1217 unsigned int CRd;
1377 unsigned int cp_num; 1218 unsigned int cp_num;
1378 unsigned int opcode_2; 1219 unsigned int opcode_2;
1379 unsigned int CRm; 1220 unsigned int CRm;
1380 uint32 inst; 1221 uint32 inst;
1381}cdp_inst; 1222}cdp_inst;
1382 1223
1383typedef struct _uxtb_inst { 1224typedef struct _uxtb_inst {
1384 unsigned int Rd; 1225 unsigned int Rd;
1385 unsigned int Rm; 1226 unsigned int Rm;
1386 unsigned int rotate; 1227 unsigned int rotate;
1387} uxtb_inst; 1228} uxtb_inst;
1388 1229
1389typedef struct _swp_inst { 1230typedef struct _swp_inst {
1390 unsigned int Rn; 1231 unsigned int Rn;
1391 unsigned int Rd; 1232 unsigned int Rd;
1392 unsigned int Rm; 1233 unsigned int Rm;
1393} swp_inst; 1234} swp_inst;
1394 1235
1395typedef struct _b_2_thumb { 1236typedef struct _b_2_thumb {
1396 unsigned int imm; 1237 unsigned int imm;
1397}b_2_thumb; 1238}b_2_thumb;
1398typedef struct _b_cond_thumb { 1239typedef struct _b_cond_thumb {
1399 unsigned int imm; 1240 unsigned int imm;
1400 unsigned int cond; 1241 unsigned int cond;
1401}b_cond_thumb; 1242}b_cond_thumb;
1402 1243
1403typedef struct _bl_1_thumb { 1244typedef struct _bl_1_thumb {
1404 unsigned int imm; 1245 unsigned int imm;
1405}bl_1_thumb; 1246}bl_1_thumb;
1406typedef struct _bl_2_thumb { 1247typedef struct _bl_2_thumb {
1407 unsigned int imm; 1248 unsigned int imm;
1408}bl_2_thumb; 1249}bl_2_thumb;
1409typedef struct _blx_1_thumb { 1250typedef struct _blx_1_thumb {
1410 unsigned int imm; 1251 unsigned int imm;
1411 unsigned int instr; 1252 unsigned int instr;
1412}blx_1_thumb; 1253}blx_1_thumb;
1413 1254
1255typedef struct _pkh_inst {
1256 u32 Rm;
1257 u32 Rn;
1258 u32 Rd;
1259 u8 imm;
1260} pkh_inst;
1261
1414typedef arm_inst * ARM_INST_PTR; 1262typedef arm_inst * ARM_INST_PTR;
1415 1263
1416#define CACHE_BUFFER_SIZE (64 * 1024 * 2000) 1264#define CACHE_BUFFER_SIZE (64 * 1024 * 2000)
1417char inst_buf[CACHE_BUFFER_SIZE]; 1265char inst_buf[CACHE_BUFFER_SIZE];
1418int top = 0; 1266int top = 0;
1419inline void *AllocBuffer(unsigned int size) 1267inline void *AllocBuffer(unsigned int size) {
1420{ 1268 int start = top;
1421 int start = top; 1269 top += size;
1422 top += size; 1270 if (top > CACHE_BUFFER_SIZE) {
1423 if (top > CACHE_BUFFER_SIZE) { 1271 LOG_ERROR(Core_ARM11, "inst_buf is full");
1424 LOG_ERROR(Core_ARM11, "inst_buf is full"); 1272 CITRA_IGNORE_EXIT(-1);
1425 CITRA_IGNORE_EXIT(-1); 1273 }
1426 } 1274 return (void *)&inst_buf[start];
1427 return (void *)&inst_buf[start]; 1275}
1428} 1276
1429 1277int CondPassed(arm_processor *cpu, unsigned int cond) {
1430int CondPassed(arm_processor *cpu, unsigned int cond) 1278 #define NFLAG cpu->NFlag
1431{ 1279 #define ZFLAG cpu->ZFlag
1432 #define NFLAG cpu->NFlag 1280 #define CFLAG cpu->CFlag
1433 #define ZFLAG cpu->ZFlag 1281 #define VFLAG cpu->VFlag
1434 #define CFLAG cpu->CFlag 1282
1435 #define VFLAG cpu->VFlag 1283 int temp;
1436 int temp; 1284
1437 switch (cond) { 1285 switch (cond) {
1438 case 0x0: 1286 case 0x0:
1439 temp = ZFLAG; 1287 temp = ZFLAG;
1440 break; 1288 break;
1441 case 0x1: /* NE */ 1289 case 0x1: // NE
1442 temp = !ZFLAG; 1290 temp = !ZFLAG;
1443 break; 1291 break;
1444 case 0x6: /* VS */ 1292 case 0x6: // VS
1445 temp = VFLAG; 1293 temp = VFLAG;
1446 break; 1294 break;
1447 case 0x7: /* VC */ 1295 case 0x7: // VC
1448 temp = !VFLAG; 1296 temp = !VFLAG;
1449 break; 1297 break;
1450 case 0x4: /* MI */ 1298 case 0x4: // MI
1451 temp = NFLAG; 1299 temp = NFLAG;
1452 break; 1300 break;
1453 case 0x5: /* PL */ 1301 case 0x5: // PL
1454 temp = !NFLAG; 1302 temp = !NFLAG;
1455 break; 1303 break;
1456 case 0x2: /* CS */ 1304 case 0x2: // CS
1457 temp = CFLAG; 1305 temp = CFLAG;
1458 break; 1306 break;
1459 case 0x3: /* CC */ 1307 case 0x3: // CC
1460 temp = !CFLAG; 1308 temp = !CFLAG;
1461 break; 1309 break;
1462 case 0x8: /* HI */ 1310 case 0x8: // HI
1463 temp = (CFLAG && !ZFLAG); 1311 temp = (CFLAG && !ZFLAG);
1464 break; 1312 break;
1465 case 0x9: /* LS */ 1313 case 0x9: // LS
1466 temp = (!CFLAG || ZFLAG); 1314 temp = (!CFLAG || ZFLAG);
1467 break; 1315 break;
1468 case 0xa: /* GE */ 1316 case 0xa: // GE
1469 temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG)); 1317 temp = ((!NFLAG && !VFLAG) || (NFLAG && VFLAG));
1470 break; 1318 break;
1471 case 0xb: /* LT */ 1319 case 0xb: // LT
1472 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)); 1320 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG));
1473 break; 1321 break;
1474 case 0xc: /* GT */ 1322 case 0xc: // GT
1475 temp = ((!NFLAG && !VFLAG && !ZFLAG) 1323 temp = ((!NFLAG && !VFLAG && !ZFLAG) || (NFLAG && VFLAG && !ZFLAG));
1476 || (NFLAG && VFLAG && !ZFLAG)); 1324 break;
1477 break; 1325 case 0xd: // LE
1478 case 0xd: /* LE */ 1326 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) || ZFLAG;
1479 temp = ((NFLAG && !VFLAG) || (!NFLAG && VFLAG)) 1327 break;
1480 || ZFLAG; 1328 case 0xe: // AL
1481 break; 1329 temp = 1;
1482 case 0xe: /* AL */ 1330 break;
1483 temp = 1; 1331 case 0xf:
1484 break; 1332 temp = 1;
1485 case 0xf: 1333 break;
1486// DEBUG_LOG(ARM11, "inst is %x\n"); 1334 }
1487// DEBUG_LOG(ARM11, "icounter is %lld\n", cpu->icounter); 1335 return temp;
1488// CITRA_IGNORE_EXIT(-1);
1489 temp = 1;
1490 break;
1491 }
1492 return temp;
1493} 1336}
1494 1337
1495enum DECODE_STATUS { 1338enum DECODE_STATUS {
1496 DECODE_SUCCESS, 1339 DECODE_SUCCESS,
1497 DECODE_FAILURE 1340 DECODE_FAILURE
1498}; 1341};
1499 1342
1500int decode_arm_instr(uint32_t instr, int32_t *idx); 1343int decode_arm_instr(uint32_t instr, int32_t *idx);
1501 1344
1502shtop_fp_t get_shtop(unsigned int inst) 1345shtop_fp_t get_shtop(unsigned int inst) {
1503{ 1346 if (BIT(inst, 25)) {
1504 if (BIT(inst, 25)) { 1347 return DPO(Immediate);
1505 return DPO(Immediate); 1348 } else if (BITS(inst, 4, 11) == 0) {
1506 } else if (BITS(inst, 4, 11) == 0) { 1349 return DPO(Register);
1507 return DPO(Register); 1350 } else if (BITS(inst, 4, 6) == 0) {
1508 } else if (BITS(inst, 4, 6) == 0) { 1351 return DPO(LogicalShiftLeftByImmediate);
1509 return DPO(LogicalShiftLeftByImmediate); 1352 } else if (BITS(inst, 4, 7) == 1) {
1510 } else if (BITS(inst, 4, 7) == 1) { 1353 return DPO(LogicalShiftLeftByRegister);
1511 return DPO(LogicalShiftLeftByRegister); 1354 } else if (BITS(inst, 4, 6) == 2) {
1512 } else if (BITS(inst, 4, 6) == 2) { 1355 return DPO(LogicalShiftRightByImmediate);
1513 return DPO(LogicalShiftRightByImmediate); 1356 } else if (BITS(inst, 4, 7) == 3) {
1514 } else if (BITS(inst, 4, 7) == 3) { 1357 return DPO(LogicalShiftRightByRegister);
1515 return DPO(LogicalShiftRightByRegister); 1358 } else if (BITS(inst, 4, 6) == 4) {
1516 } else if (BITS(inst, 4, 6) == 4) { 1359 return DPO(ArithmeticShiftRightByImmediate);
1517 return DPO(ArithmeticShiftRightByImmediate); 1360 } else if (BITS(inst, 4, 7) == 5) {
1518 } else if (BITS(inst, 4, 7) == 5) { 1361 return DPO(ArithmeticShiftRightByRegister);
1519 return DPO(ArithmeticShiftRightByRegister); 1362 } else if (BITS(inst, 4, 6) == 6) {
1520 } else if (BITS(inst, 4, 6) == 6) { 1363 return DPO(RotateRightByImmediate);
1521 return DPO(RotateRightByImmediate); 1364 } else if (BITS(inst, 4, 7) == 7) {
1522 } else if (BITS(inst, 4, 7) == 7) { 1365 return DPO(RotateRightByRegister);
1523 return DPO(RotateRightByRegister); 1366 }
1524 } 1367 return nullptr;
1525 return NULL; 1368}
1526} 1369
1527 1370get_addr_fp_t get_calc_addr_op(unsigned int inst) {
1528get_addr_fp_t get_calc_addr_op(unsigned int inst) 1371 if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 0) {
1529{ 1372 return LnSWoUB(ImmediateOffset);
1530 /* 1 */ 1373 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) {
1531 if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 0) { 1374 return LnSWoUB(RegisterOffset);
1532// DEBUG_LOG(ARM11, "line is %d", __LINE__); 1375 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) {
1533 return LnSWoUB(ImmediateOffset); 1376 return LnSWoUB(ScaledRegisterOffset);
1534 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) { 1377 } else if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 1) {
1535// DEBUG_MSG; 1378 return LnSWoUB(ImmediatePreIndexed);
1536// DEBUG_LOG(ARM11, "line is %d", __LINE__); 1379 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 1 && BITS(inst, 4, 11) == 0) {
1537 return LnSWoUB(RegisterOffset); 1380 return LnSWoUB(RegisterPreIndexed);
1538 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) { 1381 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 1 && BIT(inst, 4) == 0) {
1539// DEBUG_MSG; 1382 return LnSWoUB(ScaledRegisterPreIndexed);
1540// DEBUG_LOG(ARM11, "line is %d", __LINE__); 1383 } else if (BITS(inst, 24, 27) == 4 && BIT(inst, 21) == 0) {
1541 return LnSWoUB(ScaledRegisterOffset); 1384 return LnSWoUB(ImmediatePostIndexed);
1542 } else if (BITS(inst, 24, 27) == 5 && BIT(inst, 21) == 1) { 1385 } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) {
1543// DEBUG_LOG(ARM11, "line is %d", __LINE__); 1386 return LnSWoUB(RegisterPostIndexed);
1544 return LnSWoUB(ImmediatePreIndexed); 1387 } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) {
1545 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 1 && BITS(inst, 4, 11) == 0) { 1388 return LnSWoUB(ScaledRegisterPostIndexed);
1546 return LnSWoUB(RegisterPreIndexed); 1389 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1547 } else if (BITS(inst, 24, 27) == 7 && BIT(inst, 21) == 1 && BIT(inst, 4) == 0) { 1390 return MLnS(ImmediateOffset);
1548 return LnSWoUB(ScaledRegisterPreIndexed); 1391 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1549 } else if (BITS(inst, 24, 27) == 4 && BIT(inst, 21) == 0) { 1392 return MLnS(RegisterOffset);
1550 return LnSWoUB(ImmediatePostIndexed); 1393 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 3 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1551 } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BITS(inst, 4, 11) == 0) { 1394 return MLnS(ImmediatePreIndexed);
1552// DEBUG_MSG; 1395 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 1 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1553 return LnSWoUB(RegisterPostIndexed); 1396 return MLnS(RegisterPreIndexed);
1554 } else if (BITS(inst, 24, 27) == 6 && BIT(inst, 21) == 0 && BIT(inst, 4) == 0) { 1397 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1555 return LnSWoUB(ScaledRegisterPostIndexed); 1398 return MLnS(ImmediatePostIndexed);
1556// DEBUG_MSG; 1399 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1557 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 1400 return MLnS(RegisterPostIndexed);
1558 /* 2 */ 1401 } else if (BITS(inst, 23, 27) == 0x11) {
1559// DEBUG_LOG(ARM11, "line is %d", __LINE__); 1402 return LdnStM(IncrementAfter);
1560 return MLnS(ImmediateOffset); 1403 } else if (BITS(inst, 23, 27) == 0x13) {
1561// DEBUG_MSG; 1404 return LdnStM(IncrementBefore);
1562 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 1405 } else if (BITS(inst, 23, 27) == 0x10) {
1563// DEBUG_LOG(ARM11, "line is %d\n", __LINE__); 1406 return LdnStM(DecrementAfter);
1564 return MLnS(RegisterOffset); 1407 } else if (BITS(inst, 23, 27) == 0x12) {
1565// DEBUG_MSG; 1408 return LdnStM(DecrementBefore);
1566 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 3 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) { 1409 }
1567// DEBUG_LOG(ARM11, "line is %d\n", __LINE__); 1410 return nullptr;
1568 return MLnS(ImmediatePreIndexed);
1569// DEBUG_MSG;
1570 } else if (BITS(inst, 24, 27) == 1 && BITS(inst, 21, 22) == 1 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1571 return MLnS(RegisterPreIndexed);
1572 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 2 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1573// DEBUG_MSG;
1574 return MLnS(ImmediatePostIndexed);
1575 } else if (BITS(inst, 24, 27) == 0 && BITS(inst, 21, 22) == 0 && BIT(inst, 7) == 1 && BIT(inst, 4) == 1) {
1576 //DEBUG_MSG;
1577 return MLnS(RegisterPostIndexed);
1578 } else if (BITS(inst, 23, 27) == 0x11) {
1579 /* 3 */
1580// DEBUG_MSG;
1581// DEBUG_LOG(ARM11, "line is %d", __LINE__);
1582 return LdnStM(IncrementAfter);
1583 } else if (BITS(inst, 23, 27) == 0x13) {
1584// DEBUG_LOG(ARM11, "line is %d", __LINE__);
1585 return LdnStM(IncrementBefore);
1586// DEBUG_MSG;
1587 } else if (BITS(inst, 23, 27) == 0x10) {
1588// DEBUG_MSG;
1589// DEBUG_LOG(ARM11, "line is %d", __LINE__);
1590 return LdnStM(DecrementAfter);
1591 } else if (BITS(inst, 23, 27) == 0x12) {
1592// DEBUG_MSG;
1593// DEBUG_LOG(ARM11, "line is %d", __LINE__);
1594 return LdnStM(DecrementBefore);
1595 }
1596 #if 0
1597 DEBUG_LOG(ARM11, "In %s Unknown addressing mode\n", __FUNCTION__);
1598 DEBUG_LOG(ARM11, "inst:%x\n", inst);
1599 CITRA_IGNORE_EXIT(-1);
1600 #endif
1601 return NULL;
1602} 1411}
1603 1412
1604#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s) 1413#define INTERPRETER_TRANSLATE(s) glue(InterpreterTranslate_, s)
1605 1414
1606#define CHECK_RN (inst_cream->Rn == 15) 1415#define CHECK_RN (inst_cream->Rn == 15)
1607#define CHECK_RM (inst_cream->Rm == 15) 1416#define CHECK_RM (inst_cream->Rm == 15)
1608#define CHECK_RS (inst_cream->Rs == 15) 1417#define CHECK_RS (inst_cream->Rs == 15)
1609 1418
1610#define UNIMPLEMENTED_INSTRUCTION(mnemonic) \ 1419#define UNIMPLEMENTED_INSTRUCTION(mnemonic) \
1611 LOG_ERROR(Core_ARM11, "unimplemented instruction: %s", mnemonic); \ 1420 LOG_ERROR(Core_ARM11, "unimplemented instruction: %s", mnemonic); \
@@ -1614,882 +1423,970 @@ get_addr_fp_t get_calc_addr_op(unsigned int inst)
1614 1423
1615ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index) 1424ARM_INST_PTR INTERPRETER_TRANSLATE(adc)(unsigned int inst, int index)
1616{ 1425{
1617 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst)); 1426 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(adc_inst));
1618 adc_inst *inst_cream = (adc_inst *)inst_base->component; 1427 adc_inst *inst_cream = (adc_inst *)inst_base->component;
1619 1428
1620 inst_base->cond = BITS(inst, 28, 31); 1429 inst_base->cond = BITS(inst, 28, 31);
1621 inst_base->idx = index; 1430 inst_base->idx = index;
1622 inst_base->br = NON_BRANCH; 1431 inst_base->br = NON_BRANCH;
1623 inst_base->load_r15 = 0; 1432 inst_base->load_r15 = 0;
1624 1433
1625 inst_cream->I = BIT(inst, 25); 1434 inst_cream->I = BIT(inst, 25);
1626 inst_cream->S = BIT(inst, 20); 1435 inst_cream->S = BIT(inst, 20);
1627 inst_cream->Rn = BITS(inst, 16, 19); 1436 inst_cream->Rn = BITS(inst, 16, 19);
1628 inst_cream->Rd = BITS(inst, 12, 15); 1437 inst_cream->Rd = BITS(inst, 12, 15);
1629 if (CHECK_RN) 1438 if (CHECK_RN)
1630 inst_base->load_r15 = 1; 1439 inst_base->load_r15 = 1;
1631 inst_cream->shifter_operand = BITS(inst, 0, 11); 1440 inst_cream->shifter_operand = BITS(inst, 0, 11);
1632 inst_cream->shtop_func = get_shtop(inst); 1441 inst_cream->shtop_func = get_shtop(inst);
1633 if (inst_cream->Rd == 15) { 1442 if (inst_cream->Rd == 15) {
1634 inst_base->br = INDIRECT_BRANCH; 1443 inst_base->br = INDIRECT_BRANCH;
1635 } 1444 }
1636 return inst_base; 1445 return inst_base;
1637} 1446}
1638ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index) 1447ARM_INST_PTR INTERPRETER_TRANSLATE(add)(unsigned int inst, int index)
1639{ 1448{
1640 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(add_inst)); 1449 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(add_inst));
1641 add_inst *inst_cream = (add_inst *)inst_base->component; 1450 add_inst *inst_cream = (add_inst *)inst_base->component;
1642 1451
1643 inst_base->cond = BITS(inst, 28, 31); 1452 inst_base->cond = BITS(inst, 28, 31);
1644 inst_base->idx = index; 1453 inst_base->idx = index;
1645 inst_base->br = NON_BRANCH; 1454 inst_base->br = NON_BRANCH;
1646 inst_base->load_r15 = 0; 1455 inst_base->load_r15 = 0;
1647 1456
1648 inst_cream->I = BIT(inst, 25); 1457 inst_cream->I = BIT(inst, 25);
1649 inst_cream->S = BIT(inst, 20); 1458 inst_cream->S = BIT(inst, 20);
1650 inst_cream->Rn = BITS(inst, 16, 19); 1459 inst_cream->Rn = BITS(inst, 16, 19);
1651 inst_cream->Rd = BITS(inst, 12, 15); 1460 inst_cream->Rd = BITS(inst, 12, 15);
1652 if (CHECK_RN) 1461 if (CHECK_RN)
1653 inst_base->load_r15 = 1; 1462 inst_base->load_r15 = 1;
1654 inst_cream->shifter_operand = BITS(inst, 0, 11); 1463 inst_cream->shifter_operand = BITS(inst, 0, 11);
1655 inst_cream->shtop_func = get_shtop(inst); 1464 inst_cream->shtop_func = get_shtop(inst);
1656 if (inst_cream->Rd == 15) { 1465 if (inst_cream->Rd == 15) {
1657 inst_base->br = INDIRECT_BRANCH; 1466 inst_base->br = INDIRECT_BRANCH;
1658 } 1467 }
1659 return inst_base; 1468 return inst_base;
1660} 1469}
1661ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index) 1470ARM_INST_PTR INTERPRETER_TRANSLATE(and)(unsigned int inst, int index)
1662{ 1471{
1663 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(and_inst)); 1472 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(and_inst));
1664 and_inst *inst_cream = (and_inst *)inst_base->component; 1473 and_inst *inst_cream = (and_inst *)inst_base->component;
1665 1474
1666 inst_base->cond = BITS(inst, 28, 31); 1475 inst_base->cond = BITS(inst, 28, 31);
1667 inst_base->idx = index; 1476 inst_base->idx = index;
1668 inst_base->br = NON_BRANCH; 1477 inst_base->br = NON_BRANCH;
1669 inst_base->load_r15 = 0; 1478 inst_base->load_r15 = 0;
1670 1479
1671 inst_cream->I = BIT(inst, 25); 1480 inst_cream->I = BIT(inst, 25);
1672 inst_cream->S = BIT(inst, 20); 1481 inst_cream->S = BIT(inst, 20);
1673 inst_cream->Rn = BITS(inst, 16, 19); 1482 inst_cream->Rn = BITS(inst, 16, 19);
1674 inst_cream->Rd = BITS(inst, 12, 15); 1483 inst_cream->Rd = BITS(inst, 12, 15);
1675 if (CHECK_RN) 1484 if (CHECK_RN)
1676 inst_base->load_r15 = 1; 1485 inst_base->load_r15 = 1;
1677 inst_cream->shifter_operand = BITS(inst, 0, 11); 1486 inst_cream->shifter_operand = BITS(inst, 0, 11);
1678 inst_cream->shtop_func = get_shtop(inst); 1487 inst_cream->shtop_func = get_shtop(inst);
1679 if (inst_cream->Rd == 15) 1488 if (inst_cream->Rd == 15)
1680 inst_base->br = INDIRECT_BRANCH; 1489 inst_base->br = INDIRECT_BRANCH;
1681 return inst_base; 1490 return inst_base;
1682} 1491}
1683ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index) 1492ARM_INST_PTR INTERPRETER_TRANSLATE(bbl)(unsigned int inst, int index)
1684{ 1493{
1685 #define POSBRANCH ((inst & 0x7fffff) << 2) 1494 #define POSBRANCH ((inst & 0x7fffff) << 2)
1686 #define NEGBRANCH ((0xff000000 |(inst & 0xffffff)) << 2) 1495 #define NEGBRANCH ((0xff000000 |(inst & 0xffffff)) << 2)
1687 1496
1688 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst)); 1497 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bbl_inst));
1689 bbl_inst *inst_cream = (bbl_inst *)inst_base->component; 1498 bbl_inst *inst_cream = (bbl_inst *)inst_base->component;
1690 1499
1691 inst_base->cond = BITS(inst, 28, 31); 1500 inst_base->cond = BITS(inst, 28, 31);
1692 inst_base->idx = index; 1501 inst_base->idx = index;
1693 inst_base->br = DIRECT_BRANCH; 1502 inst_base->br = DIRECT_BRANCH;
1694 1503
1695 if (BIT(inst, 24)) 1504 if (BIT(inst, 24))
1696 inst_base->br = CALL; 1505 inst_base->br = CALL;
1697 if (BITS(inst, 28, 31) <= 0xe) 1506 if (BITS(inst, 28, 31) <= 0xe)
1698 inst_base->br |= COND; 1507 inst_base->br |= COND;
1699 1508
1700 inst_cream->L = BIT(inst, 24); 1509 inst_cream->L = BIT(inst, 24);
1701 inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH; 1510 inst_cream->signed_immed_24 = BIT(inst, 23) ? NEGBRANCH : POSBRANCH;
1702 1511
1703 return inst_base; 1512 return inst_base;
1704} 1513}
1705ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index) 1514ARM_INST_PTR INTERPRETER_TRANSLATE(bic)(unsigned int inst, int index)
1706{ 1515{
1707 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bic_inst)); 1516 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bic_inst));
1708 bic_inst *inst_cream = (bic_inst *)inst_base->component; 1517 bic_inst *inst_cream = (bic_inst *)inst_base->component;
1709 1518
1710 inst_base->cond = BITS(inst, 28, 31); 1519 inst_base->cond = BITS(inst, 28, 31);
1711 inst_base->idx = index; 1520 inst_base->idx = index;
1712 inst_base->br = NON_BRANCH; 1521 inst_base->br = NON_BRANCH;
1713 inst_base->load_r15 = 0; 1522 inst_base->load_r15 = 0;
1714 1523
1715 inst_cream->I = BIT(inst, 25); 1524 inst_cream->I = BIT(inst, 25);
1716 inst_cream->S = BIT(inst, 20); 1525 inst_cream->S = BIT(inst, 20);
1717 inst_cream->Rn = BITS(inst, 16, 19); 1526 inst_cream->Rn = BITS(inst, 16, 19);
1718 inst_cream->Rd = BITS(inst, 12, 15); 1527 inst_cream->Rd = BITS(inst, 12, 15);
1719 if (CHECK_RN) 1528 if (CHECK_RN)
1720 inst_base->load_r15 = 1; 1529 inst_base->load_r15 = 1;
1721 inst_cream->shifter_operand = BITS(inst, 0, 11); 1530 inst_cream->shifter_operand = BITS(inst, 0, 11);
1722 inst_cream->shtop_func = get_shtop(inst); 1531 inst_cream->shtop_func = get_shtop(inst);
1723 1532
1724 if (inst_cream->Rd == 15) 1533 if (inst_cream->Rd == 15)
1725 inst_base->br = INDIRECT_BRANCH; 1534 inst_base->br = INDIRECT_BRANCH;
1726 return inst_base; 1535 return inst_base;
1727} 1536}
1728ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("BKPT"); } 1537ARM_INST_PTR INTERPRETER_TRANSLATE(bkpt)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("BKPT"); }
1729ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index) 1538ARM_INST_PTR INTERPRETER_TRANSLATE(blx)(unsigned int inst, int index)
1730{ 1539{
1731 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_inst)); 1540 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_inst));
1732 blx_inst *inst_cream = (blx_inst *)inst_base->component; 1541 blx_inst *inst_cream = (blx_inst *)inst_base->component;
1733 1542
1734 inst_base->cond = BITS(inst, 28, 31); 1543 inst_base->cond = BITS(inst, 28, 31);
1735 inst_base->idx = index; 1544 inst_base->idx = index;
1736 inst_base->br = INDIRECT_BRANCH; 1545 inst_base->br = INDIRECT_BRANCH;
1737 1546
1738 inst_cream->inst = inst; 1547 inst_cream->inst = inst;
1739 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { 1548 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
1740 inst_cream->val.Rm = BITS(inst, 0, 3); 1549 inst_cream->val.Rm = BITS(inst, 0, 3);
1741 } else { 1550 } else {
1742 inst_cream->val.signed_immed_24 = BITS(inst, 0, 23); 1551 inst_cream->val.signed_immed_24 = BITS(inst, 0, 23);
1743 //DEBUG_LOG(ARM11, " blx inst is %x\n", inst); 1552 }
1744 //CITRA_IGNORE_EXIT(-1);
1745// DEBUG_MSG;
1746 }
1747 1553
1748 return inst_base; 1554 return inst_base;
1749} 1555}
1750ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index) 1556ARM_INST_PTR INTERPRETER_TRANSLATE(bx)(unsigned int inst, int index)
1751{ 1557{
1752 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst)); 1558 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bx_inst));
1753 bx_inst *inst_cream = (bx_inst *)inst_base->component; 1559 bx_inst *inst_cream = (bx_inst *)inst_base->component;
1754 1560
1755 inst_base->cond = BITS(inst, 28, 31); 1561 inst_base->cond = BITS(inst, 28, 31);
1756 inst_base->idx = index; 1562 inst_base->idx = index;
1757 inst_base->br = INDIRECT_BRANCH; 1563 inst_base->br = INDIRECT_BRANCH;
1758 1564
1759 inst_cream->Rm = BITS(inst, 0, 3); 1565 inst_cream->Rm = BITS(inst, 0, 3);
1760 1566
1761 return inst_base; 1567 return inst_base;
1762} 1568}
1763ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("BXJ"); } 1569ARM_INST_PTR INTERPRETER_TRANSLATE(bxj)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("BXJ"); }
1764ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index){ 1570ARM_INST_PTR INTERPRETER_TRANSLATE(cdp)(unsigned int inst, int index){
1765 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst)); 1571 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cdp_inst));
1766 cdp_inst *inst_cream = (cdp_inst *)inst_base->component; 1572 cdp_inst *inst_cream = (cdp_inst *)inst_base->component;
1767 inst_base->cond = BITS(inst, 28, 31); 1573 inst_base->cond = BITS(inst, 28, 31);
1768 inst_base->idx = index; 1574 inst_base->idx = index;
1769 inst_base->br = NON_BRANCH; 1575 inst_base->br = NON_BRANCH;
1770 inst_base->load_r15 = 0; 1576 inst_base->load_r15 = 0;
1771 1577
1772 inst_cream->CRm = BITS(inst, 0, 3); 1578 inst_cream->CRm = BITS(inst, 0, 3);
1773 inst_cream->CRd = BITS(inst, 12, 15); 1579 inst_cream->CRd = BITS(inst, 12, 15);
1774 inst_cream->CRn = BITS(inst, 16, 19); 1580 inst_cream->CRn = BITS(inst, 16, 19);
1775 inst_cream->cp_num = BITS(inst, 8, 11); 1581 inst_cream->cp_num = BITS(inst, 8, 11);
1776 inst_cream->opcode_2 = BITS(inst, 5, 7); 1582 inst_cream->opcode_2 = BITS(inst, 5, 7);
1777 inst_cream->opcode_1 = BITS(inst, 20, 23); 1583 inst_cream->opcode_1 = BITS(inst, 20, 23);
1778 inst_cream->inst = inst; 1584 inst_cream->inst = inst;
1779 1585
1780 LOG_TRACE(Core_ARM11, "inst %x index %x", inst, index); 1586 LOG_TRACE(Core_ARM11, "inst %x index %x", inst, index);
1781 return inst_base; 1587 return inst_base;
1782} 1588}
1783ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index) 1589ARM_INST_PTR INTERPRETER_TRANSLATE(clrex)(unsigned int inst, int index)
1784{ 1590{
1785 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clrex_inst)); 1591 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clrex_inst));
1786 inst_base->cond = BITS(inst, 28, 31); 1592 inst_base->cond = BITS(inst, 28, 31);
1787 inst_base->idx = index; 1593 inst_base->idx = index;
1788 inst_base->br = NON_BRANCH; 1594 inst_base->br = NON_BRANCH;
1789 1595
1790 return inst_base; 1596 return inst_base;
1791} 1597}
1792ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index) 1598ARM_INST_PTR INTERPRETER_TRANSLATE(clz)(unsigned int inst, int index)
1793{ 1599{
1794 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clz_inst)); 1600 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(clz_inst));
1795 clz_inst *inst_cream = (clz_inst *)inst_base->component; 1601 clz_inst *inst_cream = (clz_inst *)inst_base->component;
1796 1602
1797 inst_base->cond = BITS(inst, 28, 31); 1603 inst_base->cond = BITS(inst, 28, 31);
1798 inst_base->idx = index; 1604 inst_base->idx = index;
1799 inst_base->br = NON_BRANCH; 1605 inst_base->br = NON_BRANCH;
1800 inst_base->load_r15 = 0; 1606 inst_base->load_r15 = 0;
1801 1607
1802 inst_cream->Rm = BITS(inst, 0, 3); 1608 inst_cream->Rm = BITS(inst, 0, 3);
1803 inst_cream->Rd = BITS(inst, 12, 15); 1609 inst_cream->Rd = BITS(inst, 12, 15);
1804 if (CHECK_RM) 1610 if (CHECK_RM)
1805 inst_base->load_r15 = 1; 1611 inst_base->load_r15 = 1;
1806 1612
1807 return inst_base; 1613 return inst_base;
1808} 1614}
1809ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index) 1615ARM_INST_PTR INTERPRETER_TRANSLATE(cmn)(unsigned int inst, int index)
1810{ 1616{
1811 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmn_inst)); 1617 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmn_inst));
1812 cmn_inst *inst_cream = (cmn_inst *)inst_base->component; 1618 cmn_inst *inst_cream = (cmn_inst *)inst_base->component;
1813 1619
1814 inst_base->cond = BITS(inst, 28, 31); 1620 inst_base->cond = BITS(inst, 28, 31);
1815 inst_base->idx = index; 1621 inst_base->idx = index;
1816 inst_base->br = NON_BRANCH; 1622 inst_base->br = NON_BRANCH;
1817 inst_base->load_r15 = 0; 1623 inst_base->load_r15 = 0;
1818 1624
1819 inst_cream->I = BIT(inst, 25); 1625 inst_cream->I = BIT(inst, 25);
1820 //inst_cream->S = BIT(inst, 20); 1626 //inst_cream->S = BIT(inst, 20);
1821 inst_cream->Rn = BITS(inst, 16, 19); 1627 inst_cream->Rn = BITS(inst, 16, 19);
1822 //inst_cream->Rd = BITS(inst, 12, 15); 1628 //inst_cream->Rd = BITS(inst, 12, 15);
1823 if (CHECK_RN) 1629 if (CHECK_RN)
1824 inst_base->load_r15 = 1; 1630 inst_base->load_r15 = 1;
1825 inst_cream->shifter_operand = BITS(inst, 0, 11); 1631 inst_cream->shifter_operand = BITS(inst, 0, 11);
1826 inst_cream->shtop_func = get_shtop(inst); 1632 inst_cream->shtop_func = get_shtop(inst);
1827 return inst_base; 1633 return inst_base;
1828} 1634}
1829ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index) 1635ARM_INST_PTR INTERPRETER_TRANSLATE(cmp)(unsigned int inst, int index)
1830{ 1636{
1831 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmp_inst)); 1637 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cmp_inst));
1832 cmp_inst *inst_cream = (cmp_inst *)inst_base->component; 1638 cmp_inst *inst_cream = (cmp_inst *)inst_base->component;
1833 1639
1834 inst_base->cond = BITS(inst, 28, 31); 1640 inst_base->cond = BITS(inst, 28, 31);
1835 inst_base->idx = index; 1641 inst_base->idx = index;
1836 inst_base->br = NON_BRANCH; 1642 inst_base->br = NON_BRANCH;
1837 inst_base->load_r15 = 0; 1643 inst_base->load_r15 = 0;
1838 1644
1839 inst_cream->I = BIT(inst, 25); 1645 inst_cream->I = BIT(inst, 25);
1840 inst_cream->Rn = BITS(inst, 16, 19); 1646 inst_cream->Rn = BITS(inst, 16, 19);
1841 if (CHECK_RN) 1647 if (CHECK_RN)
1842 inst_base->load_r15 = 1; 1648 inst_base->load_r15 = 1;
1843 inst_cream->shifter_operand = BITS(inst, 0, 11); 1649 inst_cream->shifter_operand = BITS(inst, 0, 11);
1844 inst_cream->shtop_func = get_shtop(inst); 1650 inst_cream->shtop_func = get_shtop(inst);
1845 return inst_base; 1651 return inst_base;
1846} 1652}
1847ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index) 1653ARM_INST_PTR INTERPRETER_TRANSLATE(cps)(unsigned int inst, int index)
1848{ 1654{
1849 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cps_inst)); 1655 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(cps_inst));
1850 cps_inst *inst_cream = (cps_inst *)inst_base->component; 1656 cps_inst *inst_cream = (cps_inst *)inst_base->component;
1851 1657
1852 inst_base->cond = BITS(inst, 28, 31); 1658 inst_base->cond = BITS(inst, 28, 31);
1853 inst_base->idx = index; 1659 inst_base->idx = index;
1854 inst_base->br = NON_BRANCH; 1660 inst_base->br = NON_BRANCH;
1855 1661
1856 inst_cream->imod0 = BIT(inst, 18); 1662 inst_cream->imod0 = BIT(inst, 18);
1857 inst_cream->imod1 = BIT(inst, 19); 1663 inst_cream->imod1 = BIT(inst, 19);
1858 inst_cream->mmod = BIT(inst, 17); 1664 inst_cream->mmod = BIT(inst, 17);
1859 inst_cream->A = BIT(inst, 8); 1665 inst_cream->A = BIT(inst, 8);
1860 inst_cream->I = BIT(inst, 7); 1666 inst_cream->I = BIT(inst, 7);
1861 inst_cream->F = BIT(inst, 6); 1667 inst_cream->F = BIT(inst, 6);
1862 inst_cream->mode = BITS(inst, 0, 4); 1668 inst_cream->mode = BITS(inst, 0, 4);
1863 1669
1864 return inst_base; 1670 return inst_base;
1865} 1671}
1866ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index) 1672ARM_INST_PTR INTERPRETER_TRANSLATE(cpy)(unsigned int inst, int index)
1867{ 1673{
1868 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst)); 1674 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst));
1869 mov_inst *inst_cream = (mov_inst *)inst_base->component; 1675 mov_inst *inst_cream = (mov_inst *)inst_base->component;
1870 1676
1871 inst_base->cond = BITS(inst, 28, 31); 1677 inst_base->cond = BITS(inst, 28, 31);
1872 inst_base->idx = index; 1678 inst_base->idx = index;
1873 inst_base->br = NON_BRANCH; 1679 inst_base->br = NON_BRANCH;
1874 1680
1875 inst_cream->I = BIT(inst, 25); 1681 inst_cream->I = BIT(inst, 25);
1876 inst_cream->S = BIT(inst, 20); 1682 inst_cream->S = BIT(inst, 20);
1877 inst_cream->Rd = BITS(inst, 12, 15); 1683 inst_cream->Rd = BITS(inst, 12, 15);
1878 inst_cream->shifter_operand = BITS(inst, 0, 11); 1684 inst_cream->shifter_operand = BITS(inst, 0, 11);
1879 inst_cream->shtop_func = get_shtop(inst); 1685 inst_cream->shtop_func = get_shtop(inst);
1880 1686
1881 if (inst_cream->Rd == 15) { 1687 if (inst_cream->Rd == 15) {
1882 inst_base->br = INDIRECT_BRANCH; 1688 inst_base->br = INDIRECT_BRANCH;
1883 } 1689 }
1884 return inst_base; 1690 return inst_base;
1885} 1691}
1886ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index) 1692ARM_INST_PTR INTERPRETER_TRANSLATE(eor)(unsigned int inst, int index)
1887{ 1693{
1888 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(eor_inst)); 1694 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(eor_inst));
1889 eor_inst *inst_cream = (eor_inst *)inst_base->component; 1695 eor_inst *inst_cream = (eor_inst *)inst_base->component;
1890 1696
1891 inst_base->cond = BITS(inst, 28, 31); 1697 inst_base->cond = BITS(inst, 28, 31);
1892 inst_base->idx = index; 1698 inst_base->idx = index;
1893 inst_base->br = NON_BRANCH; 1699 inst_base->br = NON_BRANCH;
1894 inst_base->load_r15 = 0; 1700 inst_base->load_r15 = 0;
1895 1701
1896 inst_cream->I = BIT(inst, 25); 1702 inst_cream->I = BIT(inst, 25);
1897 inst_cream->S = BIT(inst, 20); 1703 inst_cream->S = BIT(inst, 20);
1898 inst_cream->Rn = BITS(inst, 16, 19); 1704 inst_cream->Rn = BITS(inst, 16, 19);
1899 inst_cream->Rd = BITS(inst, 12, 15); 1705 inst_cream->Rd = BITS(inst, 12, 15);
1900 if (CHECK_RN) 1706 if (CHECK_RN)
1901 inst_base->load_r15 = 1; 1707 inst_base->load_r15 = 1;
1902 inst_cream->shifter_operand = BITS(inst, 0, 11); 1708 inst_cream->shifter_operand = BITS(inst, 0, 11);
1903 inst_cream->shtop_func = get_shtop(inst); 1709 inst_cream->shtop_func = get_shtop(inst);
1904 if (inst_cream->Rd == 15) { 1710 if (inst_cream->Rd == 15) {
1905 inst_base->br = INDIRECT_BRANCH; 1711 inst_base->br = INDIRECT_BRANCH;
1906 } 1712 }
1907 return inst_base; 1713 return inst_base;
1908} 1714}
1909ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index) 1715ARM_INST_PTR INTERPRETER_TRANSLATE(ldc)(unsigned int inst, int index)
1910{ 1716{
1911 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldc_inst)); 1717 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldc_inst));
1912 inst_base->cond = BITS(inst, 28, 31); 1718 inst_base->cond = BITS(inst, 28, 31);
1913 inst_base->idx = index; 1719 inst_base->idx = index;
1914 inst_base->br = NON_BRANCH; 1720 inst_base->br = NON_BRANCH;
1915 1721
1916 return inst_base; 1722 return inst_base;
1917} 1723}
1918ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index) 1724ARM_INST_PTR INTERPRETER_TRANSLATE(ldm)(unsigned int inst, int index)
1919{ 1725{
1920 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1726 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1921 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1727 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
1922 1728
1923 inst_base->cond = BITS(inst, 28, 31); 1729 inst_base->cond = BITS(inst, 28, 31);
1924 inst_base->idx = index; 1730 inst_base->idx = index;
1925 inst_base->br = NON_BRANCH; 1731 inst_base->br = NON_BRANCH;
1926 1732
1927 inst_cream->inst = inst; 1733 inst_cream->inst = inst;
1928 inst_cream->get_addr = get_calc_addr_op(inst); 1734 inst_cream->get_addr = get_calc_addr_op(inst);
1929 1735
1930 if (BIT(inst, 15)) { 1736 if (BIT(inst, 15)) {
1931 inst_base->br = INDIRECT_BRANCH; 1737 inst_base->br = INDIRECT_BRANCH;
1932 } 1738 }
1933 return inst_base; 1739 return inst_base;
1934} 1740}
1935ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index) 1741ARM_INST_PTR INTERPRETER_TRANSLATE(sxth)(unsigned int inst, int index)
1936{ 1742{
1937 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst)); 1743 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst));
1938 sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component; 1744 sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component;
1939 1745
1940 inst_base->cond = BITS(inst, 28, 31); 1746 inst_base->cond = BITS(inst, 28, 31);
1941 inst_base->idx = index; 1747 inst_base->idx = index;
1942 inst_base->br = NON_BRANCH; 1748 inst_base->br = NON_BRANCH;
1943 inst_base->load_r15 = 0; 1749 inst_base->load_r15 = 0;
1944 1750
1945 inst_cream->Rd = BITS(inst, 12, 15); 1751 inst_cream->Rd = BITS(inst, 12, 15);
1946 inst_cream->Rm = BITS(inst, 0, 3); 1752 inst_cream->Rm = BITS(inst, 0, 3);
1947 inst_cream->rotate = BITS(inst, 10, 11); 1753 inst_cream->rotate = BITS(inst, 10, 11);
1948 if (CHECK_RM) 1754 if (CHECK_RM)
1949 inst_base->load_r15 = 1; 1755 inst_base->load_r15 = 1;
1950 1756
1951 return inst_base; 1757 return inst_base;
1952} 1758}
1953ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index) 1759ARM_INST_PTR INTERPRETER_TRANSLATE(ldr)(unsigned int inst, int index)
1954{ 1760{
1955 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1761 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1956 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1762 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
1957 1763
1958 inst_base->cond = BITS(inst, 28, 31); 1764 inst_base->cond = BITS(inst, 28, 31);
1959 inst_base->idx = index; 1765 inst_base->idx = index;
1960 inst_base->br = NON_BRANCH; 1766 inst_base->br = NON_BRANCH;
1961 inst_base->load_r15 = 0; 1767 inst_base->load_r15 = 0;
1962 1768
1963 inst_cream->inst = inst; 1769 inst_cream->inst = inst;
1964 inst_cream->get_addr = get_calc_addr_op(inst); 1770 inst_cream->get_addr = get_calc_addr_op(inst);
1965 1771
1966 if (BITS(inst, 12, 15) == 15) { 1772 if (BITS(inst, 12, 15) == 15) {
1967 inst_base->br = INDIRECT_BRANCH; 1773 inst_base->br = INDIRECT_BRANCH;
1968 } 1774 }
1969 return inst_base; 1775 return inst_base;
1970} 1776}
1971 1777
1972ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index) 1778ARM_INST_PTR INTERPRETER_TRANSLATE(ldrcond)(unsigned int inst, int index)
1973{ 1779{
1974 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1780 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
1975 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1781 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
1976 1782
1977 inst_base->cond = BITS(inst, 28, 31); 1783 inst_base->cond = BITS(inst, 28, 31);
1978 inst_base->idx = index; 1784 inst_base->idx = index;
1979 inst_base->br = NON_BRANCH; 1785 inst_base->br = NON_BRANCH;
1980 inst_base->load_r15 = 0; 1786 inst_base->load_r15 = 0;
1981 1787
1982 inst_cream->inst = inst; 1788 inst_cream->inst = inst;
1983 inst_cream->get_addr = get_calc_addr_op(inst); 1789 inst_cream->get_addr = get_calc_addr_op(inst);
1984 1790
1985 if (BITS(inst, 12, 15) == 15) { 1791 if (BITS(inst, 12, 15) == 15) {
1986 inst_base->br = INDIRECT_BRANCH; 1792 inst_base->br = INDIRECT_BRANCH;
1987 } 1793 }
1988 return inst_base; 1794 return inst_base;
1989} 1795}
1990 1796
1991ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index) 1797ARM_INST_PTR INTERPRETER_TRANSLATE(uxth)(unsigned int inst, int index)
1992{ 1798{
1993 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst)); 1799 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst));
1994 uxth_inst *inst_cream = (uxth_inst *)inst_base->component; 1800 uxth_inst *inst_cream = (uxth_inst *)inst_base->component;
1995 1801
1996 inst_base->cond = BITS(inst, 28, 31); 1802 inst_base->cond = BITS(inst, 28, 31);
1997 inst_base->idx = index; 1803 inst_base->idx = index;
1998 inst_base->br = NON_BRANCH; 1804 inst_base->br = NON_BRANCH;
1999 inst_base->load_r15 = 0; 1805 inst_base->load_r15 = 0;
2000 1806
2001 inst_cream->Rd = BITS(inst, 12, 15); 1807 inst_cream->Rd = BITS(inst, 12, 15);
2002 inst_cream->rotate = BITS(inst, 10, 11); 1808 inst_cream->rotate = BITS(inst, 10, 11);
2003 inst_cream->Rm = BITS(inst, 0, 3); 1809 inst_cream->Rm = BITS(inst, 0, 3);
2004 if (CHECK_RM) 1810 if (CHECK_RM)
2005 inst_base->load_r15 = 1; 1811 inst_base->load_r15 = 1;
2006 1812
2007 return inst_base; 1813 return inst_base;
2008} 1814}
2009ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index) 1815ARM_INST_PTR INTERPRETER_TRANSLATE(uxtah)(unsigned int inst, int index)
2010{ 1816{
2011 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtah_inst)); 1817 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtah_inst));
2012 uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component; 1818 uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component;
2013 1819
2014 inst_base->cond = BITS(inst, 28, 31); 1820 inst_base->cond = BITS(inst, 28, 31);
2015 inst_base->idx = index; 1821 inst_base->idx = index;
2016 inst_base->br = NON_BRANCH; 1822 inst_base->br = NON_BRANCH;
2017 inst_base->load_r15 = 0; 1823 inst_base->load_r15 = 0;
2018 1824
2019 inst_cream->Rn = BITS(inst, 16, 19); 1825 inst_cream->Rn = BITS(inst, 16, 19);
2020 inst_cream->Rd = BITS(inst, 12, 15); 1826 inst_cream->Rd = BITS(inst, 12, 15);
2021 inst_cream->rotate = BITS(inst, 10, 11); 1827 inst_cream->rotate = BITS(inst, 10, 11);
2022 inst_cream->Rm = BITS(inst, 0, 3); 1828 inst_cream->Rm = BITS(inst, 0, 3);
2023 if (CHECK_RM || CHECK_RN) 1829 if (CHECK_RM || CHECK_RN)
2024 inst_base->load_r15 = 1; 1830 inst_base->load_r15 = 1;
2025 1831
2026 return inst_base; 1832 return inst_base;
2027} 1833}
2028ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index) 1834ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index)
2029{ 1835{
2030 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1836 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2031 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1837 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2032 1838
2033 inst_base->cond = BITS(inst, 28, 31); 1839 inst_base->cond = BITS(inst, 28, 31);
2034 inst_base->idx = index; 1840 inst_base->idx = index;
2035 inst_base->br = NON_BRANCH; 1841 inst_base->br = NON_BRANCH;
2036 1842
2037 inst_cream->inst = inst; 1843 inst_cream->inst = inst;
2038 inst_cream->get_addr = get_calc_addr_op(inst); 1844 inst_cream->get_addr = get_calc_addr_op(inst);
2039 1845
2040 if (BITS(inst, 12, 15) == 15) { 1846 if (BITS(inst, 12, 15) == 15) {
2041 inst_base->br = INDIRECT_BRANCH; 1847 inst_base->br = INDIRECT_BRANCH;
2042 } 1848 }
2043 return inst_base; 1849 return inst_base;
2044} 1850}
2045ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index) 1851ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index)
2046{ 1852{
2047 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1853 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2048 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1854 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2049 1855
2050 inst_base->cond = BITS(inst, 28, 31); 1856 inst_base->cond = BITS(inst, 28, 31);
2051 inst_base->idx = index; 1857 inst_base->idx = index;
2052 inst_base->br = NON_BRANCH; 1858 inst_base->br = NON_BRANCH;
2053 1859
2054 inst_cream->inst = inst; 1860 inst_cream->inst = inst;
2055 if (I_BIT == 0) { 1861 if (I_BIT == 0) {
2056 inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); 1862 inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
2057 } else { 1863 } else {
2058 DEBUG_MSG; 1864 DEBUG_MSG;
2059 } 1865 }
2060 #if 0 1866 #if 0
2061 inst_cream->get_addr = get_calc_addr_op(inst); 1867 inst_cream->get_addr = get_calc_addr_op(inst);
2062 if(inst == 0x54f13001) { 1868 if(inst == 0x54f13001) {
2063 DEBUG_LOG(ARM11, "get_calc_addr_op:%llx\n", inst_cream->get_addr); 1869 DEBUG_LOG(ARM11, "get_calc_addr_op:%llx\n", inst_cream->get_addr);
2064 } 1870 }
2065 #endif 1871 #endif
2066 1872
2067 if (BITS(inst, 12, 15) == 15) { 1873 if (BITS(inst, 12, 15) == 15) {
2068 inst_base->br = INDIRECT_BRANCH; 1874 inst_base->br = INDIRECT_BRANCH;
2069 } 1875 }
2070 return inst_base; 1876 return inst_base;
2071} 1877}
2072ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index) 1878ARM_INST_PTR INTERPRETER_TRANSLATE(ldrd)(unsigned int inst, int index)
2073{ 1879{
2074 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1880 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2075 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1881 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2076 1882
2077 inst_base->cond = BITS(inst, 28, 31); 1883 inst_base->cond = BITS(inst, 28, 31);
2078 inst_base->idx = index; 1884 inst_base->idx = index;
2079 inst_base->br = NON_BRANCH; 1885 inst_base->br = NON_BRANCH;
2080 1886
2081 inst_cream->inst = inst; 1887 inst_cream->inst = inst;
2082 inst_cream->get_addr = get_calc_addr_op(inst); 1888 inst_cream->get_addr = get_calc_addr_op(inst);
2083 1889
2084 return inst_base; 1890 return inst_base;
2085} 1891}
2086 1892
2087ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index) 1893ARM_INST_PTR INTERPRETER_TRANSLATE(ldrex)(unsigned int inst, int index)
2088{ 1894{
2089 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1895 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2090 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1896 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2091 1897
2092 inst_base->cond = BITS(inst, 28, 31); 1898 inst_base->cond = BITS(inst, 28, 31);
2093 inst_base->idx = index; 1899 inst_base->idx = index;
2094 inst_base->br = NON_BRANCH; 1900 inst_base->br = NON_BRANCH;
2095 1901
2096 inst_cream->inst = inst; 1902 inst_cream->inst = inst;
2097 //inst_cream->get_addr = get_calc_addr_op(inst); 1903 //inst_cream->get_addr = get_calc_addr_op(inst);
2098 1904
2099 if (BITS(inst, 12, 15) == 15) { 1905 if (BITS(inst, 12, 15) == 15) {
2100 inst_base->br = INDIRECT_BRANCH; 1906 inst_base->br = INDIRECT_BRANCH;
2101 } 1907 }
2102 return inst_base; 1908 return inst_base;
2103} 1909}
2104ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index) 1910ARM_INST_PTR INTERPRETER_TRANSLATE(ldrexb)(unsigned int inst, int index)
2105{ 1911{
2106 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1912 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2107 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1913 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2108 1914
2109 inst_base->cond = BITS(inst, 28, 31); 1915 inst_base->cond = BITS(inst, 28, 31);
2110 inst_base->idx = index; 1916 inst_base->idx = index;
2111 inst_base->br = NON_BRANCH; 1917 inst_base->br = NON_BRANCH;
2112 1918
2113 inst_cream->inst = inst; 1919 inst_cream->inst = inst;
2114 inst_cream->get_addr = get_calc_addr_op(inst); 1920 inst_cream->get_addr = get_calc_addr_op(inst);
2115 1921
2116 if (BITS(inst, 12, 15) == 15) { 1922 if (BITS(inst, 12, 15) == 15) {
2117 inst_base->br = INDIRECT_BRANCH; 1923 inst_base->br = INDIRECT_BRANCH;
2118 } 1924 }
2119 return inst_base; 1925 return inst_base;
2120} 1926}
2121ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index) 1927ARM_INST_PTR INTERPRETER_TRANSLATE(ldrh)(unsigned int inst, int index)
2122{ 1928{
2123 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1929 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2124 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1930 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2125 1931
2126 inst_base->cond = BITS(inst, 28, 31); 1932 inst_base->cond = BITS(inst, 28, 31);
2127 inst_base->idx = index; 1933 inst_base->idx = index;
2128 inst_base->br = NON_BRANCH; 1934 inst_base->br = NON_BRANCH;
2129 1935
2130 inst_cream->inst = inst; 1936 inst_cream->inst = inst;
2131 inst_cream->get_addr = get_calc_addr_op(inst); 1937 inst_cream->get_addr = get_calc_addr_op(inst);
2132 1938
2133 if (BITS(inst, 12, 15) == 15) { 1939 if (BITS(inst, 12, 15) == 15) {
2134 inst_base->br = INDIRECT_BRANCH; 1940 inst_base->br = INDIRECT_BRANCH;
2135 } 1941 }
2136 return inst_base; 1942 return inst_base;
2137} 1943}
2138ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index) 1944ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsb)(unsigned int inst, int index)
2139{ 1945{
2140 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1946 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2141 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1947 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2142 1948
2143 inst_base->cond = BITS(inst, 28, 31); 1949 inst_base->cond = BITS(inst, 28, 31);
2144 inst_base->idx = index; 1950 inst_base->idx = index;
2145 inst_base->br = NON_BRANCH; 1951 inst_base->br = NON_BRANCH;
2146 1952
2147 inst_cream->inst = inst; 1953 inst_cream->inst = inst;
2148 inst_cream->get_addr = get_calc_addr_op(inst); 1954 inst_cream->get_addr = get_calc_addr_op(inst);
2149 1955
2150 if (BITS(inst, 12, 15) == 15) { 1956 if (BITS(inst, 12, 15) == 15) {
2151 inst_base->br = INDIRECT_BRANCH; 1957 inst_base->br = INDIRECT_BRANCH;
2152 } 1958 }
2153 return inst_base; 1959 return inst_base;
2154} 1960}
2155ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) 1961ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index)
2156{ 1962{
2157 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1963 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2158 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1964 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2159 1965
2160 inst_base->cond = BITS(inst, 28, 31); 1966 inst_base->cond = BITS(inst, 28, 31);
2161 inst_base->idx = index; 1967 inst_base->idx = index;
2162 inst_base->br = NON_BRANCH; 1968 inst_base->br = NON_BRANCH;
2163 1969
2164 inst_cream->inst = inst; 1970 inst_cream->inst = inst;
2165 inst_cream->get_addr = get_calc_addr_op(inst); 1971 inst_cream->get_addr = get_calc_addr_op(inst);
2166 1972
2167 if (BITS(inst, 12, 15) == 15) { 1973 if (BITS(inst, 12, 15) == 15) {
2168 inst_base->br = INDIRECT_BRANCH; 1974 inst_base->br = INDIRECT_BRANCH;
2169 } 1975 }
2170 return inst_base; 1976 return inst_base;
2171} 1977}
2172ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index) 1978ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index)
2173{ 1979{
2174 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 1980 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2175 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 1981 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2176 1982
2177 inst_base->cond = BITS(inst, 28, 31); 1983 inst_base->cond = BITS(inst, 28, 31);
2178 inst_base->idx = index; 1984 inst_base->idx = index;
2179 inst_base->br = NON_BRANCH; 1985 inst_base->br = NON_BRANCH;
2180 1986
2181 inst_cream->inst = inst; 1987 inst_cream->inst = inst;
2182 if (I_BIT == 0) { 1988 if (I_BIT == 0) {
2183 inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); 1989 inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
2184 } else { 1990 } else {
2185 DEBUG_MSG; 1991 DEBUG_MSG;
2186 } 1992 }
2187 1993
2188 if (BITS(inst, 12, 15) == 15) { 1994 if (BITS(inst, 12, 15) == 15) {
2189 inst_base->br = INDIRECT_BRANCH; 1995 inst_base->br = INDIRECT_BRANCH;
2190 } 1996 }
2191 return inst_base; 1997 return inst_base;
2192} 1998}
2193ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index) 1999ARM_INST_PTR INTERPRETER_TRANSLATE(mcr)(unsigned int inst, int index)
2194{ 2000{
2195 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mcr_inst)); 2001 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mcr_inst));
2196 mcr_inst *inst_cream = (mcr_inst *)inst_base->component; 2002 mcr_inst *inst_cream = (mcr_inst *)inst_base->component;
2197 inst_base->cond = BITS(inst, 28, 31); 2003 inst_base->cond = BITS(inst, 28, 31);
2198 inst_base->idx = index; 2004 inst_base->idx = index;
2199 inst_base->br = NON_BRANCH; 2005 inst_base->br = NON_BRANCH;
2200 2006
2201 inst_cream->crn = BITS(inst, 16, 19); 2007 inst_cream->crn = BITS(inst, 16, 19);
2202 inst_cream->crm = BITS(inst, 0, 3); 2008 inst_cream->crm = BITS(inst, 0, 3);
2203 inst_cream->opcode_1 = BITS(inst, 21, 23); 2009 inst_cream->opcode_1 = BITS(inst, 21, 23);
2204 inst_cream->opcode_2 = BITS(inst, 5, 7); 2010 inst_cream->opcode_2 = BITS(inst, 5, 7);
2205 inst_cream->Rd = BITS(inst, 12, 15); 2011 inst_cream->Rd = BITS(inst, 12, 15);
2206 inst_cream->cp_num = BITS(inst, 8, 11); 2012 inst_cream->cp_num = BITS(inst, 8, 11);
2207 inst_cream->inst = inst; 2013 inst_cream->inst = inst;
2208 return inst_base; 2014 return inst_base;
2209} 2015}
2210ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("MCRR"); } 2016ARM_INST_PTR INTERPRETER_TRANSLATE(mcrr)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("MCRR"); }
2211ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index) 2017ARM_INST_PTR INTERPRETER_TRANSLATE(mla)(unsigned int inst, int index)
2212{ 2018{
2213 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst)); 2019 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mla_inst));
2214 mla_inst *inst_cream = (mla_inst *)inst_base->component; 2020 mla_inst *inst_cream = (mla_inst *)inst_base->component;
2215 2021
2216 inst_base->cond = BITS(inst, 28, 31); 2022 inst_base->cond = BITS(inst, 28, 31);
2217 inst_base->idx = index; 2023 inst_base->idx = index;
2218 inst_base->br = NON_BRANCH; 2024 inst_base->br = NON_BRANCH;
2219 inst_base->load_r15 = 0; 2025 inst_base->load_r15 = 0;
2220 2026
2221 inst_cream->S = BIT(inst, 20); 2027 inst_cream->S = BIT(inst, 20);
2222 inst_cream->Rn = BITS(inst, 12, 15); 2028 inst_cream->Rn = BITS(inst, 12, 15);
2223 inst_cream->Rd = BITS(inst, 16, 19); 2029 inst_cream->Rd = BITS(inst, 16, 19);
2224 inst_cream->Rs = BITS(inst, 8, 11); 2030 inst_cream->Rs = BITS(inst, 8, 11);
2225 inst_cream->Rm = BITS(inst, 0, 3); 2031 inst_cream->Rm = BITS(inst, 0, 3);
2226 2032
2227 if (CHECK_RM || CHECK_RN || CHECK_RS) 2033 if (CHECK_RM || CHECK_RN || CHECK_RS)
2228 inst_base->load_r15 = 1; 2034 inst_base->load_r15 = 1;
2229 2035
2230 return inst_base; 2036 return inst_base;
2231} 2037}
2232ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index) 2038ARM_INST_PTR INTERPRETER_TRANSLATE(mov)(unsigned int inst, int index)
2233{ 2039{
2234 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst)); 2040 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mov_inst));
2235 mov_inst *inst_cream = (mov_inst *)inst_base->component; 2041 mov_inst *inst_cream = (mov_inst *)inst_base->component;
2236 2042
2237 inst_base->cond = BITS(inst, 28, 31); 2043 inst_base->cond = BITS(inst, 28, 31);
2238 inst_base->idx = index; 2044 inst_base->idx = index;
2239 inst_base->br = NON_BRANCH; 2045 inst_base->br = NON_BRANCH;
2240 2046
2241 inst_cream->I = BIT(inst, 25); 2047 inst_cream->I = BIT(inst, 25);
2242 inst_cream->S = BIT(inst, 20); 2048 inst_cream->S = BIT(inst, 20);
2243 inst_cream->Rd = BITS(inst, 12, 15); 2049 inst_cream->Rd = BITS(inst, 12, 15);
2244 inst_cream->shifter_operand = BITS(inst, 0, 11); 2050 inst_cream->shifter_operand = BITS(inst, 0, 11);
2245 inst_cream->shtop_func = get_shtop(inst); 2051 inst_cream->shtop_func = get_shtop(inst);
2246 2052
2247 if (inst_cream->Rd == 15) { 2053 if (inst_cream->Rd == 15) {
2248 inst_base->br = INDIRECT_BRANCH; 2054 inst_base->br = INDIRECT_BRANCH;
2249 } 2055 }
2250 return inst_base; 2056 return inst_base;
2251} 2057}
2252ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index) 2058ARM_INST_PTR INTERPRETER_TRANSLATE(mrc)(unsigned int inst, int index)
2253{ 2059{
2254 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrc_inst)); 2060 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrc_inst));
2255 mrc_inst *inst_cream = (mrc_inst *)inst_base->component; 2061 mrc_inst *inst_cream = (mrc_inst *)inst_base->component;
2256 inst_base->cond = BITS(inst, 28, 31); 2062 inst_base->cond = BITS(inst, 28, 31);
2257 inst_base->idx = index; 2063 inst_base->idx = index;
2258 inst_base->br = NON_BRANCH; 2064 inst_base->br = NON_BRANCH;
2259 2065
2260 inst_cream->crn = BITS(inst, 16, 19); 2066 inst_cream->crn = BITS(inst, 16, 19);
2261 inst_cream->crm = BITS(inst, 0, 3); 2067 inst_cream->crm = BITS(inst, 0, 3);
2262 inst_cream->opcode_1 = BITS(inst, 21, 23); 2068 inst_cream->opcode_1 = BITS(inst, 21, 23);
2263 inst_cream->opcode_2 = BITS(inst, 5, 7); 2069 inst_cream->opcode_2 = BITS(inst, 5, 7);
2264 inst_cream->Rd = BITS(inst, 12, 15); 2070 inst_cream->Rd = BITS(inst, 12, 15);
2265 inst_cream->cp_num = BITS(inst, 8, 11); 2071 inst_cream->cp_num = BITS(inst, 8, 11);
2266 inst_cream->inst = inst; 2072 inst_cream->inst = inst;
2267 return inst_base; 2073 return inst_base;
2268} 2074}
2269ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("MRRC"); } 2075ARM_INST_PTR INTERPRETER_TRANSLATE(mrrc)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("MRRC"); }
2270ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index) 2076ARM_INST_PTR INTERPRETER_TRANSLATE(mrs)(unsigned int inst, int index)
2271{ 2077{
2272 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst)); 2078 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mrs_inst));
2273 mrs_inst *inst_cream = (mrs_inst *)inst_base->component; 2079 mrs_inst *inst_cream = (mrs_inst *)inst_base->component;
2274 2080
2275 inst_base->cond = BITS(inst, 28, 31); 2081 inst_base->cond = BITS(inst, 28, 31);
2276 inst_base->idx = index; 2082 inst_base->idx = index;
2277 inst_base->br = NON_BRANCH; 2083 inst_base->br = NON_BRANCH;
2278 2084
2279 inst_cream->Rd = BITS(inst, 12, 15); 2085 inst_cream->Rd = BITS(inst, 12, 15);
2280 inst_cream->R = BIT(inst, 22); 2086 inst_cream->R = BIT(inst, 22);
2281 2087
2282 return inst_base; 2088 return inst_base;
2283} 2089}
2284ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index) 2090ARM_INST_PTR INTERPRETER_TRANSLATE(msr)(unsigned int inst, int index)
2285{ 2091{
2286 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(msr_inst)); 2092 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(msr_inst));
2287 msr_inst *inst_cream = (msr_inst *)inst_base->component; 2093 msr_inst *inst_cream = (msr_inst *)inst_base->component;
2288 2094
2289 inst_base->cond = BITS(inst, 28, 31); 2095 inst_base->cond = BITS(inst, 28, 31);
2290 inst_base->idx = index; 2096 inst_base->idx = index;
2291 inst_base->br = NON_BRANCH; 2097 inst_base->br = NON_BRANCH;
2292 2098
2293 inst_cream->field_mask = BITS(inst, 16, 19); 2099 inst_cream->field_mask = BITS(inst, 16, 19);
2294 inst_cream->R = BIT(inst, 22); 2100 inst_cream->R = BIT(inst, 22);
2295 inst_cream->inst = inst; 2101 inst_cream->inst = inst;
2296 2102
2297 return inst_base; 2103 return inst_base;
2298} 2104}
2299ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index) 2105ARM_INST_PTR INTERPRETER_TRANSLATE(mul)(unsigned int inst, int index)
2300{ 2106{
2301 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mul_inst)); 2107 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mul_inst));
2302 mul_inst *inst_cream = (mul_inst *)inst_base->component; 2108 mul_inst *inst_cream = (mul_inst *)inst_base->component;
2303 2109
2304 inst_base->cond = BITS(inst, 28, 31); 2110 inst_base->cond = BITS(inst, 28, 31);
2305 inst_base->idx = index; 2111 inst_base->idx = index;
2306 inst_base->br = NON_BRANCH; 2112 inst_base->br = NON_BRANCH;
2307 inst_base->load_r15 = 0; 2113 inst_base->load_r15 = 0;
2308 2114
2309 inst_cream->S = BIT(inst, 20); 2115 inst_cream->S = BIT(inst, 20);
2310 inst_cream->Rm = BITS(inst, 0, 3); 2116 inst_cream->Rm = BITS(inst, 0, 3);
2311 inst_cream->Rs = BITS(inst, 8, 11); 2117 inst_cream->Rs = BITS(inst, 8, 11);
2312 inst_cream->Rd = BITS(inst, 16, 19); 2118 inst_cream->Rd = BITS(inst, 16, 19);
2313 2119
2314 if (CHECK_RM || CHECK_RS) 2120 if (CHECK_RM || CHECK_RS)
2315 inst_base->load_r15 = 1; 2121 inst_base->load_r15 = 1;
2316 return inst_base; 2122 return inst_base;
2317} 2123}
2318ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index) 2124ARM_INST_PTR INTERPRETER_TRANSLATE(mvn)(unsigned int inst, int index)
2319{ 2125{
2320 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mvn_inst)); 2126 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(mvn_inst));
2321 mvn_inst *inst_cream = (mvn_inst *)inst_base->component; 2127 mvn_inst *inst_cream = (mvn_inst *)inst_base->component;
2322 2128
2323 inst_base->cond = BITS(inst, 28, 31); 2129 inst_base->cond = BITS(inst, 28, 31);
2324 inst_base->idx = index; 2130 inst_base->idx = index;
2325 inst_base->br = NON_BRANCH; 2131 inst_base->br = NON_BRANCH;
2326 2132
2327 inst_cream->I = BIT(inst, 25); 2133 inst_cream->I = BIT(inst, 25);
2328 inst_cream->S = BIT(inst, 20); 2134 inst_cream->S = BIT(inst, 20);
2329 inst_cream->Rd = BITS(inst, 12, 15); 2135 inst_cream->Rd = BITS(inst, 12, 15);
2330 inst_cream->shifter_operand = BITS(inst, 0, 11); 2136 inst_cream->shifter_operand = BITS(inst, 0, 11);
2331 inst_cream->shtop_func = get_shtop(inst); 2137 inst_cream->shtop_func = get_shtop(inst);
2332 2138
2333 if (inst_cream->Rd == 15) { 2139 if (inst_cream->Rd == 15) {
2334 inst_base->br = INDIRECT_BRANCH; 2140 inst_base->br = INDIRECT_BRANCH;
2335 } 2141 }
2336 return inst_base; 2142 return inst_base;
2337 2143
2338} 2144}
2339ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index) 2145ARM_INST_PTR INTERPRETER_TRANSLATE(orr)(unsigned int inst, int index)
2340{ 2146{
2341 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(orr_inst)); 2147 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(orr_inst));
2342 orr_inst *inst_cream = (orr_inst *)inst_base->component; 2148 orr_inst *inst_cream = (orr_inst *)inst_base->component;
2343 2149
2344 inst_base->cond = BITS(inst, 28, 31); 2150 inst_base->cond = BITS(inst, 28, 31);
2345 inst_base->idx = index; 2151 inst_base->idx = index;
2346 inst_base->br = NON_BRANCH; 2152 inst_base->br = NON_BRANCH;
2347 inst_base->load_r15 = 0; 2153 inst_base->load_r15 = 0;
2348 2154
2349 inst_cream->I = BIT(inst, 25); 2155 inst_cream->I = BIT(inst, 25);
2350 inst_cream->S = BIT(inst, 20); 2156 inst_cream->S = BIT(inst, 20);
2351 inst_cream->Rd = BITS(inst, 12, 15); 2157 inst_cream->Rd = BITS(inst, 12, 15);
2352 inst_cream->Rn = BITS(inst, 16, 19); 2158 inst_cream->Rn = BITS(inst, 16, 19);
2353 inst_cream->shifter_operand = BITS(inst, 0, 11); 2159 inst_cream->shifter_operand = BITS(inst, 0, 11);
2354 inst_cream->shtop_func = get_shtop(inst); 2160 inst_cream->shtop_func = get_shtop(inst);
2355 2161
2356 if (CHECK_RN) 2162 if (CHECK_RN)
2357 inst_base->load_r15 = 1; 2163 inst_base->load_r15 = 1;
2358 if (inst_cream->Rd == 15) { 2164 if (inst_cream->Rd == 15) {
2359 inst_base->br = INDIRECT_BRANCH; 2165 inst_base->br = INDIRECT_BRANCH;
2360 } 2166 }
2361 return inst_base; 2167 return inst_base;
2362} 2168}
2363ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("PKHBT"); } 2169
2364ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("PKHTB"); } 2170ARM_INST_PTR INTERPRETER_TRANSLATE(pkhbt)(unsigned int inst, int index)
2171{
2172 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pkh_inst));
2173 pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
2174
2175 inst_base->cond = BITS(inst, 28, 31);
2176 inst_base->idx = index;
2177 inst_base->br = NON_BRANCH;
2178 inst_base->load_r15 = 0;
2179
2180 inst_cream->Rd = BITS(inst, 12, 15);
2181 inst_cream->Rn = BITS(inst, 16, 19);
2182 inst_cream->Rm = BITS(inst, 0, 3);
2183 inst_cream->imm = BITS(inst, 7, 11);
2184
2185 return inst_base;
2186}
2187
2188ARM_INST_PTR INTERPRETER_TRANSLATE(pkhtb)(unsigned int inst, int index)
2189{
2190 return INTERPRETER_TRANSLATE(pkhbt)(inst, index);
2191}
2192
2365ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index) 2193ARM_INST_PTR INTERPRETER_TRANSLATE(pld)(unsigned int inst, int index)
2366{ 2194{
2367 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst)); 2195 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(pld_inst));
2368 2196
2369 inst_base->cond = BITS(inst, 28, 31); 2197 inst_base->cond = BITS(inst, 28, 31);
2370 inst_base->idx = index; 2198 inst_base->idx = index;
2371 inst_base->br = NON_BRANCH; 2199 inst_base->br = NON_BRANCH;
2372 inst_base->load_r15 = 0; 2200 inst_base->load_r15 = 0;
2373 2201
2374 return inst_base; 2202 return inst_base;
2375} 2203}
2376ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD"); } 2204ARM_INST_PTR INTERPRETER_TRANSLATE(qadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD"); }
2377ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD16"); } 2205ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index)
2378ARM_INST_PTR INTERPRETER_TRANSLATE(qadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADD8"); } 2206{
2379ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QADDSUBX"); } 2207 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
2208 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2209
2210 inst_base->cond = BITS(inst, 28, 31);
2211 inst_base->idx = index;
2212 inst_base->br = NON_BRANCH;
2213 inst_base->load_r15 = 0;
2214
2215 inst_cream->Rm = BITS(inst, 0, 3);
2216 inst_cream->Rn = BITS(inst, 16, 19);
2217 inst_cream->Rd = BITS(inst, 12, 15);
2218 inst_cream->op1 = BITS(inst, 20, 21);
2219 inst_cream->op2 = BITS(inst, 5, 7);
2220
2221 return inst_base;
2222}
2223ARM_INST_PTR INTERPRETER_TRANSLATE(qadd16)(unsigned int inst, int index)
2224{
2225 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2226}
2227ARM_INST_PTR INTERPRETER_TRANSLATE(qaddsubx)(unsigned int inst, int index)
2228{
2229 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2230}
2380ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDADD"); } 2231ARM_INST_PTR INTERPRETER_TRANSLATE(qdadd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDADD"); }
2381ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDSUB"); } 2232ARM_INST_PTR INTERPRETER_TRANSLATE(qdsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QDSUB"); }
2382ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB"); } 2233ARM_INST_PTR INTERPRETER_TRANSLATE(qsub)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB"); }
2383ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB16"); } 2234ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index)
2384ARM_INST_PTR INTERPRETER_TRANSLATE(qsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUB8"); } 2235{
2385ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("QSUBADDX"); } 2236 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2237}
2238ARM_INST_PTR INTERPRETER_TRANSLATE(qsub16)(unsigned int inst, int index)
2239{
2240 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2241}
2242ARM_INST_PTR INTERPRETER_TRANSLATE(qsubaddx)(unsigned int inst, int index)
2243{
2244 return INTERPRETER_TRANSLATE(qadd8)(inst, index);
2245}
2386ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index) 2246ARM_INST_PTR INTERPRETER_TRANSLATE(rev)(unsigned int inst, int index)
2387{ 2247{
2388 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst)); 2248 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst));
2389 rev_inst *inst_cream = (rev_inst *)inst_base->component; 2249 rev_inst *inst_cream = (rev_inst *)inst_base->component;
2390 2250
2391 inst_base->cond = BITS(inst, 28, 31); 2251 inst_base->cond = BITS(inst, 28, 31);
2392 inst_base->idx = index; 2252 inst_base->idx = index;
2393 inst_base->br = NON_BRANCH; 2253 inst_base->br = NON_BRANCH;
2394 inst_base->load_r15 = 0; 2254 inst_base->load_r15 = 0;
2395 2255
2396 inst_cream->Rm = BITS(inst, 0, 3); 2256 inst_cream->Rm = BITS(inst, 0, 3);
2397 inst_cream->Rd = BITS(inst, 12, 15); 2257 inst_cream->Rd = BITS(inst, 12, 15);
2398 2258
2399 return inst_base; 2259 return inst_base;
2400} 2260}
2401ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index){ 2261ARM_INST_PTR INTERPRETER_TRANSLATE(rev16)(unsigned int inst, int index){
2402 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst)); 2262 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rev_inst));
2403 rev_inst *inst_cream = (rev_inst *)inst_base->component; 2263 rev_inst *inst_cream = (rev_inst *)inst_base->component;
2404 2264
2405 inst_base->cond = BITS(inst, 28, 31); 2265 inst_base->cond = BITS(inst, 28, 31);
2406 inst_base->idx = index; 2266 inst_base->idx = index;
2407 inst_base->br = NON_BRANCH; 2267 inst_base->br = NON_BRANCH;
2408 inst_base->load_r15 = 0; 2268 inst_base->load_r15 = 0;
2409 2269
2410 inst_cream->Rm = BITS(inst, 0, 3); 2270 inst_cream->Rm = BITS(inst, 0, 3);
2411 inst_cream->Rd = BITS(inst, 12, 15); 2271 inst_cream->Rd = BITS(inst, 12, 15);
2412 2272
2413 return inst_base; 2273 return inst_base;
2414} 2274}
2415ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("REVSH"); } 2275ARM_INST_PTR INTERPRETER_TRANSLATE(revsh)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("REVSH"); }
2416ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("RFE"); } 2276ARM_INST_PTR INTERPRETER_TRANSLATE(rfe)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("RFE"); }
2417ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index) 2277ARM_INST_PTR INTERPRETER_TRANSLATE(rsb)(unsigned int inst, int index)
2418{ 2278{
2419 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsb_inst)); 2279 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsb_inst));
2420 rsb_inst *inst_cream = (rsb_inst *)inst_base->component; 2280 rsb_inst *inst_cream = (rsb_inst *)inst_base->component;
2421 2281
2422 inst_base->cond = BITS(inst, 28, 31); 2282 inst_base->cond = BITS(inst, 28, 31);
2423 inst_base->idx = index; 2283 inst_base->idx = index;
2424 inst_base->br = NON_BRANCH; 2284 inst_base->br = NON_BRANCH;
2425 inst_base->load_r15 = 0; 2285 inst_base->load_r15 = 0;
2426 2286
2427 inst_cream->I = BIT(inst, 25); 2287 inst_cream->I = BIT(inst, 25);
2428 inst_cream->S = BIT(inst, 20); 2288 inst_cream->S = BIT(inst, 20);
2429 inst_cream->Rn = BITS(inst, 16, 19); 2289 inst_cream->Rn = BITS(inst, 16, 19);
2430 inst_cream->Rd = BITS(inst, 12, 15); 2290 inst_cream->Rd = BITS(inst, 12, 15);
2431 inst_cream->shifter_operand = BITS(inst, 0, 11); 2291 inst_cream->shifter_operand = BITS(inst, 0, 11);
2432 inst_cream->shtop_func = get_shtop(inst); 2292 inst_cream->shtop_func = get_shtop(inst);
2433 if (CHECK_RN) 2293 if (CHECK_RN)
2434 inst_base->load_r15 = 1; 2294 inst_base->load_r15 = 1;
2435 2295
2436 if (inst_cream->Rd == 15) { 2296 if (inst_cream->Rd == 15) {
2437 inst_base->br = INDIRECT_BRANCH; 2297 inst_base->br = INDIRECT_BRANCH;
2438 } 2298 }
2439 return inst_base; 2299 return inst_base;
2440} 2300}
2441ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index) 2301ARM_INST_PTR INTERPRETER_TRANSLATE(rsc)(unsigned int inst, int index)
2442{ 2302{
2443 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsc_inst)); 2303 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(rsc_inst));
2444 rsc_inst *inst_cream = (rsc_inst *)inst_base->component; 2304 rsc_inst *inst_cream = (rsc_inst *)inst_base->component;
2445 2305
2446 inst_base->cond = BITS(inst, 28, 31); 2306 inst_base->cond = BITS(inst, 28, 31);
2447 inst_base->idx = index; 2307 inst_base->idx = index;
2448 inst_base->br = NON_BRANCH; 2308 inst_base->br = NON_BRANCH;
2449 inst_base->load_r15 = 0; 2309 inst_base->load_r15 = 0;
2450 2310
2451 inst_cream->I = BIT(inst, 25); 2311 inst_cream->I = BIT(inst, 25);
2452 inst_cream->S = BIT(inst, 20); 2312 inst_cream->S = BIT(inst, 20);
2453 inst_cream->Rn = BITS(inst, 16, 19); 2313 inst_cream->Rn = BITS(inst, 16, 19);
2454 inst_cream->Rd = BITS(inst, 12, 15); 2314 inst_cream->Rd = BITS(inst, 12, 15);
2455 inst_cream->shifter_operand = BITS(inst, 0, 11); 2315 inst_cream->shifter_operand = BITS(inst, 0, 11);
2456 inst_cream->shtop_func = get_shtop(inst); 2316 inst_cream->shtop_func = get_shtop(inst);
2457 if (CHECK_RN) 2317 if (CHECK_RN)
2458 inst_base->load_r15 = 1; 2318 inst_base->load_r15 = 1;
2459 2319
2460 if (inst_cream->Rd == 15) { 2320 if (inst_cream->Rd == 15) {
2461 inst_base->br = INDIRECT_BRANCH; 2321 inst_base->br = INDIRECT_BRANCH;
2462 } 2322 }
2463 return inst_base; 2323 return inst_base;
2464} 2324}
2465ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SADD16"); }
2466ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SADD8"); } 2325ARM_INST_PTR INTERPRETER_TRANSLATE(sadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SADD8"); }
2467ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SADDSUBX"); } 2326ARM_INST_PTR INTERPRETER_TRANSLATE(sadd16)(unsigned int inst, int index)
2327{
2328 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
2329 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2330
2331 inst_base->cond = BITS(inst, 28, 31);
2332 inst_base->idx = index;
2333 inst_base->br = NON_BRANCH;
2334 inst_base->load_r15 = 0;
2335
2336 inst_cream->Rm = BITS(inst, 0, 3);
2337 inst_cream->Rn = BITS(inst, 16, 19);
2338 inst_cream->Rd = BITS(inst, 12, 15);
2339 inst_cream->op1 = BITS(inst, 20, 21);
2340 inst_cream->op2 = BITS(inst, 5, 7);
2341
2342 return inst_base;
2343}
2344ARM_INST_PTR INTERPRETER_TRANSLATE(saddsubx)(unsigned int inst, int index)
2345{
2346 return INTERPRETER_TRANSLATE(sadd16)(inst, index);
2347}
2468ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index) 2348ARM_INST_PTR INTERPRETER_TRANSLATE(sbc)(unsigned int inst, int index)
2469{ 2349{
2470 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sbc_inst)); 2350 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sbc_inst));
2471 sbc_inst *inst_cream = (sbc_inst *)inst_base->component; 2351 sbc_inst *inst_cream = (sbc_inst *)inst_base->component;
2472 2352
2473 inst_base->cond = BITS(inst, 28, 31); 2353 inst_base->cond = BITS(inst, 28, 31);
2474 inst_base->idx = index; 2354 inst_base->idx = index;
2475 inst_base->br = NON_BRANCH; 2355 inst_base->br = NON_BRANCH;
2476 inst_base->load_r15 = 0; 2356 inst_base->load_r15 = 0;
2477 2357
2478 inst_cream->I = BIT(inst, 25); 2358 inst_cream->I = BIT(inst, 25);
2479 inst_cream->S = BIT(inst, 20); 2359 inst_cream->S = BIT(inst, 20);
2480 inst_cream->Rn = BITS(inst, 16, 19); 2360 inst_cream->Rn = BITS(inst, 16, 19);
2481 inst_cream->Rd = BITS(inst, 12, 15); 2361 inst_cream->Rd = BITS(inst, 12, 15);
2482 inst_cream->shifter_operand = BITS(inst, 0, 11); 2362 inst_cream->shifter_operand = BITS(inst, 0, 11);
2483 inst_cream->shtop_func = get_shtop(inst); 2363 inst_cream->shtop_func = get_shtop(inst);
2484 if (CHECK_RN) 2364 if (CHECK_RN)
2485 inst_base->load_r15 = 1; 2365 inst_base->load_r15 = 1;
2486 2366
2487 if (inst_cream->Rd == 15) { 2367 if (inst_cream->Rd == 15) {
2488 inst_base->br = INDIRECT_BRANCH; 2368 inst_base->br = INDIRECT_BRANCH;
2489 } 2369 }
2490 return inst_base; 2370 return inst_base;
2491} 2371}
2492ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SEL"); } 2372ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index)
2373{
2374 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
2375 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
2376
2377 inst_base->cond = BITS(inst, 28, 31);
2378 inst_base->idx = index;
2379 inst_base->br = NON_BRANCH;
2380 inst_base->load_r15 = 0;
2381
2382 inst_cream->Rm = BITS(inst, 0, 3);
2383 inst_cream->Rn = BITS(inst, 16, 19);
2384 inst_cream->Rd = BITS(inst, 12, 15);
2385 inst_cream->op1 = BITS(inst, 20, 22);
2386 inst_cream->op2 = BITS(inst, 5, 7);
2387
2388 return inst_base;
2389}
2493ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SETEND"); } 2390ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SETEND"); }
2494ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SHADD16"); } 2391ARM_INST_PTR INTERPRETER_TRANSLATE(shadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SHADD16"); }
2495ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SHADD8"); } 2392ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SHADD8"); }
@@ -2499,61 +2396,61 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(shsub8)(unsigned int inst, int index) { UN
2499ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SHSUBADDX"); } 2396ARM_INST_PTR INTERPRETER_TRANSLATE(shsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SHSUBADDX"); }
2500ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index) 2397ARM_INST_PTR INTERPRETER_TRANSLATE(smla)(unsigned int inst, int index)
2501{ 2398{
2502 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst)); 2399 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smla_inst));
2503 smla_inst *inst_cream = (smla_inst *)inst_base->component; 2400 smla_inst *inst_cream = (smla_inst *)inst_base->component;
2504 2401
2505 inst_base->cond = BITS(inst, 28, 31); 2402 inst_base->cond = BITS(inst, 28, 31);
2506 inst_base->idx = index; 2403 inst_base->idx = index;
2507 inst_base->br = NON_BRANCH; 2404 inst_base->br = NON_BRANCH;
2508 inst_base->load_r15 = 0; 2405 inst_base->load_r15 = 0;
2509 2406
2510 inst_cream->x = BIT(inst, 5); 2407 inst_cream->x = BIT(inst, 5);
2511 inst_cream->y = BIT(inst, 6); 2408 inst_cream->y = BIT(inst, 6);
2512 inst_cream->Rm = BITS(inst, 0, 3); 2409 inst_cream->Rm = BITS(inst, 0, 3);
2513 inst_cream->Rs = BITS(inst, 8, 11); 2410 inst_cream->Rs = BITS(inst, 8, 11);
2514 inst_cream->Rd = BITS(inst, 16, 19); 2411 inst_cream->Rd = BITS(inst, 16, 19);
2515 inst_cream->Rn = BITS(inst, 12, 15); 2412 inst_cream->Rn = BITS(inst, 12, 15);
2516 2413
2517 return inst_base; 2414 return inst_base;
2518} 2415}
2519ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(unsigned int inst, int index){ 2416ARM_INST_PTR INTERPRETER_TRANSLATE(smlad)(unsigned int inst, int index){
2520 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); 2417 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
2521 smlad_inst *inst_cream = (smlad_inst *)inst_base->component; 2418 smlad_inst *inst_cream = (smlad_inst *)inst_base->component;
2522 2419
2523 inst_base->cond = BITS(inst, 28, 31); 2420 inst_base->cond = BITS(inst, 28, 31);
2524 inst_base->idx = index; 2421 inst_base->idx = index;
2525 inst_base->br = NON_BRANCH; 2422 inst_base->br = NON_BRANCH;
2526 inst_base->load_r15 = 0; 2423 inst_base->load_r15 = 0;
2527 2424
2528 inst_cream->m = BIT(inst, 4); 2425 inst_cream->m = BIT(inst, 4);
2529 inst_cream->Rn = BITS(inst, 0, 3); 2426 inst_cream->Rn = BITS(inst, 0, 3);
2530 inst_cream->Rm = BITS(inst, 8, 11); 2427 inst_cream->Rm = BITS(inst, 8, 11);
2531 inst_cream->Rd = BITS(inst, 16, 19); 2428 inst_cream->Rd = BITS(inst, 16, 19);
2532 inst_cream->Ra = BITS(inst, 12, 15); 2429 inst_cream->Ra = BITS(inst, 12, 15);
2533 2430
2534 if (CHECK_RM ) 2431 if (CHECK_RM )
2535 inst_base->load_r15 = 1; 2432 inst_base->load_r15 = 1;
2536 return inst_base; 2433 return inst_base;
2537} 2434}
2538ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index) 2435ARM_INST_PTR INTERPRETER_TRANSLATE(smlal)(unsigned int inst, int index)
2539{ 2436{
2540 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); 2437 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst));
2541 umlal_inst *inst_cream = (umlal_inst *)inst_base->component; 2438 umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
2542 2439
2543 inst_base->cond = BITS(inst, 28, 31); 2440 inst_base->cond = BITS(inst, 28, 31);
2544 inst_base->idx = index; 2441 inst_base->idx = index;
2545 inst_base->br = NON_BRANCH; 2442 inst_base->br = NON_BRANCH;
2546 inst_base->load_r15 = 0; 2443 inst_base->load_r15 = 0;
2547 2444
2548 inst_cream->S = BIT(inst, 20); 2445 inst_cream->S = BIT(inst, 20);
2549 inst_cream->Rm = BITS(inst, 0, 3); 2446 inst_cream->Rm = BITS(inst, 0, 3);
2550 inst_cream->Rs = BITS(inst, 8, 11); 2447 inst_cream->Rs = BITS(inst, 8, 11);
2551 inst_cream->RdHi = BITS(inst, 16, 19); 2448 inst_cream->RdHi = BITS(inst, 16, 19);
2552 inst_cream->RdLo = BITS(inst, 12, 15); 2449 inst_cream->RdLo = BITS(inst, 12, 15);
2553 2450
2554 if (CHECK_RM || CHECK_RS) 2451 if (CHECK_RM || CHECK_RS)
2555 inst_base->load_r15 = 1; 2452 inst_base->load_r15 = 1;
2556 return inst_base; 2453 return inst_base;
2557} 2454}
2558ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLALXY"); } 2455ARM_INST_PTR INTERPRETER_TRANSLATE(smlalxy)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLALXY"); }
2559ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLALD"); } 2456ARM_INST_PTR INTERPRETER_TRANSLATE(smlald)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMLALD"); }
@@ -2566,572 +2463,700 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(smmul)(unsigned int inst, int index) { UNIM
2566ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMUAD"); } 2463ARM_INST_PTR INTERPRETER_TRANSLATE(smuad)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMUAD"); }
2567ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index) 2464ARM_INST_PTR INTERPRETER_TRANSLATE(smul)(unsigned int inst, int index)
2568{ 2465{
2569 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smul_inst)); 2466 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smul_inst));
2570 smul_inst *inst_cream = (smul_inst *)inst_base->component; 2467 smul_inst *inst_cream = (smul_inst *)inst_base->component;
2571 2468
2572 inst_base->cond = BITS(inst, 28, 31); 2469 inst_base->cond = BITS(inst, 28, 31);
2573 inst_base->idx = index; 2470 inst_base->idx = index;
2574 inst_base->br = NON_BRANCH; 2471 inst_base->br = NON_BRANCH;
2575 inst_base->load_r15 = 0; 2472 inst_base->load_r15 = 0;
2576 2473
2577 inst_cream->Rd = BITS(inst, 16, 19); 2474 inst_cream->Rd = BITS(inst, 16, 19);
2578 inst_cream->Rs = BITS(inst, 8, 11); 2475 inst_cream->Rs = BITS(inst, 8, 11);
2579 inst_cream->Rm = BITS(inst, 0, 3); 2476 inst_cream->Rm = BITS(inst, 0, 3);
2580 2477
2581 inst_cream->x = BIT(inst, 5); 2478 inst_cream->x = BIT(inst, 5);
2582 inst_cream->y = BIT(inst, 6); 2479 inst_cream->y = BIT(inst, 6);
2583 2480
2584 if (CHECK_RM || CHECK_RS) 2481 if (CHECK_RM || CHECK_RS)
2585 inst_base->load_r15 = 1; 2482 inst_base->load_r15 = 1;
2586 return inst_base; 2483 return inst_base;
2587 2484
2588} 2485}
2589ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index) 2486ARM_INST_PTR INTERPRETER_TRANSLATE(smull)(unsigned int inst, int index)
2590{ 2487{
2591 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst)); 2488 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst));
2592 umull_inst *inst_cream = (umull_inst *)inst_base->component; 2489 umull_inst *inst_cream = (umull_inst *)inst_base->component;
2593 2490
2594 inst_base->cond = BITS(inst, 28, 31); 2491 inst_base->cond = BITS(inst, 28, 31);
2595 inst_base->idx = index; 2492 inst_base->idx = index;
2596 inst_base->br = NON_BRANCH; 2493 inst_base->br = NON_BRANCH;
2597 inst_base->load_r15 = 0; 2494 inst_base->load_r15 = 0;
2598 2495
2599 inst_cream->S = BIT(inst, 20); 2496 inst_cream->S = BIT(inst, 20);
2600 inst_cream->Rm = BITS(inst, 0, 3); 2497 inst_cream->Rm = BITS(inst, 0, 3);
2601 inst_cream->Rs = BITS(inst, 8, 11); 2498 inst_cream->Rs = BITS(inst, 8, 11);
2602 inst_cream->RdHi = BITS(inst, 16, 19); 2499 inst_cream->RdHi = BITS(inst, 16, 19);
2603 inst_cream->RdLo = BITS(inst, 12, 15); 2500 inst_cream->RdLo = BITS(inst, 12, 15);
2604 2501
2605 if (CHECK_RM || CHECK_RS) 2502 if (CHECK_RM || CHECK_RS)
2606 inst_base->load_r15 = 1; 2503 inst_base->load_r15 = 1;
2607 return inst_base; 2504 return inst_base;
2608} 2505}
2609 2506
2610ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index) 2507ARM_INST_PTR INTERPRETER_TRANSLATE(smulw)(unsigned int inst, int index)
2611{ 2508{
2612 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst)); 2509 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(smlad_inst));
2613 smlad_inst *inst_cream = (smlad_inst *)inst_base->component; 2510 smlad_inst *inst_cream = (smlad_inst *)inst_base->component;
2614 2511
2615 inst_base->cond = BITS(inst, 28, 31); 2512 inst_base->cond = BITS(inst, 28, 31);
2616 inst_base->idx = index; 2513 inst_base->idx = index;
2617 inst_base->br = NON_BRANCH; 2514 inst_base->br = NON_BRANCH;
2618 inst_base->load_r15 = 0; 2515 inst_base->load_r15 = 0;
2619 2516
2620 inst_cream->m = BIT(inst, 6); 2517 inst_cream->m = BIT(inst, 6);
2621 inst_cream->Rm = BITS(inst, 8, 11); 2518 inst_cream->Rm = BITS(inst, 8, 11);
2622 inst_cream->Rn = BITS(inst, 0, 3); 2519 inst_cream->Rn = BITS(inst, 0, 3);
2623 inst_cream->Rd = BITS(inst, 16, 19); 2520 inst_cream->Rd = BITS(inst, 16, 19);
2624 2521
2625 if (CHECK_RM || CHECK_RN) 2522 if (CHECK_RM || CHECK_RN)
2626 inst_base->load_r15 = 1; 2523 inst_base->load_r15 = 1;
2627 return inst_base; 2524 return inst_base;
2628} 2525}
2629ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMUSD"); } 2526ARM_INST_PTR INTERPRETER_TRANSLATE(smusd)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SMUSD"); }
2630ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SRS"); } 2527ARM_INST_PTR INTERPRETER_TRANSLATE(srs)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SRS"); }
2631ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SSAT"); } 2528ARM_INST_PTR INTERPRETER_TRANSLATE(ssat)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SSAT"); }
2632ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SSAT16"); } 2529ARM_INST_PTR INTERPRETER_TRANSLATE(ssat16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SSAT16"); }
2633ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SSUB16"); }
2634ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SSUB8"); } 2530ARM_INST_PTR INTERPRETER_TRANSLATE(ssub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SSUB8"); }
2635ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SSUBADDX"); } 2531ARM_INST_PTR INTERPRETER_TRANSLATE(ssub16)(unsigned int inst, int index)
2532{
2533 return INTERPRETER_TRANSLATE(sadd16)(inst, index);
2534}
2535ARM_INST_PTR INTERPRETER_TRANSLATE(ssubaddx)(unsigned int inst, int index)
2536{
2537 return INTERPRETER_TRANSLATE(sadd16)(inst, index);
2538}
2636ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index) 2539ARM_INST_PTR INTERPRETER_TRANSLATE(stc)(unsigned int inst, int index)
2637{ 2540{
2638 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(stc_inst)); 2541 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(stc_inst));
2639 inst_base->cond = BITS(inst, 28, 31); 2542 inst_base->cond = BITS(inst, 28, 31);
2640 inst_base->idx = index; 2543 inst_base->idx = index;
2641 inst_base->br = NON_BRANCH; 2544 inst_base->br = NON_BRANCH;
2642 2545
2643 return inst_base; 2546 return inst_base;
2644} 2547}
2645ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index) 2548ARM_INST_PTR INTERPRETER_TRANSLATE(stm)(unsigned int inst, int index)
2646{ 2549{
2647 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 2550 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2648 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2551 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2649 2552
2650 inst_base->cond = BITS(inst, 28, 31); 2553 inst_base->cond = BITS(inst, 28, 31);
2651 inst_base->idx = index; 2554 inst_base->idx = index;
2652 inst_base->br = NON_BRANCH; 2555 inst_base->br = NON_BRANCH;
2653 2556
2654 inst_cream->inst = inst; 2557 inst_cream->inst = inst;
2655 inst_cream->get_addr = get_calc_addr_op(inst); 2558 inst_cream->get_addr = get_calc_addr_op(inst);
2656 return inst_base; 2559 return inst_base;
2657} 2560}
2658ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index) 2561ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb)(unsigned int inst, int index)
2659{ 2562{
2660 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst)); 2563 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtb_inst));
2661 sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component; 2564 sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component;
2662 2565
2663 inst_base->cond = BITS(inst, 28, 31); 2566 inst_base->cond = BITS(inst, 28, 31);
2664 inst_base->idx = index; 2567 inst_base->idx = index;
2665 inst_base->br = NON_BRANCH; 2568 inst_base->br = NON_BRANCH;
2666 inst_base->load_r15 = 0; 2569 inst_base->load_r15 = 0;
2667 2570
2668 inst_cream->Rd = BITS(inst, 12, 15); 2571 inst_cream->Rd = BITS(inst, 12, 15);
2669 inst_cream->Rm = BITS(inst, 0, 3); 2572 inst_cream->Rm = BITS(inst, 0, 3);
2670 inst_cream->rotate = BITS(inst, 10, 11); 2573 inst_cream->rotate = BITS(inst, 10, 11);
2671 2574
2672 if (CHECK_RM) 2575 if (CHECK_RM)
2673 inst_base->load_r15 = 1; 2576 inst_base->load_r15 = 1;
2674 return inst_base; 2577 return inst_base;
2675} 2578}
2676ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index) 2579ARM_INST_PTR INTERPRETER_TRANSLATE(str)(unsigned int inst, int index)
2677{ 2580{
2678 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 2581 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2679 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2582 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2680 2583
2681 inst_base->cond = BITS(inst, 28, 31); 2584 inst_base->cond = BITS(inst, 28, 31);
2682 inst_base->idx = index; 2585 inst_base->idx = index;
2683 inst_base->br = NON_BRANCH; 2586 inst_base->br = NON_BRANCH;
2684 2587
2685 inst_cream->inst = inst; 2588 inst_cream->inst = inst;
2686 inst_cream->get_addr = get_calc_addr_op(inst); 2589 inst_cream->get_addr = get_calc_addr_op(inst);
2687 2590
2688 if (BITS(inst, 12, 15) == 15) { 2591 if (BITS(inst, 12, 15) == 15) {
2689 inst_base->br = INDIRECT_BRANCH; 2592 inst_base->br = INDIRECT_BRANCH;
2690 } 2593 }
2691 return inst_base; 2594 return inst_base;
2692} 2595}
2693ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index) 2596ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb)(unsigned int inst, int index)
2694{ 2597{
2695 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst)); 2598 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxth_inst));
2696 uxth_inst *inst_cream = (uxth_inst *)inst_base->component; 2599 uxth_inst *inst_cream = (uxth_inst *)inst_base->component;
2697 2600
2698 inst_base->cond = BITS(inst, 28, 31); 2601 inst_base->cond = BITS(inst, 28, 31);
2699 inst_base->idx = index; 2602 inst_base->idx = index;
2700 inst_base->br = NON_BRANCH; 2603 inst_base->br = NON_BRANCH;
2701 inst_base->load_r15 = 0; 2604 inst_base->load_r15 = 0;
2702 2605
2703 inst_cream->Rd = BITS(inst, 12, 15); 2606 inst_cream->Rd = BITS(inst, 12, 15);
2704 inst_cream->rotate = BITS(inst, 10, 11); 2607 inst_cream->rotate = BITS(inst, 10, 11);
2705 inst_cream->Rm = BITS(inst, 0, 3); 2608 inst_cream->Rm = BITS(inst, 0, 3);
2706 2609
2707 if (CHECK_RM) 2610 if (CHECK_RM)
2708 inst_base->load_r15 = 1; 2611 inst_base->load_r15 = 1;
2709 return inst_base; 2612 return inst_base;
2710} 2613}
2711ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index) 2614ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab)(unsigned int inst, int index)
2712{ 2615{
2713 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst)); 2616 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst));
2714 uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component; 2617 uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component;
2715 2618
2716 inst_base->cond = BITS(inst, 28, 31); 2619 inst_base->cond = BITS(inst, 28, 31);
2717 inst_base->idx = index; 2620 inst_base->idx = index;
2718 inst_base->br = NON_BRANCH; 2621 inst_base->br = NON_BRANCH;
2719 inst_base->load_r15 = 0; 2622 inst_base->load_r15 = 0;
2720 2623
2721 inst_cream->Rd = BITS(inst, 12, 15); 2624 inst_cream->Rd = BITS(inst, 12, 15);
2722 inst_cream->rotate = BITS(inst, 10, 11); 2625 inst_cream->rotate = BITS(inst, 10, 11);
2723 inst_cream->Rm = BITS(inst, 0, 3); 2626 inst_cream->Rm = BITS(inst, 0, 3);
2724 inst_cream->Rn = BITS(inst, 16, 19); 2627 inst_cream->Rn = BITS(inst, 16, 19);
2725 2628
2726 return inst_base; 2629 return inst_base;
2727} 2630}
2728ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index) 2631ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index)
2729{ 2632{
2730 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 2633 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2731 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2634 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2732 2635
2733 inst_base->cond = BITS(inst, 28, 31); 2636 inst_base->cond = BITS(inst, 28, 31);
2734 inst_base->idx = index; 2637 inst_base->idx = index;
2735 inst_base->br = NON_BRANCH; 2638 inst_base->br = NON_BRANCH;
2736 2639
2737 inst_cream->inst = inst; 2640 inst_cream->inst = inst;
2738 inst_cream->get_addr = get_calc_addr_op(inst); 2641 inst_cream->get_addr = get_calc_addr_op(inst);
2739 2642
2740 if (BITS(inst, 12, 15) == 15) { 2643 if (BITS(inst, 12, 15) == 15) {
2741 inst_base->br = INDIRECT_BRANCH; 2644 inst_base->br = INDIRECT_BRANCH;
2742 } 2645 }
2743 return inst_base; 2646 return inst_base;
2744} 2647}
2745ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index) 2648ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index)
2746{ 2649{
2747 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 2650 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2748 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2651 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2749 2652
2750 inst_base->cond = BITS(inst, 28, 31); 2653 inst_base->cond = BITS(inst, 28, 31);
2751 inst_base->idx = index; 2654 inst_base->idx = index;
2752 inst_base->br = NON_BRANCH; 2655 inst_base->br = NON_BRANCH;
2753 2656
2754 inst_cream->inst = inst; 2657 inst_cream->inst = inst;
2755// inst_cream->get_addr = get_calc_addr_op(inst); 2658// inst_cream->get_addr = get_calc_addr_op(inst);
2756 if (I_BIT == 0) { 2659 if (I_BIT == 0) {
2757 inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); 2660 inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
2758 } else { 2661 } else {
2759 DEBUG_MSG; 2662 DEBUG_MSG;
2760 } 2663 }
2761 2664
2762 if (BITS(inst, 12, 15) == 15) { 2665 if (BITS(inst, 12, 15) == 15) {
2763 inst_base->br = INDIRECT_BRANCH; 2666 inst_base->br = INDIRECT_BRANCH;
2764 } 2667 }
2765 return inst_base; 2668 return inst_base;
2766} 2669}
2767ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){ 2670ARM_INST_PTR INTERPRETER_TRANSLATE(strd)(unsigned int inst, int index){
2768 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 2671 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2769 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2672 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2770 2673
2771 inst_base->cond = BITS(inst, 28, 31); 2674 inst_base->cond = BITS(inst, 28, 31);
2772 inst_base->idx = index; 2675 inst_base->idx = index;
2773 inst_base->br = NON_BRANCH; 2676 inst_base->br = NON_BRANCH;
2774 2677
2775 inst_cream->inst = inst; 2678 inst_cream->inst = inst;
2776 inst_cream->get_addr = get_calc_addr_op(inst); 2679 inst_cream->get_addr = get_calc_addr_op(inst);
2777 2680
2778 if (BITS(inst, 12, 15) == 15) { 2681 if (BITS(inst, 12, 15) == 15) {
2779 inst_base->br = INDIRECT_BRANCH; 2682 inst_base->br = INDIRECT_BRANCH;
2780 } 2683 }
2781 return inst_base; 2684 return inst_base;
2782} 2685}
2783ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index) 2686ARM_INST_PTR INTERPRETER_TRANSLATE(strex)(unsigned int inst, int index)
2784{ 2687{
2785 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 2688 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2786 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2689 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2787 2690
2788 inst_base->cond = BITS(inst, 28, 31); 2691 inst_base->cond = BITS(inst, 28, 31);
2789 inst_base->idx = index; 2692 inst_base->idx = index;
2790 inst_base->br = NON_BRANCH; 2693 inst_base->br = NON_BRANCH;
2791 2694
2792 inst_cream->inst = inst; 2695 inst_cream->inst = inst;
2793 inst_cream->get_addr = get_calc_addr_op(inst); 2696 inst_cream->get_addr = get_calc_addr_op(inst);
2794 2697
2795 if (BITS(inst, 12, 15) == 15) { 2698 if (BITS(inst, 12, 15) == 15) {
2796 inst_base->br = INDIRECT_BRANCH; 2699 inst_base->br = INDIRECT_BRANCH;
2797 } 2700 }
2798 return inst_base; 2701 return inst_base;
2799} 2702}
2800ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index) 2703ARM_INST_PTR INTERPRETER_TRANSLATE(strexb)(unsigned int inst, int index)
2801{ 2704{
2802 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 2705 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2803 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2706 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2804 2707
2805 inst_base->cond = BITS(inst, 28, 31); 2708 inst_base->cond = BITS(inst, 28, 31);
2806 inst_base->idx = index; 2709 inst_base->idx = index;
2807 inst_base->br = NON_BRANCH; 2710 inst_base->br = NON_BRANCH;
2808 2711
2809 inst_cream->inst = inst; 2712 inst_cream->inst = inst;
2810 inst_cream->get_addr = get_calc_addr_op(inst); 2713 inst_cream->get_addr = get_calc_addr_op(inst);
2811 2714
2812 if (BITS(inst, 12, 15) == 15) { 2715 if (BITS(inst, 12, 15) == 15) {
2813 inst_base->br = INDIRECT_BRANCH; 2716 inst_base->br = INDIRECT_BRANCH;
2814 } 2717 }
2815 return inst_base; 2718 return inst_base;
2816} 2719}
2817ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) 2720ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index)
2818{ 2721{
2819 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 2722 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2820 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2723 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2821 2724
2822 inst_base->cond = BITS(inst, 28, 31); 2725 inst_base->cond = BITS(inst, 28, 31);
2823 inst_base->idx = index; 2726 inst_base->idx = index;
2824 inst_base->br = NON_BRANCH; 2727 inst_base->br = NON_BRANCH;
2825 2728
2826 inst_cream->inst = inst; 2729 inst_cream->inst = inst;
2827 inst_cream->get_addr = get_calc_addr_op(inst); 2730 inst_cream->get_addr = get_calc_addr_op(inst);
2828 2731
2829 if (BITS(inst, 12, 15) == 15) { 2732 if (BITS(inst, 12, 15) == 15) {
2830 inst_base->br = INDIRECT_BRANCH; 2733 inst_base->br = INDIRECT_BRANCH;
2831 } 2734 }
2832 return inst_base; 2735 return inst_base;
2833} 2736}
2834ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index) 2737ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index)
2835{ 2738{
2836 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); 2739 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst));
2837 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 2740 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
2838 2741
2839 inst_base->cond = BITS(inst, 28, 31); 2742 inst_base->cond = BITS(inst, 28, 31);
2840 inst_base->idx = index; 2743 inst_base->idx = index;
2841 inst_base->br = NON_BRANCH; 2744 inst_base->br = NON_BRANCH;
2842 2745
2843 inst_cream->inst = inst; 2746 inst_cream->inst = inst;
2844 if (I_BIT == 0) { 2747 if (I_BIT == 0) {
2845 inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); 2748 inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed);
2846 } else { 2749 } else {
2847 DEBUG_MSG; 2750 DEBUG_MSG;
2848 } 2751 }
2849 2752
2850 if (BITS(inst, 12, 15) == 15) { 2753 if (BITS(inst, 12, 15) == 15) {
2851 inst_base->br = INDIRECT_BRANCH; 2754 inst_base->br = INDIRECT_BRANCH;
2852 } 2755 }
2853 return inst_base; 2756 return inst_base;
2854} 2757}
2855ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index) 2758ARM_INST_PTR INTERPRETER_TRANSLATE(sub)(unsigned int inst, int index)
2856{ 2759{
2857 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sub_inst)); 2760 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sub_inst));
2858 sub_inst *inst_cream = (sub_inst *)inst_base->component; 2761 sub_inst *inst_cream = (sub_inst *)inst_base->component;
2859 2762
2860 inst_base->cond = BITS(inst, 28, 31); 2763 inst_base->cond = BITS(inst, 28, 31);
2861 inst_base->idx = index; 2764 inst_base->idx = index;
2862 inst_base->br = NON_BRANCH; 2765 inst_base->br = NON_BRANCH;
2863 inst_base->load_r15 = 0; 2766 inst_base->load_r15 = 0;
2864 2767
2865 inst_cream->I = BIT(inst, 25); 2768 inst_cream->I = BIT(inst, 25);
2866 inst_cream->S = BIT(inst, 20); 2769 inst_cream->S = BIT(inst, 20);
2867 inst_cream->Rn = BITS(inst, 16, 19); 2770 inst_cream->Rn = BITS(inst, 16, 19);
2868 inst_cream->Rd = BITS(inst, 12, 15); 2771 inst_cream->Rd = BITS(inst, 12, 15);
2869 inst_cream->shifter_operand = BITS(inst, 0, 11); 2772 inst_cream->shifter_operand = BITS(inst, 0, 11);
2870 inst_cream->shtop_func = get_shtop(inst); 2773 inst_cream->shtop_func = get_shtop(inst);
2871 if (inst_cream->Rd == 15) { 2774 if (inst_cream->Rd == 15) {
2872 inst_base->br = INDIRECT_BRANCH; 2775 inst_base->br = INDIRECT_BRANCH;
2873 } 2776 }
2874 if (CHECK_RN) 2777 if (CHECK_RN)
2875 inst_base->load_r15 = 1; 2778 inst_base->load_r15 = 1;
2876 2779
2877 return inst_base; 2780 return inst_base;
2878} 2781}
2879ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index) 2782ARM_INST_PTR INTERPRETER_TRANSLATE(swi)(unsigned int inst, int index)
2880{ 2783{
2881 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swi_inst)); 2784 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swi_inst));
2882 swi_inst *inst_cream = (swi_inst *)inst_base->component; 2785 swi_inst *inst_cream = (swi_inst *)inst_base->component;
2883 2786
2884 inst_base->cond = BITS(inst, 28, 31); 2787 inst_base->cond = BITS(inst, 28, 31);
2885 inst_base->idx = index; 2788 inst_base->idx = index;
2886 inst_base->br = NON_BRANCH; 2789 inst_base->br = NON_BRANCH;
2887 2790
2888 inst_cream->num = BITS(inst, 0, 23); 2791 inst_cream->num = BITS(inst, 0, 23);
2889 return inst_base; 2792 return inst_base;
2890} 2793}
2891ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index) 2794ARM_INST_PTR INTERPRETER_TRANSLATE(swp)(unsigned int inst, int index)
2892{ 2795{
2893 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst)); 2796 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst));
2894 swp_inst *inst_cream = (swp_inst *)inst_base->component; 2797 swp_inst *inst_cream = (swp_inst *)inst_base->component;
2895 2798
2896 inst_base->cond = BITS(inst, 28, 31); 2799 inst_base->cond = BITS(inst, 28, 31);
2897 inst_base->idx = index; 2800 inst_base->idx = index;
2898 inst_base->br = NON_BRANCH; 2801 inst_base->br = NON_BRANCH;
2899 2802
2900 inst_cream->Rn = BITS(inst, 16, 19); 2803 inst_cream->Rn = BITS(inst, 16, 19);
2901 inst_cream->Rd = BITS(inst, 12, 15); 2804 inst_cream->Rd = BITS(inst, 12, 15);
2902 inst_cream->Rm = BITS(inst, 0, 3); 2805 inst_cream->Rm = BITS(inst, 0, 3);
2903 2806
2904 if (inst_cream->Rd == 15) { 2807 if (inst_cream->Rd == 15) {
2905 inst_base->br = INDIRECT_BRANCH; 2808 inst_base->br = INDIRECT_BRANCH;
2906 } 2809 }
2907 return inst_base; 2810 return inst_base;
2908} 2811}
2909ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){ 2812ARM_INST_PTR INTERPRETER_TRANSLATE(swpb)(unsigned int inst, int index){
2910 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst)); 2813 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(swp_inst));
2911 swp_inst *inst_cream = (swp_inst *)inst_base->component; 2814 swp_inst *inst_cream = (swp_inst *)inst_base->component;
2912 2815
2913 inst_base->cond = BITS(inst, 28, 31); 2816 inst_base->cond = BITS(inst, 28, 31);
2914 inst_base->idx = index; 2817 inst_base->idx = index;
2915 inst_base->br = NON_BRANCH; 2818 inst_base->br = NON_BRANCH;
2916 2819
2917 inst_cream->Rn = BITS(inst, 16, 19); 2820 inst_cream->Rn = BITS(inst, 16, 19);
2918 inst_cream->Rd = BITS(inst, 12, 15); 2821 inst_cream->Rd = BITS(inst, 12, 15);
2919 inst_cream->Rm = BITS(inst, 0, 3); 2822 inst_cream->Rm = BITS(inst, 0, 3);
2920 2823
2921 if (inst_cream->Rd == 15) { 2824 if (inst_cream->Rd == 15) {
2922 inst_base->br = INDIRECT_BRANCH; 2825 inst_base->br = INDIRECT_BRANCH;
2923 } 2826 }
2924 return inst_base; 2827 return inst_base;
2925} 2828}
2926ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index){ 2829ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab)(unsigned int inst, int index){
2927 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst)); 2830 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtab_inst));
2928 sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component; 2831 sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component;
2929 2832
2930 inst_base->cond = BITS(inst, 28, 31); 2833 inst_base->cond = BITS(inst, 28, 31);
2931 inst_base->idx = index; 2834 inst_base->idx = index;
2932 inst_base->br = NON_BRANCH; 2835 inst_base->br = NON_BRANCH;
2933 inst_base->load_r15 = 0; 2836 inst_base->load_r15 = 0;
2934 2837
2935 inst_cream->Rd = BITS(inst, 12, 15); 2838 inst_cream->Rd = BITS(inst, 12, 15);
2936 inst_cream->rotate = BITS(inst, 10, 11); 2839 inst_cream->rotate = BITS(inst, 10, 11);
2937 inst_cream->Rm = BITS(inst, 0, 3); 2840 inst_cream->Rm = BITS(inst, 0, 3);
2938 inst_cream->Rn = BITS(inst, 16, 19); 2841 inst_cream->Rn = BITS(inst, 16, 19);
2939 2842
2940 return inst_base; 2843 return inst_base;
2941} 2844}
2942ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SXTAB16"); } 2845ARM_INST_PTR INTERPRETER_TRANSLATE(sxtab16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SXTAB16"); }
2943ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index){ 2846ARM_INST_PTR INTERPRETER_TRANSLATE(sxtah)(unsigned int inst, int index){
2944 LOG_WARNING(Core_ARM11, "SXTAH untested"); 2847 LOG_WARNING(Core_ARM11, "SXTAH untested");
2945 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtah_inst)); 2848 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(sxtah_inst));
2946 sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component; 2849 sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component;
2947 2850
2948 inst_base->cond = BITS(inst, 28, 31); 2851 inst_base->cond = BITS(inst, 28, 31);
2949 inst_base->idx = index; 2852 inst_base->idx = index;
2950 inst_base->br = NON_BRANCH; 2853 inst_base->br = NON_BRANCH;
2951 inst_base->load_r15 = 0; 2854 inst_base->load_r15 = 0;
2952 2855
2953 inst_cream->Rd = BITS(inst, 12, 15); 2856 inst_cream->Rd = BITS(inst, 12, 15);
2954 inst_cream->rotate = BITS(inst, 10, 11); 2857 inst_cream->rotate = BITS(inst, 10, 11);
2955 inst_cream->Rm = BITS(inst, 0, 3); 2858 inst_cream->Rm = BITS(inst, 0, 3);
2956 inst_cream->Rn = BITS(inst, 16, 19); 2859 inst_cream->Rn = BITS(inst, 16, 19);
2957 2860
2958 return inst_base; 2861 return inst_base;
2959} 2862}
2960ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SXTB16"); } 2863ARM_INST_PTR INTERPRETER_TRANSLATE(sxtb16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("SXTB16"); }
2961ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index) 2864ARM_INST_PTR INTERPRETER_TRANSLATE(teq)(unsigned int inst, int index)
2962{ 2865{
2963 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(teq_inst)); 2866 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(teq_inst));
2964 teq_inst *inst_cream = (teq_inst *)inst_base->component; 2867 teq_inst *inst_cream = (teq_inst *)inst_base->component;
2965 2868
2966 inst_base->cond = BITS(inst, 28, 31); 2869 inst_base->cond = BITS(inst, 28, 31);
2967 inst_base->idx = index; 2870 inst_base->idx = index;
2968 inst_base->br = NON_BRANCH; 2871 inst_base->br = NON_BRANCH;
2969 inst_base->load_r15 = 0; 2872 inst_base->load_r15 = 0;
2970 2873
2971 inst_cream->I = BIT(inst, 25); 2874 inst_cream->I = BIT(inst, 25);
2972 inst_cream->Rn = BITS(inst, 16, 19); 2875 inst_cream->Rn = BITS(inst, 16, 19);
2973 inst_cream->shifter_operand = BITS(inst, 0, 11); 2876 inst_cream->shifter_operand = BITS(inst, 0, 11);
2974 inst_cream->shtop_func = get_shtop(inst); 2877 inst_cream->shtop_func = get_shtop(inst);
2975 2878
2976 if (CHECK_RN) 2879 if (CHECK_RN)
2977 inst_base->load_r15 = 1; 2880 inst_base->load_r15 = 1;
2978 return inst_base; 2881 return inst_base;
2979} 2882}
2980ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index) 2883ARM_INST_PTR INTERPRETER_TRANSLATE(tst)(unsigned int inst, int index)
2981{ 2884{
2982 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(tst_inst)); 2885 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(tst_inst));
2983 tst_inst *inst_cream = (tst_inst *)inst_base->component; 2886 tst_inst *inst_cream = (tst_inst *)inst_base->component;
2984 2887
2985 inst_base->cond = BITS(inst, 28, 31); 2888 inst_base->cond = BITS(inst, 28, 31);
2986 inst_base->idx = index; 2889 inst_base->idx = index;
2987 inst_base->br = NON_BRANCH; 2890 inst_base->br = NON_BRANCH;
2988 inst_base->load_r15 = 0; 2891 inst_base->load_r15 = 0;
2989 2892
2990 inst_cream->I = BIT(inst, 25); 2893 inst_cream->I = BIT(inst, 25);
2991 inst_cream->S = BIT(inst, 20); 2894 inst_cream->S = BIT(inst, 20);
2992 inst_cream->Rn = BITS(inst, 16, 19); 2895 inst_cream->Rn = BITS(inst, 16, 19);
2993 inst_cream->Rd = BITS(inst, 12, 15); 2896 inst_cream->Rd = BITS(inst, 12, 15);
2994 inst_cream->shifter_operand = BITS(inst, 0, 11); 2897 inst_cream->shifter_operand = BITS(inst, 0, 11);
2995 inst_cream->shtop_func = get_shtop(inst); 2898 inst_cream->shtop_func = get_shtop(inst);
2996 if (inst_cream->Rd == 15) { 2899 if (inst_cream->Rd == 15) {
2997 inst_base->br = INDIRECT_BRANCH; 2900 inst_base->br = INDIRECT_BRANCH;
2998 } 2901 }
2999 2902
3000 if (CHECK_RN) 2903 if (CHECK_RN)
3001 inst_base->load_r15 = 1; 2904 inst_base->load_r15 = 1;
3002 return inst_base; 2905 return inst_base;
3003} 2906}
3004ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADD16"); }
3005ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADD8"); } 2907ARM_INST_PTR INTERPRETER_TRANSLATE(uadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADD8"); }
2908ARM_INST_PTR INTERPRETER_TRANSLATE(uadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADD16"); }
3006ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADDSUBX"); } 2909ARM_INST_PTR INTERPRETER_TRANSLATE(uaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UADDSUBX"); }
3007ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHADD16"); } 2910ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index)
3008ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHADD8"); } 2911{
3009ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHADDSUBX"); } 2912 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
3010ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUB16"); } 2913 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
3011ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUB8"); } 2914
3012ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UHSUBADDX"); } 2915 inst_base->cond = BITS(inst, 28, 31);
3013ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UMAAL"); } 2916 inst_base->idx = index;
2917 inst_base->br = NON_BRANCH;
2918 inst_base->load_r15 = 0;
2919
2920 inst_cream->op1 = BITS(inst, 20, 21);
2921 inst_cream->op2 = BITS(inst, 5, 7);
2922 inst_cream->Rm = BITS(inst, 0, 3);
2923 inst_cream->Rn = BITS(inst, 16, 19);
2924 inst_cream->Rd = BITS(inst, 12, 15);
2925
2926 return inst_base;
2927}
2928ARM_INST_PTR INTERPRETER_TRANSLATE(uhadd16)(unsigned int inst, int index)
2929{
2930 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
2931}
2932ARM_INST_PTR INTERPRETER_TRANSLATE(uhaddsubx)(unsigned int inst, int index)
2933{
2934 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
2935}
2936ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub8)(unsigned int inst, int index)
2937{
2938 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
2939}
2940ARM_INST_PTR INTERPRETER_TRANSLATE(uhsub16)(unsigned int inst, int index)
2941{
2942 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
2943}
2944ARM_INST_PTR INTERPRETER_TRANSLATE(uhsubaddx)(unsigned int inst, int index)
2945{
2946 return INTERPRETER_TRANSLATE(uhadd8)(inst, index);
2947}
2948ARM_INST_PTR INTERPRETER_TRANSLATE(umaal)(unsigned int inst, int index)
2949{
2950 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(umaal_inst));
2951 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
2952
2953 inst_base->cond = BITS(inst, 28, 31);
2954 inst_base->idx = index;
2955 inst_base->br = NON_BRANCH;
2956 inst_base->load_r15 = 0;
2957
2958 inst_cream->Rm = BITS(inst, 8, 11);
2959 inst_cream->Rn = BITS(inst, 0, 3);
2960 inst_cream->RdLo = BITS(inst, 12, 15);
2961 inst_cream->RdHi = BITS(inst, 16, 19);
2962
2963 if (CHECK_RM || CHECK_RN)
2964 inst_base->load_r15 = 1;
2965
2966 return inst_base;
2967}
3014ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index) 2968ARM_INST_PTR INTERPRETER_TRANSLATE(umlal)(unsigned int inst, int index)
3015{ 2969{
3016 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst)); 2970 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umlal_inst));
3017 umlal_inst *inst_cream = (umlal_inst *)inst_base->component; 2971 umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
3018 2972
3019 inst_base->cond = BITS(inst, 28, 31); 2973 inst_base->cond = BITS(inst, 28, 31);
3020 inst_base->idx = index; 2974 inst_base->idx = index;
3021 inst_base->br = NON_BRANCH; 2975 inst_base->br = NON_BRANCH;
3022 inst_base->load_r15 = 0; 2976 inst_base->load_r15 = 0;
3023 2977
3024 inst_cream->S = BIT(inst, 20); 2978 inst_cream->S = BIT(inst, 20);
3025 inst_cream->Rm = BITS(inst, 0, 3); 2979 inst_cream->Rm = BITS(inst, 0, 3);
3026 inst_cream->Rs = BITS(inst, 8, 11); 2980 inst_cream->Rs = BITS(inst, 8, 11);
3027 inst_cream->RdHi = BITS(inst, 16, 19); 2981 inst_cream->RdHi = BITS(inst, 16, 19);
3028 inst_cream->RdLo = BITS(inst, 12, 15); 2982 inst_cream->RdLo = BITS(inst, 12, 15);
3029 2983
3030 if (CHECK_RM || CHECK_RS) 2984 if (CHECK_RM || CHECK_RS)
3031 inst_base->load_r15 = 1; 2985 inst_base->load_r15 = 1;
3032 return inst_base; 2986
2987 return inst_base;
3033} 2988}
3034ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index) 2989ARM_INST_PTR INTERPRETER_TRANSLATE(umull)(unsigned int inst, int index)
3035{ 2990{
3036 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst)); 2991 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(umull_inst));
3037 umull_inst *inst_cream = (umull_inst *)inst_base->component; 2992 umull_inst *inst_cream = (umull_inst *)inst_base->component;
3038 2993
3039 inst_base->cond = BITS(inst, 28, 31); 2994 inst_base->cond = BITS(inst, 28, 31);
3040 inst_base->idx = index; 2995 inst_base->idx = index;
3041 inst_base->br = NON_BRANCH; 2996 inst_base->br = NON_BRANCH;
3042 inst_base->load_r15 = 0; 2997 inst_base->load_r15 = 0;
3043 2998
3044 inst_cream->S = BIT(inst, 20); 2999 inst_cream->S = BIT(inst, 20);
3045 inst_cream->Rm = BITS(inst, 0, 3); 3000 inst_cream->Rm = BITS(inst, 0, 3);
3046 inst_cream->Rs = BITS(inst, 8, 11); 3001 inst_cream->Rs = BITS(inst, 8, 11);
3047 inst_cream->RdHi = BITS(inst, 16, 19); 3002 inst_cream->RdHi = BITS(inst, 16, 19);
3048 inst_cream->RdLo = BITS(inst, 12, 15); 3003 inst_cream->RdLo = BITS(inst, 12, 15);
3049 3004
3050 if (CHECK_RM || CHECK_RS) 3005 if (CHECK_RM || CHECK_RS)
3051 inst_base->load_r15 = 1; 3006 inst_base->load_r15 = 1;
3052 return inst_base; 3007 return inst_base;
3053} 3008}
3054 3009
3055ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index) 3010ARM_INST_PTR INTERPRETER_TRANSLATE(b_2_thumb)(unsigned int tinst, int index)
3056{ 3011{
3057 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_2_thumb)); 3012 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_2_thumb));
3058 b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component; 3013 b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component;
3014
3015 inst_cream->imm = ((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0);
3016
3017 inst_base->idx = index;
3018 inst_base->br = DIRECT_BRANCH;
3059 3019
3060 inst_cream->imm =((tinst & 0x3FF) << 1) | ((tinst & (1 << 10)) ? 0xFFFFF800 : 0); 3020 return inst_base;
3061 //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x\n", __FUNCTION__, tinst, inst_cream->imm);
3062 inst_base->idx = index;
3063 inst_base->br = DIRECT_BRANCH;
3064 return inst_base;
3065} 3021}
3066 3022
3067ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index) 3023ARM_INST_PTR INTERPRETER_TRANSLATE(b_cond_thumb)(unsigned int tinst, int index)
3068{ 3024{
3069 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_cond_thumb)); 3025 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(b_cond_thumb));
3070 b_cond_thumb *inst_cream = (b_cond_thumb *)inst_base->component; 3026 b_cond_thumb *inst_cream = (b_cond_thumb *)inst_base->component;
3071 3027
3072 inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0)); 3028 inst_cream->imm = (((tinst & 0x7F) << 1) | ((tinst & (1 << 7)) ? 0xFFFFFF00 : 0));
3073 inst_cream->cond = ((tinst >> 8) & 0xf); 3029 inst_cream->cond = ((tinst >> 8) & 0xf);
3074 //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x, cond=0x%x\n", __FUNCTION__, tinst, inst_cream->imm, inst_cream->cond); 3030 inst_base->idx = index;
3075 inst_base->idx = index; 3031 inst_base->br = DIRECT_BRANCH;
3076 inst_base->br = DIRECT_BRANCH; 3032
3077 return inst_base; 3033 return inst_base;
3078} 3034}
3079 3035
3080ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index) 3036ARM_INST_PTR INTERPRETER_TRANSLATE(bl_1_thumb)(unsigned int tinst, int index)
3081{ 3037{
3082 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_1_thumb)); 3038 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_1_thumb));
3083 bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component; 3039 bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component;
3084 3040
3085 inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0)); 3041 inst_cream->imm = (((tinst & 0x07FF) << 12) | ((tinst & (1 << 10)) ? 0xFF800000 : 0));
3086 //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x\n", __FUNCTION__, tinst, inst_cream->imm);
3087 3042
3088 inst_base->idx = index; 3043 inst_base->idx = index;
3089 inst_base->br = NON_BRANCH; 3044 inst_base->br = NON_BRANCH;
3090 return inst_base; 3045 return inst_base;
3091} 3046}
3092ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index) 3047ARM_INST_PTR INTERPRETER_TRANSLATE(bl_2_thumb)(unsigned int tinst, int index)
3093{ 3048{
3094 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_2_thumb)); 3049 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(bl_2_thumb));
3095 bl_2_thumb *inst_cream = (bl_2_thumb *)inst_base->component; 3050 bl_2_thumb *inst_cream = (bl_2_thumb *)inst_base->component;
3051
3052 inst_cream->imm = (tinst & 0x07FF) << 1;
3096 3053
3097 inst_cream->imm = (tinst & 0x07FF) << 1; 3054 inst_base->idx = index;
3098 //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x\n", __FUNCTION__, tinst, inst_cream->imm); 3055 inst_base->br = DIRECT_BRANCH;
3099 inst_base->idx = index; 3056 return inst_base;
3100 inst_base->br = DIRECT_BRANCH;
3101 return inst_base;
3102} 3057}
3103ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index) 3058ARM_INST_PTR INTERPRETER_TRANSLATE(blx_1_thumb)(unsigned int tinst, int index)
3104{ 3059{
3105 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_1_thumb)); 3060 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(blx_1_thumb));
3106 blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component; 3061 blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component;
3107 3062
3108 inst_cream->imm = (tinst & 0x07FF) << 1; 3063 inst_cream->imm = (tinst & 0x07FF) << 1;
3109 //DEBUG_LOG(ARM11, "In %s, tinst=0x%x, imm=0x%x\n", __FUNCTION__, tinst, inst_cream->imm); 3064 inst_cream->instr = tinst;
3110 inst_cream->instr = tinst; 3065
3111 inst_base->idx = index; 3066 inst_base->idx = index;
3112 inst_base->br = DIRECT_BRANCH; 3067 inst_base->br = DIRECT_BRANCH;
3113 return inst_base; 3068 return inst_base;
3114} 3069}
3115 3070
3116ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQADD16"); } 3071ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index)
3117ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQADD8"); } 3072{
3118ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQADDSUBX"); } 3073 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
3119ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQSUB16"); } 3074 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
3120ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQSUB8"); } 3075
3121ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UQSUBADDX"); } 3076 inst_base->cond = BITS(inst, 28, 31);
3122ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAD8"); } 3077 inst_base->idx = index;
3123ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USADA8"); } 3078 inst_base->br = NON_BRANCH;
3079 inst_base->load_r15 = 0;
3080
3081 inst_cream->Rm = BITS(inst, 0, 3);
3082 inst_cream->Rn = BITS(inst, 16, 19);
3083 inst_cream->Rd = BITS(inst, 12, 15);
3084 inst_cream->op1 = BITS(inst, 20, 21);
3085 inst_cream->op2 = BITS(inst, 5, 7);
3086
3087 return inst_base;
3088}
3089ARM_INST_PTR INTERPRETER_TRANSLATE(uqadd16)(unsigned int inst, int index)
3090{
3091 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
3092}
3093ARM_INST_PTR INTERPRETER_TRANSLATE(uqaddsubx)(unsigned int inst, int index)
3094{
3095 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
3096}
3097ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub8)(unsigned int inst, int index)
3098{
3099 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
3100}
3101ARM_INST_PTR INTERPRETER_TRANSLATE(uqsub16)(unsigned int inst, int index)
3102{
3103 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
3104}
3105ARM_INST_PTR INTERPRETER_TRANSLATE(uqsubaddx)(unsigned int inst, int index)
3106{
3107 return INTERPRETER_TRANSLATE(uqadd8)(inst, index);
3108}
3109ARM_INST_PTR INTERPRETER_TRANSLATE(usada8)(unsigned int inst, int index)
3110{
3111 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(generic_arm_inst));
3112 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
3113
3114 inst_base->cond = BITS(inst, 28, 31);
3115 inst_base->idx = index;
3116 inst_base->br = NON_BRANCH;
3117 inst_base->load_r15 = 0;
3118
3119 inst_cream->op1 = BITS(inst, 20, 24);
3120 inst_cream->op2 = BITS(inst, 5, 7);
3121 inst_cream->Rm = BITS(inst, 8, 11);
3122 inst_cream->Rn = BITS(inst, 0, 3);
3123 inst_cream->Ra = BITS(inst, 12, 15);
3124
3125 return inst_base;
3126}
3127ARM_INST_PTR INTERPRETER_TRANSLATE(usad8)(unsigned int inst, int index)
3128{
3129 return INTERPRETER_TRANSLATE(usada8)(inst, index);
3130}
3124ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT"); } 3131ARM_INST_PTR INTERPRETER_TRANSLATE(usat)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT"); }
3125ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT16"); } 3132ARM_INST_PTR INTERPRETER_TRANSLATE(usat16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USAT16"); }
3126ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUB16"); } 3133ARM_INST_PTR INTERPRETER_TRANSLATE(usub16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUB16"); }
3127ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUB8"); } 3134ARM_INST_PTR INTERPRETER_TRANSLATE(usub8)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUB8"); }
3128ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUBADDX"); } 3135ARM_INST_PTR INTERPRETER_TRANSLATE(usubaddx)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("USUBADDX"); }
3129ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UXTAB16"); }
3130ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) { UNIMPLEMENTED_INSTRUCTION("UXTB16"); }
3131 3136
3137ARM_INST_PTR INTERPRETER_TRANSLATE(uxtab16)(unsigned int inst, int index)
3138{
3139 arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(uxtab_inst));
3140 uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
3132 3141
3142 inst_base->cond = BITS(inst, 28, 31);
3143 inst_base->idx = index;
3144 inst_base->br = NON_BRANCH;
3145 inst_base->load_r15 = 0;
3133 3146
3134/* Floating point VFPv3 structures and instructions */ 3147 inst_cream->Rm = BITS(inst, 0, 3);
3148 inst_cream->Rn = BITS(inst, 16, 19);
3149 inst_cream->Rd = BITS(inst, 12, 15);
3150 inst_cream->rotate = BITS(inst, 10, 11);
3151
3152 return inst_base;
3153}
3154ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index)
3155{
3156 return INTERPRETER_TRANSLATE(uxtab16)(inst, index);
3157}
3158
3159// Floating point VFPv3 structures and instructions
3135 3160
3136#define VFP_INTERPRETER_STRUCT 3161#define VFP_INTERPRETER_STRUCT
3137#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 3162#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
@@ -3141,321 +3166,288 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(uxtb16)(unsigned int inst, int index) { UN
3141#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 3166#include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
3142#undef VFP_INTERPRETER_TRANS 3167#undef VFP_INTERPRETER_TRANS
3143 3168
3144
3145
3146typedef ARM_INST_PTR (*transop_fp_t)(unsigned int, int); 3169typedef ARM_INST_PTR (*transop_fp_t)(unsigned int, int);
3147 3170
3148const transop_fp_t arm_instruction_trans[] = { 3171const transop_fp_t arm_instruction_trans[] = {
3149 #define VFP_INTERPRETER_TABLE 3172 INTERPRETER_TRANSLATE(vmla),
3150 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 3173 INTERPRETER_TRANSLATE(vmls),
3151 #undef VFP_INTERPRETER_TABLE 3174 INTERPRETER_TRANSLATE(vnmla),
3152 INTERPRETER_TRANSLATE(srs), 3175 INTERPRETER_TRANSLATE(vnmla),
3153 INTERPRETER_TRANSLATE(rfe), 3176 INTERPRETER_TRANSLATE(vnmls),
3154 INTERPRETER_TRANSLATE(bkpt), 3177 INTERPRETER_TRANSLATE(vnmul),
3155 INTERPRETER_TRANSLATE(blx), 3178 INTERPRETER_TRANSLATE(vmul),
3156 INTERPRETER_TRANSLATE(cps), 3179 INTERPRETER_TRANSLATE(vadd),
3157 INTERPRETER_TRANSLATE(pld), 3180 INTERPRETER_TRANSLATE(vsub),
3158 INTERPRETER_TRANSLATE(setend), 3181 INTERPRETER_TRANSLATE(vdiv),
3159 INTERPRETER_TRANSLATE(clrex), 3182 INTERPRETER_TRANSLATE(vmovi),
3160 INTERPRETER_TRANSLATE(rev16), 3183 INTERPRETER_TRANSLATE(vmovr),
3161 INTERPRETER_TRANSLATE(usad8), 3184 INTERPRETER_TRANSLATE(vabs),
3162 INTERPRETER_TRANSLATE(sxtb), 3185 INTERPRETER_TRANSLATE(vneg),
3163 INTERPRETER_TRANSLATE(uxtb), 3186 INTERPRETER_TRANSLATE(vsqrt),
3164 INTERPRETER_TRANSLATE(sxth), 3187 INTERPRETER_TRANSLATE(vcmp),
3165 INTERPRETER_TRANSLATE(sxtb16), 3188 INTERPRETER_TRANSLATE(vcmp2),
3166 INTERPRETER_TRANSLATE(uxth), 3189 INTERPRETER_TRANSLATE(vcvtbds),
3167 INTERPRETER_TRANSLATE(uxtb16), 3190 INTERPRETER_TRANSLATE(vcvtbff),
3168 INTERPRETER_TRANSLATE(cpy), 3191 INTERPRETER_TRANSLATE(vcvtbfi),
3169 INTERPRETER_TRANSLATE(uxtab), 3192 INTERPRETER_TRANSLATE(vmovbrs),
3170 INTERPRETER_TRANSLATE(ssub8), 3193 INTERPRETER_TRANSLATE(vmsr),
3171 INTERPRETER_TRANSLATE(shsub8), 3194 INTERPRETER_TRANSLATE(vmovbrc),
3172 INTERPRETER_TRANSLATE(ssubaddx), 3195 INTERPRETER_TRANSLATE(vmrs),
3173 INTERPRETER_TRANSLATE(strex), 3196 INTERPRETER_TRANSLATE(vmovbcr),
3174 INTERPRETER_TRANSLATE(strexb), 3197 INTERPRETER_TRANSLATE(vmovbrrss),
3175 INTERPRETER_TRANSLATE(swp), 3198 INTERPRETER_TRANSLATE(vmovbrrd),
3176 INTERPRETER_TRANSLATE(swpb), 3199 INTERPRETER_TRANSLATE(vstr),
3177 INTERPRETER_TRANSLATE(ssub16), 3200 INTERPRETER_TRANSLATE(vpush),
3178 INTERPRETER_TRANSLATE(ssat16), 3201 INTERPRETER_TRANSLATE(vstm),
3179 INTERPRETER_TRANSLATE(shsubaddx), 3202 INTERPRETER_TRANSLATE(vpop),
3180 INTERPRETER_TRANSLATE(qsubaddx), 3203 INTERPRETER_TRANSLATE(vldr),
3181 INTERPRETER_TRANSLATE(shaddsubx), 3204 INTERPRETER_TRANSLATE(vldm),
3182 INTERPRETER_TRANSLATE(shadd8), 3205
3183 INTERPRETER_TRANSLATE(shadd16), 3206 INTERPRETER_TRANSLATE(srs),
3184 INTERPRETER_TRANSLATE(sel), 3207 INTERPRETER_TRANSLATE(rfe),
3185 INTERPRETER_TRANSLATE(saddsubx), 3208 INTERPRETER_TRANSLATE(bkpt),
3186 INTERPRETER_TRANSLATE(sadd8), 3209 INTERPRETER_TRANSLATE(blx),
3187 INTERPRETER_TRANSLATE(sadd16), 3210 INTERPRETER_TRANSLATE(cps),
3188 INTERPRETER_TRANSLATE(shsub16), 3211 INTERPRETER_TRANSLATE(pld),
3189 INTERPRETER_TRANSLATE(umaal), 3212 INTERPRETER_TRANSLATE(setend),
3190 INTERPRETER_TRANSLATE(uxtab16), 3213 INTERPRETER_TRANSLATE(clrex),
3191 INTERPRETER_TRANSLATE(usubaddx), 3214 INTERPRETER_TRANSLATE(rev16),
3192 INTERPRETER_TRANSLATE(usub8), 3215 INTERPRETER_TRANSLATE(usad8),
3193 INTERPRETER_TRANSLATE(usub16), 3216 INTERPRETER_TRANSLATE(sxtb),
3194 INTERPRETER_TRANSLATE(usat16), 3217 INTERPRETER_TRANSLATE(uxtb),
3195 INTERPRETER_TRANSLATE(usada8), 3218 INTERPRETER_TRANSLATE(sxth),
3196 INTERPRETER_TRANSLATE(uqsubaddx), 3219 INTERPRETER_TRANSLATE(sxtb16),
3197 INTERPRETER_TRANSLATE(uqsub8), 3220 INTERPRETER_TRANSLATE(uxth),
3198 INTERPRETER_TRANSLATE(uqsub16), 3221 INTERPRETER_TRANSLATE(uxtb16),
3199 INTERPRETER_TRANSLATE(uqaddsubx), 3222 INTERPRETER_TRANSLATE(cpy),
3200 INTERPRETER_TRANSLATE(uqadd8), 3223 INTERPRETER_TRANSLATE(uxtab),
3201 INTERPRETER_TRANSLATE(uqadd16), 3224 INTERPRETER_TRANSLATE(ssub8),
3202 INTERPRETER_TRANSLATE(sxtab), 3225 INTERPRETER_TRANSLATE(shsub8),
3203 INTERPRETER_TRANSLATE(uhsubaddx), 3226 INTERPRETER_TRANSLATE(ssubaddx),
3204 INTERPRETER_TRANSLATE(uhsub8), 3227 INTERPRETER_TRANSLATE(strex),
3205 INTERPRETER_TRANSLATE(uhsub16), 3228 INTERPRETER_TRANSLATE(strexb),
3206 INTERPRETER_TRANSLATE(uhaddsubx), 3229 INTERPRETER_TRANSLATE(swp),
3207 INTERPRETER_TRANSLATE(uhadd8), 3230 INTERPRETER_TRANSLATE(swpb),
3208 INTERPRETER_TRANSLATE(uhadd16), 3231 INTERPRETER_TRANSLATE(ssub16),
3209 INTERPRETER_TRANSLATE(uaddsubx), 3232 INTERPRETER_TRANSLATE(ssat16),
3210 INTERPRETER_TRANSLATE(uadd8), 3233 INTERPRETER_TRANSLATE(shsubaddx),
3211 INTERPRETER_TRANSLATE(uadd16), 3234 INTERPRETER_TRANSLATE(qsubaddx),
3212 INTERPRETER_TRANSLATE(sxtah), 3235 INTERPRETER_TRANSLATE(shaddsubx),
3213 INTERPRETER_TRANSLATE(sxtab16), 3236 INTERPRETER_TRANSLATE(shadd8),
3214 INTERPRETER_TRANSLATE(qadd8), 3237 INTERPRETER_TRANSLATE(shadd16),
3215 INTERPRETER_TRANSLATE(bxj), 3238 INTERPRETER_TRANSLATE(sel),
3216 INTERPRETER_TRANSLATE(clz), 3239 INTERPRETER_TRANSLATE(saddsubx),
3217 INTERPRETER_TRANSLATE(uxtah), 3240 INTERPRETER_TRANSLATE(sadd8),
3218 INTERPRETER_TRANSLATE(bx), 3241 INTERPRETER_TRANSLATE(sadd16),
3219 INTERPRETER_TRANSLATE(rev), 3242 INTERPRETER_TRANSLATE(shsub16),
3220 INTERPRETER_TRANSLATE(blx), 3243 INTERPRETER_TRANSLATE(umaal),
3221 INTERPRETER_TRANSLATE(revsh), 3244 INTERPRETER_TRANSLATE(uxtab16),
3222 INTERPRETER_TRANSLATE(qadd), 3245 INTERPRETER_TRANSLATE(usubaddx),
3223 INTERPRETER_TRANSLATE(qadd16), 3246 INTERPRETER_TRANSLATE(usub8),
3224 INTERPRETER_TRANSLATE(qaddsubx), 3247 INTERPRETER_TRANSLATE(usub16),
3225 INTERPRETER_TRANSLATE(ldrex), 3248 INTERPRETER_TRANSLATE(usat16),
3226 INTERPRETER_TRANSLATE(qdadd), 3249 INTERPRETER_TRANSLATE(usada8),
3227 INTERPRETER_TRANSLATE(qdsub), 3250 INTERPRETER_TRANSLATE(uqsubaddx),
3228 INTERPRETER_TRANSLATE(qsub), 3251 INTERPRETER_TRANSLATE(uqsub8),
3229 INTERPRETER_TRANSLATE(ldrexb), 3252 INTERPRETER_TRANSLATE(uqsub16),
3230 INTERPRETER_TRANSLATE(qsub8), 3253 INTERPRETER_TRANSLATE(uqaddsubx),
3231 INTERPRETER_TRANSLATE(qsub16), 3254 INTERPRETER_TRANSLATE(uqadd8),
3232 INTERPRETER_TRANSLATE(smuad), 3255 INTERPRETER_TRANSLATE(uqadd16),
3233 INTERPRETER_TRANSLATE(smmul), 3256 INTERPRETER_TRANSLATE(sxtab),
3234 INTERPRETER_TRANSLATE(smusd), 3257 INTERPRETER_TRANSLATE(uhsubaddx),
3235 INTERPRETER_TRANSLATE(smlsd), 3258 INTERPRETER_TRANSLATE(uhsub8),
3236 INTERPRETER_TRANSLATE(smlsld), 3259 INTERPRETER_TRANSLATE(uhsub16),
3237 INTERPRETER_TRANSLATE(smmla), 3260 INTERPRETER_TRANSLATE(uhaddsubx),
3238 INTERPRETER_TRANSLATE(smmls), 3261 INTERPRETER_TRANSLATE(uhadd8),
3239 INTERPRETER_TRANSLATE(smlald), 3262 INTERPRETER_TRANSLATE(uhadd16),
3240 INTERPRETER_TRANSLATE(smlad), 3263 INTERPRETER_TRANSLATE(uaddsubx),
3241 INTERPRETER_TRANSLATE(smlaw), 3264 INTERPRETER_TRANSLATE(uadd8),
3242 INTERPRETER_TRANSLATE(smulw), 3265 INTERPRETER_TRANSLATE(uadd16),
3243 INTERPRETER_TRANSLATE(pkhtb), 3266 INTERPRETER_TRANSLATE(sxtah),
3244 INTERPRETER_TRANSLATE(pkhbt), 3267 INTERPRETER_TRANSLATE(sxtab16),
3245 INTERPRETER_TRANSLATE(smul), 3268 INTERPRETER_TRANSLATE(qadd8),
3246 INTERPRETER_TRANSLATE(smlalxy), 3269 INTERPRETER_TRANSLATE(bxj),
3247 INTERPRETER_TRANSLATE(smla), 3270 INTERPRETER_TRANSLATE(clz),
3248 INTERPRETER_TRANSLATE(mcrr), 3271 INTERPRETER_TRANSLATE(uxtah),
3249 INTERPRETER_TRANSLATE(mrrc), 3272 INTERPRETER_TRANSLATE(bx),
3250 INTERPRETER_TRANSLATE(cmp), 3273 INTERPRETER_TRANSLATE(rev),
3251 INTERPRETER_TRANSLATE(tst), 3274 INTERPRETER_TRANSLATE(blx),
3252 INTERPRETER_TRANSLATE(teq), 3275 INTERPRETER_TRANSLATE(revsh),
3253 INTERPRETER_TRANSLATE(cmn), 3276 INTERPRETER_TRANSLATE(qadd),
3254 INTERPRETER_TRANSLATE(smull), 3277 INTERPRETER_TRANSLATE(qadd16),
3255 INTERPRETER_TRANSLATE(umull), 3278 INTERPRETER_TRANSLATE(qaddsubx),
3256 INTERPRETER_TRANSLATE(umlal), 3279 INTERPRETER_TRANSLATE(ldrex),
3257 INTERPRETER_TRANSLATE(smlal), 3280 INTERPRETER_TRANSLATE(qdadd),
3258 INTERPRETER_TRANSLATE(mul), 3281 INTERPRETER_TRANSLATE(qdsub),
3259 INTERPRETER_TRANSLATE(mla), 3282 INTERPRETER_TRANSLATE(qsub),
3260 INTERPRETER_TRANSLATE(ssat), 3283 INTERPRETER_TRANSLATE(ldrexb),
3261 INTERPRETER_TRANSLATE(usat), 3284 INTERPRETER_TRANSLATE(qsub8),
3262 INTERPRETER_TRANSLATE(mrs), 3285 INTERPRETER_TRANSLATE(qsub16),
3263 INTERPRETER_TRANSLATE(msr), 3286 INTERPRETER_TRANSLATE(smuad),
3264 INTERPRETER_TRANSLATE(and), 3287 INTERPRETER_TRANSLATE(smmul),
3265 INTERPRETER_TRANSLATE(bic), 3288 INTERPRETER_TRANSLATE(smusd),
3266 INTERPRETER_TRANSLATE(ldm), 3289 INTERPRETER_TRANSLATE(smlsd),
3267 INTERPRETER_TRANSLATE(eor), 3290 INTERPRETER_TRANSLATE(smlsld),
3268 INTERPRETER_TRANSLATE(add), 3291 INTERPRETER_TRANSLATE(smmla),
3269 INTERPRETER_TRANSLATE(rsb), 3292 INTERPRETER_TRANSLATE(smmls),
3270 INTERPRETER_TRANSLATE(rsc), 3293 INTERPRETER_TRANSLATE(smlald),
3271 INTERPRETER_TRANSLATE(sbc), 3294 INTERPRETER_TRANSLATE(smlad),
3272 INTERPRETER_TRANSLATE(adc), 3295 INTERPRETER_TRANSLATE(smlaw),
3273 INTERPRETER_TRANSLATE(sub), 3296 INTERPRETER_TRANSLATE(smulw),
3274 INTERPRETER_TRANSLATE(orr), 3297 INTERPRETER_TRANSLATE(pkhtb),
3275 INTERPRETER_TRANSLATE(mvn), 3298 INTERPRETER_TRANSLATE(pkhbt),
3276 INTERPRETER_TRANSLATE(mov), 3299 INTERPRETER_TRANSLATE(smul),
3277 INTERPRETER_TRANSLATE(stm), 3300 INTERPRETER_TRANSLATE(smlalxy),
3278 INTERPRETER_TRANSLATE(ldm), 3301 INTERPRETER_TRANSLATE(smla),
3279 INTERPRETER_TRANSLATE(ldrsh), 3302 INTERPRETER_TRANSLATE(mcrr),
3280 INTERPRETER_TRANSLATE(stm), 3303 INTERPRETER_TRANSLATE(mrrc),
3281 INTERPRETER_TRANSLATE(ldm), 3304 INTERPRETER_TRANSLATE(cmp),
3282 INTERPRETER_TRANSLATE(ldrsb), 3305 INTERPRETER_TRANSLATE(tst),
3283 INTERPRETER_TRANSLATE(strd), 3306 INTERPRETER_TRANSLATE(teq),
3284 INTERPRETER_TRANSLATE(ldrh), 3307 INTERPRETER_TRANSLATE(cmn),
3285 INTERPRETER_TRANSLATE(strh), 3308 INTERPRETER_TRANSLATE(smull),
3286 INTERPRETER_TRANSLATE(ldrd), 3309 INTERPRETER_TRANSLATE(umull),
3287 INTERPRETER_TRANSLATE(strt), 3310 INTERPRETER_TRANSLATE(umlal),
3288 INTERPRETER_TRANSLATE(strbt), 3311 INTERPRETER_TRANSLATE(smlal),
3289 INTERPRETER_TRANSLATE(ldrbt), 3312 INTERPRETER_TRANSLATE(mul),
3290 INTERPRETER_TRANSLATE(ldrt), 3313 INTERPRETER_TRANSLATE(mla),
3291 INTERPRETER_TRANSLATE(mrc), 3314 INTERPRETER_TRANSLATE(ssat),
3292 INTERPRETER_TRANSLATE(mcr), 3315 INTERPRETER_TRANSLATE(usat),
3293 INTERPRETER_TRANSLATE(msr), 3316 INTERPRETER_TRANSLATE(mrs),
3294 INTERPRETER_TRANSLATE(ldrb), 3317 INTERPRETER_TRANSLATE(msr),
3295 INTERPRETER_TRANSLATE(strb), 3318 INTERPRETER_TRANSLATE(and),
3296 INTERPRETER_TRANSLATE(ldr), 3319 INTERPRETER_TRANSLATE(bic),
3297 INTERPRETER_TRANSLATE(ldrcond), 3320 INTERPRETER_TRANSLATE(ldm),
3298 INTERPRETER_TRANSLATE(str), 3321 INTERPRETER_TRANSLATE(eor),
3299 INTERPRETER_TRANSLATE(cdp), 3322 INTERPRETER_TRANSLATE(add),
3300 INTERPRETER_TRANSLATE(stc), 3323 INTERPRETER_TRANSLATE(rsb),
3301 INTERPRETER_TRANSLATE(ldc), 3324 INTERPRETER_TRANSLATE(rsc),
3302 INTERPRETER_TRANSLATE(swi), 3325 INTERPRETER_TRANSLATE(sbc),
3303 INTERPRETER_TRANSLATE(bbl), 3326 INTERPRETER_TRANSLATE(adc),
3304 /* All the thumb instructions should be placed the end of table */ 3327 INTERPRETER_TRANSLATE(sub),
3305 INTERPRETER_TRANSLATE(b_2_thumb), 3328 INTERPRETER_TRANSLATE(orr),
3306 INTERPRETER_TRANSLATE(b_cond_thumb), 3329 INTERPRETER_TRANSLATE(mvn),
3307 INTERPRETER_TRANSLATE(bl_1_thumb), 3330 INTERPRETER_TRANSLATE(mov),
3308 INTERPRETER_TRANSLATE(bl_2_thumb), 3331 INTERPRETER_TRANSLATE(stm),
3309 INTERPRETER_TRANSLATE(blx_1_thumb) 3332 INTERPRETER_TRANSLATE(ldm),
3333 INTERPRETER_TRANSLATE(ldrsh),
3334 INTERPRETER_TRANSLATE(stm),
3335 INTERPRETER_TRANSLATE(ldm),
3336 INTERPRETER_TRANSLATE(ldrsb),
3337 INTERPRETER_TRANSLATE(strd),
3338 INTERPRETER_TRANSLATE(ldrh),
3339 INTERPRETER_TRANSLATE(strh),
3340 INTERPRETER_TRANSLATE(ldrd),
3341 INTERPRETER_TRANSLATE(strt),
3342 INTERPRETER_TRANSLATE(strbt),
3343 INTERPRETER_TRANSLATE(ldrbt),
3344 INTERPRETER_TRANSLATE(ldrt),
3345 INTERPRETER_TRANSLATE(mrc),
3346 INTERPRETER_TRANSLATE(mcr),
3347 INTERPRETER_TRANSLATE(msr),
3348 INTERPRETER_TRANSLATE(ldrb),
3349 INTERPRETER_TRANSLATE(strb),
3350 INTERPRETER_TRANSLATE(ldr),
3351 INTERPRETER_TRANSLATE(ldrcond),
3352 INTERPRETER_TRANSLATE(str),
3353 INTERPRETER_TRANSLATE(cdp),
3354 INTERPRETER_TRANSLATE(stc),
3355 INTERPRETER_TRANSLATE(ldc),
3356 INTERPRETER_TRANSLATE(swi),
3357 INTERPRETER_TRANSLATE(bbl),
3358 // All the thumb instructions should be placed the end of table
3359 INTERPRETER_TRANSLATE(b_2_thumb),
3360 INTERPRETER_TRANSLATE(b_cond_thumb),
3361 INTERPRETER_TRANSLATE(bl_1_thumb),
3362 INTERPRETER_TRANSLATE(bl_2_thumb),
3363 INTERPRETER_TRANSLATE(blx_1_thumb)
3310}; 3364};
3311 3365
3312typedef std::unordered_map<u32, int> bb_map; 3366typedef std::unordered_map<u32, int> bb_map;
3313bb_map CreamCache; 3367bb_map CreamCache;
3314 3368
3315//#define USE_DUMMY_CACHE 3369void insert_bb(unsigned int addr, int start) {
3316 3370 CreamCache[addr] = start;
3317#ifdef USE_DUMMY_CACHE
3318unsigned int DummyCache[0x100000];
3319#endif
3320
3321void insert_bb(unsigned int addr, int start)
3322{
3323#ifdef USE_DUMMY_CACHE
3324 DummyCache[addr] = start;
3325#else
3326 CreamCache[addr] = start;
3327#endif
3328} 3371}
3329 3372
3330#define TRANS_THRESHOLD 65000 3373#define TRANS_THRESHOLD 65000
3331int find_bb(unsigned int addr, int &start) 3374int find_bb(unsigned int addr, int &start) {
3332{ 3375 int ret = -1;
3333 int ret = -1; 3376 bb_map::const_iterator it = CreamCache.find(addr);
3334#ifdef USE_DUMMY_CACHE 3377 if (it != CreamCache.end()) {
3335 start = DummyCache[addr]; 3378 start = static_cast<int>(it->second);
3336 if (start) { 3379 ret = 0;
3337 ret = 0; 3380 } else {
3338 } else 3381 ret = -1;
3339 ret = -1; 3382 }
3340#else 3383 return ret;
3341 bb_map::const_iterator it = CreamCache.find(addr);
3342 if (it != CreamCache.end()) {
3343 start = static_cast<int>(it->second);
3344 ret = 0;
3345#if HYBRID_MODE
3346#if PROFILE
3347#else
3348 /* increase the bb counter */
3349 if(get_bb_prof(cpu, addr, 1) == TRANS_THRESHOLD){
3350 push_to_compiled(cpu, addr);
3351 }
3352#endif
3353#endif
3354 } else {
3355 ret = -1;
3356 }
3357#endif
3358 return ret;
3359} 3384}
3360 3385
3361
3362enum { 3386enum {
3363 FETCH_SUCCESS, 3387 FETCH_SUCCESS,
3364 FETCH_FAILURE 3388 FETCH_FAILURE
3365}; 3389};
3390
3366static tdstate decode_thumb_instr(arm_processor *cpu, uint32_t inst, addr_t addr, uint32_t *arm_inst, uint32_t* inst_size, ARM_INST_PTR* ptr_inst_base){ 3391static tdstate decode_thumb_instr(arm_processor *cpu, uint32_t inst, addr_t addr, uint32_t *arm_inst, uint32_t* inst_size, ARM_INST_PTR* ptr_inst_base){
3367 /* Check if in Thumb mode. */ 3392 // Check if in Thumb mode
3368 tdstate ret; 3393 tdstate ret = thumb_translate (addr, inst, arm_inst, inst_size);
3369 ret = thumb_translate (addr, inst, arm_inst, inst_size); 3394 if(ret == t_branch){
3370 if(ret == t_branch){ 3395 // TODO: FIXME, endian should be judged
3371 /* FIXME, endian should be judged */ 3396 uint32 tinstr;
3372 uint32 tinstr; 3397 if((addr & 0x3) != 0)
3373 if((addr & 0x3) != 0) 3398 tinstr = inst >> 16;
3374 tinstr = inst >> 16; 3399 else
3375 else 3400 tinstr = inst & 0xFFFF;
3376 tinstr = inst & 0xFFFF; 3401
3377 3402 int inst_index;
3378 //tinstr = inst & 0xFFFF; 3403 int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t);
3379 int inst_index; 3404
3380 /* table_length */ 3405 switch((tinstr & 0xF800) >> 11){
3381 int table_length = sizeof(arm_instruction_trans) / sizeof(transop_fp_t); 3406 case 26:
3382 3407 case 27:
3383 switch((tinstr & 0xF800) >> 11){ 3408 if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){
3384 /* we will translate the thumb instruction directly here */ 3409 uint32 cond = (tinstr & 0x0F00) >> 8;
3385 /* we will translate the thumb instruction directly here */ 3410 inst_index = table_length - 4;
3386 case 26: 3411 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
3387 case 27: 3412 } else {
3388 if (((tinstr & 0x0F00) != 0x0E00) && ((tinstr & 0x0F00) != 0x0F00)){ 3413 LOG_ERROR(Core_ARM11, "thumb decoder error");
3389 uint32 cond = (tinstr & 0x0F00) >> 8; 3414 }
3390 inst_index = table_length - 4; 3415 break;
3391 //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, blx 1 thumb index=%d\n", __FUNCTION__, tinstr, inst_index); 3416 case 28:
3392 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); 3417 // Branch 2, unconditional branch
3393 } 3418 inst_index = table_length - 5;
3394 else{ 3419 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
3395 /* something wrong */ 3420 break;
3396 LOG_ERROR(Core_ARM11, "thumb decoder error"); 3421
3397 } 3422 case 8:
3398 break; 3423 case 29:
3399 case 28: 3424 // For BLX 1 thumb instruction
3400 /* Branch 2, unconditional branch */ 3425 inst_index = table_length - 1;
3401 inst_index = table_length - 5; 3426 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
3402 //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, blx 1 thumb index=%d\n", __FUNCTION__, tinstr, inst_index); 3427 break;
3403 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); 3428 case 30:
3404 break; 3429 // For BL 1 thumb instruction
3405 3430 inst_index = table_length - 3;
3406 case 8: 3431 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
3407 case 29: 3432 break;
3408 /* For BLX 1 thumb instruction*/ 3433 case 31:
3409 inst_index = table_length - 1; 3434 // For BL 2 thumb instruction
3410 //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, blx 1 thumb index=%d, pc=0x%x\n", __FUNCTION__, tinstr, inst_index, cpu->translate_pc); 3435 inst_index = table_length - 2;
3411 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); 3436 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
3412 break; 3437 break;
3413 case 30: 3438 default:
3414 /* For BL 1 thumb instruction*/ 3439 ret = t_undefined;
3415 inst_index = table_length - 3; 3440 break;
3416 //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, bl 1 thumb index=%d, pc=0x%x\n", __FUNCTION__, tinstr, inst_index, cpu->translate_pc); 3441 }
3417 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index); 3442 }
3418 break; 3443 return ret;
3419 case 31:
3420 /* For BL 2 thumb instruction*/
3421 inst_index = table_length - 2;
3422 //DEBUG_LOG(ARM11, "In %s, tinstr=0x%x, bl 2 thumb index=%d, px=0x%x\n", __FUNCTION__, tinstr, inst_index, cpu->translate_pc);
3423 *ptr_inst_base = arm_instruction_trans[inst_index](tinstr, inst_index);
3424 break;
3425 default:
3426 ret = t_undefined;
3427 break;
3428 }
3429 }
3430 return ret;
3431}
3432
3433#if 0
3434int FetchInst(cpu_t *core, unsigned int &inst)
3435{
3436 //arm_processor *cpu = (arm_processor *)get_cast_conf_obj(core->cpu_data, "arm_core_t");
3437 arm_processor *cpu = (arm_processor *)(core->cpu_data->obj);
3438// fault_t fault = interpreter_read_memory(cpu->translate_pc, inst, 32);
3439 fault_t fault = interpreter_fetch(core, cpu->translate_pc, inst, 32);
3440 if (!core->is_user_mode) {
3441 if (fault) {
3442 cpu->abortSig = true;
3443 cpu->Aborted = ARMul_PrefetchAbortV;
3444 cpu->AbortAddr = cpu->translate_pc;
3445 cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff;
3446 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = cpu->translate_pc;
3447 return FETCH_FAILURE;
3448 }
3449 }
3450 return FETCH_SUCCESS;
3451} 3444}
3452#endif
3453 3445
3454unsigned int *InstLength; 3446unsigned int *InstLength;
3455 3447
3456enum { 3448enum {
3457 KEEP_GOING, 3449 KEEP_GOING,
3458 FETCH_EXCEPTION 3450 FETCH_EXCEPTION
3459}; 3451};
3460 3452
3461typedef struct instruction_set_encoding_item ISEITEM; 3453typedef struct instruction_set_encoding_item ISEITEM;
@@ -3464,274 +3456,148 @@ extern const ISEITEM arm_instruction[];
3464 3456
3465vector<uint64_t> code_page_set; 3457vector<uint64_t> code_page_set;
3466 3458
3467void flush_bb(uint32_t addr) 3459void flush_bb(uint32_t addr) {
3468{ 3460 bb_map::iterator it;
3469 bb_map::iterator it; 3461 uint32_t start;
3470 uint32_t start; 3462
3471 3463 addr &= 0xfffff000;
3472 addr &= 0xfffff000; 3464 for (it = CreamCache.begin(); it != CreamCache.end(); ) {
3473 for (it = CreamCache.begin(); it != CreamCache.end(); ) { 3465 start = static_cast<uint32_t>(it->first);
3474 start = static_cast<uint32_t>(it->first); 3466 start &= 0xfffff000;
3475 //start = (start >> 12) << 12; 3467 if (start == addr) {
3476 start &= 0xfffff000; 3468 CreamCache.erase(it++);
3477 if (start == addr) { 3469 } else
3478 //DEBUG_LOG(ARM11, "[ERASE][0x%08x]\n", static_cast<int>(it->first)); 3470 ++it;
3479 CreamCache.erase(it++); 3471 }
3480 } else 3472}
3481 ++it;
3482 }
3483
3484 //DEBUG_LOG(ARM11, "flush bb @ %x\n", addr);
3485}
3486
3487//static uint32_t get_bank_addr(void *addr)
3488//{
3489// uint64_t address = (uint64_t)addr;
3490// uint64_t bank0 = get_dma_addr(BANK0_START);
3491// if ((address >= bank0) && (address < (bank0 + BANK0_SIZE))) {
3492// //DEBUG_LOG(ARM11, "1.addr is %llx\n", addr);
3493// return ((uint64_t)addr - bank0) + BANK0_START;
3494// }
3495// return 0;
3496//}
3497
3498/* shenoubang add win32 2012-6-12 */
3499//#ifndef __WIN32__
3500//static void flush_code_cache(int signal_number, siginfo_t *si, void *unused)
3501//{
3502// DEBUG_LOG(ARM11, "in %s, addr=0x%llx\n", __FUNCTION__, si->si_addr);
3503// uint64_t addr = (uint64_t)si->si_addr;
3504// addr = (addr >> 12) << 12;
3505// skyeye_backtrace();
3506// #if 0
3507// if (addr == 0) {
3508// return;
3509// }
3510// const vector<uint64_t>::iterator it = find(code_page_set.begin(),
3511// code_page_set.end(),
3512// (uint64_t)addr);
3513// if (it != code_page_set.end()) {
3514// code_page_set.erase(it);
3515// }
3516// mprotect((void *)addr, 4096, PROT_READ | PROT_WRITE);
3517// //DEBUG_LOG(ARM11, "[flush][ADDR:0x%08llx]\n", addr);
3518// uint32_t phys_addr = get_bank_addr((void *)addr);
3519//// DEBUG_LOG(ARM11, "[PHYSICAL][ADDR:0x%08llx]\n", phys_addr);
3520// flush_bb(phys_addr);
3521// flush_bb(phys_addr + 4096);
3522//#if HYBRID_MODE
3523// /* flush the translated BB of dyncom */
3524// clear_translated_cache(phys_addr);
3525//#endif
3526// #endif
3527//}
3528//#endif /* shenoubang */
3529
3530//void protect_code_page(uint32_t addr)
3531//{
3532// void *mem_ptr = (void *)get_dma_addr(addr);
3533// mem_ptr = (void *)((long long int)mem_ptr & 0xfffffffffffff000LL);
3534//
3535// const vector<uint64_t>::iterator it = find(code_page_set.begin(),
3536// code_page_set.end(),
3537// (uint64_t)mem_ptr);
3538// if (it != code_page_set.end()) {
3539// return;
3540// }
3541// //DEBUG_LOG(ARM11, "[mprotect][ADDR:0x%08llx]\n", mem_ptr);
3542// /* shenoubang add win32 2012-6-12 */
3543//#ifndef __WIN32__
3544// struct sigaction sa;
3545//
3546// memset(&sa, 0, sizeof(sa));
3547// sa.sa_flags = SA_RESTART | SA_SIGINFO;
3548// sa.sa_sigaction = &flush_code_cache;
3549// sigaction(SIGSEGV, &sa, NULL);
3550//
3551// //mprotect(mem_ptr, 4096, PROT_READ);
3552//
3553// code_page_set.push_back((uint64_t)mem_ptr);
3554//#endif /* shenoubang */
3555//}
3556
3557
3558
3559int InterpreterTranslate(arm_processor *cpu, int &bb_start, addr_t addr)
3560{
3561 /* Decode instruction, get index */
3562 /* Allocate memory and init InsCream */
3563 /* Go on next, until terminal instruction */
3564 /* Save start addr of basicblock in CreamCache */
3565 //arm_processor *cpu = (arm_processor *)get_cast_conf_obj(core->cpu_data, "arm_core_t");
3566 //arm_processor *cpu = (arm_processor *)(core->cpu_data->obj);
3567 ARM_INST_PTR inst_base = NULL;
3568 unsigned int inst, inst_size = 4;
3569 int idx;
3570 int ret = NON_BRANCH;
3571 int thumb = 0;
3572 /* instruction size of basic block */
3573 int size = 0;
3574 /* (R15 - 8) ? */
3575 //cpu->translate_pc = cpu->Reg[15];
3576 bb_start = top;
3577
3578 if (cpu->TFlag)
3579 thumb = THUMB;
3580
3581 addr_t phys_addr;
3582 addr_t pc_start;
3583 fault_t fault = NO_FAULT;
3584 //fault = check_address_validity(cpu, addr, &phys_addr, 1, INSN_TLB);
3585 fault = check_address_validity(cpu, addr, &phys_addr, 1);
3586 if(fault != NO_FAULT){
3587 cpu->abortSig = true;
3588 cpu->Aborted = ARMul_PrefetchAbortV;
3589 cpu->AbortAddr = addr;
3590 cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff;
3591 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = addr;
3592 return FETCH_EXCEPTION;
3593 }
3594 pc_start = phys_addr;
3595 //phys_addr = get_dma_addr(phys_addr);
3596 while(ret == NON_BRANCH) {
3597 /* shenoubang add win32 2012-6-14 */
3598#ifdef __WIN32__
3599 mem_bank_t* bank;
3600 if (bank = bank_ptr(addr)) {
3601 bank->bank_read(32, phys_addr, &inst);
3602 }
3603 else {
3604 LOG_ERROR(Core_ARM11, "SKYEYE: Read physical addr 0x%x error!!\n", phys_addr);
3605 return FETCH_FAILURE;
3606 }
3607#else
3608 inst = Memory::Read32(phys_addr & 0xFFFFFFFC);//*(uint32_t *)(phys_addr & 0xFFFFFFFC);
3609#endif
3610 //or_tag(core, phys_addr, TAG_FAST_INTERP);
3611
3612 /*if (ret == FETCH_FAILURE) {
3613 return FETCH_EXCEPTION;
3614 }*/
3615
3616 size ++;
3617 /* If we are in thumb instruction, we will translate one thumb to one corresponding arm instruction */
3618 if (cpu->TFlag){
3619 //if(cpu->Cpsr & (1 << THUMB_BIT)){
3620 uint32_t arm_inst;
3621 tdstate state;
3622 state = decode_thumb_instr(cpu, inst, phys_addr, &arm_inst, &inst_size, &inst_base);
3623 //or_tag(core, phys_addr, TAG_THUMB);
3624 //DEBUG_LOG(ARM11, "In thumb state, arm_inst=0x%x, inst_size=0x%x, pc=0x%x\n", arm_inst, inst_size, cpu->translate_pc);
3625 /* we have translated the branch instruction of thumb in thumb decoder */
3626 if(state == t_branch){
3627 goto translated;
3628 }
3629 inst = arm_inst;
3630 }
3631
3632 ret = decode_arm_instr(inst, &idx);
3633 if (ret == DECODE_FAILURE) {
3634 LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : [%x]", phys_addr, inst);
3635 LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]);
3636 CITRA_IGNORE_EXIT(-1);
3637 }
3638// DEBUG_LOG(ARM11, "PC : [0x%x] INST : %s\n", cpu->translate_pc, arm_instruction[idx].name);
3639 inst_base = arm_instruction_trans[idx](inst, idx);
3640// DEBUG_LOG(ARM11, "translated @ %x INST : %x\n", cpu->translate_pc, inst);
3641// DEBUG_LOG(ARM11, "inst size is %d\n", InstLength[idx]);
3642translated:
3643 phys_addr += inst_size;
3644 3473
3645 if ((phys_addr & 0xfff) == 0) { 3474int InterpreterTranslate(arm_processor *cpu, int &bb_start, addr_t addr) {
3646 inst_base->br = END_OF_PAGE; 3475 // Decode instruction, get index
3647 } 3476 // Allocate memory and init InsCream
3648 ret = inst_base->br; 3477 // Go on next, until terminal instruction
3649 }; 3478 // Save start addr of basicblock in CreamCache
3479 ARM_INST_PTR inst_base = nullptr;
3480 unsigned int inst, inst_size = 4;
3481 int idx;
3482 int ret = NON_BRANCH;
3483 int thumb = 0;
3484 int size = 0; // instruction size of basic block
3485 bb_start = top;
3486
3487 if (cpu->TFlag)
3488 thumb = THUMB;
3489
3490 addr_t phys_addr;
3491 addr_t pc_start;
3492 fault_t fault = NO_FAULT;
3493 fault = check_address_validity(cpu, addr, &phys_addr, 1);
3494 if(fault != NO_FAULT){
3495 cpu->abortSig = true;
3496 cpu->Aborted = ARMul_PrefetchAbortV;
3497 cpu->AbortAddr = addr;
3498 cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff;
3499 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = addr;
3500 return FETCH_EXCEPTION;
3501 }
3650 3502
3651 //DEBUG_LOG(ARM11, "In %s,insert_bb pc=0x%x, TFlag=0x%x\n", __FUNCTION__, pc_start, cpu->TFlag); 3503 pc_start = phys_addr;
3652 insert_bb(pc_start, bb_start);
3653 return KEEP_GOING;
3654}
3655 3504
3656#define LOG_IN_CLR skyeye_printf_in_color 3505 while(ret == NON_BRANCH) {
3506 inst = Memory::Read32(phys_addr & 0xFFFFFFFC);//*(uint32_t *)(phys_addr & 0xFFFFFFFC);
3657 3507
3658int cmp(const void *x, const void *y) 3508 size ++;
3659{ 3509 // If we are in thumb instruction, we will translate one thumb to one corresponding arm instruction
3660 return *(unsigned long long int*)x - *(unsigned long long int *)y; 3510 if (cpu->TFlag) {
3511 uint32_t arm_inst;
3512 tdstate state;
3513 state = decode_thumb_instr(cpu, inst, phys_addr, &arm_inst, &inst_size, &inst_base);
3514 // We have translated the branch instruction of thumb in thumb decoder
3515 if(state == t_branch){
3516 goto translated;
3517 }
3518 inst = arm_inst;
3519 }
3520
3521 ret = decode_arm_instr(inst, &idx);
3522 if (ret == DECODE_FAILURE) {
3523 LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : [%x]", phys_addr, inst);
3524 LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]);
3525 CITRA_IGNORE_EXIT(-1);
3526 }
3527 inst_base = arm_instruction_trans[idx](inst, idx);
3528translated:
3529 phys_addr += inst_size;
3530
3531 if ((phys_addr & 0xfff) == 0) {
3532 inst_base->br = END_OF_PAGE;
3533 }
3534 ret = inst_base->br;
3535 };
3536 insert_bb(pc_start, bb_start);
3537 return KEEP_GOING;
3538}
3539
3540#define LOG_IN_CLR skyeye_printf_in_color
3541
3542int cmp(const void *x, const void *y) {
3543 return *(unsigned long long int*)x - *(unsigned long long int *)y;
3544}
3545
3546void InterpreterInitInstLength(unsigned long long int *ptr, size_t size) {
3547 int array_size = size / sizeof(void *);
3548 unsigned long long int *InstLabel = new unsigned long long int[array_size];
3549 memcpy(InstLabel, ptr, size);
3550 qsort(InstLabel, array_size, sizeof(void *), cmp);
3551 InstLength = new unsigned int[array_size - 4];
3552 for (int i = 0; i < array_size - 4; i ++) {
3553 for (int j = 0; j < array_size; j ++) {
3554 if (ptr[i] == InstLabel[j]) {
3555 InstLength[i] = InstLabel[j + 1] - InstLabel[j];
3556 break;
3557 }
3558 }
3559 }
3560 for (int i = 0; i < array_size - 4; i ++)
3561 LOG_DEBUG(Core_ARM11, "[%d]:%d", i, InstLength[i]);
3661} 3562}
3662 3563
3663void InterpreterInitInstLength(unsigned long long int *ptr, size_t size) 3564int clz(unsigned int x) {
3664{ 3565 int n;
3665 int array_size = size / sizeof(void *); 3566 if (x == 0) return (32);
3666 unsigned long long int *InstLabel = new unsigned long long int[array_size]; 3567 n = 1;
3667 memcpy(InstLabel, ptr, size); 3568 if ((x >> 16) == 0) { n = n + 16; x = x << 16;}
3668 qsort(InstLabel, array_size, sizeof(void *), cmp); 3569 if ((x >> 24) == 0) { n = n + 8; x = x << 8;}
3669 InstLength = new unsigned int[array_size - 4]; 3570 if ((x >> 28) == 0) { n = n + 4; x = x << 4;}
3670 for (int i = 0; i < array_size - 4; i ++) { 3571 if ((x >> 30) == 0) { n = n + 2; x = x << 2;}
3671 for (int j = 0; j < array_size; j ++) { 3572 n = n - (x >> 31);
3672 if (ptr[i] == InstLabel[j]) { 3573 return n;
3673 InstLength[i] = InstLabel[j + 1] - InstLabel[j];
3674 break;
3675 }
3676 }
3677 }
3678 for (int i = 0; i < array_size - 4; i ++)
3679 LOG_DEBUG(Core_ARM11, "[%d]:%d", i, InstLength[i]);
3680}
3681
3682int clz(unsigned int x)
3683{
3684 int n;
3685 if (x == 0) return (32);
3686 n = 1;
3687 if ((x >> 16) == 0) { n = n + 16; x = x << 16;}
3688 if ((x >> 24) == 0) { n = n + 8; x = x << 8;}
3689 if ((x >> 28) == 0) { n = n + 4; x = x << 4;}
3690 if ((x >> 30) == 0) { n = n + 2; x = x << 2;}
3691 n = n - (x >> 31);
3692 return n;
3693} 3574}
3694 3575
3695unsigned arm_dyncom_SWI (ARMul_State * state, ARMword number); 3576unsigned arm_dyncom_SWI (ARMul_State * state, ARMword number);
3696 3577
3697static bool InAPrivilegedMode(arm_core_t *core) 3578static bool InAPrivilegedMode(arm_core_t *core) {
3698{ 3579 return (core->Mode != USER32MODE);
3699 return (core->Mode != USER32MODE);
3700} 3580}
3701 3581
3702/* r15 = r15 + 8 */ 3582unsigned InterpreterMainLoop(ARMul_State* state) {
3703unsigned InterpreterMainLoop(ARMul_State* state) 3583 #define CRn inst_cream->crn
3704{ 3584 #define OPCODE_2 inst_cream->opcode_2
3705 #define CRn inst_cream->crn 3585 #define CRm inst_cream->crm
3706 #define OPCODE_2 inst_cream->opcode_2 3586 #define CP15_REG(n) cpu->CP15[CP15(n)]
3707 #define CRm inst_cream->crm 3587 #define RD cpu->Reg[inst_cream->Rd]
3708 #define CP15_REG(n) cpu->CP15[CP15(n)] 3588 #define RN cpu->Reg[inst_cream->Rn]
3709 #define RD cpu->Reg[inst_cream->Rd] 3589 #define RM cpu->Reg[inst_cream->Rm]
3710 #define RN cpu->Reg[inst_cream->Rn] 3590 #define RS cpu->Reg[inst_cream->Rs]
3711 #define RM cpu->Reg[inst_cream->Rm] 3591 #define RDHI cpu->Reg[inst_cream->RdHi]
3712 #define RS cpu->Reg[inst_cream->Rs] 3592 #define RDLO cpu->Reg[inst_cream->RdLo]
3713 #define RDHI cpu->Reg[inst_cream->RdHi] 3593 #define LINK_RTN_ADDR (cpu->Reg[14] = cpu->Reg[15] + 4)
3714 #define RDLO cpu->Reg[inst_cream->RdLo] 3594 #define SET_PC (cpu->Reg[15] = cpu->Reg[15] + 8 + inst_cream->signed_immed_24)
3715 #define LINK_RTN_ADDR (cpu->Reg[14] = cpu->Reg[15] + 4) 3595 #define SHIFTER_OPERAND inst_cream->shtop_func(cpu, inst_cream->shifter_operand)
3716 #define SET_PC (cpu->Reg[15] = cpu->Reg[15] + 8 + inst_cream->signed_immed_24) 3596
3717 #define SHIFTER_OPERAND inst_cream->shtop_func(cpu, inst_cream->shifter_operand) 3597 #define FETCH_INST if (inst_base->br != NON_BRANCH) goto DISPATCH; \
3718 3598 inst_base = (arm_inst *)&inst_buf[ptr]
3719 #if ENABLE_ICOUNTER 3599
3720 #define INC_ICOUNTER cpu->icounter++; \ 3600 #define INC_PC(l) ptr += sizeof(arm_inst) + l
3721 if(cpu->Reg[15] > 0xc0000000) \
3722 cpu->kernel_icounter++;
3723 //if (debug_function(core)) \
3724 if (core->check_int_flag) \
3725 goto END
3726 //LOG_TRACE(Core_ARM11, "icounter is %llx pc is %x\n", cpu->icounter, cpu->Reg[15])
3727 #else
3728 #define INC_ICOUNTER ;
3729 #endif
3730
3731 #define FETCH_INST if (inst_base->br != NON_BRANCH) \
3732 goto DISPATCH; \
3733 inst_base = (arm_inst *)&inst_buf[ptr]
3734#define INC_PC(l) ptr += sizeof(arm_inst) + l
3735 3601
3736// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a 3602// GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback to a
3737// clunky switch statement. 3603// clunky switch statement.
@@ -3872,7 +3738,7 @@ unsigned InterpreterMainLoop(ARMul_State* state)
3872 case 124: goto PKHTB_INST; \ 3738 case 124: goto PKHTB_INST; \
3873 case 125: goto PKHBT_INST; \ 3739 case 125: goto PKHBT_INST; \
3874 case 126: goto SMUL_INST; \ 3740 case 126: goto SMUL_INST; \
3875 case 127: goto SMLAL_INST; \ 3741 case 127: goto SMLALXY_INST; \
3876 case 128: goto SMLA_INST; \ 3742 case 128: goto SMLA_INST; \
3877 case 129: goto MCRR_INST; \ 3743 case 129: goto MCRR_INST; \
3878 case 130: goto MRRC_INST; \ 3744 case 130: goto MRRC_INST; \
@@ -3941,2606 +3807,2522 @@ unsigned InterpreterMainLoop(ARMul_State* state)
3941 } 3807 }
3942#endif 3808#endif
3943 3809
3944 #define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0) 3810 #define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0)
3945 #define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1) 3811 #define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1)
3946// #define UPDATE_CFLAG(dst, lop, rop) (cpu->CFlag = ((ISNEG(lop) && ISPOS(rop)) || \ 3812
3947 (ISNEG(lop) && ISPOS(dst)) || \ 3813 #define UPDATE_CFLAG(dst, lop, rop) (cpu->CFlag = ((dst < lop) || (dst < rop)))
3948 (ISPOS(rop) && ISPOS(dst)))) 3814 #define UPDATE_CFLAG_CARRY_FROM_ADD(lop, rop, flag) (cpu->CFlag = (((uint64_t) lop + (uint64_t) rop + (uint64_t) flag) > 0xffffffff) )
3949 #define UPDATE_CFLAG(dst, lop, rop) (cpu->CFlag = ((dst < lop) || (dst < rop))) 3815 #define UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(lop, rop, flag) (cpu->CFlag = ((uint64_t) lop >= ((uint64_t) rop + (uint64_t) flag)))
3950 #define UPDATE_CFLAG_CARRY_FROM_ADD(lop, rop, flag) (cpu->CFlag = (((uint64_t) lop + (uint64_t) rop + (uint64_t) flag) > 0xffffffff) ) 3816 #define UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop) (cpu->CFlag = (lop >= rop))
3951 #define UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(lop, rop, flag) (cpu->CFlag = ((uint64_t) lop >= ((uint64_t) rop + (uint64_t) flag))) 3817 #define UPDATE_CFLAG_WITH_NOT(dst, lop, rop) (cpu->CFlag = !(dst < lop))
3952 #define UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop) (cpu->CFlag = (lop >= rop)) 3818 #define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out)
3953 #define UPDATE_CFLAG_WITH_NOT(dst, lop, rop) (cpu->CFlag = !(dst < lop)) 3819
3954 #define UPDATE_CFLAG_WITH_SC cpu->CFlag = cpu->shifter_carry_out 3820 #define UPDATE_VFLAG(dst, lop, rop) (cpu->VFlag = (((lop < 0) && (rop < 0) && (dst >= 0)) || \
3955// #define UPDATE_CFLAG_WITH_NOT(dst, lop, rop) cpu->CFlag = !((ISNEG(lop) && ISPOS(rop)) || \ 3821 ((lop >= 0) && (rop) >= 0 && (dst < 0))))
3956 (ISNEG(lop) && ISPOS(dst)) || \ 3822 #define UPDATE_VFLAG_WITH_NOT(dst, lop, rop) (cpu->VFlag = !(((lop < 0) && (rop < 0) && (dst >= 0)) || \
3957 (ISPOS(rop) && ISPOS(dst))) 3823 ((lop >= 0) && (rop) >= 0 && (dst < 0))))
3958 #define UPDATE_VFLAG(dst, lop, rop) (cpu->VFlag = (((lop < 0) && (rop < 0) && (dst >= 0)) || \ 3824 #define UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop) (cpu->VFlag = (((lop ^ rop) & (lop ^ dst)) >> 31))
3959 ((lop >= 0) && (rop) >= 0 && (dst < 0)))) 3825
3960 #define UPDATE_VFLAG_WITH_NOT(dst, lop, rop) (cpu->VFlag = !(((lop < 0) && (rop < 0) && (dst >= 0)) || \ 3826 #define SAVE_NZCVT cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | \
3961 ((lop >= 0) && (rop) >= 0 && (dst < 0)))) 3827 (cpu->NFlag << 31) | \
3962 #define UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop) (cpu->VFlag = (((lop ^ rop) & (lop ^ dst)) >> 31)) 3828 (cpu->ZFlag << 30) | \
3963 3829 (cpu->CFlag << 29) | \
3964 #define SAVE_NZCVT cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | \ 3830 (cpu->VFlag << 28) | \
3965 (cpu->NFlag << 31) | \ 3831 (cpu->TFlag << 5)
3966 (cpu->ZFlag << 30) | \ 3832 #define LOAD_NZCVT cpu->NFlag = (cpu->Cpsr >> 31); \
3967 (cpu->CFlag << 29) | \ 3833 cpu->ZFlag = (cpu->Cpsr >> 30) & 1; \
3968 (cpu->VFlag << 28) | \ 3834 cpu->CFlag = (cpu->Cpsr >> 29) & 1; \
3969 (cpu->TFlag << 5) 3835 cpu->VFlag = (cpu->Cpsr >> 28) & 1; \
3970 #define LOAD_NZCVT cpu->NFlag = (cpu->Cpsr >> 31); \ 3836 cpu->TFlag = (cpu->Cpsr >> 5) & 1;
3971 cpu->ZFlag = (cpu->Cpsr >> 30) & 1; \ 3837
3972 cpu->CFlag = (cpu->Cpsr >> 29) & 1; \ 3838 #define CurrentModeHasSPSR (cpu->Mode != SYSTEM32MODE) && (cpu->Mode != USER32MODE)
3973 cpu->VFlag = (cpu->Cpsr >> 28) & 1; \ 3839 #define PC (cpu->Reg[15])
3974 cpu->TFlag = (cpu->Cpsr >> 5) & 1; 3840 #define CHECK_EXT_INT if (!cpu->NirqSig && !(cpu->Cpsr & 0x80)) goto END;
3975 3841
3976 #define CurrentModeHasSPSR (cpu->Mode != SYSTEM32MODE) && (cpu->Mode != USER32MODE) 3842 arm_processor *cpu = state;
3977 #define PC (cpu->Reg[15])
3978 #define CHECK_EXT_INT if (!cpu->NirqSig) { \
3979 if (!(cpu->Cpsr & 0x80)) { \
3980 goto END; \
3981 } \
3982 }
3983
3984
3985
3986 //arm_processor *cpu = (arm_processor *)get_cast_conf_obj(core->cpu_data, "arm_core_t");
3987 arm_processor *cpu = state; //(arm_processor *)(core->cpu_data->obj);
3988 3843
3989 // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback 3844 // GCC and Clang have a C++ extension to support a lookup table of labels. Otherwise, fallback
3990 // to a clunky switch statement. 3845 // to a clunky switch statement.
3991#if defined __GNUC__ || defined __clang__ 3846#if defined __GNUC__ || defined __clang__
3992 void *InstLabel[] = { 3847 void *InstLabel[] = {
3993 #define VFP_INTERPRETER_LABEL 3848 &&VMLA_INST, &&VMLS_INST, &&VNMLA_INST, &&VNMLA_INST, &&VNMLS_INST, &&VNMUL_INST, &&VMUL_INST, &&VADD_INST, &&VSUB_INST,
3994 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 3849 &&VDIV_INST, &&VMOVI_INST, &&VMOVR_INST, &&VABS_INST, &&VNEG_INST, &&VSQRT_INST, &&VCMP_INST, &&VCMP2_INST, &&VCVTBDS_INST,
3995 #undef VFP_INTERPRETER_LABEL 3850 &&VCVTBFF_INST, &&VCVTBFI_INST, &&VMOVBRS_INST, &&VMSR_INST, &&VMOVBRC_INST, &&VMRS_INST, &&VMOVBCR_INST, &&VMOVBRRSS_INST,
3996 &&SRS_INST,&&RFE_INST,&&BKPT_INST,&&BLX_INST,&&CPS_INST,&&PLD_INST,&&SETEND_INST,&&CLREX_INST,&&REV16_INST,&&USAD8_INST,&&SXTB_INST, 3851 &&VMOVBRRD_INST, &&VSTR_INST, &&VPUSH_INST, &&VSTM_INST, &&VPOP_INST, &&VLDR_INST, &&VLDM_INST,
3997 &&UXTB_INST,&&SXTH_INST,&&SXTB16_INST,&&UXTH_INST,&&UXTB16_INST,&&CPY_INST,&&UXTAB_INST,&&SSUB8_INST,&&SHSUB8_INST,&&SSUBADDX_INST, 3852
3998 &&STREX_INST,&&STREXB_INST,&&SWP_INST,&&SWPB_INST,&&SSUB16_INST,&&SSAT16_INST,&&SHSUBADDX_INST,&&QSUBADDX_INST,&&SHADDSUBX_INST, 3853 &&SRS_INST,&&RFE_INST,&&BKPT_INST,&&BLX_INST,&&CPS_INST,&&PLD_INST,&&SETEND_INST,&&CLREX_INST,&&REV16_INST,&&USAD8_INST,&&SXTB_INST,
3999 &&SHADD8_INST,&&SHADD16_INST,&&SEL_INST,&&SADDSUBX_INST,&&SADD8_INST,&&SADD16_INST,&&SHSUB16_INST,&&UMAAL_INST,&&UXTAB16_INST, 3854 &&UXTB_INST,&&SXTH_INST,&&SXTB16_INST,&&UXTH_INST,&&UXTB16_INST,&&CPY_INST,&&UXTAB_INST,&&SSUB8_INST,&&SHSUB8_INST,&&SSUBADDX_INST,
4000 &&USUBADDX_INST,&&USUB8_INST,&&USUB16_INST,&&USAT16_INST,&&USADA8_INST,&&UQSUBADDX_INST,&&UQSUB8_INST,&&UQSUB16_INST, 3855 &&STREX_INST,&&STREXB_INST,&&SWP_INST,&&SWPB_INST,&&SSUB16_INST,&&SSAT16_INST,&&SHSUBADDX_INST,&&QSUBADDX_INST,&&SHADDSUBX_INST,
4001 &&UQADDSUBX_INST,&&UQADD8_INST,&&UQADD16_INST,&&SXTAB_INST,&&UHSUBADDX_INST,&&UHSUB8_INST,&&UHSUB16_INST,&&UHADDSUBX_INST,&&UHADD8_INST, 3856 &&SHADD8_INST,&&SHADD16_INST,&&SEL_INST,&&SADDSUBX_INST,&&SADD8_INST,&&SADD16_INST,&&SHSUB16_INST,&&UMAAL_INST,&&UXTAB16_INST,
4002 &&UHADD16_INST,&&UADDSUBX_INST,&&UADD8_INST,&&UADD16_INST,&&SXTAH_INST,&&SXTAB16_INST,&&QADD8_INST,&&BXJ_INST,&&CLZ_INST,&&UXTAH_INST, 3857 &&USUBADDX_INST,&&USUB8_INST,&&USUB16_INST,&&USAT16_INST,&&USADA8_INST,&&UQSUBADDX_INST,&&UQSUB8_INST,&&UQSUB16_INST,
4003 &&BX_INST,&&REV_INST,&&BLX_INST,&&REVSH_INST,&&QADD_INST,&&QADD16_INST,&&QADDSUBX_INST,&&LDREX_INST,&&QDADD_INST,&&QDSUB_INST, 3858 &&UQADDSUBX_INST,&&UQADD8_INST,&&UQADD16_INST,&&SXTAB_INST,&&UHSUBADDX_INST,&&UHSUB8_INST,&&UHSUB16_INST,&&UHADDSUBX_INST,&&UHADD8_INST,
4004 &&QSUB_INST,&&LDREXB_INST,&&QSUB8_INST,&&QSUB16_INST,&&SMUAD_INST,&&SMMUL_INST,&&SMUSD_INST,&&SMLSD_INST,&&SMLSLD_INST,&&SMMLA_INST, 3859 &&UHADD16_INST,&&UADDSUBX_INST,&&UADD8_INST,&&UADD16_INST,&&SXTAH_INST,&&SXTAB16_INST,&&QADD8_INST,&&BXJ_INST,&&CLZ_INST,&&UXTAH_INST,
4005 &&SMMLS_INST,&&SMLALD_INST,&&SMLAD_INST,&&SMLAW_INST,&&SMULW_INST,&&PKHTB_INST,&&PKHBT_INST,&&SMUL_INST,&&SMLAL_INST,&&SMLA_INST, 3860 &&BX_INST,&&REV_INST,&&BLX_INST,&&REVSH_INST,&&QADD_INST,&&QADD16_INST,&&QADDSUBX_INST,&&LDREX_INST,&&QDADD_INST,&&QDSUB_INST,
4006 &&MCRR_INST,&&MRRC_INST,&&CMP_INST,&&TST_INST,&&TEQ_INST,&&CMN_INST,&&SMULL_INST,&&UMULL_INST,&&UMLAL_INST,&&SMLAL_INST,&&MUL_INST, 3861 &&QSUB_INST,&&LDREXB_INST,&&QSUB8_INST,&&QSUB16_INST,&&SMUAD_INST,&&SMMUL_INST,&&SMUSD_INST,&&SMLSD_INST,&&SMLSLD_INST,&&SMMLA_INST,
4007 &&MLA_INST,&&SSAT_INST,&&USAT_INST,&&MRS_INST,&&MSR_INST,&&AND_INST,&&BIC_INST,&&LDM_INST,&&EOR_INST,&&ADD_INST,&&RSB_INST,&&RSC_INST, 3862 &&SMMLS_INST,&&SMLALD_INST,&&SMLAD_INST,&&SMLAW_INST,&&SMULW_INST,&&PKHTB_INST,&&PKHBT_INST,&&SMUL_INST,&&SMLALXY_INST,&&SMLA_INST,
4008 &&SBC_INST,&&ADC_INST,&&SUB_INST,&&ORR_INST,&&MVN_INST,&&MOV_INST,&&STM_INST,&&LDM_INST,&&LDRSH_INST,&&STM_INST,&&LDM_INST,&&LDRSB_INST, 3863 &&MCRR_INST,&&MRRC_INST,&&CMP_INST,&&TST_INST,&&TEQ_INST,&&CMN_INST,&&SMULL_INST,&&UMULL_INST,&&UMLAL_INST,&&SMLAL_INST,&&MUL_INST,
4009 &&STRD_INST,&&LDRH_INST,&&STRH_INST,&&LDRD_INST,&&STRT_INST,&&STRBT_INST,&&LDRBT_INST,&&LDRT_INST,&&MRC_INST,&&MCR_INST,&&MSR_INST, 3864 &&MLA_INST,&&SSAT_INST,&&USAT_INST,&&MRS_INST,&&MSR_INST,&&AND_INST,&&BIC_INST,&&LDM_INST,&&EOR_INST,&&ADD_INST,&&RSB_INST,&&RSC_INST,
4010 &&LDRB_INST,&&STRB_INST,&&LDR_INST,&&LDRCOND_INST, &&STR_INST,&&CDP_INST,&&STC_INST,&&LDC_INST,&&SWI_INST,&&BBL_INST,&&B_2_THUMB, &&B_COND_THUMB, 3865 &&SBC_INST,&&ADC_INST,&&SUB_INST,&&ORR_INST,&&MVN_INST,&&MOV_INST,&&STM_INST,&&LDM_INST,&&LDRSH_INST,&&STM_INST,&&LDM_INST,&&LDRSB_INST,
4011 &&BL_1_THUMB, &&BL_2_THUMB, &&BLX_1_THUMB, &&DISPATCH,&&INIT_INST_LENGTH,&&END 3866 &&STRD_INST,&&LDRH_INST,&&STRH_INST,&&LDRD_INST,&&STRT_INST,&&STRBT_INST,&&LDRBT_INST,&&LDRT_INST,&&MRC_INST,&&MCR_INST,&&MSR_INST,
4012 }; 3867 &&LDRB_INST,&&STRB_INST,&&LDR_INST,&&LDRCOND_INST, &&STR_INST,&&CDP_INST,&&STC_INST,&&LDC_INST,&&SWI_INST,&&BBL_INST,&&B_2_THUMB, &&B_COND_THUMB,
4013#endif 3868 &&BL_1_THUMB, &&BL_2_THUMB, &&BLX_1_THUMB, &&DISPATCH,&&INIT_INST_LENGTH,&&END
4014 arm_inst * inst_base; 3869 };
4015 unsigned int lop, rop, dst;
4016 unsigned int addr;
4017 unsigned int phys_addr;
4018 unsigned int last_pc = 0;
4019 unsigned int num_instrs = 0;
4020 fault_t fault;
4021 static unsigned int last_physical_base = 0, last_logical_base = 0;
4022 int ptr;
4023 bool single_step = (cpu->NumInstrsToExecute == 1);
4024
4025 LOAD_NZCVT;
4026 DISPATCH:
4027 {
4028 if (!cpu->NirqSig) {
4029 if (!(cpu->Cpsr & 0x80)) {
4030 goto END;
4031 }
4032 }
4033
4034 if (cpu->TFlag) {
4035 cpu->Reg[15] &= 0xfffffffe;
4036 } else
4037 cpu->Reg[15] &= 0xfffffffc;
4038#if PROFILE
4039 /* check next instruction address is valid. */
4040 last_pc = cpu->Reg[15];
4041#endif 3870#endif
4042#if USER_MODE_OPT 3871 arm_inst * inst_base;
4043 phys_addr = cpu->Reg[15]; 3872 unsigned int lop, rop, dst;
4044#else 3873 unsigned int addr;
4045 { 3874 unsigned int phys_addr;
4046 if (last_logical_base == (cpu->Reg[15] & 0xfffff000)) 3875 unsigned int last_pc = 0;
4047 phys_addr = last_physical_base + (cpu->Reg[15] & 0xfff); 3876 unsigned int num_instrs = 0;
4048 else { 3877 fault_t fault;
4049 /* check next instruction address is valid. */ 3878 static unsigned int last_physical_base = 0, last_logical_base = 0;
4050 fault = check_address_validity(cpu, cpu->Reg[15], &phys_addr, 1, INSN_TLB); 3879 int ptr;
4051 if (fault) { 3880 bool single_step = (cpu->NumInstrsToExecute == 1);
4052 cpu->abortSig = true; 3881
4053 cpu->Aborted = ARMul_PrefetchAbortV; 3882 LOAD_NZCVT;
4054 cpu->AbortAddr = cpu->Reg[15]; 3883 DISPATCH:
4055 cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff; 3884 {
4056 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = cpu->Reg[15]; 3885 if (!cpu->NirqSig) {
4057 goto END; 3886 if (!(cpu->Cpsr & 0x80)) {
4058 } 3887 goto END;
4059 last_logical_base = cpu->Reg[15] & 0xfffff000; 3888 }
4060 last_physical_base = phys_addr & 0xfffff000; 3889 }
4061 } 3890
4062 } 3891 if (cpu->TFlag)
4063#if HYBRID_MODE 3892 cpu->Reg[15] &= 0xfffffffe;
4064 /* check if the native code of dyncom is available */ 3893 else
4065 //fast_map hash_map = core->dyncom_engine->fmap; 3894 cpu->Reg[15] &= 0xfffffffc;
4066 //void * pfunc = NULL; 3895
4067 //PFUNC(phys_addr); 3896 phys_addr = cpu->Reg[15];
4068 //if(pfunc){ 3897
4069 if(is_translated_entry(core, phys_addr)){ 3898 if (find_bb(phys_addr, ptr) == -1)
4070 int rc = JIT_RETURN_NOERR;
4071 //DEBUG_LOG(ARM11, "enter jit icounter is %lld, pc=0x%x\n", core->icounter, cpu->Reg[15]);
4072 SAVE_NZCVT;
4073// resume_timing();
4074 rc = cpu_run(core);
4075 LOAD_NZCVT;
4076 //DEBUG_LOG(ARM11, "out of jit ret is %d icounter is %lld, pc=0x%x\n", rc, core->icounter, cpu->Reg[15]);
4077 if((rc == JIT_RETURN_FUNCNOTFOUND) || (rc == JIT_RETURN_FUNC_BLANK)){
4078 /* keep the tflag same with the bit in CPSR */
4079 //cpu->TFlag = cpu->Cpsr & (1 << THUMB_BIT);
4080 //cpu->TFlag = cpu->Cpsr & (1 << 5);
4081 //switch_mode(cpu, cpu->Cpsr & 0x1f);
4082 //DEBUG_LOG(ARM11, "FUNCTION not found , pc=0x%x\n", cpu->Reg[15]);
4083 fault = check_address_validity(cpu, cpu->Reg[15], &phys_addr, 1, INSN_TLB);
4084 if (fault) {
4085 cpu->abortSig = true;
4086 cpu->Aborted = ARMul_PrefetchAbortV;
4087 cpu->AbortAddr = cpu->Reg[15];
4088 cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff;
4089 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = cpu->Reg[15];
4090 goto END;
4091 }
4092 last_logical_base = cpu->Reg[15] & 0xfffff000;
4093 last_physical_base = phys_addr & 0xfffff000;
4094 core->current_page_phys = last_physical_base;
4095 core->current_page_effec = last_logical_base;
4096 //push_to_compiled(core, phys_addr);
4097 }
4098 else{
4099 if((cpu->CP15[CP15(CP15_TLB_FAULT_STATUS)] & 0xf0)){
4100 //DEBUG_LOG(ARM11, "\n\n###############In %s, fsr=0x%x, fault_addr=0x%x, pc=0x%x\n\n", __FUNCTION__, cpu->CP15[CP15(CP15_FAULT_STATUS)], cpu->CP15[CP15(CP15_FAULT_ADDRESS)], cpu->Reg[15]);
4101 //core->Reg[15] -= get_instr_size(cpu_dyncom);
4102 fill_tlb(cpu);
4103 goto END;
4104 }
4105 if (cpu->syscallSig) {
4106 goto END;
4107 }
4108 if (cpu->abortSig) {
4109 cpu->CP15[CP15_TLB_FAULT_STATUS - CP15_BASE] &= 0xFFFFFFF0;
4110 goto END;
4111 }
4112 if (!cpu->NirqSig) {
4113 if (!(cpu->Cpsr & 0x80)) {
4114 goto END;
4115 }
4116 }
4117
4118 /* if regular trap */
4119 cpu->Reg[15] += GET_INST_SIZE(cpu);
4120 /*uint32_t mode = cpu->Cpsr & 0x1f;
4121 if ((mode != cpu->Mode) && (!is_user_mode(core))) {
4122 switch_mode(cpu, mode);
4123 return 1;
4124 }*/
4125
4126 goto END;
4127 }
4128 //phys_addr = cpu->Reg[15];
4129 }
4130 else{
4131 if (last_logical_base == (cpu->Reg[15] & 0xfffff000))
4132 phys_addr = last_physical_base + (cpu->Reg[15] & 0xfff);
4133 else {
4134 /* check next instruction address is valid. */
4135 fault = check_address_validity(cpu, cpu->Reg[15], &phys_addr, 1, INSN_TLB);
4136 if (fault) {
4137 cpu->abortSig = true;
4138 cpu->Aborted = ARMul_PrefetchAbortV;
4139 cpu->AbortAddr = cpu->Reg[15];
4140 cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)] = fault & 0xff;
4141 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = cpu->Reg[15];
4142 goto END;
4143 }
4144 last_logical_base = cpu->Reg[15] & 0xfffff000;
4145 last_physical_base = phys_addr & 0xfffff000;
4146 }
4147 }
4148#endif /* #if HYBRID_MODE */
4149#endif /* #if USER_MODE_OPT */
4150 if (true){//if(is_fast_interp_code(core, phys_addr)){
4151 if (find_bb(phys_addr, ptr) == -1)
4152 if (InterpreterTranslate(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
4153 goto END;
4154 }
4155 else{
4156 if (InterpreterTranslate(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION) 3899 if (InterpreterTranslate(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
4157 goto END; 3900 goto END;
4158 } 3901
4159#if PROFILE 3902 inst_base = (arm_inst *)&inst_buf[ptr];
4160 resume_timing(); 3903 GOTO_NEXT_INST;
4161#endif 3904 }
4162 inst_base = (arm_inst *)&inst_buf[ptr]; 3905 ADC_INST:
4163 GOTO_NEXT_INST; 3906 {
4164 } 3907 adc_inst *inst_cream = (adc_inst *)inst_base->component;
4165 ADC_INST: 3908 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4166 { 3909 lop = RN;
4167 INC_ICOUNTER; 3910 unsigned int sht_op = SHIFTER_OPERAND;
4168 adc_inst *inst_cream = (adc_inst *)inst_base->component; 3911 rop = SHIFTER_OPERAND + cpu->CFlag;
4169 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 3912 RD = dst = lop + rop;
4170 lop = RN; 3913 if (inst_cream->S && (inst_cream->Rd == 15)) {
4171 unsigned int sht_op = SHIFTER_OPERAND; 3914 if (CurrentModeHasSPSR) {
4172 rop = SHIFTER_OPERAND + cpu->CFlag; 3915 cpu->Cpsr = cpu->Spsr_copy;
4173 RD = dst = lop + rop; 3916 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
4174 if (inst_cream->S && (inst_cream->Rd == 15)) { 3917 LOAD_NZCVT;
4175 /* cpsr = spsr */ 3918 }
4176 if (CurrentModeHasSPSR) { 3919 } else if (inst_cream->S) {
4177 cpu->Cpsr = cpu->Spsr_copy; 3920 UPDATE_NFLAG(dst);
4178 switch_mode(cpu, cpu->Spsr_copy & 0x1f); 3921 UPDATE_ZFLAG(dst);
4179 LOAD_NZCVT; 3922 UPDATE_CFLAG_CARRY_FROM_ADD(lop, sht_op, cpu->CFlag);
4180 } 3923 UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
4181 } else if (inst_cream->S) { 3924 }
4182 UPDATE_NFLAG(dst); 3925 if (inst_cream->Rd == 15) {
4183 UPDATE_ZFLAG(dst); 3926 INC_PC(sizeof(adc_inst));
4184 UPDATE_CFLAG_CARRY_FROM_ADD(lop, sht_op, cpu->CFlag); 3927 goto DISPATCH;
4185 UPDATE_VFLAG((int)dst, (int)lop, (int)rop); 3928 }
4186 } 3929 }
4187 if (inst_cream->Rd == 15) { 3930 cpu->Reg[15] += GET_INST_SIZE(cpu);
4188 INC_PC(sizeof(adc_inst)); 3931 INC_PC(sizeof(adc_inst));
4189 goto DISPATCH; 3932 FETCH_INST;
4190 } 3933 GOTO_NEXT_INST;
4191 } 3934 }
4192 cpu->Reg[15] += GET_INST_SIZE(cpu); 3935 ADD_INST:
4193 INC_PC(sizeof(adc_inst)); 3936 {
4194 FETCH_INST; 3937 add_inst *inst_cream = (add_inst *)inst_base->component;
4195 GOTO_NEXT_INST; 3938 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4196 } 3939 lop = RN;
4197 ADD_INST: 3940 if (inst_cream->Rn == 15) {
4198 { 3941 lop += 2 * GET_INST_SIZE(cpu);
4199 INC_ICOUNTER; 3942 }
4200 add_inst *inst_cream = (add_inst *)inst_base->component; 3943 rop = SHIFTER_OPERAND;
4201 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 3944 RD = dst = lop + rop;
4202 lop = RN; 3945 if (inst_cream->S && (inst_cream->Rd == 15)) {
4203 if (inst_cream->Rn == 15) { 3946 if (CurrentModeHasSPSR) {
4204 lop += 2 * GET_INST_SIZE(cpu); 3947 cpu->Cpsr = cpu->Spsr_copy;
4205 } 3948 switch_mode(cpu, cpu->Cpsr & 0x1f);
4206 rop = SHIFTER_OPERAND; 3949 LOAD_NZCVT;
4207 RD = dst = lop + rop; 3950 }
4208 if (inst_cream->S && (inst_cream->Rd == 15)) { 3951 } else if (inst_cream->S) {
4209 /* cpsr = spsr*/ 3952 UPDATE_NFLAG(dst);
4210 if (CurrentModeHasSPSR) { 3953 UPDATE_ZFLAG(dst);
4211 cpu->Cpsr = cpu->Spsr_copy; 3954 UPDATE_CFLAG(dst, lop, rop);
4212 switch_mode(cpu, cpu->Cpsr & 0x1f); 3955 UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
4213 LOAD_NZCVT; 3956 }
4214 } 3957 if (inst_cream->Rd == 15) {
4215 } else if (inst_cream->S) { 3958 INC_PC(sizeof(add_inst));
4216 UPDATE_NFLAG(dst); 3959 goto DISPATCH;
4217 UPDATE_ZFLAG(dst); 3960 }
4218 UPDATE_CFLAG(dst, lop, rop); 3961 }
4219 UPDATE_VFLAG((int)dst, (int)lop, (int)rop); 3962 cpu->Reg[15] += GET_INST_SIZE(cpu);
4220 } 3963 INC_PC(sizeof(add_inst));
4221 if (inst_cream->Rd == 15) { 3964 FETCH_INST;
4222 INC_PC(sizeof(add_inst)); 3965 GOTO_NEXT_INST;
4223 goto DISPATCH; 3966 }
4224 } 3967 AND_INST:
4225 } 3968 {
4226 cpu->Reg[15] += GET_INST_SIZE(cpu); 3969 and_inst *inst_cream = (and_inst *)inst_base->component;
4227 INC_PC(sizeof(add_inst)); 3970 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4228 FETCH_INST; 3971 lop = RN;
4229 GOTO_NEXT_INST; 3972 rop = SHIFTER_OPERAND;
4230 } 3973 RD = dst = lop & rop;
4231 AND_INST: 3974 if (inst_cream->S && (inst_cream->Rd == 15)) {
4232 { 3975 if (CurrentModeHasSPSR) {
4233 INC_ICOUNTER; 3976 cpu->Cpsr = cpu->Spsr_copy;
4234 and_inst *inst_cream = (and_inst *)inst_base->component; 3977 switch_mode(cpu, cpu->Cpsr & 0x1f);
4235 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 3978 LOAD_NZCVT;
4236 lop = RN; 3979 }
4237 rop = SHIFTER_OPERAND; 3980 } else if (inst_cream->S) {
4238 RD = dst = lop & rop; 3981 UPDATE_NFLAG(dst);
4239 if (inst_cream->S && (inst_cream->Rd == 15)) { 3982 UPDATE_ZFLAG(dst);
4240 /* cpsr = spsr*/ 3983 UPDATE_CFLAG_WITH_SC;
4241 if (CurrentModeHasSPSR) { 3984 }
4242 cpu->Cpsr = cpu->Spsr_copy; 3985 if (inst_cream->Rd == 15) {
4243 switch_mode(cpu, cpu->Cpsr & 0x1f); 3986 INC_PC(sizeof(and_inst));
4244 LOAD_NZCVT; 3987 goto DISPATCH;
4245 } 3988 }
4246 } else if (inst_cream->S) { 3989 }
4247 UPDATE_NFLAG(dst); 3990 cpu->Reg[15] += GET_INST_SIZE(cpu);
4248 UPDATE_ZFLAG(dst); 3991 INC_PC(sizeof(and_inst));
4249 UPDATE_CFLAG_WITH_SC; 3992 FETCH_INST;
4250 //UPDATE_VFLAG((int)dst, (int)lop, (int)rop); 3993 GOTO_NEXT_INST;
4251 } 3994 }
4252 if (inst_cream->Rd == 15) { 3995 BBL_INST:
4253 INC_PC(sizeof(and_inst)); 3996 {
4254 goto DISPATCH; 3997 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4255 } 3998 bbl_inst *inst_cream = (bbl_inst *)inst_base->component;
4256 } 3999 if (inst_cream->L) {
4257 cpu->Reg[15] += GET_INST_SIZE(cpu); 4000 LINK_RTN_ADDR;
4258 INC_PC(sizeof(and_inst)); 4001 }
4259 FETCH_INST; 4002 SET_PC;
4260 GOTO_NEXT_INST; 4003 INC_PC(sizeof(bbl_inst));
4261 } 4004 goto DISPATCH;
4262 BBL_INST: 4005 }
4263 { 4006 cpu->Reg[15] += GET_INST_SIZE(cpu);
4264 INC_ICOUNTER; 4007 INC_PC(sizeof(bbl_inst));
4265 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4008 goto DISPATCH;
4266 bbl_inst *inst_cream = (bbl_inst *)inst_base->component; 4009 }
4267 if (inst_cream->L) { 4010 BIC_INST:
4268 LINK_RTN_ADDR; 4011 {
4269 } 4012 bic_inst *inst_cream = (bic_inst *)inst_base->component;
4270 SET_PC; 4013 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4271 INC_PC(sizeof(bbl_inst)); 4014 lop = RN;
4272 goto DISPATCH; 4015 if (inst_cream->Rn == 15) {
4273 } 4016 lop += 2 * GET_INST_SIZE(cpu);
4274 cpu->Reg[15] += GET_INST_SIZE(cpu); 4017 }
4275 INC_PC(sizeof(bbl_inst)); 4018 rop = SHIFTER_OPERAND;
4276 goto DISPATCH; 4019 RD = dst = lop & (~rop);
4277 } 4020 if ((inst_cream->S) && (inst_cream->Rd == 15)) {
4278 BIC_INST: 4021 if (CurrentModeHasSPSR) {
4279 { 4022 cpu->Cpsr = cpu->Spsr_copy;
4280 INC_ICOUNTER; 4023 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
4281 bic_inst *inst_cream = (bic_inst *)inst_base->component; 4024 LOAD_NZCVT;
4282 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4025 }
4283 lop = RN; 4026 } else if (inst_cream->S) {
4284 if (inst_cream->Rn == 15) { 4027 UPDATE_NFLAG(dst);
4285 lop += 2 * GET_INST_SIZE(cpu); 4028 UPDATE_ZFLAG(dst);
4286 } 4029 UPDATE_CFLAG_WITH_SC;
4287 rop = SHIFTER_OPERAND; 4030 }
4288// RD = dst = lop & (rop ^ 0xffffffff); 4031 if (inst_cream->Rd == 15) {
4289 RD = dst = lop & (~rop); 4032 INC_PC(sizeof(bic_inst));
4290 if ((inst_cream->S) && (inst_cream->Rd == 15)) { 4033 goto DISPATCH;
4291 /* cpsr = spsr */ 4034 }
4292 if (CurrentModeHasSPSR) { 4035 }
4293 cpu->Cpsr = cpu->Spsr_copy; 4036 cpu->Reg[15] += GET_INST_SIZE(cpu);
4294 switch_mode(cpu, cpu->Spsr_copy & 0x1f); 4037 INC_PC(sizeof(bic_inst));
4295 LOAD_NZCVT; 4038 FETCH_INST;
4296 } 4039 GOTO_NEXT_INST;
4297 } else if (inst_cream->S) { 4040 }
4298 UPDATE_NFLAG(dst); 4041 BKPT_INST:
4299 UPDATE_ZFLAG(dst); 4042 BLX_INST:
4300 UPDATE_CFLAG_WITH_SC; 4043 {
4301 } 4044 blx_inst *inst_cream = (blx_inst *)inst_base->component;
4302 if (inst_cream->Rd == 15) { 4045 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4303 INC_PC(sizeof(bic_inst)); 4046 unsigned int inst = inst_cream->inst;
4304 goto DISPATCH; 4047 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
4305 } 4048 cpu->Reg[14] = (cpu->Reg[15] + GET_INST_SIZE(cpu));
4306 } 4049 if(cpu->TFlag)
4307 cpu->Reg[15] += GET_INST_SIZE(cpu); 4050 cpu->Reg[14] |= 0x1;
4308 INC_PC(sizeof(bic_inst)); 4051 cpu->Reg[15] = cpu->Reg[inst_cream->val.Rm] & 0xfffffffe;
4309 FETCH_INST; 4052 cpu->TFlag = cpu->Reg[inst_cream->val.Rm] & 0x1;
4310 GOTO_NEXT_INST; 4053 } else {
4311 } 4054 cpu->Reg[14] = (cpu->Reg[15] + GET_INST_SIZE(cpu));
4312 BKPT_INST: 4055 cpu->TFlag = 0x1;
4313 BLX_INST: 4056 int signed_int = inst_cream->val.signed_immed_24;
4314 { 4057 signed_int = (signed_int) & 0x800000 ? (0x3F000000 | signed_int) : signed_int;
4315 INC_ICOUNTER; 4058 signed_int = signed_int << 2;
4316 blx_inst *inst_cream = (blx_inst *)inst_base->component; 4059 cpu->Reg[15] = cpu->Reg[15] + 8 + signed_int + (BIT(inst, 24) << 1);
4317 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4060 }
4318 unsigned int inst = inst_cream->inst; 4061 INC_PC(sizeof(blx_inst));
4319 if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) { 4062 goto DISPATCH;
4320 //LINK_RTN_ADDR; 4063 }
4321 cpu->Reg[14] = (cpu->Reg[15] + GET_INST_SIZE(cpu)); 4064 cpu->Reg[15] += GET_INST_SIZE(cpu);
4322 if(cpu->TFlag) 4065 INC_PC(sizeof(blx_inst));
4323 cpu->Reg[14] |= 0x1; 4066 goto DISPATCH;
4324 cpu->Reg[15] = cpu->Reg[inst_cream->val.Rm] & 0xfffffffe; 4067 }
4325 cpu->TFlag = cpu->Reg[inst_cream->val.Rm] & 0x1; 4068 BX_INST:
4326 //cpu->Reg[15] = cpu->Reg[BITS(inst, 0, 3)] & 0xfffffffe; 4069 {
4327 //cpu->TFlag = cpu->Reg[BITS(inst, 0, 3)] & 0x1; 4070 bx_inst *inst_cream = (bx_inst *)inst_base->component;
4328 } else { 4071 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4329 cpu->Reg[14] = (cpu->Reg[15] + GET_INST_SIZE(cpu)); 4072 if (inst_cream->Rm == 15)
4330 cpu->TFlag = 0x1; 4073 LOG_WARNING(Core_ARM11, "BX at pc %x: use of Rm = R15 is discouraged", cpu->Reg[15]);
4331 int signed_int = inst_cream->val.signed_immed_24; 4074 cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1;
4332 signed_int = (signed_int) & 0x800000 ? (0x3F000000 | signed_int) : signed_int; 4075 cpu->Reg[15] = cpu->Reg[inst_cream->Rm] & 0xfffffffe;
4333 signed_int = signed_int << 2; 4076 INC_PC(sizeof(bx_inst));
4334 // cpu->Reg[15] = cpu->Reg[15] + 2 * GET_INST_SIZE(cpu) 4077 goto DISPATCH;
4335 cpu->Reg[15] = cpu->Reg[15] + 8 4078 }
4336 + signed_int + (BIT(inst, 24) << 1); 4079 cpu->Reg[15] += GET_INST_SIZE(cpu);
4337 //DEBUG_MSG; 4080 INC_PC(sizeof(bx_inst));
4338 } 4081 goto DISPATCH;
4339 INC_PC(sizeof(blx_inst)); 4082 }
4340 goto DISPATCH; 4083 BXJ_INST:
4341 } 4084 CDP_INST:
4342 cpu->Reg[15] += GET_INST_SIZE(cpu); 4085 {
4343// INC_PC(sizeof(bx_inst)); 4086 cdp_inst *inst_cream = (cdp_inst *)inst_base->component;
4344 INC_PC(sizeof(blx_inst)); 4087 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4345 goto DISPATCH; 4088 // Undefined instruction here
4346 } 4089 cpu->NumInstrsToExecute = 0;
4347 BX_INST: 4090 return num_instrs;
4348 { 4091 }
4349 INC_ICOUNTER; 4092 cpu->Reg[15] += GET_INST_SIZE(cpu);
4350 bx_inst *inst_cream = (bx_inst *)inst_base->component; 4093 INC_PC(sizeof(cdp_inst));
4351 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4094 FETCH_INST;
4352 if (inst_cream->Rm == 15) 4095 GOTO_NEXT_INST;
4353 LOG_WARNING(Core_ARM11, "BX at pc %x: use of Rm = R15 is discouraged", cpu->Reg[15]); 4096 }
4354 cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1; 4097
4355 cpu->Reg[15] = cpu->Reg[inst_cream->Rm] & 0xfffffffe; 4098 CLREX_INST:
4356// cpu->TFlag = cpu->Reg[inst_cream->Rm] & 0x1; 4099 {
4357 INC_PC(sizeof(bx_inst)); 4100 remove_exclusive(cpu, 0);
4358 goto DISPATCH; 4101 cpu->exclusive_state = 0;
4359 } 4102
4360 cpu->Reg[15] += GET_INST_SIZE(cpu); 4103 cpu->Reg[15] += GET_INST_SIZE(cpu);
4361// INC_PC(sizeof(bx_inst)); 4104 INC_PC(sizeof(clrex_inst));
4362 INC_PC(sizeof(bx_inst)); 4105 FETCH_INST;
4363 goto DISPATCH; 4106 GOTO_NEXT_INST;
4364 } 4107 }
4365 BXJ_INST: 4108 CLZ_INST:
4366 CDP_INST: 4109 {
4367 { 4110 clz_inst *inst_cream = (clz_inst *)inst_base->component;
4368 INC_ICOUNTER; 4111 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4369 cdp_inst *inst_cream = (cdp_inst *)inst_base->component; 4112 RD = clz(RM);
4370 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4113 }
4371 /* FIXME, check if cp access allowed */ 4114 cpu->Reg[15] += GET_INST_SIZE(cpu);
4372 #define CP_ACCESS_ALLOW 0 4115 INC_PC(sizeof(clz_inst));
4373 if(CP_ACCESS_ALLOW){ 4116 FETCH_INST;
4374 /* undefined instruction here */ 4117 GOTO_NEXT_INST;
4375 cpu->NumInstrsToExecute = 0; 4118 }
4376 return num_instrs; 4119 CMN_INST:
4377 } 4120 {
4378 LOG_ERROR(Core_ARM11, "CDP insn inst=0x%x, pc=0x%x\n", inst_cream->inst, cpu->Reg[15]); 4121 cmn_inst *inst_cream = (cmn_inst *)inst_base->component;
4379 unsigned cpab = (cpu->CDP[inst_cream->cp_num]) (cpu, ARMul_FIRST, inst_cream->inst); 4122 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4380 if(cpab != ARMul_DONE){ 4123 lop = RN;
4381 LOG_ERROR(Core_ARM11, "CDP insn wrong, inst=0x%x, cp_num=0x%x\n", inst_cream->inst, inst_cream->cp_num); 4124 rop = SHIFTER_OPERAND;
4382 //CITRA_IGNORE_EXIT(-1); 4125 dst = lop + rop;
4383 } 4126 UPDATE_NFLAG(dst);
4384 } 4127 UPDATE_ZFLAG(dst);
4385 cpu->Reg[15] += GET_INST_SIZE(cpu); 4128 UPDATE_CFLAG(dst, lop, rop);
4386 INC_PC(sizeof(cdp_inst)); 4129 UPDATE_VFLAG((int)dst, (int)lop, (int)rop);
4387 FETCH_INST; 4130 }
4388 GOTO_NEXT_INST; 4131 cpu->Reg[15] += GET_INST_SIZE(cpu);
4389 } 4132 INC_PC(sizeof(cmn_inst));
4390 4133 FETCH_INST;
4391 CLREX_INST: 4134 GOTO_NEXT_INST;
4392 { 4135 }
4393 INC_ICOUNTER; 4136 CMP_INST:
4394 remove_exclusive(cpu, 0); 4137 {
4395 cpu->exclusive_state = 0; 4138 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4396 4139 cmp_inst *inst_cream = (cmp_inst *)inst_base->component;
4397 cpu->Reg[15] += GET_INST_SIZE(cpu); 4140 lop = RN;
4398 INC_PC(sizeof(clrex_inst)); 4141 if (inst_cream->Rn == 15) {
4399 FETCH_INST; 4142 lop += 2 * GET_INST_SIZE(cpu);
4400 GOTO_NEXT_INST; 4143 }
4401 } 4144 rop = SHIFTER_OPERAND;
4402 CLZ_INST: 4145 dst = lop - rop;
4403 { 4146
4404 INC_ICOUNTER; 4147 UPDATE_NFLAG(dst);
4405 clz_inst *inst_cream = (clz_inst *)inst_base->component; 4148 UPDATE_ZFLAG(dst);
4406 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4149 UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop);
4407 RD = clz(RM); 4150 UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop);
4408 } 4151 }
4409 cpu->Reg[15] += GET_INST_SIZE(cpu); 4152 cpu->Reg[15] += GET_INST_SIZE(cpu);
4410 INC_PC(sizeof(clz_inst)); 4153 INC_PC(sizeof(cmp_inst));
4411 FETCH_INST; 4154 FETCH_INST;
4412 GOTO_NEXT_INST; 4155 GOTO_NEXT_INST;
4413 } 4156 }
4414 CMN_INST: 4157 CPS_INST:
4415 { 4158 {
4416 INC_ICOUNTER; 4159 cps_inst *inst_cream = (cps_inst *)inst_base->component;
4417 cmn_inst *inst_cream = (cmn_inst *)inst_base->component; 4160 uint32_t aif_val = 0;
4418 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4161 uint32_t aif_mask = 0;
4419// DEBUG_LOG(ARM11, "RN is %x\n", RN); 4162 if (InAPrivilegedMode(cpu)) {
4420 lop = RN; 4163 if (inst_cream->imod1) {
4421 rop = SHIFTER_OPERAND; 4164 if (inst_cream->A) {
4422 dst = lop + rop; 4165 aif_val |= (inst_cream->imod0 << 8);
4423 UPDATE_NFLAG(dst); 4166 aif_mask |= 1 << 8;
4424 UPDATE_ZFLAG(dst); 4167 }
4425 UPDATE_CFLAG(dst, lop, rop); 4168 if (inst_cream->I) {
4426 UPDATE_VFLAG((int)dst, (int)lop, (int)rop); 4169 aif_val |= (inst_cream->imod0 << 7);
4427 } 4170 aif_mask |= 1 << 7;
4428 cpu->Reg[15] += GET_INST_SIZE(cpu); 4171 }
4429 INC_PC(sizeof(cmn_inst)); 4172 if (inst_cream->F) {
4430 FETCH_INST; 4173 aif_val |= (inst_cream->imod0 << 6);
4431 GOTO_NEXT_INST; 4174 aif_mask |= 1 << 6;
4432 } 4175 }
4433 CMP_INST: 4176 aif_mask = ~aif_mask;
4434 { 4177 cpu->Cpsr = (cpu->Cpsr & aif_mask) | aif_val;
4435// DEBUG_LOG(ARM11, "cmp inst\n"); 4178 }
4436// DEBUG_LOG(ARM11, "pc: %x\n", cpu->Reg[15]); 4179 if (inst_cream->mmod) {
4437 INC_ICOUNTER; 4180 cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode;
4438 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4181 switch_mode(cpu, inst_cream->mode);
4439// DEBUG_LOG(ARM11, "r0 is %x\n", cpu->Reg[0]); 4182 }
4440 cmp_inst *inst_cream = (cmp_inst *)inst_base->component; 4183 }
4441 lop = RN; 4184 cpu->Reg[15] += GET_INST_SIZE(cpu);
4442 if (inst_cream->Rn == 15) { 4185 INC_PC(sizeof(cps_inst));
4443 lop += 2 * GET_INST_SIZE(cpu); 4186 FETCH_INST;
4444 } 4187 GOTO_NEXT_INST;
4445 rop = SHIFTER_OPERAND; 4188 }
4446 dst = lop - rop; 4189 CPY_INST:
4447 4190 {
4448 UPDATE_NFLAG(dst); 4191 mov_inst *inst_cream = (mov_inst *)inst_base->component;
4449 UPDATE_ZFLAG(dst); 4192 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4450// UPDATE_CFLAG(dst, lop, rop); 4193 RD = SHIFTER_OPERAND;
4451 UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop); 4194 if ((inst_cream->Rd == 15)) {
4452// UPDATE_VFLAG((int)dst, (int)lop, (int)rop); 4195 INC_PC(sizeof(mov_inst));
4453 UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop); 4196 goto DISPATCH;
4454// UPDATE_VFLAG_WITH_NOT(dst, lop, rop); 4197 }
4455 } 4198 }
4456 cpu->Reg[15] += GET_INST_SIZE(cpu); 4199 cpu->Reg[15] += GET_INST_SIZE(cpu);
4457 INC_PC(sizeof(cmp_inst)); 4200 INC_PC(sizeof(mov_inst));
4458 FETCH_INST; 4201 FETCH_INST;
4459 GOTO_NEXT_INST; 4202 GOTO_NEXT_INST;
4460 } 4203 }
4461 CPS_INST: 4204 EOR_INST:
4462 { 4205 {
4463 INC_ICOUNTER; 4206 eor_inst *inst_cream = (eor_inst *)inst_base->component;
4464 cps_inst *inst_cream = (cps_inst *)inst_base->component; 4207 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4465 uint32_t aif_val = 0; 4208 lop = RN;
4466 uint32_t aif_mask = 0; 4209 if (inst_cream->Rn == 15) {
4467 if (InAPrivilegedMode(cpu)) { 4210 lop += 2 * GET_INST_SIZE(cpu);
4468 /* isInAPrivilegedMode */ 4211 }
4469 if (inst_cream->imod1) { 4212 rop = SHIFTER_OPERAND;
4470 if (inst_cream->A) { 4213 RD = dst = lop ^ rop;
4471 aif_val |= (inst_cream->imod0 << 8); 4214 if (inst_cream->S && (inst_cream->Rd == 15)) {
4472 aif_mask |= 1 << 8; 4215 if (CurrentModeHasSPSR) {
4473 } 4216 cpu->Cpsr = cpu->Spsr_copy;
4474 if (inst_cream->I) { 4217 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
4475 aif_val |= (inst_cream->imod0 << 7); 4218 LOAD_NZCVT;
4476 aif_mask |= 1 << 7; 4219 }
4477 } 4220 } else if (inst_cream->S) {
4478 if (inst_cream->F) { 4221 UPDATE_NFLAG(dst);
4479 aif_val |= (inst_cream->imod0 << 6); 4222 UPDATE_ZFLAG(dst);
4480 aif_mask |= 1 << 6; 4223 UPDATE_CFLAG_WITH_SC;
4481 } 4224 }
4482 aif_mask = ~aif_mask; 4225 if (inst_cream->Rd == 15) {
4483 cpu->Cpsr = (cpu->Cpsr & aif_mask) | aif_val; 4226 INC_PC(sizeof(eor_inst));
4484 } 4227 goto DISPATCH;
4485 if (inst_cream->mmod) { 4228 }
4486 cpu->Cpsr = (cpu->Cpsr & 0xffffffe0) | inst_cream->mode; 4229 }
4487 switch_mode(cpu, inst_cream->mode); 4230 cpu->Reg[15] += GET_INST_SIZE(cpu);
4488 } 4231 INC_PC(sizeof(eor_inst));
4489 } 4232 FETCH_INST;
4490 cpu->Reg[15] += GET_INST_SIZE(cpu); 4233 GOTO_NEXT_INST;
4491 INC_PC(sizeof(cps_inst)); 4234 }
4492 FETCH_INST; 4235 LDC_INST:
4493 GOTO_NEXT_INST; 4236 {
4494 } 4237 // Instruction not implemented
4495 CPY_INST: 4238 //LOG_CRITICAL(Core_ARM11, "unimplemented instruction");
4496 { 4239 cpu->Reg[15] += GET_INST_SIZE(cpu);
4497 INC_ICOUNTER; 4240 INC_PC(sizeof(ldc_inst));
4498 mov_inst *inst_cream = (mov_inst *)inst_base->component; 4241 FETCH_INST;
4499// cpy_inst *inst_cream = (cpy_inst *)inst_base->component; 4242 GOTO_NEXT_INST;
4500 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4243 }
4501 RD = SHIFTER_OPERAND; 4244 LDM_INST:
4502// RD = RM; 4245 {
4503 if ((inst_cream->Rd == 15)) { 4246 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4504 INC_PC(sizeof(mov_inst)); 4247 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4505 goto DISPATCH; 4248 int i;
4506 } 4249 unsigned int ret;
4507 } 4250 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4508// DEBUG_LOG(ARM11, "cpy inst %x\n", cpu->Reg[15]); 4251 if (fault) {
4509 cpu->Reg[15] += GET_INST_SIZE(cpu); 4252 goto MMU_EXCEPTION;
4510 INC_PC(sizeof(mov_inst)); 4253 }
4511 FETCH_INST; 4254 unsigned int inst = inst_cream->inst;
4512 GOTO_NEXT_INST; 4255 if (BIT(inst, 22) && !BIT(inst, 15)) {
4513 } 4256 for (i = 0; i < 13; i++) {
4514 EOR_INST: 4257 if(BIT(inst, i)){
4515 { 4258 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4516 INC_ICOUNTER; 4259 cpu->Reg[i] = ret;
4517 eor_inst *inst_cream = (eor_inst *)inst_base->component; 4260 addr += 4;
4518 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4261 if ((addr & 0xfff) == 0) {
4519 lop = RN; 4262 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4520 if (inst_cream->Rn == 15) { 4263 } else {
4521 lop += 2 * GET_INST_SIZE(cpu); 4264 phys_addr += 4;
4522 } 4265 }
4523 rop = SHIFTER_OPERAND; 4266 }
4524 RD = dst = lop ^ rop; 4267 }
4525 if (inst_cream->S && (inst_cream->Rd == 15)) { 4268 if (BIT(inst, 13)) {
4526 /* cpsr = spsr*/ 4269 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4527 if (CurrentModeHasSPSR) { 4270
4528 cpu->Cpsr = cpu->Spsr_copy; 4271 if (cpu->Mode == USER32MODE)
4529 switch_mode(cpu, cpu->Spsr_copy & 0x1f); 4272 cpu->Reg[13] = ret;
4530 LOAD_NZCVT; 4273 else
4531 } 4274 cpu->Reg_usr[0] = ret;
4532 } else if (inst_cream->S) { 4275 addr += 4;
4533 UPDATE_NFLAG(dst); 4276 if ((addr & 0xfff) == 0) {
4534 UPDATE_ZFLAG(dst); 4277 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4535 UPDATE_CFLAG_WITH_SC; 4278 } else {
4536// UPDATE_CFLAG(dst, lop, rop); 4279 phys_addr += 4;
4537// UPDATE_VFLAG((int)dst, (int)lop, (int)rop); 4280 }
4538 } 4281 }
4539 if (inst_cream->Rd == 15) { 4282 if (BIT(inst, 14)) {
4540 INC_PC(sizeof(eor_inst)); 4283 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4541 goto DISPATCH; 4284
4542 } 4285 if (cpu->Mode == USER32MODE)
4543 } 4286 cpu->Reg[14] = ret;
4544 cpu->Reg[15] += GET_INST_SIZE(cpu); 4287 else
4545 INC_PC(sizeof(eor_inst)); 4288 cpu->Reg_usr[1] = ret;
4546 FETCH_INST; 4289 }
4547 GOTO_NEXT_INST; 4290 } else if (!BIT(inst, 22)) {
4548 } 4291 for( i = 0; i < 16; i ++ ){
4549 LDC_INST: 4292 if(BIT(inst, i)){
4550 { 4293 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4551 INC_ICOUNTER; 4294 if (fault) goto MMU_EXCEPTION;
4552 /* NOT IMPL */ 4295
4553 cpu->Reg[15] += GET_INST_SIZE(cpu); 4296 // For armv5t, should enter thumb when bits[0] is non-zero.
4554 INC_PC(sizeof(ldc_inst)); 4297 if(i == 15){
4555 FETCH_INST; 4298 cpu->TFlag = ret & 0x1;
4556 GOTO_NEXT_INST; 4299 ret &= 0xFFFFFFFE;
4557 }
4558 LDM_INST:
4559 {
4560 INC_ICOUNTER;
4561 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4562 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4563 int i;
4564 unsigned int ret;
4565 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4566 if (fault) {
4567 goto MMU_EXCEPTION;
4568 }
4569 unsigned int inst = inst_cream->inst;
4570 if (BIT(inst, 22) && !BIT(inst, 15)) {
4571// DEBUG_MSG;
4572 #if 1
4573 /* LDM (2) user */
4574 for (i = 0; i < 13; i++) {
4575 if(BIT(inst, i)){
4576 #if 0
4577 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4578 if (fault) {
4579 goto MMU_EXCEPTION;
4580 }
4581 #endif
4582 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4583 //if (fault) goto MMU_EXCEPTION;
4584 cpu->Reg[i] = ret;
4585 addr += 4;
4586 if ((addr & 0xfff) == 0) {
4587 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4588 } else {
4589 phys_addr += 4;
4590 }
4591 }
4592 }
4593 if (BIT(inst, 13)) {
4594 #if 0
4595 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4596 if (fault) {
4597 goto MMU_EXCEPTION;
4598 }
4599 #endif
4600 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4601 //if (fault) goto MMU_EXCEPTION;
4602 if (cpu->Mode == USER32MODE)
4603 cpu->Reg[13] = ret;
4604 else
4605 cpu->Reg_usr[0] = ret;
4606 addr += 4;
4607 if ((addr & 0xfff) == 0) {
4608 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4609 } else {
4610 phys_addr += 4;
4611 }
4612 }
4613 if (BIT(inst, 14)) {
4614 #if 0
4615 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4616 if (fault) {
4617 goto MMU_EXCEPTION;
4618 }
4619 #endif
4620 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4621 //if (fault) goto MMU_EXCEPTION;
4622 if (cpu->Mode == USER32MODE)
4623 cpu->Reg[14] = ret;
4624 else
4625 cpu->Reg_usr[1] = ret;
4626 }
4627 #endif
4628 } else if (!BIT(inst, 22)) {
4629 for( i = 0; i < 16; i ++ ){
4630 if(BIT(inst, i)){
4631 //bus_read(32, addr, &ret);
4632 #if 0
4633 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4634 if (fault) {
4635 goto MMU_EXCEPTION;
4636 }
4637 #endif
4638 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4639 if (fault) goto MMU_EXCEPTION;
4640 /* For armv5t, should enter thumb when bits[0] is non-zero. */
4641 if(i == 15){
4642 cpu->TFlag = ret & 0x1;
4643 ret &= 0xFFFFFFFE;
4644 //DEBUG_LOG(ARM11, "In %s, TFlag ret=0x%x\n", __FUNCTION__, ret);
4645 }
4646
4647 cpu->Reg[i] = ret;
4648 addr += 4;
4649 if ((addr & 0xfff) == 0) {
4650 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4651 } else {
4652 phys_addr += 4;
4653 }
4654 }
4655 }
4656 } else if (BIT(inst, 22) && BIT(inst, 15)) {
4657 for( i = 0; i < 15; i ++ ){
4658 if(BIT(inst, i)){
4659 #if 0
4660 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4661 if (fault) {
4662 goto MMU_EXCEPTION;
4663 }
4664 #endif
4665 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4666 //if (fault) goto MMU_EXCEPTION;
4667 cpu->Reg[i] = ret;
4668 addr += 4;
4669 if ((addr & 0xfff) == 0) {
4670 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4671 } else {
4672 phys_addr += 4;
4673 }
4674 }
4675 }
4676
4677 if (CurrentModeHasSPSR) {
4678 cpu->Cpsr = cpu->Spsr_copy;
4679 switch_mode(cpu, cpu->Cpsr & 0x1f);
4680 LOAD_NZCVT;
4681 }
4682 #if 0
4683 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4684 if (fault) {
4685 goto MMU_EXCEPTION;
4686 }
4687 #endif
4688 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4689 if (fault) {
4690 goto MMU_EXCEPTION;
4691 }
4692 cpu->Reg[15] = ret;
4693 #if 0
4694 addr += 4;
4695 phys_addr += 4;
4696 #endif
4697 }
4698 if (BIT(inst, 15)) {
4699 INC_PC(sizeof(ldst_inst));
4700 goto DISPATCH;
4701 }
4702 }
4703 cpu->Reg[15] += GET_INST_SIZE(cpu);
4704 INC_PC(sizeof(ldst_inst));
4705 FETCH_INST;
4706 GOTO_NEXT_INST;
4707 }
4708 SXTH_INST:
4709 {
4710 INC_ICOUNTER;
4711 sxth_inst *inst_cream = (sxth_inst *)inst_base->component;
4712 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4713 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
4714 if (BIT(operand2, 15)) {
4715 operand2 |= 0xffff0000;
4716 } else {
4717 operand2 &= 0xffff;
4718 }
4719 RD = operand2;
4720 }
4721 cpu->Reg[15] += GET_INST_SIZE(cpu);
4722 INC_PC(sizeof(sxth_inst));
4723 FETCH_INST;
4724 GOTO_NEXT_INST;
4725 }
4726 LDR_INST:
4727 {
4728 INC_ICOUNTER;
4729 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4730 //if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4731 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4732 if (fault) goto MMU_EXCEPTION;
4733 unsigned int value;
4734 //bus_read(32, addr, &value);
4735 fault = interpreter_read_memory(addr, phys_addr, value, 32);
4736 if (BIT(CP15_REG(CP15_CONTROL), 22) == 1)
4737 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4738 else {
4739 value = ROTATE_RIGHT_32(value,(8*(addr&0x3)));
4740 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4741 }
4742 if (BITS(inst_cream->inst, 12, 15) == 15) {
4743 /* For armv5t, should enter thumb when bits[0] is non-zero. */
4744 cpu->TFlag = value & 0x1;
4745 cpu->Reg[15] &= 0xFFFFFFFE;
4746 INC_PC(sizeof(ldst_inst));
4747 goto DISPATCH;
4748 }
4749 //}
4750 cpu->Reg[15] += GET_INST_SIZE(cpu);
4751 INC_PC(sizeof(ldst_inst));
4752 FETCH_INST;
4753 GOTO_NEXT_INST;
4754 }
4755 LDRCOND_INST:
4756 {
4757 INC_ICOUNTER;
4758 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4759 if (CondPassed(cpu, inst_base->cond)) {
4760 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4761 if (fault) goto MMU_EXCEPTION;
4762 unsigned int value;
4763 //bus_read(32, addr, &value);
4764 fault = interpreter_read_memory(addr, phys_addr, value, 32);
4765 if (BIT(CP15_REG(CP15_CONTROL), 22) == 1)
4766 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4767 else {
4768 value = ROTATE_RIGHT_32(value,(8*(addr&0x3)));
4769 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4770 } 4300 }
4771 4301
4772 if (BITS(inst_cream->inst, 12, 15) == 15) { 4302 cpu->Reg[i] = ret;
4773 /* For armv5t, should enter thumb when bits[0] is non-zero. */ 4303 addr += 4;
4774 cpu->TFlag = value & 0x1; 4304 if ((addr & 0xfff) == 0) {
4775 cpu->Reg[15] &= 0xFFFFFFFE; 4305 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4776 INC_PC(sizeof(ldst_inst)); 4306 } else {
4777 goto DISPATCH; 4307 phys_addr += 4;
4778 } 4308 }
4779 } 4309 }
4780 cpu->Reg[15] += GET_INST_SIZE(cpu); 4310 }
4781 INC_PC(sizeof(ldst_inst)); 4311 } else if (BIT(inst, 22) && BIT(inst, 15)) {
4782 FETCH_INST; 4312 for( i = 0; i < 15; i ++ ){
4783 GOTO_NEXT_INST; 4313 if(BIT(inst, i)){
4784 } 4314 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4785 UXTH_INST: 4315 cpu->Reg[i] = ret;
4786 { 4316 addr += 4;
4787 INC_ICOUNTER; 4317 if ((addr & 0xfff) == 0) {
4788 uxth_inst *inst_cream = (uxth_inst *)inst_base->component; 4318 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4789 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4319 } else {
4790 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) 4320 phys_addr += 4;
4791 & 0xffff; 4321 }
4792 RD = operand2; 4322 }
4793 } 4323 }
4794 cpu->Reg[15] += GET_INST_SIZE(cpu); 4324
4795 INC_PC(sizeof(uxth_inst)); 4325 if (CurrentModeHasSPSR) {
4796 FETCH_INST; 4326 cpu->Cpsr = cpu->Spsr_copy;
4797 GOTO_NEXT_INST; 4327 switch_mode(cpu, cpu->Cpsr & 0x1f);
4798 } 4328 LOAD_NZCVT;
4799 UXTAH_INST: 4329 }
4800 { 4330
4801 INC_ICOUNTER; 4331 fault = interpreter_read_memory(addr, phys_addr, ret, 32);
4802 uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component; 4332 if (fault) {
4803 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4333 goto MMU_EXCEPTION;
4804 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) 4334 }
4805 & 0xffff; 4335 cpu->Reg[15] = ret;
4806 RD = RN + operand2; 4336 }
4807 if (inst_cream->Rn == 15 || inst_cream->Rm == 15) { 4337 if (BIT(inst, 15)) {
4808 LOG_ERROR(Core_ARM11, "invalid operands for UXTAH"); 4338 INC_PC(sizeof(ldst_inst));
4809 CITRA_IGNORE_EXIT(-1); 4339 goto DISPATCH;
4810 } 4340 }
4811 } 4341 }
4812 cpu->Reg[15] += GET_INST_SIZE(cpu); 4342 cpu->Reg[15] += GET_INST_SIZE(cpu);
4813 INC_PC(sizeof(uxtah_inst)); 4343 INC_PC(sizeof(ldst_inst));
4814 FETCH_INST; 4344 FETCH_INST;
4815 GOTO_NEXT_INST; 4345 GOTO_NEXT_INST;
4816 } 4346 }
4817 LDRB_INST: 4347 SXTH_INST:
4818 { 4348 {
4819 INC_ICOUNTER; 4349 sxth_inst *inst_cream = (sxth_inst *)inst_base->component;
4820 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4350 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4821 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4351 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
4822 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); 4352 if (BIT(operand2, 15)) {
4823 if (fault) goto MMU_EXCEPTION; 4353 operand2 |= 0xffff0000;
4824 unsigned int value; 4354 } else {
4825 fault = interpreter_read_memory(addr, phys_addr, value, 8); 4355 operand2 &= 0xffff;
4826 if (fault) goto MMU_EXCEPTION; 4356 }
4827 //bus_read(8, addr, &value); 4357 RD = operand2;
4828 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4358 }
4829 if (BITS(inst_cream->inst, 12, 15) == 15) { 4359 cpu->Reg[15] += GET_INST_SIZE(cpu);
4830 INC_PC(sizeof(ldst_inst)); 4360 INC_PC(sizeof(sxth_inst));
4831 goto DISPATCH; 4361 FETCH_INST;
4832 } 4362 GOTO_NEXT_INST;
4833 } 4363 }
4834 cpu->Reg[15] += GET_INST_SIZE(cpu); 4364 LDR_INST:
4835 INC_PC(sizeof(ldst_inst)); 4365 {
4836 FETCH_INST; 4366 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4837 GOTO_NEXT_INST; 4367 //if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4838 } 4368 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4839 LDRBT_INST: 4369 if (fault) goto MMU_EXCEPTION;
4840 { 4370 unsigned int value;
4841 INC_ICOUNTER; 4371 fault = interpreter_read_memory(addr, phys_addr, value, 32);
4842 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4372 if (BIT(CP15_REG(CP15_CONTROL), 22) == 1)
4843 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4373 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4844 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); 4374 else {
4845 if (fault) goto MMU_EXCEPTION; 4375 value = ROTATE_RIGHT_32(value,(8*(addr&0x3)));
4846 unsigned int value; 4376 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4847 fault = interpreter_read_memory(addr, phys_addr, value, 8); 4377 }
4848 if (fault) goto MMU_EXCEPTION; 4378 if (BITS(inst_cream->inst, 12, 15) == 15) {
4849 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4379 // For armv5t, should enter thumb when bits[0] is non-zero.
4850 if (BITS(inst_cream->inst, 12, 15) == 15) { 4380 cpu->TFlag = value & 0x1;
4851 INC_PC(sizeof(ldst_inst)); 4381 cpu->Reg[15] &= 0xFFFFFFFE;
4852 goto DISPATCH; 4382 INC_PC(sizeof(ldst_inst));
4853 } 4383 goto DISPATCH;
4854 } 4384 }
4855 cpu->Reg[15] += GET_INST_SIZE(cpu); 4385 //}
4856 INC_PC(sizeof(ldst_inst)); 4386 cpu->Reg[15] += GET_INST_SIZE(cpu);
4857 FETCH_INST; 4387 INC_PC(sizeof(ldst_inst));
4858 GOTO_NEXT_INST; 4388 FETCH_INST;
4859 } 4389 GOTO_NEXT_INST;
4860 LDRD_INST: 4390 }
4861 { 4391 LDRCOND_INST:
4862 INC_ICOUNTER; 4392 {
4863 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4393 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4864 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4394 if (CondPassed(cpu, inst_base->cond)) {
4865 /* Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0) */ 4395 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4866 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); 4396 if (fault) goto MMU_EXCEPTION;
4867 if (fault) goto MMU_EXCEPTION; 4397 unsigned int value;
4868 uint32_t rear_phys_addr; 4398 fault = interpreter_read_memory(addr, phys_addr, value, 32);
4869 fault = check_address_validity(cpu, addr + 4, &rear_phys_addr, 1); 4399 if (BIT(CP15_REG(CP15_CONTROL), 22) == 1)
4870 if(fault){ 4400 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4871 LOG_ERROR(Core_ARM11, "mmu fault , should rollback the above get_addr\n"); 4401 else {
4872 CITRA_IGNORE_EXIT(-1); 4402 value = ROTATE_RIGHT_32(value,(8*(addr&0x3)));
4873 goto MMU_EXCEPTION; 4403 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4874 } 4404 }
4875 unsigned int value; 4405
4876 fault = interpreter_read_memory(addr, phys_addr, value, 32); 4406 if (BITS(inst_cream->inst, 12, 15) == 15) {
4877 if (fault) goto MMU_EXCEPTION; 4407 // For armv5t, should enter thumb when bits[0] is non-zero.
4878 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4408 cpu->TFlag = value & 0x1;
4879 fault = interpreter_read_memory(addr + 4, rear_phys_addr, value, 32); 4409 cpu->Reg[15] &= 0xFFFFFFFE;
4880 if (fault) goto MMU_EXCEPTION; 4410 INC_PC(sizeof(ldst_inst));
4881 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = value; 4411 goto DISPATCH;
4882 /* No dispatch since this operation should not modify R15 */ 4412 }
4883 } 4413 }
4884 cpu->Reg[15] += 4; 4414 cpu->Reg[15] += GET_INST_SIZE(cpu);
4885 INC_PC(sizeof(ldst_inst)); 4415 INC_PC(sizeof(ldst_inst));
4886 FETCH_INST; 4416 FETCH_INST;
4887 GOTO_NEXT_INST; 4417 GOTO_NEXT_INST;
4888 } 4418 }
4889 4419 UXTH_INST:
4890 LDREX_INST: 4420 {
4891 { 4421 uxth_inst *inst_cream = (uxth_inst *)inst_base->component;
4892 INC_ICOUNTER; 4422 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4893 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4423 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate)
4894 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4424 & 0xffff;
4895 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; 4425 RD = operand2;
4896 fault = check_address_validity(cpu, addr, &phys_addr, 1); 4426 }
4897 if (fault) goto MMU_EXCEPTION; 4427 cpu->Reg[15] += GET_INST_SIZE(cpu);
4898 unsigned int value; 4428 INC_PC(sizeof(uxth_inst));
4899 fault = interpreter_read_memory(addr, phys_addr, value, 32); 4429 FETCH_INST;
4900 if (fault) goto MMU_EXCEPTION; 4430 GOTO_NEXT_INST;
4901 4431 }
4902 add_exclusive_addr(cpu, phys_addr); 4432 UXTAH_INST:
4903 cpu->exclusive_state = 1; 4433 {
4904 4434 uxtah_inst *inst_cream = (uxtah_inst *)inst_base->component;
4905 //bus_read(32, addr, &value); 4435 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4906 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4436 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate)
4907 if (BITS(inst_cream->inst, 12, 15) == 15) { 4437 & 0xffff;
4908 INC_PC(sizeof(ldst_inst)); 4438 RD = RN + operand2;
4909 goto DISPATCH; 4439 if (inst_cream->Rn == 15 || inst_cream->Rm == 15) {
4910 } 4440 LOG_ERROR(Core_ARM11, "invalid operands for UXTAH");
4911 } 4441 CITRA_IGNORE_EXIT(-1);
4912 cpu->Reg[15] += GET_INST_SIZE(cpu); 4442 }
4913 INC_PC(sizeof(ldst_inst)); 4443 }
4914 FETCH_INST; 4444 cpu->Reg[15] += GET_INST_SIZE(cpu);
4915 GOTO_NEXT_INST; 4445 INC_PC(sizeof(uxtah_inst));
4916 } 4446 FETCH_INST;
4917 LDREXB_INST: 4447 GOTO_NEXT_INST;
4918 { 4448 }
4919 INC_ICOUNTER; 4449 LDRB_INST:
4920 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4450 {
4921 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4451 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4922 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; 4452 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4923 fault = check_address_validity(cpu, addr, &phys_addr, 1); 4453 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4924 if (fault) goto MMU_EXCEPTION; 4454 if (fault) goto MMU_EXCEPTION;
4925 unsigned int value; 4455 unsigned int value;
4926 fault = interpreter_read_memory(addr, phys_addr, value, 8); 4456 fault = interpreter_read_memory(addr, phys_addr, value, 8);
4927 if (fault) goto MMU_EXCEPTION; 4457 if (fault) goto MMU_EXCEPTION;
4928 4458 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4929 add_exclusive_addr(cpu, phys_addr); 4459 if (BITS(inst_cream->inst, 12, 15) == 15) {
4930 cpu->exclusive_state = 1; 4460 INC_PC(sizeof(ldst_inst));
4931 4461 goto DISPATCH;
4932 //bus_read(8, addr, &value); 4462 }
4933 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4463 }
4934 if (BITS(inst_cream->inst, 12, 15) == 15) { 4464 cpu->Reg[15] += GET_INST_SIZE(cpu);
4935 INC_PC(sizeof(ldst_inst)); 4465 INC_PC(sizeof(ldst_inst));
4936 goto DISPATCH; 4466 FETCH_INST;
4937 } 4467 GOTO_NEXT_INST;
4938 } 4468 }
4939 cpu->Reg[15] += GET_INST_SIZE(cpu); 4469 LDRBT_INST:
4940 INC_PC(sizeof(ldst_inst)); 4470 {
4941 FETCH_INST; 4471 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4942 GOTO_NEXT_INST; 4472 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4943 } 4473 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4944 LDRH_INST: 4474 if (fault) goto MMU_EXCEPTION;
4945 { 4475 unsigned int value;
4946 INC_ICOUNTER; 4476 fault = interpreter_read_memory(addr, phys_addr, value, 8);
4947 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4477 if (fault) goto MMU_EXCEPTION;
4948 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4478 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4949 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); 4479 if (BITS(inst_cream->inst, 12, 15) == 15) {
4950 if (fault) goto MMU_EXCEPTION; 4480 INC_PC(sizeof(ldst_inst));
4951 unsigned int value = 0; 4481 goto DISPATCH;
4952 fault = interpreter_read_memory(addr, phys_addr, value, 16); 4482 }
4953// fault = interpreter_read_memory(addr, value, 32); 4483 }
4954 if (fault) goto MMU_EXCEPTION; 4484 cpu->Reg[15] += GET_INST_SIZE(cpu);
4955 //if (value == 0xffff && cpu->icounter > 190000000 && cpu->icounter < 210000000) { 4485 INC_PC(sizeof(ldst_inst));
4956 // value = 0xffffffff; 4486 FETCH_INST;
4957 //} 4487 GOTO_NEXT_INST;
4958 //bus_read(16, addr, &value); 4488 }
4959// cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value & 0xffff; 4489 LDRD_INST:
4960 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4490 {
4961 if (BITS(inst_cream->inst, 12, 15) == 15) { 4491 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4962 INC_PC(sizeof(ldst_inst)); 4492 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4963 goto DISPATCH; 4493 // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0)
4964 } 4494 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
4965 } 4495 if (fault) goto MMU_EXCEPTION;
4966 cpu->Reg[15] += GET_INST_SIZE(cpu); 4496 uint32_t rear_phys_addr;
4967 INC_PC(sizeof(ldst_inst)); 4497 fault = check_address_validity(cpu, addr + 4, &rear_phys_addr, 1);
4968 FETCH_INST; 4498 if(fault){
4969 GOTO_NEXT_INST; 4499 LOG_ERROR(Core_ARM11, "MMU fault , should rollback the above get_addr\n");
4970 } 4500 CITRA_IGNORE_EXIT(-1);
4971 LDRSB_INST: 4501 goto MMU_EXCEPTION;
4972 { 4502 }
4973 INC_ICOUNTER; 4503 unsigned int value;
4974 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4504 fault = interpreter_read_memory(addr, phys_addr, value, 32);
4975 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4505 if (fault) goto MMU_EXCEPTION;
4976 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); 4506 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
4977 if (fault) goto MMU_EXCEPTION; 4507 fault = interpreter_read_memory(addr + 4, rear_phys_addr, value, 32);
4978 unsigned int value; 4508 if (fault) goto MMU_EXCEPTION;
4979// DEBUG_LOG(ARM11, "ldrsb addr is %x\n", addr); 4509 cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = value;
4980 fault = interpreter_read_memory(addr, phys_addr, value, 8); 4510
4981 if (fault) goto MMU_EXCEPTION; 4511 // No dispatch since this operation should not modify R15
4982 //bus_read(8, addr, &value); 4512 }
4983 if (BIT(value, 7)) { 4513 cpu->Reg[15] += 4;
4984 value |= 0xffffff00; 4514 INC_PC(sizeof(ldst_inst));
4985 } 4515 FETCH_INST;
4986 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4516 GOTO_NEXT_INST;
4987 if (BITS(inst_cream->inst, 12, 15) == 15) { 4517 }
4988 INC_PC(sizeof(ldst_inst)); 4518
4989 goto DISPATCH; 4519 LDREX_INST:
4990 } 4520 {
4991 } 4521 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
4992 cpu->Reg[15] += GET_INST_SIZE(cpu); 4522 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4993 INC_PC(sizeof(ldst_inst)); 4523 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)];
4994 FETCH_INST; 4524 fault = check_address_validity(cpu, addr, &phys_addr, 1);
4995 GOTO_NEXT_INST; 4525 if (fault) goto MMU_EXCEPTION;
4996 } 4526 unsigned int value;
4997 LDRSH_INST: 4527 fault = interpreter_read_memory(addr, phys_addr, value, 32);
4998 { 4528 if (fault) goto MMU_EXCEPTION;
4999 INC_ICOUNTER; 4529
5000 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4530 add_exclusive_addr(cpu, phys_addr);
5001 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4531 cpu->exclusive_state = 1;
5002 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); 4532
5003 if (fault) goto MMU_EXCEPTION; 4533 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
5004 unsigned int value; 4534 if (BITS(inst_cream->inst, 12, 15) == 15) {
5005 fault = interpreter_read_memory(addr, phys_addr, value, 16); 4535 INC_PC(sizeof(ldst_inst));
5006 if (fault) goto MMU_EXCEPTION; 4536 goto DISPATCH;
5007 //bus_read(16, addr, &value); 4537 }
5008 if (BIT(value, 15)) { 4538 }
5009 value |= 0xffff0000; 4539 cpu->Reg[15] += GET_INST_SIZE(cpu);
5010 } 4540 INC_PC(sizeof(ldst_inst));
5011 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4541 FETCH_INST;
5012 if (BITS(inst_cream->inst, 12, 15) == 15) { 4542 GOTO_NEXT_INST;
5013 INC_PC(sizeof(ldst_inst)); 4543 }
5014 goto DISPATCH; 4544 LDREXB_INST:
5015 } 4545 {
5016 } 4546 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
5017 cpu->Reg[15] += GET_INST_SIZE(cpu); 4547 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5018 INC_PC(sizeof(ldst_inst)); 4548 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)];
5019 FETCH_INST; 4549 fault = check_address_validity(cpu, addr, &phys_addr, 1);
5020 GOTO_NEXT_INST; 4550 if (fault) goto MMU_EXCEPTION;
5021 } 4551 unsigned int value;
5022 LDRT_INST: 4552 fault = interpreter_read_memory(addr, phys_addr, value, 8);
5023 { 4553 if (fault) goto MMU_EXCEPTION;
5024 INC_ICOUNTER; 4554
5025 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 4555 add_exclusive_addr(cpu, phys_addr);
5026 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4556 cpu->exclusive_state = 1;
5027 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1); 4557
5028 if (fault) goto MMU_EXCEPTION; 4558 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
5029 unsigned int value; 4559 if (BITS(inst_cream->inst, 12, 15) == 15) {
5030 fault = interpreter_read_memory(addr, phys_addr, value, 32); 4560 INC_PC(sizeof(ldst_inst));
5031 if (fault) goto MMU_EXCEPTION; 4561 goto DISPATCH;
5032 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4562 }
5033 4563 }
5034 if (BIT(CP15_REG(CP15_CONTROL), 22) == 1) 4564 cpu->Reg[15] += GET_INST_SIZE(cpu);
5035 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; 4565 INC_PC(sizeof(ldst_inst));
5036 else 4566 FETCH_INST;
5037 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = ROTATE_RIGHT_32(value,(8*(addr&0x3))) ; 4567 GOTO_NEXT_INST;
5038 4568 }
5039 if (BITS(inst_cream->inst, 12, 15) == 15) { 4569 LDRH_INST:
5040 INC_PC(sizeof(ldst_inst)); 4570 {
5041 goto DISPATCH; 4571 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
5042 } 4572 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5043 } 4573 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
5044 cpu->Reg[15] += GET_INST_SIZE(cpu); 4574 if (fault) goto MMU_EXCEPTION;
5045 INC_PC(sizeof(ldst_inst)); 4575 unsigned int value = 0;
5046 FETCH_INST; 4576 fault = interpreter_read_memory(addr, phys_addr, value, 16);
5047 GOTO_NEXT_INST; 4577 if (fault) goto MMU_EXCEPTION;
5048 } 4578 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
5049 MCR_INST: 4579 if (BITS(inst_cream->inst, 12, 15) == 15) {
5050 { 4580 INC_PC(sizeof(ldst_inst));
5051 INC_ICOUNTER; 4581 goto DISPATCH;
5052 /* NOT IMPL */ 4582 }
5053 mcr_inst *inst_cream = (mcr_inst *)inst_base->component; 4583 }
5054 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4584 cpu->Reg[15] += GET_INST_SIZE(cpu);
5055 unsigned int inst = inst_cream->inst; 4585 INC_PC(sizeof(ldst_inst));
5056 if (inst_cream->Rd == 15) { 4586 FETCH_INST;
5057 DEBUG_MSG; 4587 GOTO_NEXT_INST;
5058 } else { 4588 }
5059 if (inst_cream->cp_num == 15) { 4589 LDRSB_INST:
5060 if(CRn == 0 && OPCODE_2 == 0 && CRm == 0) { 4590 {
5061 //LET(RD, CONST(0x0007b000)); 4591 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
5062 //LET(RD, CONST(0x410FB760)); 4592 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5063 //LET(CP15_MAIN_ID, R(RD)); 4593 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
5064 CP15_REG(CP15_MAIN_ID) = RD; 4594 if (fault) goto MMU_EXCEPTION;
5065 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) { 4595 unsigned int value;
5066 //LET(RD, R(CP15_CONTROL)); 4596 fault = interpreter_read_memory(addr, phys_addr, value, 8);
5067 CP15_REG(CP15_AUXILIARY_CONTROL) = RD; 4597 if (fault) goto MMU_EXCEPTION;
5068 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) { 4598 if (BIT(value, 7)) {
5069 //LET(RD, R(CP15_CONTROL)); 4599 value |= 0xffffff00;
5070 CP15_REG(CP15_COPROCESSOR_ACCESS_CONTROL) = RD; 4600 }
5071 } else if(CRn == 1 && CRm == 0 && OPCODE_2 == 0) { 4601 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
5072 //LET(CP15_CONTROL, R(RD)); 4602 if (BITS(inst_cream->inst, 12, 15) == 15) {
5073 CP15_REG(CP15_CONTROL) = RD; 4603 INC_PC(sizeof(ldst_inst));
5074 } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) { 4604 goto DISPATCH;
5075 //LET(CP15_DOMAIN_ACCESS_CONTROL, R(RD)); 4605 }
5076 CP15_REG(CP15_DOMAIN_ACCESS_CONTROL) = RD; 4606 }
5077 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) { 4607 cpu->Reg[15] += GET_INST_SIZE(cpu);
5078 //LET(CP15_TRANSLATION_BASE_TABLE_0, R(RD)); 4608 INC_PC(sizeof(ldst_inst));
5079 CP15_REG(CP15_TRANSLATION_BASE_TABLE_0) = RD; 4609 FETCH_INST;
5080 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 1) { 4610 GOTO_NEXT_INST;
5081 //LET(CP15_TRANSLATION_BASE_TABLE_1, R(RD)); 4611 }
5082 CP15_REG(CP15_TRANSLATION_BASE_TABLE_1) = RD; 4612 LDRSH_INST:
5083 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 2) { 4613 {
5084 //LET(CP15_TRANSLATION_BASE_CONTROL, R(RD)); 4614 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
5085 CP15_REG(CP15_TRANSLATION_BASE_CONTROL) = RD; 4615 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5086 } else if(CRn == MMU_CACHE_OPS){ 4616 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
5087 //SKYEYE_WARNING("cache operation have not implemented.\n"); 4617 if (fault) goto MMU_EXCEPTION;
5088 } else if(CRn == MMU_TLB_OPS){ 4618 unsigned int value;
5089 switch (CRm) { 4619 fault = interpreter_read_memory(addr, phys_addr, value, 16);
5090 case 5: /* ITLB */ 4620 if (fault) goto MMU_EXCEPTION;
5091 switch(OPCODE_2){ 4621 if (BIT(value, 15)) {
5092 case 0: /* invalidate all */ 4622 value |= 0xffff0000;
5093 //invalidate_all_tlb(state); 4623 }
5094 LOG_DEBUG(Core_ARM11, "{TLB} [INSN] invalidate all"); 4624 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
5095 //remove_tlb(INSN_TLB); 4625 if (BITS(inst_cream->inst, 12, 15) == 15) {
5096 //erase_all(core, INSN_TLB); 4626 INC_PC(sizeof(ldst_inst));
5097 break; 4627 goto DISPATCH;
5098 case 1: /* invalidate by MVA */ 4628 }
5099 //invalidate_by_mva(state, value); 4629 }
5100 //DEBUG_LOG(ARM11, "{TLB} [INSN] invalidate by mva\n"); 4630 cpu->Reg[15] += GET_INST_SIZE(cpu);
5101 //remove_tlb_by_mva(RD, INSN_TLB); 4631 INC_PC(sizeof(ldst_inst));
5102 //erase_by_mva(core, RD, INSN_TLB); 4632 FETCH_INST;
5103 break; 4633 GOTO_NEXT_INST;
5104 case 2: /* invalidate by asid */ 4634 }
5105 //invalidate_by_asid(state, value); 4635 LDRT_INST:
5106 //DEBUG_LOG(ARM11, "{TLB} [INSN] invalidate by asid\n"); 4636 {
5107 //erase_by_asid(core, RD, INSN_TLB); 4637 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
5108 break; 4638 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5109 default: 4639 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 1);
5110 break; 4640 if (fault) goto MMU_EXCEPTION;
5111 } 4641 unsigned int value;
5112 4642 fault = interpreter_read_memory(addr, phys_addr, value, 32);
5113 break; 4643 if (fault) goto MMU_EXCEPTION;
5114 case 6: /* DTLB */ 4644 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
5115 switch(OPCODE_2){ 4645
5116 case 0: /* invalidate all */ 4646 if (BIT(CP15_REG(CP15_CONTROL), 22) == 1)
5117 //invalidate_all_tlb(state); 4647 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value;
5118 //remove_tlb(DATA_TLB); 4648 else
5119 //erase_all(core, DATA_TLB); 4649 cpu->Reg[BITS(inst_cream->inst, 12, 15)] = ROTATE_RIGHT_32(value,(8*(addr&0x3))) ;
5120 LOG_DEBUG(Core_ARM11, "{TLB} [DATA] invalidate all"); 4650
5121 break; 4651 if (BITS(inst_cream->inst, 12, 15) == 15) {
5122 case 1: /* invalidate by MVA */ 4652 INC_PC(sizeof(ldst_inst));
5123 //invalidate_by_mva(state, value); 4653 goto DISPATCH;
5124 //remove_tlb_by_mva(RD, DATA_TLB); 4654 }
5125 //erase_by_mva(core, RD, DATA_TLB); 4655 }
5126 //DEBUG_LOG(ARM11, "{TLB} [DATA] invalidate by mva\n"); 4656 cpu->Reg[15] += GET_INST_SIZE(cpu);
5127 break; 4657 INC_PC(sizeof(ldst_inst));
5128 case 2: /* invalidate by asid */ 4658 FETCH_INST;
5129 //invalidate_by_asid(state, value); 4659 GOTO_NEXT_INST;
5130 //remove_tlb_by_asid(RD, DATA_TLB); 4660 }
5131 //erase_by_asid(core, RD, DATA_TLB); 4661 MCR_INST:
5132 //DEBUG_LOG(ARM11, "{TLB} [DATA] invalidate by asid\n"); 4662 {
5133 break; 4663 mcr_inst *inst_cream = (mcr_inst *)inst_base->component;
5134 default: 4664 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5135 break; 4665 unsigned int inst = inst_cream->inst;
5136 } 4666 if (inst_cream->Rd == 15) {
5137 break; 4667 DEBUG_MSG;
5138 case 7: /* UNIFILED TLB */ 4668 } else {
5139 switch(OPCODE_2){ 4669 if (inst_cream->cp_num == 15) {
5140 case 0: /* invalidate all */ 4670 if(CRn == 0 && OPCODE_2 == 0 && CRm == 0) {
5141 //invalidate_all_tlb(state); 4671 CP15_REG(CP15_MAIN_ID) = RD;
5142 //erase_all(core, INSN_TLB); 4672 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) {
5143 //erase_all(core, DATA_TLB); 4673 CP15_REG(CP15_AUXILIARY_CONTROL) = RD;
5144 //remove_tlb(DATA_TLB); 4674 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) {
5145 //remove_tlb(INSN_TLB); 4675 CP15_REG(CP15_COPROCESSOR_ACCESS_CONTROL) = RD;
5146 //DEBUG_LOG(ARM11, "{TLB} [UNIFILED] invalidate all\n"); 4676 } else if(CRn == 1 && CRm == 0 && OPCODE_2 == 0) {
5147 break; 4677 CP15_REG(CP15_CONTROL) = RD;
5148 case 1: /* invalidate by MVA */ 4678 } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) {
5149 //invalidate_by_mva(state, value); 4679 CP15_REG(CP15_DOMAIN_ACCESS_CONTROL) = RD;
5150 //erase_by_mva(core, RD, DATA_TLB); 4680 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) {
5151 //erase_by_mva(core, RD, INSN_TLB); 4681 CP15_REG(CP15_TRANSLATION_BASE_TABLE_0) = RD;
5152 LOG_DEBUG(Core_ARM11, "{TLB} [UNIFILED] invalidate by mva"); 4682 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 1) {
5153 break; 4683 CP15_REG(CP15_TRANSLATION_BASE_TABLE_1) = RD;
5154 case 2: /* invalidate by asid */ 4684 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 2) {
5155 //invalidate_by_asid(state, value); 4685 CP15_REG(CP15_TRANSLATION_BASE_CONTROL) = RD;
5156 //erase_by_asid(core, RD, DATA_TLB); 4686 } else if(CRn == MMU_CACHE_OPS){
5157 //erase_by_asid(core, RD, INSN_TLB); 4687 //LOG_WARNING(Core_ARM11, "cache operations have not implemented.");
5158 LOG_DEBUG(Core_ARM11, "{TLB} [UNIFILED] invalidate by asid"); 4688 } else if(CRn == MMU_TLB_OPS){
5159 break; 4689 switch (CRm) {
5160 default: 4690 case 5: // ITLB
5161 break; 4691 switch(OPCODE_2) {
5162 } 4692 case 0: // Invalidate all
5163 break; 4693 LOG_DEBUG(Core_ARM11, "{TLB} [INSN] invalidate all");
5164 default: 4694 break;
5165 break; 4695 case 1: // Invalidate by MVA
5166 } 4696 LOG_DEBUG(Core_ARM11, "{TLB} [INSN] invalidate by mva");
5167 } else if(CRn == MMU_PID){ 4697 break;
5168 if(OPCODE_2 == 0) 4698 case 2: // Invalidate by asid
5169 CP15_REG(CP15_PID) = RD; 4699 LOG_DEBUG(Core_ARM11, "{TLB} [INSN] invalidate by asid");
5170 else if(OPCODE_2 == 1) 4700 break;
5171 CP15_REG(CP15_CONTEXT_ID) = RD; 4701 default:
5172 else if(OPCODE_2 == 3){ 4702 break;
5173 CP15_REG(CP15_THREAD_URO) = RD; 4703 }
5174 } 4704
5175 else{ 4705 break;
5176 printf ("mmu_mcr wrote UNKNOWN - reg %d\n", CRn); 4706 case 6: // DTLB
5177 } 4707 switch(OPCODE_2){
5178 4708 case 0: // Invalidate all
5179 } else { 4709 LOG_DEBUG(Core_ARM11, "{TLB} [DATA] invalidate all");
5180 LOG_ERROR(Core_ARM11, "mcr CRn=%d, CRm=%d OP2=%d is not implemented", CRn, CRm, OPCODE_2); 4710 break;
5181 } 4711 case 1: // Invalidate by MVA
5182 } 4712 LOG_DEBUG(Core_ARM11, "{TLB} [DATA] invalidate by mva");
5183 } 4713 break;
5184 } 4714 case 2: // Invalidate by asid
5185 cpu->Reg[15] += GET_INST_SIZE(cpu); 4715 LOG_DEBUG(Core_ARM11, "{TLB} [DATA] invalidate by asid");
5186 INC_PC(sizeof(mcr_inst)); 4716 break;
5187 FETCH_INST; 4717 default:
5188 GOTO_NEXT_INST; 4718 break;
5189 } 4719 }
5190 MCRR_INST: 4720 break;
5191 MLA_INST: 4721 case 7: // UNIFILED TLB
5192 { 4722 switch(OPCODE_2){
5193 INC_ICOUNTER; 4723 case 0: // invalidate all
5194 mla_inst *inst_cream = (mla_inst *)inst_base->component; 4724 LOG_DEBUG(Core_ARM11, "{TLB} [UNIFILED] invalidate all");
5195 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4725 break;
5196 uint64_t rm = RM; 4726 case 1: // Invalidate by MVA
5197 uint64_t rs = RS; 4727 LOG_DEBUG(Core_ARM11, "{TLB} [UNIFILED] invalidate by mva");
5198 uint64_t rn = RN; 4728 break;
5199 if (inst_cream->Rm == 15 || inst_cream->Rs == 15 || inst_cream->Rn == 15) { 4729 case 2: // Invalidate by asid
5200 LOG_ERROR(Core_ARM11, "invalid operands for MLA"); 4730 LOG_DEBUG(Core_ARM11, "{TLB} [UNIFILED] invalidate by asid");
5201 CITRA_IGNORE_EXIT(-1); 4731 break;
5202 } 4732 default:
5203// RD = dst = RM * RS + RN; 4733 break;
5204 RD = dst = static_cast<uint32_t>((rm * rs + rn) & 0xffffffff); 4734 }
5205 if (inst_cream->S) { 4735 break;
5206 UPDATE_NFLAG(dst); 4736 default:
5207 UPDATE_ZFLAG(dst); 4737 break;
5208 } 4738 }
5209 if (inst_cream->Rd == 15) { 4739 } else if(CRn == MMU_PID) {
5210 INC_PC(sizeof(mla_inst)); 4740 if(OPCODE_2 == 0)
5211 goto DISPATCH; 4741 CP15_REG(CP15_PID) = RD;
5212 } 4742 else if(OPCODE_2 == 1)
5213 } 4743 CP15_REG(CP15_CONTEXT_ID) = RD;
5214 cpu->Reg[15] += GET_INST_SIZE(cpu); 4744 else if(OPCODE_2 == 3) {
5215 INC_PC(sizeof(mla_inst)); 4745 CP15_REG(CP15_THREAD_URO) = RD;
5216 FETCH_INST; 4746 } else {
5217 GOTO_NEXT_INST; 4747 LOG_ERROR(Core_ARM11, "mmu_mcr wrote UNKNOWN - reg %d", CRn);
5218 } 4748 }
5219 MOV_INST: 4749 } else {
5220 { 4750 LOG_ERROR(Core_ARM11, "mcr CRn=%d, CRm=%d OP2=%d is not implemented", CRn, CRm, OPCODE_2);
5221// DEBUG_LOG(ARM11, "mov inst\n"); 4751 }
5222// DEBUG_LOG(ARM11, "pc: %x\n", cpu->Reg[15]); 4752 }
5223// debug_function(cpu); 4753 }
5224// cpu->icount ++; 4754 }
5225 INC_ICOUNTER; 4755 cpu->Reg[15] += GET_INST_SIZE(cpu);
5226 mov_inst *inst_cream = (mov_inst *)inst_base->component; 4756 INC_PC(sizeof(mcr_inst));
5227 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4757 FETCH_INST;
5228 RD = dst = SHIFTER_OPERAND; 4758 GOTO_NEXT_INST;
5229 if (inst_cream->S && (inst_cream->Rd == 15)) { 4759 }
5230 /* cpsr = spsr */ 4760 MCRR_INST:
5231 if (CurrentModeHasSPSR) { 4761 MLA_INST:
5232 cpu->Cpsr = cpu->Spsr_copy; 4762 {
5233 switch_mode(cpu, cpu->Spsr_copy & 0x1f); 4763 mla_inst *inst_cream = (mla_inst *)inst_base->component;
5234 LOAD_NZCVT; 4764 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5235 } 4765 uint64_t rm = RM;
5236 } else if (inst_cream->S) { 4766 uint64_t rs = RS;
5237 UPDATE_NFLAG(dst); 4767 uint64_t rn = RN;
5238 UPDATE_ZFLAG(dst); 4768 if (inst_cream->Rm == 15 || inst_cream->Rs == 15 || inst_cream->Rn == 15) {
5239 UPDATE_CFLAG_WITH_SC; 4769 LOG_ERROR(Core_ARM11, "invalid operands for MLA");
5240 } 4770 CITRA_IGNORE_EXIT(-1);
5241 if (inst_cream->Rd == 15) { 4771 }
5242 INC_PC(sizeof(mov_inst)); 4772 RD = dst = static_cast<uint32_t>((rm * rs + rn) & 0xffffffff);
5243 goto DISPATCH; 4773 if (inst_cream->S) {
5244 } 4774 UPDATE_NFLAG(dst);
5245// return; 4775 UPDATE_ZFLAG(dst);
5246 } 4776 }
5247 cpu->Reg[15] += GET_INST_SIZE(cpu); 4777 if (inst_cream->Rd == 15) {
5248 INC_PC(sizeof(mov_inst)); 4778 INC_PC(sizeof(mla_inst));
5249 FETCH_INST; 4779 goto DISPATCH;
5250 GOTO_NEXT_INST; 4780 }
5251 } 4781 }
5252 MRC_INST: 4782 cpu->Reg[15] += GET_INST_SIZE(cpu);
5253 { 4783 INC_PC(sizeof(mla_inst));
5254 INC_ICOUNTER; 4784 FETCH_INST;
5255 /* NOT IMPL */ 4785 GOTO_NEXT_INST;
5256 mrc_inst *inst_cream = (mrc_inst *)inst_base->component; 4786 }
5257 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4787 MOV_INST:
5258 unsigned int inst = inst_cream->inst; 4788 {
5259 if (inst_cream->Rd == 15) { 4789 mov_inst *inst_cream = (mov_inst *)inst_base->component;
5260 DEBUG_MSG; 4790 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5261 } 4791 RD = dst = SHIFTER_OPERAND;
5262 if (inst_cream->inst == 0xeef04a10) { 4792 if (inst_cream->S && (inst_cream->Rd == 15)) {
5263 /* undefined instruction fmrx */ 4793 if (CurrentModeHasSPSR) {
5264 RD = 0x20000000; 4794 cpu->Cpsr = cpu->Spsr_copy;
5265 CITRA_IGNORE_EXIT(-1); 4795 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
5266 goto END; 4796 LOAD_NZCVT;
5267 } else { 4797 }
5268 if (inst_cream->cp_num == 15) { 4798 } else if (inst_cream->S) {
5269 if(CRn == 0 && OPCODE_2 == 0 && CRm == 0) { 4799 UPDATE_NFLAG(dst);
5270 //LET(RD, CONST(0x0007b000)); 4800 UPDATE_ZFLAG(dst);
5271 //LET(RD, CONST(0x410FB760)); 4801 UPDATE_CFLAG_WITH_SC;
5272 //LET(RD, R(CP15_MAIN_ID)); 4802 }
5273 RD = cpu->CP15[CP15(CP15_MAIN_ID)]; 4803 if (inst_cream->Rd == 15) {
5274 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 0) { 4804 INC_PC(sizeof(mov_inst));
5275 //LET(RD, R(CP15_CONTROL)); 4805 goto DISPATCH;
5276 RD = cpu->CP15[CP15(CP15_CONTROL)]; 4806 }
5277 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) { 4807 }
5278 //LET(RD, R(CP15_CONTROL)); 4808 cpu->Reg[15] += GET_INST_SIZE(cpu);
5279 RD = cpu->CP15[CP15(CP15_AUXILIARY_CONTROL)]; 4809 INC_PC(sizeof(mov_inst));
5280 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) { 4810 FETCH_INST;
5281 //LET(RD, R(CP15_CONTROL)); 4811 GOTO_NEXT_INST;
5282 RD = cpu->CP15[CP15(CP15_COPROCESSOR_ACCESS_CONTROL)]; 4812 }
5283 } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) { 4813 MRC_INST:
5284 //LET(RD, R(CP15_DOMAIN_ACCESS_CONTROL)); 4814 {
5285 RD = cpu->CP15[CP15(CP15_DOMAIN_ACCESS_CONTROL)]; 4815 mrc_inst *inst_cream = (mrc_inst *)inst_base->component;
5286 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) { 4816 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5287 //LET(RD, R(CP15_TRANSLATION_BASE_TABLE_0)); 4817 unsigned int inst = inst_cream->inst;
5288 RD = cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_0)]; 4818 if (inst_cream->Rd == 15) {
5289 } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 0) { 4819 DEBUG_MSG;
5290 //LET(RD, R(CP15_FAULT_STATUS)); 4820 }
5291 RD = cpu->CP15[CP15(CP15_FAULT_STATUS)]; 4821 if (inst_cream->inst == 0xeef04a10) {
5292 } else if (CRn == 6 && CRm == 0 && OPCODE_2 == 0) { 4822 // Undefined instruction fmrx
5293 //LET(RD, R(CP15_FAULT_ADDRESS)); 4823 RD = 0x20000000;
5294 RD = cpu->CP15[CP15(CP15_FAULT_ADDRESS)]; 4824 CITRA_IGNORE_EXIT(-1);
5295 } else if (CRn == 0 && CRm == 0 && OPCODE_2 == 1) { 4825 goto END;
5296 //LET(RD, R(CP15_CACHE_TYPE)); 4826 } else {
5297 RD = cpu->CP15[CP15(CP15_CACHE_TYPE)]; 4827 if (inst_cream->cp_num == 15) {
5298 } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 1) { 4828 if(CRn == 0 && OPCODE_2 == 0 && CRm == 0) {
5299 //LET(RD, R(CP15_INSTR_FAULT_STATUS)); 4829 RD = cpu->CP15[CP15(CP15_MAIN_ID)];
5300 RD = cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)]; 4830 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 0) {
5301 } else if (CRn == 13) { 4831 RD = cpu->CP15[CP15(CP15_CONTROL)];
5302 if(OPCODE_2 == 0) 4832 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 1) {
5303 RD = CP15_REG(CP15_PID); 4833 RD = cpu->CP15[CP15(CP15_AUXILIARY_CONTROL)];
5304 else if(OPCODE_2 == 1) 4834 } else if (CRn == 1 && CRm == 0 && OPCODE_2 == 2) {
5305 RD = CP15_REG(CP15_CONTEXT_ID); 4835 RD = cpu->CP15[CP15(CP15_COPROCESSOR_ACCESS_CONTROL)];
5306 else if(OPCODE_2 == 3){ 4836 } else if (CRn == 3 && CRm == 0 && OPCODE_2 == 0) {
5307 RD = Memory::KERNEL_MEMORY_VADDR; 4837 RD = cpu->CP15[CP15(CP15_DOMAIN_ACCESS_CONTROL)];
5308 } 4838 } else if (CRn == 2 && CRm == 0 && OPCODE_2 == 0) {
5309 else{ 4839 RD = cpu->CP15[CP15(CP15_TRANSLATION_BASE_TABLE_0)];
5310 printf ("mmu_mrr wrote UNKNOWN - reg %d\n", CRn); 4840 } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 0) {
5311 } 4841 RD = cpu->CP15[CP15(CP15_FAULT_STATUS)];
5312 } 4842 } else if (CRn == 6 && CRm == 0 && OPCODE_2 == 0) {
5313 else { 4843 RD = cpu->CP15[CP15(CP15_FAULT_ADDRESS)];
5314 LOG_ERROR(Core_ARM11, "mrc CRn=%d, CRm=%d, OP2=%d is not implemented", CRn, CRm, OPCODE_2); 4844 } else if (CRn == 0 && CRm == 0 && OPCODE_2 == 1) {
5315 } 4845 RD = cpu->CP15[CP15(CP15_CACHE_TYPE)];
5316 } 4846 } else if (CRn == 5 && CRm == 0 && OPCODE_2 == 1) {
5317 //DEBUG_LOG(ARM11, "mrc is not implementated. CRn is %d, CRm is %d, OPCODE_2 is %d\n", CRn, CRm, OPCODE_2); 4847 RD = cpu->CP15[CP15(CP15_INSTR_FAULT_STATUS)];
5318 } 4848 } else if (CRn == 13) {
5319 } 4849 if(OPCODE_2 == 0)
5320 cpu->Reg[15] += GET_INST_SIZE(cpu); 4850 RD = CP15_REG(CP15_PID);
5321 INC_PC(sizeof(mrc_inst)); 4851 else if(OPCODE_2 == 1)
5322 FETCH_INST; 4852 RD = CP15_REG(CP15_CONTEXT_ID);
5323 GOTO_NEXT_INST; 4853 else if(OPCODE_2 == 3) {
5324 } 4854 RD = Memory::KERNEL_MEMORY_VADDR;
5325 MRRC_INST: 4855 } else {
5326 MRS_INST: 4856 LOG_ERROR(Core_ARM11, "mmu_mrr wrote UNKNOWN - reg %d", CRn);
5327 { 4857 }
5328 INC_ICOUNTER; 4858 } else {
5329 mrs_inst *inst_cream = (mrs_inst *)inst_base->component; 4859 LOG_ERROR(Core_ARM11, "mrc CRn=%d, CRm=%d, OP2=%d is not implemented", CRn, CRm, OPCODE_2);
5330 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4860 }
5331 if (inst_cream->R) { 4861 }
5332 RD = cpu->Spsr_copy; 4862 }
5333 } else { 4863 }
5334 SAVE_NZCVT; 4864 cpu->Reg[15] += GET_INST_SIZE(cpu);
5335 RD = cpu->Cpsr; 4865 INC_PC(sizeof(mrc_inst));
5336 } 4866 FETCH_INST;
5337 } 4867 GOTO_NEXT_INST;
5338 cpu->Reg[15] += GET_INST_SIZE(cpu); 4868 }
5339 INC_PC(sizeof(mrs_inst)); 4869 MRRC_INST:
5340 FETCH_INST; 4870 MRS_INST:
5341 GOTO_NEXT_INST; 4871 {
5342 } 4872 mrs_inst *inst_cream = (mrs_inst *)inst_base->component;
5343 MSR_INST: 4873 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5344 { 4874 if (inst_cream->R) {
5345 INC_ICOUNTER; 4875 RD = cpu->Spsr_copy;
5346 msr_inst *inst_cream = (msr_inst *)inst_base->component; 4876 } else {
5347 const uint32_t UnallocMask = 0x06f0fc00, UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020; 4877 SAVE_NZCVT;
5348 unsigned int inst = inst_cream->inst; 4878 RD = cpu->Cpsr;
5349 unsigned int operand; 4879 }
5350 4880 }
5351 if (BIT(inst, 25)) { 4881 cpu->Reg[15] += GET_INST_SIZE(cpu);
5352 int rot_imm = BITS(inst, 8, 11) * 2; 4882 INC_PC(sizeof(mrs_inst));
5353 //operand = ROTL(CONST(BITS(0, 7)), CONST(32 - rot_imm)); 4883 FETCH_INST;
5354 operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm); 4884 GOTO_NEXT_INST;
5355 } else { 4885 }
5356 //operand = R(RM); 4886 MSR_INST:
5357 operand = cpu->Reg[BITS(inst, 0, 3)]; 4887 {
5358 } 4888 msr_inst *inst_cream = (msr_inst *)inst_base->component;
5359 uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) 4889 const uint32_t UnallocMask = 0x06f0fc00, UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020;
5360 | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); 4890 unsigned int inst = inst_cream->inst;
5361 uint32_t mask; 4891 unsigned int operand;
5362 if (!inst_cream->R) { 4892
5363 if (InAPrivilegedMode(cpu)) { 4893 if (BIT(inst, 25)) {
5364 if ((operand & StateMask) != 0) { 4894 int rot_imm = BITS(inst, 8, 11) * 2;
5365 /* UNPREDICTABLE */ 4895 operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm);
5366 DEBUG_MSG; 4896 } else {
5367 } else 4897 operand = cpu->Reg[BITS(inst, 0, 3)];
5368 mask = byte_mask & (UserMask | PrivMask); 4898 }
5369 } else { 4899 uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0)
5370 mask = byte_mask & UserMask; 4900 | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
5371 } 4901 uint32_t mask;
5372 //LET(CPSR_REG, OR(AND(R(CPSR_REG), COM(CONST(mask))), AND(operand, CONST(mask)))); 4902 if (!inst_cream->R) {
5373 SAVE_NZCVT; 4903 if (InAPrivilegedMode(cpu)) {
5374 4904 if ((operand & StateMask) != 0) {
5375 cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); 4905 /// UNPREDICTABLE
5376 switch_mode(cpu, cpu->Cpsr & 0x1f); 4906 DEBUG_MSG;
5377 LOAD_NZCVT; 4907 } else
5378 } else { 4908 mask = byte_mask & (UserMask | PrivMask);
5379 if (CurrentModeHasSPSR) { 4909 } else {
5380 mask = byte_mask & (UserMask | PrivMask | StateMask); 4910 mask = byte_mask & UserMask;
5381 //LET(SPSR_REG, OR(AND(R(SPSR_REG), COM(CONST(mask))), AND(operand, CONST(mask)))); 4911 }
5382 cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask); 4912 SAVE_NZCVT;
5383 } 4913
5384 } 4914 cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask);
5385 cpu->Reg[15] += GET_INST_SIZE(cpu); 4915 switch_mode(cpu, cpu->Cpsr & 0x1f);
5386 INC_PC(sizeof(msr_inst)); 4916 LOAD_NZCVT;
5387 FETCH_INST; 4917 } else {
5388 GOTO_NEXT_INST; 4918 if (CurrentModeHasSPSR) {
5389 } 4919 mask = byte_mask & (UserMask | PrivMask | StateMask);
5390 MUL_INST: 4920 cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask);
5391 { 4921 }
5392 INC_ICOUNTER; 4922 }
5393 mul_inst *inst_cream = (mul_inst *)inst_base->component; 4923 cpu->Reg[15] += GET_INST_SIZE(cpu);
5394 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4924 INC_PC(sizeof(msr_inst));
5395// RD = dst = SHIFTER_OPERAND; 4925 FETCH_INST;
5396 uint64_t rm = RM; 4926 GOTO_NEXT_INST;
5397 uint64_t rs = RS; 4927 }
5398 RD = dst = static_cast<uint32_t>((rm * rs) & 0xffffffff); 4928 MUL_INST:
5399 if (inst_cream->S) { 4929 {
5400 UPDATE_NFLAG(dst); 4930 mul_inst *inst_cream = (mul_inst *)inst_base->component;
5401 UPDATE_ZFLAG(dst); 4931 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5402 } 4932 uint64_t rm = RM;
5403 if (inst_cream->Rd == 15) { 4933 uint64_t rs = RS;
5404 INC_PC(sizeof(mul_inst)); 4934 RD = dst = static_cast<uint32_t>((rm * rs) & 0xffffffff);
5405 goto DISPATCH; 4935 if (inst_cream->S) {
5406 } 4936 UPDATE_NFLAG(dst);
5407 } 4937 UPDATE_ZFLAG(dst);
5408 cpu->Reg[15] += GET_INST_SIZE(cpu); 4938 }
5409 INC_PC(sizeof(mul_inst)); 4939 if (inst_cream->Rd == 15) {
5410 FETCH_INST; 4940 INC_PC(sizeof(mul_inst));
5411 GOTO_NEXT_INST; 4941 goto DISPATCH;
5412 } 4942 }
5413 MVN_INST: 4943 }
5414 { 4944 cpu->Reg[15] += GET_INST_SIZE(cpu);
5415 INC_ICOUNTER; 4945 INC_PC(sizeof(mul_inst));
5416 mvn_inst *inst_cream = (mvn_inst *)inst_base->component; 4946 FETCH_INST;
5417 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4947 GOTO_NEXT_INST;
5418// RD = dst = (SHIFTER_OPERAND ^ 0xffffffff); 4948 }
5419 RD = dst = ~SHIFTER_OPERAND; 4949 MVN_INST:
5420 if (inst_cream->S && (inst_cream->Rd == 15)) { 4950 {
5421 /* cpsr = spsr */ 4951 mvn_inst *inst_cream = (mvn_inst *)inst_base->component;
5422 if (CurrentModeHasSPSR) { 4952 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5423 cpu->Cpsr = cpu->Spsr_copy; 4953 RD = dst = ~SHIFTER_OPERAND;
5424 switch_mode(cpu, cpu->Spsr_copy & 0x1f); 4954 if (inst_cream->S && (inst_cream->Rd == 15)) {
5425 LOAD_NZCVT; 4955 if (CurrentModeHasSPSR) {
5426 } 4956 cpu->Cpsr = cpu->Spsr_copy;
5427 } else if (inst_cream->S) { 4957 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
5428 UPDATE_NFLAG(dst); 4958 LOAD_NZCVT;
5429 UPDATE_ZFLAG(dst); 4959 }
5430 UPDATE_CFLAG_WITH_SC; 4960 } else if (inst_cream->S) {
5431 } 4961 UPDATE_NFLAG(dst);
5432 if (inst_cream->Rd == 15) { 4962 UPDATE_ZFLAG(dst);
5433 INC_PC(sizeof(mvn_inst)); 4963 UPDATE_CFLAG_WITH_SC;
5434 goto DISPATCH; 4964 }
5435 } 4965 if (inst_cream->Rd == 15) {
5436 } 4966 INC_PC(sizeof(mvn_inst));
5437 cpu->Reg[15] += GET_INST_SIZE(cpu); 4967 goto DISPATCH;
5438 INC_PC(sizeof(mvn_inst)); 4968 }
5439 FETCH_INST; 4969 }
5440 GOTO_NEXT_INST; 4970 cpu->Reg[15] += GET_INST_SIZE(cpu);
5441 } 4971 INC_PC(sizeof(mvn_inst));
5442 ORR_INST: 4972 FETCH_INST;
5443 { 4973 GOTO_NEXT_INST;
5444 INC_ICOUNTER; 4974 }
5445 orr_inst *inst_cream = (orr_inst *)inst_base->component; 4975 ORR_INST:
5446 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4976 {
5447 lop = RN; 4977 orr_inst *inst_cream = (orr_inst *)inst_base->component;
5448 rop = SHIFTER_OPERAND; 4978 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5449// DEBUG_LOG(ARM11, "lop is %x, rop is %x, r2 is %x, r3 is %x\n", lop, rop, cpu->Reg[2], cpu->Reg[3]); 4979 lop = RN;
5450 RD = dst = lop | rop; 4980 rop = SHIFTER_OPERAND;
5451 if (inst_cream->S && (inst_cream->Rd == 15)) { 4981 RD = dst = lop | rop;
5452 /* cpsr = spsr*/ 4982 if (inst_cream->S && (inst_cream->Rd == 15)) {
5453 if (CurrentModeHasSPSR) { 4983 if (CurrentModeHasSPSR) {
5454 cpu->Cpsr = cpu->Spsr_copy; 4984 cpu->Cpsr = cpu->Spsr_copy;
5455 switch_mode(cpu, cpu->Spsr_copy & 0x1f); 4985 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
5456 LOAD_NZCVT; 4986 LOAD_NZCVT;
5457 } 4987 }
5458 } else if (inst_cream->S) { 4988 } else if (inst_cream->S) {
5459 UPDATE_NFLAG(dst); 4989 UPDATE_NFLAG(dst);
5460 UPDATE_ZFLAG(dst); 4990 UPDATE_ZFLAG(dst);
5461 UPDATE_CFLAG_WITH_SC; 4991 UPDATE_CFLAG_WITH_SC;
5462// UPDATE_CFLAG(dst, lop, rop); 4992 }
5463 } 4993 if (inst_cream->Rd == 15) {
5464 if (inst_cream->Rd == 15) { 4994 INC_PC(sizeof(orr_inst));
5465 INC_PC(sizeof(orr_inst)); 4995 goto DISPATCH;
5466 goto DISPATCH; 4996 }
5467 } 4997 }
5468 } 4998 cpu->Reg[15] += GET_INST_SIZE(cpu);
5469 cpu->Reg[15] += GET_INST_SIZE(cpu); 4999 INC_PC(sizeof(orr_inst));
5470 INC_PC(sizeof(orr_inst)); 5000 FETCH_INST;
5471 FETCH_INST; 5001 GOTO_NEXT_INST;
5472 GOTO_NEXT_INST; 5002 }
5473 } 5003
5474 PKHBT_INST: 5004 PKHBT_INST:
5475 PKHTB_INST: 5005 {
5476 PLD_INST: 5006 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5477 { 5007 pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
5478 INC_ICOUNTER; 5008 RD = (RN & 0xFFFF) | ((RM << inst_cream->imm) & 0xFFFF0000);
5479 /* NOT IMPL */ 5009 }
5480 cpu->Reg[15] += GET_INST_SIZE(cpu); 5010 cpu->Reg[15] += GET_INST_SIZE(cpu);
5481 INC_PC(sizeof(stc_inst)); 5011 INC_PC(sizeof(pkh_inst));
5482 FETCH_INST; 5012 FETCH_INST;
5483 GOTO_NEXT_INST; 5013 GOTO_NEXT_INST;
5484 } 5014 }
5485 QADD_INST: 5015
5486 QADD16_INST: 5016 PKHTB_INST:
5487 QADD8_INST: 5017 {
5488 QADDSUBX_INST: 5018 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5489 QDADD_INST: 5019 pkh_inst *inst_cream = (pkh_inst *)inst_base->component;
5490 QDSUB_INST: 5020 int shift_imm = inst_cream->imm ? inst_cream->imm : 31;
5491 QSUB_INST: 5021 RD = ((static_cast<s32>(RM) >> shift_imm) & 0xFFFF) | (RN & 0xFFFF0000);
5492 QSUB16_INST: 5022 }
5493 QSUB8_INST: 5023 cpu->Reg[15] += GET_INST_SIZE(cpu);
5494 QSUBADDX_INST: 5024 INC_PC(sizeof(pkh_inst));
5495 REV_INST: 5025 FETCH_INST;
5496 { 5026 GOTO_NEXT_INST;
5497 INC_ICOUNTER; 5027 }
5498 rev_inst *inst_cream = (rev_inst *)inst_base->component; 5028
5499 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5029 PLD_INST:
5500 RD = ((RM & 0xff) << 24) | 5030 {
5501 (((RM >> 8) & 0xff) << 16) | 5031 // Instruction not implemented
5502 (((RM >> 16) & 0xff) << 8) | 5032 //LOG_CRITICAL(Core_ARM11, "unimplemented instruction");
5503 ((RM >> 24) & 0xff); 5033 cpu->Reg[15] += GET_INST_SIZE(cpu);
5504 if (inst_cream->Rm == 15) { 5034 INC_PC(sizeof(stc_inst));
5505 LOG_ERROR(Core_ARM11, "invalid operand for REV"); 5035 FETCH_INST;
5506 CITRA_IGNORE_EXIT(-1); 5036 GOTO_NEXT_INST;
5507 } 5037 }
5508 } 5038
5509 cpu->Reg[15] += GET_INST_SIZE(cpu); 5039 QADD_INST:
5510 INC_PC(sizeof(rev_inst)); 5040 QADD8_INST:
5511 FETCH_INST; 5041 QADD16_INST:
5512 GOTO_NEXT_INST; 5042 QADDSUBX_INST:
5513 } 5043 QSUB8_INST:
5514 REV16_INST: 5044 QSUB16_INST:
5515 { 5045 QSUBADDX_INST:
5516 INC_ICOUNTER; 5046 {
5517 rev_inst *inst_cream = (rev_inst *)inst_base->component; 5047 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5518 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5048 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
5519 RD = (BITS(RM, 0, 7) << 8) | 5049 const u16 rm_lo = (RM & 0xFFFF);
5520 BITS(RM, 8, 15) | 5050 const u16 rm_hi = ((RM >> 16) & 0xFFFF);
5521 (BITS(RM, 16, 23) << 24) | 5051 const u16 rn_lo = (RN & 0xFFFF);
5522 (BITS(RM, 24, 31) << 16); 5052 const u16 rn_hi = ((RN >> 16) & 0xFFFF);
5523 } 5053 const u8 op2 = inst_cream->op2;
5524 cpu->Reg[15] += GET_INST_SIZE(cpu); 5054
5525 INC_PC(sizeof(rev_inst)); 5055 u16 lo_result = 0;
5526 FETCH_INST; 5056 u16 hi_result = 0;
5527 GOTO_NEXT_INST; 5057
5528 } 5058 // QADD16
5529 REVSH_INST: 5059 if (op2 == 0x00) {
5530 RFE_INST: 5060 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
5531 RSB_INST: 5061 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
5532 { 5062 }
5533 INC_ICOUNTER; 5063 // QASX
5534 rsb_inst *inst_cream = (rsb_inst *)inst_base->component; 5064 else if (op2 == 0x01) {
5535 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5065 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
5536 rop = RN; 5066 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
5537 lop = SHIFTER_OPERAND; 5067 }
5538 if (inst_cream->Rn == 15) { 5068 // QSAX
5539 rop += 2 * GET_INST_SIZE(cpu);; 5069 else if (op2 == 0x02) {
5540 } 5070 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
5541 RD = dst = lop - rop; 5071 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
5542 if (inst_cream->S && (inst_cream->Rd == 15)) { 5072 }
5543 /* cpsr = spsr */ 5073 // QSUB16
5544 if (CurrentModeHasSPSR) { 5074 else if (op2 == 0x03) {
5545 cpu->Cpsr = cpu->Spsr_copy; 5075 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
5546 switch_mode(cpu, cpu->Spsr_copy & 0x1f); 5076 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi);
5547 LOAD_NZCVT; 5077 }
5548 } 5078 // QADD8
5549 } else if (inst_cream->S) { 5079 else if (op2 == 0x04) {
5550 UPDATE_NFLAG(dst); 5080 lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) |
5551 UPDATE_ZFLAG(dst); 5081 ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8;
5552 UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop); 5082 hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) |
5553// UPDATE_VFLAG((int)dst, (int)lop, (int)rop); 5083 ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8;
5554 UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop); 5084 }
5555 } 5085 // QSUB8
5556 if (inst_cream->Rd == 15) { 5086 else if (op2 == 0x07) {
5557 INC_PC(sizeof(rsb_inst)); 5087 lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) |
5558 goto DISPATCH; 5088 ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8;
5559 } 5089 hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) |
5560 } 5090 ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8;
5561 cpu->Reg[15] += GET_INST_SIZE(cpu); 5091 }
5562 INC_PC(sizeof(rsb_inst)); 5092
5563 FETCH_INST; 5093 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
5564 GOTO_NEXT_INST; 5094 }
5565 } 5095
5566 RSC_INST: 5096 cpu->Reg[15] += GET_INST_SIZE(cpu);
5567 { 5097 INC_PC(sizeof(generic_arm_inst));
5568 INC_ICOUNTER; 5098 FETCH_INST;
5569 rsc_inst *inst_cream = (rsc_inst *)inst_base->component; 5099 GOTO_NEXT_INST;
5570 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5100 }
5571 //lop = RN + !cpu->CFlag; 5101
5572 //rop = SHIFTER_OPERAND; 5102 QDADD_INST:
5573 //RD = dst = rop - lop; 5103 QDSUB_INST:
5574 lop = RN; 5104 QSUB_INST:
5575 rop = SHIFTER_OPERAND; 5105 REV_INST:
5576 RD = dst = rop - lop - !cpu->CFlag; 5106 {
5577 if (inst_cream->S && (inst_cream->Rd == 15)) { 5107 rev_inst *inst_cream = (rev_inst *)inst_base->component;
5578 /* cpsr = spsr */ 5108 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5579 if (CurrentModeHasSPSR) { 5109 RD = ((RM & 0xff) << 24) |
5580 cpu->Cpsr = cpu->Spsr_copy; 5110 (((RM >> 8) & 0xff) << 16) |
5581 switch_mode(cpu, cpu->Spsr_copy & 0x1f); 5111 (((RM >> 16) & 0xff) << 8) |
5582 LOAD_NZCVT; 5112 ((RM >> 24) & 0xff);
5583 } 5113 if (inst_cream->Rm == 15) {
5584 } else if (inst_cream->S) { 5114 LOG_ERROR(Core_ARM11, "invalid operand for REV");
5585 UPDATE_NFLAG(dst); 5115 CITRA_IGNORE_EXIT(-1);
5586 UPDATE_ZFLAG(dst); 5116 }
5587// UPDATE_CFLAG(dst, lop, rop); 5117 }
5588// UPDATE_CFLAG_NOT_BORROW_FROM(rop, lop); 5118 cpu->Reg[15] += GET_INST_SIZE(cpu);
5589 UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(rop, lop, !cpu->CFlag); 5119 INC_PC(sizeof(rev_inst));
5590// cpu->CFlag = !((ISNEG(lop) && ISPOS(rop)) || (ISNEG(lop) && ISPOS(dst)) || (ISPOS(rop) && ISPOS(dst))); 5120 FETCH_INST;
5591 UPDATE_VFLAG_OVERFLOW_FROM((int)dst, (int)rop, (int)lop); 5121 GOTO_NEXT_INST;
5592 } 5122 }
5593 if (inst_cream->Rd == 15) { 5123 REV16_INST:
5594 INC_PC(sizeof(rsc_inst)); 5124 {
5595 goto DISPATCH; 5125 rev_inst *inst_cream = (rev_inst *)inst_base->component;
5596 } 5126 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5597 } 5127 RD = (BITS(RM, 0, 7) << 8) |
5598 cpu->Reg[15] += GET_INST_SIZE(cpu); 5128 BITS(RM, 8, 15) |
5599 INC_PC(sizeof(rsc_inst)); 5129 (BITS(RM, 16, 23) << 24) |
5600 FETCH_INST; 5130 (BITS(RM, 24, 31) << 16);
5601 GOTO_NEXT_INST; 5131 }
5602 } 5132 cpu->Reg[15] += GET_INST_SIZE(cpu);
5603 SADD16_INST: 5133 INC_PC(sizeof(rev_inst));
5604 SADD8_INST: 5134 FETCH_INST;
5605 SADDSUBX_INST: 5135 GOTO_NEXT_INST;
5606 SBC_INST: 5136 }
5607 { 5137 REVSH_INST:
5608 INC_ICOUNTER; 5138 RFE_INST:
5609 sbc_inst *inst_cream = (sbc_inst *)inst_base->component; 5139 RSB_INST:
5610 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5140 {
5611 lop = SHIFTER_OPERAND + !cpu->CFlag; 5141 rsb_inst *inst_cream = (rsb_inst *)inst_base->component;
5612 rop = RN; 5142 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5613 RD = dst = rop - lop; 5143 rop = RN;
5614 if (inst_cream->S && (inst_cream->Rd == 15)) { 5144 lop = SHIFTER_OPERAND;
5615 /* cpsr = spsr */ 5145 if (inst_cream->Rn == 15) {
5616 if (CurrentModeHasSPSR) { 5146 rop += 2 * GET_INST_SIZE(cpu);;
5617 cpu->Cpsr = cpu->Spsr_copy; 5147 }
5618 switch_mode(cpu, cpu->Spsr_copy & 0x1f); 5148 RD = dst = lop - rop;
5619 LOAD_NZCVT; 5149 if (inst_cream->S && (inst_cream->Rd == 15)) {
5620 } 5150 if (CurrentModeHasSPSR) {
5621 } else if (inst_cream->S) { 5151 cpu->Cpsr = cpu->Spsr_copy;
5622 UPDATE_NFLAG(dst); 5152 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
5623 UPDATE_ZFLAG(dst); 5153 LOAD_NZCVT;
5624// UPDATE_CFLAG(dst, lop, rop); 5154 }
5625 //UPDATE_CFLAG_NOT_BORROW_FROM(rop, lop); 5155 } else if (inst_cream->S) {
5626 //rop = rop - !cpu->CFlag; 5156 UPDATE_NFLAG(dst);
5627 if(rop >= !cpu->CFlag) 5157 UPDATE_ZFLAG(dst);
5628 UPDATE_CFLAG_NOT_BORROW_FROM(rop - !cpu->CFlag, SHIFTER_OPERAND); 5158 UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop);
5629 else 5159 UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop);
5630 UPDATE_CFLAG_NOT_BORROW_FROM(rop, !cpu->CFlag); 5160 }
5631// cpu->CFlag = !((ISNEG(lop) && ISPOS(rop)) || (ISNEG(lop) && ISPOS(dst)) || (ISPOS(rop) && ISPOS(dst))); 5161 if (inst_cream->Rd == 15) {
5632 UPDATE_VFLAG_OVERFLOW_FROM(dst, rop, lop); 5162 INC_PC(sizeof(rsb_inst));
5633 } 5163 goto DISPATCH;
5634 if (inst_cream->Rd == 15) { 5164 }
5635 INC_PC(sizeof(sbc_inst)); 5165 }
5636 goto DISPATCH; 5166 cpu->Reg[15] += GET_INST_SIZE(cpu);
5637 } 5167 INC_PC(sizeof(rsb_inst));
5638 } 5168 FETCH_INST;
5639 cpu->Reg[15] += GET_INST_SIZE(cpu); 5169 GOTO_NEXT_INST;
5640 INC_PC(sizeof(sbc_inst)); 5170 }
5641 FETCH_INST; 5171 RSC_INST:
5642 GOTO_NEXT_INST; 5172 {
5643 } 5173 rsc_inst *inst_cream = (rsc_inst *)inst_base->component;
5644 SEL_INST: 5174 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5645 SETEND_INST: 5175 lop = RN;
5646 SHADD16_INST: 5176 rop = SHIFTER_OPERAND;
5647 SHADD8_INST: 5177 RD = dst = rop - lop - !cpu->CFlag;
5648 SHADDSUBX_INST: 5178 if (inst_cream->S && (inst_cream->Rd == 15)) {
5649 SHSUB16_INST: 5179 if (CurrentModeHasSPSR) {
5650 SHSUB8_INST: 5180 cpu->Cpsr = cpu->Spsr_copy;
5651 SHSUBADDX_INST: 5181 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
5652 SMLA_INST: 5182 LOAD_NZCVT;
5653 { 5183 }
5654 INC_ICOUNTER; 5184 } else if (inst_cream->S) {
5655 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5185 UPDATE_NFLAG(dst);
5656 smla_inst *inst_cream = (smla_inst *)inst_base->component; 5186 UPDATE_ZFLAG(dst);
5657 int32_t operand1, operand2; 5187 UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(rop, lop, !cpu->CFlag);
5658 if (inst_cream->x == 0) 5188 UPDATE_VFLAG_OVERFLOW_FROM((int)dst, (int)rop, (int)lop);
5659 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15); 5189 }
5660 else 5190 if (inst_cream->Rd == 15) {
5661 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31); 5191 INC_PC(sizeof(rsc_inst));
5662 5192 goto DISPATCH;
5663 if (inst_cream->y == 0) 5193 }
5664 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15); 5194 }
5665 else 5195 cpu->Reg[15] += GET_INST_SIZE(cpu);
5666 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31); 5196 INC_PC(sizeof(rsc_inst));
5667 RD = operand1 * operand2 + RN; 5197 FETCH_INST;
5668 //FIXME: UPDATE Q FLAGS 5198 GOTO_NEXT_INST;
5669 } 5199 }
5670 cpu->Reg[15] += GET_INST_SIZE(cpu); 5200
5671 INC_PC(sizeof(smla_inst)); 5201 SADD8_INST:
5672 FETCH_INST; 5202 SADD16_INST:
5673 GOTO_NEXT_INST; 5203 SADDSUBX_INST:
5674 } 5204 SSUBADDX_INST:
5675 SMLAD_INST: 5205 SSUB16_INST:
5676 { 5206 {
5677 INC_ICOUNTER; 5207 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5678 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5208 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
5679 smlad_inst *inst_cream = (smlad_inst *)inst_base->component; 5209
5680 long long int rm = cpu->Reg[inst_cream->Rm]; 5210 const s16 rn_lo = (RN & 0xFFFF);
5681 long long int rn = cpu->Reg[inst_cream->Rn]; 5211 const s16 rn_hi = ((RN >> 16) & 0xFFFF);
5682 long long int ra = cpu->Reg[inst_cream->Ra]; 5212 const s16 rm_lo = (RM & 0xFFFF);
5683 /* see SMUAD */ 5213 const s16 rm_hi = ((RM >> 16) & 0xFFFF);
5684 if(inst_cream->Ra == 15) 5214
5685 CITRA_IGNORE_EXIT(-1); 5215 s32 lo_result = 0;
5686 int operand2 = (inst_cream->m)? ROTATE_RIGHT_32(rm, 16):rm; 5216 s32 hi_result = 0;
5687 5217
5688 int half_rn, half_operand2; 5218 // SADD16
5689 half_rn = rn & 0xFFFF; 5219 if (inst_cream->op2 == 0x00) {
5690 half_rn = (half_rn & 0x8000)? (0xFFFF0000|half_rn) : half_rn; 5220 lo_result = (rn_lo + rm_lo);
5691 5221 hi_result = (rn_hi + rm_hi);
5692 half_operand2 = operand2 & 0xFFFF; 5222 }
5693 half_operand2 = (half_operand2 & 0x8000)? (0xFFFF0000|half_operand2) : half_operand2; 5223 // SASX
5694 5224 else if (inst_cream->op2 == 0x01) {
5695 long long int product1 = half_rn * half_operand2; 5225 lo_result = (rn_lo - rm_hi);
5696 5226 hi_result = (rn_hi + rm_lo);
5697 half_rn = (rn & 0xFFFF0000) >> 16; 5227 }
5698 half_rn = (half_rn & 0x8000)? (0xFFFF0000|half_rn) : half_rn; 5228 // SSAX
5699 5229 else if (inst_cream->op2 == 0x02) {
5700 half_operand2 = (operand2 & 0xFFFF0000) >> 16; 5230 lo_result = (rn_lo + rm_hi);
5701 half_operand2 = (half_operand2 & 0x8000)? (0xFFFF0000|half_operand2) : half_operand2; 5231 hi_result = (rn_hi - rm_lo);
5702 5232 }
5703 long long int product2 = half_rn * half_operand2; 5233 // SSUB16
5704 5234 else if (inst_cream->op2 == 0x03) {
5705 long long int signed_ra = (ra & 0x80000000)? (0xFFFFFFFF00000000LL) | ra : ra; 5235 lo_result = (rn_lo - rm_lo);
5706 long long int result = product1 + product2 + signed_ra; 5236 hi_result = (rn_hi - rm_hi);
5707 cpu->Reg[inst_cream->Rd] = result & 0xFFFFFFFF; 5237 }
5708 /* FIXME , should check Signed overflow */ 5238
5709 } 5239 RD = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
5710 cpu->Reg[15] += GET_INST_SIZE(cpu); 5240
5711 INC_PC(sizeof(umlal_inst)); 5241 if (lo_result >= 0) {
5712 FETCH_INST; 5242 cpu->Cpsr |= (1 << 16);
5713 GOTO_NEXT_INST; 5243 cpu->Cpsr |= (1 << 17);
5714 } 5244 } else {
5715 5245 cpu->Cpsr &= ~(1 << 16);
5716 SMLAL_INST: 5246 cpu->Cpsr &= ~(1 << 17);
5717 { 5247 }
5718 INC_ICOUNTER; 5248
5719 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5249 if (hi_result >= 0) {
5720 umlal_inst *inst_cream = (umlal_inst *)inst_base->component; 5250 cpu->Cpsr |= (1 << 18);
5721 long long int rm = RM; 5251 cpu->Cpsr |= (1 << 19);
5722 long long int rs = RS; 5252 } else {
5723 if (BIT(rm, 31)) { 5253 cpu->Cpsr &= ~(1 << 18);
5724 rm |= 0xffffffff00000000LL; 5254 cpu->Cpsr &= ~(1 << 19);
5725 } 5255 }
5726 if (BIT(rs, 31)) { 5256 }
5727 rs |= 0xffffffff00000000LL; 5257
5728 } 5258 cpu->Reg[15] += GET_INST_SIZE(cpu);
5729 long long int rst = rm * rs; 5259 INC_PC(sizeof(generic_arm_inst));
5730 long long int rdhi32 = RDHI; 5260 FETCH_INST;
5731 long long int hilo = (rdhi32 << 32) + RDLO; 5261 GOTO_NEXT_INST;
5732 rst += hilo; 5262 }
5733 RDLO = BITS(rst, 0, 31); 5263
5734 RDHI = BITS(rst, 32, 63); 5264 SBC_INST:
5735 if (inst_cream->S) { 5265 {
5736 cpu->NFlag = BIT(RDHI, 31); 5266 sbc_inst *inst_cream = (sbc_inst *)inst_base->component;
5737 cpu->ZFlag = (RDHI == 0 && RDLO == 0); 5267 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5738 } 5268 lop = SHIFTER_OPERAND + !cpu->CFlag;
5739 } 5269 rop = RN;
5740 cpu->Reg[15] += GET_INST_SIZE(cpu); 5270 RD = dst = rop - lop;
5741 INC_PC(sizeof(umlal_inst)); 5271 if (inst_cream->S && (inst_cream->Rd == 15)) {
5742 FETCH_INST; 5272 if (CurrentModeHasSPSR) {
5743 GOTO_NEXT_INST; 5273 cpu->Cpsr = cpu->Spsr_copy;
5744 } 5274 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
5745 SMLALXY_INST: 5275 LOAD_NZCVT;
5746 SMLALD_INST: 5276 }
5747 SMLAW_INST: 5277 } else if (inst_cream->S) {
5748 SMLSD_INST: 5278 UPDATE_NFLAG(dst);
5749 SMLSLD_INST: 5279 UPDATE_ZFLAG(dst);
5750 SMMLA_INST: 5280
5751 SMMLS_INST: 5281 if(rop >= !cpu->CFlag)
5752 SMMUL_INST: 5282 UPDATE_CFLAG_NOT_BORROW_FROM(rop - !cpu->CFlag, SHIFTER_OPERAND);
5753 SMUAD_INST: 5283 else
5754 SMUL_INST: 5284 UPDATE_CFLAG_NOT_BORROW_FROM(rop, !cpu->CFlag);
5755 { 5285
5756 INC_ICOUNTER; 5286 UPDATE_VFLAG_OVERFLOW_FROM(dst, rop, lop);
5757 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5287 }
5758 smul_inst *inst_cream = (smul_inst *)inst_base->component; 5288 if (inst_cream->Rd == 15) {
5759 uint32_t operand1, operand2; 5289 INC_PC(sizeof(sbc_inst));
5760 if (inst_cream->x == 0) 5290 goto DISPATCH;
5761 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15); 5291 }
5762 else 5292 }
5763 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31); 5293 cpu->Reg[15] += GET_INST_SIZE(cpu);
5764 5294 INC_PC(sizeof(sbc_inst));
5765 if (inst_cream->y == 0) 5295 FETCH_INST;
5766 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15); 5296 GOTO_NEXT_INST;
5767 else 5297 }
5768 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31); 5298
5769 RD = operand1 * operand2; 5299 SEL_INST:
5770 } 5300 {
5771 cpu->Reg[15] += GET_INST_SIZE(cpu); 5301 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5772 INC_PC(sizeof(smul_inst)); 5302 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
5773 FETCH_INST; 5303
5774 GOTO_NEXT_INST; 5304 const u32 to = RM;
5775 } 5305 const u32 from = RN;
5776 SMULL_INST: 5306 const u32 cpsr = cpu->Cpsr;
5777 { 5307
5778 INC_ICOUNTER; 5308 u32 result;
5779 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5309 if (cpsr & (1 << 16))
5780 umull_inst *inst_cream = (umull_inst *)inst_base->component; 5310 result = from & 0xff;
5781// DEBUG_LOG(ARM11, "rm : [%llx] rs : [%llx] rst [%llx]\n", RM, RS, rst); 5311 else
5782 int64_t rm = RM; 5312 result = to & 0xff;
5783 int64_t rs = RS; 5313
5784 if (BIT(rm, 31)) { 5314 if (cpsr & (1 << 17))
5785 rm |= 0xffffffff00000000LL; 5315 result |= from & 0x0000ff00;
5786 } 5316 else
5787 if (BIT(rs, 31)) { 5317 result |= to & 0x0000ff00;
5788 rs |= 0xffffffff00000000LL; 5318
5789 } 5319 if (cpsr & (1 << 18))
5790 int64_t rst = rm * rs; 5320 result |= from & 0x00ff0000;
5791 RDHI = BITS(rst, 32, 63); 5321 else
5792 RDLO = BITS(rst, 0, 31); 5322 result |= to & 0x00ff0000;
5793 5323
5794 5324 if (cpsr & (1 << 19))
5795 if (inst_cream->S) { 5325 result |= from & 0xff000000;
5796 cpu->NFlag = BIT(RDHI, 31); 5326 else
5797 cpu->ZFlag = (RDHI == 0 && RDLO == 0); 5327 result |= to & 0xff000000;
5798 } 5328
5799 } 5329 RD = result;
5800 cpu->Reg[15] += GET_INST_SIZE(cpu); 5330 }
5801 INC_PC(sizeof(umull_inst)); 5331
5802 FETCH_INST; 5332 cpu->Reg[15] += GET_INST_SIZE(cpu);
5803 GOTO_NEXT_INST; 5333 INC_PC(sizeof(generic_arm_inst));
5804 } 5334 FETCH_INST;
5805 SMULW_INST: 5335 GOTO_NEXT_INST;
5806 INC_ICOUNTER; 5336 }
5807 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5337
5808 smlad_inst *inst_cream = (smlad_inst *)inst_base->component; 5338 SETEND_INST:
5809// DEBUG_LOG(ARM11, "rm : [%llx] rs : [%llx] rst [%llx]\n", RM, RS, rst); 5339 SHADD16_INST:
5810 int64_t rm = RM; 5340 SHADD8_INST:
5811 int64_t rn = RN; 5341 SHADDSUBX_INST:
5812 if (inst_cream->m) 5342 SHSUB16_INST:
5813 rm = BITS(rm,16 , 31); 5343 SHSUB8_INST:
5814 else 5344 SHSUBADDX_INST:
5815 rm = BITS(rm,0 , 15); 5345 SMLA_INST:
5816 int64_t rst = rm * rn; 5346 {
5817 RD = BITS(rst, 16, 47); 5347 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5818 } 5348 smla_inst *inst_cream = (smla_inst *)inst_base->component;
5819 cpu->Reg[15] += GET_INST_SIZE(cpu); 5349 int32_t operand1, operand2;
5820 INC_PC(sizeof(smlad_inst)); 5350 if (inst_cream->x == 0)
5821 FETCH_INST; 5351 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
5822 GOTO_NEXT_INST; 5352 else
5823 5353 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
5824 SMUSD_INST: 5354
5825 SRS_INST: 5355 if (inst_cream->y == 0)
5826 SSAT_INST: 5356 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15);
5827 SSAT16_INST: 5357 else
5828 SSUB16_INST: 5358 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
5829 SSUB8_INST: 5359 RD = operand1 * operand2 + RN;
5830 SSUBADDX_INST: 5360
5831 STC_INST: 5361 // TODO: FIXME: UPDATE Q FLAGS
5832 { 5362 }
5833 INC_ICOUNTER; 5363 cpu->Reg[15] += GET_INST_SIZE(cpu);
5834 /* NOT IMPL */ 5364 INC_PC(sizeof(smla_inst));
5835 cpu->Reg[15] += GET_INST_SIZE(cpu); 5365 FETCH_INST;
5836 INC_PC(sizeof(stc_inst)); 5366 GOTO_NEXT_INST;
5837 FETCH_INST; 5367 }
5838 GOTO_NEXT_INST; 5368 SMLAD_INST:
5839 } 5369 {
5840 STM_INST: 5370 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5841 { 5371 smlad_inst *inst_cream = (smlad_inst *)inst_base->component;
5842 INC_ICOUNTER; 5372 long long int rm = cpu->Reg[inst_cream->Rm];
5843 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 5373 long long int rn = cpu->Reg[inst_cream->Rn];
5844 unsigned int inst = inst_cream->inst; 5374 long long int ra = cpu->Reg[inst_cream->Ra];
5845 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5375
5846 int i; 5376 // See SMUAD
5847 unsigned int Rn = BITS(inst, 16, 19); 5377 if(inst_cream->Ra == 15)
5848 unsigned int old_RN = cpu->Reg[Rn]; 5378 CITRA_IGNORE_EXIT(-1);
5849 5379 int operand2 = (inst_cream->m)? ROTATE_RIGHT_32(rm, 16):rm;
5850 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0); 5380 int half_rn, half_operand2;
5851 if (fault) goto MMU_EXCEPTION; 5381
5852 if (BIT(inst_cream->inst, 22) == 1) { 5382 half_rn = rn & 0xFFFF;
5853// DEBUG_MSG; 5383 half_rn = (half_rn & 0x8000)? (0xFFFF0000|half_rn) : half_rn;
5854 #if 1 5384
5855 for (i = 0; i < 13; i++) { 5385 half_operand2 = operand2 & 0xFFFF;
5856 if(BIT(inst_cream->inst, i)){ 5386 half_operand2 = (half_operand2 & 0x8000)? (0xFFFF0000|half_operand2) : half_operand2;
5857 fault = check_address_validity(cpu, addr, &phys_addr, 0); 5387
5858 if (fault) { 5388 long long int product1 = half_rn * half_operand2;
5859 goto MMU_EXCEPTION; 5389
5860 } 5390 half_rn = (rn & 0xFFFF0000) >> 16;
5861 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32); 5391 half_rn = (half_rn & 0x8000)? (0xFFFF0000|half_rn) : half_rn;
5862 if (fault) goto MMU_EXCEPTION; 5392
5863 addr += 4; 5393 half_operand2 = (operand2 & 0xFFFF0000) >> 16;
5864 phys_addr += 4; 5394 half_operand2 = (half_operand2 & 0x8000)? (0xFFFF0000|half_operand2) : half_operand2;
5865 } 5395
5866 } 5396 long long int product2 = half_rn * half_operand2;
5867 if (BIT(inst_cream->inst, 13)) { 5397
5868 if (cpu->Mode == USER32MODE) { 5398 long long int signed_ra = (ra & 0x80000000)? (0xFFFFFFFF00000000LL) | ra : ra;
5869 fault = check_address_validity(cpu, addr, &phys_addr, 0); 5399 long long int result = product1 + product2 + signed_ra;
5870 if (fault) { 5400 cpu->Reg[inst_cream->Rd] = result & 0xFFFFFFFF;
5871 goto MMU_EXCEPTION; 5401
5872 } 5402 // TODO: FIXME should check Signed overflow
5873 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32); 5403 }
5874 if (fault) goto MMU_EXCEPTION; 5404 cpu->Reg[15] += GET_INST_SIZE(cpu);
5875 addr += 4; 5405 INC_PC(sizeof(umlal_inst));
5876 phys_addr += 4; 5406 FETCH_INST;
5877 } else { 5407 GOTO_NEXT_INST;
5878 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg_usr[0], 32); 5408 }
5879 if (fault) goto MMU_EXCEPTION; 5409
5880 addr += 4; 5410 SMLAL_INST:
5881 phys_addr += 4; 5411 {
5882 } 5412 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5883 } 5413 umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
5884 if (BIT(inst_cream->inst, 14)) { 5414 long long int rm = RM;
5885 if (cpu->Mode == USER32MODE) { 5415 long long int rs = RS;
5886 fault = check_address_validity(cpu, addr, &phys_addr, 0); 5416 if (BIT(rm, 31)) {
5887 if (fault) { 5417 rm |= 0xffffffff00000000LL;
5888 goto MMU_EXCEPTION; 5418 }
5889 } 5419 if (BIT(rs, 31)) {
5890 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32); 5420 rs |= 0xffffffff00000000LL;
5891 if (fault) goto MMU_EXCEPTION; 5421 }
5892 addr += 4; 5422 long long int rst = rm * rs;
5893 phys_addr += 4; 5423 long long int rdhi32 = RDHI;
5894 } else { 5424 long long int hilo = (rdhi32 << 32) + RDLO;
5895 fault = check_address_validity(cpu, addr, &phys_addr, 0); 5425 rst += hilo;
5896 if (fault) { 5426 RDLO = BITS(rst, 0, 31);
5897 goto MMU_EXCEPTION; 5427 RDHI = BITS(rst, 32, 63);
5898 } 5428 if (inst_cream->S) {
5899 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg_usr[1], 32); 5429 cpu->NFlag = BIT(RDHI, 31);
5900 if (fault) goto MMU_EXCEPTION; 5430 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
5901 addr += 4; 5431 }
5902 phys_addr += 4; 5432 }
5903 } 5433 cpu->Reg[15] += GET_INST_SIZE(cpu);
5904 } 5434 INC_PC(sizeof(umlal_inst));
5905 if (BIT(inst_cream->inst, 15)) { 5435 FETCH_INST;
5906 fault = check_address_validity(cpu, addr, &phys_addr, 0); 5436 GOTO_NEXT_INST;
5907 if (fault) { 5437 }
5908 goto MMU_EXCEPTION; 5438 SMLALXY_INST:
5909 } 5439 SMLALD_INST:
5910 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i] + 8, 32); 5440 SMLAW_INST:
5911 if (fault) goto MMU_EXCEPTION; 5441 SMLSD_INST:
5912 } 5442 SMLSLD_INST:
5913 #endif 5443 SMMLA_INST:
5914 } else { 5444 SMMLS_INST:
5915 for( i = 0; i < 15; i ++ ){ 5445 SMMUL_INST:
5916 if(BIT(inst_cream->inst, i)){ 5446 SMUAD_INST:
5917 //arch_write_memory(cpu, bb, Addr, R(i), 32); 5447 SMUL_INST:
5918 //bus_write(32, addr, cpu->Reg[i]); 5448 {
5919 fault = check_address_validity(cpu, addr, &phys_addr, 0); 5449 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5920 if (fault) { 5450 smul_inst *inst_cream = (smul_inst *)inst_base->component;
5921 goto MMU_EXCEPTION; 5451 uint32_t operand1, operand2;
5922 } 5452 if (inst_cream->x == 0)
5923 if(i == Rn) 5453 operand1 = (BIT(RM, 15)) ? (BITS(RM, 0, 15) | 0xffff0000) : BITS(RM, 0, 15);
5924 fault = interpreter_write_memory(addr, phys_addr, old_RN, 32); 5454 else
5925 else 5455 operand1 = (BIT(RM, 31)) ? (BITS(RM, 16, 31) | 0xffff0000) : BITS(RM, 16, 31);
5926 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32); 5456
5927 if (fault) goto MMU_EXCEPTION; 5457 if (inst_cream->y == 0)
5928 addr += 4; 5458 operand2 = (BIT(RS, 15)) ? (BITS(RS, 0, 15) | 0xffff0000) : BITS(RS, 0, 15);
5929 phys_addr += 4; 5459 else
5930 //Addr = ADD(Addr, CONST(4)); 5460 operand2 = (BIT(RS, 31)) ? (BITS(RS, 16, 31) | 0xffff0000) : BITS(RS, 16, 31);
5931 } 5461 RD = operand1 * operand2;
5932 } 5462 }
5933 5463 cpu->Reg[15] += GET_INST_SIZE(cpu);
5934 /* check pc reg*/ 5464 INC_PC(sizeof(smul_inst));
5935 if(BIT(inst_cream->inst, i)){ 5465 FETCH_INST;
5936 //arch_write_memory(cpu, bb, Addr, STOREM_CHECK_PC, 32); 5466 GOTO_NEXT_INST;
5937 //bus_write(32, addr, cpu->Reg[i] + 8); 5467 }
5938 fault = check_address_validity(cpu, addr, &phys_addr, 0); 5468 SMULL_INST:
5939 if (fault) { 5469 {
5940 goto MMU_EXCEPTION; 5470 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5941 } 5471 umull_inst *inst_cream = (umull_inst *)inst_base->component;
5942 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i] + 8, 32); 5472 int64_t rm = RM;
5943 if (fault) goto MMU_EXCEPTION; 5473 int64_t rs = RS;
5944 } 5474 if (BIT(rm, 31)) {
5945 } 5475 rm |= 0xffffffff00000000LL;
5946 } 5476 }
5947 cpu->Reg[15] += GET_INST_SIZE(cpu); 5477 if (BIT(rs, 31)) {
5948 INC_PC(sizeof(ldst_inst)); 5478 rs |= 0xffffffff00000000LL;
5949 FETCH_INST; 5479 }
5950 GOTO_NEXT_INST; 5480 int64_t rst = rm * rs;
5951 } 5481 RDHI = BITS(rst, 32, 63);
5952 SXTB_INST: 5482 RDLO = BITS(rst, 0, 31);
5953 { 5483
5954 INC_ICOUNTER; 5484 if (inst_cream->S) {
5955 sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component; 5485 cpu->NFlag = BIT(RDHI, 31);
5956 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5486 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
5957 if (inst_cream->Rm == 15) { 5487 }
5958 LOG_ERROR(Core_ARM11, "invalid operand for SXTB"); 5488 }
5959 CITRA_IGNORE_EXIT(-1); 5489 cpu->Reg[15] += GET_INST_SIZE(cpu);
5960 } 5490 INC_PC(sizeof(umull_inst));
5961 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate); 5491 FETCH_INST;
5962 if (BIT(operand2, 7)) { 5492 GOTO_NEXT_INST;
5963 operand2 |= 0xffffff00; 5493 }
5964 } else 5494
5965 operand2 &= 0xff; 5495 SMULW_INST:
5966 RD = operand2; 5496 {
5967 } 5497 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5968 cpu->Reg[15] += GET_INST_SIZE(cpu); 5498 smlad_inst *inst_cream = (smlad_inst *)inst_base->component;
5969 INC_PC(sizeof(sxtb_inst)); 5499 int64_t rm = RM;
5970 FETCH_INST; 5500 int64_t rn = RN;
5971 GOTO_NEXT_INST; 5501 if (inst_cream->m)
5972 } 5502 rm = BITS(rm, 16, 31);
5973 STR_INST: 5503 else
5974 { 5504 rm = BITS(rm, 0, 15);
5975 INC_ICOUNTER; 5505 int64_t rst = rm * rn;
5976 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 5506 RD = BITS(rst, 16, 47);
5977 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5507 }
5978 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0); 5508 cpu->Reg[15] += GET_INST_SIZE(cpu);
5979 if (fault) goto MMU_EXCEPTION; 5509 INC_PC(sizeof(smlad_inst));
5980 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; 5510 FETCH_INST;
5981 //bus_write(32, addr, value); 5511 GOTO_NEXT_INST;
5982 fault = interpreter_write_memory(addr, phys_addr, value, 32); 5512 }
5983 if (fault) goto MMU_EXCEPTION; 5513
5984 } 5514 SMUSD_INST:
5985 cpu->Reg[15] += GET_INST_SIZE(cpu); 5515 SRS_INST:
5986 INC_PC(sizeof(ldst_inst)); 5516 SSAT_INST:
5987 FETCH_INST; 5517 SSAT16_INST:
5988 GOTO_NEXT_INST; 5518 SSUB8_INST:
5989 } 5519 STC_INST:
5990 UXTB_INST: 5520 {
5991 { 5521 // Instruction not implemented
5992 INC_ICOUNTER; 5522 //LOG_CRITICAL(Core_ARM11, "unimplemented instruction");
5993 uxtb_inst *inst_cream = (uxtb_inst *)inst_base->component; 5523 cpu->Reg[15] += GET_INST_SIZE(cpu);
5994 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5524 INC_PC(sizeof(stc_inst));
5995 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) 5525 FETCH_INST;
5996 & 0xff; 5526 GOTO_NEXT_INST;
5997 RD = operand2; 5527 }
5998 } 5528 STM_INST:
5999 cpu->Reg[15] += GET_INST_SIZE(cpu); 5529 {
6000 INC_PC(sizeof(uxtb_inst)); 5530 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
6001 FETCH_INST; 5531 unsigned int inst = inst_cream->inst;
6002 GOTO_NEXT_INST; 5532 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6003 } 5533 int i;
6004 UXTAB_INST: 5534 unsigned int Rn = BITS(inst, 16, 19);
6005 { 5535 unsigned int old_RN = cpu->Reg[Rn];
6006 INC_ICOUNTER; 5536
6007 uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component; 5537 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0);
6008 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5538 if (fault) goto MMU_EXCEPTION;
6009 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) 5539 if (BIT(inst_cream->inst, 22) == 1) {
6010 & 0xff; 5540 for (i = 0; i < 13; i++) {
6011 RD = RN + operand2; 5541 if(BIT(inst_cream->inst, i)){
6012 } 5542 fault = check_address_validity(cpu, addr, &phys_addr, 0);
6013 cpu->Reg[15] += GET_INST_SIZE(cpu); 5543 if (fault) goto MMU_EXCEPTION;
6014 INC_PC(sizeof(uxtab_inst)); 5544 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32);
6015 FETCH_INST; 5545 if (fault) goto MMU_EXCEPTION;
6016 GOTO_NEXT_INST; 5546 addr += 4;
6017 } 5547 phys_addr += 4;
6018 STRB_INST: 5548 }
6019 { 5549 }
6020 INC_ICOUNTER; 5550 if (BIT(inst_cream->inst, 13)) {
6021 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 5551 if (cpu->Mode == USER32MODE) {
6022 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5552 fault = check_address_validity(cpu, addr, &phys_addr, 0);
6023 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0); 5553 if (fault) goto MMU_EXCEPTION;
6024 if (fault) goto MMU_EXCEPTION; 5554 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32);
6025 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; 5555 if (fault) goto MMU_EXCEPTION;
6026 //bus_write(8, addr, value); 5556 addr += 4;
6027 fault = interpreter_write_memory(addr, phys_addr, value, 8); 5557 phys_addr += 4;
6028 if (fault) goto MMU_EXCEPTION; 5558 } else {
6029 } 5559 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg_usr[0], 32);
6030 cpu->Reg[15] += GET_INST_SIZE(cpu); 5560 if (fault) goto MMU_EXCEPTION;
6031 INC_PC(sizeof(ldst_inst)); 5561 addr += 4;
6032 FETCH_INST; 5562 phys_addr += 4;
6033 GOTO_NEXT_INST; 5563 }
6034 } 5564 }
6035 STRBT_INST: 5565 if (BIT(inst_cream->inst, 14)) {
6036 { 5566 if (cpu->Mode == USER32MODE) {
6037 INC_ICOUNTER; 5567 fault = check_address_validity(cpu, addr, &phys_addr, 0);
6038 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 5568 if (fault) goto MMU_EXCEPTION;
6039 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5569 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32);
6040 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0); 5570 if (fault) goto MMU_EXCEPTION;
6041 if (fault) goto MMU_EXCEPTION; 5571 addr += 4;
6042 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff; 5572 phys_addr += 4;
6043 //bus_write(8, addr, value); 5573 } else {
6044 fault = interpreter_write_memory(addr, phys_addr, value, 8); 5574 fault = check_address_validity(cpu, addr, &phys_addr, 0);
6045 if (fault) goto MMU_EXCEPTION; 5575 if (fault) goto MMU_EXCEPTION;
6046 } 5576 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg_usr[1], 32);
6047 cpu->Reg[15] += GET_INST_SIZE(cpu); 5577 if (fault) goto MMU_EXCEPTION;
6048 //if (BITS(inst_cream->inst, 12, 15) == 15) 5578 addr += 4;
6049 // goto DISPATCH; 5579 phys_addr += 4;
6050 INC_PC(sizeof(ldst_inst)); 5580 }
6051 FETCH_INST; 5581 }
6052 GOTO_NEXT_INST; 5582 if (BIT(inst_cream->inst, 15)) {
6053 } 5583 fault = check_address_validity(cpu, addr, &phys_addr, 0);
6054 STRD_INST: 5584 if (fault) goto MMU_EXCEPTION;
6055 { 5585 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i] + 8, 32);
6056 INC_ICOUNTER; 5586 if (fault) goto MMU_EXCEPTION;
6057 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 5587 }
6058 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5588 } else {
6059 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0); 5589 for( i = 0; i < 15; i ++ ) {
6060 if (fault) goto MMU_EXCEPTION; 5590 if(BIT(inst_cream->inst, i)) {
6061 uint32_t rear_phys_addr; 5591 fault = check_address_validity(cpu, addr, &phys_addr, 0);
6062 fault = check_address_validity(cpu, addr + 4, &rear_phys_addr, 0); 5592 if (fault) goto MMU_EXCEPTION;
5593 if(i == Rn)
5594 fault = interpreter_write_memory(addr, phys_addr, old_RN, 32);
5595 else
5596 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i], 32);
5597 if (fault) goto MMU_EXCEPTION;
5598 addr += 4;
5599 phys_addr += 4;
5600 }
5601 }
5602
5603 // Check PC reg
5604 if(BIT(inst_cream->inst, i)) {
5605 fault = check_address_validity(cpu, addr, &phys_addr, 0);
5606 if (fault) goto MMU_EXCEPTION;
5607 fault = interpreter_write_memory(addr, phys_addr, cpu->Reg[i] + 8, 32);
5608 if (fault) goto MMU_EXCEPTION;
5609 }
5610 }
5611 }
5612 cpu->Reg[15] += GET_INST_SIZE(cpu);
5613 INC_PC(sizeof(ldst_inst));
5614 FETCH_INST;
5615 GOTO_NEXT_INST;
5616 }
5617 SXTB_INST:
5618 {
5619 sxtb_inst *inst_cream = (sxtb_inst *)inst_base->component;
5620 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5621 if (inst_cream->Rm == 15) {
5622 LOG_ERROR(Core_ARM11, "invalid operand for SXTB");
5623 CITRA_IGNORE_EXIT(-1);
5624 }
5625 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate);
5626 if (BIT(operand2, 7)) {
5627 operand2 |= 0xffffff00;
5628 } else
5629 operand2 &= 0xff;
5630 RD = operand2;
5631 }
5632 cpu->Reg[15] += GET_INST_SIZE(cpu);
5633 INC_PC(sizeof(sxtb_inst));
5634 FETCH_INST;
5635 GOTO_NEXT_INST;
5636 }
5637 STR_INST:
5638 {
5639 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
5640 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5641 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0);
5642 if (fault) goto MMU_EXCEPTION;
5643 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
5644 fault = interpreter_write_memory(addr, phys_addr, value, 32);
5645 if (fault) goto MMU_EXCEPTION;
5646 }
5647 cpu->Reg[15] += GET_INST_SIZE(cpu);
5648 INC_PC(sizeof(ldst_inst));
5649 FETCH_INST;
5650 GOTO_NEXT_INST;
5651 }
5652 UXTB_INST:
5653 {
5654 uxtb_inst *inst_cream = (uxtb_inst *)inst_base->component;
5655 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5656 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate)
5657 & 0xff;
5658 RD = operand2;
5659 }
5660 cpu->Reg[15] += GET_INST_SIZE(cpu);
5661 INC_PC(sizeof(uxtb_inst));
5662 FETCH_INST;
5663 GOTO_NEXT_INST;
5664 }
5665 UXTAB_INST:
5666 {
5667 uxtab_inst *inst_cream = (uxtab_inst *)inst_base->component;
5668 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5669 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate)
5670 & 0xff;
5671 RD = RN + operand2;
5672 }
5673 cpu->Reg[15] += GET_INST_SIZE(cpu);
5674 INC_PC(sizeof(uxtab_inst));
5675 FETCH_INST;
5676 GOTO_NEXT_INST;
5677 }
5678 STRB_INST:
5679 {
5680 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
5681 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5682 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0);
5683 if (fault) goto MMU_EXCEPTION;
5684 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
5685 fault = interpreter_write_memory(addr, phys_addr, value, 8);
5686 if (fault) goto MMU_EXCEPTION;
5687 }
5688 cpu->Reg[15] += GET_INST_SIZE(cpu);
5689 INC_PC(sizeof(ldst_inst));
5690 FETCH_INST;
5691 GOTO_NEXT_INST;
5692 }
5693 STRBT_INST:
5694 {
5695 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
5696 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5697 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0);
5698 if (fault) goto MMU_EXCEPTION;
5699 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xff;
5700 fault = interpreter_write_memory(addr, phys_addr, value, 8);
5701 if (fault) goto MMU_EXCEPTION;
5702 }
5703 cpu->Reg[15] += GET_INST_SIZE(cpu);
5704 INC_PC(sizeof(ldst_inst));
5705 FETCH_INST;
5706 GOTO_NEXT_INST;
5707 }
5708 STRD_INST:
5709 {
5710 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
5711 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5712 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0);
5713 if (fault) goto MMU_EXCEPTION;
5714 uint32_t rear_phys_addr;
5715 fault = check_address_validity(cpu, addr + 4, &rear_phys_addr, 0);
6063 if (fault){ 5716 if (fault){
6064 LOG_ERROR(Core_ARM11, "mmu fault , should rollback the above get_addr\n"); 5717 LOG_ERROR(Core_ARM11, "MMU fault , should rollback the above get_addr");
6065 CITRA_IGNORE_EXIT(-1); 5718 CITRA_IGNORE_EXIT(-1);
6066 goto MMU_EXCEPTION; 5719 goto MMU_EXCEPTION;
6067 } 5720 }
6068 5721
6069 //fault = inst_cream->get_addr(cpu, inst_cream->inst, addr + 4, phys_addr + 4, 0); 5722 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
6070 //if (fault) goto MMU_EXCEPTION; 5723 fault = interpreter_write_memory(addr, phys_addr, value, 32);
6071 5724 if (fault) goto MMU_EXCEPTION;
6072 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; 5725 value = cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1];
6073 //bus_write(32, addr, value); 5726 fault = interpreter_write_memory(addr + 4, rear_phys_addr, value, 32);
6074 fault = interpreter_write_memory(addr, phys_addr, value, 32); 5727 if (fault) goto MMU_EXCEPTION;
6075 if (fault) goto MMU_EXCEPTION; 5728 }
6076 value = cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]; 5729 cpu->Reg[15] += GET_INST_SIZE(cpu);
6077 //bus_write(32, addr, value); 5730 INC_PC(sizeof(ldst_inst));
6078 fault = interpreter_write_memory(addr + 4, rear_phys_addr, value, 32); 5731 FETCH_INST;
6079 if (fault) goto MMU_EXCEPTION; 5732 GOTO_NEXT_INST;
6080 } 5733 }
6081 cpu->Reg[15] += GET_INST_SIZE(cpu); 5734 STREX_INST:
6082 INC_PC(sizeof(ldst_inst)); 5735 {
6083 FETCH_INST; 5736 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
6084 GOTO_NEXT_INST; 5737 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6085 } 5738 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)];
6086 STREX_INST: 5739 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 0, 3)];
6087 { 5740 fault = check_address_validity(cpu, addr, &phys_addr, 0);
6088 INC_ICOUNTER; 5741 if (fault) goto MMU_EXCEPTION;
6089 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 5742
6090 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5743 int dest_reg = BITS(inst_cream->inst, 12, 15);
6091 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; 5744 if((exclusive_detect(cpu, phys_addr) == 0) && (cpu->exclusive_state == 1)){
6092 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 0, 3)]; 5745 remove_exclusive(cpu, phys_addr);
6093 fault = check_address_validity(cpu, addr, &phys_addr, 0); 5746 cpu->Reg[dest_reg] = 0;
6094 if (fault) goto MMU_EXCEPTION; 5747 cpu->exclusive_state = 0;
6095 5748
6096 int dest_reg = BITS(inst_cream->inst, 12, 15); 5749 fault = interpreter_write_memory(addr, phys_addr, value, 32);
6097 if((exclusive_detect(cpu, phys_addr) == 0) && (cpu->exclusive_state == 1)){ 5750 if (fault) goto MMU_EXCEPTION;
6098 remove_exclusive(cpu, phys_addr); 5751 } else {
6099 cpu->Reg[dest_reg] = 0; 5752 // Failed to write due to mutex access
6100 cpu->exclusive_state = 0; 5753 cpu->Reg[dest_reg] = 1;
6101 5754 }
6102 // bus_write(32, addr, value); 5755 }
6103 fault = interpreter_write_memory(addr, phys_addr, value, 32); 5756 cpu->Reg[15] += GET_INST_SIZE(cpu);
6104 if (fault) goto MMU_EXCEPTION; 5757 INC_PC(sizeof(ldst_inst));
6105 } 5758 FETCH_INST;
6106 else{ 5759 GOTO_NEXT_INST;
6107 /* Failed to write due to mutex access */ 5760 }
6108 cpu->Reg[dest_reg] = 1; 5761 STREXB_INST:
6109 } 5762 {
6110 } 5763 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
6111 cpu->Reg[15] += GET_INST_SIZE(cpu); 5764 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6112 INC_PC(sizeof(ldst_inst)); 5765 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)];
6113 FETCH_INST; 5766 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 0, 3)] & 0xff;
6114 GOTO_NEXT_INST; 5767 fault = check_address_validity(cpu, addr, &phys_addr, 0);
6115 } 5768 if (fault) goto MMU_EXCEPTION;
6116 STREXB_INST: 5769 int dest_reg = BITS(inst_cream->inst, 12, 15);
6117 { 5770 if((exclusive_detect(cpu, phys_addr) == 0) && (cpu->exclusive_state == 1)){
6118 INC_ICOUNTER; 5771 remove_exclusive(cpu, phys_addr);
6119 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 5772 cpu->Reg[dest_reg] = 0;
6120 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5773 cpu->exclusive_state = 0;
6121 addr = cpu->Reg[BITS(inst_cream->inst, 16, 19)]; 5774 fault = interpreter_write_memory(addr, phys_addr, value, 8);
6122 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 0, 3)] & 0xff; 5775 if (fault) goto MMU_EXCEPTION;
6123 fault = check_address_validity(cpu, addr, &phys_addr, 0); 5776 } else {
6124 if (fault) goto MMU_EXCEPTION; 5777 cpu->Reg[dest_reg] = 1;
6125 //bus_write(8, addr, value); 5778 }
6126 int dest_reg = BITS(inst_cream->inst, 12, 15); 5779 }
6127 if((exclusive_detect(cpu, phys_addr) == 0) && (cpu->exclusive_state == 1)){ 5780 cpu->Reg[15] += GET_INST_SIZE(cpu);
6128 remove_exclusive(cpu, phys_addr); 5781 INC_PC(sizeof(ldst_inst));
6129 cpu->Reg[dest_reg] = 0; 5782 FETCH_INST;
6130 cpu->exclusive_state = 0; 5783 GOTO_NEXT_INST;
6131 fault = interpreter_write_memory(addr, phys_addr, value, 8); 5784 }
6132 if (fault) goto MMU_EXCEPTION; 5785 STRH_INST:
6133 5786 {
6134 } 5787 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
6135 else{ 5788 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6136 cpu->Reg[dest_reg] = 1; 5789 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0);
6137 } 5790 if (fault) goto MMU_EXCEPTION;
6138 } 5791 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff;
6139 cpu->Reg[15] += GET_INST_SIZE(cpu); 5792 fault = interpreter_write_memory(addr, phys_addr, value, 16);
6140 INC_PC(sizeof(ldst_inst)); 5793 if (fault) goto MMU_EXCEPTION;
6141 FETCH_INST; 5794 }
6142 GOTO_NEXT_INST; 5795 cpu->Reg[15] += GET_INST_SIZE(cpu);
6143 } 5796 INC_PC(sizeof(ldst_inst));
6144 STRH_INST: 5797 FETCH_INST;
6145 { 5798 GOTO_NEXT_INST;
6146 INC_ICOUNTER; 5799 }
6147 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 5800 STRT_INST:
6148 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5801 {
6149 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0); 5802 ldst_inst *inst_cream = (ldst_inst *)inst_base->component;
6150 if (fault) goto MMU_EXCEPTION; 5803 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6151 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff; 5804 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0);
6152 //bus_write(16, addr, value); 5805 if (fault) goto MMU_EXCEPTION;
6153 fault = interpreter_write_memory(addr, phys_addr, value, 16); 5806 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)];
6154 if (fault) goto MMU_EXCEPTION; 5807 fault = interpreter_write_memory(addr, phys_addr, value, 32);
6155 } 5808 if (fault) goto MMU_EXCEPTION;
6156 cpu->Reg[15] += GET_INST_SIZE(cpu); 5809 }
6157 //if (BITS(inst_cream->inst, 12, 15) == 15) 5810 cpu->Reg[15] += GET_INST_SIZE(cpu);
6158 // goto DISPATCH; 5811 INC_PC(sizeof(ldst_inst));
6159 INC_PC(sizeof(ldst_inst)); 5812 FETCH_INST;
6160 FETCH_INST; 5813 GOTO_NEXT_INST;
6161 GOTO_NEXT_INST; 5814 }
6162 } 5815 SUB_INST:
6163 STRT_INST: 5816 {
6164 { 5817 sub_inst *inst_cream = (sub_inst *)inst_base->component;
6165 INC_ICOUNTER; 5818 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6166 ldst_inst *inst_cream = (ldst_inst *)inst_base->component; 5819 lop = RN;
6167 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5820 if (inst_cream->Rn == 15) {
6168 fault = inst_cream->get_addr(cpu, inst_cream->inst, addr, phys_addr, 0); 5821 lop += 8;
6169 if (fault) goto MMU_EXCEPTION; 5822 }
6170 unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; 5823 rop = SHIFTER_OPERAND;
6171 //bus_write(16, addr, value); 5824 RD = dst = lop - rop;
6172 fault = interpreter_write_memory(addr, phys_addr, value, 32); 5825 if (inst_cream->S && (inst_cream->Rd == 15)) {
6173 if (fault) goto MMU_EXCEPTION; 5826 if (CurrentModeHasSPSR) {
6174 } 5827 cpu->Cpsr = cpu->Spsr_copy;
6175 cpu->Reg[15] += GET_INST_SIZE(cpu); 5828 switch_mode(cpu, cpu->Spsr_copy & 0x1f);
6176 INC_PC(sizeof(ldst_inst)); 5829 LOAD_NZCVT;
6177 FETCH_INST; 5830 }
6178 GOTO_NEXT_INST; 5831 } else if (inst_cream->S) {
6179 } 5832 UPDATE_NFLAG(dst);
6180 SUB_INST: 5833 UPDATE_ZFLAG(dst);
6181 { 5834 UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop);
6182 INC_ICOUNTER; 5835 UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop);
6183 sub_inst *inst_cream = (sub_inst *)inst_base->component; 5836 }
6184 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5837 if (inst_cream->Rd == 15) {
6185 lop = RN; 5838 INC_PC(sizeof(sub_inst));
6186 if (inst_cream->Rn == 15) { 5839 goto DISPATCH;
6187 lop += 8; 5840 }
6188 } 5841 }
6189 rop = SHIFTER_OPERAND; 5842 cpu->Reg[15] += GET_INST_SIZE(cpu);
6190 RD = dst = lop - rop; 5843 INC_PC(sizeof(sub_inst));
6191 if (inst_cream->S && (inst_cream->Rd == 15)) { 5844 FETCH_INST;
6192 /* cpsr = spsr */ 5845 GOTO_NEXT_INST;
6193 if (CurrentModeHasSPSR) { 5846 }
6194 cpu->Cpsr = cpu->Spsr_copy; 5847 SWI_INST:
6195 switch_mode(cpu, cpu->Spsr_copy & 0x1f); 5848 {
6196 LOAD_NZCVT; 5849 swi_inst *inst_cream = (swi_inst *)inst_base->component;
6197 } 5850
6198 } else if (inst_cream->S) { 5851 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond))
6199 UPDATE_NFLAG(dst); 5852 HLE::CallSVC(Memory::Read32(cpu->Reg[15]));
6200 UPDATE_ZFLAG(dst); 5853
6201// UPDATE_CFLAG(dst, lop, rop); 5854 cpu->Reg[15] += GET_INST_SIZE(cpu);
6202 UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop); 5855 INC_PC(sizeof(swi_inst));
6203 // UPDATE_VFLAG((int)dst, (int)lop, (int)rop); 5856 FETCH_INST;
6204 UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop); 5857 GOTO_NEXT_INST;
6205 } 5858 }
6206 if (inst_cream->Rd == 15) { 5859 SWP_INST:
6207 INC_PC(sizeof(sub_inst)); 5860 {
6208 goto DISPATCH; 5861 swp_inst *inst_cream = (swp_inst *)inst_base->component;
6209 } 5862 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6210 } 5863 addr = RN;
6211 cpu->Reg[15] += GET_INST_SIZE(cpu); 5864 fault = check_address_validity(cpu, addr, &phys_addr, 1);
6212 INC_PC(sizeof(sub_inst)); 5865 if (fault) goto MMU_EXCEPTION;
6213 FETCH_INST; 5866 unsigned int value;
6214 GOTO_NEXT_INST; 5867 fault = interpreter_read_memory(addr, phys_addr, value, 32);
6215 } 5868 if (fault) goto MMU_EXCEPTION;
6216 SWI_INST: 5869 fault = interpreter_write_memory(addr, phys_addr, RM, 32);
6217 { 5870 if (fault) goto MMU_EXCEPTION;
6218 INC_ICOUNTER; 5871
6219 swi_inst *inst_cream = (swi_inst *)inst_base->component; 5872 assert((phys_addr & 0x3) == 0);
6220 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5873 RD = value;
6221 if (true){ //if (core->is_user_mode) { --> Citra only emulates user mode 5874 }
6222 //arm_dyncom_SWI(cpu, inst_cream->num); 5875 cpu->Reg[15] += GET_INST_SIZE(cpu);
6223 HLE::CallSVC(Memory::Read32(cpu->Reg[15])); 5876 INC_PC(sizeof(swp_inst));
6224 } else { 5877 FETCH_INST;
6225 cpu->syscallSig = 1; 5878 GOTO_NEXT_INST;
6226 goto END; 5879 }
6227 } 5880 SWPB_INST:
6228 } 5881 {
6229 cpu->Reg[15] += GET_INST_SIZE(cpu); 5882 swp_inst *inst_cream = (swp_inst *)inst_base->component;
6230 INC_PC(sizeof(swi_inst)); 5883 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6231 FETCH_INST; 5884 addr = RN;
6232 GOTO_NEXT_INST; 5885 fault = check_address_validity(cpu, addr, &phys_addr, 1);
6233 } 5886 if (fault) goto MMU_EXCEPTION;
6234 SWP_INST: 5887 unsigned int value;
6235 { 5888 fault = interpreter_read_memory(addr, phys_addr, value, 8);
6236 INC_ICOUNTER; 5889 if (fault) goto MMU_EXCEPTION;
6237 swp_inst *inst_cream = (swp_inst *)inst_base->component; 5890 fault = interpreter_write_memory(addr, phys_addr, (RM & 0xFF), 8);
6238 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5891 if (fault) goto MMU_EXCEPTION;
6239 addr = RN; 5892 }
6240 fault = check_address_validity(cpu, addr, &phys_addr, 1); 5893 cpu->Reg[15] += GET_INST_SIZE(cpu);
6241 if (fault) goto MMU_EXCEPTION; 5894 INC_PC(sizeof(swp_inst));
6242 unsigned int value; 5895 FETCH_INST;
6243 fault = interpreter_read_memory(addr, phys_addr, value, 32); 5896 GOTO_NEXT_INST;
6244 if (fault) goto MMU_EXCEPTION; 5897 }
6245 fault = interpreter_write_memory(addr, phys_addr, RM, 32); 5898 SXTAB_INST:
6246 if (fault) goto MMU_EXCEPTION; 5899 {
6247 5900 sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component;
6248 /* ROR(data, 8*UInt(address<1:0>)); */ 5901 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6249 assert((phys_addr & 0x3) == 0); 5902 // R15 should be check
6250 RD = value; 5903 if(inst_cream->Rn == 15 || inst_cream->Rm == 15 || inst_cream->Rd ==15){
6251 } 5904 CITRA_IGNORE_EXIT(-1);
6252 cpu->Reg[15] += GET_INST_SIZE(cpu); 5905 }
6253 INC_PC(sizeof(swp_inst)); 5906 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xff;
6254 FETCH_INST; 5907
6255 GOTO_NEXT_INST; 5908 // Sign extend for byte
6256 } 5909 operand2 = (0x80 & operand2)? (0xFFFFFF00 | operand2):operand2;
6257 SWPB_INST: 5910 RD = RN + operand2;
6258 { 5911 }
6259 INC_ICOUNTER; 5912 cpu->Reg[15] += GET_INST_SIZE(cpu);
6260 swp_inst *inst_cream = (swp_inst *)inst_base->component; 5913 INC_PC(sizeof(uxtab_inst));
6261 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5914 FETCH_INST;
6262 addr = RN; 5915 GOTO_NEXT_INST;
6263 fault = check_address_validity(cpu, addr, &phys_addr, 1); 5916 }
6264 if (fault) goto MMU_EXCEPTION; 5917 SXTAB16_INST:
6265 unsigned int value; 5918 SXTAH_INST:
6266 fault = interpreter_read_memory(addr, phys_addr, value, 8); 5919 {
6267 if (fault) goto MMU_EXCEPTION; 5920 sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component;
6268 fault = interpreter_write_memory(addr, phys_addr, (RM & 0xFF), 8); 5921 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6269 if (fault) goto MMU_EXCEPTION; 5922 // R15 should be check
6270 5923 if(inst_cream->Rn == 15 || inst_cream->Rm == 15 || inst_cream->Rd ==15) {
6271 /* FIXME */ 5924 CITRA_IGNORE_EXIT(-1);
6272 #if 0 5925 }
6273 if Shared(address) then 5926 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff;
6274 /* ARMv6 */ 5927 // Sign extend for half
6275 physical_address = TLB(address) 5928 operand2 = (0x8000 & operand2) ? (0xFFFF0000 | operand2) : operand2;
6276 ClearExclusiveByAddress(physical_address,processor_id,1) 5929 RD = RN + operand2;
6277 /* See Summary of operation on page A2-49 */ 5930 }
6278 #endif 5931 cpu->Reg[15] += GET_INST_SIZE(cpu);
6279 } 5932 INC_PC(sizeof(sxtah_inst));
6280 cpu->Reg[15] += GET_INST_SIZE(cpu); 5933 FETCH_INST;
6281 INC_PC(sizeof(swp_inst)); 5934 GOTO_NEXT_INST;
6282 FETCH_INST; 5935 }
6283 GOTO_NEXT_INST; 5936 SXTB16_INST:
6284 } 5937 TEQ_INST:
6285 SXTAB_INST: 5938 {
6286 { 5939 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6287 INC_ICOUNTER; 5940 teq_inst *inst_cream = (teq_inst *)inst_base->component;
6288 sxtab_inst *inst_cream = (sxtab_inst *)inst_base->component; 5941 lop = RN;
6289 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5942
6290 /* R15 should be check */ 5943 if (inst_cream->Rn == 15)
6291 if(inst_cream->Rn == 15 || inst_cream->Rm == 15 || inst_cream->Rd ==15){ 5944 lop += GET_INST_SIZE(cpu) * 2;
6292 CITRA_IGNORE_EXIT(-1); 5945
6293 } 5946 rop = SHIFTER_OPERAND;
6294 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) 5947 dst = lop ^ rop;
6295 & 0xff; 5948
6296 /* sign extend for byte */ 5949 UPDATE_NFLAG(dst);
6297 operand2 = (0x80 & operand2)? (0xFFFFFF00 | operand2):operand2; 5950 UPDATE_ZFLAG(dst);
6298 RD = RN + operand2; 5951 UPDATE_CFLAG_WITH_SC;
6299 } 5952 }
6300 cpu->Reg[15] += GET_INST_SIZE(cpu); 5953 cpu->Reg[15] += GET_INST_SIZE(cpu);
6301 INC_PC(sizeof(uxtab_inst)); 5954 INC_PC(sizeof(teq_inst));
6302 FETCH_INST; 5955 FETCH_INST;
6303 GOTO_NEXT_INST; 5956 GOTO_NEXT_INST;
6304 } 5957 }
6305 SXTAB16_INST: 5958 TST_INST:
6306 SXTAH_INST: 5959 {
6307 { 5960 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6308 INC_ICOUNTER; 5961 tst_inst *inst_cream = (tst_inst *)inst_base->component;
6309 sxtah_inst *inst_cream = (sxtah_inst *)inst_base->component; 5962 lop = RN;
6310 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5963
6311 /* R15 should be check */ 5964 if (inst_cream->Rn == 15)
6312 if(inst_cream->Rn == 15 || inst_cream->Rm == 15 || inst_cream->Rd ==15){ 5965 lop += GET_INST_SIZE(cpu) * 2;
6313 CITRA_IGNORE_EXIT(-1); 5966
6314 } 5967 rop = SHIFTER_OPERAND;
6315 unsigned int operand2 = ROTATE_RIGHT_32(RM, 8 * inst_cream->rotate) & 0xffff; 5968 dst = lop & rop;
6316 /* sign extend for half */ 5969
6317 operand2 = (0x8000 & operand2)? (0xFFFF0000 | operand2):operand2; 5970 UPDATE_NFLAG(dst);
6318 RD = RN + operand2; 5971 UPDATE_ZFLAG(dst);
6319 } 5972 UPDATE_CFLAG_WITH_SC;
6320 cpu->Reg[15] += GET_INST_SIZE(cpu); 5973 }
6321 INC_PC(sizeof(sxtah_inst)); 5974 cpu->Reg[15] += GET_INST_SIZE(cpu);
6322 FETCH_INST; 5975 INC_PC(sizeof(tst_inst));
6323 GOTO_NEXT_INST; 5976 FETCH_INST;
6324 } 5977 GOTO_NEXT_INST;
6325 SXTB16_INST: 5978 }
6326 TEQ_INST: 5979 UADD8_INST:
6327 { 5980 UADD16_INST:
6328 INC_ICOUNTER; 5981 UADDSUBX_INST:
6329 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5982
6330 teq_inst *inst_cream = (teq_inst *)inst_base->component; 5983 UHADD8_INST:
6331 lop = RN; 5984 UHADD16_INST:
6332 if (inst_cream->Rn == 15) 5985 UHADDSUBX_INST:
6333 lop += GET_INST_SIZE(cpu) * 2; 5986 UHSUBADDX_INST:
6334 5987 UHSUB8_INST:
6335 rop = SHIFTER_OPERAND; 5988 UHSUB16_INST:
6336 dst = lop ^ rop; 5989 {
6337 5990 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
6338 UPDATE_NFLAG(dst); 5991 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
6339 UPDATE_ZFLAG(dst); 5992 const u32 rm_val = RM;
6340 UPDATE_CFLAG_WITH_SC; 5993 const u32 rn_val = RN;
6341 } 5994 const u8 op2 = inst_cream->op2;
6342 cpu->Reg[15] += GET_INST_SIZE(cpu); 5995
6343 INC_PC(sizeof(teq_inst)); 5996 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03)
6344 FETCH_INST; 5997 {
6345 GOTO_NEXT_INST; 5998 u32 lo_val = 0;
6346 } 5999 u32 hi_val = 0;
6347 TST_INST: 6000
6348 { 6001 // UHADD16
6349 INC_ICOUNTER; 6002 if (op2 == 0x00) {
6350 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 6003 lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
6351 tst_inst *inst_cream = (tst_inst *)inst_base->component; 6004 hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
6352 lop = RN; 6005 }
6353 if (inst_cream->Rn == 15) 6006 // UHASX
6354 lop += GET_INST_SIZE(cpu) * 2; 6007 else if (op2 == 0x01) {
6355 rop = SHIFTER_OPERAND; 6008 lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
6356 dst = lop & rop; 6009 hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
6357 6010 }
6358 UPDATE_NFLAG(dst); 6011 // UHSAX
6359 UPDATE_ZFLAG(dst); 6012 else if (op2 == 0x02) {
6360 UPDATE_CFLAG_WITH_SC; 6013 lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
6361 } 6014 hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
6362 cpu->Reg[15] += GET_INST_SIZE(cpu); 6015 }
6363 INC_PC(sizeof(tst_inst)); 6016 // UHSUB16
6364 FETCH_INST; 6017 else if (op2 == 0x03) {
6365 GOTO_NEXT_INST; 6018 lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
6366 } 6019 hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
6367 UADD16_INST: 6020 }
6368 UADD8_INST: 6021
6369 UADDSUBX_INST: 6022 lo_val >>= 1;
6370 UHADD16_INST: 6023 hi_val >>= 1;
6371 UHADD8_INST: 6024
6372 UHADDSUBX_INST: 6025 RD = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16);
6373 UHSUB16_INST: 6026 }
6374 UHSUB8_INST: 6027 else if (op2 == 0x04 || op2 == 0x07) {
6375 UHSUBADDX_INST: 6028 u32 sum1;
6376 UMAAL_INST: 6029 u32 sum2;
6377 UMLAL_INST: 6030 u32 sum3;
6378 { 6031 u32 sum4;
6379 INC_ICOUNTER; 6032
6380 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 6033 // UHADD8
6381 umlal_inst *inst_cream = (umlal_inst *)inst_base->component; 6034 if (op2 == 0x04) {
6382 unsigned long long int rm = RM; 6035 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
6383 unsigned long long int rs = RS; 6036 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
6384 unsigned long long int rst = rm * rs; 6037 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
6385 unsigned long long int add = ((unsigned long long) RDHI)<<32; 6038 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
6386 add += RDLO; 6039 }
6387 //DEBUG_LOG(ARM11, "rm[%llx] * rs[%llx] = rst[%llx] | add[%llx]\n", RM, RS, rst, add); 6040 // UHSUB8
6388 rst += add; 6041 else {
6389 RDLO = BITS(rst, 0, 31); 6042 sum1 = (rn_val & 0xFF) - (rm_val & 0xFF);
6390 RDHI = BITS(rst, 32, 63); 6043 sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
6391 6044 sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
6392 if (inst_cream->S) 6045 sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
6393 { 6046 }
6394 cpu->NFlag = BIT(RDHI, 31); 6047
6395 cpu->ZFlag = (RDHI == 0 && RDLO == 0); 6048 sum1 >>= 1;
6396 } 6049 sum2 >>= 1;
6397 } 6050 sum3 >>= 1;
6398 cpu->Reg[15] += GET_INST_SIZE(cpu); 6051 sum4 >>= 1;
6399 INC_PC(sizeof(umlal_inst)); 6052
6400 FETCH_INST; 6053 RD = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | ((sum4 & 0xFF) << 24);
6401 GOTO_NEXT_INST; 6054 }
6402 } 6055 }
6403 UMULL_INST: 6056
6404 { 6057 cpu->Reg[15] += GET_INST_SIZE(cpu);
6405 INC_ICOUNTER; 6058 INC_PC(sizeof(generic_arm_inst));
6406 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 6059 FETCH_INST;
6407 umull_inst *inst_cream = (umull_inst *)inst_base->component; 6060 GOTO_NEXT_INST;
6408 unsigned long long int rm = RM; 6061 }
6409 unsigned long long int rs = RS; 6062
6410 unsigned long long int rst = rm * rs; 6063 UMAAL_INST:
6411// DEBUG_LOG(ARM11, "rm : [%llx] rs : [%llx] rst [%llx]\n", RM, RS, rst); 6064 {
6412 RDHI = BITS(rst, 32, 63); 6065 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
6413 RDLO = BITS(rst, 0, 31); 6066 umaal_inst* const inst_cream = (umaal_inst*)inst_base->component;
6414 6067 const u32 rm = RM;
6415 if (inst_cream->S) { 6068 const u32 rn = RN;
6416 cpu->NFlag = BIT(RDHI, 31); 6069 const u32 rd_lo = RDLO;
6417 cpu->ZFlag = (RDHI == 0 && RDLO == 0); 6070 const u32 rd_hi = RDHI;
6418 } 6071 const u64 result = (rm * rn) + rd_lo + rd_hi;
6419 } 6072
6420 cpu->Reg[15] += GET_INST_SIZE(cpu); 6073 RDLO = (result & 0xFFFFFFFF);
6421 INC_PC(sizeof(umull_inst)); 6074 RDHI = ((result >> 32) & 0xFFFFFFFF);
6422 FETCH_INST; 6075 }
6423 GOTO_NEXT_INST; 6076 cpu->Reg[15] += GET_INST_SIZE(cpu);
6424 } 6077 INC_PC(sizeof(umaal_inst));
6425 B_2_THUMB: 6078 FETCH_INST;
6426 { 6079 GOTO_NEXT_INST;
6427 INC_ICOUNTER; 6080 }
6428 b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component; 6081 UMLAL_INST:
6429 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; 6082 {
6430 //DEBUG_LOG(ARM11, " BL_1_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); 6083 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6431 INC_PC(sizeof(b_2_thumb)); 6084 umlal_inst *inst_cream = (umlal_inst *)inst_base->component;
6432 goto DISPATCH; 6085 unsigned long long int rm = RM;
6433 } 6086 unsigned long long int rs = RS;
6434 B_COND_THUMB: 6087 unsigned long long int rst = rm * rs;
6435 { 6088 unsigned long long int add = ((unsigned long long) RDHI)<<32;
6436 INC_ICOUNTER; 6089 add += RDLO;
6437 b_cond_thumb *inst_cream = (b_cond_thumb *)inst_base->component; 6090 rst += add;
6438 if(CondPassed(cpu, inst_cream->cond)) 6091 RDLO = BITS(rst, 0, 31);
6439 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm; 6092 RDHI = BITS(rst, 32, 63);
6440 else 6093
6441 cpu->Reg[15] += 2; 6094 if (inst_cream->S) {
6442 //DEBUG_LOG(ARM11, " B_COND_THUMB: imm=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[15]); 6095 cpu->NFlag = BIT(RDHI, 31);
6443 INC_PC(sizeof(b_cond_thumb)); 6096 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
6444 goto DISPATCH; 6097 }
6445 } 6098 }
6446 BL_1_THUMB: 6099 cpu->Reg[15] += GET_INST_SIZE(cpu);
6447 { 6100 INC_PC(sizeof(umlal_inst));
6448 INC_ICOUNTER; 6101 FETCH_INST;
6449 bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component; 6102 GOTO_NEXT_INST;
6450 cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm; 6103 }
6451 //cpu->Reg[15] += 2; 6104 UMULL_INST:
6452 //DEBUG_LOG(ARM11, " BL_1_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); 6105 {
6453 6106 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
6454 cpu->Reg[15] += GET_INST_SIZE(cpu); 6107 umull_inst *inst_cream = (umull_inst *)inst_base->component;
6455 INC_PC(sizeof(bl_1_thumb)); 6108 unsigned long long int rm = RM;
6456 FETCH_INST; 6109 unsigned long long int rs = RS;
6457 GOTO_NEXT_INST; 6110 unsigned long long int rst = rm * rs;
6458 6111 RDHI = BITS(rst, 32, 63);
6459 } 6112 RDLO = BITS(rst, 0, 31);
6460 BL_2_THUMB: 6113
6461 { 6114 if (inst_cream->S) {
6462 INC_ICOUNTER; 6115 cpu->NFlag = BIT(RDHI, 31);
6463 bl_2_thumb *inst_cream = (bl_2_thumb *)inst_base->component; 6116 cpu->ZFlag = (RDHI == 0 && RDLO == 0);
6464 int tmp = ((cpu->Reg[15] + 2) | 1); 6117 }
6465 cpu->Reg[15] = 6118 }
6466 (cpu->Reg[14] + inst_cream->imm); 6119 cpu->Reg[15] += GET_INST_SIZE(cpu);
6467 cpu->Reg[14] = tmp; 6120 INC_PC(sizeof(umull_inst));
6468 //DEBUG_LOG(ARM11, " BL_2_THUMB: imm=0x%x, r14=0x%x, r15=0x%x\n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); 6121 FETCH_INST;
6469 INC_PC(sizeof(bl_2_thumb)); 6122 GOTO_NEXT_INST;
6470 goto DISPATCH; 6123 }
6471 } 6124 B_2_THUMB:
6472 BLX_1_THUMB: 6125 {
6473 { 6126 b_2_thumb *inst_cream = (b_2_thumb *)inst_base->component;
6474 /* BLX 1 for armv5t and above */ 6127 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
6475 INC_ICOUNTER; 6128 INC_PC(sizeof(b_2_thumb));
6476 uint32 tmp = cpu->Reg[15]; 6129 goto DISPATCH;
6477 blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component; 6130 }
6478 cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm) & 0xFFFFFFFC; 6131 B_COND_THUMB:
6479 //DEBUG_LOG(ARM11, "In BLX_1_THUMB, BLX(1),imm=0x%x,r14=0x%x, instr=0x%x\n", inst_cream->imm, cpu->Reg[14], inst_cream->instr); 6132 {
6480 cpu->Reg[14] = ((tmp + 2) | 1); 6133 b_cond_thumb *inst_cream = (b_cond_thumb *)inst_base->component;
6481 //(state->Reg[14] + ((tinstr & 0x07FF) << 1)) & 0xFFFFFFFC; 6134
6482 /* switch to arm state from thumb state */ 6135 if(CondPassed(cpu, inst_cream->cond))
6483 cpu->TFlag = 0; 6136 cpu->Reg[15] = cpu->Reg[15] + 4 + inst_cream->imm;
6484 //DEBUG_LOG(ARM11, "In BLX_1_THUMB, BLX(1),imm=0x%x,r14=0x%x, r15=0x%x, \n", inst_cream->imm, cpu->Reg[14], cpu->Reg[15]); 6137 else
6485 INC_PC(sizeof(blx_1_thumb)); 6138 cpu->Reg[15] += 2;
6486 goto DISPATCH; 6139
6487 } 6140 INC_PC(sizeof(b_cond_thumb));
6488 6141 goto DISPATCH;
6489 UQADD16_INST: 6142 }
6490 UQADD8_INST: 6143 BL_1_THUMB:
6491 UQADDSUBX_INST: 6144 {
6492 UQSUB16_INST: 6145 bl_1_thumb *inst_cream = (bl_1_thumb *)inst_base->component;
6493 UQSUB8_INST: 6146 cpu->Reg[14] = cpu->Reg[15] + 4 + inst_cream->imm;
6494 UQSUBADDX_INST: 6147 cpu->Reg[15] += GET_INST_SIZE(cpu);
6495 USAD8_INST: 6148 INC_PC(sizeof(bl_1_thumb));
6496 USADA8_INST: 6149 FETCH_INST;
6497 USAT_INST: 6150 GOTO_NEXT_INST;
6498 USAT16_INST: 6151 }
6499 USUB16_INST: 6152 BL_2_THUMB:
6500 USUB8_INST: 6153 {
6501 USUBADDX_INST: 6154 bl_2_thumb *inst_cream = (bl_2_thumb *)inst_base->component;
6502 UXTAB16_INST: 6155 int tmp = ((cpu->Reg[15] + 2) | 1);
6503 UXTB16_INST: 6156 cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm);
6504 #define VFP_INTERPRETER_IMPL 6157 cpu->Reg[14] = tmp;
6505 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 6158 INC_PC(sizeof(bl_2_thumb));
6506 #undef VFP_INTERPRETER_IMPL 6159 goto DISPATCH;
6507 MMU_EXCEPTION: 6160 }
6508 { 6161 BLX_1_THUMB:
6509 SAVE_NZCVT; 6162 {
6510 cpu->abortSig = true; 6163 // BLX 1 for armv5t and above
6511 cpu->Aborted = ARMul_DataAbortV; 6164 uint32 tmp = cpu->Reg[15];
6512 cpu->AbortAddr = addr; 6165 blx_1_thumb *inst_cream = (blx_1_thumb *)inst_base->component;
6513 cpu->CP15[CP15(CP15_FAULT_STATUS)] = fault & 0xff; 6166 cpu->Reg[15] = (cpu->Reg[14] + inst_cream->imm) & 0xFFFFFFFC;
6514 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = addr; 6167 cpu->Reg[14] = ((tmp + 2) | 1);
6515 cpu->NumInstrsToExecute = 0; 6168 cpu->TFlag = 0;
6516 return num_instrs; 6169 INC_PC(sizeof(blx_1_thumb));
6517 } 6170 goto DISPATCH;
6518 END: 6171 }
6519 { 6172
6520 SAVE_NZCVT; 6173 UQADD8_INST:
6521 cpu->NumInstrsToExecute = 0; 6174 UQADD16_INST:
6522 return num_instrs; 6175 UQADDSUBX_INST:
6523 } 6176 UQSUB8_INST:
6524 INIT_INST_LENGTH: 6177 UQSUB16_INST:
6525 { 6178 UQSUBADDX_INST:
6526#if 0 6179 {
6527 DEBUG_LOG(ARM11, "InstLabel:%d\n", sizeof(InstLabel)); 6180 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
6528 for (int i = 0; i < (sizeof(InstLabel) / sizeof(void *)); i ++) 6181 generic_arm_inst* const inst_cream = (generic_arm_inst*)inst_base->component;
6529 DEBUG_LOG(ARM11, "[%llx]\n", InstLabel[i]); 6182
6530 DEBUG_LOG(ARM11, "InstLabel:%d\n", sizeof(InstLabel)); 6183 const u8 op2 = inst_cream->op2;
6531#endif 6184 const u32 rm_val = RM;
6185 const u32 rn_val = RN;
6186
6187 u16 lo_val = 0;
6188 u16 hi_val = 0;
6189
6190 // UQADD16
6191 if (op2 == 0x00) {
6192 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF);
6193 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
6194 }
6195 // UQASX
6196 else if (op2 == 0x01) {
6197 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
6198 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
6199 }
6200 // UQSAX
6201 else if (op2 == 0x02) {
6202 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
6203 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
6204 }
6205 // UQSUB16
6206 else if (op2 == 0x03) {
6207 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF);
6208 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
6209 }
6210 // UQADD8
6211 else if (op2 == 0x04) {
6212 lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) |
6213 ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8;
6214 hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) |
6215 ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8;
6216 }
6217 // UQSUB8
6218 else {
6219 lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) |
6220 ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8;
6221 hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) |
6222 ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8;
6223 }
6224
6225 RD = ((lo_val & 0xFFFF) | hi_val << 16);
6226 }
6227
6228 cpu->Reg[15] += GET_INST_SIZE(cpu);
6229 INC_PC(sizeof(generic_arm_inst));
6230 FETCH_INST;
6231 GOTO_NEXT_INST;
6232 }
6233
6234 USAD8_INST:
6235 USADA8_INST:
6236 {
6237 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
6238 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
6239
6240 const u8 ra_idx = inst_cream->Ra;
6241 const u32 rm_val = RM;
6242 const u32 rn_val = RN;
6243
6244 const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF);
6245 const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF);
6246 const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF);
6247 const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF);
6248
6249 u32 finalDif = (diff1 + diff2 + diff3 + diff4);
6250
6251 // Op is USADA8 if true.
6252 if (ra_idx != 15)
6253 finalDif += cpu->Reg[ra_idx];
6254
6255 RD = finalDif;
6256 }
6257
6258 cpu->Reg[15] += GET_INST_SIZE(cpu);
6259 INC_PC(sizeof(generic_arm_inst));
6260 FETCH_INST;
6261 GOTO_NEXT_INST;
6262 }
6263
6264 USAT_INST:
6265 USAT16_INST:
6266 USUB16_INST:
6267 USUB8_INST:
6268 USUBADDX_INST:
6269 UXTAB16_INST:
6270 UXTB16_INST:
6271 {
6272 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
6273 uxtab_inst* const inst_cream = (uxtab_inst*)inst_base->component;
6274
6275 const u8 rn_idx = inst_cream->Rn;
6276 const u32 rm_val = RM;
6277 const u32 rotation = inst_cream->rotate * 8;
6278 const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
6279
6280 // UXTB16, otherwise UXTAB16
6281 if (rn_idx == 15) {
6282 RD = rotated_rm & 0x00FF00FF;
6283 } else {
6284 const u32 rn_val = RN;
6285 const u8 lo_rotated = (rotated_rm & 0xFF);
6286 const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated;
6287 const u8 hi_rotated = (rotated_rm >> 16) & 0xFF;
6288 const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated;
6289
6290 RD = ((hi_result << 16) | (lo_result & 0xFFFF));
6291 }
6292 }
6293
6294 cpu->Reg[15] += GET_INST_SIZE(cpu);
6295 INC_PC(sizeof(uxtab_inst));
6296 FETCH_INST;
6297 GOTO_NEXT_INST;
6298 }
6299
6300 #define VFP_INTERPRETER_IMPL
6301 #include "core/arm/skyeye_common/vfp/vfpinstr.cpp"
6302 #undef VFP_INTERPRETER_IMPL
6303 MMU_EXCEPTION:
6304 {
6305 SAVE_NZCVT;
6306 cpu->abortSig = true;
6307 cpu->Aborted = ARMul_DataAbortV;
6308 cpu->AbortAddr = addr;
6309 cpu->CP15[CP15(CP15_FAULT_STATUS)] = fault & 0xff;
6310 cpu->CP15[CP15(CP15_FAULT_ADDRESS)] = addr;
6311 cpu->NumInstrsToExecute = 0;
6312 return num_instrs;
6313 }
6314 END:
6315 {
6316 SAVE_NZCVT;
6317 cpu->NumInstrsToExecute = 0;
6318 return num_instrs;
6319 }
6320 INIT_INST_LENGTH:
6321 {
6532#if defined __GNUC__ || defined __clang__ 6322#if defined __GNUC__ || defined __clang__
6533 InterpreterInitInstLength((unsigned long long int *)InstLabel, sizeof(InstLabel)); 6323 InterpreterInitInstLength((unsigned long long int *)InstLabel, sizeof(InstLabel));
6534#endif 6324#endif
6535#if 0 6325 cpu->NumInstrsToExecute = 0;
6536 for (int i = 0; i < (sizeof(InstLabel) / sizeof(void *)); i ++) 6326 return num_instrs;
6537 DEBUG_LOG(ARM11, "[%llx]\n", InstLabel[i]); 6327 }
6538 DEBUG_LOG(ARM11, "%llx\n", InstEndLabel[1]);
6539 DEBUG_LOG(ARM11, "%llx\n", InstLabel[1]);
6540 DEBUG_LOG(ARM11, "%lld\n", (char *)InstEndLabel[1] - (char *)InstLabel[1]);
6541#endif
6542 cpu->NumInstrsToExecute = 0;
6543 return num_instrs;
6544 }
6545} 6328}
6546
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.h b/src/core/arm/dyncom/arm_dyncom_interpreter.h
index 3a2462f55..4791ea25f 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.h
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/arm/dyncom/arm_dyncom_run.cpp b/src/core/arm/dyncom/arm_dyncom_run.cpp
index a2026cbf3..d457d0ac5 100644
--- a/src/core/arm/dyncom/arm_dyncom_run.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_run.cpp
@@ -1,42 +1,15 @@
1/* Copyright (C) 1// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
2* 2011 - Michael.Kang blackfin.kang@gmail.com 2// Licensed under GPLv2 or any later version
3* This program is free software; you can redistribute it and/or 3// Refer to the license.txt file included.
4* modify it under the terms of the GNU General Public License
5* as published by the Free Software Foundation; either version 2
6* of the License, or (at your option) any later version.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program; if not, write to the Free Software
15* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16*
17*/
18/**
19* @file arm_dyncom_run.cpp
20* @brief The dyncom run implementation for arm
21* @author Michael.Kang blackfin.kang@gmail.com
22* @version 78.77
23* @date 2011-11-20
24*/
25 4
26#include <assert.h> 5#include <assert.h>
27 6
28#include "core/arm/skyeye_common/armdefs.h" 7#include "core/arm/skyeye_common/armdefs.h"
29 8
30void switch_mode(arm_core_t *core, uint32_t mode) 9void switch_mode(arm_core_t *core, uint32_t mode) {
31{ 10 if (core->Mode == mode)
32 uint32_t tmp1, tmp2;
33 if (core->Mode == mode) {
34 //Mode not changed.
35 //printf("mode not changed\n");
36 return; 11 return;
37 } 12
38 //printf("%d --->>> %d\n", core->Mode, mode);
39 //printf("In %s, Cpsr=0x%x, R15=0x%x, last_pc=0x%x, cpsr=0x%x, spsr_copy=0x%x, icounter=%lld\n", __FUNCTION__, core->Cpsr, core->Reg[15], core->last_pc, core->Cpsr, core->Spsr_copy, core->icounter);
40 if (mode != USERBANK) { 13 if (mode != USERBANK) {
41 switch (core->Mode) { 14 switch (core->Mode) {
42 case USER32MODE: 15 case USER32MODE:
@@ -110,11 +83,8 @@ void switch_mode(arm_core_t *core, uint32_t mode)
110 83
111 } 84 }
112 core->Mode = mode; 85 core->Mode = mode;
113 //printf("In %si end, Cpsr=0x%x, R15=0x%x, last_pc=0x%x, cpsr=0x%x, spsr_copy=0x%x, icounter=%lld\n", __FUNCTION__, core->Cpsr, core->Reg[15], core->last_pc, core->Cpsr, core->Spsr_copy, core->icounter); 86 } else {
114 //printf("\n--------------------------------------\n"); 87 LOG_CRITICAL(Core_ARM11, "user mode");
115 }
116 else {
117 printf("user mode\n");
118 exit(-2); 88 exit(-2);
119 } 89 }
120} 90}
diff --git a/src/core/arm/dyncom/arm_dyncom_thumb.cpp b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
index e10f2f9ee..de70ca8ae 100644
--- a/src/core/arm/dyncom/arm_dyncom_thumb.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_thumb.cpp
@@ -1,35 +1,13 @@
1/* Copyright (C) 1// Copyright 2012 Michael Kang, 2014 Citra Emulator Project
2* 2011 - Michael.Kang blackfin.kang@gmail.com 2// Licensed under GPLv2 or any later version
3* This program is free software; you can redistribute it and/or 3// Refer to the license.txt file included.
4* modify it under the terms of the GNU General Public License 4
5* as published by the Free Software Foundation; either version 2 5// We can provide simple Thumb simulation by decoding the Thumb instruction into its corresponding
6* of the License, or (at your option) any later version. 6// ARM instruction, and using the existing ARM simulator.
7*
8* This program is distributed in the hope that it will be useful,
9* but WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program; if not, write to the Free Software
15* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16*
17*/
18/**
19* @file arm_dyncom_thumb.c
20* @brief The thumb dynamic interpreter
21* @author Michael.Kang blackfin.kang@gmail.com
22* @version 78.77
23* @date 2011-11-07
24*/
25
26/* We can provide simple Thumb simulation by decoding the Thumb
27instruction into its corresponding ARM instruction, and using the
28existing ARM simulator. */
29 7
30#include "core/arm/skyeye_common/skyeye_defs.h" 8#include "core/arm/skyeye_common/skyeye_defs.h"
31 9
32#ifndef MODET /* required for the Thumb instruction support */ 10#ifndef MODET // Required for the Thumb instruction support
33#if 1 11#if 1
34#error "MODET needs to be defined for the Thumb world to work" 12#error "MODET needs to be defined for the Thumb world to work"
35#else 13#else
@@ -40,482 +18,359 @@ existing ARM simulator. */
40#include "core/arm/skyeye_common/armos.h" 18#include "core/arm/skyeye_common/armos.h"
41#include "core/arm/dyncom/arm_dyncom_thumb.h" 19#include "core/arm/dyncom/arm_dyncom_thumb.h"
42 20
43/* Decode a 16bit Thumb instruction. The instruction is in the low 21// Decode a 16bit Thumb instruction. The instruction is in the low 16-bits of the tinstr field,
44 16-bits of the tinstr field, with the following Thumb instruction 22// with the following Thumb instruction held in the high 16-bits. Passing in two Thumb instructions
45 held in the high 16-bits. Passing in two Thumb instructions allows 23// allows easier simulation of the special dual BL instruction.
46 easier simulation of the special dual BL instruction. */
47 24
48tdstate thumb_translate (addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t* inst_size) 25tdstate thumb_translate (addr_t addr, uint32_t instr, uint32_t* ainstr, uint32_t* inst_size) {
49{
50 tdstate valid = t_uninitialized; 26 tdstate valid = t_uninitialized;
51 ARMword next_instr; 27 ARMword tinstr;
52 ARMword tinstr; 28 tinstr = instr;
53 tinstr = instr; 29
54 /* The endian should be judge here */ 30 // The endian should be judge here
55 #if 0 31 if((addr & 0x3) != 0)
56 if (state->bigendSig) { 32 tinstr = instr >> 16;
57 next_instr = tinstr & 0xFFFF; 33 else
58 tinstr >>= 16; 34 tinstr &= 0xFFFF;
59 } 35
60 else { 36 *ainstr = 0xDEADC0DE; // Debugging to catch non updates
61 next_instr = tinstr >> 16; 37
62 tinstr &= 0xFFFF; 38 switch ((tinstr & 0xF800) >> 11) {
63 } 39 case 0: // LSL
64 #endif 40 case 1: // LSR
65 if((addr & 0x3) != 0) 41 case 2: // ASR
66 tinstr = instr >> 16; 42 *ainstr = 0xE1B00000 // base opcode
67 else 43 | ((tinstr & 0x1800) >> (11 - 5)) // shift type
68 tinstr &= 0xFFFF; 44 |((tinstr & 0x07C0) << (7 - 6)) // imm5
69 45 |((tinstr & 0x0038) >> 3) // Rs
70 //printf("In %s, instr=0x%x, tinstr=0x%x, r15=0x%x\n", __FUNCTION__, instr, tinstr, cpu->translate_pc); 46 |((tinstr & 0x0007) << 12); // Rd
71#if 1 /* debugging to catch non updates */ 47 break;
72 *ainstr = 0xDEADC0DE; 48
73#endif 49 case 3: // ADD/SUB
50 {
51 ARMword subset[4] = {
52 0xE0900000, // ADDS Rd,Rs,Rn
53 0xE0500000, // SUBS Rd,Rs,Rn
54 0xE2900000, // ADDS Rd,Rs,#imm3
55 0xE2500000 // SUBS Rd,Rs,#imm3
56 };
57 // It is quicker indexing into a table, than performing switch or conditionals:
58 *ainstr = subset[(tinstr & 0x0600) >> 9] // base opcode
59 |((tinstr & 0x01C0) >> 6) // Rn or imm3
60 |((tinstr & 0x0038) << (16 - 3)) // Rs
61 |((tinstr & 0x0007) << (12 - 0)); // Rd
62 }
63 break;
64
65 case 4: // MOV
66 case 5: // CMP
67 case 6: // ADD
68 case 7: // SUB
69 {
70 ARMword subset[4] = {
71 0xE3B00000, // MOVS Rd,#imm8
72 0xE3500000, // CMP Rd,#imm8
73 0xE2900000, // ADDS Rd,Rd,#imm8
74 0xE2500000, // SUBS Rd,Rd,#imm8
75 };
76
77 *ainstr = subset[(tinstr & 0x1800) >> 11] // base opcode
78 |((tinstr & 0x00FF) >> 0) // imm8
79 |((tinstr & 0x0700) << (16 - 8)) // Rn
80 |((tinstr & 0x0700) << (12 - 8)); // Rd
81 }
82 break;
83
84 case 8: // Arithmetic and high register transfers
85
86 // TODO: Since the subsets for both Format 4 and Format 5 instructions are made up of
87 // different ARM encodings, we could save the following conditional, and just have one
88 // large subset
89
90 if ((tinstr & (1 << 10)) == 0) {
91 enum otype {
92 t_norm,
93 t_shift,
94 t_neg,
95 t_mul
96 };
97
98 struct {
99 ARMword opcode;
100 otype type;
101 } subset[16] = {
102 { 0xE0100000, t_norm }, // ANDS Rd,Rd,Rs
103 { 0xE0300000, t_norm }, // EORS Rd,Rd,Rs
104 { 0xE1B00010, t_shift }, // MOVS Rd,Rd,LSL Rs
105 { 0xE1B00030, t_shift }, // MOVS Rd,Rd,LSR Rs
106 { 0xE1B00050, t_shift }, // MOVS Rd,Rd,ASR Rs
107 { 0xE0B00000, t_norm }, // ADCS Rd,Rd,Rs
108 { 0xE0D00000, t_norm }, // SBCS Rd,Rd,Rs
109 { 0xE1B00070, t_shift }, // MOVS Rd,Rd,ROR Rs
110 { 0xE1100000, t_norm }, // TST Rd,Rs
111 { 0xE2700000, t_neg }, // RSBS Rd,Rs,#0
112 { 0xE1500000, t_norm }, // CMP Rd,Rs
113 { 0xE1700000, t_norm }, // CMN Rd,Rs
114 { 0xE1900000, t_norm }, // ORRS Rd,Rd,Rs
115 { 0xE0100090, t_mul }, // MULS Rd,Rd,Rs
116 { 0xE1D00000, t_norm }, // BICS Rd,Rd,Rs
117 { 0xE1F00000, t_norm } // MVNS Rd,Rs
118 };
119
120 *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; // base
121
122 switch (subset[(tinstr & 0x03C0) >> 6].type) {
123 case t_norm:
124 *ainstr |= ((tinstr & 0x0007) << 16) // Rn
125 |((tinstr & 0x0007) << 12) // Rd
126 |((tinstr & 0x0038) >> 3); // Rs
127 break;
128 case t_shift:
129 *ainstr |= ((tinstr & 0x0007) << 12) // Rd
130 |((tinstr & 0x0007) >> 0) // Rm
131 |((tinstr & 0x0038) << (8 - 3)); // Rs
132 break;
133 case t_neg:
134 *ainstr |= ((tinstr & 0x0007) << 12) // Rd
135 |((tinstr & 0x0038) << (16 - 3)); // Rn
136 break;
137 case t_mul:
138 *ainstr |= ((tinstr & 0x0007) << 16) // Rd
139 |((tinstr & 0x0007) << 8) // Rs
140 |((tinstr & 0x0038) >> 3); // Rm
141 break;
142 }
143 } else {
144 ARMword Rd = ((tinstr & 0x0007) >> 0);
145 ARMword Rs = ((tinstr & 0x0038) >> 3);
146
147 if (tinstr & (1 << 7))
148 Rd += 8;
149 if (tinstr & (1 << 6))
150 Rs += 8;
151
152 switch ((tinstr & 0x03C0) >> 6) {
153 case 0x1: // ADD Rd,Rd,Hs
154 case 0x2: // ADD Hd,Hd,Rs
155 case 0x3: // ADD Hd,Hd,Hs
156 *ainstr = 0xE0800000 // base
157 | (Rd << 16) // Rn
158 |(Rd << 12) // Rd
159 |(Rs << 0); // Rm
160 break;
161 case 0x5: // CMP Rd,Hs
162 case 0x6: // CMP Hd,Rs
163 case 0x7: // CMP Hd,Hs
164 *ainstr = 0xE1500000 // base
165 | (Rd << 16) // Rn
166 |(Rd << 12) // Rd
167 |(Rs << 0); // Rm
168 break;
169 case 0x9: // MOV Rd,Hs
170 case 0xA: // MOV Hd,Rs
171 case 0xB: // MOV Hd,Hs
172 *ainstr = 0xE1A00000 // base
173 | (Rd << 16) // Rn
174 |(Rd << 12) // Rd
175 |(Rs << 0); // Rm
176 break;
177 case 0xC: // BX Rs
178 case 0xD: // BX Hs
179 *ainstr = 0xE12FFF10 // base
180 | ((tinstr & 0x0078) >> 3); // Rd
181 break;
182 case 0x0: // UNDEFINED
183 case 0x4: // UNDEFINED
184 case 0x8: // UNDEFINED
185 valid = t_undefined;
186 break;
187 case 0xE: // BLX
188 case 0xF: // BLX
189 *ainstr = 0xE1200030 // base
190 | (Rs << 0); // Rm
191 break;
192 }
193 }
194 break;
195
196 case 9: // LDR Rd,[PC,#imm8]
197 *ainstr = 0xE59F0000 // base
198 | ((tinstr & 0x0700) << (12 - 8)) // Rd
199 |((tinstr & 0x00FF) << (2 - 0)); // off8
200 break;
201
202 case 10:
203 case 11:
204 // TODO: Format 7 and Format 8 perform the same ARM encoding, so the following could be
205 // merged into a single subset, saving on the following boolean:
206
207 if ((tinstr & (1 << 9)) == 0) {
208 ARMword subset[4] = {
209 0xE7800000, // STR Rd,[Rb,Ro]
210 0xE7C00000, // STRB Rd,[Rb,Ro]
211 0xE7900000, // LDR Rd,[Rb,Ro]
212 0xE7D00000 // LDRB Rd,[Rb,Ro]
213 };
214
215 *ainstr = subset[(tinstr & 0x0C00) >> 10] // base
216 |((tinstr & 0x0007) << (12 - 0)) // Rd
217 |((tinstr & 0x0038) << (16 - 3)) // Rb
218 |((tinstr & 0x01C0) >> 6); // Ro
219
220 } else {
221 ARMword subset[4] = {
222 0xE18000B0, // STRH Rd,[Rb,Ro]
223 0xE19000D0, // LDRSB Rd,[Rb,Ro]
224 0xE19000B0, // LDRH Rd,[Rb,Ro]
225 0xE19000F0 // LDRSH Rd,[Rb,Ro]
226 };
227 *ainstr = subset[(tinstr & 0x0C00) >> 10] // base
228 |((tinstr & 0x0007) << (12 - 0)) // Rd
229 |((tinstr & 0x0038) << (16 - 3)) // Rb
230 |((tinstr & 0x01C0) >> 6); // Ro
231 }
232 break;
233
234 case 12: // STR Rd,[Rb,#imm5]
235 case 13: // LDR Rd,[Rb,#imm5]
236 case 14: // STRB Rd,[Rb,#imm5]
237 case 15: // LDRB Rd,[Rb,#imm5]
238 {
239 ARMword subset[4] = {
240 0xE5800000, // STR Rd,[Rb,#imm5]
241 0xE5900000, // LDR Rd,[Rb,#imm5]
242 0xE5C00000, // STRB Rd,[Rb,#imm5]
243 0xE5D00000 // LDRB Rd,[Rb,#imm5]
244 };
245 // The offset range defends on whether we are transferring a byte or word value:
246 *ainstr = subset[(tinstr & 0x1800) >> 11] // base
247 |((tinstr & 0x0007) << (12 - 0)) // Rd
248 |((tinstr & 0x0038) << (16 - 3)) // Rb
249 |((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); // off5
250 }
251 break;
252
253 case 16: // STRH Rd,[Rb,#imm5]
254 case 17: // LDRH Rd,[Rb,#imm5]
255 *ainstr = ((tinstr & (1 << 11)) // base
256 ? 0xE1D000B0 // LDRH
257 : 0xE1C000B0) // STRH
258 |((tinstr & 0x0007) << (12 - 0)) // Rd
259 |((tinstr & 0x0038) << (16 - 3)) // Rb
260 |((tinstr & 0x01C0) >> (6 - 1)) // off5, low nibble
261 |((tinstr & 0x0600) >> (9 - 8)); // off5, high nibble
262 break;
263
264 case 18: // STR Rd,[SP,#imm8]
265 case 19: // LDR Rd,[SP,#imm8]
266 *ainstr = ((tinstr & (1 << 11)) // base
267 ? 0xE59D0000 // LDR
268 : 0xE58D0000) // STR
269 |((tinstr & 0x0700) << (12 - 8)) // Rd
270 |((tinstr & 0x00FF) << 2); // off8
271 break;
272
273 case 20: // ADD Rd,PC,#imm8
274 case 21: // ADD Rd,SP,#imm8
275
276 if ((tinstr & (1 << 11)) == 0) {
277
278 // NOTE: The PC value used here should by word aligned. We encode shift-left-by-2 in the
279 // rotate immediate field, so no shift of off8 is needed.
280
281 *ainstr = 0xE28F0F00 // base
282 | ((tinstr & 0x0700) << (12 - 8)) // Rd
283 |(tinstr & 0x00FF); // off8
284 } else {
285 // We encode shift-left-by-2 in the rotate immediate field, so no shift of off8 is needed.
286 *ainstr = 0xE28D0F00 // base
287 | ((tinstr & 0x0700) << (12 - 8)) // Rd
288 |(tinstr & 0x00FF); // off8
289 }
290 break;
291
292 case 22:
293 case 23:
294 if ((tinstr & 0x0F00) == 0x0000) {
295 // NOTE: The instruction contains a shift left of 2 equivalent (implemented as ROR #30):
296 *ainstr = ((tinstr & (1 << 7)) // base
297 ? 0xE24DDF00 // SUB
298 : 0xE28DDF00) // ADD
299 |(tinstr & 0x007F); // off7
300 } else if ((tinstr & 0x0F00) == 0x0e00)
301 *ainstr = 0xEF000000 | SWI_Breakpoint;
302 else {
303 ARMword subset[4] = {
304 0xE92D0000, // STMDB sp!,{rlist}
305 0xE92D4000, // STMDB sp!,{rlist,lr}
306 0xE8BD0000, // LDMIA sp!,{rlist}
307 0xE8BD8000 // LDMIA sp!,{rlist,pc}
308 };
309 *ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] // base
310 |(tinstr & 0x00FF); // mask8
311 }
312 break;
313
314 case 24: // STMIA
315 case 25: // LDMIA
316 *ainstr = ((tinstr & (1 << 11)) // base
317 ? 0xE8B00000 // LDMIA
318 : 0xE8A00000) // STMIA
319 |((tinstr & 0x0700) << (16 - 8)) // Rb
320 |(tinstr & 0x00FF); // mask8
321 break;
322
323 case 26: // Bcc
324 case 27: // Bcc/SWI
325 if ((tinstr & 0x0F00) == 0x0F00) {
326 // Format 17 : SWI
327 *ainstr = 0xEF000000;
328 // Breakpoint must be handled specially.
329 if ((tinstr & 0x00FF) == 0x18)
330 *ainstr |= ((tinstr & 0x00FF) << 16);
331 // New breakpoint value. See gdb/arm-tdep.c
332 else if ((tinstr & 0x00FF) == 0xFE)
333 *ainstr |= SWI_Breakpoint;
334 else
335 *ainstr |= (tinstr & 0x00FF);
336 } else if ((tinstr & 0x0F00) != 0x0E00)
337 valid = t_branch;
338 else // UNDEFINED : cc=1110(AL) uses different format
339 valid = t_undefined;
340
341 break;
342
343 case 28: // B
344 valid = t_branch;
345 break;
346
347 case 29:
348 if(tinstr & 0x1)
349 valid = t_undefined;
350 else
351 valid = t_branch;
352 break;
353
354 case 30: // BL instruction 1
355
356 // There is no single ARM instruction equivalent for this Thumb instruction. To keep the
357 // simulation simple (from the user perspective) we check if the following instruction is
358 // the second half of this BL, and if it is we simulate it immediately
359
360 valid = t_branch;
361 break;
362
363 case 31: // BL instruction 2
364
365 // There is no single ARM instruction equivalent for this instruction. Also, it should only
366 // ever be matched with the fmt19 "BL instruction 1" instruction. However, we do allow the
367 // simulation of it on its own, with undefined results if r14 is not suitably initialised.
368
369 valid = t_branch;
370 break;
371 }
372
373 *inst_size = 2;
74 374
75 switch ((tinstr & 0xF800) >> 11) { 375 return valid;
76 case 0: /* LSL */
77 case 1: /* LSR */
78 case 2: /* ASR */
79 /* Format 1 */
80 *ainstr = 0xE1B00000 /* base opcode */
81 | ((tinstr & 0x1800) >> (11 - 5)) /* shift type */
82 |((tinstr & 0x07C0) << (7 - 6)) /* imm5 */
83 |((tinstr & 0x0038) >> 3) /* Rs */
84 |((tinstr & 0x0007) << 12); /* Rd */
85 break;
86 case 3: /* ADD/SUB */
87 /* Format 2 */
88 {
89 ARMword subset[4] = {
90 0xE0900000, /* ADDS Rd,Rs,Rn */
91 0xE0500000, /* SUBS Rd,Rs,Rn */
92 0xE2900000, /* ADDS Rd,Rs,#imm3 */
93 0xE2500000 /* SUBS Rd,Rs,#imm3 */
94 };
95 /* It is quicker indexing into a table, than performing switch
96 or conditionals: */
97 *ainstr = subset[(tinstr & 0x0600) >> 9] /* base opcode */
98 |((tinstr & 0x01C0) >> 6) /* Rn or imm3 */
99 |((tinstr & 0x0038) << (16 - 3)) /* Rs */
100 |((tinstr & 0x0007) << (12 - 0)); /* Rd */
101 }
102 break;
103 case 4: /* MOV */
104 case 5: /* CMP */
105 case 6: /* ADD */
106 case 7: /* SUB */
107 /* Format 3 */
108 {
109 ARMword subset[4] = {
110 0xE3B00000, /* MOVS Rd,#imm8 */
111 0xE3500000, /* CMP Rd,#imm8 */
112 0xE2900000, /* ADDS Rd,Rd,#imm8 */
113 0xE2500000, /* SUBS Rd,Rd,#imm8 */
114 };
115 *ainstr = subset[(tinstr & 0x1800) >> 11] /* base opcode */
116 |((tinstr & 0x00FF) >> 0) /* imm8 */
117 |((tinstr & 0x0700) << (16 - 8)) /* Rn */
118 |((tinstr & 0x0700) << (12 - 8)); /* Rd */
119 }
120 break;
121 case 8: /* Arithmetic and high register transfers */
122 /* TODO: Since the subsets for both Format 4 and Format 5
123 instructions are made up of different ARM encodings, we could
124 save the following conditional, and just have one large
125 subset. */
126 if ((tinstr & (1 << 10)) == 0) {
127 typedef enum
128 { t_norm, t_shift, t_neg, t_mul }otype_t;
129
130 /* Format 4 */
131 struct
132 {
133 ARMword opcode;
134 otype_t otype;
135 }
136 subset[16] = {
137 {
138 0xE0100000, t_norm}, /* ANDS Rd,Rd,Rs */
139 {
140 0xE0300000, t_norm}, /* EORS Rd,Rd,Rs */
141 {
142 0xE1B00010, t_shift}, /* MOVS Rd,Rd,LSL Rs */
143 {
144 0xE1B00030, t_shift}, /* MOVS Rd,Rd,LSR Rs */
145 {
146 0xE1B00050, t_shift}, /* MOVS Rd,Rd,ASR Rs */
147 {
148 0xE0B00000, t_norm}, /* ADCS Rd,Rd,Rs */
149 {
150 0xE0D00000, t_norm}, /* SBCS Rd,Rd,Rs */
151 {
152 0xE1B00070, t_shift}, /* MOVS Rd,Rd,ROR Rs */
153 {
154 0xE1100000, t_norm}, /* TST Rd,Rs */
155 {
156 0xE2700000, t_neg}, /* RSBS Rd,Rs,#0 */
157 {
158 0xE1500000, t_norm}, /* CMP Rd,Rs */
159 {
160 0xE1700000, t_norm}, /* CMN Rd,Rs */
161 {
162 0xE1900000, t_norm}, /* ORRS Rd,Rd,Rs */
163 {
164 0xE0100090, t_mul}, /* MULS Rd,Rd,Rs */
165 {
166 0xE1D00000, t_norm}, /* BICS Rd,Rd,Rs */
167 {
168 0xE1F00000, t_norm} /* MVNS Rd,Rs */
169 };
170 *ainstr = subset[(tinstr & 0x03C0) >> 6].opcode; /* base */
171 switch (subset[(tinstr & 0x03C0) >> 6].otype) {
172 case t_norm:
173 *ainstr |= ((tinstr & 0x0007) << 16) /* Rn */
174 |((tinstr & 0x0007) << 12) /* Rd */
175 |((tinstr & 0x0038) >> 3); /* Rs */
176 break;
177 case t_shift:
178 *ainstr |= ((tinstr & 0x0007) << 12) /* Rd */
179 |((tinstr & 0x0007) >> 0) /* Rm */
180 |((tinstr & 0x0038) << (8 - 3)); /* Rs */
181 break;
182 case t_neg:
183 *ainstr |= ((tinstr & 0x0007) << 12) /* Rd */
184 |((tinstr & 0x0038) << (16 - 3)); /* Rn */
185 break;
186 case t_mul:
187 *ainstr |= ((tinstr & 0x0007) << 16) /* Rd */
188 |((tinstr & 0x0007) << 8) /* Rs */
189 |((tinstr & 0x0038) >> 3); /* Rm */
190 break;
191 }
192 }
193 else {
194 /* Format 5 */
195 ARMword Rd = ((tinstr & 0x0007) >> 0);
196 ARMword Rs = ((tinstr & 0x0038) >> 3);
197 if (tinstr & (1 << 7))
198 Rd += 8;
199 if (tinstr & (1 << 6))
200 Rs += 8;
201 switch ((tinstr & 0x03C0) >> 6) {
202 case 0x1: /* ADD Rd,Rd,Hs */
203 case 0x2: /* ADD Hd,Hd,Rs */
204 case 0x3: /* ADD Hd,Hd,Hs */
205 *ainstr = 0xE0800000 /* base */
206 | (Rd << 16) /* Rn */
207 |(Rd << 12) /* Rd */
208 |(Rs << 0); /* Rm */
209 break;
210 case 0x5: /* CMP Rd,Hs */
211 case 0x6: /* CMP Hd,Rs */
212 case 0x7: /* CMP Hd,Hs */
213 *ainstr = 0xE1500000 /* base */
214 | (Rd << 16) /* Rn */
215 |(Rd << 12) /* Rd */
216 |(Rs << 0); /* Rm */
217 break;
218 case 0x9: /* MOV Rd,Hs */
219 case 0xA: /* MOV Hd,Rs */
220 case 0xB: /* MOV Hd,Hs */
221 *ainstr = 0xE1A00000 /* base */
222 | (Rd << 16) /* Rn */
223 |(Rd << 12) /* Rd */
224 |(Rs << 0); /* Rm */
225 break;
226 case 0xC: /* BX Rs */
227 case 0xD: /* BX Hs */
228 *ainstr = 0xE12FFF10 /* base */
229 | ((tinstr & 0x0078) >> 3); /* Rd */
230 break;
231 case 0x0: /* UNDEFINED */
232 case 0x4: /* UNDEFINED */
233 case 0x8: /* UNDEFINED */
234 valid = t_undefined;
235 break;
236 case 0xE: /* BLX */
237 case 0xF: /* BLX */
238
239 //if (state->is_v5) {
240 if(1){
241 //valid = t_branch;
242 #if 1
243 *ainstr = 0xE1200030 /* base */
244 |(Rs << 0); /* Rm */
245 #endif
246 } else {
247 valid = t_undefined;
248 }
249 break;
250 }
251 }
252 break;
253 case 9: /* LDR Rd,[PC,#imm8] */
254 /* Format 6 */
255 *ainstr = 0xE59F0000 /* base */
256 | ((tinstr & 0x0700) << (12 - 8)) /* Rd */
257 |((tinstr & 0x00FF) << (2 - 0)); /* off8 */
258 break;
259 case 10:
260 case 11:
261 /* TODO: Format 7 and Format 8 perform the same ARM encoding, so
262 the following could be merged into a single subset, saving on
263 the following boolean: */
264 if ((tinstr & (1 << 9)) == 0) {
265 /* Format 7 */
266 ARMword subset[4] = {
267 0xE7800000, /* STR Rd,[Rb,Ro] */
268 0xE7C00000, /* STRB Rd,[Rb,Ro] */
269 0xE7900000, /* LDR Rd,[Rb,Ro] */
270 0xE7D00000 /* LDRB Rd,[Rb,Ro] */
271 };
272 *ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */
273 |((tinstr & 0x0007) << (12 - 0)) /* Rd */
274 |((tinstr & 0x0038) << (16 - 3)) /* Rb */
275 |((tinstr & 0x01C0) >> 6); /* Ro */
276 }
277 else {
278 /* Format 8 */
279 ARMword subset[4] = {
280 0xE18000B0, /* STRH Rd,[Rb,Ro] */
281 0xE19000D0, /* LDRSB Rd,[Rb,Ro] */
282 0xE19000B0, /* LDRH Rd,[Rb,Ro] */
283 0xE19000F0 /* LDRSH Rd,[Rb,Ro] */
284 };
285 *ainstr = subset[(tinstr & 0x0C00) >> 10] /* base */
286 |((tinstr & 0x0007) << (12 - 0)) /* Rd */
287 |((tinstr & 0x0038) << (16 - 3)) /* Rb */
288 |((tinstr & 0x01C0) >> 6); /* Ro */
289 }
290 break;
291 case 12: /* STR Rd,[Rb,#imm5] */
292 case 13: /* LDR Rd,[Rb,#imm5] */
293 case 14: /* STRB Rd,[Rb,#imm5] */
294 case 15: /* LDRB Rd,[Rb,#imm5] */
295 /* Format 9 */
296 {
297 ARMword subset[4] = {
298 0xE5800000, /* STR Rd,[Rb,#imm5] */
299 0xE5900000, /* LDR Rd,[Rb,#imm5] */
300 0xE5C00000, /* STRB Rd,[Rb,#imm5] */
301 0xE5D00000 /* LDRB Rd,[Rb,#imm5] */
302 };
303 /* The offset range defends on whether we are transferring a
304 byte or word value: */
305 *ainstr = subset[(tinstr & 0x1800) >> 11] /* base */
306 |((tinstr & 0x0007) << (12 - 0)) /* Rd */
307 |((tinstr & 0x0038) << (16 - 3)) /* Rb */
308 |((tinstr & 0x07C0) >> (6 - ((tinstr & (1 << 12)) ? 0 : 2))); /* off5 */
309 }
310 break;
311 case 16: /* STRH Rd,[Rb,#imm5] */
312 case 17: /* LDRH Rd,[Rb,#imm5] */
313 /* Format 10 */
314 *ainstr = ((tinstr & (1 << 11)) /* base */
315 ? 0xE1D000B0 /* LDRH */
316 : 0xE1C000B0) /* STRH */
317 |((tinstr & 0x0007) << (12 - 0)) /* Rd */
318 |((tinstr & 0x0038) << (16 - 3)) /* Rb */
319 |((tinstr & 0x01C0) >> (6 - 1)) /* off5, low nibble */
320 |((tinstr & 0x0600) >> (9 - 8)); /* off5, high nibble */
321 break;
322 case 18: /* STR Rd,[SP,#imm8] */
323 case 19: /* LDR Rd,[SP,#imm8] */
324 /* Format 11 */
325 *ainstr = ((tinstr & (1 << 11)) /* base */
326 ? 0xE59D0000 /* LDR */
327 : 0xE58D0000) /* STR */
328 |((tinstr & 0x0700) << (12 - 8)) /* Rd */
329 |((tinstr & 0x00FF) << 2); /* off8 */
330 break;
331 case 20: /* ADD Rd,PC,#imm8 */
332 case 21: /* ADD Rd,SP,#imm8 */
333 /* Format 12 */
334 if ((tinstr & (1 << 11)) == 0) {
335 /* NOTE: The PC value used here should by word aligned */
336 /* We encode shift-left-by-2 in the rotate immediate field,
337 so no shift of off8 is needed. */
338 *ainstr = 0xE28F0F00 /* base */
339 | ((tinstr & 0x0700) << (12 - 8)) /* Rd */
340 |(tinstr & 0x00FF); /* off8 */
341 }
342 else {
343 /* We encode shift-left-by-2 in the rotate immediate field,
344 so no shift of off8 is needed. */
345 *ainstr = 0xE28D0F00 /* base */
346 | ((tinstr & 0x0700) << (12 - 8)) /* Rd */
347 |(tinstr & 0x00FF); /* off8 */
348 }
349 break;
350 case 22:
351 case 23:
352 if ((tinstr & 0x0F00) == 0x0000) {
353 /* Format 13 */
354 /* NOTE: The instruction contains a shift left of 2
355 equivalent (implemented as ROR #30): */
356 *ainstr = ((tinstr & (1 << 7)) /* base */
357 ? 0xE24DDF00 /* SUB */
358 : 0xE28DDF00) /* ADD */
359 |(tinstr & 0x007F); /* off7 */
360 }
361 else if ((tinstr & 0x0F00) == 0x0e00)
362 *ainstr = 0xEF000000 | SWI_Breakpoint;
363 else {
364 /* Format 14 */
365 ARMword subset[4] = {
366 0xE92D0000, /* STMDB sp!,{rlist} */
367 0xE92D4000, /* STMDB sp!,{rlist,lr} */
368 0xE8BD0000, /* LDMIA sp!,{rlist} */
369 0xE8BD8000 /* LDMIA sp!,{rlist,pc} */
370 };
371 *ainstr = subset[((tinstr & (1 << 11)) >> 10) | ((tinstr & (1 << 8)) >> 8)] /* base */
372 |(tinstr & 0x00FF); /* mask8 */
373 }
374 break;
375 case 24: /* STMIA */
376 case 25: /* LDMIA */
377 /* Format 15 */
378 *ainstr = ((tinstr & (1 << 11)) /* base */
379 ? 0xE8B00000 /* LDMIA */
380 : 0xE8A00000) /* STMIA */
381 |((tinstr & 0x0700) << (16 - 8)) /* Rb */
382 |(tinstr & 0x00FF); /* mask8 */
383 break;
384 case 26: /* Bcc */
385 case 27: /* Bcc/SWI */
386 if ((tinstr & 0x0F00) == 0x0F00) {
387 #if 0
388 if (tinstr == (ARMul_ABORTWORD & 0xffff) &&
389 state->AbortAddr == pc) {
390 *ainstr = ARMul_ABORTWORD;
391 break;
392 }
393 #endif
394 /* Format 17 : SWI */
395 *ainstr = 0xEF000000;
396 /* Breakpoint must be handled specially. */
397 if ((tinstr & 0x00FF) == 0x18)
398 *ainstr |= ((tinstr & 0x00FF) << 16);
399 /* New breakpoint value. See gdb/arm-tdep.c */
400 else if ((tinstr & 0x00FF) == 0xFE)
401 *ainstr |= SWI_Breakpoint;
402 else
403 *ainstr |= (tinstr & 0x00FF);
404 }
405 else if ((tinstr & 0x0F00) != 0x0E00) {
406 /* Format 16 */
407 #if 0
408 int doit = FALSE;
409 /* TODO: Since we are doing a switch here, we could just add
410 the SWI and undefined instruction checks into this
411 switch to same on a couple of conditionals: */
412 switch ((tinstr & 0x0F00) >> 8) {
413 case EQ:
414 doit = ZFLAG;
415 break;
416 case NE:
417 doit = !ZFLAG;
418 break;
419 case VS:
420 doit = VFLAG;
421 break;
422 case VC:
423 doit = !VFLAG;
424 break;
425 case MI:
426 doit = NFLAG;
427 break;
428 case PL:
429 doit = !NFLAG;
430 break;
431 case CS:
432 doit = CFLAG;
433 break;
434 case CC:
435 doit = !CFLAG;
436 break;
437 case HI:
438 doit = (CFLAG && !ZFLAG);
439 break;
440 case LS:
441 doit = (!CFLAG || ZFLAG);
442 break;
443 case GE:
444 doit = ((!NFLAG && !VFLAG)
445 || (NFLAG && VFLAG));
446 break;
447 case LT:
448 doit = ((NFLAG && !VFLAG)
449 || (!NFLAG && VFLAG));
450 break;
451 case GT:
452 doit = ((!NFLAG && !VFLAG && !ZFLAG)
453 || (NFLAG && VFLAG && !ZFLAG));
454 break;
455 case LE:
456 doit = ((NFLAG && !VFLAG)
457 || (!NFLAG && VFLAG)) || ZFLAG;
458 break;
459 }
460 if (doit) {
461 state->Reg[15] = (pc + 4
462 + (((tinstr & 0x7F) << 1)
463 | ((tinstr & (1 << 7)) ?
464 0xFFFFFF00 : 0)));
465 FLUSHPIPE;
466 }
467 #endif
468 valid = t_branch;
469 }
470 else /* UNDEFINED : cc=1110(AL) uses different format */
471 valid = t_undefined;
472 break;
473 case 28: /* B */
474 /* Format 18 */
475 #if 0
476 state->Reg[15] = (pc + 4 + (((tinstr & 0x3FF) << 1)
477 | ((tinstr & (1 << 10)) ?
478 0xFFFFF800 : 0)));
479 #endif
480 //FLUSHPIPE;
481 valid = t_branch;
482 break;
483 case 29:
484 if(tinstr & 0x1)
485 valid = t_undefined;
486 else{
487 /* BLX 1 for armv5t and above */
488 //printf("In %s, After BLX(1),LR=0x%x,PC=0x%x, offset=0x%x\n", __FUNCTION__, state->Reg[14], state->Reg[15], (tinstr &0x7FF) << 1);
489 valid = t_branch;
490 }
491 break;
492 case 30: /* BL instruction 1 */
493 /* Format 19 */
494 /* There is no single ARM instruction equivalent for this Thumb
495 instruction. To keep the simulation simple (from the user
496 perspective) we check if the following instruction is the
497 second half of this BL, and if it is we simulate it
498 immediately. */
499 valid = t_branch;
500 break;
501 case 31: /* BL instruction 2 */
502 /* Format 19 */
503 /* There is no single ARM instruction equivalent for this
504 instruction. Also, it should only ever be matched with the
505 fmt19 "BL instruction 1" instruction. However, we do allow
506 the simulation of it on its own, with undefined results if
507 r14 is not suitably initialised. */
508 {
509 #if 0
510 ARMword tmp = (pc + 2);
511 state->Reg[15] =
512 (state->Reg[14] + ((tinstr & 0x07FF) << 1));
513 state->Reg[14] = (tmp | 1);
514 #endif
515 valid = t_branch;
516 }
517 break;
518 }
519 *inst_size = 2;
520 return valid;
521} 376}
diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp
index e2aa5ce92..80ebc359e 100644
--- a/src/core/arm/interpreter/arm_interpreter.cpp
+++ b/src/core/arm/interpreter/arm_interpreter.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/arm/interpreter/arm_interpreter.h" 5#include "core/arm/interpreter/arm_interpreter.h"
@@ -38,78 +38,43 @@ ARM_Interpreter::~ARM_Interpreter() {
38 delete state; 38 delete state;
39} 39}
40 40
41/**
42 * Set the Program Counter to an address
43 * @param addr Address to set PC to
44 */
45void ARM_Interpreter::SetPC(u32 pc) { 41void ARM_Interpreter::SetPC(u32 pc) {
46 state->pc = state->Reg[15] = pc; 42 state->pc = state->Reg[15] = pc;
47} 43}
48 44
49/*
50 * Get the current Program Counter
51 * @return Returns current PC
52 */
53u32 ARM_Interpreter::GetPC() const { 45u32 ARM_Interpreter::GetPC() const {
54 return state->pc; 46 return state->pc;
55} 47}
56 48
57/**
58 * Get an ARM register
59 * @param index Register index (0-15)
60 * @return Returns the value in the register
61 */
62u32 ARM_Interpreter::GetReg(int index) const { 49u32 ARM_Interpreter::GetReg(int index) const {
63 return state->Reg[index]; 50 return state->Reg[index];
64} 51}
65 52
66/**
67 * Set an ARM register
68 * @param index Register index (0-15)
69 * @param value Value to set register to
70 */
71void ARM_Interpreter::SetReg(int index, u32 value) { 53void ARM_Interpreter::SetReg(int index, u32 value) {
72 state->Reg[index] = value; 54 state->Reg[index] = value;
73} 55}
74 56
75/**
76 * Get the current CPSR register
77 * @return Returns the value of the CPSR register
78 */
79u32 ARM_Interpreter::GetCPSR() const { 57u32 ARM_Interpreter::GetCPSR() const {
80 return state->Cpsr; 58 return state->Cpsr;
81} 59}
82 60
83/**
84 * Set the current CPSR register
85 * @param cpsr Value to set CPSR to
86 */
87void ARM_Interpreter::SetCPSR(u32 cpsr) { 61void ARM_Interpreter::SetCPSR(u32 cpsr) {
88 state->Cpsr = cpsr; 62 state->Cpsr = cpsr;
89} 63}
90 64
91/**
92 * Returns the number of clock ticks since the last reset
93 * @return Returns number of clock ticks
94 */
95u64 ARM_Interpreter::GetTicks() const { 65u64 ARM_Interpreter::GetTicks() const {
96 return ARMul_Time(state); 66 return state->NumInstrs;
67}
68
69void ARM_Interpreter::AddTicks(u64 ticks) {
70 state->NumInstrs += ticks;
97} 71}
98 72
99/**
100 * Executes the given number of instructions
101 * @param num_instructions Number of instructions to executes
102 */
103void ARM_Interpreter::ExecuteInstructions(int num_instructions) { 73void ARM_Interpreter::ExecuteInstructions(int num_instructions) {
104 state->NumInstrsToExecute = num_instructions - 1; 74 state->NumInstrsToExecute = num_instructions - 1;
105 ARMul_Emulate32(state); 75 ARMul_Emulate32(state);
106} 76}
107 77
108/**
109 * Saves the current CPU context
110 * @param ctx Thread context to save
111 * @todo Do we need to save Reg[15] and NextInstr?
112 */
113void ARM_Interpreter::SaveContext(ThreadContext& ctx) { 78void ARM_Interpreter::SaveContext(ThreadContext& ctx) {
114 memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers)); 79 memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers));
115 memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers)); 80 memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers));
@@ -126,11 +91,6 @@ void ARM_Interpreter::SaveContext(ThreadContext& ctx) {
126 ctx.mode = state->NextInstr; 91 ctx.mode = state->NextInstr;
127} 92}
128 93
129/**
130 * Loads a CPU context
131 * @param ctx Thread context to load
132 * @param Do we need to load Reg[15] and NextInstr?
133 */
134void ARM_Interpreter::LoadContext(const ThreadContext& ctx) { 94void ARM_Interpreter::LoadContext(const ThreadContext& ctx) {
135 memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers)); 95 memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers));
136 memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers)); 96 memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers));
@@ -147,7 +107,6 @@ void ARM_Interpreter::LoadContext(const ThreadContext& ctx) {
147 state->NextInstr = ctx.mode; 107 state->NextInstr = ctx.mode;
148} 108}
149 109
150/// Prepare core for thread reschedule (if needed to correctly handle state)
151void ARM_Interpreter::PrepareReschedule() { 110void ARM_Interpreter::PrepareReschedule() {
152 state->NumInstrsToExecute = 0; 111 state->NumInstrsToExecute = 0;
153} 112}
diff --git a/src/core/arm/interpreter/arm_interpreter.h b/src/core/arm/interpreter/arm_interpreter.h
index ed53d997c..019dad5df 100644
--- a/src/core/arm/interpreter/arm_interpreter.h
+++ b/src/core/arm/interpreter/arm_interpreter.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -61,6 +61,12 @@ public:
61 u64 GetTicks() const override; 61 u64 GetTicks() const override;
62 62
63 /** 63 /**
64 * Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time)
65 * @param ticks Number of ticks to advance the CPU core
66 */
67 void AddTicks(u64 ticks) override;
68
69 /**
64 * Saves the current CPU context 70 * Saves the current CPU context
65 * @param ctx Thread context to save 71 * @param ctx Thread context to save
66 */ 72 */
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 825955ade..b9c2aa6c2 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -1166,7 +1166,7 @@ mainswitch:
1166 else if ((((int)BITS(21, 27)) == 0x3e) && ((int)BITS(4, 6) == 0x1)) { 1166 else if ((((int)BITS(21, 27)) == 0x3e) && ((int)BITS(4, 6) == 0x1)) {
1167 //(ARMword)(instr<<(31-(n))) >> ((31-(n))+(m)) 1167 //(ARMword)(instr<<(31-(n))) >> ((31-(n))+(m))
1168 unsigned msb ,tmp_rn, tmp_rd, dst; 1168 unsigned msb ,tmp_rn, tmp_rd, dst;
1169 msb = tmp_rd = tmp_rn = dst = 0; 1169 tmp_rd = tmp_rn = dst = 0;
1170 Rd = BITS(12, 15); 1170 Rd = BITS(12, 15);
1171 Rn = BITS(0, 3); 1171 Rn = BITS(0, 3);
1172 lsb = BITS(7, 11); 1172 lsb = BITS(7, 11);
@@ -1356,7 +1356,13 @@ mainswitch:
1356 } 1356 }
1357 break; 1357 break;
1358 1358
1359 case 0x04: /* SUB reg */ 1359 case 0x04: /* SUB reg */
1360 // Signifies UMAAL
1361 if (state->is_v6 && BITS(4, 7) == 0x09) {
1362 if (handle_v6_insn(state, instr))
1363 break;
1364 }
1365
1360#ifdef MODET 1366#ifdef MODET
1361 if (BITS (4, 7) == 0xB) { 1367 if (BITS (4, 7) == 0xB) {
1362 /* STRH immediate offset, no write-back, down, post indexed. */ 1368 /* STRH immediate offset, no write-back, down, post indexed. */
@@ -1664,7 +1670,7 @@ mainswitch:
1664 op1 *= op2; 1670 op1 *= op2;
1665 //printf("SMLA_INST:BB,op1=0x%x, op2=0x%x. Rn=0x%x\n", op1, op2, Rn); 1671 //printf("SMLA_INST:BB,op1=0x%x, op2=0x%x. Rn=0x%x\n", op1, op2, Rn);
1666 if (AddOverflow(op1, Rn, op1 + Rn)) 1672 if (AddOverflow(op1, Rn, op1 + Rn))
1667 SETS; 1673 SETQ;
1668 state->Reg[BITS (16, 19)] = op1 + Rn; 1674 state->Reg[BITS (16, 19)] = op1 + Rn;
1669 break; 1675 break;
1670 } 1676 }
@@ -1676,7 +1682,7 @@ mainswitch:
1676 ARMword result = op1 + op2; 1682 ARMword result = op1 + op2;
1677 if (AddOverflow(op1, op2, result)) { 1683 if (AddOverflow(op1, op2, result)) {
1678 result = POS (result) ? 0x80000000 : 0x7fffffff; 1684 result = POS (result) ? 0x80000000 : 0x7fffffff;
1679 SETS; 1685 SETQ;
1680 } 1686 }
1681 state->Reg[BITS (12, 15)] = result; 1687 state->Reg[BITS (12, 15)] = result;
1682 break; 1688 break;
@@ -1718,7 +1724,7 @@ mainswitch:
1718 TAKEABORT; 1724 TAKEABORT;
1719 } else if ((BITS (0, 11) == 0) && (LHSReg == 15)) { /* MRS CPSR */ 1725 } else if ((BITS (0, 11) == 0) && (LHSReg == 15)) { /* MRS CPSR */
1720 UNDEF_MRSPC; 1726 UNDEF_MRSPC;
1721 DEST = ECC | EINT | EMODE; 1727 DEST = ARMul_GetCPSR(state);
1722 } else { 1728 } else {
1723 UNDEF_Test; 1729 UNDEF_Test;
1724 } 1730 }
@@ -1737,7 +1743,7 @@ mainswitch:
1737 //chy 2006-02-15 if in user mode, can not set cpsr 0:23 1743 //chy 2006-02-15 if in user mode, can not set cpsr 0:23
1738 //from p165 of ARMARM book 1744 //from p165 of ARMARM book
1739 state->Cpsr = GETSPSR (state->Bank); 1745 state->Cpsr = GETSPSR (state->Bank);
1740 //ARMul_CPSRAltered (state); 1746 ARMul_CPSRAltered (state);
1741#else 1747#else
1742 rhs = DPRegRHS; 1748 rhs = DPRegRHS;
1743 temp = LHS & rhs; 1749 temp = LHS & rhs;
@@ -1789,7 +1795,7 @@ mainswitch:
1789 ARMword Rn = state->Reg[BITS(12, 15)]; 1795 ARMword Rn = state->Reg[BITS(12, 15)];
1790 1796
1791 if (AddOverflow((ARMword)result, Rn, (ARMword)(result + Rn))) 1797 if (AddOverflow((ARMword)result, Rn, (ARMword)(result + Rn)))
1792 SETS; 1798 SETQ;
1793 result += Rn; 1799 result += Rn;
1794 } 1800 }
1795 state->Reg[BITS (16, 19)] = (ARMword)result; 1801 state->Reg[BITS (16, 19)] = (ARMword)result;
@@ -1805,7 +1811,7 @@ mainswitch:
1805 if (SubOverflow 1811 if (SubOverflow
1806 (op1, op2, result)) { 1812 (op1, op2, result)) {
1807 result = POS (result) ? 0x80000000 : 0x7fffffff; 1813 result = POS (result) ? 0x80000000 : 0x7fffffff;
1808 SETS; 1814 SETQ;
1809 } 1815 }
1810 1816
1811 state->Reg[BITS (12, 15)] = result; 1817 state->Reg[BITS (12, 15)] = result;
@@ -1877,7 +1883,7 @@ mainswitch:
1877 /* TEQP reg */ 1883 /* TEQP reg */
1878#ifdef MODE32 1884#ifdef MODE32
1879 state->Cpsr = GETSPSR (state->Bank); 1885 state->Cpsr = GETSPSR (state->Bank);
1880 //ARMul_CPSRAltered (state); 1886 ARMul_CPSRAltered (state);
1881#else 1887#else
1882 rhs = DPRegRHS; 1888 rhs = DPRegRHS;
1883 temp = LHS ^ rhs; 1889 temp = LHS ^ rhs;
@@ -1928,13 +1934,13 @@ mainswitch:
1928 1934
1929 if (AddOverflow 1935 if (AddOverflow
1930 (op2, op2, op2d)) { 1936 (op2, op2, op2d)) {
1931 SETS; 1937 SETQ;
1932 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff; 1938 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
1933 } 1939 }
1934 1940
1935 result = op1 + op2d; 1941 result = op1 + op2d;
1936 if (AddOverflow(op1, op2d, result)) { 1942 if (AddOverflow(op1, op2d, result)) {
1937 SETS; 1943 SETQ;
1938 result = POS (result) ? 0x80000000 : 0x7fffffff; 1944 result = POS (result) ? 0x80000000 : 0x7fffffff;
1939 } 1945 }
1940 1946
@@ -1993,7 +1999,7 @@ mainswitch:
1993 /* CMPP reg. */ 1999 /* CMPP reg. */
1994#ifdef MODE32 2000#ifdef MODE32
1995 state->Cpsr = GETSPSR (state->Bank); 2001 state->Cpsr = GETSPSR (state->Bank);
1996 //ARMul_CPSRAltered (state); 2002 ARMul_CPSRAltered (state);
1997#else 2003#else
1998 rhs = DPRegRHS; 2004 rhs = DPRegRHS;
1999 temp = LHS - rhs; 2005 temp = LHS - rhs;
@@ -2047,13 +2053,13 @@ mainswitch:
2047 ARMword result; 2053 ARMword result;
2048 2054
2049 if (AddOverflow(op2, op2, op2d)) { 2055 if (AddOverflow(op2, op2, op2d)) {
2050 SETS; 2056 SETQ;
2051 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff; 2057 op2d = POS (op2d) ? 0x80000000 : 0x7fffffff;
2052 } 2058 }
2053 2059
2054 result = op1 - op2d; 2060 result = op1 - op2d;
2055 if (SubOverflow(op1, op2d, result)) { 2061 if (SubOverflow(op1, op2d, result)) {
2056 SETS; 2062 SETQ;
2057 result = POS (result) ? 0x80000000 : 0x7fffffff; 2063 result = POS (result) ? 0x80000000 : 0x7fffffff;
2058 } 2064 }
2059 2065
@@ -2112,7 +2118,7 @@ mainswitch:
2112 if (DESTReg == 15) { 2118 if (DESTReg == 15) {
2113#ifdef MODE32 2119#ifdef MODE32
2114 state->Cpsr = GETSPSR (state->Bank); 2120 state->Cpsr = GETSPSR (state->Bank);
2115 //ARMul_CPSRAltered (state); 2121 ARMul_CPSRAltered (state);
2116#else 2122#else
2117 rhs = DPRegRHS; 2123 rhs = DPRegRHS;
2118 temp = LHS + rhs; 2124 temp = LHS + rhs;
@@ -2200,17 +2206,57 @@ mainswitch:
2200 Handle_Store_Double (state, instr); 2206 Handle_Store_Double (state, instr);
2201 break; 2207 break;
2202 } 2208 }
2209 if (BITS(4, 11) == 0xF9) { //strexd
2210 u32 l = LHSReg;
2211
2212 bool enter = false;
2213
2214 if (state->currentexval == (u32)ARMul_ReadWord(state, state->currentexaddr)&&
2215 state->currentexvald == (u32)ARMul_ReadWord(state, state->currentexaddr + 4))
2216 enter = true;
2217
2218
2219 //todo bug this and STREXD and LDREXD http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0360e/CHDGJGGC.html
2220
2221
2222 if (enter) {
2223 ARMul_StoreWordN(state, LHS, state->Reg[RHSReg]);
2224 ARMul_StoreWordN(state,LHS + 4 , state->Reg[RHSReg + 1]);
2225 state->Reg[DESTReg] = 0;
2226 } else {
2227 state->Reg[DESTReg] = 1;
2228 }
2229
2230 break;
2231 }
2203#endif 2232#endif
2204 dest = DPRegRHS; 2233 dest = DPRegRHS;
2205 WRITEDEST (dest); 2234 WRITEDEST (dest);
2206 break; 2235 break;
2207 2236
2208 case 0x1b: /* MOVS reg */ 2237 case 0x1B: /* MOVS reg */
2209#ifdef MODET 2238#ifdef MODET
2239 /* ldrexd ichfly */
2240 if (BITS(0, 11) == 0xF9F) { //strexd
2241 lhs = LHS;
2242
2243 state->currentexaddr = lhs;
2244 state->currentexval = (u32)ARMul_ReadWord(state, lhs);
2245 state->currentexvald = (u32)ARMul_ReadWord(state, lhs + 4);
2246
2247 state->Reg[DESTReg] = ARMul_LoadWordN(state, lhs);
2248 state->Reg[DESTReg] = ARMul_LoadWordN(state, lhs + 4);
2249 break;
2250 }
2251
2210 if ((BITS (4, 11) & 0xF9) == 0x9) 2252 if ((BITS (4, 11) & 0xF9) == 0x9)
2211 /* LDR register offset, write-back, up, pre indexed. */ 2253 /* LDR register offset, write-back, up, pre indexed. */
2212 LHPREUPWB (); 2254 LHPREUPWB ();
2213 /* Continue with remaining instruction decoding. */ 2255 /* Continue with remaining instruction decoding. */
2256
2257
2258
2259
2214#endif 2260#endif
2215 dest = DPSRegRHS; 2261 dest = DPSRegRHS;
2216 WRITESDEST (dest); 2262 WRITESDEST (dest);
@@ -2297,12 +2343,12 @@ mainswitch:
2297 if (state->currentexval == (u32)ARMul_LoadHalfWord(state, state->currentexaddr))enter = true; 2343 if (state->currentexval == (u32)ARMul_LoadHalfWord(state, state->currentexaddr))enter = true;
2298 2344
2299 2345
2300 ARMul_StoreHalfWord(state, lhs, RHS);
2301 //StoreWord(state, lhs, RHS) 2346 //StoreWord(state, lhs, RHS)
2302 if (state->Aborted) { 2347 if (state->Aborted) {
2303 TAKEABORT; 2348 TAKEABORT;
2304 } 2349 }
2305 if (enter) { 2350 if (enter) {
2351 ARMul_StoreHalfWord(state, lhs, RHS);
2306 state->Reg[DESTReg] = 0; 2352 state->Reg[DESTReg] = 0;
2307 } else { 2353 } else {
2308 state->Reg[DESTReg] = 1; 2354 state->Reg[DESTReg] = 1;
@@ -2520,7 +2566,7 @@ mainswitch:
2520 /* TSTP immed. */ 2566 /* TSTP immed. */
2521#ifdef MODE32 2567#ifdef MODE32
2522 state->Cpsr = GETSPSR (state->Bank); 2568 state->Cpsr = GETSPSR (state->Bank);
2523 //ARMul_CPSRAltered (state); 2569 ARMul_CPSRAltered (state);
2524#else 2570#else
2525 temp = LHS & DPImmRHS; 2571 temp = LHS & DPImmRHS;
2526 SETR15PSR (temp); 2572 SETR15PSR (temp);
@@ -2547,7 +2593,7 @@ mainswitch:
2547 /* TEQP immed. */ 2593 /* TEQP immed. */
2548#ifdef MODE32 2594#ifdef MODE32
2549 state->Cpsr = GETSPSR (state->Bank); 2595 state->Cpsr = GETSPSR (state->Bank);
2550 //ARMul_CPSRAltered (state); 2596 ARMul_CPSRAltered (state);
2551#else 2597#else
2552 temp = LHS ^ DPImmRHS; 2598 temp = LHS ^ DPImmRHS;
2553 SETR15PSR (temp); 2599 SETR15PSR (temp);
@@ -2568,7 +2614,7 @@ mainswitch:
2568 /* CMPP immed. */ 2614 /* CMPP immed. */
2569#ifdef MODE32 2615#ifdef MODE32
2570 state->Cpsr = GETSPSR (state->Bank); 2616 state->Cpsr = GETSPSR (state->Bank);
2571 //ARMul_CPSRAltered (state); 2617 ARMul_CPSRAltered (state);
2572#else 2618#else
2573 temp = LHS - DPImmRHS; 2619 temp = LHS - DPImmRHS;
2574 SETR15PSR (temp); 2620 SETR15PSR (temp);
@@ -2604,7 +2650,7 @@ mainswitch:
2604 /* CMNP immed. */ 2650 /* CMNP immed. */
2605#ifdef MODE32 2651#ifdef MODE32
2606 state->Cpsr = GETSPSR (state->Bank); 2652 state->Cpsr = GETSPSR (state->Bank);
2607 //ARMul_CPSRAltered (state); 2653 ARMul_CPSRAltered (state);
2608#else 2654#else
2609 temp = LHS + DPImmRHS; 2655 temp = LHS + DPImmRHS;
2610 SETR15PSR (temp); 2656 SETR15PSR (temp);
@@ -3054,27 +3100,21 @@ mainswitch:
3054 break; 3100 break;
3055 3101
3056 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */ 3102 case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
3057 //ichfly PKHBT PKHTB todo check this 3103 if ((instr & 0x70) == 0x10) { //pkhbt
3058 if ((instr & 0x70) == 0x10) //pkhbt
3059 {
3060 u8 idest = BITS(12, 15); 3104 u8 idest = BITS(12, 15);
3061 u8 rfis = BITS(16, 19); 3105 u8 rfis = BITS(16, 19);
3062 u8 rlast = BITS(0, 3); 3106 u8 rlast = BITS(0, 3);
3063 u8 ishi = BITS(7,11); 3107 u8 ishi = BITS(7,11);
3064 state->Reg[idest] = (state->Reg[rfis] & 0xFFFF) | ((state->Reg[rlast] << ishi) & 0xFFFF0000); 3108 state->Reg[idest] = (state->Reg[rfis] & 0xFFFF) | ((state->Reg[rlast] << ishi) & 0xFFFF0000);
3065 break; 3109 break;
3066 } 3110 } else if ((instr & 0x70) == 0x50) { //pkhtb
3067 else if ((instr & 0x70) == 0x50)//pkhtb 3111 u8 rd_idx = BITS(12, 15);
3068 { 3112 u8 rn_idx = BITS(16, 19);
3069 u8 idest = BITS(12, 15); 3113 u8 rm_idx = BITS(0, 3);
3070 u8 rfis = BITS(16, 19); 3114 u8 imm5 = BITS(7, 11) ? BITS(7, 11) : 31;
3071 u8 rlast = BITS(0, 3); 3115 state->Reg[rd_idx] = ((static_cast<s32>(state->Reg[rm_idx]) >> imm5) & 0xFFFF) | ((state->Reg[rn_idx]) & 0xFFFF0000);
3072 u8 ishi = BITS(7, 11);
3073 if (ishi == 0)ishi = 0x20;
3074 state->Reg[idest] = (((int)(state->Reg[rlast]) >> (int)(ishi))& 0xFFFF) | ((state->Reg[rfis]) & 0xFFFF0000);
3075 break; 3116 break;
3076 } 3117 } else if (BIT (4)) {
3077 else if (BIT (4)) {
3078#ifdef MODE32 3118#ifdef MODE32
3079 if (state->is_v6 3119 if (state->is_v6
3080 && handle_v6_insn (state, instr)) 3120 && handle_v6_insn (state, instr))
@@ -3686,13 +3726,11 @@ mainswitch:
3686 3726
3687 /* Co-Processor Data Transfers. */ 3727 /* Co-Processor Data Transfers. */
3688 case 0xc4: 3728 case 0xc4:
3689 if ((instr & 0x0FF00FF0) == 0xC400B10) //vmov BIT(0-3), BIT(12-15), BIT(16-20), vmov d0, r0, r0 3729 if ((instr & 0x0FF00FF0) == 0xC400B10) { //vmov BIT(0-3), BIT(12-15), BIT(16-20), vmov d0, r0, r0
3690 {
3691 state->ExtReg[BITS(0, 3) << 1] = state->Reg[BITS(12, 15)]; 3730 state->ExtReg[BITS(0, 3) << 1] = state->Reg[BITS(12, 15)];
3692 state->ExtReg[(BITS(0, 3) << 1) + 1] = state->Reg[BITS(16, 20)]; 3731 state->ExtReg[(BITS(0, 3) << 1) + 1] = state->Reg[BITS(16, 20)];
3693 break; 3732 break;
3694 } 3733 } else if (state->is_v5) {
3695 else if (state->is_v5) {
3696 /* Reading from R15 is UNPREDICTABLE. */ 3734 /* Reading from R15 is UNPREDICTABLE. */
3697 if (BITS (12, 15) == 15 || BITS (16, 19) == 15) 3735 if (BITS (12, 15) == 15 || BITS (16, 19) == 15)
3698 ARMul_UndefInstr (state, instr); 3736 ARMul_UndefInstr (state, instr);
@@ -3712,22 +3750,18 @@ mainswitch:
3712 break; 3750 break;
3713 3751
3714 case 0xc5: 3752 case 0xc5:
3715 if ((instr & 0x00000FF0) == 0xB10) //vmov BIT(12-15), BIT(16-20), BIT(0-3) vmov r0, r0, d0 3753 if ((instr & 0x00000FF0) == 0xB10) { //vmov BIT(12-15), BIT(16-20), BIT(0-3) vmov r0, r0, d0
3716 {
3717 state->Reg[BITS(12, 15)] = state->ExtReg[BITS(0, 3) << 1]; 3754 state->Reg[BITS(12, 15)] = state->ExtReg[BITS(0, 3) << 1];
3718 state->Reg[BITS(16, 19)] = state->ExtReg[(BITS(0, 3) << 1) + 1]; 3755 state->Reg[BITS(16, 19)] = state->ExtReg[(BITS(0, 3) << 1) + 1];
3719 break; 3756 break;
3720 } 3757 } else if (state->is_v5) {
3721 else if (state->is_v5) {
3722 /* Writes to R15 are UNPREDICATABLE. */ 3758 /* Writes to R15 are UNPREDICATABLE. */
3723 if (DESTReg == 15 || LHSReg == 15) 3759 if (DESTReg == 15 || LHSReg == 15)
3724 ARMul_UndefInstr (state, instr); 3760 ARMul_UndefInstr (state, instr);
3725 /* Is access to the coprocessor allowed ? */ 3761 /* Is access to the coprocessor allowed ? */
3726 else if (!CP_ACCESS_ALLOWED(state, CPNum)) 3762 else if (!CP_ACCESS_ALLOWED(state, CPNum)) {
3727 {
3728 ARMul_UndefInstr(state, instr); 3763 ARMul_UndefInstr(state, instr);
3729 } 3764 } else {
3730 else {
3731 /* MRRC, ARMv5TE and up */ 3765 /* MRRC, ARMv5TE and up */
3732 ARMul_MRRC (state, instr, &DEST, &(state->Reg[LHSReg])); 3766 ARMul_MRRC (state, instr, &DEST, &(state->Reg[LHSReg]));
3733 break; 3767 break;
@@ -4565,7 +4599,7 @@ out:
4565#ifdef MODE32 4599#ifdef MODE32
4566 if (state->Bank > 0) { 4600 if (state->Bank > 0) {
4567 state->Cpsr = state->Spsr[state->Bank]; 4601 state->Cpsr = state->Spsr[state->Bank];
4568 //ARMul_CPSRAltered (state); 4602 ARMul_CPSRAltered (state);
4569 } 4603 }
4570#ifdef MODET 4604#ifdef MODET
4571 if (TFLAG) 4605 if (TFLAG)
@@ -5256,7 +5290,7 @@ L_ldm_s_makeabort:
5256 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode 5290 //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode
5257 if (state->Mode != USER26MODE && state->Mode != USER32MODE ) { 5291 if (state->Mode != USER26MODE && state->Mode != USER32MODE ) {
5258 state->Cpsr = GETSPSR (state->Bank); 5292 state->Cpsr = GETSPSR (state->Bank);
5259 //ARMul_CPSRAltered (state); 5293 ARMul_CPSRAltered (state);
5260 } 5294 }
5261 5295
5262 WriteR15 (state, PC); 5296 WriteR15 (state, PC);
@@ -5639,37 +5673,29 @@ L_stm_s_takeabort:
5639 /* Attempt to emulate an ARMv6 instruction. 5673 /* Attempt to emulate an ARMv6 instruction.
5640 Returns non-zero upon success. */ 5674 Returns non-zero upon success. */
5641 5675
5642 static int 5676 static int handle_v6_insn(ARMul_State* state, ARMword instr) {
5643 handle_v6_insn (ARMul_State * state, ARMword instr) { 5677 switch (BITS(20, 27)) {
5644 switch (BITS (20, 27)) {
5645 //ichfly
5646 case 0x66: //UQSUB8
5647 if ((instr & 0x0FF00FF0) == 0x06600FF0) {
5648 u32 rd = (instr >> 12) & 0xF;
5649 u32 rm = (instr >> 16) & 0xF;
5650 u32 rn = (instr >> 0) & 0xF;
5651 u32 subfrom = state->Reg[rm];
5652 u32 tosub = state->Reg[rn];
5653
5654 u8 b1 = (u8)((u8)(subfrom)-(u8)(tosub));
5655 if (b1 > (u8)(subfrom)) b1 = 0;
5656 u8 b2 = (u8)((u8)(subfrom >> 8) - (u8)(tosub >> 8));
5657 if (b2 > (u8)(subfrom >> 8)) b2 = 0;
5658 u8 b3 = (u8)((u8)(subfrom >> 16) - (u8)(tosub >> 16));
5659 if (b3 > (u8)(subfrom >> 16)) b3 = 0;
5660 u8 b4 = (u8)((u8)(subfrom >> 24) - (u8)(tosub >> 24));
5661 if (b4 > (u8)(subfrom >> 24)) b4 = 0;
5662 state->Reg[rd] = (u32)(b1 | b2 << 8 | b3 << 16 | b4 << 24);
5663 return 1;
5664 } else {
5665 printf("UQSUB8 decoding fail %08X",instr);
5666 }
5667#if 0
5668 case 0x03: 5678 case 0x03:
5669 printf ("Unhandled v6 insn: ldr\n"); 5679 printf ("Unhandled v6 insn: ldr\n");
5670 break; 5680 break;
5671 case 0x04: 5681 case 0x04: // UMAAL
5672 printf ("Unhandled v6 insn: umaal\n"); 5682 {
5683 const u8 rm_idx = BITS(8, 11);
5684 const u8 rn_idx = BITS(0, 3);
5685 const u8 rd_lo_idx = BITS(12, 15);
5686 const u8 rd_hi_idx = BITS(16, 19);
5687
5688 const u32 rm_val = state->Reg[rm_idx];
5689 const u32 rn_val = state->Reg[rn_idx];
5690 const u32 rd_lo_val = state->Reg[rd_lo_idx];
5691 const u32 rd_hi_val = state->Reg[rd_hi_idx];
5692
5693 const u64 result = (rn_val * rm_val) + rd_lo_val + rd_hi_val;
5694
5695 state->Reg[rd_lo_idx] = (result & 0xFFFFFFFF);
5696 state->Reg[rd_hi_idx] = ((result >> 32) & 0xFFFFFFFF);
5697 return 1;
5698 }
5673 break; 5699 break;
5674 case 0x06: 5700 case 0x06:
5675 printf ("Unhandled v6 insn: mls/str\n"); 5701 printf ("Unhandled v6 insn: mls/str\n");
@@ -5678,9 +5704,43 @@ L_stm_s_takeabort:
5678 printf ("Unhandled v6 insn: smi\n"); 5704 printf ("Unhandled v6 insn: smi\n");
5679 break; 5705 break;
5680 case 0x18: 5706 case 0x18:
5707 if (BITS(4, 7) == 0x9) {
5708 /* strex */
5709 u32 l = LHSReg;
5710 u32 r = RHSReg;
5711 u32 lhs = LHS;
5712
5713 bool enter = false;
5714
5715 if (state->currentexval == (u32)ARMul_ReadWord(state, state->currentexaddr))enter = true;
5716 //StoreWord(state, lhs, RHS)
5717 if (state->Aborted) {
5718 TAKEABORT;
5719 }
5720
5721 if (enter) {
5722 ARMul_StoreWordS(state, lhs, RHS);
5723 state->Reg[DESTReg] = 0;
5724 }
5725 else {
5726 state->Reg[DESTReg] = 1;
5727 }
5728
5729 return 1;
5730 }
5681 printf ("Unhandled v6 insn: strex\n"); 5731 printf ("Unhandled v6 insn: strex\n");
5682 break; 5732 break;
5683 case 0x19: 5733 case 0x19:
5734 /* ldrex */
5735 if (BITS(4, 7) == 0x9) {
5736 u32 lhs = LHS;
5737
5738 state->currentexaddr = lhs;
5739 state->currentexval = ARMul_ReadWord(state, lhs);
5740
5741 LoadWord(state, instr, lhs);
5742 return 1;
5743 }
5684 printf ("Unhandled v6 insn: ldrex\n"); 5744 printf ("Unhandled v6 insn: ldrex\n");
5685 break; 5745 break;
5686 case 0x1a: 5746 case 0x1a:
@@ -5690,9 +5750,52 @@ L_stm_s_takeabort:
5690 printf ("Unhandled v6 insn: ldrexd\n"); 5750 printf ("Unhandled v6 insn: ldrexd\n");
5691 break; 5751 break;
5692 case 0x1c: 5752 case 0x1c:
5753 if (BITS(4, 7) == 0x9) {
5754 /* strexb */
5755 u32 lhs = LHS;
5756
5757 bool enter = false;
5758
5759 if (state->currentexval == (u32)ARMul_ReadByte(state, state->currentexaddr))enter = true;
5760
5761 BUSUSEDINCPCN;
5762 if (state->Aborted) {
5763 TAKEABORT;
5764 }
5765
5766
5767 if (enter) {
5768 ARMul_StoreByte(state, lhs, RHS);
5769 state->Reg[DESTReg] = 0;
5770 }
5771 else {
5772 state->Reg[DESTReg] = 1;
5773 }
5774
5775 //printf("In %s, strexb not implemented\n", __FUNCTION__);
5776 UNDEF_LSRBPC;
5777 /* WRITESDEST (dest); */
5778 return 1;
5779 }
5693 printf ("Unhandled v6 insn: strexb\n"); 5780 printf ("Unhandled v6 insn: strexb\n");
5694 break; 5781 break;
5695 case 0x1d: 5782 case 0x1d:
5783 if ((BITS(4, 7)) == 0x9) {
5784 /* ldrexb */
5785 u32 lhs = LHS;
5786 LoadByte(state, instr, lhs, LUNSIGNED);
5787
5788 state->currentexaddr = lhs;
5789 state->currentexval = (u32)ARMul_ReadByte(state, lhs);
5790
5791 //state->Reg[BITS(12, 15)] = ARMul_LoadByte(state, state->Reg[BITS(16, 19)]);
5792 //printf("ldrexb\n");
5793 //printf("instr is %x rm is %d\n", instr, BITS(16, 19));
5794 //exit(-1);
5795
5796 //printf("In %s, ldrexb not implemented\n", __FUNCTION__);
5797 return 1;
5798 }
5696 printf ("Unhandled v6 insn: ldrexb\n"); 5799 printf ("Unhandled v6 insn: ldrexb\n");
5697 break; 5800 break;
5698 case 0x1e: 5801 case 0x1e:
@@ -5713,510 +5816,801 @@ L_stm_s_takeabort:
5713 case 0x3f: 5816 case 0x3f:
5714 printf ("Unhandled v6 insn: rbit\n"); 5817 printf ("Unhandled v6 insn: rbit\n");
5715 break; 5818 break;
5716#endif 5819 case 0x61: // SADD16, SASX, SSAX, and SSUB16
5717 case 0x61: 5820 if ((instr & 0xFF0) == 0xf10 || (instr & 0xFF0) == 0xf30 ||
5718 if ((instr & 0xFF0) == 0xf70)//ssub16 5821 (instr & 0xFF0) == 0xf50 || (instr & 0xFF0) == 0xf70)
5719 {
5720 u8 tar = BITS(12, 15);
5721 u8 src1 = BITS(16, 19);
5722 u8 src2 = BITS(0, 3);
5723 s16 a1 = (state->Reg[src1] & 0xFFFF);
5724 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5725 s16 b1 = (state->Reg[src2] & 0xFFFF);
5726 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
5727 state->Reg[tar] = ((a1 - a2) & 0xFFFF) | (((b1 - b2)&0xFFFF)<< 0x10);
5728 return 1;
5729 }
5730 else if ((instr & 0xFF0) == 0xf10)//sadd16
5731 { 5822 {
5732 u8 tar = BITS(12, 15); 5823 const u8 rd_idx = BITS(12, 15);
5733 u8 src1 = BITS(16, 19); 5824 const u8 rm_idx = BITS(0, 3);
5734 u8 src2 = BITS(0, 3); 5825 const u8 rn_idx = BITS(16, 19);
5735 s16 a1 = (state->Reg[src1] & 0xFFFF); 5826 const s16 rn_lo = (state->Reg[rn_idx] & 0xFFFF);
5736 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); 5827 const s16 rn_hi = ((state->Reg[rn_idx] >> 16) & 0xFFFF);
5737 s16 b1 = (state->Reg[src2] & 0xFFFF); 5828 const s16 rm_lo = (state->Reg[rm_idx] & 0xFFFF);
5738 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); 5829 const s16 rm_hi = ((state->Reg[rm_idx] >> 16) & 0xFFFF);
5739 state->Reg[tar] = ((a1 + a2) & 0xFFFF) | (((b1 + b2)&0xFFFF)<< 0x10); 5830
5831 s32 lo_result;
5832 s32 hi_result;
5833
5834 // SADD16
5835 if ((instr & 0xFF0) == 0xf10) {
5836 lo_result = (rn_lo + rm_lo);
5837 hi_result = (rn_hi + rm_hi);
5838 }
5839 // SASX
5840 else if ((instr & 0xFF0) == 0xf30) {
5841 lo_result = (rn_lo - rm_hi);
5842 hi_result = (rn_hi + rm_lo);
5843 }
5844 // SSAX
5845 else if ((instr & 0xFF0) == 0xf50) {
5846 lo_result = (rn_lo + rm_hi);
5847 hi_result = (rn_hi - rm_lo);
5848 }
5849 // SSUB16
5850 else {
5851 lo_result = (rn_lo - rm_lo);
5852 hi_result = (rn_hi - rm_hi);
5853 }
5854
5855 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
5856
5857 if (lo_result >= 0) {
5858 state->GEFlag |= (1 << 16);
5859 state->GEFlag |= (1 << 17);
5860 } else {
5861 state->GEFlag &= ~(1 << 16);
5862 state->GEFlag &= ~(1 << 17);
5863 }
5864
5865 if (hi_result >= 0) {
5866 state->GEFlag |= (1 << 18);
5867 state->GEFlag |= (1 << 19);
5868 } else {
5869 state->GEFlag &= ~(1 << 18);
5870 state->GEFlag &= ~(1 << 19);
5871 }
5872
5740 return 1; 5873 return 1;
5741 } 5874 }
5742 else if ((instr & 0xFF0) == 0xf50)//ssax 5875 // SADD8/SSUB8
5876 else if ((instr & 0xFF0) == 0xf90 || (instr & 0xFF0) == 0xff0)
5743 { 5877 {
5744 u8 tar = BITS(12, 15); 5878 const u8 rd_idx = BITS(12, 15);
5745 u8 src1 = BITS(16, 19); 5879 const u8 rm_idx = BITS(0, 3);
5746 u8 src2 = BITS(0, 3); 5880 const u8 rn_idx = BITS(16, 19);
5747 s16 a1 = (state->Reg[src1] & 0xFFFF); 5881 const u32 rm_val = state->Reg[rm_idx];
5748 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); 5882 const u32 rn_val = state->Reg[rn_idx];
5749 s16 b1 = (state->Reg[src2] & 0xFFFF); 5883
5750 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); 5884 u8 lo_val1;
5751 state->Reg[tar] = ((a1 + b2) & 0xFFFF) | (((a2 - b1) & 0xFFFF) << 0x10); 5885 u8 lo_val2;
5886 u8 hi_val1;
5887 u8 hi_val2;
5888
5889 // SADD8
5890 if ((instr & 0xFF0) == 0xf90) {
5891 lo_val1 = (u8)((rn_val & 0xFF) + (rm_val & 0xFF));
5892 lo_val2 = (u8)(((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF));
5893 hi_val1 = (u8)(((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF));
5894 hi_val2 = (u8)(((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF));
5895
5896 if (lo_val1 & 0x80)
5897 state->GEFlag |= (1 << 16);
5898 else
5899 state->GEFlag &= ~(1 << 16);
5900
5901 if (lo_val2 & 0x80)
5902 state->GEFlag |= (1 << 17);
5903 else
5904 state->GEFlag &= ~(1 << 17);
5905
5906 if (hi_val1 & 0x80)
5907 state->GEFlag |= (1 << 18);
5908 else
5909 state->GEFlag &= ~(1 << 18);
5910
5911 if (hi_val2 & 0x80)
5912 state->GEFlag |= (1 << 19);
5913 else
5914 state->GEFlag &= ~(1 << 19);
5915 }
5916 // SSUB8
5917 else {
5918 lo_val1 = (u8)((rn_val & 0xFF) - (rm_val & 0xFF));
5919 lo_val2 = (u8)(((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF));
5920 hi_val1 = (u8)(((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF));
5921 hi_val2 = (u8)(((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF));
5922
5923 if (!(lo_val1 & 0x80))
5924 state->GEFlag |= (1 << 16);
5925 else
5926 state->GEFlag &= ~(1 << 16);
5927
5928 if (!(lo_val2 & 0x80))
5929 state->GEFlag |= (1 << 17);
5930 else
5931 state->GEFlag &= ~(1 << 17);
5932
5933 if (!(hi_val1 & 0x80))
5934 state->GEFlag |= (1 << 18);
5935 else
5936 state->GEFlag &= ~(1 << 18);
5937
5938 if (!(hi_val2 & 0x80))
5939 state->GEFlag |= (1 << 19);
5940 else
5941 state->GEFlag &= ~(1 << 19);
5942 }
5943
5944 state->Reg[rd_idx] = (lo_val1 | lo_val2 << 8 | hi_val1 << 16 | hi_val2 << 24);
5752 return 1; 5945 return 1;
5753 } 5946 }
5754 else if ((instr & 0xFF0) == 0xf30)//sasx 5947 else {
5755 { 5948 printf("Unhandled v6 insn: %08x", instr);
5756 u8 tar = BITS(12, 15);
5757 u8 src1 = BITS(16, 19);
5758 u8 src2 = BITS(0, 3);
5759 s16 a1 = (state->Reg[src1] & 0xFFFF);
5760 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5761 s16 b1 = (state->Reg[src2] & 0xFFFF);
5762 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF);
5763 state->Reg[tar] = ((a1 - b2) & 0xFFFF) | (((a2 + b1) & 0xFFFF) << 0x10);
5764 return 1;
5765 } 5949 }
5766 else printf ("Unhandled v6 insn: sadd/ssub\n");
5767 break; 5950 break;
5768 case 0x62: 5951 case 0x62: // QADD16, QASX, QSAX, QSUB16, QADD8, and QSUB8
5769 if ((instr & 0xFF0) == 0xf70)//QSUB16
5770 { 5952 {
5771 u8 tar = BITS(12, 15); 5953 const u8 op2 = BITS(5, 7);
5772 u8 src1 = BITS(16, 19); 5954
5773 u8 src2 = BITS(0, 3); 5955 const u8 rd_idx = BITS(12, 15);
5774 s16 a1 = (state->Reg[src1] & 0xFFFF); 5956 const u8 rn_idx = BITS(16, 19);
5775 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); 5957 const u8 rm_idx = BITS(0, 3);
5776 s16 b1 = (state->Reg[src2] & 0xFFFF); 5958 const u16 rm_lo = (state->Reg[rm_idx] & 0xFFFF);
5777 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); 5959 const u16 rm_hi = ((state->Reg[rm_idx] >> 0x10) & 0xFFFF);
5778 s32 res1 = (a1 - b1); 5960 const u16 rn_lo = (state->Reg[rn_idx] & 0xFFFF);
5779 s32 res2 = (a2 - b2); 5961 const u16 rn_hi = ((state->Reg[rn_idx] >> 0x10) & 0xFFFF);
5780 if (res1 > 0x7FFF) res1 = 0x7FFF; 5962
5781 if (res2 > 0x7FFF) res2 = 0x7FFF; 5963 u16 lo_result = 0;
5782 if (res1 < 0x7FFF) res1 = -0x8000; 5964 u16 hi_result = 0;
5783 if (res2 < 0x7FFF) res2 = -0x8000; 5965
5784 state->Reg[tar] = (res1 & 0xFFFF) | ((res2 & 0xFFFF) << 0x10); 5966 // QADD16
5785 return 1; 5967 if (op2 == 0x00) {
5786 } 5968 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_lo);
5787 else if ((instr & 0xFF0) == 0xf10)//QADD16 5969 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_hi);
5788 { 5970 }
5789 u8 tar = BITS(12, 15); 5971 // QASX
5790 u8 src1 = BITS(16, 19); 5972 else if (op2 == 0x01) {
5791 u8 src2 = BITS(0, 3); 5973 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_hi);
5792 s16 a1 = (state->Reg[src1] & 0xFFFF); 5974 hi_result = ARMul_SignedSaturatedAdd16(rn_hi, rm_lo);
5793 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); 5975 }
5794 s16 b1 = (state->Reg[src2] & 0xFFFF); 5976 // QSAX
5795 s16 b2 = ((state->Reg[src2] >> 0x10) & 0xFFFF); 5977 else if (op2 == 0x02) {
5796 s32 res1 = (a1 + b1); 5978 lo_result = ARMul_SignedSaturatedAdd16(rn_lo, rm_hi);
5797 s32 res2 = (a2 + b2); 5979 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_lo);
5798 if (res1 > 0x7FFF) res1 = 0x7FFF; 5980 }
5799 if (res2 > 0x7FFF) res2 = 0x7FFF; 5981 // QSUB16
5800 if (res1 < 0x7FFF) res1 = -0x8000; 5982 else if (op2 == 0x03) {
5801 if (res2 < 0x7FFF) res2 = -0x8000; 5983 lo_result = ARMul_SignedSaturatedSub16(rn_lo, rm_lo);
5802 state->Reg[tar] = ((res1) & 0xFFFF) | (((res2) & 0xFFFF) << 0x10); 5984 hi_result = ARMul_SignedSaturatedSub16(rn_hi, rm_hi);
5985 }
5986 // QADD8
5987 else if (op2 == 0x04) {
5988 lo_result = ARMul_SignedSaturatedAdd8(rn_lo & 0xFF, rm_lo & 0xFF) |
5989 ARMul_SignedSaturatedAdd8(rn_lo >> 8, rm_lo >> 8) << 8;
5990 hi_result = ARMul_SignedSaturatedAdd8(rn_hi & 0xFF, rm_hi & 0xFF) |
5991 ARMul_SignedSaturatedAdd8(rn_hi >> 8, rm_hi >> 8) << 8;
5992 }
5993 // QSUB8
5994 else if (op2 == 0x07) {
5995 lo_result = ARMul_SignedSaturatedSub8(rn_lo & 0xFF, rm_lo & 0xFF) |
5996 ARMul_SignedSaturatedSub8(rn_lo >> 8, rm_lo >> 8) << 8;
5997 hi_result = ARMul_SignedSaturatedSub8(rn_hi & 0xFF, rm_hi & 0xFF) |
5998 ARMul_SignedSaturatedSub8(rn_hi >> 8, rm_hi >> 8) << 8;
5999 }
6000
6001 state->Reg[rd_idx] = (lo_result & 0xFFFF) | ((hi_result & 0xFFFF) << 16);
5803 return 1; 6002 return 1;
5804 } 6003 }
5805 else printf ("Unhandled v6 insn: qadd/qsub\n");
5806 break; 6004 break;
5807#if 0
5808 case 0x63: 6005 case 0x63:
5809 printf ("Unhandled v6 insn: shadd/shsub\n"); 6006 printf ("Unhandled v6 insn: shadd/shsub\n");
5810 break; 6007 break;
5811 case 0x65: 6008 case 0x65:
5812 printf ("Unhandled v6 insn: uadd/usub\n"); 6009 {
5813 break; 6010 u32 rd = (instr >> 12) & 0xF;
5814 case 0x66: 6011 u32 rn = (instr >> 16) & 0xF;
5815 printf ("Unhandled v6 insn: uqadd/uqsub\n"); 6012 u32 rm = (instr >> 0) & 0xF;
5816 break; 6013 u32 from = state->Reg[rn];
5817 case 0x67: 6014 u32 to = state->Reg[rm];
5818 printf ("Unhandled v6 insn: uhadd/uhsub\n"); 6015
5819 break; 6016 if ((instr & 0xFF0) == 0xF10 || (instr & 0xFF0) == 0xF70) { // UADD16/USUB16
5820 case 0x68: 6017 u32 h1, h2;
5821 printf ("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); 6018 state->Cpsr &= 0xfff0ffff;
5822 break; 6019 if ((instr & 0x0F0) == 0x070) { // USUB16
5823#endif 6020 h1 = ((u16)from - (u16)to);
5824 case 0x6c: 6021 h2 = ((u16)(from >> 16) - (u16)(to >> 16));
5825 if ((instr & 0xf03f0) == 0xf0070) //uxtb16 6022
5826 { 6023 if (!(h1 & 0xffff0000))
5827 u8 src1 = BITS(0, 3); 6024 state->GEFlag |= (3 << 16);
5828 u8 tar = BITS(12, 15); 6025 else
5829 u32 base = state->Reg[src1]; 6026 state->GEFlag &= ~(3 << 16);
5830 u32 shamt = BITS(9,10)* 8;
5831 u32 in = ((base << (32 - shamt)) | (base >> shamt));
5832 state->Reg[tar] = in & 0x00FF00FF;
5833 return 1;
5834 }
5835 else
5836 printf ("Unhandled v6 insn: uxtb16/uxtab16\n");
5837 break;
5838 case 0x70:
5839 if ((instr & 0xf0d0) == 0xf010)//smuad //ichfly
5840 {
5841 u8 tar = BITS(16, 19);
5842 u8 src1 = BITS(0, 3);
5843 u8 src2 = BITS(8, 11);
5844 u8 swap = BIT(5);
5845 s16 a1 = (state->Reg[src1] & 0xFFFF);
5846 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5847 s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF);
5848 s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF);
5849 state->Reg[tar] = a1*a2 + b1*b2;
5850 return 1;
5851 6027
5852 } 6028 if (!(h2 & 0xffff0000))
5853 else if ((instr & 0xf0d0) == 0xf050)//smusd 6029 state->GEFlag |= (3 << 18);
5854 { 6030 else
5855 u8 tar = BITS(16, 19); 6031 state->GEFlag &= ~(3 << 18);
5856 u8 src1 = BITS(0, 3); 6032 }
5857 u8 src2 = BITS(8, 11); 6033 else { // UADD16
5858 u8 swap = BIT(5); 6034 h1 = ((u16)from + (u16)to);
5859 s16 a1 = (state->Reg[src1] & 0xFFFF); 6035 h2 = ((u16)(from >> 16) + (u16)(to >> 16));
5860 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF); 6036
5861 s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF); 6037 if (h1 & 0xffff0000)
5862 s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF); 6038 state->GEFlag |= (3 << 16);
5863 state->Reg[tar] = a1*a2 - b1*b2; 6039 else
5864 return 1; 6040 state->GEFlag &= ~(3 << 16);
5865 } 6041
5866 else if ((instr & 0xd0) == 0x10)//smlad 6042 if (h2 & 0xffff0000)
5867 { 6043 state->GEFlag |= (3 << 18);
5868 u8 tar = BITS(16, 19); 6044 else
5869 u8 src1 = BITS(0, 3); 6045 state->GEFlag &= ~(3 << 18);
5870 u8 src2 = BITS(8, 11); 6046 }
5871 u8 src3 = BITS(12, 15); 6047
5872 u8 swap = BIT(5); 6048 state->Reg[rd] = (u32)((h1 & 0xffff) | ((h2 & 0xffff) << 16));
5873
5874 u32 a3 = state->Reg[src3];
5875
5876 s16 a1 = (state->Reg[src1] & 0xFFFF);
5877 s16 a2 = ((state->Reg[src1] >> 0x10) & 0xFFFF);
5878 s16 b1 = swap ? ((state->Reg[src2] >> 0x10) & 0xFFFF) : (state->Reg[src2] & 0xFFFF);
5879 s16 b2 = swap ? (state->Reg[src2] & 0xFFFF) : ((state->Reg[src2] >> 0x10) & 0xFFFF);
5880 state->Reg[tar] = a1*a2 + b1*b2 + a3;
5881 return 1; 6049 return 1;
5882 } 6050 }
5883 else printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); 6051 else
5884 break; 6052 if ((instr & 0xFF0) == 0xF90 || (instr & 0xFF0) == 0xFF0) { // UADD8/USUB8
5885 case 0x74: 6053 u32 b1, b2, b3, b4;
5886 printf ("Unhandled v6 insn: smlald/smlsld\n"); 6054 state->Cpsr &= 0xfff0ffff;
5887 break; 6055 if ((instr & 0x0F0) == 0x0F0) { // USUB8
5888 case 0x75: 6056 b1 = ((u8)from - (u8)to);
5889 printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); 6057 b2 = ((u8)(from >> 8) - (u8)(to >> 8));
5890 break; 6058 b3 = ((u8)(from >> 16) - (u8)(to >> 16));
5891 case 0x78: 6059 b4 = ((u8)(from >> 24) - (u8)(to >> 24));
5892 printf ("Unhandled v6 insn: usad/usada8\n"); 6060
5893 break; 6061 if (!(b1 & 0xffffff00))
5894#if 0 6062 state->GEFlag |= (1 << 16);
5895 case 0x7a: 6063 else
5896 printf ("Unhandled v6 insn: usbfx\n"); 6064 state->GEFlag &= ~(1 << 16);
5897 break;
5898 case 0x7c:
5899 printf ("Unhandled v6 insn: bfc/bfi\n");
5900 break;
5901#endif
5902 6065
6066 if (!(b2 & 0xffffff00))
6067 state->GEFlag |= (1 << 17);
6068 else
6069 state->GEFlag &= ~(1 << 17);
5903 6070
5904 /* add new instr for arm v6. */ 6071 if (!(b3 & 0xffffff00))
5905 ARMword lhs, temp; 6072 state->GEFlag |= (1 << 18);
5906 case 0x18: { /* ORR reg */ 6073 else
5907 /* dyf add armv6 instr strex 2010.9.17 */ 6074 state->GEFlag &= ~(1 << 18);
5908 if (BITS (4, 7) == 0x9) {
5909 u32 l = LHSReg;
5910 u32 r = RHSReg;
5911 lhs = LHS;
5912 6075
5913 bool enter = false; 6076 if (!(b4 & 0xffffff00))
6077 state->GEFlag |= (1 << 19);
6078 else
6079 state->GEFlag &= ~(1 << 19);
6080 }
6081 else { // UADD8
6082 b1 = ((u8)from + (u8)to);
6083 b2 = ((u8)(from >> 8) + (u8)(to >> 8));
6084 b3 = ((u8)(from >> 16) + (u8)(to >> 16));
6085 b4 = ((u8)(from >> 24) + (u8)(to >> 24));
5914 6086
5915 if (state->currentexval == (u32)ARMul_ReadWord(state, state->currentexaddr))enter = true; 6087 if (b1 & 0xffffff00)
5916 ARMul_StoreWordS(state, lhs, RHS); 6088 state->GEFlag |= (1 << 16);
5917 //StoreWord(state, lhs, RHS) 6089 else
5918 if (state->Aborted) { 6090 state->GEFlag &= ~(1 << 16);
5919 TAKEABORT;
5920 }
5921 6091
5922 if (enter) { 6092 if (b2 & 0xffffff00)
5923 state->Reg[DESTReg] = 0; 6093 state->GEFlag |= (1 << 17);
5924 } else { 6094 else
5925 state->Reg[DESTReg] = 1; 6095 state->GEFlag &= ~(1 << 17);
5926 }
5927 6096
5928 return 1; 6097 if (b3 & 0xffffff00)
5929 } 6098 state->GEFlag |= (1 << 18);
5930 break; 6099 else
5931 } 6100 state->GEFlag &= ~(1 << 18);
5932 6101
5933 case 0x19: { /* orrs reg */ 6102 if (b4 & 0xffffff00)
5934 /* dyf add armv6 instr ldrex */ 6103 state->GEFlag |= (1 << 19);
5935 if (BITS (4, 7) == 0x9) { 6104 else
5936 lhs = LHS; 6105 state->GEFlag &= ~(1 << 19);
6106 }
5937 6107
5938 state->currentexaddr = lhs; 6108 state->Reg[rd] = (u32)(b1 | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24);
5939 state->currentexval = ARMul_ReadWord(state, lhs); 6109 return 1;
6110 }
6111 }
6112 printf("Unhandled v6 insn: uasx/usax\n");
6113 break;
6114 case 0x66: // UQADD16, UQASX, UQSAX, UQSUB16, UQADD8, and UQSUB8
6115 {
6116 const u8 rd_idx = BITS(12, 15);
6117 const u8 rm_idx = BITS(0, 3);
6118 const u8 rn_idx = BITS(16, 19);
6119 const u8 op2 = BITS(5, 7);
6120 const u32 rm_val = state->Reg[rm_idx];
6121 const u32 rn_val = state->Reg[rn_idx];
6122
6123 u16 lo_val = 0;
6124 u16 hi_val = 0;
6125
6126 // UQADD16
6127 if (op2 == 0x00) {
6128 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, rm_val & 0xFFFF);
6129 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
6130 }
6131 // UQASX
6132 else if (op2 == 0x01) {
6133 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
6134 hi_val = ARMul_UnsignedSaturatedAdd16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
6135 }
6136 // UQSAX
6137 else if (op2 == 0x02) {
6138 lo_val = ARMul_UnsignedSaturatedAdd16(rn_val & 0xFFFF, (rm_val >> 16) & 0xFFFF);
6139 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, rm_val & 0xFFFF);
6140 }
6141 // UQSUB16
6142 else if (op2 == 0x03) {
6143 lo_val = ARMul_UnsignedSaturatedSub16(rn_val & 0xFFFF, rm_val & 0xFFFF);
6144 hi_val = ARMul_UnsignedSaturatedSub16((rn_val >> 16) & 0xFFFF, (rm_val >> 16) & 0xFFFF);
6145 }
6146 // UQADD8
6147 else if (op2 == 0x04) {
6148 lo_val = ARMul_UnsignedSaturatedAdd8(rn_val, rm_val) |
6149 ARMul_UnsignedSaturatedAdd8(rn_val >> 8, rm_val >> 8) << 8;
6150 hi_val = ARMul_UnsignedSaturatedAdd8(rn_val >> 16, rm_val >> 16) |
6151 ARMul_UnsignedSaturatedAdd8(rn_val >> 24, rm_val >> 24) << 8;
6152 }
6153 // UQSUB8
6154 else {
6155 lo_val = ARMul_UnsignedSaturatedSub8(rn_val, rm_val) |
6156 ARMul_UnsignedSaturatedSub8(rn_val >> 8, rm_val >> 8) << 8;
6157 hi_val = ARMul_UnsignedSaturatedSub8(rn_val >> 16, rm_val >> 16) |
6158 ARMul_UnsignedSaturatedSub8(rn_val >> 24, rm_val >> 24) << 8;
6159 }
5940 6160
5941 LoadWord (state, instr, lhs); 6161 state->Reg[rd_idx] = ((lo_val & 0xFFFF) | hi_val << 16);
5942 return 1; 6162 return 1;
5943 } 6163 }
5944 break; 6164 break;
5945 } 6165 case 0x67: // UHADD16, UHASX, UHSAX, UHSUB16, UHADD8, and UHSUB8.
6166 {
6167 const u8 op2 = BITS(5, 7);
5946 6168
5947 case 0x1c: { /* BIC reg */ 6169 const u8 rm_idx = BITS(0, 3);
5948 /* dyf add for STREXB */ 6170 const u8 rn_idx = BITS(16, 19);
5949 if (BITS (4, 7) == 0x9) { 6171 const u8 rd_idx = BITS(12, 15);
5950 lhs = LHS;
5951 6172
5952 bool enter = false; 6173 const u32 rm_val = state->Reg[rm_idx];
6174 const u32 rn_val = state->Reg[rn_idx];
5953 6175
5954 if (state->currentexval == (u32)ARMul_ReadByte(state, state->currentexaddr))enter = true; 6176 if (op2 == 0x00 || op2 == 0x01 || op2 == 0x02 || op2 == 0x03)
6177 {
6178 u32 lo_val = 0;
6179 u32 hi_val = 0;
5955 6180
5956 ARMul_StoreByte (state, lhs, RHS); 6181 // UHADD16
5957 BUSUSEDINCPCN; 6182 if (op2 == 0x00) {
5958 if (state->Aborted) { 6183 lo_val = (rn_val & 0xFFFF) + (rm_val & 0xFFFF);
5959 TAKEABORT; 6184 hi_val = ((rn_val >> 16) & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
5960 } 6185 }
6186 // UHASX
6187 else if (op2 == 0x01) {
6188 lo_val = (rn_val & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
6189 hi_val = ((rn_val >> 16) & 0xFFFF) + (rm_val & 0xFFFF);
6190 }
6191 // UHSAX
6192 else if (op2 == 0x02) {
6193 lo_val = (rn_val & 0xFFFF) + ((rm_val >> 16) & 0xFFFF);
6194 hi_val = ((rn_val >> 16) & 0xFFFF) - (rm_val & 0xFFFF);
6195 }
6196 // UHSUB16
6197 else if (op2 == 0x03) {
6198 lo_val = (rn_val & 0xFFFF) - (rm_val & 0xFFFF);
6199 hi_val = ((rn_val >> 16) & 0xFFFF) - ((rm_val >> 16) & 0xFFFF);
6200 }
5961 6201
6202 lo_val >>= 1;
6203 hi_val >>= 1;
5962 6204
5963 if (enter) { 6205 state->Reg[rd_idx] = (lo_val & 0xFFFF) | ((hi_val & 0xFFFF) << 16);
5964 state->Reg[DESTReg] = 0; 6206 return 1;
5965 } else { 6207 }
5966 state->Reg[DESTReg] = 1; 6208 else if (op2 == 0x04 || op2 == 0x07) {
6209 u32 sum1;
6210 u32 sum2;
6211 u32 sum3;
6212 u32 sum4;
6213
6214 // UHADD8
6215 if (op2 == 0x04) {
6216 sum1 = (rn_val & 0xFF) + (rm_val & 0xFF);
6217 sum2 = ((rn_val >> 8) & 0xFF) + ((rm_val >> 8) & 0xFF);
6218 sum3 = ((rn_val >> 16) & 0xFF) + ((rm_val >> 16) & 0xFF);
6219 sum4 = ((rn_val >> 24) & 0xFF) + ((rm_val >> 24) & 0xFF);
6220 }
6221 // UHSUB8
6222 else {
6223 sum1 = (rn_val & 0xFF) - (rm_val & 0xFF);
6224 sum2 = ((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF);
6225 sum3 = ((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF);
6226 sum4 = ((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF);
6227 }
6228
6229 sum1 >>= 1;
6230 sum2 >>= 1;
6231 sum3 >>= 1;
6232 sum4 >>= 1;
6233
6234 state->Reg[rd_idx] = (sum1 & 0xFF) | ((sum2 & 0xFF) << 8) | ((sum3 & 0xFF) << 16) | ((sum4 & 0xFF) << 24);
6235 return 1;
5967 } 6236 }
5968
5969 //printf("In %s, strexb not implemented\n", __FUNCTION__);
5970 UNDEF_LSRBPC;
5971 /* WRITESDEST (dest); */
5972 return 1;
5973 } 6237 }
5974 break; 6238 break;
6239 case 0x68:
6240 {
6241 u32 rd = (instr >> 12) & 0xF;
6242 u32 rn = (instr >> 16) & 0xF;
6243 u32 rm = (instr >> 0) & 0xF;
6244 u32 from = state->Reg[rn];
6245 u32 to = state->Reg[rm];
6246 u32 cpsr = ARMul_GetCPSR(state);
6247 if ((instr & 0xFF0) == 0xFB0) { // SEL
6248 u32 result;
6249 if (cpsr & (1 << 16))
6250 result = from & 0xff;
6251 else
6252 result = to & 0xff;
6253 if (cpsr & (1 << 17))
6254 result |= from & 0x0000ff00;
6255 else
6256 result |= to & 0x0000ff00;
6257 if (cpsr & (1 << 18))
6258 result |= from & 0x00ff0000;
6259 else
6260 result |= to & 0x00ff0000;
6261 if (cpsr & (1 << 19))
6262 result |= from & 0xff000000;
6263 else
6264 result |= to & 0xff000000;
6265 state->Reg[rd] = result;
6266 return 1;
6267 }
5975 } 6268 }
6269 printf("Unhandled v6 insn: pkh/sxtab/selsxtb\n");
6270 break;
6271
6272 case 0x6a: // SSAT, SSAT16, SXTB, and SXTAB
6273 {
6274 const u8 op2 = BITS(5, 7);
6275
6276 // SSAT16
6277 if (op2 == 0x01) {
6278 const u8 rd_idx = BITS(12, 15);
6279 const u8 rn_idx = BITS(0, 3);
6280 const u8 num_bits = BITS(16, 19) + 1;
6281 const s16 min = -(0x8000 >> (16 - num_bits));
6282 const s16 max = (0x7FFF >> (16 - num_bits));
6283 s16 rn_lo = (state->Reg[rn_idx]);
6284 s16 rn_hi = (state->Reg[rn_idx] >> 16);
6285
6286 if (rn_lo > max) {
6287 rn_lo = max;
6288 SETQ;
6289 } else if (rn_lo < min) {
6290 rn_lo = min;
6291 SETQ;
6292 }
6293
6294 if (rn_hi > max) {
6295 rn_hi = max;
6296 SETQ;
6297 } else if (rn_hi < min) {
6298 rn_hi = min;
6299 SETQ;
6300 }
6301
6302 state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16);
6303 return 1;
6304 }
6305 else if (op2 == 0x03) {
6306 const u8 rotation = BITS(10, 11) * 8;
6307 u32 rm = ((state->Reg[BITS(0, 3)] >> rotation) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotation)) & 0xFF) & 0xFF);
6308 if (rm & 0x80)
6309 rm |= 0xffffff00;
6310
6311 // SXTB, otherwise SXTAB
6312 if (BITS(16, 19) == 0xf)
6313 state->Reg[BITS(12, 15)] = rm;
6314 else
6315 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
6316
6317 return 1;
6318 }
6319 else {
6320 printf("Unimplemented op: SSAT");
6321 }
6322 }
6323 break;
6324
6325 case 0x6b: // REV, REV16, SXTH, and SXTAH
6326 {
6327 const u8 op2 = BITS(5, 7);
6328
6329 // REV
6330 if (op2 == 0x01) {
6331 DEST = ((RHS & 0xFF) << 24) | ((RHS & 0xFF00)) << 8 | ((RHS & 0xFF0000) >> 8) | ((RHS & 0xFF000000) >> 24);
6332 return 1;
6333 }
6334 // REV16
6335 else if (op2 == 0x05) {
6336 DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00)) >> 8 | ((RHS & 0xFF0000) << 8) | ((RHS & 0xFF000000) >> 8);
6337 return 1;
6338 }
6339 else if (op2 == 0x03) {
6340 const u8 rotate = BITS(10, 11) * 8;
6341
6342 u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF);
6343 if (rm & 0x8000)
6344 rm |= 0xffff0000;
6345
6346 // SXTH, otherwise SXTAH
6347 if (BITS(16, 19) == 15)
6348 state->Reg[BITS(12, 15)] = rm;
6349 else
6350 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
6351
6352 return 1;
6353 }
6354 }
6355 break;
6356
6357 case 0x6c: // UXTB16 and UXTAB16
6358 {
6359 const u8 rm_idx = BITS(0, 3);
6360 const u8 rn_idx = BITS(16, 19);
6361 const u8 rd_idx = BITS(12, 15);
6362 const u32 rm_val = state->Reg[rm_idx];
6363 const u32 rn_val = state->Reg[rn_idx];
6364 const u32 rotation = BITS(10, 11) * 8;
6365 const u32 rotated_rm = ((rm_val << (32 - rotation)) | (rm_val >> rotation));
6366
6367 // UXTB16
6368 if ((instr & 0xf03f0) == 0xf0070) {
6369 state->Reg[rd_idx] = rotated_rm & 0x00FF00FF;
6370 }
6371 else { // UXTAB16
6372 const u8 lo_rotated = (rotated_rm & 0xFF);
6373 const u16 lo_result = (rn_val & 0xFFFF) + (u16)lo_rotated;
6374
6375 const u8 hi_rotated = (rotated_rm >> 16) & 0xFF;
6376 const u16 hi_result = (rn_val >> 16) + (u16)hi_rotated;
6377
6378 state->Reg[rd_idx] = ((hi_result << 16) | (lo_result & 0xFFFF));
6379 }
6380
6381 return 1;
6382 }
6383 break;
6384 case 0x6e: // USAT, USAT16, UXTB, and UXTAB
6385 {
6386 const u8 op2 = BITS(5, 7);
6387
6388 // USAT16
6389 if (op2 == 0x01) {
6390 const u8 rd_idx = BITS(12, 15);
6391 const u8 rn_idx = BITS(0, 3);
6392 const u8 num_bits = BITS(16, 19);
6393 const s16 max = 0xFFFF >> (16 - num_bits);
6394 s16 rn_lo = (state->Reg[rn_idx]);
6395 s16 rn_hi = (state->Reg[rn_idx] >> 16);
6396
6397 if (max < rn_lo) {
6398 rn_lo = max;
6399 SETQ;
6400 } else if (rn_lo < 0) {
6401 rn_lo = 0;
6402 SETQ;
6403 }
6404
6405 if (max < rn_hi) {
6406 rn_hi = max;
6407 SETQ;
6408 } else if (rn_hi < 0) {
6409 rn_hi = 0;
6410 SETQ;
6411 }
6412
6413 state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF);
6414 return 1;
6415 }
6416 else if (op2 == 0x03) {
6417 const u8 rotate = BITS(10, 11) * 8;
6418 const u32 rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFF) & 0xFF);
6419
6420 if (BITS(16, 19) == 0xf)
6421 /* UXTB */
6422 state->Reg[BITS(12, 15)] = rm;
6423 else
6424 /* UXTAB */
6425 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
6426
6427 return 1;
6428 }
6429 else {
6430 printf("Unimplemented op: USAT");
6431 }
6432 }
6433 break;
6434
6435 case 0x6f: // UXTH, UXTAH, and REVSH.
6436 {
6437 const u8 op2 = BITS(5, 7);
6438
6439 // REVSH
6440 if (op2 == 0x05) {
6441 DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00) >> 8);
6442 if (DEST & 0x8000)
6443 DEST |= 0xffff0000;
6444 return 1;
6445 }
6446 // UXTH and UXTAH
6447 else if (op2 == 0x03) {
6448 const u8 rotate = BITS(10, 11) * 8;
6449 const ARMword rm = ((state->Reg[BITS(0, 3)] >> rotate) & 0xFFFF) | (((state->Reg[BITS(0, 3)] << (32 - rotate)) & 0xFFFF) & 0xFFFF);
6450
6451 // UXTH
6452 if (BITS(16, 19) == 0xf) {
6453 state->Reg[BITS(12, 15)] = rm;
6454 }
6455 // UXTAH
6456 else {
6457 state->Reg[BITS(12, 15)] = state->Reg[BITS(16, 19)] + rm;
6458 }
6459
6460 return 1;
6461 }
6462 }
6463 case 0x70:
6464 // ichfly
6465 // SMUAD, SMUSD, SMLAD, and SMLSD
6466 if ((instr & 0xf0d0) == 0xf010 || (instr & 0xf0d0) == 0xf050 ||
6467 (instr & 0xd0) == 0x10 || (instr & 0xd0) == 0x50)
6468 {
6469 const u8 rd_idx = BITS(16, 19);
6470 const u8 rn_idx = BITS(0, 3);
6471 const u8 rm_idx = BITS(8, 11);
6472 const u8 ra_idx = BITS(12, 15);
6473 const bool do_swap = (BIT(5) == 1);
5976 6474
5977 case 0x1d: { /* BICS reg */ 6475 u32 rm_val = state->Reg[rm_idx];
5978 if ((BITS (4, 7)) == 0x9) { 6476 const u32 rn_val = state->Reg[rn_idx];
5979 /* ldrexb */
5980 temp = LHS;
5981 LoadByte (state, instr, temp, LUNSIGNED);
5982 6477
5983 state->currentexaddr = temp; 6478 if (do_swap)
5984 state->currentexval = (u32)ARMul_ReadByte(state, temp); 6479 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
5985 6480
5986 //state->Reg[BITS(12, 15)] = ARMul_LoadByte(state, state->Reg[BITS(16, 19)]); 6481 const s16 rm_lo = (rm_val & 0xFFFF);
5987 //printf("ldrexb\n"); 6482 const s16 rm_hi = ((rm_val >> 16) & 0xFFFF);
5988 //printf("instr is %x rm is %d\n", instr, BITS(16, 19)); 6483 const s16 rn_lo = (rn_val & 0xFFFF);
5989 //exit(-1); 6484 const s16 rn_hi = ((rn_val >> 16) & 0xFFFF);
5990 6485
5991 //printf("In %s, ldrexb not implemented\n", __FUNCTION__); 6486 const u32 product1 = (rn_lo * rm_lo);
5992 return 1; 6487 const u32 product2 = (rn_hi * rm_hi);
5993 }
5994 break;
5995 }
5996 /* add end */
5997 6488
5998 case 0x6a: { 6489 // SMUAD and SMLAD
5999 ARMword Rm; 6490 if (BIT(6) == 0) {
6000 int ror = -1; 6491 state->Reg[rd_idx] = product1 + product2;
6001 6492
6002 switch (BITS (4, 11)) { 6493 if (BITS(12, 15) != 15) {
6003 case 0x07: 6494 state->Reg[rd_idx] += state->Reg[ra_idx];
6004 ror = 0; 6495 ARMul_AddOverflowQ(state, product1 + product2, state->Reg[ra_idx]);
6005 break; 6496 }
6006 case 0x47:
6007 ror = 8;
6008 break;
6009 case 0x87:
6010 ror = 16;
6011 break;
6012 case 0xc7:
6013 ror = 24;
6014 break;
6015 6497
6016 case 0x01: 6498 ARMul_AddOverflowQ(state, product1, product2);
6017 case 0xf3: 6499 }
6018 //ichfly 6500 // SMUSD and SMLSD
6019 //SSAT16 6501 else {
6020 { 6502 state->Reg[rd_idx] = product1 - product2;
6021 u8 tar = BITS(12,15); 6503
6022 u8 src = BITS(0, 3); 6504 if (BITS(12, 15) != 15)
6023 u8 val = BITS(16, 19) + 1; 6505 state->Reg[rd_idx] += state->Reg[ra_idx];
6024 s16 a1 = (state->Reg[src]); 6506 }
6025 s16 a2 = (state->Reg[src] >> 0x10);
6026 s16 min = (s16)(0x8000) >> (16 - val);
6027 s16 max = 0x7FFF >> (16 - val);
6028 if (min > a1) a1 = min;
6029 if (max < a1) a1 = max;
6030 if (min > a2) a2 = min;
6031 if (max < a2) a2 = max;
6032 u32 temp2 = ((u32)(a2)) << 0x10;
6033 state->Reg[tar] = (a1&0xFFFF) | (temp2);
6034 }
6035 6507
6036 return 1; 6508 return 1;
6037 default:
6038 break;
6039 } 6509 }
6040 6510 break;
6041 if (ror == -1) { 6511 case 0x74: // SMLALD and SMLSLD
6042 if (BITS (4, 6) == 0x7) { 6512 {
6043 printf ("Unhandled v6 insn: ssat\n"); 6513 const u8 rm_idx = BITS(8, 11);
6044 return 0; 6514 const u8 rn_idx = BITS(0, 3);
6515 const u8 rdlo_idx = BITS(12, 15);
6516 const u8 rdhi_idx = BITS(16, 19);
6517 const bool do_swap = (BIT(5) == 1);
6518
6519 const u32 rdlo_val = state->Reg[rdlo_idx];
6520 const u32 rdhi_val = state->Reg[rdhi_idx];
6521 const u32 rn_val = state->Reg[rn_idx];
6522 u32 rm_val = state->Reg[rm_idx];
6523
6524 if (do_swap)
6525 rm_val = (((rm_val & 0xFFFF) << 16) | (rm_val >> 16));
6526
6527 const s32 product1 = (s16)(rn_val & 0xFFFF) * (s16)(rm_val & 0xFFFF);
6528 const s32 product2 = (s16)((rn_val >> 16) & 0xFFFF) * (s16)((rm_val >> 16) & 0xFFFF);
6529 s64 result;
6530
6531 // SMLALD
6532 if (BIT(6) == 0) {
6533 result = (product1 + product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
6534 }
6535 // SMLSLD
6536 else {
6537 result = (product1 - product2) + (s64)(rdlo_val | ((s64)rdhi_val << 32));
6045 } 6538 }
6046 break;
6047 }
6048
6049 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF);
6050 if (Rm & 0x80)
6051 Rm |= 0xffffff00;
6052
6053 if (BITS (16, 19) == 0xf)
6054 /* SXTB */
6055 state->Reg[BITS (12, 15)] = Rm;
6056 else
6057 /* SXTAB */
6058 state->Reg[BITS (12, 15)] += Rm;
6059 }
6060 return 1;
6061
6062 case 0x6b: {
6063 ARMword Rm;
6064 int ror = -1;
6065
6066 switch (BITS (4, 11)) {
6067 case 0x07:
6068 ror = 0;
6069 break;
6070 case 0x47:
6071 ror = 8;
6072 break;
6073 case 0x87:
6074 ror = 16;
6075 break;
6076 case 0xc7:
6077 ror = 24;
6078 break;
6079 6539
6080 case 0xf3: 6540 state->Reg[rdlo_idx] = (result & 0xFFFFFFFF);
6081 DEST = ((RHS & 0xFF) << 24) | ((RHS & 0xFF00)) << 8 | ((RHS & 0xFF0000) >> 8) | ((RHS & 0xFF000000) >> 24); 6541 state->Reg[rdhi_idx] = ((result >> 32) & 0xFFFFFFFF);
6082 return 1; 6542 return 1;
6083 case 0xfb:
6084 DEST = ((RHS & 0xFF) << 8) | ((RHS & 0xFF00)) >> 8 | ((RHS & 0xFF0000) << 8) | ((RHS & 0xFF000000) >> 8);
6085 return 1;
6086 default:
6087 break;
6088 } 6543 }
6544 break;
6545 case 0x75: // SMMLA, SMMUL, and SMMLS
6546 {
6547 const u8 rm_idx = BITS(8, 11);
6548 const u8 rn_idx = BITS(0, 3);
6549 const u8 ra_idx = BITS(12, 15);
6550 const u8 rd_idx = BITS(16, 19);
6551 const bool do_round = (BIT(5) == 1);
6089 6552
6090 if (ror == -1) 6553 const u32 rm_val = state->Reg[rm_idx];
6091 break; 6554 const u32 rn_val = state->Reg[rn_idx];
6092 6555
6093 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF); 6556 // Assume SMMUL by default.
6094 if (Rm & 0x8000) 6557 s64 result = (s64)(s32)rn_val * (s64)(s32)rm_val;
6095 Rm |= 0xffff0000;
6096 6558
6097 if (BITS (16, 19) == 0xf) 6559 if (ra_idx != 15) {
6098 /* SXTH */ 6560 const u32 ra_val = state->Reg[ra_idx];
6099 state->Reg[BITS (12, 15)] = Rm;
6100 else
6101 /* SXTAH */
6102 state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm;
6103 }
6104 return 1;
6105 6561
6106 case 0x6e: { 6562 // SMMLA, otherwise SMMLS
6107 ARMword Rm; 6563 if (BIT(6) == 0)
6108 int ror = -1; 6564 result += ((s64)ra_val << 32);
6565 else
6566 result = ((s64)ra_val << 32) - result;
6567 }
6109 6568
6110 switch (BITS (4, 11)) { 6569 if (do_round)
6111 case 0x07: 6570 result += 0x80000000;
6112 ror = 0;
6113 break;
6114 case 0x47:
6115 ror = 8;
6116 break;
6117 case 0x87:
6118 ror = 16;
6119 break;
6120 case 0xc7:
6121 ror = 24;
6122 break;
6123 6571
6124 case 0x01: 6572 state->Reg[rd_idx] = ((result >> 32) & 0xFFFFFFFF);
6125 case 0xf3:
6126 //ichfly
6127 //USAT16
6128 {
6129 u8 tar = BITS(12, 15);
6130 u8 src = BITS(0, 3);
6131 u8 val = BITS(16, 19);
6132 s16 a1 = (state->Reg[src]);
6133 s16 a2 = (state->Reg[src] >> 0x10);
6134 s16 max = 0xFFFF >> (16 - val);
6135 if (max < a1) a1 = max;
6136 if (max < a2) a2 = max;
6137 u32 temp2 = ((u32)(a2)) << 0x10;
6138 state->Reg[tar] = (a1 & 0xFFFF) | (temp2);
6139 }
6140 return 1; 6573 return 1;
6141 default:
6142 break;
6143 }
6144
6145 if (ror == -1) {
6146 if (BITS (4, 6) == 0x7) {
6147 printf ("Unhandled v6 insn: usat\n");
6148 return 0;
6149 }
6150 break;
6151 } 6574 }
6575 break;
6576 case 0x78:
6577 if (BITS(20, 24) == 0x18)
6578 {
6579 const u8 rm_idx = BITS(8, 11);
6580 const u8 rn_idx = BITS(0, 3);
6581 const u8 rd_idx = BITS(16, 19);
6152 6582
6153 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF); 6583 const u32 rm_val = state->Reg[rm_idx];
6154 6584 const u32 rn_val = state->Reg[rn_idx];
6155 if (BITS (16, 19) == 0xf)
6156 /* UXTB */
6157 state->Reg[BITS (12, 15)] = Rm;
6158 else
6159 /* UXTAB */
6160 state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm;
6161 }
6162 return 1;
6163 6585
6164 case 0x6f: { 6586 const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF);
6165 ARMword Rm; 6587 const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF);
6166 int ror = -1; 6588 const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF);
6589 const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF);
6167 6590
6168 switch (BITS (4, 11)) { 6591 u32 finalDif = (diff1 + diff2 + diff3 + diff4);
6169 case 0x07:
6170 ror = 0;
6171 break;
6172 case 0x47:
6173 ror = 8;
6174 break;
6175 case 0x87:
6176 ror = 16;
6177 break;
6178 case 0xc7:
6179 ror = 24;
6180 break;
6181 6592
6182 case 0xfb: 6593 // Op is USADA8 if true.
6183 printf ("Unhandled v6 insn: revsh\n"); 6594 const u8 ra_idx = BITS(12, 15);
6184 return 0; 6595 if (ra_idx != 15)
6185 default: 6596 finalDif += state->Reg[ra_idx];
6186 break;
6187 }
6188 6597
6189 if (ror == -1) 6598 state->Reg[rd_idx] = finalDif;
6190 break; 6599 return 1;
6191
6192 Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF);
6193
6194 /* UXT */
6195 /* state->Reg[BITS (12, 15)] = Rm; */
6196 /* dyf add */
6197 if (BITS (16, 19) == 0xf) {
6198 state->Reg[BITS (12, 15)] = (Rm >> (8 * BITS(10, 11))) & 0x0000FFFF;
6199 } else {
6200 /* UXTAH */
6201 /* state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm; */
6202// printf("rd is %x rn is %x rm is %x rotate is %x\n", state->Reg[BITS (12, 15)], state->Reg[BITS (16, 19)]
6203// , Rm, BITS(10, 11));
6204// printf("icounter is %lld\n", state->NumInstrs);
6205 state->Reg[BITS (12, 15)] = (state->Reg[BITS (16, 19)] >> (8 * (BITS(10, 11)))) + Rm;
6206// printf("rd is %x\n", state->Reg[BITS (12, 15)]);
6207// exit(-1);
6208 } 6600 }
6209 } 6601 break;
6210 return 1; 6602 case 0x7a:
6211 6603 printf ("Unhandled v6 insn: usbfx\n");
6212#if 0 6604 break;
6605 case 0x7c:
6606 printf ("Unhandled v6 insn: bfc/bfi\n");
6607 break;
6213 case 0x84: 6608 case 0x84:
6214 printf ("Unhandled v6 insn: srs\n"); 6609 printf ("Unhandled v6 insn: srs\n");
6215 break; 6610 break;
6216#endif
6217 default: 6611 default:
6218 break; 6612 break;
6219 } 6613 }
6220 printf("Unhandled v6 insn: UNKNOWN: %08x %08X\n", instr, BITS(20, 27)); 6614 printf("Unhandled v6 insn: UNKNOWN: %08x %08X\n", instr, BITS(20, 27));
6221 return 0; 6615 return 0;
6222 } 6616 } \ No newline at end of file
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index 30519f216..8b3661c8f 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -227,8 +227,9 @@ ARMul_CPSRAltered (ARMul_State * state)
227 //state->Cpsr &= ~CBIT; 227 //state->Cpsr &= ~CBIT;
228 ASSIGNV ((state->Cpsr & VBIT) != 0); 228 ASSIGNV ((state->Cpsr & VBIT) != 0);
229 //state->Cpsr &= ~VBIT; 229 //state->Cpsr &= ~VBIT;
230 ASSIGNS ((state->Cpsr & SBIT) != 0); 230 ASSIGNQ ((state->Cpsr & QBIT) != 0);
231 //state->Cpsr &= ~SBIT; 231 //state->Cpsr &= ~QBIT;
232 state->GEFlag = (state->Cpsr & 0x000F0000);
232#ifdef MODET 233#ifdef MODET
233 ASSIGNT ((state->Cpsr & TBIT) != 0); 234 ASSIGNT ((state->Cpsr & TBIT) != 0);
234 //state->Cpsr &= ~TBIT; 235 //state->Cpsr &= ~TBIT;
@@ -391,6 +392,15 @@ ARMul_NthReg (ARMword instr, unsigned number)
391 return (bit - 1); 392 return (bit - 1);
392} 393}
393 394
395/* Unsigned sum of absolute difference */
396u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
397{
398 if (left > right)
399 return left - right;
400
401 return right - left;
402}
403
394/* Assigns the N and Z flags depending on the value of result. */ 404/* Assigns the N and Z flags depending on the value of result. */
395 405
396void 406void
@@ -443,6 +453,14 @@ ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
443 ASSIGNV (AddOverflow (a, b, result)); 453 ASSIGNV (AddOverflow (a, b, result));
444} 454}
445 455
456/* Assigns the Q flag if the given result is considered an overflow from the addition of a and b */
457void ARMul_AddOverflowQ(ARMul_State* state, ARMword a, ARMword b)
458{
459 u32 result = a + b;
460 if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0)
461 SETQ;
462}
463
446/* Assigns the C flag after an subtraction of a and b to give result. */ 464/* Assigns the C flag after an subtraction of a and b to give result. */
447 465
448void 466void
@@ -460,6 +478,107 @@ ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
460 ASSIGNV (SubOverflow (a, b, result)); 478 ASSIGNV (SubOverflow (a, b, result));
461} 479}
462 480
481/* 8-bit signed saturated addition */
482u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right)
483{
484 u8 result = left + right;
485
486 if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) {
487 if (left & 0x80)
488 result = 0x80;
489 else
490 result = 0x7F;
491 }
492
493 return result;
494}
495
496/* 8-bit signed saturated subtraction */
497u8 ARMul_SignedSaturatedSub8(u8 left, u8 right)
498{
499 u8 result = left - right;
500
501 if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) {
502 if (left & 0x80)
503 result = 0x80;
504 else
505 result = 0x7F;
506 }
507
508 return result;
509}
510
511/* 16-bit signed saturated addition */
512u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right)
513{
514 u16 result = left + right;
515
516 if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) {
517 if (left & 0x8000)
518 result = 0x8000;
519 else
520 result = 0x7FFF;
521 }
522
523 return result;
524}
525
526/* 16-bit signed saturated subtraction */
527u16 ARMul_SignedSaturatedSub16(u16 left, u16 right)
528{
529 u16 result = left - right;
530
531 if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) {
532 if (left & 0x8000)
533 result = 0x8000;
534 else
535 result = 0x7FFF;
536 }
537
538 return result;
539}
540
541/* 8-bit unsigned saturated addition */
542u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right)
543{
544 u8 result = left + right;
545
546 if (result < left)
547 result = 0xFF;
548
549 return result;
550}
551
552/* 16-bit unsigned saturated addition */
553u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right)
554{
555 u16 result = left + right;
556
557 if (result < left)
558 result = 0xFFFF;
559
560 return result;
561}
562
563/* 8-bit unsigned saturated subtraction */
564u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right)
565{
566 if (left <= right)
567 return 0;
568
569 return left - right;
570}
571
572/* 16-bit unsigned saturated subtraction */
573u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right)
574{
575 if (left <= right)
576 return 0;
577
578 return left - right;
579}
580
581
463/* This function does the work of generating the addresses used in an 582/* This function does the work of generating the addresses used in an
464 LDC instruction. The code here is always post-indexed, it's up to the 583 LDC instruction. The code here is always post-indexed, it's up to the
465 caller to get the input address correct and to handle base register 584 caller to get the input address correct and to handle base register
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h
index 8343aaa01..0f2bcbdb1 100644
--- a/src/core/arm/skyeye_common/armdefs.h
+++ b/src/core/arm/skyeye_common/armdefs.h
@@ -18,38 +18,26 @@
18#ifndef _ARMDEFS_H_ 18#ifndef _ARMDEFS_H_
19#define _ARMDEFS_H_ 19#define _ARMDEFS_H_
20 20
21#include <stdio.h> 21#include <cerrno>
22#include <stdlib.h> 22#include <csignal>
23#include <errno.h> 23#include <cstdio>
24 24#include <cstdlib>
25#include "common/platform.h" 25#include <cstring>
26 26#include <fcntl.h>
27//teawater add for arm2x86 2005.02.14------------------------------------------- 27#include <sys/stat.h>
28// koodailar remove it for mingw 2005.12.18---------------- 28#include <sys/types.h>
29//anthonylee modify it for portable 2007.01.30
30//#include "portable/mman.h"
31 29
32#include "arm_regformat.h" 30#include "arm_regformat.h"
31#include "common/common_types.h"
33#include "common/platform.h" 32#include "common/platform.h"
33#include "core/arm/skyeye_common/armmmu.h"
34#include "core/arm/skyeye_common/skyeye_defs.h" 34#include "core/arm/skyeye_common/skyeye_defs.h"
35 35
36//AJ2D--------------------------------------------------------------------------
37
38//teawater add for arm2x86 2005.07.03-------------------------------------------
39
40#include <sys/types.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#if EMU_PLATFORM == PLATFORM_LINUX 36#if EMU_PLATFORM == PLATFORM_LINUX
37#include <sys/time.h>
45#include <unistd.h> 38#include <unistd.h>
46#endif 39#endif
47#include <errno.h>
48#include <sys/stat.h>
49#include <fcntl.h>
50 40
51//#include <memory_space.h>
52//AJ2D--------------------------------------------------------------------------
53#if 0 41#if 0
54#if 0 42#if 0
55#define DIFF_STATE 1 43#define DIFF_STATE 1
@@ -70,25 +58,8 @@
70#define LOWHIGH 1 58#define LOWHIGH 1
71#define HIGHLOW 2 59#define HIGHLOW 2
72 60
73//teawater add DBCT_TEST_SPEED 2005.10.04---------------------------------------
74#include <signal.h>
75
76#include "common/platform.h"
77
78#if EMU_PLATFORM == PLATFORM_LINUX
79#include <sys/time.h>
80#endif
81
82//#define DBCT_TEST_SPEED 61//#define DBCT_TEST_SPEED
83#define DBCT_TEST_SPEED_SEC 10 62#define DBCT_TEST_SPEED_SEC 10
84//AJ2D--------------------------------------------------------------------------
85
86//teawater add compile switch for DBCT GDB RSP function 2005.10.21--------------
87//#define DBCT_GDBRSP
88//AJ2D--------------------------------------------------------------------------
89
90//#include <skyeye_defs.h>
91//#include <skyeye_types.h>
92 63
93#define ARM_BYTE_TYPE 0 64#define ARM_BYTE_TYPE 0
94#define ARM_HALFWORD_TYPE 1 65#define ARM_HALFWORD_TYPE 1
@@ -103,71 +74,34 @@
103typedef char *VoidStar; 74typedef char *VoidStar;
104#endif 75#endif
105 76
106typedef unsigned long long ARMdword; /* must be 64 bits wide */ 77typedef u64 ARMdword; // must be 64 bits wide
107typedef unsigned int ARMword; /* must be 32 bits wide */ 78typedef u32 ARMword; // must be 32 bits wide
108typedef unsigned char ARMbyte; /* must be 8 bits wide */ 79typedef u16 ARMhword; // must be 16 bits wide
109typedef unsigned short ARMhword; /* must be 16 bits wide */ 80typedef u8 ARMbyte; // must be 8 bits wide
110typedef struct ARMul_State ARMul_State; 81typedef struct ARMul_State ARMul_State;
111typedef struct ARMul_io ARMul_io; 82typedef struct ARMul_io ARMul_io;
112typedef struct ARMul_Energy ARMul_Energy; 83typedef struct ARMul_Energy ARMul_Energy;
113 84
114//teawater add for arm2x86 2005.06.24-------------------------------------------
115#include <stdint.h>
116//AJ2D--------------------------------------------------------------------------
117/*
118//chy 2005-05-11
119#ifndef __CYGWIN__
120//teawater add for arm2x86 2005.02.14-------------------------------------------
121typedef unsigned char uint8_t;
122typedef unsigned short uint16_t;
123typedef unsigned int u32;
124#if defined (__x86_64__)
125typedef unsigned long uint64_t;
126#else
127typedef unsigned long long uint64_t;
128#endif
129////AJ2D--------------------------------------------------------------------------
130#endif
131*/
132 85
133#include "core/arm/skyeye_common/armmmu.h" 86typedef unsigned ARMul_CPInits(ARMul_State* state);
134//#include "lcd/skyeye_lcd.h" 87typedef unsigned ARMul_CPExits(ARMul_State* state);
135 88typedef unsigned ARMul_LDCs(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
136 89typedef unsigned ARMul_STCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
137//#include "skyeye.h" 90typedef unsigned ARMul_MRCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value);
138//#include "skyeye_device.h" 91typedef unsigned ARMul_MCRs(ARMul_State* state, unsigned type, ARMword instr, ARMword value);
139//#include "net/skyeye_net.h" 92typedef unsigned ARMul_MRRCs(ARMul_State* state, unsigned type, ARMword instr, ARMword* value1, ARMword* value2);
140//#include "skyeye_config.h" 93typedef unsigned ARMul_MCRRs(ARMul_State* state, unsigned type, ARMword instr, ARMword value1, ARMword value2);
141 94typedef unsigned ARMul_CDPs(ARMul_State* state, unsigned type, ARMword instr);
142 95typedef unsigned ARMul_CPReads(ARMul_State* state, unsigned reg, ARMword* value);
143typedef unsigned ARMul_CPInits (ARMul_State * state); 96typedef unsigned ARMul_CPWrites(ARMul_State* state, unsigned reg, ARMword value);
144typedef unsigned ARMul_CPExits (ARMul_State * state);
145typedef unsigned ARMul_LDCs (ARMul_State * state, unsigned type,
146 ARMword instr, ARMword value);
147typedef unsigned ARMul_STCs (ARMul_State * state, unsigned type,
148 ARMword instr, ARMword * value);
149typedef unsigned ARMul_MRCs (ARMul_State * state, unsigned type,
150 ARMword instr, ARMword * value);
151typedef unsigned ARMul_MCRs (ARMul_State * state, unsigned type,
152 ARMword instr, ARMword value);
153typedef unsigned ARMul_MRRCs (ARMul_State * state, unsigned type,
154 ARMword instr, ARMword * value1, ARMword * value2);
155typedef unsigned ARMul_MCRRs (ARMul_State * state, unsigned type,
156 ARMword instr, ARMword value1, ARMword value2);
157typedef unsigned ARMul_CDPs (ARMul_State * state, unsigned type,
158 ARMword instr);
159typedef unsigned ARMul_CPReads (ARMul_State * state, unsigned reg,
160 ARMword * value);
161typedef unsigned ARMul_CPWrites (ARMul_State * state, unsigned reg,
162 ARMword value);
163 97
164 98
165//added by ksh,2004-3-5 99//added by ksh,2004-3-5
166struct ARMul_io 100struct ARMul_io
167{ 101{
168 ARMword *instr; //to display the current interrupt state 102 ARMword *instr; // to display the current interrupt state
169 ARMword *net_flag; //to judge if network is enabled 103 ARMword *net_flag; // to judge if network is enabled
170 ARMword *net_int; //netcard interrupt 104 ARMword *net_int; // netcard interrupt
171 105
172 //ywc,2004-04-01 106 //ywc,2004-04-01
173 ARMword *ts_int; 107 ARMword *ts_int;
@@ -180,17 +114,17 @@ struct ARMul_io
180/* added by ksh,2004-11-26,some energy profiling */ 114/* added by ksh,2004-11-26,some energy profiling */
181struct ARMul_Energy 115struct ARMul_Energy
182{ 116{
183 int energy_prof; /* <tktan> BUG200103282109 : for energy profiling */ 117 int energy_prof; /* <tktan> BUG200103282109 : for energy profiling */
184 int enable_func_energy; /* <tktan> BUG200105181702 */ 118 int enable_func_energy; /* <tktan> BUG200105181702 */
185 char *func_energy; 119 char *func_energy;
186 int func_display; /* <tktan> BUG200103311509 : for function call display */ 120 int func_display; /* <tktan> BUG200103311509 : for function call display */
187 int func_disp_start; /* <tktan> BUG200104191428 : to start func profiling */ 121 int func_disp_start; /* <tktan> BUG200104191428 : to start func profiling */
188 char *start_func; /* <tktan> BUG200104191428 */ 122 char *start_func; /* <tktan> BUG200104191428 */
189 123
190 FILE *outfile; /* <tktan> BUG200105201531 : direct console to file */ 124 FILE *outfile; /* <tktan> BUG200105201531 : direct console to file */
191 long long tcycle, pcycle; 125 long long tcycle, pcycle;
192 float t_energy; 126 float t_energy;
193 void *cur_task; /* <tktan> BUG200103291737 */ 127 void *cur_task; /* <tktan> BUG200103291737 */
194 long long t_mem_cycle, t_idle_cycle, t_uart_cycle; 128 long long t_mem_cycle, t_idle_cycle, t_uart_cycle;
195 long long p_mem_cycle, p_idle_cycle, p_uart_cycle; 129 long long p_mem_cycle, p_idle_cycle, p_uart_cycle;
196 long long p_io_update_tcycle; 130 long long p_io_update_tcycle;
@@ -203,13 +137,12 @@ struct ARMul_Energy
203 137
204typedef struct mem_bank 138typedef struct mem_bank
205{ 139{
206 ARMword (*read_byte) (ARMul_State * state, ARMword addr); 140 ARMword (*read_byte) (ARMul_State* state, ARMword addr);
207 void (*write_byte) (ARMul_State * state, ARMword addr, ARMword data); 141 void (*write_byte) (ARMul_State* state, ARMword addr, ARMword data);
208 ARMword (*read_halfword) (ARMul_State * state, ARMword addr); 142 ARMword (*read_halfword) (ARMul_State* state, ARMword addr);
209 void (*write_halfword) (ARMul_State * state, ARMword addr, 143 void (*write_halfword) (ARMul_State* state, ARMword addr, ARMword data);
210 ARMword data); 144 ARMword (*read_word) (ARMul_State* state, ARMword addr);
211 ARMword (*read_word) (ARMul_State * state, ARMword addr); 145 void (*write_word) (ARMul_State* state, ARMword addr, ARMword data);
212 void (*write_word) (ARMul_State * state, ARMword addr, ARMword data);
213 unsigned int addr, len; 146 unsigned int addr, len;
214 char filename[MAX_STR]; 147 char filename[MAX_STR];
215 unsigned type; //chy 2003-09-21: maybe io,ram,rom 148 unsigned type; //chy 2003-09-21: maybe io,ram,rom
@@ -224,24 +157,24 @@ typedef struct
224#define VFP_REG_NUM 64 157#define VFP_REG_NUM 64
225struct ARMul_State 158struct ARMul_State
226{ 159{
227 ARMword Emulate; /* to start and stop emulation */ 160 ARMword Emulate; /* to start and stop emulation */
228 unsigned EndCondition; /* reason for stopping */ 161 unsigned EndCondition; /* reason for stopping */
229 unsigned ErrorCode; /* type of illegal instruction */ 162 unsigned ErrorCode; /* type of illegal instruction */
230 163
231 /* Order of the following register should not be modified */ 164 /* Order of the following register should not be modified */
232 ARMword Reg[16]; /* the current register file */ 165 ARMword Reg[16]; /* the current register file */
233 ARMword Cpsr; /* the current psr */ 166 ARMword Cpsr; /* the current psr */
234 ARMword Spsr_copy; 167 ARMword Spsr_copy;
235 ARMword phys_pc; 168 ARMword phys_pc;
236 ARMword Reg_usr[2]; 169 ARMword Reg_usr[2];
237 ARMword Reg_svc[2]; /* R13_SVC R14_SVC */ 170 ARMword Reg_svc[2]; /* R13_SVC R14_SVC */
238 ARMword Reg_abort[2]; /* R13_ABORT R14_ABORT */ 171 ARMword Reg_abort[2]; /* R13_ABORT R14_ABORT */
239 ARMword Reg_undef[2]; /* R13 UNDEF R14 UNDEF */ 172 ARMword Reg_undef[2]; /* R13 UNDEF R14 UNDEF */
240 ARMword Reg_irq[2]; /* R13_IRQ R14_IRQ */ 173 ARMword Reg_irq[2]; /* R13_IRQ R14_IRQ */
241 ARMword Reg_firq[7]; /* R8---R14 FIRQ */ 174 ARMword Reg_firq[7]; /* R8---R14 FIRQ */
242 ARMword Spsr[7]; /* the exception psr's */ 175 ARMword Spsr[7]; /* the exception psr's */
243 ARMword Mode; /* the current mode */ 176 ARMword Mode; /* the current mode */
244 ARMword Bank; /* the current register bank */ 177 ARMword Bank; /* the current register bank */
245 ARMword exclusive_tag; 178 ARMword exclusive_tag;
246 ARMword exclusive_state; 179 ARMword exclusive_state;
247 ARMword exclusive_result; 180 ARMword exclusive_result;
@@ -265,7 +198,7 @@ struct ARMul_State
265 //ARMword translate_pc; 198 //ARMword translate_pc;
266 199
267 /* add armv6 flags dyf:2010-08-09 */ 200 /* add armv6 flags dyf:2010-08-09 */
268 ARMword GEFlag, EFlag, AFlag, QFlags; 201 ARMword GEFlag, EFlag, AFlag, QFlag;
269 //chy:2003-08-19, used in arm v5e|xscale 202 //chy:2003-08-19, used in arm v5e|xscale
270 ARMword SFlag; 203 ARMword SFlag;
271#ifdef MODET 204#ifdef MODET
@@ -281,38 +214,39 @@ struct ARMul_State
281 214
282 ARMword currentexaddr; 215 ARMword currentexaddr;
283 ARMword currentexval; 216 ARMword currentexval;
217 ARMword currentexvald;
284 ARMword servaddr; 218 ARMword servaddr;
285 219
286 unsigned NextInstr; 220 unsigned NextInstr;
287 unsigned VectorCatch; /* caught exception mask */ 221 unsigned VectorCatch; /* caught exception mask */
288 unsigned CallDebug; /* set to call the debugger */ 222 unsigned CallDebug; /* set to call the debugger */
289 unsigned CanWatch; /* set by memory interface if its willing to suffer the 223 unsigned CanWatch; /* set by memory interface if its willing to suffer the
290 overhead of checking for watchpoints on each memory 224 overhead of checking for watchpoints on each memory
291 access */ 225 access */
292 unsigned int StopHandle; 226 unsigned int StopHandle;
293 227
294 char *CommandLine; /* Command Line from ARMsd */ 228 char *CommandLine; /* Command Line from ARMsd */
295 229
296 ARMul_CPInits *CPInit[16]; /* coprocessor initialisers */ 230 ARMul_CPInits *CPInit[16]; /* coprocessor initialisers */
297 ARMul_CPExits *CPExit[16]; /* coprocessor finalisers */ 231 ARMul_CPExits *CPExit[16]; /* coprocessor finalisers */
298 ARMul_LDCs *LDC[16]; /* LDC instruction */ 232 ARMul_LDCs *LDC[16]; /* LDC instruction */
299 ARMul_STCs *STC[16]; /* STC instruction */ 233 ARMul_STCs *STC[16]; /* STC instruction */
300 ARMul_MRCs *MRC[16]; /* MRC instruction */ 234 ARMul_MRCs *MRC[16]; /* MRC instruction */
301 ARMul_MCRs *MCR[16]; /* MCR instruction */ 235 ARMul_MCRs *MCR[16]; /* MCR instruction */
302 ARMul_MRRCs *MRRC[16]; /* MRRC instruction */ 236 ARMul_MRRCs *MRRC[16]; /* MRRC instruction */
303 ARMul_MCRRs *MCRR[16]; /* MCRR instruction */ 237 ARMul_MCRRs *MCRR[16]; /* MCRR instruction */
304 ARMul_CDPs *CDP[16]; /* CDP instruction */ 238 ARMul_CDPs *CDP[16]; /* CDP instruction */
305 ARMul_CPReads *CPRead[16]; /* Read CP register */ 239 ARMul_CPReads *CPRead[16]; /* Read CP register */
306 ARMul_CPWrites *CPWrite[16]; /* Write CP register */ 240 ARMul_CPWrites *CPWrite[16]; /* Write CP register */
307 unsigned char *CPData[16]; /* Coprocessor data */ 241 unsigned char *CPData[16]; /* Coprocessor data */
308 unsigned char const *CPRegWords[16]; /* map of coprocessor register sizes */ 242 unsigned char const *CPRegWords[16]; /* map of coprocessor register sizes */
309 243
310 unsigned EventSet; /* the number of events in the queue */ 244 unsigned EventSet; /* the number of events in the queue */
311 unsigned int Now; /* time to the nearest cycle */ 245 unsigned int Now; /* time to the nearest cycle */
312 struct EventNode **EventPtr; /* the event list */ 246 struct EventNode **EventPtr; /* the event list */
313 247
314 unsigned Debug; /* show instructions as they are executed */ 248 unsigned Debug; /* show instructions as they are executed */
315 unsigned NresetSig; /* reset the processor */ 249 unsigned NresetSig; /* reset the processor */
316 unsigned NfiqSig; 250 unsigned NfiqSig;
317 unsigned NirqSig; 251 unsigned NirqSig;
318 252
@@ -356,12 +290,12 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
356*/ 290*/
357 unsigned lateabtSig; 291 unsigned lateabtSig;
358 292
359 ARMword Vector; /* synthesize aborts in cycle modes */ 293 ARMword Vector; /* synthesize aborts in cycle modes */
360 ARMword Aborted; /* sticky flag for aborts */ 294 ARMword Aborted; /* sticky flag for aborts */
361 ARMword Reseted; /* sticky flag for Reset */ 295 ARMword Reseted; /* sticky flag for Reset */
362 ARMword Inted, LastInted; /* sticky flags for interrupts */ 296 ARMword Inted, LastInted; /* sticky flags for interrupts */
363 ARMword Base; /* extra hand for base writeback */ 297 ARMword Base; /* extra hand for base writeback */
364 ARMword AbortAddr; /* to keep track of Prefetch aborts */ 298 ARMword AbortAddr; /* to keep track of Prefetch aborts */
365 299
366 const struct Dbg_HostosInterface *hostif; 300 const struct Dbg_HostosInterface *hostif;
367 301
@@ -378,7 +312,7 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
378 //chy: 2003-08-11, for different arm core type 312 //chy: 2003-08-11, for different arm core type
379 unsigned is_v4; /* Are we emulating a v4 architecture (or higher) ? */ 313 unsigned is_v4; /* Are we emulating a v4 architecture (or higher) ? */
380 unsigned is_v5; /* Are we emulating a v5 architecture ? */ 314 unsigned is_v5; /* Are we emulating a v5 architecture ? */
381 unsigned is_v5e; /* Are we emulating a v5e architecture ? */ 315 unsigned is_v5e; /* Are we emulating a v5e architecture ? */
382 unsigned is_v6; /* Are we emulating a v6 architecture ? */ 316 unsigned is_v6; /* Are we emulating a v6 architecture ? */
383 unsigned is_v7; /* Are we emulating a v7 architecture ? */ 317 unsigned is_v7; /* Are we emulating a v7 architecture ? */
384 unsigned is_XScale; /* Are we emulating an XScale architecture ? */ 318 unsigned is_XScale; /* Are we emulating an XScale architecture ? */
@@ -387,51 +321,43 @@ So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
387 //chy 2005-09-19 321 //chy 2005-09-19
388 unsigned is_pxa27x; /* Are we emulating a Intel PXA27x co-processor ? */ 322 unsigned is_pxa27x; /* Are we emulating a Intel PXA27x co-processor ? */
389 //chy: seems only used in xscale's CP14 323 //chy: seems only used in xscale's CP14
390 unsigned int LastTime; /* Value of last call to ARMul_Time() */ 324 unsigned int LastTime; /* Value of last call to ARMul_Time() */
391 ARMword CP14R0_CCD; /* used to count 64 clock cycles with CP14 R0 bit 3 set */ 325 ARMword CP14R0_CCD; /* used to count 64 clock cycles with CP14 R0 bit 3 set */
392 326
393 327
394//added by ksh:for handle different machs io 2004-3-5 328 //added by ksh:for handle different machs io 2004-3-5
395 ARMul_io mach_io; 329 ARMul_io mach_io;
396 330
397/*added by ksh,2004-11-26,some energy profiling*/ 331 /*added by ksh,2004-11-26,some energy profiling*/
398 ARMul_Energy energy; 332 ARMul_Energy energy;
399 333
400//teawater add for next_dis 2004.10.27----------------------- 334 //teawater add for next_dis 2004.10.27-----------------------
401 int disassemble; 335 int disassemble;
402//AJ2D------------------------------------------
403 336
404//teawater add for arm2x86 2005.02.15------------------------------------------- 337
338 //teawater add for arm2x86 2005.02.15-------------------------------------------
405 u32 trap; 339 u32 trap;
406 u32 tea_break_addr; 340 u32 tea_break_addr;
407 u32 tea_break_ok; 341 u32 tea_break_ok;
408 int tea_pc; 342 int tea_pc;
409//AJ2D--------------------------------------------------------------------------
410//teawater add for arm2x86 2005.07.03-------------------------------------------
411
412 /*
413 * 2007-01-24 removed the term-io functions by Anthony Lee,
414 * moved to "device/uart/skyeye_uart_stdio.c".
415 */
416 343
417//AJ2D-------------------------------------------------------------------------- 344 //teawater add for arm2x86 2005.07.05-------------------------------------------
418//teawater add for arm2x86 2005.07.05-------------------------------------------
419 //arm_arm A2-18 345 //arm_arm A2-18
420 int abort_model; //0 Base Restored Abort Model, 1 the Early Abort Model, 2 Base Updated Abort Model 346 int abort_model; //0 Base Restored Abort Model, 1 the Early Abort Model, 2 Base Updated Abort Model
421//AJ2D-------------------------------------------------------------------------- 347
422//teawater change for return if running tb dirty 2005.07.09--------------------- 348 //teawater change for return if running tb dirty 2005.07.09---------------------
423 void *tb_now; 349 void *tb_now;
424//AJ2D--------------------------------------------------------------------------
425 350
426//teawater add for record reg value to ./reg.txt 2005.07.10--------------------- 351
352 //teawater add for record reg value to ./reg.txt 2005.07.10---------------------
427 FILE *tea_reg_fd; 353 FILE *tea_reg_fd;
428//AJ2D--------------------------------------------------------------------------
429 354
430/*added by ksh in 2005-10-1*/ 355
356 /*added by ksh in 2005-10-1*/
431 cpu_config_t *cpu; 357 cpu_config_t *cpu;
432 //mem_config_t *mem_bank; 358 //mem_config_t *mem_bank;
433 359
434/* added LPC remap function */ 360 /* added LPC remap function */
435 int vector_remap_flag; 361 int vector_remap_flag;
436 u32 vector_remap_addr; 362 u32 vector_remap_addr;
437 u32 vector_remap_size; 363 u32 vector_remap_size;
@@ -486,17 +412,14 @@ typedef ARMul_State arm_core_t;
486#define ARM_Debug_Prop 0x10 412#define ARM_Debug_Prop 0x10
487#define ARM_Isync_Prop ARM_Debug_Prop 413#define ARM_Isync_Prop ARM_Debug_Prop
488#define ARM_Lock_Prop 0x20 414#define ARM_Lock_Prop 0x20
489//chy 2003-08-11
490#define ARM_v4_Prop 0x40 415#define ARM_v4_Prop 0x40
491#define ARM_v5_Prop 0x80 416#define ARM_v5_Prop 0x80
492/*jeff.du 2010-08-05 */
493#define ARM_v6_Prop 0xc0 417#define ARM_v6_Prop 0xc0
494 418
495#define ARM_v5e_Prop 0x100 419#define ARM_v5e_Prop 0x100
496#define ARM_XScale_Prop 0x200 420#define ARM_XScale_Prop 0x200
497#define ARM_ep9312_Prop 0x400 421#define ARM_ep9312_Prop 0x400
498#define ARM_iWMMXt_Prop 0x800 422#define ARM_iWMMXt_Prop 0x800
499//chy 2005-09-19
500#define ARM_PXA27X_Prop 0x1000 423#define ARM_PXA27X_Prop 0x1000
501#define ARM_v7_Prop 0x2000 424#define ARM_v7_Prop 0x2000
502 425
@@ -591,47 +514,44 @@ typedef ARMul_State arm_core_t;
591#ifdef __cplusplus 514#ifdef __cplusplus
592extern "C" { 515extern "C" {
593#endif 516#endif
594extern void ARMul_EmulateInit (void); 517extern void ARMul_EmulateInit();
595extern void ARMul_Reset (ARMul_State * state); 518extern void ARMul_Reset(ARMul_State* state);
596#ifdef __cplusplus 519#ifdef __cplusplus
597 } 520 }
598#endif 521#endif
599extern ARMul_State *ARMul_NewState (ARMul_State * state); 522extern ARMul_State *ARMul_NewState(ARMul_State* state);
600extern ARMword ARMul_DoProg (ARMul_State * state); 523extern ARMword ARMul_DoProg(ARMul_State* state);
601extern ARMword ARMul_DoInstr (ARMul_State * state); 524extern ARMword ARMul_DoInstr(ARMul_State* state);
602/***************************************************************************\ 525/***************************************************************************\
603* Definitons of things for event handling * 526* Definitons of things for event handling *
604\***************************************************************************/ 527\***************************************************************************/
605 528
606extern void ARMul_ScheduleEvent (ARMul_State * state, unsigned int delay, 529extern void ARMul_ScheduleEvent(ARMul_State* state, unsigned int delay, unsigned(*func) ());
607 unsigned (*func) ()); 530extern void ARMul_EnvokeEvent(ARMul_State* state);
608extern void ARMul_EnvokeEvent (ARMul_State * state); 531extern unsigned int ARMul_Time(ARMul_State* state);
609extern unsigned int ARMul_Time (ARMul_State * state);
610 532
611/***************************************************************************\ 533/***************************************************************************\
612* Useful support routines * 534* Useful support routines *
613\***************************************************************************/ 535\***************************************************************************/
614 536
615extern ARMword ARMul_GetReg (ARMul_State * state, unsigned mode, 537extern ARMword ARMul_GetReg (ARMul_State* state, unsigned mode, unsigned reg);
616 unsigned reg); 538extern void ARMul_SetReg (ARMul_State* state, unsigned mode, unsigned reg, ARMword value);
617extern void ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, 539extern ARMword ARMul_GetPC(ARMul_State* state);
618 ARMword value); 540extern ARMword ARMul_GetNextPC(ARMul_State* state);
619extern ARMword ARMul_GetPC (ARMul_State * state); 541extern void ARMul_SetPC(ARMul_State* state, ARMword value);
620extern ARMword ARMul_GetNextPC (ARMul_State * state); 542extern ARMword ARMul_GetR15(ARMul_State* state);
621extern void ARMul_SetPC (ARMul_State * state, ARMword value); 543extern void ARMul_SetR15(ARMul_State* state, ARMword value);
622extern ARMword ARMul_GetR15 (ARMul_State * state); 544
623extern void ARMul_SetR15 (ARMul_State * state, ARMword value); 545extern ARMword ARMul_GetCPSR(ARMul_State* state);
624 546extern void ARMul_SetCPSR(ARMul_State* state, ARMword value);
625extern ARMword ARMul_GetCPSR (ARMul_State * state); 547extern ARMword ARMul_GetSPSR(ARMul_State* state, ARMword mode);
626extern void ARMul_SetCPSR (ARMul_State * state, ARMword value); 548extern void ARMul_SetSPSR(ARMul_State* state, ARMword mode, ARMword value);
627extern ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode);
628extern void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value);
629 549
630/***************************************************************************\ 550/***************************************************************************\
631* Definitons of things to handle aborts * 551* Definitons of things to handle aborts *
632\***************************************************************************/ 552\***************************************************************************/
633 553
634extern void ARMul_Abort (ARMul_State * state, ARMword address); 554extern void ARMul_Abort(ARMul_State* state, ARMword address);
635#ifdef MODET 555#ifdef MODET
636#define ARMul_ABORTWORD (state->TFlag ? 0xefffdfff : 0xefffffff) /* SWI -1 */ 556#define ARMul_ABORTWORD (state->TFlag ? 0xefffdfff : 0xefffffff) /* SWI -1 */
637#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \ 557#define ARMul_PREFETCHABORT(address) if (state->AbortAddr == 1) \
@@ -649,54 +569,40 @@ extern void ARMul_Abort (ARMul_State * state, ARMword address);
649* Definitons of things in the memory interface * 569* Definitons of things in the memory interface *
650\***************************************************************************/ 570\***************************************************************************/
651 571
652extern unsigned ARMul_MemoryInit (ARMul_State * state, 572extern unsigned ARMul_MemoryInit(ARMul_State* state, unsigned int initmemsize);
653 unsigned int initmemsize); 573extern void ARMul_MemoryExit(ARMul_State* state);
654extern void ARMul_MemoryExit (ARMul_State * state);
655 574
656extern ARMword ARMul_LoadInstrS (ARMul_State * state, ARMword address, 575extern ARMword ARMul_LoadInstrS(ARMul_State* state, ARMword address, ARMword isize);
657 ARMword isize); 576extern ARMword ARMul_LoadInstrN(ARMul_State* state, ARMword address, ARMword isize);
658extern ARMword ARMul_LoadInstrN (ARMul_State * state, ARMword address,
659 ARMword isize);
660#ifdef __cplusplus 577#ifdef __cplusplus
661extern "C" { 578extern "C" {
662#endif 579#endif
663extern ARMword ARMul_ReLoadInstr (ARMul_State * state, ARMword address, 580extern ARMword ARMul_ReLoadInstr(ARMul_State* state, ARMword address, ARMword isize);
664 ARMword isize);
665#ifdef __cplusplus 581#ifdef __cplusplus
666 } 582 }
667#endif 583#endif
668extern ARMword ARMul_LoadWordS (ARMul_State * state, ARMword address); 584extern ARMword ARMul_LoadWordS(ARMul_State* state, ARMword address);
669extern ARMword ARMul_LoadWordN (ARMul_State * state, ARMword address); 585extern ARMword ARMul_LoadWordN(ARMul_State* state, ARMword address);
670extern ARMword ARMul_LoadHalfWord (ARMul_State * state, ARMword address); 586extern ARMword ARMul_LoadHalfWord(ARMul_State* state, ARMword address);
671extern ARMword ARMul_LoadByte (ARMul_State * state, ARMword address); 587extern ARMword ARMul_LoadByte(ARMul_State* state, ARMword address);
672 588
673extern void ARMul_StoreWordS (ARMul_State * state, ARMword address, 589extern void ARMul_StoreWordS(ARMul_State* state, ARMword address, ARMword data);
674 ARMword data); 590extern void ARMul_StoreWordN(ARMul_State* state, ARMword address, ARMword data);
675extern void ARMul_StoreWordN (ARMul_State * state, ARMword address, 591extern void ARMul_StoreHalfWord(ARMul_State* state, ARMword address, ARMword data);
676 ARMword data); 592extern void ARMul_StoreByte(ARMul_State* state, ARMword address, ARMword data);
677extern void ARMul_StoreHalfWord (ARMul_State * state, ARMword address, 593
678 ARMword data); 594extern ARMword ARMul_SwapWord(ARMul_State* state, ARMword address, ARMword data);
679extern void ARMul_StoreByte (ARMul_State * state, ARMword address, 595extern ARMword ARMul_SwapByte(ARMul_State* state, ARMword address, ARMword data);
680 ARMword data); 596
681 597extern void ARMul_Icycles(ARMul_State* state, unsigned number, ARMword address);
682extern ARMword ARMul_SwapWord (ARMul_State * state, ARMword address, 598extern void ARMul_Ccycles(ARMul_State* state, unsigned number, ARMword address);
683 ARMword data); 599
684extern ARMword ARMul_SwapByte (ARMul_State * state, ARMword address, 600extern ARMword ARMul_ReadWord(ARMul_State* state, ARMword address);
685 ARMword data); 601extern ARMword ARMul_ReadByte(ARMul_State* state, ARMword address);
686 602extern void ARMul_WriteWord(ARMul_State* state, ARMword address, ARMword data);
687extern void ARMul_Icycles (ARMul_State * state, unsigned number, 603extern void ARMul_WriteByte(ARMul_State* state, ARMword address, ARMword data);
688 ARMword address); 604
689extern void ARMul_Ccycles (ARMul_State * state, unsigned number, 605extern ARMword ARMul_MemAccess(ARMul_State* state, ARMword, ARMword,
690 ARMword address);
691
692extern ARMword ARMul_ReadWord (ARMul_State * state, ARMword address);
693extern ARMword ARMul_ReadByte (ARMul_State * state, ARMword address);
694extern void ARMul_WriteWord (ARMul_State * state, ARMword address,
695 ARMword data);
696extern void ARMul_WriteByte (ARMul_State * state, ARMword address,
697 ARMword data);
698
699extern ARMword ARMul_MemAccess (ARMul_State * state, ARMword, ARMword,
700 ARMword, ARMword, ARMword, ARMword, ARMword, 606 ARMword, ARMword, ARMword, ARMword, ARMword,
701 ARMword, ARMword, ARMword); 607 ARMword, ARMword, ARMword);
702 608
@@ -739,66 +645,40 @@ extern ARMword ARMul_MemAccess (ARMul_State * state, ARMword, ARMword,
739#define ARMul_CP15_DBCON_E1 0x000c 645#define ARMul_CP15_DBCON_E1 0x000c
740#define ARMul_CP15_DBCON_E0 0x0003 646#define ARMul_CP15_DBCON_E0 0x0003
741 647
742extern unsigned ARMul_CoProInit (ARMul_State * state); 648extern unsigned ARMul_CoProInit(ARMul_State* state);
743extern void ARMul_CoProExit (ARMul_State * state); 649extern void ARMul_CoProExit(ARMul_State* state);
744extern void ARMul_CoProAttach (ARMul_State * state, unsigned number, 650extern void ARMul_CoProAttach (ARMul_State* state, unsigned number,
745 ARMul_CPInits * init, ARMul_CPExits * exit, 651 ARMul_CPInits* init, ARMul_CPExits* exit,
746 ARMul_LDCs * ldc, ARMul_STCs * stc, 652 ARMul_LDCs* ldc, ARMul_STCs* stc,
747 ARMul_MRCs * mrc, ARMul_MCRs * mcr, 653 ARMul_MRCs* mrc, ARMul_MCRs* mcr,
748 ARMul_MRRCs * mrrc, ARMul_MCRRs * mcrr, 654 ARMul_MRRCs* mrrc, ARMul_MCRRs* mcrr,
749 ARMul_CDPs * cdp, 655 ARMul_CDPs* cdp,
750 ARMul_CPReads * read, ARMul_CPWrites * write); 656 ARMul_CPReads* read, ARMul_CPWrites* write);
751extern void ARMul_CoProDetach (ARMul_State * state, unsigned number); 657extern void ARMul_CoProDetach(ARMul_State* state, unsigned number);
752 658
753/***************************************************************************\ 659/***************************************************************************\
754* Definitons of things in the host environment * 660* Definitons of things in the host environment *
755\***************************************************************************/ 661\***************************************************************************/
756 662
757extern unsigned ARMul_OSInit (ARMul_State * state); 663extern unsigned ARMul_OSInit(ARMul_State* state);
758extern void ARMul_OSExit (ARMul_State * state); 664extern void ARMul_OSExit(ARMul_State* state);
759 665
760#ifdef __cplusplus 666#ifdef __cplusplus
761 extern "C" { 667 extern "C" {
762#endif 668#endif
763 669
764extern unsigned ARMul_OSHandleSWI (ARMul_State * state, ARMword number); 670extern unsigned ARMul_OSHandleSWI(ARMul_State* state, ARMword number);
765#ifdef __cplusplus 671#ifdef __cplusplus
766} 672}
767#endif 673#endif
768 674
769 675
770extern ARMword ARMul_OSLastErrorP (ARMul_State * state); 676extern ARMword ARMul_OSLastErrorP(ARMul_State* state);
771 677
772extern ARMword ARMul_Debug (ARMul_State * state, ARMword pc, ARMword instr); 678extern ARMword ARMul_Debug(ARMul_State* state, ARMword pc, ARMword instr);
773extern unsigned ARMul_OSException (ARMul_State * state, ARMword vector, 679extern unsigned ARMul_OSException(ARMul_State* state, ARMword vector, ARMword pc);
774 ARMword pc);
775extern int rdi_log; 680extern int rdi_log;
776 681
777/***************************************************************************\
778* Host-dependent stuff *
779\***************************************************************************/
780
781#ifdef macintosh
782pascal void SpinCursor (short increment); /* copied from CursorCtl.h */
783# define HOURGLASS SpinCursor( 1 )
784# define HOURGLASS_RATE 1023 /* 2^n - 1 */
785#endif
786
787//teawater add for arm2x86 2005.02.14-------------------------------------------
788/*ywc 2005-03-31*/
789/*
790#include "arm2x86.h"
791#include "arm2x86_dp.h"
792#include "arm2x86_movl.h"
793#include "arm2x86_psr.h"
794#include "arm2x86_shift.h"
795#include "arm2x86_mem.h"
796#include "arm2x86_mul.h"
797#include "arm2x86_test.h"
798#include "arm2x86_other.h"
799#include "list.h"
800#include "tb.h"
801*/
802enum ConditionCode { 682enum ConditionCode {
803 EQ = 0, 683 EQ = 0,
804 NE = 1, 684 NE = 1,
@@ -851,32 +731,16 @@ enum ConditionCode {
851#define ZBIT_SHIFT 30 731#define ZBIT_SHIFT 30
852#define CBIT_SHIFT 29 732#define CBIT_SHIFT 29
853#define VBIT_SHIFT 28 733#define VBIT_SHIFT 28
854#ifdef DBCT 734
855//teawater change for local tb branch directly jump 2005.10.18------------------
856#include "dbct/list.h"
857#include "dbct/arm2x86.h"
858#include "dbct/arm2x86_dp.h"
859#include "dbct/arm2x86_movl.h"
860#include "dbct/arm2x86_psr.h"
861#include "dbct/arm2x86_shift.h"
862#include "dbct/arm2x86_mem.h"
863#include "dbct/arm2x86_mul.h"
864#include "dbct/arm2x86_test.h"
865#include "dbct/arm2x86_other.h"
866#include "dbct/arm2x86_coproc.h"
867#include "dbct/tb.h"
868#endif
869//AJ2D--------------------------------------------------------------------------
870//AJ2D--------------------------------------------------------------------------
871#define SKYEYE_OUTREGS(fd) { fprintf ((fd), "R %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,C %x,S %x,%x,%x,%x,%x,%x,%x,M %x,B %x,E %x,I %x,P %x,T %x,L %x,D %x,",\ 735#define SKYEYE_OUTREGS(fd) { fprintf ((fd), "R %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,C %x,S %x,%x,%x,%x,%x,%x,%x,M %x,B %x,E %x,I %x,P %x,T %x,L %x,D %x,",\
872 state->Reg[0],state->Reg[1],state->Reg[2],state->Reg[3], \ 736 state->Reg[0],state->Reg[1],state->Reg[2],state->Reg[3], \
873 state->Reg[4],state->Reg[5],state->Reg[6],state->Reg[7], \ 737 state->Reg[4],state->Reg[5],state->Reg[6],state->Reg[7], \
874 state->Reg[8],state->Reg[9],state->Reg[10],state->Reg[11], \ 738 state->Reg[8],state->Reg[9],state->Reg[10],state->Reg[11], \
875 state->Reg[12],state->Reg[13],state->Reg[14],state->Reg[15], \ 739 state->Reg[12],state->Reg[13],state->Reg[14],state->Reg[15], \
876 state->Cpsr, state->Spsr[0], state->Spsr[1], state->Spsr[2],\ 740 state->Cpsr, state->Spsr[0], state->Spsr[1], state->Spsr[2],\
877 state->Spsr[3],state->Spsr[4], state->Spsr[5], state->Spsr[6],\ 741 state->Spsr[3],state->Spsr[4], state->Spsr[5], state->Spsr[6],\
878 state->Mode,state->Bank,state->ErrorCode,state->instr,state->pc,\ 742 state->Mode,state->Bank,state->ErrorCode,state->instr,state->pc,\
879 state->temp,state->loaded,state->decoded);} 743 state->temp,state->loaded,state->decoded);}
880 744
881#define SKYEYE_OUTMOREREGS(fd) { fprintf ((fd),"\ 745#define SKYEYE_OUTMOREREGS(fd) { fprintf ((fd),"\
882RUs %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\ 746RUs %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,\
@@ -914,17 +778,28 @@ RUn %x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",\
914 778
915#define SA1110 0x6901b110 779#define SA1110 0x6901b110
916#define SA1100 0x4401a100 780#define SA1100 0x4401a100
917#define PXA250 0x69052100 781#define PXA250 0x69052100
918#define PXA270 0x69054110 782#define PXA270 0x69054110
919//#define PXA250 0x69052903 783//#define PXA250 0x69052903
920// 0x69052903; //PXA250 B1 from intel 278522-001.pdf 784// 0x69052903; //PXA250 B1 from intel 278522-001.pdf
921 785
922 786
923extern void ARMul_UndefInstr (ARMul_State *, ARMword); 787extern void ARMul_UndefInstr(ARMul_State*, ARMword);
924extern void ARMul_FixCPSR (ARMul_State *, ARMword, ARMword); 788extern void ARMul_FixCPSR(ARMul_State*, ARMword, ARMword);
925extern void ARMul_FixSPSR (ARMul_State *, ARMword, ARMword); 789extern void ARMul_FixSPSR(ARMul_State*, ARMword, ARMword);
926extern void ARMul_ConsolePrint (ARMul_State *, const char *, ...); 790extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...);
927extern void ARMul_SelectProcessor (ARMul_State *, unsigned); 791extern void ARMul_SelectProcessor(ARMul_State*, unsigned);
792
793extern u8 ARMul_SignedSaturatedAdd8(u8, u8);
794extern u8 ARMul_SignedSaturatedSub8(u8, u8);
795extern u16 ARMul_SignedSaturatedAdd16(u16, u16);
796extern u16 ARMul_SignedSaturatedSub16(u16, u16);
797
798extern u8 ARMul_UnsignedSaturatedAdd8(u8, u8);
799extern u16 ARMul_UnsignedSaturatedAdd16(u16, u16);
800extern u8 ARMul_UnsignedSaturatedSub8(u8, u8);
801extern u16 ARMul_UnsignedSaturatedSub16(u16, u16);
802extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
928 803
929#define DIFF_LOG 0 804#define DIFF_LOG 0
930#define SAVE_LOG 0 805#define SAVE_LOG 0
diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h
index 7f7c0e682..3ea14b5a3 100644
--- a/src/core/arm/skyeye_common/armemu.h
+++ b/src/core/arm/skyeye_common/armemu.h
@@ -34,7 +34,7 @@
34#define ZBIT (1L << 30) 34#define ZBIT (1L << 30)
35#define CBIT (1L << 29) 35#define CBIT (1L << 29)
36#define VBIT (1L << 28) 36#define VBIT (1L << 28)
37#define SBIT (1L << 27) 37#define QBIT (1L << 27)
38#define IBIT (1L << 7) 38#define IBIT (1L << 7)
39#define FBIT (1L << 6) 39#define FBIT (1L << 6)
40#define IFBITS (3L << 6) 40#define IFBITS (3L << 6)
@@ -156,13 +156,14 @@
156#define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS)) 156#define R15PCMODE (state->Reg[15] & (R15PCBITS | R15MODEBITS))
157#define R15MODE (state->Reg[15] & R15MODEBITS) 157#define R15MODE (state->Reg[15] & R15MODEBITS)
158 158
159#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28) | (SFLAG << 27)) 159#define ECC ((NFLAG << 31) | (ZFLAG << 30) | (CFLAG << 29) | (VFLAG << 28) | (QFLAG << 27))
160#define EINT (IFFLAGS << 6) 160#define EINT (IFFLAGS << 6)
161#define ER15INT (IFFLAGS << 26) 161#define ER15INT (IFFLAGS << 26)
162#define EMODE (state->Mode) 162#define EMODE (state->Mode)
163#define EGEBITS (state->GEFlag & 0x000F0000)
163 164
164#ifdef MODET 165#ifdef MODET
165#define CPSR (ECC | EINT | EMODE | (TFLAG << 5)) 166#define CPSR (ECC | EGEBITS | (EFLAG << 9) | (AFLAG << 8) | EINT | (TFLAG << 5) | EMODE)
166#else 167#else
167#define CPSR (ECC | EINT | EMODE) 168#define CPSR (ECC | EINT | EMODE)
168#endif 169#endif
@@ -601,6 +602,7 @@ extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword);
601extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword); 602extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword);
602extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword); 603extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword);
603extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword); 604extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword);
605extern void ARMul_AddOverflowQ(ARMul_State*, ARMword, ARMword);
604extern void ARMul_SubCarry (ARMul_State *, ARMword, ARMword, ARMword); 606extern void ARMul_SubCarry (ARMul_State *, ARMword, ARMword, ARMword);
605extern void ARMul_AddCarry (ARMul_State *, ARMword, ARMword, ARMword); 607extern void ARMul_AddCarry (ARMul_State *, ARMword, ARMword, ARMword);
606extern tdstate ARMul_ThumbDecode (ARMul_State *, ARMword, ARMword, ARMword *); 608extern tdstate ARMul_ThumbDecode (ARMul_State *, ARMword, ARMword, ARMword *);
diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp
index 454f60099..5c036caeb 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfp.cpp
@@ -32,8 +32,7 @@
32 32
33//ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_state. */ 33//ARMul_State* persistent_state; /* function calls from SoftFloat lib don't have an access to ARMul_state. */
34 34
35unsigned 35unsigned VFPInit(ARMul_State* state)
36VFPInit (ARMul_State *state)
37{ 36{
38 state->VFP[VFP_OFFSET(VFP_FPSID)] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 | 37 state->VFP[VFP_OFFSET(VFP_FPSID)] = VFP_FPSID_IMPLMEN<<24 | VFP_FPSID_SW<<23 | VFP_FPSID_SUBARCH<<16 |
39 VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION; 38 VFP_FPSID_PARTNUM<<8 | VFP_FPSID_VARIANT<<4 | VFP_FPSID_REVISION;
@@ -46,8 +45,7 @@ VFPInit (ARMul_State *state)
46 return 0; 45 return 0;
47} 46}
48 47
49unsigned 48unsigned VFPMRC(ARMul_State* state, unsigned type, u32 instr, u32* value)
50VFPMRC (ARMul_State * state, unsigned type, u32 instr, u32 * value)
51{ 49{
52 /* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ 50 /* MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
53 int CoProc = BITS (8, 11); /* 10 or 11 */ 51 int CoProc = BITS (8, 11); /* 10 or 11 */
@@ -61,10 +59,21 @@ VFPMRC (ARMul_State * state, unsigned type, u32 instr, u32 * value)
61 59
62 /* CRn/opc1 CRm/opc2 */ 60 /* CRn/opc1 CRm/opc2 */
63 61
64 if (CoProc == 10 || CoProc == 11) { 62 if (CoProc == 10 || CoProc == 11)
65#define VFP_MRC_TRANS 63 {
66#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 64 if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
67#undef VFP_MRC_TRANS 65 {
66 /* VMOV r to s */
67 /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
68 VMOVBRS(state, BIT(20), Rt, BIT(7)|CRn<<1, value);
69 return ARMul_DONE;
70 }
71
72 if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
73 {
74 VMRS(state, CRn, Rt, value);
75 return ARMul_DONE;
76 }
68 } 77 }
69 DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n", 78 DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
70 instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2); 79 instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
@@ -72,8 +81,7 @@ VFPMRC (ARMul_State * state, unsigned type, u32 instr, u32 * value)
72 return ARMul_CANT; 81 return ARMul_CANT;
73} 82}
74 83
75unsigned 84unsigned VFPMCR(ARMul_State* state, unsigned type, u32 instr, u32 value)
76VFPMCR (ARMul_State * state, unsigned type, u32 instr, u32 value)
77{ 85{
78 /* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */ 86 /* MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>} */
79 int CoProc = BITS (8, 11); /* 10 or 11 */ 87 int CoProc = BITS (8, 11); /* 10 or 11 */
@@ -86,10 +94,33 @@ VFPMCR (ARMul_State * state, unsigned type, u32 instr, u32 value)
86 /* TODO check access permission */ 94 /* TODO check access permission */
87 95
88 /* CRn/opc1 CRm/opc2 */ 96 /* CRn/opc1 CRm/opc2 */
89 if (CoProc == 10 || CoProc == 11) { 97 if (CoProc == 10 || CoProc == 11)
90#define VFP_MCR_TRANS 98 {
91#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 99 if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
92#undef VFP_MCR_TRANS 100 {
101 /* VMOV s to r */
102 /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
103 VMOVBRS(state, BIT(20), Rt, BIT(7)|CRn<<1, &value);
104 return ARMul_DONE;
105 }
106
107 if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
108 {
109 VMSR(state, CRn, Rt);
110 return ARMul_DONE;
111 }
112
113 if ((OPC_1 & 0x4) == 0 && CoProc == 11 && CRm == 0)
114 {
115 VFP_DEBUG_UNIMPLEMENTED(VMOVBRC);
116 return ARMul_DONE;
117 }
118
119 if (CoProc == 11 && CRm == 0)
120 {
121 VFP_DEBUG_UNIMPLEMENTED(VMOVBCR);
122 return ARMul_DONE;
123 }
93 } 124 }
94 DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n", 125 DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, CRn %x, CRm %x, OPC_2 %x\n",
95 instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2); 126 instr, CoProc, OPC_1, Rt, CRn, CRm, OPC_2);
@@ -97,8 +128,7 @@ VFPMCR (ARMul_State * state, unsigned type, u32 instr, u32 value)
97 return ARMul_CANT; 128 return ARMul_CANT;
98} 129}
99 130
100unsigned 131unsigned VFPMRRC(ARMul_State* state, unsigned type, u32 instr, u32* value1, u32* value2)
101VFPMRRC (ARMul_State * state, unsigned type, u32 instr, u32 * value1, u32 * value2)
102{ 132{
103 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ 133 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
104 int CoProc = BITS (8, 11); /* 10 or 11 */ 134 int CoProc = BITS (8, 11); /* 10 or 11 */
@@ -107,10 +137,20 @@ VFPMRRC (ARMul_State * state, unsigned type, u32 instr, u32 * value1, u32 * valu
107 int Rt2 = BITS (16, 19); 137 int Rt2 = BITS (16, 19);
108 int CRm = BITS (0, 3); 138 int CRm = BITS (0, 3);
109 139
110 if (CoProc == 10 || CoProc == 11) { 140 if (CoProc == 10 || CoProc == 11)
111#define VFP_MRRC_TRANS 141 {
112#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 142 if (CoProc == 10 && (OPC_1 & 0xD) == 1)
113#undef VFP_MRRC_TRANS 143 {
144 VFP_DEBUG_UNIMPLEMENTED(VMOVBRRSS);
145 return ARMul_DONE;
146 }
147
148 if (CoProc == 11 && (OPC_1 & 0xD) == 1)
149 {
150 /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
151 VMOVBRRD(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, value1, value2);
152 return ARMul_DONE;
153 }
114 } 154 }
115 DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n", 155 DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
116 instr, CoProc, OPC_1, Rt, Rt2, CRm); 156 instr, CoProc, OPC_1, Rt, Rt2, CRm);
@@ -118,8 +158,7 @@ VFPMRRC (ARMul_State * state, unsigned type, u32 instr, u32 * value1, u32 * valu
118 return ARMul_CANT; 158 return ARMul_CANT;
119} 159}
120 160
121unsigned 161unsigned VFPMCRR(ARMul_State* state, unsigned type, u32 instr, u32 value1, u32 value2)
122VFPMCRR (ARMul_State * state, unsigned type, u32 instr, u32 value1, u32 value2)
123{ 162{
124 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */ 163 /* MCRR<c> <coproc>,<opc1>,<Rt>,<Rt2>,<CRm> */
125 int CoProc = BITS (8, 11); /* 10 or 11 */ 164 int CoProc = BITS (8, 11); /* 10 or 11 */
@@ -132,10 +171,20 @@ VFPMCRR (ARMul_State * state, unsigned type, u32 instr, u32 value1, u32 value2)
132 171
133 /* CRn/opc1 CRm/opc2 */ 172 /* CRn/opc1 CRm/opc2 */
134 173
135 if (CoProc == 11 || CoProc == 10) { 174 if (CoProc == 11 || CoProc == 10)
136#define VFP_MCRR_TRANS 175 {
137#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 176 if (CoProc == 10 && (OPC_1 & 0xD) == 1)
138#undef VFP_MCRR_TRANS 177 {
178 VFP_DEBUG_UNIMPLEMENTED(VMOVBRRSS);
179 return ARMul_DONE;
180 }
181
182 if (CoProc == 11 && (OPC_1 & 0xD) == 1)
183 {
184 /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
185 VMOVBRRD(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, &value1, &value2);
186 return ARMul_DONE;
187 }
139 } 188 }
140 DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n", 189 DEBUG("Can't identify %x, CoProc %x, OPC_1 %x, Rt %x, Rt2 %x, CRm %x\n",
141 instr, CoProc, OPC_1, Rt, Rt2, CRm); 190 instr, CoProc, OPC_1, Rt, Rt2, CRm);
@@ -143,8 +192,7 @@ VFPMCRR (ARMul_State * state, unsigned type, u32 instr, u32 value1, u32 value2)
143 return ARMul_CANT; 192 return ARMul_CANT;
144} 193}
145 194
146unsigned 195unsigned VFPSTC(ARMul_State* state, unsigned type, u32 instr, u32 * value)
147VFPSTC (ARMul_State * state, unsigned type, u32 instr, u32 * value)
148{ 196{
149 /* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */ 197 /* STC{L}<c> <coproc>,<CRd>,[<Rn>],<option> */
150 int CoProc = BITS (8, 11); /* 10 or 11 */ 198 int CoProc = BITS (8, 11); /* 10 or 11 */
@@ -175,9 +223,17 @@ VFPSTC (ARMul_State * state, unsigned type, u32 instr, u32 * value)
175 } 223 }
176#endif 224#endif
177 225
178#define VFP_STC_TRANS 226 if (P == 1 && W == 0)
179#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 227 {
180#undef VFP_STC_TRANS 228 return VSTR(state, type, instr, value);
229 }
230
231 if (P == 1 && U == 0 && W == 1 && Rn == 0xD)
232 {
233 return VPUSH(state, type, instr, value);
234 }
235
236 return VSTM(state, type, instr, value);
181 } 237 }
182 DEBUG("Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n", 238 DEBUG("Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",
183 instr, CoProc, CRd, Rn, imm8, P, U, D, W); 239 instr, CoProc, CRd, Rn, imm8, P, U, D, W);
@@ -185,8 +241,7 @@ VFPSTC (ARMul_State * state, unsigned type, u32 instr, u32 * value)
185 return ARMul_CANT; 241 return ARMul_CANT;
186} 242}
187 243
188unsigned 244unsigned VFPLDC(ARMul_State* state, unsigned type, u32 instr, u32 value)
189VFPLDC (ARMul_State * state, unsigned type, u32 instr, u32 value)
190{ 245{
191 /* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */ 246 /* LDC{L}<c> <coproc>,<CRd>,[<Rn>] */
192 int CoProc = BITS (8, 11); /* 10 or 11 */ 247 int CoProc = BITS (8, 11); /* 10 or 11 */
@@ -204,10 +259,19 @@ VFPLDC (ARMul_State * state, unsigned type, u32 instr, u32 value)
204 DEBUG("In %s, UNDEFINED\n", __FUNCTION__); 259 DEBUG("In %s, UNDEFINED\n", __FUNCTION__);
205 exit(-1); 260 exit(-1);
206 } 261 }
207 if (CoProc == 10 || CoProc == 11) { 262 if (CoProc == 10 || CoProc == 11)
208#define VFP_LDC_TRANS 263 {
209#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 264 if (P == 1 && W == 0)
210#undef VFP_LDC_TRANS 265 {
266 return VLDR(state, type, instr, value);
267 }
268
269 if (P == 0 && U == 1 && W == 1 && Rn == 0xD)
270 {
271 return VPOP(state, type, instr, value);
272 }
273
274 return VLDM(state, type, instr, value);
211 } 275 }
212 DEBUG("Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n", 276 DEBUG("Can't identify %x, CoProc %x, CRd %x, Rn %x, imm8 %x, P %x, U %x, D %x, W %x\n",
213 instr, CoProc, CRd, Rn, imm8, P, U, D, W); 277 instr, CoProc, CRd, Rn, imm8, P, U, D, W);
@@ -215,8 +279,7 @@ VFPLDC (ARMul_State * state, unsigned type, u32 instr, u32 value)
215 return ARMul_CANT; 279 return ARMul_CANT;
216} 280}
217 281
218unsigned 282unsigned VFPCDP(ARMul_State* state, unsigned type, u32 instr)
219VFPCDP (ARMul_State * state, unsigned type, u32 instr)
220{ 283{
221 /* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */ 284 /* CDP<c> <coproc>,<opc1>,<CRd>,<CRn>,<CRm>,<opc2> */
222 int CoProc = BITS (8, 11); /* 10 or 11 */ 285 int CoProc = BITS (8, 11); /* 10 or 11 */
@@ -275,10 +338,83 @@ VFPCDP (ARMul_State * state, unsigned type, u32 instr)
275 338
276 /* CRn/opc1 CRm/opc2 */ 339 /* CRn/opc1 CRm/opc2 */
277 340
278 if (CoProc == 10 || CoProc == 11) { 341 if (CoProc == 10 || CoProc == 11)
279#define VFP_CDP_TRANS 342 {
280#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 343 if ((OPC_1 & 0xB) == 0 && (OPC_2 & 0x2) == 0)
281#undef VFP_CDP_TRANS 344 DBG("VMLA :\n");
345
346 if ((OPC_1 & 0xB) == 0 && (OPC_2 & 0x2) == 2)
347 DBG("VMLS :\n");
348
349 if ((OPC_1 & 0xB) == 1 && (OPC_2 & 0x2) == 2)
350 DBG("VNMLA :\n");
351
352 if ((OPC_1 & 0xB) == 1 && (OPC_2 & 0x2) == 0)
353 DBG("VNMLS :\n");
354
355 if ((OPC_1 & 0xB) == 2 && (OPC_2 & 0x2) == 2)
356 DBG("VNMUL :\n");
357
358 if ((OPC_1 & 0xB) == 2 && (OPC_2 & 0x2) == 0)
359 DBG("VMUL :\n");
360
361 if ((OPC_1 & 0xB) == 3 && (OPC_2 & 0x2) == 0)
362 DBG("VADD :\n");
363
364 if ((OPC_1 & 0xB) == 3 && (OPC_2 & 0x2) == 2)
365 DBG("VSUB :\n");
366
367 if ((OPC_1 & 0xB) == 0xA && (OPC_2 & 0x2) == 0)
368 DBG("VDIV :\n");
369
370 if ((OPC_1 & 0xB) == 0xB && BITS(4, 7) == 0)
371 {
372 unsigned int single = BIT(8) == 0;
373 unsigned int d = (single ? BITS(12,15)<<1 | BIT(22) : BITS(12,15) | BIT(22)<<4);
374 unsigned int imm;
375 instr = BITS(16, 19) << 4 | BITS(0, 3); /* FIXME dirty workaround to get a correct imm */
376
377 if (single)
378 imm = BIT(7)<<31 | (BIT(6)==0)<<30 | (BIT(6) ? 0x1f : 0)<<25 | BITS(0, 5)<<19;
379 else
380 imm = BIT(7)<<31 | (BIT(6)==0)<<30 | (BIT(6) ? 0xff : 0)<<22 | BITS(0, 5)<<16;
381
382 VMOVI(state, single, d, imm);
383 return ARMul_DONE;
384 }
385
386 if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x6) == 0x2)
387 {
388 unsigned int single = BIT(8) == 0;
389 unsigned int d = (single ? BITS(12,15)<<1 | BIT(22) : BITS(12,15) | BIT(22)<<4);
390 unsigned int m = (single ? BITS( 0, 3)<<1 | BIT( 5) : BITS( 0, 3) | BIT( 5)<<4);;
391 VMOVR(state, single, d, m);
392 return ARMul_DONE;
393 }
394
395 if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x7) == 6)
396 DBG("VABS :\n");
397
398 if ((OPC_1 & 0xB) == 0xB && CRn == 1 && (OPC_2 & 0x7) == 2)
399 DBG("VNEG :\n");
400
401 if ((OPC_1 & 0xB) == 0xB && CRn == 1 && (OPC_2 & 0x7) == 6)
402 DBG("VSQRT :\n");
403
404 if ((OPC_1 & 0xB) == 0xB && CRn == 4 && (OPC_2 & 0x2) == 2)
405 DBG("VCMP(1) :\n");
406
407 if ((OPC_1 & 0xB) == 0xB && CRn == 5 && (OPC_2 & 0x2) == 2 && CRm == 0)
408 DBG("VCMP(2) :\n");
409
410 if ((OPC_1 & 0xB) == 0xB && CRn == 7 && (OPC_2 & 0x6) == 6)
411 DBG("VCVT(BDS) :\n");
412
413 if ((OPC_1 & 0xB) == 0xB && CRn >= 0xA && (OPC_2 & 0x2) == 2)
414 DBG("VCVT(BFF) :\n");
415
416 if ((OPC_1 & 0xB) == 0xB && CRn > 7 && (OPC_2 & 0x2) == 2)
417 DBG("VCVT(BFI) :\n");
282 418
283 int exceptions = 0; 419 int exceptions = 0;
284 if (CoProc == 10) 420 if (CoProc == 10)
@@ -296,23 +432,93 @@ VFPCDP (ARMul_State * state, unsigned type, u32 instr)
296 432
297 433
298/* ----------- MRC ------------ */ 434/* ----------- MRC ------------ */
299#define VFP_MRC_IMPL 435void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value)
300#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 436{
301#undef VFP_MRC_IMPL 437 DBG("VMOV(BRS) :\n");
302 438 if (to_arm)
303#define VFP_MRRC_IMPL 439 {
304#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 440 DBG("\tr%d <= s%d=[%x]\n", t, n, state->ExtReg[n]);
305#undef VFP_MRRC_IMPL 441 *value = state->ExtReg[n];
306 442 }
443 else
444 {
445 DBG("\ts%d <= r%d=[%x]\n", n, t, *value);
446 state->ExtReg[n] = *value;
447 }
448}
449void VMRS(ARMul_State* state, ARMword reg, ARMword Rt, ARMword* value)
450{
451 DBG("VMRS :");
452 if (reg == 1)
453 {
454 if (Rt != 15)
455 {
456 *value = state->VFP[VFP_OFFSET(VFP_FPSCR)];
457 DBG("\tr%d <= fpscr[%08x]\n", Rt, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
458 }
459 else
460 {
461 *value = state->VFP[VFP_OFFSET(VFP_FPSCR)] ;
462 DBG("\tflags <= fpscr[%1xxxxxxxx]\n", state->VFP[VFP_OFFSET(VFP_FPSCR)]>>28);
463 }
464 }
465 else
466 {
467 switch (reg)
468 {
469 case 0:
470 *value = state->VFP[VFP_OFFSET(VFP_FPSID)];
471 DBG("\tr%d <= fpsid[%08x]\n", Rt, state->VFP[VFP_OFFSET(VFP_FPSID)]);
472 break;
473 case 6:
474 /* MVFR1, VFPv3 only ? */
475 DBG("\tr%d <= MVFR1 unimplemented\n", Rt);
476 break;
477 case 7:
478 /* MVFR0, VFPv3 only? */
479 DBG("\tr%d <= MVFR0 unimplemented\n", Rt);
480 break;
481 case 8:
482 *value = state->VFP[VFP_OFFSET(VFP_FPEXC)];
483 DBG("\tr%d <= fpexc[%08x]\n", Rt, state->VFP[VFP_OFFSET(VFP_FPEXC)]);
484 break;
485 default:
486 DBG("\tSUBARCHITECTURE DEFINED\n");
487 break;
488 }
489 }
490}
491void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2)
492{
493 DBG("VMOV(BRRD) :\n");
494 if (to_arm)
495 {
496 DBG("\tr[%d-%d] <= s[%d-%d]=[%x-%x]\n", t2, t, n*2+1, n*2, state->ExtReg[n*2+1], state->ExtReg[n*2]);
497 *value2 = state->ExtReg[n*2+1];
498 *value1 = state->ExtReg[n*2];
499 }
500 else
501 {
502 DBG("\ts[%d-%d] <= r[%d-%d]=[%x-%x]\n", n*2+1, n*2, t2, t, *value2, *value1);
503 state->ExtReg[n*2+1] = *value2;
504 state->ExtReg[n*2] = *value1;
505 }
506}
307 507
308/* ----------- MCR ------------ */ 508/* ----------- MCR ------------ */
309#define VFP_MCR_IMPL 509void VMSR(ARMul_State* state, ARMword reg, ARMword Rt)
310#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 510{
311#undef VFP_MCR_IMPL 511 if (reg == 1)
312 512 {
313#define VFP_MCRR_IMPL 513 DBG("VMSR :\tfpscr <= r%d=[%x]\n", Rt, state->Reg[Rt]);
314#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 514 state->VFP[VFP_OFFSET(VFP_FPSCR)] = state->Reg[Rt];
315#undef VFP_MCRR_IMPL 515 }
516 else if (reg == 8)
517 {
518 DBG("VMSR :\tfpexc <= r%d=[%x]\n", Rt, state->Reg[Rt]);
519 state->VFP[VFP_OFFSET(VFP_FPEXC)] = state->Reg[Rt];
520 }
521}
316 522
317/* Memory operation are not inlined, as old Interpreter and Fast interpreter 523/* Memory operation are not inlined, as old Interpreter and Fast interpreter
318 don't have the same memory operation interface. 524 don't have the same memory operation interface.
@@ -322,21 +528,342 @@ VFPCDP (ARMul_State * state, unsigned type, u32 instr)
322 of vfp instructions in old interpreter and fast interpreter are separate. */ 528 of vfp instructions in old interpreter and fast interpreter are separate. */
323 529
324/* ----------- STC ------------ */ 530/* ----------- STC ------------ */
325#define VFP_STC_IMPL 531int VSTR(ARMul_State* state, int type, ARMword instr, ARMword* value)
326#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 532{
327#undef VFP_STC_IMPL 533 static int i = 0;
534 static int single_reg, add, d, n, imm32, regs;
535 if (type == ARMul_FIRST)
536 {
537 single_reg = BIT(8) == 0; /* Double precision */
538 add = BIT(23); /* */
539 imm32 = BITS(0,7)<<2; /* may not be used */
540 d = single_reg ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
541 n = BITS(16, 19); /* destination register */
328 542
543 DBG("VSTR :\n");
544
545 i = 0;
546 regs = 1;
547
548 return ARMul_DONE;
549 }
550 else if (type == ARMul_DATA)
551 {
552 if (single_reg)
553 {
554 *value = state->ExtReg[d+i];
555 DBG("\taddr[?] <= s%d=[%x]\n", d+i, state->ExtReg[d+i]);
556 i++;
557 if (i < regs)
558 return ARMul_INC;
559 else
560 return ARMul_DONE;
561 }
562 else
563 {
564 /* FIXME Careful of endianness, may need to rework this */
565 *value = state->ExtReg[d*2+i];
566 DBG("\taddr[?] <= s[%d]=[%x]\n", d*2+i, state->ExtReg[d*2+i]);
567 i++;
568 if (i < regs*2)
569 return ARMul_INC;
570 else
571 return ARMul_DONE;
572 }
573 }
574
575 return -1;
576}
577int VPUSH(ARMul_State* state, int type, ARMword instr, ARMword* value)
578{
579 static int i = 0;
580 static int single_regs, add, wback, d, n, imm32, regs;
581 if (type == ARMul_FIRST)
582 {
583 single_regs = BIT(8) == 0; /* Single precision */
584 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
585 imm32 = BITS(0,7)<<2; /* may not be used */
586 regs = single_regs ? BITS(0, 7) : BITS(1, 7); /* FSTMX if regs is odd */
587
588 DBG("VPUSH :\n");
589 DBG("\tsp[%x]", state->Reg[R13]);
590 state->Reg[R13] = state->Reg[R13] - imm32;
591 DBG("=>[%x]\n", state->Reg[R13]);
592
593 i = 0;
594
595 return ARMul_DONE;
596 }
597 else if (type == ARMul_DATA)
598 {
599 if (single_regs)
600 {
601 *value = state->ExtReg[d + i];
602 DBG("\taddr[?] <= s%d=[%x]\n", d+i, state->ExtReg[d + i]);
603 i++;
604 if (i < regs)
605 return ARMul_INC;
606 else
607 return ARMul_DONE;
608 }
609 else
610 {
611 /* FIXME Careful of endianness, may need to rework this */
612 *value = state->ExtReg[d*2 + i];
613 DBG("\taddr[?] <= s[%d]=[%x]\n", d*2 + i, state->ExtReg[d*2 + i]);
614 i++;
615 if (i < regs*2)
616 return ARMul_INC;
617 else
618 return ARMul_DONE;
619 }
620 }
621
622 return -1;
623}
624int VSTM(ARMul_State* state, int type, ARMword instr, ARMword* value)
625{
626 static int i = 0;
627 static int single_regs, add, wback, d, n, imm32, regs;
628 if (type == ARMul_FIRST)
629 {
630 single_regs = BIT(8) == 0; /* Single precision */
631 add = BIT(23); /* */
632 wback = BIT(21); /* write-back */
633 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
634 n = BITS(16, 19); /* destination register */
635 imm32 = BITS(0,7) * 4; /* may not be used */
636 regs = single_regs ? BITS(0, 7) : BITS(0, 7)>>1; /* FSTMX if regs is odd */
637
638 DBG("VSTM :\n");
639
640 if (wback) {
641 state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
642 DBG("\twback r%d[%x]\n", n, state->Reg[n]);
643 }
644
645 i = 0;
646
647 return ARMul_DONE;
648 }
649 else if (type == ARMul_DATA)
650 {
651 if (single_regs)
652 {
653 *value = state->ExtReg[d + i];
654 DBG("\taddr[?] <= s%d=[%x]\n", d+i, state->ExtReg[d + i]);
655 i++;
656 if (i < regs)
657 return ARMul_INC;
658 else
659 return ARMul_DONE;
660 }
661 else
662 {
663 /* FIXME Careful of endianness, may need to rework this */
664 *value = state->ExtReg[d*2 + i];
665 DBG("\taddr[?] <= s[%d]=[%x]\n", d*2 + i, state->ExtReg[d*2 + i]);
666 i++;
667 if (i < regs*2)
668 return ARMul_INC;
669 else
670 return ARMul_DONE;
671 }
672 }
673
674 return -1;
675}
329 676
330/* ----------- LDC ------------ */ 677/* ----------- LDC ------------ */
331#define VFP_LDC_IMPL 678int VPOP(ARMul_State* state, int type, ARMword instr, ARMword value)
332#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 679{
333#undef VFP_LDC_IMPL 680 static int i = 0;
681 static int single_regs, add, wback, d, n, imm32, regs;
682 if (type == ARMul_FIRST)
683 {
684 single_regs = BIT(8) == 0; /* Single precision */
685 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
686 imm32 = BITS(0,7)<<2; /* may not be used */
687 regs = single_regs ? BITS(0, 7) : BITS(1, 7); /* FLDMX if regs is odd */
334 688
689 DBG("VPOP :\n");
690 DBG("\tsp[%x]", state->Reg[R13]);
691 state->Reg[R13] = state->Reg[R13] + imm32;
692 DBG("=>[%x]\n", state->Reg[R13]);
693
694 i = 0;
695
696 return ARMul_DONE;
697 }
698 else if (type == ARMul_TRANSFER)
699 {
700 return ARMul_DONE;
701 }
702 else if (type == ARMul_DATA)
703 {
704 if (single_regs)
705 {
706 state->ExtReg[d + i] = value;
707 DBG("\ts%d <= [%x]\n", d + i, value);
708 i++;
709 if (i < regs)
710 return ARMul_INC;
711 else
712 return ARMul_DONE;
713 }
714 else
715 {
716 /* FIXME Careful of endianness, may need to rework this */
717 state->ExtReg[d*2 + i] = value;
718 DBG("\ts%d <= [%x]\n", d*2 + i, value);
719 i++;
720 if (i < regs*2)
721 return ARMul_INC;
722 else
723 return ARMul_DONE;
724 }
725 }
726
727 return -1;
728}
729int VLDR(ARMul_State* state, int type, ARMword instr, ARMword value)
730{
731 static int i = 0;
732 static int single_reg, add, d, n, imm32, regs;
733 if (type == ARMul_FIRST)
734 {
735 single_reg = BIT(8) == 0; /* Double precision */
736 add = BIT(23); /* */
737 imm32 = BITS(0,7)<<2; /* may not be used */
738 d = single_reg ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
739 n = BITS(16, 19); /* destination register */
740
741 DBG("VLDR :\n");
742
743 i = 0;
744 regs = 1;
745
746 return ARMul_DONE;
747 }
748 else if (type == ARMul_TRANSFER)
749 {
750 return ARMul_DONE;
751 }
752 else if (type == ARMul_DATA)
753 {
754 if (single_reg)
755 {
756 state->ExtReg[d+i] = value;
757 DBG("\ts%d <= [%x]\n", d+i, value);
758 i++;
759 if (i < regs)
760 return ARMul_INC;
761 else
762 return ARMul_DONE;
763 }
764 else
765 {
766 /* FIXME Careful of endianness, may need to rework this */
767 state->ExtReg[d*2+i] = value;
768 DBG("\ts[%d] <= [%x]\n", d*2+i, value);
769 i++;
770 if (i < regs*2)
771 return ARMul_INC;
772 else
773 return ARMul_DONE;
774 }
775 }
776
777 return -1;
778}
779int VLDM(ARMul_State* state, int type, ARMword instr, ARMword value)
780{
781 static int i = 0;
782 static int single_regs, add, wback, d, n, imm32, regs;
783 if (type == ARMul_FIRST)
784 {
785 single_regs = BIT(8) == 0; /* Single precision */
786 add = BIT(23); /* */
787 wback = BIT(21); /* write-back */
788 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
789 n = BITS(16, 19); /* destination register */
790 imm32 = BITS(0,7) * 4; /* may not be used */
791 regs = single_regs ? BITS(0, 7) : BITS(0, 7)>>1; /* FLDMX if regs is odd */
792
793 DBG("VLDM :\n");
794
795 if (wback) {
796 state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
797 DBG("\twback r%d[%x]\n", n, state->Reg[n]);
798 }
799
800 i = 0;
801
802 return ARMul_DONE;
803 }
804 else if (type == ARMul_DATA)
805 {
806 if (single_regs)
807 {
808 state->ExtReg[d + i] = value;
809 DBG("\ts%d <= [%x] addr[?]\n", d+i, state->ExtReg[d + i]);
810 i++;
811 if (i < regs)
812 return ARMul_INC;
813 else
814 return ARMul_DONE;
815 }
816 else
817 {
818 /* FIXME Careful of endianness, may need to rework this */
819 state->ExtReg[d*2 + i] = value;
820 DBG("\ts[%d] <= [%x] addr[?]\n", d*2 + i, state->ExtReg[d*2 + i]);
821 i++;
822 if (i < regs*2)
823 return ARMul_INC;
824 else
825 return ARMul_DONE;
826 }
827 }
828
829 return -1;
830}
335 831
336/* ----------- CDP ------------ */ 832/* ----------- CDP ------------ */
337#define VFP_CDP_IMPL 833void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm)
338#include "core/arm/skyeye_common/vfp/vfpinstr.cpp" 834{
339#undef VFP_CDP_IMPL 835 DBG("VMOV(I) :\n");
836
837 if (single)
838 {
839 DBG("\ts%d <= [%x]\n", d, imm);
840 state->ExtReg[d] = imm;
841 }
842 else
843 {
844 /* Check endian please */
845 DBG("\ts[%d-%d] <= [%x-%x]\n", d*2+1, d*2, imm, 0);
846 state->ExtReg[d*2+1] = imm;
847 state->ExtReg[d*2] = 0;
848 }
849}
850void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword m)
851{
852 DBG("VMOV(R) :\n");
853
854 if (single)
855 {
856 DBG("\ts%d <= s%d[%x]\n", d, m, state->ExtReg[m]);
857 state->ExtReg[d] = state->ExtReg[m];
858 }
859 else
860 {
861 /* Check endian please */
862 DBG("\ts[%d-%d] <= s[%d-%d][%x-%x]\n", d*2+1, d*2, m*2+1, m*2, state->ExtReg[m*2+1], state->ExtReg[m*2]);
863 state->ExtReg[d*2+1] = state->ExtReg[m*2+1];
864 state->ExtReg[d*2] = state->ExtReg[m*2];
865 }
866}
340 867
341/* Miscellaneous functions */ 868/* Miscellaneous functions */
342int32_t vfp_get_float(arm_core_t* state, unsigned int reg) 869int32_t vfp_get_float(arm_core_t* state, unsigned int reg)
@@ -366,8 +893,6 @@ void vfp_put_double(arm_core_t* state, uint64_t val, unsigned int reg)
366 state->ExtReg[reg*2+1] = (uint32_t) (val>>32); 893 state->ExtReg[reg*2+1] = (uint32_t) (val>>32);
367} 894}
368 895
369
370
371/* 896/*
372 * Process bitmask of exception conditions. (from vfpmodule.c) 897 * Process bitmask of exception conditions. (from vfpmodule.c)
373 */ 898 */
diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h
index 7256701f3..f9e8d521d 100644
--- a/src/core/arm/skyeye_common/vfp/vfp.h
+++ b/src/core/arm/skyeye_common/vfp/vfp.h
@@ -27,6 +27,12 @@
27 27
28#include "core/arm/skyeye_common/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */ 28#include "core/arm/skyeye_common/vfp/vfp_helper.h" /* for references to cdp SoftFloat functions */
29 29
30#define VFP_DEBUG_TRANSLATE DBG("in func %s, %x\n", __FUNCTION__, inst);
31#define VFP_DEBUG_UNIMPLEMENTED(x) printf("in func %s, " #x " unimplemented\n", __FUNCTION__); exit(-1);
32#define VFP_DEBUG_UNTESTED(x) printf("in func %s, " #x " untested\n", __FUNCTION__);
33#define CHECK_VFP_ENABLED
34#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]); //if (ret == -1) {printf("VFP CDP FAILURE %x\n", inst_cream->instr); exit(-1);}
35
30unsigned VFPInit (ARMul_State *state); 36unsigned VFPInit (ARMul_State *state);
31unsigned VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value); 37unsigned VFPMRC (ARMul_State * state, unsigned type, ARMword instr, ARMword * value);
32unsigned VFPMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value); 38unsigned VFPMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value);
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
index 45208fb13..27dc8a008 100644
--- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp
@@ -28,34 +28,19 @@
28/* ----------------------------------------------------------------------- */ 28/* ----------------------------------------------------------------------- */
29/* VMLA */ 29/* VMLA */
30/* cond 1110 0D00 Vn-- Vd-- 101X N0M0 Vm-- */ 30/* cond 1110 0D00 Vn-- Vd-- 101X N0M0 Vm-- */
31#define vfpinstr vmla
32#define vfpinstr_inst vmla_inst
33#define VFPLABEL_INST VMLA_INST
34#ifdef VFP_DECODE
35{"vmla", 4, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x0, 9, 11, 0x5, 4, 4, 0},
36#endif
37#ifdef VFP_DECODE_EXCLUSION
38{"vmla", 0, ARMVFP2, 0},
39#endif
40#ifdef VFP_INTERPRETER_TABLE
41INTERPRETER_TRANSLATE(vfpinstr),
42#endif
43#ifdef VFP_INTERPRETER_LABEL
44&&VFPLABEL_INST,
45#endif
46#ifdef VFP_INTERPRETER_STRUCT 31#ifdef VFP_INTERPRETER_STRUCT
47typedef struct _vmla_inst { 32typedef struct _vmla_inst {
48 unsigned int instr; 33 unsigned int instr;
49 unsigned int dp_operation; 34 unsigned int dp_operation;
50} vfpinstr_inst; 35} vmla_inst;
51#endif 36#endif
52#ifdef VFP_INTERPRETER_TRANS 37#ifdef VFP_INTERPRETER_TRANS
53ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 38ARM_INST_PTR INTERPRETER_TRANSLATE(vmla)(unsigned int inst, int index)
54{ 39{
55 VFP_DEBUG_TRANSLATE; 40 VFP_DEBUG_TRANSLATE;
56 41
57 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 42 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmla_inst));
58 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 43 vmla_inst *inst_cream = (vmla_inst *)inst_base->component;
59 44
60 inst_base->cond = BITS(inst, 28, 31); 45 inst_base->cond = BITS(inst, 28, 31);
61 inst_base->idx = index; 46 inst_base->idx = index;
@@ -69,15 +54,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
69} 54}
70#endif 55#endif
71#ifdef VFP_INTERPRETER_IMPL 56#ifdef VFP_INTERPRETER_IMPL
72VFPLABEL_INST: 57VMLA_INST:
73{ 58{
74 INC_ICOUNTER;
75 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 59 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
76 CHECK_VFP_ENABLED; 60 CHECK_VFP_ENABLED;
77 61
78 DBG("VMLA :\n"); 62 DBG("VMLA :\n");
79 63
80 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 64 vmla_inst *inst_cream = (vmla_inst *)inst_base->component;
81 65
82 int ret; 66 int ret;
83 67
@@ -89,22 +73,17 @@ VFPLABEL_INST:
89 CHECK_VFP_CDP_RET; 73 CHECK_VFP_CDP_RET;
90 } 74 }
91 cpu->Reg[15] += GET_INST_SIZE(cpu); 75 cpu->Reg[15] += GET_INST_SIZE(cpu);
92 INC_PC(sizeof(vfpinstr_inst)); 76 INC_PC(sizeof(vmla_inst));
93 FETCH_INST; 77 FETCH_INST;
94 GOTO_NEXT_INST; 78 GOTO_NEXT_INST;
95} 79}
96#endif 80#endif
97#ifdef VFP_CDP_TRANS 81
98if ((OPC_1 & 0xB) == 0 && (OPC_2 & 0x2) == 0)
99{
100 DBG("VMLA :\n");
101}
102#endif
103#ifdef VFP_DYNCOM_TABLE 82#ifdef VFP_DYNCOM_TABLE
104DYNCOM_FILL_ACTION(vfpinstr), 83DYNCOM_FILL_ACTION(vmla),
105#endif 84#endif
106#ifdef VFP_DYNCOM_TAG 85#ifdef VFP_DYNCOM_TAG
107int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 86int DYNCOM_TAG(vmla)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
108{ 87{
109 int instr_size = INSTR_SIZE; 88 int instr_size = INSTR_SIZE;
110 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 89 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -114,7 +93,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
114} 93}
115#endif 94#endif
116#ifdef VFP_DYNCOM_TRANS 95#ifdef VFP_DYNCOM_TRANS
117int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 96int DYNCOM_TRANS(vmla)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
118 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 97 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
119 //arch_arm_undef(cpu, bb, instr); 98 //arch_arm_undef(cpu, bb, instr);
120 int m; 99 int m;
@@ -168,41 +147,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
168 return No_exp; 147 return No_exp;
169} 148}
170#endif 149#endif
171#undef vfpinstr
172#undef vfpinstr_inst
173#undef VFPLABEL_INST
174 150
175/* ----------------------------------------------------------------------- */ 151/* ----------------------------------------------------------------------- */
176/* VNMLS */ 152/* VNMLS */
177/* cond 1110 0D00 Vn-- Vd-- 101X N1M0 Vm-- */ 153/* cond 1110 0D00 Vn-- Vd-- 101X N1M0 Vm-- */
178#define vfpinstr vmls
179#define vfpinstr_inst vmls_inst
180#define VFPLABEL_INST VMLS_INST
181#ifdef VFP_DECODE
182{"vmls", 7, ARMVFP2, 28 , 31, 0xF, 25, 27, 0x1, 23, 23, 1, 11, 11, 0, 8, 9, 0x2, 6, 6, 1, 4, 4, 0},
183#endif
184#ifdef VFP_DECODE_EXCLUSION
185{"vmls", 0, ARMVFP2, 0},
186#endif
187#ifdef VFP_INTERPRETER_TABLE
188INTERPRETER_TRANSLATE(vfpinstr),
189#endif
190#ifdef VFP_INTERPRETER_LABEL
191&&VFPLABEL_INST,
192#endif
193#ifdef VFP_INTERPRETER_STRUCT 154#ifdef VFP_INTERPRETER_STRUCT
194typedef struct _vmls_inst { 155typedef struct _vmls_inst {
195 unsigned int instr; 156 unsigned int instr;
196 unsigned int dp_operation; 157 unsigned int dp_operation;
197} vfpinstr_inst; 158} vmls_inst;
198#endif 159#endif
199#ifdef VFP_INTERPRETER_TRANS 160#ifdef VFP_INTERPRETER_TRANS
200ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 161ARM_INST_PTR INTERPRETER_TRANSLATE(vmls)(unsigned int inst, int index)
201{ 162{
202 VFP_DEBUG_TRANSLATE; 163 VFP_DEBUG_TRANSLATE;
203 164
204 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 165 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmls_inst));
205 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 166 vmls_inst *inst_cream = (vmls_inst *)inst_base->component;
206 167
207 inst_base->cond = BITS(inst, 28, 31); 168 inst_base->cond = BITS(inst, 28, 31);
208 inst_base->idx = index; 169 inst_base->idx = index;
@@ -216,15 +177,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
216} 177}
217#endif 178#endif
218#ifdef VFP_INTERPRETER_IMPL 179#ifdef VFP_INTERPRETER_IMPL
219VFPLABEL_INST: 180VMLS_INST:
220{ 181{
221 INC_ICOUNTER;
222 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 182 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
223 CHECK_VFP_ENABLED; 183 CHECK_VFP_ENABLED;
224 184
225 DBG("VMLS :\n"); 185 DBG("VMLS :\n");
226 186
227 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 187 vmls_inst *inst_cream = (vmls_inst *)inst_base->component;
228 188
229 int ret; 189 int ret;
230 190
@@ -236,22 +196,17 @@ VFPLABEL_INST:
236 CHECK_VFP_CDP_RET; 196 CHECK_VFP_CDP_RET;
237 } 197 }
238 cpu->Reg[15] += GET_INST_SIZE(cpu); 198 cpu->Reg[15] += GET_INST_SIZE(cpu);
239 INC_PC(sizeof(vfpinstr_inst)); 199 INC_PC(sizeof(vmls_inst));
240 FETCH_INST; 200 FETCH_INST;
241 GOTO_NEXT_INST; 201 GOTO_NEXT_INST;
242} 202}
243#endif 203#endif
244#ifdef VFP_CDP_TRANS 204
245if ((OPC_1 & 0xB) == 0 && (OPC_2 & 0x2) == 2)
246{
247 DBG("VMLS :\n");
248}
249#endif
250#ifdef VFP_DYNCOM_TABLE 205#ifdef VFP_DYNCOM_TABLE
251DYNCOM_FILL_ACTION(vfpinstr), 206DYNCOM_FILL_ACTION(vmls),
252#endif 207#endif
253#ifdef VFP_DYNCOM_TAG 208#ifdef VFP_DYNCOM_TAG
254int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 209int DYNCOM_TAG(vmls)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
255{ 210{
256 int instr_size = INSTR_SIZE; 211 int instr_size = INSTR_SIZE;
257 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 212 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -261,7 +216,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
261} 216}
262#endif 217#endif
263#ifdef VFP_DYNCOM_TRANS 218#ifdef VFP_DYNCOM_TRANS
264int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 219int DYNCOM_TRANS(vmls)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
265 DBG("\t\tin %s VMLS instruction is executed out of here.\n", __FUNCTION__); 220 DBG("\t\tin %s VMLS instruction is executed out of here.\n", __FUNCTION__);
266 //arch_arm_undef(cpu, bb, instr); 221 //arch_arm_undef(cpu, bb, instr);
267 int m; 222 int m;
@@ -315,47 +270,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
315 return No_exp; 270 return No_exp;
316} 271}
317#endif 272#endif
318#undef vfpinstr
319#undef vfpinstr_inst
320#undef VFPLABEL_INST
321 273
322/* ----------------------------------------------------------------------- */ 274/* ----------------------------------------------------------------------- */
323/* VNMLA */ 275/* VNMLA */
324/* cond 1110 0D01 Vn-- Vd-- 101X N1M0 Vm-- */ 276/* cond 1110 0D01 Vn-- Vd-- 101X N1M0 Vm-- */
325#define vfpinstr vnmla
326#define vfpinstr_inst vnmla_inst
327#define VFPLABEL_INST VNMLA_INST
328#ifdef VFP_DECODE
329//{"vnmla", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
330{"vnmla", 4, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x1, 9, 11, 0x5, 4, 4, 0},
331{"vnmla", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
332//{"vnmla", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
333#endif
334#ifdef VFP_DECODE_EXCLUSION
335{"vnmla", 0, ARMVFP2, 0},
336{"vnmla", 0, ARMVFP2, 0},
337#endif
338#ifdef VFP_INTERPRETER_TABLE
339INTERPRETER_TRANSLATE(vfpinstr),
340INTERPRETER_TRANSLATE(vfpinstr),
341#endif
342#ifdef VFP_INTERPRETER_LABEL
343&&VFPLABEL_INST,
344&&VFPLABEL_INST,
345#endif
346#ifdef VFP_INTERPRETER_STRUCT 277#ifdef VFP_INTERPRETER_STRUCT
347typedef struct _vnmla_inst { 278typedef struct _vnmla_inst {
348 unsigned int instr; 279 unsigned int instr;
349 unsigned int dp_operation; 280 unsigned int dp_operation;
350} vfpinstr_inst; 281} vnmla_inst;
351#endif 282#endif
352#ifdef VFP_INTERPRETER_TRANS 283#ifdef VFP_INTERPRETER_TRANS
353ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 284ARM_INST_PTR INTERPRETER_TRANSLATE(vnmla)(unsigned int inst, int index)
354{ 285{
355 VFP_DEBUG_TRANSLATE; 286 VFP_DEBUG_TRANSLATE;
356 287
357 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 288 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmla_inst));
358 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 289 vnmla_inst *inst_cream = (vnmla_inst *)inst_base->component;
359 290
360 inst_base->cond = BITS(inst, 28, 31); 291 inst_base->cond = BITS(inst, 28, 31);
361 inst_base->idx = index; 292 inst_base->idx = index;
@@ -369,15 +300,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
369} 300}
370#endif 301#endif
371#ifdef VFP_INTERPRETER_IMPL 302#ifdef VFP_INTERPRETER_IMPL
372VFPLABEL_INST: 303VNMLA_INST:
373{ 304{
374 INC_ICOUNTER;
375 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 305 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
376 CHECK_VFP_ENABLED; 306 CHECK_VFP_ENABLED;
377 307
378 DBG("VNMLA :\n"); 308 DBG("VNMLA :\n");
379 309
380 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 310 vnmla_inst *inst_cream = (vnmla_inst *)inst_base->component;
381 311
382 int ret; 312 int ret;
383 313
@@ -389,23 +319,18 @@ VFPLABEL_INST:
389 CHECK_VFP_CDP_RET; 319 CHECK_VFP_CDP_RET;
390 } 320 }
391 cpu->Reg[15] += GET_INST_SIZE(cpu); 321 cpu->Reg[15] += GET_INST_SIZE(cpu);
392 INC_PC(sizeof(vfpinstr_inst)); 322 INC_PC(sizeof(vnmla_inst));
393 FETCH_INST; 323 FETCH_INST;
394 GOTO_NEXT_INST; 324 GOTO_NEXT_INST;
395} 325}
396#endif 326#endif
397#ifdef VFP_CDP_TRANS 327
398if ((OPC_1 & 0xB) == 1 && (OPC_2 & 0x2) == 2)
399{
400 DBG("VNMLA :\n");
401}
402#endif
403#ifdef VFP_DYNCOM_TABLE 328#ifdef VFP_DYNCOM_TABLE
404DYNCOM_FILL_ACTION(vfpinstr), 329DYNCOM_FILL_ACTION(vnmla),
405DYNCOM_FILL_ACTION(vfpinstr), 330DYNCOM_FILL_ACTION(vnmla),
406#endif 331#endif
407#ifdef VFP_DYNCOM_TAG 332#ifdef VFP_DYNCOM_TAG
408int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 333int DYNCOM_TAG(vnmla)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
409{ 334{
410 int instr_size = INSTR_SIZE; 335 int instr_size = INSTR_SIZE;
411 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 336 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -415,7 +340,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
415} 340}
416#endif 341#endif
417#ifdef VFP_DYNCOM_TRANS 342#ifdef VFP_DYNCOM_TRANS
418int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 343int DYNCOM_TRANS(vnmla)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
419 DBG("\t\tin %s VNMLA instruction is executed out of here.\n", __FUNCTION__); 344 DBG("\t\tin %s VNMLA instruction is executed out of here.\n", __FUNCTION__);
420 //arch_arm_undef(cpu, bb, instr); 345 //arch_arm_undef(cpu, bb, instr);
421 int m; 346 int m;
@@ -469,41 +394,24 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
469 return No_exp; 394 return No_exp;
470} 395}
471#endif 396#endif
472#undef vfpinstr
473#undef vfpinstr_inst
474#undef VFPLABEL_INST
475 397
476/* ----------------------------------------------------------------------- */ 398/* ----------------------------------------------------------------------- */
477/* VNMLS */ 399/* VNMLS */
478/* cond 1110 0D01 Vn-- Vd-- 101X N0M0 Vm-- */ 400/* cond 1110 0D01 Vn-- Vd-- 101X N0M0 Vm-- */
479#define vfpinstr vnmls 401
480#define vfpinstr_inst vnmls_inst
481#define VFPLABEL_INST VNMLS_INST
482#ifdef VFP_DECODE
483{"vnmls", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x1, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
484#endif
485#ifdef VFP_DECODE_EXCLUSION
486{"vnmls", 0, ARMVFP2, 0},
487#endif
488#ifdef VFP_INTERPRETER_TABLE
489INTERPRETER_TRANSLATE(vfpinstr),
490#endif
491#ifdef VFP_INTERPRETER_LABEL
492&&VFPLABEL_INST,
493#endif
494#ifdef VFP_INTERPRETER_STRUCT 402#ifdef VFP_INTERPRETER_STRUCT
495typedef struct _vnmls_inst { 403typedef struct _vnmls_inst {
496 unsigned int instr; 404 unsigned int instr;
497 unsigned int dp_operation; 405 unsigned int dp_operation;
498} vfpinstr_inst; 406} vnmls_inst;
499#endif 407#endif
500#ifdef VFP_INTERPRETER_TRANS 408#ifdef VFP_INTERPRETER_TRANS
501ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 409ARM_INST_PTR INTERPRETER_TRANSLATE(vnmls)(unsigned int inst, int index)
502{ 410{
503 VFP_DEBUG_TRANSLATE; 411 VFP_DEBUG_TRANSLATE;
504 412
505 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 413 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmls_inst));
506 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 414 vnmls_inst *inst_cream = (vnmls_inst *)inst_base->component;
507 415
508 inst_base->cond = BITS(inst, 28, 31); 416 inst_base->cond = BITS(inst, 28, 31);
509 inst_base->idx = index; 417 inst_base->idx = index;
@@ -517,15 +425,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
517} 425}
518#endif 426#endif
519#ifdef VFP_INTERPRETER_IMPL 427#ifdef VFP_INTERPRETER_IMPL
520VFPLABEL_INST: 428VNMLS_INST:
521{ 429{
522 INC_ICOUNTER;
523 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 430 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
524 CHECK_VFP_ENABLED; 431 CHECK_VFP_ENABLED;
525 432
526 DBG("VNMLS :\n"); 433 DBG("VNMLS :\n");
527 434
528 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 435 vnmls_inst *inst_cream = (vnmls_inst *)inst_base->component;
529 436
530 int ret; 437 int ret;
531 438
@@ -537,22 +444,17 @@ VFPLABEL_INST:
537 CHECK_VFP_CDP_RET; 444 CHECK_VFP_CDP_RET;
538 } 445 }
539 cpu->Reg[15] += GET_INST_SIZE(cpu); 446 cpu->Reg[15] += GET_INST_SIZE(cpu);
540 INC_PC(sizeof(vfpinstr_inst)); 447 INC_PC(sizeof(vnmls_inst));
541 FETCH_INST; 448 FETCH_INST;
542 GOTO_NEXT_INST; 449 GOTO_NEXT_INST;
543} 450}
544#endif 451#endif
545#ifdef VFP_CDP_TRANS 452
546if ((OPC_1 & 0xB) == 1 && (OPC_2 & 0x2) == 0)
547{
548 DBG("VNMLS :\n");
549}
550#endif
551#ifdef VFP_DYNCOM_TABLE 453#ifdef VFP_DYNCOM_TABLE
552DYNCOM_FILL_ACTION(vfpinstr), 454DYNCOM_FILL_ACTION(vnmls),
553#endif 455#endif
554#ifdef VFP_DYNCOM_TAG 456#ifdef VFP_DYNCOM_TAG
555int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 457int DYNCOM_TAG(vnmls)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
556{ 458{
557 int instr_size = INSTR_SIZE; 459 int instr_size = INSTR_SIZE;
558 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 460 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -562,7 +464,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
562} 464}
563#endif 465#endif
564#ifdef VFP_DYNCOM_TRANS 466#ifdef VFP_DYNCOM_TRANS
565int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 467int DYNCOM_TRANS(vnmls)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
566 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 468 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
567 //arch_arm_undef(cpu, bb, instr); 469 //arch_arm_undef(cpu, bb, instr);
568 int m; 470 int m;
@@ -616,41 +518,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
616 return No_exp; 518 return No_exp;
617} 519}
618#endif 520#endif
619#undef vfpinstr
620#undef vfpinstr_inst
621#undef VFPLABEL_INST
622 521
623/* ----------------------------------------------------------------------- */ 522/* ----------------------------------------------------------------------- */
624/* VNMUL */ 523/* VNMUL */
625/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */ 524/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */
626#define vfpinstr vnmul
627#define vfpinstr_inst vnmul_inst
628#define VFPLABEL_INST VNMUL_INST
629#ifdef VFP_DECODE
630{"vnmul", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
631#endif
632#ifdef VFP_DECODE_EXCLUSION
633{"vnmul", 0, ARMVFP2, 0},
634#endif
635#ifdef VFP_INTERPRETER_TABLE
636INTERPRETER_TRANSLATE(vfpinstr),
637#endif
638#ifdef VFP_INTERPRETER_LABEL
639&&VFPLABEL_INST,
640#endif
641#ifdef VFP_INTERPRETER_STRUCT 525#ifdef VFP_INTERPRETER_STRUCT
642typedef struct _vnmul_inst { 526typedef struct _vnmul_inst {
643 unsigned int instr; 527 unsigned int instr;
644 unsigned int dp_operation; 528 unsigned int dp_operation;
645} vfpinstr_inst; 529} vnmul_inst;
646#endif 530#endif
647#ifdef VFP_INTERPRETER_TRANS 531#ifdef VFP_INTERPRETER_TRANS
648ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 532ARM_INST_PTR INTERPRETER_TRANSLATE(vnmul)(unsigned int inst, int index)
649{ 533{
650 VFP_DEBUG_TRANSLATE; 534 VFP_DEBUG_TRANSLATE;
651 535
652 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 536 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vnmul_inst));
653 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 537 vnmul_inst *inst_cream = (vnmul_inst *)inst_base->component;
654 538
655 inst_base->cond = BITS(inst, 28, 31); 539 inst_base->cond = BITS(inst, 28, 31);
656 inst_base->idx = index; 540 inst_base->idx = index;
@@ -664,15 +548,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
664} 548}
665#endif 549#endif
666#ifdef VFP_INTERPRETER_IMPL 550#ifdef VFP_INTERPRETER_IMPL
667VFPLABEL_INST: 551VNMUL_INST:
668{ 552{
669 INC_ICOUNTER;
670 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 553 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
671 CHECK_VFP_ENABLED; 554 CHECK_VFP_ENABLED;
672 555
673 DBG("VNMUL :\n"); 556 DBG("VNMUL :\n");
674 557
675 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 558 vnmul_inst *inst_cream = (vnmul_inst *)inst_base->component;
676 559
677 int ret; 560 int ret;
678 561
@@ -684,22 +567,17 @@ VFPLABEL_INST:
684 CHECK_VFP_CDP_RET; 567 CHECK_VFP_CDP_RET;
685 } 568 }
686 cpu->Reg[15] += GET_INST_SIZE(cpu); 569 cpu->Reg[15] += GET_INST_SIZE(cpu);
687 INC_PC(sizeof(vfpinstr_inst)); 570 INC_PC(sizeof(vnmul_inst));
688 FETCH_INST; 571 FETCH_INST;
689 GOTO_NEXT_INST; 572 GOTO_NEXT_INST;
690} 573}
691#endif 574#endif
692#ifdef VFP_CDP_TRANS 575
693if ((OPC_1 & 0xB) == 2 && (OPC_2 & 0x2) == 2)
694{
695 DBG("VNMUL :\n");
696}
697#endif
698#ifdef VFP_DYNCOM_TABLE 576#ifdef VFP_DYNCOM_TABLE
699DYNCOM_FILL_ACTION(vfpinstr), 577DYNCOM_FILL_ACTION(vnmul),
700#endif 578#endif
701#ifdef VFP_DYNCOM_TAG 579#ifdef VFP_DYNCOM_TAG
702int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 580int DYNCOM_TAG(vnmul)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
703{ 581{
704 int instr_size = INSTR_SIZE; 582 int instr_size = INSTR_SIZE;
705 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 583 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -709,7 +587,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
709} 587}
710#endif 588#endif
711#ifdef VFP_DYNCOM_TRANS 589#ifdef VFP_DYNCOM_TRANS
712int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 590int DYNCOM_TRANS(vnmul)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
713 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 591 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
714 //arch_arm_undef(cpu, bb, instr); 592 //arch_arm_undef(cpu, bb, instr);
715 int m; 593 int m;
@@ -753,41 +631,24 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
753 return No_exp; 631 return No_exp;
754} 632}
755#endif 633#endif
756#undef vfpinstr 634
757#undef vfpinstr_inst
758#undef VFPLABEL_INST
759 635
760/* ----------------------------------------------------------------------- */ 636/* ----------------------------------------------------------------------- */
761/* VMUL */ 637/* VMUL */
762/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */ 638/* cond 1110 0D10 Vn-- Vd-- 101X N0M0 Vm-- */
763#define vfpinstr vmul
764#define vfpinstr_inst vmul_inst
765#define VFPLABEL_INST VMUL_INST
766#ifdef VFP_DECODE
767{"vmul", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x2, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
768#endif
769#ifdef VFP_DECODE_EXCLUSION
770{"vmul", 0, ARMVFP2, 0},
771#endif
772#ifdef VFP_INTERPRETER_TABLE
773INTERPRETER_TRANSLATE(vfpinstr),
774#endif
775#ifdef VFP_INTERPRETER_LABEL
776&&VFPLABEL_INST,
777#endif
778#ifdef VFP_INTERPRETER_STRUCT 639#ifdef VFP_INTERPRETER_STRUCT
779typedef struct _vmul_inst { 640typedef struct _vmul_inst {
780 unsigned int instr; 641 unsigned int instr;
781 unsigned int dp_operation; 642 unsigned int dp_operation;
782} vfpinstr_inst; 643} vmul_inst;
783#endif 644#endif
784#ifdef VFP_INTERPRETER_TRANS 645#ifdef VFP_INTERPRETER_TRANS
785ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 646ARM_INST_PTR INTERPRETER_TRANSLATE(vmul)(unsigned int inst, int index)
786{ 647{
787 VFP_DEBUG_TRANSLATE; 648 VFP_DEBUG_TRANSLATE;
788 649
789 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 650 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmul_inst));
790 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 651 vmul_inst *inst_cream = (vmul_inst *)inst_base->component;
791 652
792 inst_base->cond = BITS(inst, 28, 31); 653 inst_base->cond = BITS(inst, 28, 31);
793 inst_base->idx = index; 654 inst_base->idx = index;
@@ -801,15 +662,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
801} 662}
802#endif 663#endif
803#ifdef VFP_INTERPRETER_IMPL 664#ifdef VFP_INTERPRETER_IMPL
804VFPLABEL_INST: 665VMUL_INST:
805{ 666{
806 INC_ICOUNTER;
807 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 667 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
808 CHECK_VFP_ENABLED; 668 CHECK_VFP_ENABLED;
809 669
810 DBG("VMUL :\n"); 670 DBG("VMUL :\n");
811 671
812 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 672 vmul_inst *inst_cream = (vmul_inst *)inst_base->component;
813 673
814 int ret; 674 int ret;
815 675
@@ -821,22 +681,17 @@ VFPLABEL_INST:
821 CHECK_VFP_CDP_RET; 681 CHECK_VFP_CDP_RET;
822 } 682 }
823 cpu->Reg[15] += GET_INST_SIZE(cpu); 683 cpu->Reg[15] += GET_INST_SIZE(cpu);
824 INC_PC(sizeof(vfpinstr_inst)); 684 INC_PC(sizeof(vmul_inst));
825 FETCH_INST; 685 FETCH_INST;
826 GOTO_NEXT_INST; 686 GOTO_NEXT_INST;
827} 687}
828#endif 688#endif
829#ifdef VFP_CDP_TRANS 689
830if ((OPC_1 & 0xB) == 2 && (OPC_2 & 0x2) == 0)
831{
832 DBG("VMUL :\n");
833}
834#endif
835#ifdef VFP_DYNCOM_TABLE 690#ifdef VFP_DYNCOM_TABLE
836DYNCOM_FILL_ACTION(vfpinstr), 691DYNCOM_FILL_ACTION(vmul),
837#endif 692#endif
838#ifdef VFP_DYNCOM_TAG 693#ifdef VFP_DYNCOM_TAG
839int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 694int DYNCOM_TAG(vmul)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
840{ 695{
841 int instr_size = INSTR_SIZE; 696 int instr_size = INSTR_SIZE;
842 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 697 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -846,7 +701,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
846} 701}
847#endif 702#endif
848#ifdef VFP_DYNCOM_TRANS 703#ifdef VFP_DYNCOM_TRANS
849int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 704int DYNCOM_TRANS(vmul)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
850 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 705 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
851 //printf("\n\n\t\tin %s instruction is executed out.\n\n", __FUNCTION__); 706 //printf("\n\n\t\tin %s instruction is executed out.\n\n", __FUNCTION__);
852 //arch_arm_undef(cpu, bb, instr); 707 //arch_arm_undef(cpu, bb, instr);
@@ -904,41 +759,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
904 return No_exp; 759 return No_exp;
905} 760}
906#endif 761#endif
907#undef vfpinstr
908#undef vfpinstr_inst
909#undef VFPLABEL_INST
910 762
911/* ----------------------------------------------------------------------- */ 763/* ----------------------------------------------------------------------- */
912/* VADD */ 764/* VADD */
913/* cond 1110 0D11 Vn-- Vd-- 101X N0M0 Vm-- */ 765/* cond 1110 0D11 Vn-- Vd-- 101X N0M0 Vm-- */
914#define vfpinstr vadd
915#define vfpinstr_inst vadd_inst
916#define VFPLABEL_INST VADD_INST
917#ifdef VFP_DECODE
918{"vadd", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
919#endif
920#ifdef VFP_DECODE_EXCLUSION
921{"vadd", 0, ARMVFP2, 0},
922#endif
923#ifdef VFP_INTERPRETER_TABLE
924INTERPRETER_TRANSLATE(vfpinstr),
925#endif
926#ifdef VFP_INTERPRETER_LABEL
927&&VFPLABEL_INST,
928#endif
929#ifdef VFP_INTERPRETER_STRUCT 766#ifdef VFP_INTERPRETER_STRUCT
930typedef struct _vadd_inst { 767typedef struct _vadd_inst {
931 unsigned int instr; 768 unsigned int instr;
932 unsigned int dp_operation; 769 unsigned int dp_operation;
933} vfpinstr_inst; 770} vadd_inst;
934#endif 771#endif
935#ifdef VFP_INTERPRETER_TRANS 772#ifdef VFP_INTERPRETER_TRANS
936ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 773ARM_INST_PTR INTERPRETER_TRANSLATE(vadd)(unsigned int inst, int index)
937{ 774{
938 VFP_DEBUG_TRANSLATE; 775 VFP_DEBUG_TRANSLATE;
939 776
940 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 777 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vadd_inst));
941 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 778 vadd_inst *inst_cream = (vadd_inst *)inst_base->component;
942 779
943 inst_base->cond = BITS(inst, 28, 31); 780 inst_base->cond = BITS(inst, 28, 31);
944 inst_base->idx = index; 781 inst_base->idx = index;
@@ -952,15 +789,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
952} 789}
953#endif 790#endif
954#ifdef VFP_INTERPRETER_IMPL 791#ifdef VFP_INTERPRETER_IMPL
955VFPLABEL_INST: 792VADD_INST:
956{ 793{
957 INC_ICOUNTER;
958 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 794 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
959 CHECK_VFP_ENABLED; 795 CHECK_VFP_ENABLED;
960 796
961 DBG("VADD :\n"); 797 DBG("VADD :\n");
962 798
963 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 799 vadd_inst *inst_cream = (vadd_inst *)inst_base->component;
964 800
965 int ret; 801 int ret;
966 802
@@ -972,22 +808,17 @@ VFPLABEL_INST:
972 CHECK_VFP_CDP_RET; 808 CHECK_VFP_CDP_RET;
973 } 809 }
974 cpu->Reg[15] += GET_INST_SIZE(cpu); 810 cpu->Reg[15] += GET_INST_SIZE(cpu);
975 INC_PC(sizeof(vfpinstr_inst)); 811 INC_PC(sizeof(vadd_inst));
976 FETCH_INST; 812 FETCH_INST;
977 GOTO_NEXT_INST; 813 GOTO_NEXT_INST;
978} 814}
979#endif 815#endif
980#ifdef VFP_CDP_TRANS 816
981if ((OPC_1 & 0xB) == 3 && (OPC_2 & 0x2) == 0)
982{
983 DBG("VADD :\n");
984}
985#endif
986#ifdef VFP_DYNCOM_TABLE 817#ifdef VFP_DYNCOM_TABLE
987DYNCOM_FILL_ACTION(vfpinstr), 818DYNCOM_FILL_ACTION(vadd),
988#endif 819#endif
989#ifdef VFP_DYNCOM_TAG 820#ifdef VFP_DYNCOM_TAG
990int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 821int DYNCOM_TAG(vadd)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
991{ 822{
992 int instr_size = INSTR_SIZE; 823 int instr_size = INSTR_SIZE;
993 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 824 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -997,7 +828,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
997} 828}
998#endif 829#endif
999#ifdef VFP_DYNCOM_TRANS 830#ifdef VFP_DYNCOM_TRANS
1000int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 831int DYNCOM_TRANS(vadd)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1001 DBG("\t\tin %s instruction will implement out of JIT.\n", __FUNCTION__); 832 DBG("\t\tin %s instruction will implement out of JIT.\n", __FUNCTION__);
1002 //arch_arm_undef(cpu, bb, instr); 833 //arch_arm_undef(cpu, bb, instr);
1003 int m; 834 int m;
@@ -1049,41 +880,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1049 return No_exp; 880 return No_exp;
1050} 881}
1051#endif 882#endif
1052#undef vfpinstr
1053#undef vfpinstr_inst
1054#undef VFPLABEL_INST
1055 883
1056/* ----------------------------------------------------------------------- */ 884/* ----------------------------------------------------------------------- */
1057/* VSUB */ 885/* VSUB */
1058/* cond 1110 0D11 Vn-- Vd-- 101X N1M0 Vm-- */ 886/* cond 1110 0D11 Vn-- Vd-- 101X N1M0 Vm-- */
1059#define vfpinstr vsub
1060#define vfpinstr_inst vsub_inst
1061#define VFPLABEL_INST VSUB_INST
1062#ifdef VFP_DECODE
1063{"vsub", 5, ARMVFP2, 23, 27, 0x1c, 20, 21, 0x3, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
1064#endif
1065#ifdef VFP_DECODE_EXCLUSION
1066{"vsub", 0, ARMVFP2, 0},
1067#endif
1068#ifdef VFP_INTERPRETER_TABLE
1069INTERPRETER_TRANSLATE(vfpinstr),
1070#endif
1071#ifdef VFP_INTERPRETER_LABEL
1072&&VFPLABEL_INST,
1073#endif
1074#ifdef VFP_INTERPRETER_STRUCT 887#ifdef VFP_INTERPRETER_STRUCT
1075typedef struct _vsub_inst { 888typedef struct _vsub_inst {
1076 unsigned int instr; 889 unsigned int instr;
1077 unsigned int dp_operation; 890 unsigned int dp_operation;
1078} vfpinstr_inst; 891} vsub_inst;
1079#endif 892#endif
1080#ifdef VFP_INTERPRETER_TRANS 893#ifdef VFP_INTERPRETER_TRANS
1081ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 894ARM_INST_PTR INTERPRETER_TRANSLATE(vsub)(unsigned int inst, int index)
1082{ 895{
1083 VFP_DEBUG_TRANSLATE; 896 VFP_DEBUG_TRANSLATE;
1084 897
1085 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 898 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vsub_inst));
1086 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 899 vsub_inst *inst_cream = (vsub_inst *)inst_base->component;
1087 900
1088 inst_base->cond = BITS(inst, 28, 31); 901 inst_base->cond = BITS(inst, 28, 31);
1089 inst_base->idx = index; 902 inst_base->idx = index;
@@ -1097,15 +910,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1097} 910}
1098#endif 911#endif
1099#ifdef VFP_INTERPRETER_IMPL 912#ifdef VFP_INTERPRETER_IMPL
1100VFPLABEL_INST: 913VSUB_INST:
1101{ 914{
1102 INC_ICOUNTER;
1103 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 915 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1104 CHECK_VFP_ENABLED; 916 CHECK_VFP_ENABLED;
1105 917
1106 DBG("VSUB :\n"); 918 DBG("VSUB :\n");
1107 919
1108 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 920 vsub_inst *inst_cream = (vsub_inst *)inst_base->component;
1109 921
1110 int ret; 922 int ret;
1111 923
@@ -1117,22 +929,16 @@ VFPLABEL_INST:
1117 CHECK_VFP_CDP_RET; 929 CHECK_VFP_CDP_RET;
1118 } 930 }
1119 cpu->Reg[15] += GET_INST_SIZE(cpu); 931 cpu->Reg[15] += GET_INST_SIZE(cpu);
1120 INC_PC(sizeof(vfpinstr_inst)); 932 INC_PC(sizeof(vsub_inst));
1121 FETCH_INST; 933 FETCH_INST;
1122 GOTO_NEXT_INST; 934 GOTO_NEXT_INST;
1123} 935}
1124#endif 936#endif
1125#ifdef VFP_CDP_TRANS
1126if ((OPC_1 & 0xB) == 3 && (OPC_2 & 0x2) == 2)
1127{
1128 DBG("VSUB :\n");
1129}
1130#endif
1131#ifdef VFP_DYNCOM_TABLE 937#ifdef VFP_DYNCOM_TABLE
1132DYNCOM_FILL_ACTION(vfpinstr), 938DYNCOM_FILL_ACTION(vsub),
1133#endif 939#endif
1134#ifdef VFP_DYNCOM_TAG 940#ifdef VFP_DYNCOM_TAG
1135int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 941int DYNCOM_TAG(vsub)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1136{ 942{
1137 int instr_size = INSTR_SIZE; 943 int instr_size = INSTR_SIZE;
1138 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc); 944 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
@@ -1141,7 +947,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
1141} 947}
1142#endif 948#endif
1143#ifdef VFP_DYNCOM_TRANS 949#ifdef VFP_DYNCOM_TRANS
1144int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 950int DYNCOM_TRANS(vsub)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1145 DBG("\t\tin %s instr=0x%x, instruction is executed out of JIT.\n", __FUNCTION__, instr); 951 DBG("\t\tin %s instr=0x%x, instruction is executed out of JIT.\n", __FUNCTION__, instr);
1146 //arch_arm_undef(cpu, bb, instr); 952 //arch_arm_undef(cpu, bb, instr);
1147 int m; 953 int m;
@@ -1193,41 +999,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1193 return No_exp; 999 return No_exp;
1194} 1000}
1195#endif 1001#endif
1196#undef vfpinstr
1197#undef vfpinstr_inst
1198#undef VFPLABEL_INST
1199 1002
1200/* ----------------------------------------------------------------------- */ 1003/* ----------------------------------------------------------------------- */
1201/* VDIV */ 1004/* VDIV */
1202/* cond 1110 1D00 Vn-- Vd-- 101X N0M0 Vm-- */ 1005/* cond 1110 1D00 Vn-- Vd-- 101X N0M0 Vm-- */
1203#define vfpinstr vdiv
1204#define vfpinstr_inst vdiv_inst
1205#define VFPLABEL_INST VDIV_INST
1206#ifdef VFP_DECODE
1207{"vdiv", 5, ARMVFP2, 23, 27, 0x1d, 20, 21, 0x0, 9, 11, 0x5, 6, 6, 0, 4, 4, 0},
1208#endif
1209#ifdef VFP_DECODE_EXCLUSION
1210{"vdiv", 0, ARMVFP2, 0},
1211#endif
1212#ifdef VFP_INTERPRETER_TABLE
1213INTERPRETER_TRANSLATE(vfpinstr),
1214#endif
1215#ifdef VFP_INTERPRETER_LABEL
1216&&VFPLABEL_INST,
1217#endif
1218#ifdef VFP_INTERPRETER_STRUCT 1006#ifdef VFP_INTERPRETER_STRUCT
1219typedef struct _vdiv_inst { 1007typedef struct _vdiv_inst {
1220 unsigned int instr; 1008 unsigned int instr;
1221 unsigned int dp_operation; 1009 unsigned int dp_operation;
1222} vfpinstr_inst; 1010} vdiv_inst;
1223#endif 1011#endif
1224#ifdef VFP_INTERPRETER_TRANS 1012#ifdef VFP_INTERPRETER_TRANS
1225ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1013ARM_INST_PTR INTERPRETER_TRANSLATE(vdiv)(unsigned int inst, int index)
1226{ 1014{
1227 VFP_DEBUG_TRANSLATE; 1015 VFP_DEBUG_TRANSLATE;
1228 1016
1229 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1017 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vdiv_inst));
1230 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1018 vdiv_inst *inst_cream = (vdiv_inst *)inst_base->component;
1231 1019
1232 inst_base->cond = BITS(inst, 28, 31); 1020 inst_base->cond = BITS(inst, 28, 31);
1233 inst_base->idx = index; 1021 inst_base->idx = index;
@@ -1241,15 +1029,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1241} 1029}
1242#endif 1030#endif
1243#ifdef VFP_INTERPRETER_IMPL 1031#ifdef VFP_INTERPRETER_IMPL
1244VFPLABEL_INST: 1032VDIV_INST:
1245{ 1033{
1246 INC_ICOUNTER;
1247 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1034 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1248 CHECK_VFP_ENABLED; 1035 CHECK_VFP_ENABLED;
1249 1036
1250 DBG("VDIV :\n"); 1037 DBG("VDIV :\n");
1251 1038
1252 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1039 vdiv_inst *inst_cream = (vdiv_inst *)inst_base->component;
1253 1040
1254 int ret; 1041 int ret;
1255 1042
@@ -1261,22 +1048,17 @@ VFPLABEL_INST:
1261 CHECK_VFP_CDP_RET; 1048 CHECK_VFP_CDP_RET;
1262 } 1049 }
1263 cpu->Reg[15] += GET_INST_SIZE(cpu); 1050 cpu->Reg[15] += GET_INST_SIZE(cpu);
1264 INC_PC(sizeof(vfpinstr_inst)); 1051 INC_PC(sizeof(vdiv_inst));
1265 FETCH_INST; 1052 FETCH_INST;
1266 GOTO_NEXT_INST; 1053 GOTO_NEXT_INST;
1267} 1054}
1268#endif 1055#endif
1269#ifdef VFP_CDP_TRANS 1056
1270if ((OPC_1 & 0xB) == 0xA && (OPC_2 & 0x2) == 0)
1271{
1272 DBG("VDIV :\n");
1273}
1274#endif
1275#ifdef VFP_DYNCOM_TABLE 1057#ifdef VFP_DYNCOM_TABLE
1276DYNCOM_FILL_ACTION(vfpinstr), 1058DYNCOM_FILL_ACTION(vdiv),
1277#endif 1059#endif
1278#ifdef VFP_DYNCOM_TAG 1060#ifdef VFP_DYNCOM_TAG
1279int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 1061int DYNCOM_TAG(vdiv)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1280{ 1062{
1281 int instr_size = INSTR_SIZE; 1063 int instr_size = INSTR_SIZE;
1282 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1064 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -1286,7 +1068,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
1286} 1068}
1287#endif 1069#endif
1288#ifdef VFP_DYNCOM_TRANS 1070#ifdef VFP_DYNCOM_TRANS
1289int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1071int DYNCOM_TRANS(vdiv)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1290 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1072 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1291 //arch_arm_undef(cpu, bb, instr); 1073 //arch_arm_undef(cpu, bb, instr);
1292 int m; 1074 int m;
@@ -1338,43 +1120,25 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1338 return No_exp; 1120 return No_exp;
1339} 1121}
1340#endif 1122#endif
1341#undef vfpinstr
1342#undef vfpinstr_inst
1343#undef VFPLABEL_INST
1344 1123
1345/* ----------------------------------------------------------------------- */ 1124/* ----------------------------------------------------------------------- */
1346/* VMOVI move immediate */ 1125/* VMOVI move immediate */
1347/* cond 1110 1D11 im4H Vd-- 101X 0000 im4L */ 1126/* cond 1110 1D11 im4H Vd-- 101X 0000 im4L */
1348/* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */ 1127/* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */
1349#define vfpinstr vmovi
1350#define vfpinstr_inst vmovi_inst
1351#define VFPLABEL_INST VMOVI_INST
1352#ifdef VFP_DECODE
1353{"vmov(i)", 4, ARMVFP3, 23, 27, 0x1d, 20, 21, 0x3, 9, 11, 0x5, 4, 7, 0},
1354#endif
1355#ifdef VFP_DECODE_EXCLUSION
1356{"vmov(i)", 0, ARMVFP3, 0},
1357#endif
1358#ifdef VFP_INTERPRETER_TABLE
1359INTERPRETER_TRANSLATE(vfpinstr),
1360#endif
1361#ifdef VFP_INTERPRETER_LABEL
1362&&VFPLABEL_INST,
1363#endif
1364#ifdef VFP_INTERPRETER_STRUCT 1128#ifdef VFP_INTERPRETER_STRUCT
1365typedef struct _vmovi_inst { 1129typedef struct _vmovi_inst {
1366 unsigned int single; 1130 unsigned int single;
1367 unsigned int d; 1131 unsigned int d;
1368 unsigned int imm; 1132 unsigned int imm;
1369} vfpinstr_inst; 1133} vmovi_inst;
1370#endif 1134#endif
1371#ifdef VFP_INTERPRETER_TRANS 1135#ifdef VFP_INTERPRETER_TRANS
1372ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1136ARM_INST_PTR INTERPRETER_TRANSLATE(vmovi)(unsigned int inst, int index)
1373{ 1137{
1374 VFP_DEBUG_TRANSLATE; 1138 VFP_DEBUG_TRANSLATE;
1375 1139
1376 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1140 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovi_inst));
1377 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1141 vmovi_inst *inst_cream = (vmovi_inst *)inst_base->component;
1378 1142
1379 inst_base->cond = BITS(inst, 28, 31); 1143 inst_base->cond = BITS(inst, 28, 31);
1380 inst_base->idx = index; 1144 inst_base->idx = index;
@@ -1392,62 +1156,27 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1392} 1156}
1393#endif 1157#endif
1394#ifdef VFP_INTERPRETER_IMPL 1158#ifdef VFP_INTERPRETER_IMPL
1395VFPLABEL_INST: 1159VMOVI_INST:
1396{ 1160{
1397 INC_ICOUNTER;
1398 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1161 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1399 CHECK_VFP_ENABLED; 1162 CHECK_VFP_ENABLED;
1400 1163
1401 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1164 vmovi_inst *inst_cream = (vmovi_inst *)inst_base->component;
1402 1165
1403 VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm); 1166 VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm);
1404 } 1167 }
1405 cpu->Reg[15] += GET_INST_SIZE(cpu); 1168 cpu->Reg[15] += GET_INST_SIZE(cpu);
1406 INC_PC(sizeof(vfpinstr_inst)); 1169 INC_PC(sizeof(vmovi_inst));
1407 FETCH_INST; 1170 FETCH_INST;
1408 GOTO_NEXT_INST; 1171 GOTO_NEXT_INST;
1409} 1172}
1410#endif 1173#endif
1411#ifdef VFP_CDP_TRANS 1174
1412if ( (OPC_1 & 0xb) == 0xb && BITS(4, 7) == 0)
1413{
1414 unsigned int single = BIT(8) == 0;
1415 unsigned int d = (single ? BITS(12,15)<<1 | BIT(22) : BITS(12,15) | BIT(22)<<4);
1416 unsigned int imm;
1417 instr = BITS(16, 19) << 4 | BITS(0, 3); /* FIXME dirty workaround to get a correct imm */
1418 if (single) {
1419 imm = BIT(7)<<31 | (BIT(6)==0)<<30 | (BIT(6) ? 0x1f : 0)<<25 | BITS(0, 5)<<19;
1420 } else {
1421 imm = BIT(7)<<31 | (BIT(6)==0)<<30 | (BIT(6) ? 0xff : 0)<<22 | BITS(0, 5)<<16;
1422 }
1423 VMOVI(state, single, d, imm);
1424 return ARMul_DONE;
1425}
1426#endif
1427#ifdef VFP_CDP_IMPL
1428void VMOVI(ARMul_State * state, ARMword single, ARMword d, ARMword imm)
1429{
1430 DBG("VMOV(I) :\n");
1431
1432 if (single)
1433 {
1434 DBG("\ts%d <= [%x]\n", d, imm);
1435 state->ExtReg[d] = imm;
1436 }
1437 else
1438 {
1439 /* Check endian please */
1440 DBG("\ts[%d-%d] <= [%x-%x]\n", d*2+1, d*2, imm, 0);
1441 state->ExtReg[d*2+1] = imm;
1442 state->ExtReg[d*2] = 0;
1443 }
1444}
1445#endif
1446#ifdef VFP_DYNCOM_TABLE 1175#ifdef VFP_DYNCOM_TABLE
1447DYNCOM_FILL_ACTION(vfpinstr), 1176DYNCOM_FILL_ACTION(vmovi),
1448#endif 1177#endif
1449#ifdef VFP_DYNCOM_TAG 1178#ifdef VFP_DYNCOM_TAG
1450int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 1179int DYNCOM_TAG(vmovi)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1451{ 1180{
1452 int instr_size = INSTR_SIZE; 1181 int instr_size = INSTR_SIZE;
1453 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1182 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -1456,7 +1185,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
1456} 1185}
1457#endif 1186#endif
1458#ifdef VFP_DYNCOM_TRANS 1187#ifdef VFP_DYNCOM_TRANS
1459int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1188int DYNCOM_TRANS(vmovi)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1460 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1189 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1461 //arch_arm_undef(cpu, bb, instr); 1190 //arch_arm_undef(cpu, bb, instr);
1462 int single = (BIT(8) == 0); 1191 int single = (BIT(8) == 0);
@@ -1482,44 +1211,26 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1482 return No_exp; 1211 return No_exp;
1483} 1212}
1484#endif 1213#endif
1485#undef vfpinstr
1486#undef vfpinstr_inst
1487#undef VFPLABEL_INST
1488 1214
1489/* ----------------------------------------------------------------------- */ 1215/* ----------------------------------------------------------------------- */
1490/* VMOVR move register */ 1216/* VMOVR move register */
1491/* cond 1110 1D11 0000 Vd-- 101X 01M0 Vm-- */ 1217/* cond 1110 1D11 0000 Vd-- 101X 01M0 Vm-- */
1492/* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */ 1218/* cond 1110 opc1 CRn- CRd- copr op20 CRm- CDP */
1493#define vfpinstr vmovr
1494#define vfpinstr_inst vmovr_inst
1495#define VFPLABEL_INST VMOVR_INST
1496#ifdef VFP_DECODE
1497{"vmov(r)", 5, ARMVFP3, 23, 27, 0x1d, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 1, 4, 4, 0},
1498#endif
1499#ifdef VFP_DECODE_EXCLUSION
1500{"vmov(r)", 0, ARMVFP3, 0},
1501#endif
1502#ifdef VFP_INTERPRETER_TABLE
1503INTERPRETER_TRANSLATE(vfpinstr),
1504#endif
1505#ifdef VFP_INTERPRETER_LABEL
1506&&VFPLABEL_INST,
1507#endif
1508#ifdef VFP_INTERPRETER_STRUCT 1219#ifdef VFP_INTERPRETER_STRUCT
1509typedef struct _vmovr_inst { 1220typedef struct _vmovr_inst {
1510 unsigned int single; 1221 unsigned int single;
1511 unsigned int d; 1222 unsigned int d;
1512 unsigned int m; 1223 unsigned int m;
1513} vfpinstr_inst; 1224} vmovr_inst;
1514#endif 1225#endif
1515#ifdef VFP_INTERPRETER_TRANS 1226#ifdef VFP_INTERPRETER_TRANS
1516ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1227ARM_INST_PTR INTERPRETER_TRANSLATE(vmovr)(unsigned int inst, int index)
1517{ 1228{
1518 VFP_DEBUG_TRANSLATE; 1229 VFP_DEBUG_TRANSLATE;
1519 VFP_DEBUG_UNTESTED(VMOVR); 1230 VFP_DEBUG_UNTESTED(VMOVR);
1520 1231
1521 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1232 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovr_inst));
1522 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1233 vmovr_inst *inst_cream = (vmovr_inst *)inst_base->component;
1523 1234
1524 inst_base->cond = BITS(inst, 28, 31); 1235 inst_base->cond = BITS(inst, 28, 31);
1525 inst_base->idx = index; 1236 inst_base->idx = index;
@@ -1533,56 +1244,27 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1533} 1244}
1534#endif 1245#endif
1535#ifdef VFP_INTERPRETER_IMPL 1246#ifdef VFP_INTERPRETER_IMPL
1536VFPLABEL_INST: 1247VMOVR_INST:
1537{ 1248{
1538 INC_ICOUNTER;
1539 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1249 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1540 CHECK_VFP_ENABLED; 1250 CHECK_VFP_ENABLED;
1541 1251
1542 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1252 vmovr_inst *inst_cream = (vmovr_inst *)inst_base->component;
1543 1253
1544 VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m); 1254 VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m);
1545 } 1255 }
1546 cpu->Reg[15] += GET_INST_SIZE(cpu); 1256 cpu->Reg[15] += GET_INST_SIZE(cpu);
1547 INC_PC(sizeof(vfpinstr_inst)); 1257 INC_PC(sizeof(vmovr_inst));
1548 FETCH_INST; 1258 FETCH_INST;
1549 GOTO_NEXT_INST; 1259 GOTO_NEXT_INST;
1550} 1260}
1551#endif 1261#endif
1552#ifdef VFP_CDP_TRANS 1262
1553if ( (OPC_1 & 0xb) == 0xb && CRn == 0 && (OPC_2 & 0x6) == 0x2 )
1554{
1555 unsigned int single = BIT(8) == 0;
1556 unsigned int d = (single ? BITS(12,15)<<1 | BIT(22) : BITS(12,15) | BIT(22)<<4);
1557 unsigned int m = (single ? BITS( 0, 3)<<1 | BIT( 5) : BITS( 0, 3) | BIT( 5)<<4);;
1558 VMOVR(state, single, d, m);
1559 return ARMul_DONE;
1560}
1561#endif
1562#ifdef VFP_CDP_IMPL
1563void VMOVR(ARMul_State * state, ARMword single, ARMword d, ARMword m)
1564{
1565 DBG("VMOV(R) :\n");
1566
1567 if (single)
1568 {
1569 DBG("\ts%d <= s%d[%x]\n", d, m, state->ExtReg[m]);
1570 state->ExtReg[d] = state->ExtReg[m];
1571 }
1572 else
1573 {
1574 /* Check endian please */
1575 DBG("\ts[%d-%d] <= s[%d-%d][%x-%x]\n", d*2+1, d*2, m*2+1, m*2, state->ExtReg[m*2+1], state->ExtReg[m*2]);
1576 state->ExtReg[d*2+1] = state->ExtReg[m*2+1];
1577 state->ExtReg[d*2] = state->ExtReg[m*2];
1578 }
1579}
1580#endif
1581#ifdef VFP_DYNCOM_TABLE 1263#ifdef VFP_DYNCOM_TABLE
1582DYNCOM_FILL_ACTION(vfpinstr), 1264DYNCOM_FILL_ACTION(vmovr),
1583#endif 1265#endif
1584#ifdef VFP_DYNCOM_TAG 1266#ifdef VFP_DYNCOM_TAG
1585int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 1267int DYNCOM_TAG(vmovr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1586{ 1268{
1587 int instr_size = INSTR_SIZE; 1269 int instr_size = INSTR_SIZE;
1588 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc); 1270 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
@@ -1594,7 +1276,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
1594} 1276}
1595#endif 1277#endif
1596#ifdef VFP_DYNCOM_TRANS 1278#ifdef VFP_DYNCOM_TRANS
1597int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1279int DYNCOM_TRANS(vmovr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1598 DBG("\t\tin %s VMOV \n", __FUNCTION__); 1280 DBG("\t\tin %s VMOV \n", __FUNCTION__);
1599 int single = BIT(8) == 0; 1281 int single = BIT(8) == 0;
1600 int d = (single ? BITS(12,15)<<1 | BIT(22) : BIT(22) << 4 | BITS(12,15)); 1282 int d = (single ? BITS(12,15)<<1 | BIT(22) : BIT(22) << 4 | BITS(12,15));
@@ -1613,41 +1295,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1613 return No_exp; 1295 return No_exp;
1614} 1296}
1615#endif 1297#endif
1616#undef vfpinstr
1617#undef vfpinstr_inst
1618#undef VFPLABEL_INST
1619 1298
1620/* ----------------------------------------------------------------------- */ 1299/* ----------------------------------------------------------------------- */
1621/* VABS */ 1300/* VABS */
1622/* cond 1110 1D11 0000 Vd-- 101X 11M0 Vm-- */ 1301/* cond 1110 1D11 0000 Vd-- 101X 11M0 Vm-- */
1623#define vfpinstr vabs
1624#define vfpinstr_inst vabs_inst
1625#define VFPLABEL_INST VABS_INST
1626#ifdef VFP_DECODE
1627{"vabs", 5, ARMVFP2, 23, 27, 0x1d, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 3, 4, 4, 0},
1628#endif
1629#ifdef VFP_DECODE_EXCLUSION
1630{"vabs", 0, ARMVFP2, 0},
1631#endif
1632#ifdef VFP_INTERPRETER_TABLE
1633INTERPRETER_TRANSLATE(vfpinstr),
1634#endif
1635#ifdef VFP_INTERPRETER_LABEL
1636&&VFPLABEL_INST,
1637#endif
1638#ifdef VFP_INTERPRETER_STRUCT 1302#ifdef VFP_INTERPRETER_STRUCT
1639typedef struct _vabs_inst { 1303typedef struct _vabs_inst {
1640 unsigned int instr; 1304 unsigned int instr;
1641 unsigned int dp_operation; 1305 unsigned int dp_operation;
1642} vfpinstr_inst; 1306} vabs_inst;
1643#endif 1307#endif
1644#ifdef VFP_INTERPRETER_TRANS 1308#ifdef VFP_INTERPRETER_TRANS
1645ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1309ARM_INST_PTR INTERPRETER_TRANSLATE(vabs)(unsigned int inst, int index)
1646{ 1310{
1647 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VABS); 1311 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VABS);
1648 1312
1649 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1313 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vabs_inst));
1650 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1314 vabs_inst *inst_cream = (vabs_inst *)inst_base->component;
1651 1315
1652 inst_base->cond = BITS(inst, 28, 31); 1316 inst_base->cond = BITS(inst, 28, 31);
1653 inst_base->idx = index; 1317 inst_base->idx = index;
@@ -1661,15 +1325,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1661} 1325}
1662#endif 1326#endif
1663#ifdef VFP_INTERPRETER_IMPL 1327#ifdef VFP_INTERPRETER_IMPL
1664VFPLABEL_INST: 1328VABS_INST:
1665{ 1329{
1666 INC_ICOUNTER;
1667 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1330 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1668 CHECK_VFP_ENABLED; 1331 CHECK_VFP_ENABLED;
1669 1332
1670 DBG("VABS :\n"); 1333 DBG("VABS :\n");
1671 1334
1672 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1335 vabs_inst *inst_cream = (vabs_inst *)inst_base->component;
1673 1336
1674 int ret; 1337 int ret;
1675 1338
@@ -1681,22 +1344,17 @@ VFPLABEL_INST:
1681 CHECK_VFP_CDP_RET; 1344 CHECK_VFP_CDP_RET;
1682 } 1345 }
1683 cpu->Reg[15] += GET_INST_SIZE(cpu); 1346 cpu->Reg[15] += GET_INST_SIZE(cpu);
1684 INC_PC(sizeof(vfpinstr_inst)); 1347 INC_PC(sizeof(vabs_inst));
1685 FETCH_INST; 1348 FETCH_INST;
1686 GOTO_NEXT_INST; 1349 GOTO_NEXT_INST;
1687} 1350}
1688#endif 1351#endif
1689#ifdef VFP_CDP_TRANS 1352
1690if ((OPC_1 & 0xB) == 0xB && CRn == 0 && (OPC_2 & 0x7) == 6)
1691{
1692 DBG("VABS :\n");
1693}
1694#endif
1695#ifdef VFP_DYNCOM_TABLE 1353#ifdef VFP_DYNCOM_TABLE
1696DYNCOM_FILL_ACTION(vfpinstr), 1354DYNCOM_FILL_ACTION(vabs),
1697#endif 1355#endif
1698#ifdef VFP_DYNCOM_TAG 1356#ifdef VFP_DYNCOM_TAG
1699int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 1357int DYNCOM_TAG(vabs)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1700{ 1358{
1701 int instr_size = INSTR_SIZE; 1359 int instr_size = INSTR_SIZE;
1702 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1360 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -1706,7 +1364,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
1706} 1364}
1707#endif 1365#endif
1708#ifdef VFP_DYNCOM_TRANS 1366#ifdef VFP_DYNCOM_TRANS
1709int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1367int DYNCOM_TRANS(vabs)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1710 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1368 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1711 //arch_arm_undef(cpu, bb, instr); 1369 //arch_arm_undef(cpu, bb, instr);
1712 int single = BIT(8) == 0; 1370 int single = BIT(8) == 0;
@@ -1744,42 +1402,24 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1744 return No_exp; 1402 return No_exp;
1745} 1403}
1746#endif 1404#endif
1747#undef vfpinstr
1748#undef vfpinstr_inst
1749#undef VFPLABEL_INST
1750 1405
1751/* ----------------------------------------------------------------------- */ 1406/* ----------------------------------------------------------------------- */
1752/* VNEG */ 1407/* VNEG */
1753/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */ 1408/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */
1754#define vfpinstr vneg 1409
1755#define vfpinstr_inst vneg_inst
1756#define VFPLABEL_INST VNEG_INST
1757#ifdef VFP_DECODE
1758//{"vneg", 5, ARMVFP2, 23, 27, 0x1d, 16, 21, 0x30, 9, 11, 0x5, 6, 7, 1, 4, 4, 0},
1759{"vneg", 5, ARMVFP2, 23, 27, 0x1d, 17, 21, 0x18, 9, 11, 0x5, 6, 7, 1, 4, 4, 0},
1760#endif
1761#ifdef VFP_DECODE_EXCLUSION
1762{"vneg", 0, ARMVFP2, 0},
1763#endif
1764#ifdef VFP_INTERPRETER_TABLE
1765INTERPRETER_TRANSLATE(vfpinstr),
1766#endif
1767#ifdef VFP_INTERPRETER_LABEL
1768&&VFPLABEL_INST,
1769#endif
1770#ifdef VFP_INTERPRETER_STRUCT 1410#ifdef VFP_INTERPRETER_STRUCT
1771typedef struct _vneg_inst { 1411typedef struct _vneg_inst {
1772 unsigned int instr; 1412 unsigned int instr;
1773 unsigned int dp_operation; 1413 unsigned int dp_operation;
1774} vfpinstr_inst; 1414} vneg_inst;
1775#endif 1415#endif
1776#ifdef VFP_INTERPRETER_TRANS 1416#ifdef VFP_INTERPRETER_TRANS
1777ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1417ARM_INST_PTR INTERPRETER_TRANSLATE(vneg)(unsigned int inst, int index)
1778{ 1418{
1779 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VNEG); 1419 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VNEG);
1780 1420
1781 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1421 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vneg_inst));
1782 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1422 vneg_inst *inst_cream = (vneg_inst *)inst_base->component;
1783 1423
1784 inst_base->cond = BITS(inst, 28, 31); 1424 inst_base->cond = BITS(inst, 28, 31);
1785 inst_base->idx = index; 1425 inst_base->idx = index;
@@ -1793,15 +1433,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1793} 1433}
1794#endif 1434#endif
1795#ifdef VFP_INTERPRETER_IMPL 1435#ifdef VFP_INTERPRETER_IMPL
1796VFPLABEL_INST: 1436VNEG_INST:
1797{ 1437{
1798 INC_ICOUNTER;
1799 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1438 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1800 CHECK_VFP_ENABLED; 1439 CHECK_VFP_ENABLED;
1801 1440
1802 DBG("VNEG :\n"); 1441 DBG("VNEG :\n");
1803 1442
1804 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1443 vneg_inst *inst_cream = (vneg_inst *)inst_base->component;
1805 1444
1806 int ret; 1445 int ret;
1807 1446
@@ -1813,22 +1452,17 @@ VFPLABEL_INST:
1813 CHECK_VFP_CDP_RET; 1452 CHECK_VFP_CDP_RET;
1814 } 1453 }
1815 cpu->Reg[15] += GET_INST_SIZE(cpu); 1454 cpu->Reg[15] += GET_INST_SIZE(cpu);
1816 INC_PC(sizeof(vfpinstr_inst)); 1455 INC_PC(sizeof(vneg_inst));
1817 FETCH_INST; 1456 FETCH_INST;
1818 GOTO_NEXT_INST; 1457 GOTO_NEXT_INST;
1819} 1458}
1820#endif 1459#endif
1821#ifdef VFP_CDP_TRANS 1460
1822if ((OPC_1 & 0xB) == 0xB && CRn == 1 && (OPC_2 & 0x7) == 2)
1823{
1824 DBG("VNEG :\n");
1825}
1826#endif
1827#ifdef VFP_DYNCOM_TABLE 1461#ifdef VFP_DYNCOM_TABLE
1828DYNCOM_FILL_ACTION(vfpinstr), 1462DYNCOM_FILL_ACTION(vneg),
1829#endif 1463#endif
1830#ifdef VFP_DYNCOM_TAG 1464#ifdef VFP_DYNCOM_TAG
1831int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 1465int DYNCOM_TAG(vneg)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1832{ 1466{
1833 int instr_size = INSTR_SIZE; 1467 int instr_size = INSTR_SIZE;
1834 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1468 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -1838,7 +1472,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
1838} 1472}
1839#endif 1473#endif
1840#ifdef VFP_DYNCOM_TRANS 1474#ifdef VFP_DYNCOM_TRANS
1841int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1475int DYNCOM_TRANS(vneg)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1842 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1476 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1843 //arch_arm_undef(cpu, bb, instr); 1477 //arch_arm_undef(cpu, bb, instr);
1844 int single = BIT(8) == 0; 1478 int single = BIT(8) == 0;
@@ -1876,41 +1510,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1876 return No_exp; 1510 return No_exp;
1877} 1511}
1878#endif 1512#endif
1879#undef vfpinstr
1880#undef vfpinstr_inst
1881#undef VFPLABEL_INST
1882 1513
1883/* ----------------------------------------------------------------------- */ 1514/* ----------------------------------------------------------------------- */
1884/* VSQRT */ 1515/* VSQRT */
1885/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */ 1516/* cond 1110 1D11 0001 Vd-- 101X 11M0 Vm-- */
1886#define vfpinstr vsqrt
1887#define vfpinstr_inst vsqrt_inst
1888#define VFPLABEL_INST VSQRT_INST
1889#ifdef VFP_DECODE
1890{"vsqrt", 5, ARMVFP2, 23, 27, 0x1d, 16, 21, 0x31, 9, 11, 0x5, 6, 7, 3, 4, 4, 0},
1891#endif
1892#ifdef VFP_DECODE_EXCLUSION
1893{"vsqrt", 0, ARMVFP2, 0},
1894#endif
1895#ifdef VFP_INTERPRETER_TABLE
1896INTERPRETER_TRANSLATE(vfpinstr),
1897#endif
1898#ifdef VFP_INTERPRETER_LABEL
1899&&VFPLABEL_INST,
1900#endif
1901#ifdef VFP_INTERPRETER_STRUCT 1517#ifdef VFP_INTERPRETER_STRUCT
1902typedef struct _vsqrt_inst { 1518typedef struct _vsqrt_inst {
1903 unsigned int instr; 1519 unsigned int instr;
1904 unsigned int dp_operation; 1520 unsigned int dp_operation;
1905} vfpinstr_inst; 1521} vsqrt_inst;
1906#endif 1522#endif
1907#ifdef VFP_INTERPRETER_TRANS 1523#ifdef VFP_INTERPRETER_TRANS
1908ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1524ARM_INST_PTR INTERPRETER_TRANSLATE(vsqrt)(unsigned int inst, int index)
1909{ 1525{
1910 VFP_DEBUG_TRANSLATE; 1526 VFP_DEBUG_TRANSLATE;
1911 1527
1912 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1528 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vsqrt_inst));
1913 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1529 vsqrt_inst *inst_cream = (vsqrt_inst *)inst_base->component;
1914 1530
1915 inst_base->cond = BITS(inst, 28, 31); 1531 inst_base->cond = BITS(inst, 28, 31);
1916 inst_base->idx = index; 1532 inst_base->idx = index;
@@ -1924,15 +1540,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
1924} 1540}
1925#endif 1541#endif
1926#ifdef VFP_INTERPRETER_IMPL 1542#ifdef VFP_INTERPRETER_IMPL
1927VFPLABEL_INST: 1543VSQRT_INST:
1928{ 1544{
1929 INC_ICOUNTER;
1930 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1545 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
1931 CHECK_VFP_ENABLED; 1546 CHECK_VFP_ENABLED;
1932 1547
1933 DBG("VSQRT :\n"); 1548 DBG("VSQRT :\n");
1934 1549
1935 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1550 vsqrt_inst *inst_cream = (vsqrt_inst *)inst_base->component;
1936 1551
1937 int ret; 1552 int ret;
1938 1553
@@ -1944,22 +1559,17 @@ VFPLABEL_INST:
1944 CHECK_VFP_CDP_RET; 1559 CHECK_VFP_CDP_RET;
1945 } 1560 }
1946 cpu->Reg[15] += GET_INST_SIZE(cpu); 1561 cpu->Reg[15] += GET_INST_SIZE(cpu);
1947 INC_PC(sizeof(vfpinstr_inst)); 1562 INC_PC(sizeof(vsqrt_inst));
1948 FETCH_INST; 1563 FETCH_INST;
1949 GOTO_NEXT_INST; 1564 GOTO_NEXT_INST;
1950} 1565}
1951#endif 1566#endif
1952#ifdef VFP_CDP_TRANS 1567
1953if ((OPC_1 & 0xB) == 0xB && CRn == 1 && (OPC_2 & 0x7) == 6)
1954{
1955 DBG("VSQRT :\n");
1956}
1957#endif
1958#ifdef VFP_DYNCOM_TABLE 1568#ifdef VFP_DYNCOM_TABLE
1959DYNCOM_FILL_ACTION(vfpinstr), 1569DYNCOM_FILL_ACTION(vsqrt),
1960#endif 1570#endif
1961#ifdef VFP_DYNCOM_TAG 1571#ifdef VFP_DYNCOM_TAG
1962int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 1572int DYNCOM_TAG(vsqrt)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
1963{ 1573{
1964 int instr_size = INSTR_SIZE; 1574 int instr_size = INSTR_SIZE;
1965 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1575 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -1969,7 +1579,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
1969} 1579}
1970#endif 1580#endif
1971#ifdef VFP_DYNCOM_TRANS 1581#ifdef VFP_DYNCOM_TRANS
1972int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1582int DYNCOM_TRANS(vsqrt)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
1973 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 1583 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
1974 //arch_arm_undef(cpu, bb, instr); 1584 //arch_arm_undef(cpu, bb, instr);
1975 int dp_op = (BIT(8) == 1); 1585 int dp_op = (BIT(8) == 1);
@@ -1995,41 +1605,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
1995 return No_exp; 1605 return No_exp;
1996} 1606}
1997#endif 1607#endif
1998#undef vfpinstr
1999#undef vfpinstr_inst
2000#undef VFPLABEL_INST
2001 1608
2002/* ----------------------------------------------------------------------- */ 1609/* ----------------------------------------------------------------------- */
2003/* VCMP VCMPE */ 1610/* VCMP VCMPE */
2004/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 1 */ 1611/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 1 */
2005#define vfpinstr vcmp
2006#define vfpinstr_inst vcmp_inst
2007#define VFPLABEL_INST VCMP_INST
2008#ifdef VFP_DECODE
2009{"vcmp", 5, ARMVFP2, 23, 27, 0x1d, 16, 21, 0x34, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
2010#endif
2011#ifdef VFP_DECODE_EXCLUSION
2012{"vcmp", 0, ARMVFP2, 0},
2013#endif
2014#ifdef VFP_INTERPRETER_TABLE
2015INTERPRETER_TRANSLATE(vfpinstr),
2016#endif
2017#ifdef VFP_INTERPRETER_LABEL
2018&&VFPLABEL_INST,
2019#endif
2020#ifdef VFP_INTERPRETER_STRUCT 1612#ifdef VFP_INTERPRETER_STRUCT
2021typedef struct _vcmp_inst { 1613typedef struct _vcmp_inst {
2022 unsigned int instr; 1614 unsigned int instr;
2023 unsigned int dp_operation; 1615 unsigned int dp_operation;
2024} vfpinstr_inst; 1616} vcmp_inst;
2025#endif 1617#endif
2026#ifdef VFP_INTERPRETER_TRANS 1618#ifdef VFP_INTERPRETER_TRANS
2027ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1619ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp)(unsigned int inst, int index)
2028{ 1620{
2029 VFP_DEBUG_TRANSLATE; 1621 VFP_DEBUG_TRANSLATE;
2030 1622
2031 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1623 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp_inst));
2032 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1624 vcmp_inst *inst_cream = (vcmp_inst *)inst_base->component;
2033 1625
2034 inst_base->cond = BITS(inst, 28, 31); 1626 inst_base->cond = BITS(inst, 28, 31);
2035 inst_base->idx = index; 1627 inst_base->idx = index;
@@ -2043,15 +1635,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2043} 1635}
2044#endif 1636#endif
2045#ifdef VFP_INTERPRETER_IMPL 1637#ifdef VFP_INTERPRETER_IMPL
2046VFPLABEL_INST: 1638VCMP_INST:
2047{ 1639{
2048 INC_ICOUNTER;
2049 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1640 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2050 CHECK_VFP_ENABLED; 1641 CHECK_VFP_ENABLED;
2051 1642
2052 DBG("VCMP(1) :\n"); 1643 DBG("VCMP(1) :\n");
2053 1644
2054 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1645 vcmp_inst *inst_cream = (vcmp_inst *)inst_base->component;
2055 1646
2056 int ret; 1647 int ret;
2057 1648
@@ -2063,22 +1654,17 @@ VFPLABEL_INST:
2063 CHECK_VFP_CDP_RET; 1654 CHECK_VFP_CDP_RET;
2064 } 1655 }
2065 cpu->Reg[15] += GET_INST_SIZE(cpu); 1656 cpu->Reg[15] += GET_INST_SIZE(cpu);
2066 INC_PC(sizeof(vfpinstr_inst)); 1657 INC_PC(sizeof(vcmp_inst));
2067 FETCH_INST; 1658 FETCH_INST;
2068 GOTO_NEXT_INST; 1659 GOTO_NEXT_INST;
2069} 1660}
2070#endif 1661#endif
2071#ifdef VFP_CDP_TRANS 1662
2072if ((OPC_1 & 0xB) == 0xB && CRn == 4 && (OPC_2 & 0x2) == 2)
2073{
2074 DBG("VCMP(1) :\n");
2075}
2076#endif
2077#ifdef VFP_DYNCOM_TABLE 1663#ifdef VFP_DYNCOM_TABLE
2078DYNCOM_FILL_ACTION(vfpinstr), 1664DYNCOM_FILL_ACTION(vcmp),
2079#endif 1665#endif
2080#ifdef VFP_DYNCOM_TAG 1666#ifdef VFP_DYNCOM_TAG
2081int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 1667int DYNCOM_TAG(vcmp)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2082{ 1668{
2083 int instr_size = INSTR_SIZE; 1669 int instr_size = INSTR_SIZE;
2084 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc); 1670 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
@@ -2087,7 +1673,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
2087} 1673}
2088#endif 1674#endif
2089#ifdef VFP_DYNCOM_TRANS 1675#ifdef VFP_DYNCOM_TRANS
2090int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1676int DYNCOM_TRANS(vcmp)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2091 DBG("\t\tin %s instruction is executed out of JIT.\n", __FUNCTION__); 1677 DBG("\t\tin %s instruction is executed out of JIT.\n", __FUNCTION__);
2092 //arch_arm_undef(cpu, bb, instr); 1678 //arch_arm_undef(cpu, bb, instr);
2093 int dp_op = (BIT(8) == 1); 1679 int dp_op = (BIT(8) == 1);
@@ -2141,41 +1727,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
2141 return No_exp; 1727 return No_exp;
2142} 1728}
2143#endif 1729#endif
2144#undef vfpinstr
2145#undef vfpinstr_inst
2146#undef VFPLABEL_INST
2147 1730
2148/* ----------------------------------------------------------------------- */ 1731/* ----------------------------------------------------------------------- */
2149/* VCMP VCMPE */ 1732/* VCMP VCMPE */
2150/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 2 */ 1733/* cond 1110 1D11 0100 Vd-- 101X E1M0 Vm-- Encoding 2 */
2151#define vfpinstr vcmp2
2152#define vfpinstr_inst vcmp2_inst
2153#define VFPLABEL_INST VCMP2_INST
2154#ifdef VFP_DECODE
2155{"vcmp2", 5, ARMVFP2, 23, 27, 0x1d, 16, 21, 0x35, 9, 11, 0x5, 0, 6, 0x40},
2156#endif
2157#ifdef VFP_DECODE_EXCLUSION
2158{"vcmp2", 0, ARMVFP2, 0},
2159#endif
2160#ifdef VFP_INTERPRETER_TABLE
2161INTERPRETER_TRANSLATE(vfpinstr),
2162#endif
2163#ifdef VFP_INTERPRETER_LABEL
2164&&VFPLABEL_INST,
2165#endif
2166#ifdef VFP_INTERPRETER_STRUCT 1734#ifdef VFP_INTERPRETER_STRUCT
2167typedef struct _vcmp2_inst { 1735typedef struct _vcmp2_inst {
2168 unsigned int instr; 1736 unsigned int instr;
2169 unsigned int dp_operation; 1737 unsigned int dp_operation;
2170} vfpinstr_inst; 1738} vcmp2_inst;
2171#endif 1739#endif
2172#ifdef VFP_INTERPRETER_TRANS 1740#ifdef VFP_INTERPRETER_TRANS
2173ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1741ARM_INST_PTR INTERPRETER_TRANSLATE(vcmp2)(unsigned int inst, int index)
2174{ 1742{
2175 VFP_DEBUG_TRANSLATE; 1743 VFP_DEBUG_TRANSLATE;
2176 1744
2177 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1745 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcmp2_inst));
2178 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1746 vcmp2_inst *inst_cream = (vcmp2_inst *)inst_base->component;
2179 1747
2180 inst_base->cond = BITS(inst, 28, 31); 1748 inst_base->cond = BITS(inst, 28, 31);
2181 inst_base->idx = index; 1749 inst_base->idx = index;
@@ -2189,15 +1757,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2189} 1757}
2190#endif 1758#endif
2191#ifdef VFP_INTERPRETER_IMPL 1759#ifdef VFP_INTERPRETER_IMPL
2192VFPLABEL_INST: 1760VCMP2_INST:
2193{ 1761{
2194 INC_ICOUNTER;
2195 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1762 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2196 CHECK_VFP_ENABLED; 1763 CHECK_VFP_ENABLED;
2197 1764
2198 DBG("VCMP(2) :\n"); 1765 DBG("VCMP(2) :\n");
2199 1766
2200 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1767 vcmp2_inst *inst_cream = (vcmp2_inst *)inst_base->component;
2201 1768
2202 int ret; 1769 int ret;
2203 1770
@@ -2209,22 +1776,17 @@ VFPLABEL_INST:
2209 CHECK_VFP_CDP_RET; 1776 CHECK_VFP_CDP_RET;
2210 } 1777 }
2211 cpu->Reg[15] += GET_INST_SIZE(cpu); 1778 cpu->Reg[15] += GET_INST_SIZE(cpu);
2212 INC_PC(sizeof(vfpinstr_inst)); 1779 INC_PC(sizeof(vcmp2_inst));
2213 FETCH_INST; 1780 FETCH_INST;
2214 GOTO_NEXT_INST; 1781 GOTO_NEXT_INST;
2215} 1782}
2216#endif 1783#endif
2217#ifdef VFP_CDP_TRANS 1784
2218if ((OPC_1 & 0xB) == 0xB && CRn == 5 && (OPC_2 & 0x2) == 2 && CRm == 0)
2219{
2220 DBG("VCMP(2) :\n");
2221}
2222#endif
2223#ifdef VFP_DYNCOM_TABLE 1785#ifdef VFP_DYNCOM_TABLE
2224DYNCOM_FILL_ACTION(vfpinstr), 1786DYNCOM_FILL_ACTION(vcmp2),
2225#endif 1787#endif
2226#ifdef VFP_DYNCOM_TAG 1788#ifdef VFP_DYNCOM_TAG
2227int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 1789int DYNCOM_TAG(vcmp2)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2228{ 1790{
2229 int instr_size = INSTR_SIZE; 1791 int instr_size = INSTR_SIZE;
2230 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc); 1792 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
@@ -2233,7 +1795,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
2233} 1795}
2234#endif 1796#endif
2235#ifdef VFP_DYNCOM_TRANS 1797#ifdef VFP_DYNCOM_TRANS
2236int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1798int DYNCOM_TRANS(vcmp2)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2237 DBG("\t\tin %s instruction will executed out of JIT.\n", __FUNCTION__); 1799 DBG("\t\tin %s instruction will executed out of JIT.\n", __FUNCTION__);
2238 //arch_arm_undef(cpu, bb, instr); 1800 //arch_arm_undef(cpu, bb, instr);
2239 int dp_op = (BIT(8) == 1); 1801 int dp_op = (BIT(8) == 1);
@@ -2287,41 +1849,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
2287 return No_exp; 1849 return No_exp;
2288} 1850}
2289#endif 1851#endif
2290#undef vfpinstr
2291#undef vfpinstr_inst
2292#undef VFPLABEL_INST
2293 1852
2294/* ----------------------------------------------------------------------- */ 1853/* ----------------------------------------------------------------------- */
2295/* VCVTBDS between double and single */ 1854/* VCVTBDS between double and single */
2296/* cond 1110 1D11 0111 Vd-- 101X 11M0 Vm-- */ 1855/* cond 1110 1D11 0111 Vd-- 101X 11M0 Vm-- */
2297#define vfpinstr vcvtbds
2298#define vfpinstr_inst vcvtbds_inst
2299#define VFPLABEL_INST VCVTBDS_INST
2300#ifdef VFP_DECODE
2301{"vcvt(bds)", 5, ARMVFP2, 23, 27, 0x1d, 16, 21, 0x37, 9, 11, 0x5, 6, 7, 3, 4, 4, 0},
2302#endif
2303#ifdef VFP_DECODE_EXCLUSION
2304{"vcvt(bds)", 0, ARMVFP2, 0},
2305#endif
2306#ifdef VFP_INTERPRETER_TABLE
2307INTERPRETER_TRANSLATE(vfpinstr),
2308#endif
2309#ifdef VFP_INTERPRETER_LABEL
2310&&VFPLABEL_INST,
2311#endif
2312#ifdef VFP_INTERPRETER_STRUCT 1856#ifdef VFP_INTERPRETER_STRUCT
2313typedef struct _vcvtbds_inst { 1857typedef struct _vcvtbds_inst {
2314 unsigned int instr; 1858 unsigned int instr;
2315 unsigned int dp_operation; 1859 unsigned int dp_operation;
2316} vfpinstr_inst; 1860} vcvtbds_inst;
2317#endif 1861#endif
2318#ifdef VFP_INTERPRETER_TRANS 1862#ifdef VFP_INTERPRETER_TRANS
2319ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1863ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbds)(unsigned int inst, int index)
2320{ 1864{
2321 VFP_DEBUG_TRANSLATE; 1865 VFP_DEBUG_TRANSLATE;
2322 1866
2323 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1867 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbds_inst));
2324 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1868 vcvtbds_inst *inst_cream = (vcvtbds_inst *)inst_base->component;
2325 1869
2326 inst_base->cond = BITS(inst, 28, 31); 1870 inst_base->cond = BITS(inst, 28, 31);
2327 inst_base->idx = index; 1871 inst_base->idx = index;
@@ -2335,15 +1879,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2335} 1879}
2336#endif 1880#endif
2337#ifdef VFP_INTERPRETER_IMPL 1881#ifdef VFP_INTERPRETER_IMPL
2338VFPLABEL_INST: 1882VCVTBDS_INST:
2339{ 1883{
2340 INC_ICOUNTER;
2341 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1884 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2342 CHECK_VFP_ENABLED; 1885 CHECK_VFP_ENABLED;
2343 1886
2344 DBG("VCVT(BDS) :\n"); 1887 DBG("VCVT(BDS) :\n");
2345 1888
2346 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1889 vcvtbds_inst *inst_cream = (vcvtbds_inst *)inst_base->component;
2347 1890
2348 int ret; 1891 int ret;
2349 1892
@@ -2355,22 +1898,17 @@ VFPLABEL_INST:
2355 CHECK_VFP_CDP_RET; 1898 CHECK_VFP_CDP_RET;
2356 } 1899 }
2357 cpu->Reg[15] += GET_INST_SIZE(cpu); 1900 cpu->Reg[15] += GET_INST_SIZE(cpu);
2358 INC_PC(sizeof(vfpinstr_inst)); 1901 INC_PC(sizeof(vcvtbds_inst));
2359 FETCH_INST; 1902 FETCH_INST;
2360 GOTO_NEXT_INST; 1903 GOTO_NEXT_INST;
2361} 1904}
2362#endif 1905#endif
2363#ifdef VFP_CDP_TRANS 1906
2364if ((OPC_1 & 0xB) == 0xB && CRn == 7 && (OPC_2 & 0x6) == 6)
2365{
2366 DBG("VCVT(BDS) :\n");
2367}
2368#endif
2369#ifdef VFP_DYNCOM_TABLE 1907#ifdef VFP_DYNCOM_TABLE
2370DYNCOM_FILL_ACTION(vfpinstr), 1908DYNCOM_FILL_ACTION(vcvtbds),
2371#endif 1909#endif
2372#ifdef VFP_DYNCOM_TAG 1910#ifdef VFP_DYNCOM_TAG
2373int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 1911int DYNCOM_TAG(vcvtbds)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2374{ 1912{
2375 int instr_size = INSTR_SIZE; 1913 int instr_size = INSTR_SIZE;
2376 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc); 1914 //arm_tag_trap(cpu, pc, instr, tag, new_pc, next_pc);
@@ -2379,7 +1917,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
2379} 1917}
2380#endif 1918#endif
2381#ifdef VFP_DYNCOM_TRANS 1919#ifdef VFP_DYNCOM_TRANS
2382int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 1920int DYNCOM_TRANS(vcvtbds)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2383 DBG("\t\tin %s instruction is executed out.\n", __FUNCTION__); 1921 DBG("\t\tin %s instruction is executed out.\n", __FUNCTION__);
2384 //arch_arm_undef(cpu, bb, instr); 1922 //arch_arm_undef(cpu, bb, instr);
2385 int dp_op = (BIT(8) == 1); 1923 int dp_op = (BIT(8) == 1);
@@ -2407,41 +1945,23 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
2407 return No_exp; 1945 return No_exp;
2408} 1946}
2409#endif 1947#endif
2410#undef vfpinstr
2411#undef vfpinstr_inst
2412#undef VFPLABEL_INST
2413 1948
2414/* ----------------------------------------------------------------------- */ 1949/* ----------------------------------------------------------------------- */
2415/* VCVTBFF between floating point and fixed point */ 1950/* VCVTBFF between floating point and fixed point */
2416/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */ 1951/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */
2417#define vfpinstr vcvtbff
2418#define vfpinstr_inst vcvtbff_inst
2419#define VFPLABEL_INST VCVTBFF_INST
2420#ifdef VFP_DECODE
2421{"vcvt(bff)", 6, ARMVFP3, 23, 27, 0x1d, 19, 21, 0x7, 17, 17, 0x1, 9, 11, 0x5, 6, 6, 1},
2422#endif
2423#ifdef VFP_DECODE_EXCLUSION
2424{"vcvt(bff)", 0, ARMVFP3, 4, 4, 1},
2425#endif
2426#ifdef VFP_INTERPRETER_TABLE
2427INTERPRETER_TRANSLATE(vfpinstr),
2428#endif
2429#ifdef VFP_INTERPRETER_LABEL
2430&&VFPLABEL_INST,
2431#endif
2432#ifdef VFP_INTERPRETER_STRUCT 1952#ifdef VFP_INTERPRETER_STRUCT
2433typedef struct _vcvtbff_inst { 1953typedef struct _vcvtbff_inst {
2434 unsigned int instr; 1954 unsigned int instr;
2435 unsigned int dp_operation; 1955 unsigned int dp_operation;
2436} vfpinstr_inst; 1956} vcvtbff_inst;
2437#endif 1957#endif
2438#ifdef VFP_INTERPRETER_TRANS 1958#ifdef VFP_INTERPRETER_TRANS
2439ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 1959ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbff)(unsigned int inst, int index)
2440{ 1960{
2441 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VCVTBFF); 1961 VFP_DEBUG_TRANSLATE;VFP_DEBUG_UNTESTED(VCVTBFF);
2442 1962
2443 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 1963 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbff_inst));
2444 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1964 vcvtbff_inst *inst_cream = (vcvtbff_inst *)inst_base->component;
2445 1965
2446 inst_base->cond = BITS(inst, 28, 31); 1966 inst_base->cond = BITS(inst, 28, 31);
2447 inst_base->idx = index; 1967 inst_base->idx = index;
@@ -2455,15 +1975,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2455} 1975}
2456#endif 1976#endif
2457#ifdef VFP_INTERPRETER_IMPL 1977#ifdef VFP_INTERPRETER_IMPL
2458VFPLABEL_INST: 1978VCVTBFF_INST:
2459{ 1979{
2460 INC_ICOUNTER;
2461 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 1980 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2462 CHECK_VFP_ENABLED; 1981 CHECK_VFP_ENABLED;
2463 1982
2464 DBG("VCVT(BFF) :\n"); 1983 DBG("VCVT(BFF) :\n");
2465 1984
2466 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 1985 vcvtbff_inst *inst_cream = (vcvtbff_inst *)inst_base->component;
2467 1986
2468 int ret; 1987 int ret;
2469 1988
@@ -2475,22 +1994,17 @@ VFPLABEL_INST:
2475 CHECK_VFP_CDP_RET; 1994 CHECK_VFP_CDP_RET;
2476 } 1995 }
2477 cpu->Reg[15] += GET_INST_SIZE(cpu); 1996 cpu->Reg[15] += GET_INST_SIZE(cpu);
2478 INC_PC(sizeof(vfpinstr_inst)); 1997 INC_PC(sizeof(vcvtbff_inst));
2479 FETCH_INST; 1998 FETCH_INST;
2480 GOTO_NEXT_INST; 1999 GOTO_NEXT_INST;
2481} 2000}
2482#endif 2001#endif
2483#ifdef VFP_CDP_TRANS 2002
2484if ((OPC_1 & 0xB) == 0xB && CRn >= 0xA && (OPC_2 & 0x2) == 2)
2485{
2486 DBG("VCVT(BFF) :\n");
2487}
2488#endif
2489#ifdef VFP_DYNCOM_TABLE 2003#ifdef VFP_DYNCOM_TABLE
2490DYNCOM_FILL_ACTION(vfpinstr), 2004DYNCOM_FILL_ACTION(vcvtbff),
2491#endif 2005#endif
2492#ifdef VFP_DYNCOM_TAG 2006#ifdef VFP_DYNCOM_TAG
2493int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 2007int DYNCOM_TAG(vcvtbff)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2494{ 2008{
2495 int instr_size = INSTR_SIZE; 2009 int instr_size = INSTR_SIZE;
2496 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2010 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -2499,47 +2013,29 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
2499} 2013}
2500#endif 2014#endif
2501#ifdef VFP_DYNCOM_TRANS 2015#ifdef VFP_DYNCOM_TRANS
2502int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2016int DYNCOM_TRANS(vcvtbff)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2503 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2017 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
2504 arch_arm_undef(cpu, bb, instr); 2018 arch_arm_undef(cpu, bb, instr);
2505 return No_exp; 2019 return No_exp;
2506} 2020}
2507#endif 2021#endif
2508#undef vfpinstr
2509#undef vfpinstr_inst
2510#undef VFPLABEL_INST
2511 2022
2512/* ----------------------------------------------------------------------- */ 2023/* ----------------------------------------------------------------------- */
2513/* VCVTBFI between floating point and integer */ 2024/* VCVTBFI between floating point and integer */
2514/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */ 2025/* cond 1110 1D11 1op2 Vd-- 101X X1M0 Vm-- */
2515#define vfpinstr vcvtbfi
2516#define vfpinstr_inst vcvtbfi_inst
2517#define VFPLABEL_INST VCVTBFI_INST
2518#ifdef VFP_DECODE
2519{"vcvt(bfi)", 5, ARMVFP2, 23, 27, 0x1d, 19, 21, 0x7, 9, 11, 0x5, 6, 6, 1, 4, 4, 0},
2520#endif
2521#ifdef VFP_DECODE_EXCLUSION
2522{"vcvt(bfi)", 0, ARMVFP2, 0},
2523#endif
2524#ifdef VFP_INTERPRETER_TABLE
2525INTERPRETER_TRANSLATE(vfpinstr),
2526#endif
2527#ifdef VFP_INTERPRETER_LABEL
2528&&VFPLABEL_INST,
2529#endif
2530#ifdef VFP_INTERPRETER_STRUCT 2026#ifdef VFP_INTERPRETER_STRUCT
2531typedef struct _vcvtbfi_inst { 2027typedef struct _vcvtbfi_inst {
2532 unsigned int instr; 2028 unsigned int instr;
2533 unsigned int dp_operation; 2029 unsigned int dp_operation;
2534} vfpinstr_inst; 2030} vcvtbfi_inst;
2535#endif 2031#endif
2536#ifdef VFP_INTERPRETER_TRANS 2032#ifdef VFP_INTERPRETER_TRANS
2537ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2033ARM_INST_PTR INTERPRETER_TRANSLATE(vcvtbfi)(unsigned int inst, int index)
2538{ 2034{
2539 VFP_DEBUG_TRANSLATE; 2035 VFP_DEBUG_TRANSLATE;
2540 2036
2541 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2037 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vcvtbfi_inst));
2542 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2038 vcvtbfi_inst *inst_cream = (vcvtbfi_inst *)inst_base->component;
2543 2039
2544 inst_base->cond = BITS(inst, 28, 31); 2040 inst_base->cond = BITS(inst, 28, 31);
2545 inst_base->idx = index; 2041 inst_base->idx = index;
@@ -2554,15 +2050,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2554} 2050}
2555#endif 2051#endif
2556#ifdef VFP_INTERPRETER_IMPL 2052#ifdef VFP_INTERPRETER_IMPL
2557VFPLABEL_INST: 2053VCVTBFI_INST:
2558{ 2054{
2559 INC_ICOUNTER;
2560 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2055 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2561 CHECK_VFP_ENABLED; 2056 CHECK_VFP_ENABLED;
2562 2057
2563 DBG("VCVT(BFI) :\n"); 2058 DBG("VCVT(BFI) :\n");
2564 2059
2565 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2060 vcvtbfi_inst *inst_cream = (vcvtbfi_inst *)inst_base->component;
2566 2061
2567 int ret; 2062 int ret;
2568 2063
@@ -2574,22 +2069,17 @@ VFPLABEL_INST:
2574 CHECK_VFP_CDP_RET; 2069 CHECK_VFP_CDP_RET;
2575 } 2070 }
2576 cpu->Reg[15] += GET_INST_SIZE(cpu); 2071 cpu->Reg[15] += GET_INST_SIZE(cpu);
2577 INC_PC(sizeof(vfpinstr_inst)); 2072 INC_PC(sizeof(vcvtbfi_inst));
2578 FETCH_INST; 2073 FETCH_INST;
2579 GOTO_NEXT_INST; 2074 GOTO_NEXT_INST;
2580} 2075}
2581#endif 2076#endif
2582#ifdef VFP_CDP_TRANS 2077
2583if ((OPC_1 & 0xB) == 0xB && CRn > 7 && (OPC_2 & 0x2) == 2)
2584{
2585 DBG("VCVT(BFI) :\n");
2586}
2587#endif
2588#ifdef VFP_DYNCOM_TABLE 2078#ifdef VFP_DYNCOM_TABLE
2589DYNCOM_FILL_ACTION(vfpinstr), 2079DYNCOM_FILL_ACTION(vcvtbfi),
2590#endif 2080#endif
2591#ifdef VFP_DYNCOM_TAG 2081#ifdef VFP_DYNCOM_TAG
2592int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 2082int DYNCOM_TAG(vcvtbfi)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2593{ 2083{
2594 int instr_size = INSTR_SIZE; 2084 int instr_size = INSTR_SIZE;
2595 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2085 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -2600,7 +2090,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
2600} 2090}
2601#endif 2091#endif
2602#ifdef VFP_DYNCOM_TRANS 2092#ifdef VFP_DYNCOM_TRANS
2603int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2093int DYNCOM_TRANS(vcvtbfi)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2604 DBG("\t\tin %s, instruction will be executed out of JIT.\n", __FUNCTION__); 2094 DBG("\t\tin %s, instruction will be executed out of JIT.\n", __FUNCTION__);
2605 //arch_arm_undef(cpu, bb, instr); 2095 //arch_arm_undef(cpu, bb, instr);
2606 unsigned int opc2 = BITS(16,18); 2096 unsigned int opc2 = BITS(16,18);
@@ -2694,9 +2184,6 @@ int vcvtbfi_instr_impl(arm_core_t* cpu, uint32 instr){
2694 return 0; 2184 return 0;
2695} 2185}
2696#endif 2186#endif
2697#undef vfpinstr
2698#undef vfpinstr_inst
2699#undef VFPLABEL_INST
2700 2187
2701/* ----------------------------------------------------------------------- */ 2188/* ----------------------------------------------------------------------- */
2702/* MRC / MCR instructions */ 2189/* MRC / MCR instructions */
@@ -2707,35 +2194,20 @@ int vcvtbfi_instr_impl(arm_core_t* cpu, uint32 instr){
2707/* VMOVBRS between register and single precision */ 2194/* VMOVBRS between register and single precision */
2708/* cond 1110 000o Vn-- Rt-- 1010 N001 0000 */ 2195/* cond 1110 000o Vn-- Rt-- 1010 N001 0000 */
2709/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */ 2196/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */
2710#define vfpinstr vmovbrs
2711#define vfpinstr_inst vmovbrs_inst
2712#define VFPLABEL_INST VMOVBRS_INST
2713#ifdef VFP_DECODE
2714{"vmovbrs", 3, ARMVFP2, 21, 27, 0x70, 8, 11, 0xA, 0, 6, 0x10},
2715#endif
2716#ifdef VFP_DECODE_EXCLUSION
2717{"vmovbrs", 0, ARMVFP2, 0},
2718#endif
2719#ifdef VFP_INTERPRETER_TABLE
2720INTERPRETER_TRANSLATE(vfpinstr),
2721#endif
2722#ifdef VFP_INTERPRETER_LABEL
2723&&VFPLABEL_INST,
2724#endif
2725#ifdef VFP_INTERPRETER_STRUCT 2197#ifdef VFP_INTERPRETER_STRUCT
2726typedef struct _vmovbrs_inst { 2198typedef struct _vmovbrs_inst {
2727 unsigned int to_arm; 2199 unsigned int to_arm;
2728 unsigned int t; 2200 unsigned int t;
2729 unsigned int n; 2201 unsigned int n;
2730} vfpinstr_inst; 2202} vmovbrs_inst;
2731#endif 2203#endif
2732#ifdef VFP_INTERPRETER_TRANS 2204#ifdef VFP_INTERPRETER_TRANS
2733ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2205ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrs)(unsigned int inst, int index)
2734{ 2206{
2735 VFP_DEBUG_TRANSLATE; 2207 VFP_DEBUG_TRANSLATE;
2736 2208
2737 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2209 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrs_inst));
2738 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2210 vmovbrs_inst *inst_cream = (vmovbrs_inst *)inst_base->component;
2739 2211
2740 inst_base->cond = BITS(inst, 28, 31); 2212 inst_base->cond = BITS(inst, 28, 31);
2741 inst_base->idx = index; 2213 inst_base->idx = index;
@@ -2750,61 +2222,27 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2750} 2222}
2751#endif 2223#endif
2752#ifdef VFP_INTERPRETER_IMPL 2224#ifdef VFP_INTERPRETER_IMPL
2753VFPLABEL_INST: 2225VMOVBRS_INST:
2754{ 2226{
2755 INC_ICOUNTER;
2756 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2227 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2757 CHECK_VFP_ENABLED; 2228 CHECK_VFP_ENABLED;
2758 2229
2759 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2230 vmovbrs_inst *inst_cream = (vmovbrs_inst *)inst_base->component;
2760 2231
2761 VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t])); 2232 VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t]));
2762 } 2233 }
2763 cpu->Reg[15] += GET_INST_SIZE(cpu); 2234 cpu->Reg[15] += GET_INST_SIZE(cpu);
2764 INC_PC(sizeof(vfpinstr_inst)); 2235 INC_PC(sizeof(vmovbrs_inst));
2765 FETCH_INST; 2236 FETCH_INST;
2766 GOTO_NEXT_INST; 2237 GOTO_NEXT_INST;
2767} 2238}
2768#endif 2239#endif
2769#ifdef VFP_MRC_TRANS 2240
2770if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
2771{
2772 /* VMOV r to s */
2773 /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
2774 VMOVBRS(state, BIT(20), Rt, BIT(7)|CRn<<1, value);
2775 return ARMul_DONE;
2776}
2777#endif
2778#ifdef VFP_MCR_TRANS
2779if (OPC_1 == 0x0 && CRm == 0 && (OPC_2 & 0x3) == 0)
2780{
2781 /* VMOV s to r */
2782 /* Transfering Rt is not mandatory, as the value of interest is pointed by value */
2783 VMOVBRS(state, BIT(20), Rt, BIT(7)|CRn<<1, &value);
2784 return ARMul_DONE;
2785}
2786#endif
2787#ifdef VFP_MRC_IMPL
2788void VMOVBRS(ARMul_State * state, ARMword to_arm, ARMword t, ARMword n, ARMword *value)
2789{
2790 DBG("VMOV(BRS) :\n");
2791 if (to_arm)
2792 {
2793 DBG("\tr%d <= s%d=[%x]\n", t, n, state->ExtReg[n]);
2794 *value = state->ExtReg[n];
2795 }
2796 else
2797 {
2798 DBG("\ts%d <= r%d=[%x]\n", n, t, *value);
2799 state->ExtReg[n] = *value;
2800 }
2801}
2802#endif
2803#ifdef VFP_DYNCOM_TABLE 2241#ifdef VFP_DYNCOM_TABLE
2804DYNCOM_FILL_ACTION(vfpinstr), 2242DYNCOM_FILL_ACTION(vmovbrs),
2805#endif 2243#endif
2806#ifdef VFP_DYNCOM_TAG 2244#ifdef VFP_DYNCOM_TAG
2807int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 2245int DYNCOM_TAG(vmovbrs)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2808{ 2246{
2809 int instr_size = INSTR_SIZE; 2247 int instr_size = INSTR_SIZE;
2810 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2248 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -2813,7 +2251,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
2813} 2251}
2814#endif 2252#endif
2815#ifdef VFP_DYNCOM_TRANS 2253#ifdef VFP_DYNCOM_TRANS
2816int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2254int DYNCOM_TRANS(vmovbrs)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2817 DBG("VMOV(BRS) :\n"); 2255 DBG("VMOV(BRS) :\n");
2818 int to_arm = BIT(20) == 1; 2256 int to_arm = BIT(20) == 1;
2819 int t = BITS(12, 15); 2257 int t = BITS(12, 15);
@@ -2832,42 +2270,24 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
2832 return No_exp; 2270 return No_exp;
2833} 2271}
2834#endif 2272#endif
2835#undef vfpinstr
2836#undef vfpinstr_inst
2837#undef VFPLABEL_INST
2838 2273
2839/* ----------------------------------------------------------------------- */ 2274/* ----------------------------------------------------------------------- */
2840/* VMSR */ 2275/* VMSR */
2841/* cond 1110 1110 reg- Rt-- 1010 0001 0000 */ 2276/* cond 1110 1110 reg- Rt-- 1010 0001 0000 */
2842/* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */ 2277/* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */
2843#define vfpinstr vmsr
2844#define vfpinstr_inst vmsr_inst
2845#define VFPLABEL_INST VMSR_INST
2846#ifdef VFP_DECODE
2847{"vmsr", 2, ARMVFP2, 20, 27, 0xEE, 0, 11, 0xA10},
2848#endif
2849#ifdef VFP_DECODE_EXCLUSION
2850{"vmsr", 0, ARMVFP2, 0},
2851#endif
2852#ifdef VFP_INTERPRETER_TABLE
2853INTERPRETER_TRANSLATE(vfpinstr),
2854#endif
2855#ifdef VFP_INTERPRETER_LABEL
2856&&VFPLABEL_INST,
2857#endif
2858#ifdef VFP_INTERPRETER_STRUCT 2278#ifdef VFP_INTERPRETER_STRUCT
2859typedef struct _vmsr_inst { 2279typedef struct _vmsr_inst {
2860 unsigned int reg; 2280 unsigned int reg;
2861 unsigned int Rd; 2281 unsigned int Rd;
2862} vfpinstr_inst; 2282} vmsr_inst;
2863#endif 2283#endif
2864#ifdef VFP_INTERPRETER_TRANS 2284#ifdef VFP_INTERPRETER_TRANS
2865ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2285ARM_INST_PTR INTERPRETER_TRANSLATE(vmsr)(unsigned int inst, int index)
2866{ 2286{
2867 VFP_DEBUG_TRANSLATE; 2287 VFP_DEBUG_TRANSLATE;
2868 2288
2869 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2289 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmsr_inst));
2870 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2290 vmsr_inst *inst_cream = (vmsr_inst *)inst_base->component;
2871 2291
2872 inst_base->cond = BITS(inst, 28, 31); 2292 inst_base->cond = BITS(inst, 28, 31);
2873 inst_base->idx = index; 2293 inst_base->idx = index;
@@ -2881,52 +2301,30 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
2881} 2301}
2882#endif 2302#endif
2883#ifdef VFP_INTERPRETER_IMPL 2303#ifdef VFP_INTERPRETER_IMPL
2884VFPLABEL_INST: 2304VMSR_INST:
2885{ 2305{
2886 INC_ICOUNTER;
2887 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2306 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
2888 /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled , 2307 /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled ,
2889 and in privilegied mode */ 2308 and in privilegied mode */
2890 /* Exceptions must be checked, according to v7 ref manual */ 2309 /* Exceptions must be checked, according to v7 ref manual */
2891 CHECK_VFP_ENABLED; 2310 CHECK_VFP_ENABLED;
2892 2311
2893 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2312 vmsr_inst *inst_cream = (vmsr_inst *)inst_base->component;
2894 2313
2895 VMSR(cpu, inst_cream->reg, inst_cream->Rd); 2314 VMSR(cpu, inst_cream->reg, inst_cream->Rd);
2896 } 2315 }
2897 cpu->Reg[15] += GET_INST_SIZE(cpu); 2316 cpu->Reg[15] += GET_INST_SIZE(cpu);
2898 INC_PC(sizeof(vfpinstr_inst)); 2317 INC_PC(sizeof(vmsr_inst));
2899 FETCH_INST; 2318 FETCH_INST;
2900 GOTO_NEXT_INST; 2319 GOTO_NEXT_INST;
2901} 2320}
2902#endif 2321#endif
2903#ifdef VFP_MCR_TRANS 2322
2904if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
2905{
2906 VMSR(state, CRn, Rt);
2907 return ARMul_DONE;
2908}
2909#endif
2910#ifdef VFP_MCR_IMPL
2911void VMSR(ARMul_State * state, ARMword reg, ARMword Rt)
2912{
2913 if (reg == 1)
2914 {
2915 DBG("VMSR :\tfpscr <= r%d=[%x]\n", Rt, state->Reg[Rt]);
2916 state->VFP[VFP_OFFSET(VFP_FPSCR)] = state->Reg[Rt];
2917 }
2918 else if (reg == 8)
2919 {
2920 DBG("VMSR :\tfpexc <= r%d=[%x]\n", Rt, state->Reg[Rt]);
2921 state->VFP[VFP_OFFSET(VFP_FPEXC)] = state->Reg[Rt];
2922 }
2923}
2924#endif
2925#ifdef VFP_DYNCOM_TABLE 2323#ifdef VFP_DYNCOM_TABLE
2926DYNCOM_FILL_ACTION(vfpinstr), 2324DYNCOM_FILL_ACTION(vmsr),
2927#endif 2325#endif
2928#ifdef VFP_DYNCOM_TAG 2326#ifdef VFP_DYNCOM_TAG
2929int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 2327int DYNCOM_TAG(vmsr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
2930{ 2328{
2931 int instr_size = INSTR_SIZE; 2329 int instr_size = INSTR_SIZE;
2932 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2330 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -2936,7 +2334,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
2936} 2334}
2937#endif 2335#endif
2938#ifdef VFP_DYNCOM_TRANS 2336#ifdef VFP_DYNCOM_TRANS
2939int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2337int DYNCOM_TRANS(vmsr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
2940 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2338 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
2941 //arch_arm_undef(cpu, bb, instr); 2339 //arch_arm_undef(cpu, bb, instr);
2942 DBG("VMSR :"); 2340 DBG("VMSR :");
@@ -2969,44 +2367,26 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
2969 return No_exp; 2367 return No_exp;
2970} 2368}
2971#endif 2369#endif
2972#undef vfpinstr
2973#undef vfpinstr_inst
2974#undef VFPLABEL_INST
2975 2370
2976/* ----------------------------------------------------------------------- */ 2371/* ----------------------------------------------------------------------- */
2977/* VMOVBRC register to scalar */ 2372/* VMOVBRC register to scalar */
2978/* cond 1110 0XX0 Vd-- Rt-- 1011 DXX1 0000 */ 2373/* cond 1110 0XX0 Vd-- Rt-- 1011 DXX1 0000 */
2979/* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */ 2374/* cond 1110 op10 CRn- Rt-- copr op21 CRm- MCR */
2980#define vfpinstr vmovbrc
2981#define vfpinstr_inst vmovbrc_inst
2982#define VFPLABEL_INST VMOVBRC_INST
2983#ifdef VFP_DECODE
2984{"vmovbrc", 4, ARMVFP2, 23, 27, 0x1C, 20, 20, 0x0, 8,11,0xB, 0,4,0x10},
2985#endif
2986#ifdef VFP_DECODE_EXCLUSION
2987{"vmovbrc", 0, ARMVFP2, 0},
2988#endif
2989#ifdef VFP_INTERPRETER_TABLE
2990INTERPRETER_TRANSLATE(vfpinstr),
2991#endif
2992#ifdef VFP_INTERPRETER_LABEL
2993&&VFPLABEL_INST,
2994#endif
2995#ifdef VFP_INTERPRETER_STRUCT 2375#ifdef VFP_INTERPRETER_STRUCT
2996typedef struct _vmovbrc_inst { 2376typedef struct _vmovbrc_inst {
2997 unsigned int esize; 2377 unsigned int esize;
2998 unsigned int index; 2378 unsigned int index;
2999 unsigned int d; 2379 unsigned int d;
3000 unsigned int t; 2380 unsigned int t;
3001} vfpinstr_inst; 2381} vmovbrc_inst;
3002#endif 2382#endif
3003#ifdef VFP_INTERPRETER_TRANS 2383#ifdef VFP_INTERPRETER_TRANS
3004ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2384ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrc)(unsigned int inst, int index)
3005{ 2385{
3006 VFP_DEBUG_TRANSLATE; 2386 VFP_DEBUG_TRANSLATE;
3007 2387
3008 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2388 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrc_inst));
3009 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2389 vmovbrc_inst *inst_cream = (vmovbrc_inst *)inst_base->component;
3010 2390
3011 inst_base->cond = BITS(inst, 28, 31); 2391 inst_base->cond = BITS(inst, 28, 31);
3012 inst_base->idx = index; 2392 inst_base->idx = index;
@@ -3023,34 +2403,27 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3023} 2403}
3024#endif 2404#endif
3025#ifdef VFP_INTERPRETER_IMPL 2405#ifdef VFP_INTERPRETER_IMPL
3026VFPLABEL_INST: 2406VMOVBRC_INST:
3027{ 2407{
3028 INC_ICOUNTER;
3029 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2408 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3030 CHECK_VFP_ENABLED; 2409 CHECK_VFP_ENABLED;
3031 2410
3032 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2411 vmovbrc_inst *inst_cream = (vmovbrc_inst *)inst_base->component;
3033 2412
3034 VFP_DEBUG_UNIMPLEMENTED(VMOVBRC); 2413 VFP_DEBUG_UNIMPLEMENTED(VMOVBRC);
3035 } 2414 }
3036 cpu->Reg[15] += GET_INST_SIZE(cpu); 2415 cpu->Reg[15] += GET_INST_SIZE(cpu);
3037 INC_PC(sizeof(vfpinstr_inst)); 2416 INC_PC(sizeof(vmovbrc_inst));
3038 FETCH_INST; 2417 FETCH_INST;
3039 GOTO_NEXT_INST; 2418 GOTO_NEXT_INST;
3040} 2419}
3041#endif 2420#endif
3042#ifdef VFP_MCR_TRANS 2421
3043if ((OPC_1 & 0x4) == 0 && CoProc == 11 && CRm == 0)
3044{
3045 VFP_DEBUG_UNIMPLEMENTED(VMOVBRC);
3046 return ARMul_DONE;
3047}
3048#endif
3049#ifdef VFP_DYNCOM_TABLE 2422#ifdef VFP_DYNCOM_TABLE
3050DYNCOM_FILL_ACTION(vfpinstr), 2423DYNCOM_FILL_ACTION(vmovbrc),
3051#endif 2424#endif
3052#ifdef VFP_DYNCOM_TAG 2425#ifdef VFP_DYNCOM_TAG
3053int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 2426int DYNCOM_TAG(vmovbrc)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3054{ 2427{
3055 int instr_size = INSTR_SIZE; 2428 int instr_size = INSTR_SIZE;
3056 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2429 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -3059,48 +2432,30 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
3059} 2432}
3060#endif 2433#endif
3061#ifdef VFP_DYNCOM_TRANS 2434#ifdef VFP_DYNCOM_TRANS
3062int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2435int DYNCOM_TRANS(vmovbrc)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3063 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2436 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3064 arch_arm_undef(cpu, bb, instr); 2437 arch_arm_undef(cpu, bb, instr);
3065 return No_exp; 2438 return No_exp;
3066} 2439}
3067#endif 2440#endif
3068#undef vfpinstr
3069#undef vfpinstr_inst
3070#undef VFPLABEL_INST
3071 2441
3072/* ----------------------------------------------------------------------- */ 2442/* ----------------------------------------------------------------------- */
3073/* VMRS */ 2443/* VMRS */
3074/* cond 1110 1111 CRn- Rt-- 1010 0001 0000 */ 2444/* cond 1110 1111 CRn- Rt-- 1010 0001 0000 */
3075/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */ 2445/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MRC */
3076#define vfpinstr vmrs
3077#define vfpinstr_inst vmrs_inst
3078#define VFPLABEL_INST VMRS_INST
3079#ifdef VFP_DECODE
3080{"vmrs", 2, ARMVFP2, 20, 27, 0xEF, 0, 11, 0xa10},
3081#endif
3082#ifdef VFP_DECODE_EXCLUSION
3083{"vmrs", 0, ARMVFP2, 0},
3084#endif
3085#ifdef VFP_INTERPRETER_TABLE
3086INTERPRETER_TRANSLATE(vfpinstr),
3087#endif
3088#ifdef VFP_INTERPRETER_LABEL
3089&&VFPLABEL_INST,
3090#endif
3091#ifdef VFP_INTERPRETER_STRUCT 2446#ifdef VFP_INTERPRETER_STRUCT
3092typedef struct _vmrs_inst { 2447typedef struct _vmrs_inst {
3093 unsigned int reg; 2448 unsigned int reg;
3094 unsigned int Rt; 2449 unsigned int Rt;
3095} vfpinstr_inst; 2450} vmrs_inst;
3096#endif 2451#endif
3097#ifdef VFP_INTERPRETER_TRANS 2452#ifdef VFP_INTERPRETER_TRANS
3098ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2453ARM_INST_PTR INTERPRETER_TRANSLATE(vmrs)(unsigned int inst, int index)
3099{ 2454{
3100 VFP_DEBUG_TRANSLATE; 2455 VFP_DEBUG_TRANSLATE;
3101 2456
3102 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2457 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmrs_inst));
3103 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2458 vmrs_inst *inst_cream = (vmrs_inst *)inst_base->component;
3104 2459
3105 inst_base->cond = BITS(inst, 28, 31); 2460 inst_base->cond = BITS(inst, 28, 31);
3106 inst_base->idx = index; 2461 inst_base->idx = index;
@@ -3109,21 +2464,20 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3109 2464
3110 inst_cream->reg = BITS(inst, 16, 19); 2465 inst_cream->reg = BITS(inst, 16, 19);
3111 inst_cream->Rt = BITS(inst, 12, 15); 2466 inst_cream->Rt = BITS(inst, 12, 15);
3112 2467
3113 return inst_base; 2468 return inst_base;
3114} 2469}
3115#endif 2470#endif
3116#ifdef VFP_INTERPRETER_IMPL 2471#ifdef VFP_INTERPRETER_IMPL
3117VFPLABEL_INST: 2472VMRS_INST:
3118{ 2473{
3119 INC_ICOUNTER;
3120 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2474 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3121 /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled, 2475 /* FIXME: special case for access to FPSID and FPEXC, VFP must be disabled,
3122 and in privilegied mode */ 2476 and in privilegied mode */
3123 /* Exceptions must be checked, according to v7 ref manual */ 2477 /* Exceptions must be checked, according to v7 ref manual */
3124 CHECK_VFP_ENABLED; 2478 CHECK_VFP_ENABLED;
3125 2479
3126 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2480 vmrs_inst *inst_cream = (vmrs_inst *)inst_base->component;
3127 2481
3128 DBG("VMRS :"); 2482 DBG("VMRS :");
3129 2483
@@ -3170,67 +2524,17 @@ VFPLABEL_INST:
3170 } 2524 }
3171 } 2525 }
3172 cpu->Reg[15] += GET_INST_SIZE(cpu); 2526 cpu->Reg[15] += GET_INST_SIZE(cpu);
3173 INC_PC(sizeof(vfpinstr_inst)); 2527 INC_PC(sizeof(vmrs_inst));
3174 FETCH_INST; 2528 FETCH_INST;
3175 GOTO_NEXT_INST; 2529 GOTO_NEXT_INST;
3176} 2530}
3177#endif 2531#endif
3178#ifdef VFP_MRC_TRANS 2532
3179if (OPC_1 == 0x7 && CRm == 0 && OPC_2 == 0)
3180{
3181 VMRS(state, CRn, Rt, value);
3182 return ARMul_DONE;
3183}
3184#endif
3185#ifdef VFP_MRC_IMPL
3186void VMRS(ARMul_State * state, ARMword reg, ARMword Rt, ARMword * value)
3187{
3188 DBG("VMRS :");
3189 if (reg == 1)
3190 {
3191 if (Rt != 15)
3192 {
3193 *value = state->VFP[VFP_OFFSET(VFP_FPSCR)];
3194 DBG("\tr%d <= fpscr[%08x]\n", Rt, state->VFP[VFP_OFFSET(VFP_FPSCR)]);
3195 }
3196 else
3197 {
3198 *value = state->VFP[VFP_OFFSET(VFP_FPSCR)] ;
3199 DBG("\tflags <= fpscr[%1xxxxxxxx]\n", state->VFP[VFP_OFFSET(VFP_FPSCR)]>>28);
3200 }
3201 }
3202 else
3203 {
3204 switch (reg)
3205 {
3206 case 0:
3207 *value = state->VFP[VFP_OFFSET(VFP_FPSID)];
3208 DBG("\tr%d <= fpsid[%08x]\n", Rt, state->VFP[VFP_OFFSET(VFP_FPSID)]);
3209 break;
3210 case 6:
3211 /* MVFR1, VFPv3 only ? */
3212 DBG("\tr%d <= MVFR1 unimplemented\n", Rt);
3213 break;
3214 case 7:
3215 /* MVFR0, VFPv3 only? */
3216 DBG("\tr%d <= MVFR0 unimplemented\n", Rt);
3217 break;
3218 case 8:
3219 *value = state->VFP[VFP_OFFSET(VFP_FPEXC)];
3220 DBG("\tr%d <= fpexc[%08x]\n", Rt, state->VFP[VFP_OFFSET(VFP_FPEXC)]);
3221 break;
3222 default:
3223 DBG("\tSUBARCHITECTURE DEFINED\n");
3224 break;
3225 }
3226 }
3227}
3228#endif
3229#ifdef VFP_DYNCOM_TABLE 2533#ifdef VFP_DYNCOM_TABLE
3230DYNCOM_FILL_ACTION(vfpinstr), 2534DYNCOM_FILL_ACTION(vmrs),
3231#endif 2535#endif
3232#ifdef VFP_DYNCOM_TAG 2536#ifdef VFP_DYNCOM_TAG
3233int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 2537int DYNCOM_TAG(vmrs)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3234{ 2538{
3235 int instr_size = INSTR_SIZE; 2539 int instr_size = INSTR_SIZE;
3236 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2540 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -3241,7 +2545,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
3241} 2545}
3242#endif 2546#endif
3243#ifdef VFP_DYNCOM_TRANS 2547#ifdef VFP_DYNCOM_TRANS
3244int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2548int DYNCOM_TRANS(vmrs)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3245 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2549 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3246 //arch_arm_undef(cpu, bb, instr); 2550 //arch_arm_undef(cpu, bb, instr);
3247 2551
@@ -3292,44 +2596,26 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
3292 return No_exp; 2596 return No_exp;
3293} 2597}
3294#endif 2598#endif
3295#undef vfpinstr
3296#undef vfpinstr_inst
3297#undef VFPLABEL_INST
3298 2599
3299/* ----------------------------------------------------------------------- */ 2600/* ----------------------------------------------------------------------- */
3300/* VMOVBCR scalar to register */ 2601/* VMOVBCR scalar to register */
3301/* cond 1110 XXX1 Vd-- Rt-- 1011 NXX1 0000 */ 2602/* cond 1110 XXX1 Vd-- Rt-- 1011 NXX1 0000 */
3302/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MCR */ 2603/* cond 1110 op11 CRn- Rt-- copr op21 CRm- MCR */
3303#define vfpinstr vmovbcr
3304#define vfpinstr_inst vmovbcr_inst
3305#define VFPLABEL_INST VMOVBCR_INST
3306#ifdef VFP_DECODE
3307{"vmovbcr", 4, ARMVFP2, 24, 27, 0xE, 20, 20, 1, 8, 11,0xB, 0,4, 0x10},
3308#endif
3309#ifdef VFP_DECODE_EXCLUSION
3310{"vmovbcr", 0, ARMVFP2, 0},
3311#endif
3312#ifdef VFP_INTERPRETER_TABLE
3313INTERPRETER_TRANSLATE(vfpinstr),
3314#endif
3315#ifdef VFP_INTERPRETER_LABEL
3316&&VFPLABEL_INST,
3317#endif
3318#ifdef VFP_INTERPRETER_STRUCT 2604#ifdef VFP_INTERPRETER_STRUCT
3319typedef struct _vmovbcr_inst { 2605typedef struct _vmovbcr_inst {
3320 unsigned int esize; 2606 unsigned int esize;
3321 unsigned int index; 2607 unsigned int index;
3322 unsigned int d; 2608 unsigned int d;
3323 unsigned int t; 2609 unsigned int t;
3324} vfpinstr_inst; 2610} vmovbcr_inst;
3325#endif 2611#endif
3326#ifdef VFP_INTERPRETER_TRANS 2612#ifdef VFP_INTERPRETER_TRANS
3327ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2613ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbcr)(unsigned int inst, int index)
3328{ 2614{
3329 VFP_DEBUG_TRANSLATE; 2615 VFP_DEBUG_TRANSLATE;
3330 2616
3331 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2617 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbcr_inst));
3332 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2618 vmovbcr_inst *inst_cream = (vmovbcr_inst *)inst_base->component;
3333 2619
3334 inst_base->cond = BITS(inst, 28, 31); 2620 inst_base->cond = BITS(inst, 28, 31);
3335 inst_base->idx = index; 2621 inst_base->idx = index;
@@ -3346,34 +2632,27 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3346} 2632}
3347#endif 2633#endif
3348#ifdef VFP_INTERPRETER_IMPL 2634#ifdef VFP_INTERPRETER_IMPL
3349VFPLABEL_INST: 2635VMOVBCR_INST:
3350{ 2636{
3351 INC_ICOUNTER;
3352 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2637 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3353 CHECK_VFP_ENABLED; 2638 CHECK_VFP_ENABLED;
3354 2639
3355 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2640 vmovbcr_inst *inst_cream = (vmovbcr_inst *)inst_base->component;
3356 2641
3357 VFP_DEBUG_UNIMPLEMENTED(VMOVBCR); 2642 VFP_DEBUG_UNIMPLEMENTED(VMOVBCR);
3358 } 2643 }
3359 cpu->Reg[15] += GET_INST_SIZE(cpu); 2644 cpu->Reg[15] += GET_INST_SIZE(cpu);
3360 INC_PC(sizeof(vfpinstr_inst)); 2645 INC_PC(sizeof(vmovbcr_inst));
3361 FETCH_INST; 2646 FETCH_INST;
3362 GOTO_NEXT_INST; 2647 GOTO_NEXT_INST;
3363} 2648}
3364#endif 2649#endif
3365#ifdef VFP_MCR_TRANS 2650
3366if (CoProc == 11 && CRm == 0)
3367{
3368 VFP_DEBUG_UNIMPLEMENTED(VMOVBCR);
3369 return ARMul_DONE;
3370}
3371#endif
3372#ifdef VFP_DYNCOM_TABLE 2651#ifdef VFP_DYNCOM_TABLE
3373DYNCOM_FILL_ACTION(vfpinstr), 2652DYNCOM_FILL_ACTION(vmovbcr),
3374#endif 2653#endif
3375#ifdef VFP_DYNCOM_TAG 2654#ifdef VFP_DYNCOM_TAG
3376int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 2655int DYNCOM_TAG(vmovbcr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3377{ 2656{
3378 int instr_size = INSTR_SIZE; 2657 int instr_size = INSTR_SIZE;
3379 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2658 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -3382,15 +2661,12 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
3382} 2661}
3383#endif 2662#endif
3384#ifdef VFP_DYNCOM_TRANS 2663#ifdef VFP_DYNCOM_TRANS
3385int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2664int DYNCOM_TRANS(vmovbcr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3386 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2665 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3387 arch_arm_undef(cpu, bb, instr); 2666 arch_arm_undef(cpu, bb, instr);
3388 return No_exp; 2667 return No_exp;
3389} 2668}
3390#endif 2669#endif
3391#undef vfpinstr
3392#undef vfpinstr_inst
3393#undef VFPLABEL_INST
3394 2670
3395/* ----------------------------------------------------------------------- */ 2671/* ----------------------------------------------------------------------- */
3396/* MRRC / MCRR instructions */ 2672/* MRRC / MCRR instructions */
@@ -3401,36 +2677,21 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
3401/* VMOVBRRSS between 2 registers to 2 singles */ 2677/* VMOVBRRSS between 2 registers to 2 singles */
3402/* cond 1100 010X Rt2- Rt-- 1010 00X1 Vm-- */ 2678/* cond 1100 010X Rt2- Rt-- 1010 00X1 Vm-- */
3403/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */ 2679/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */
3404#define vfpinstr vmovbrrss
3405#define vfpinstr_inst vmovbrrss_inst
3406#define VFPLABEL_INST VMOVBRRSS_INST
3407#ifdef VFP_DECODE
3408{"vmovbrrss", 3, ARMVFP2, 21, 27, 0x62, 8, 11, 0xA, 4, 4, 1},
3409#endif
3410#ifdef VFP_DECODE_EXCLUSION
3411{"vmovbrrss", 0, ARMVFP2, 0},
3412#endif
3413#ifdef VFP_INTERPRETER_TABLE
3414INTERPRETER_TRANSLATE(vfpinstr),
3415#endif
3416#ifdef VFP_INTERPRETER_LABEL
3417&&VFPLABEL_INST,
3418#endif
3419#ifdef VFP_INTERPRETER_STRUCT 2680#ifdef VFP_INTERPRETER_STRUCT
3420typedef struct _vmovbrrss_inst { 2681typedef struct _vmovbrrss_inst {
3421 unsigned int to_arm; 2682 unsigned int to_arm;
3422 unsigned int t; 2683 unsigned int t;
3423 unsigned int t2; 2684 unsigned int t2;
3424 unsigned int m; 2685 unsigned int m;
3425} vfpinstr_inst; 2686} vmovbrrss_inst;
3426#endif 2687#endif
3427#ifdef VFP_INTERPRETER_TRANS 2688#ifdef VFP_INTERPRETER_TRANS
3428ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2689ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrss)(unsigned int inst, int index)
3429{ 2690{
3430 VFP_DEBUG_TRANSLATE; 2691 VFP_DEBUG_TRANSLATE;
3431 2692
3432 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2693 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrss_inst));
3433 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2694 vmovbrrss_inst *inst_cream = (vmovbrrss_inst *)inst_base->component;
3434 2695
3435 inst_base->cond = BITS(inst, 28, 31); 2696 inst_base->cond = BITS(inst, 28, 31);
3436 inst_base->idx = index; 2697 inst_base->idx = index;
@@ -3446,41 +2707,26 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3446} 2707}
3447#endif 2708#endif
3448#ifdef VFP_INTERPRETER_IMPL 2709#ifdef VFP_INTERPRETER_IMPL
3449VFPLABEL_INST: 2710VMOVBRRSS_INST:
3450{ 2711{
3451 INC_ICOUNTER;
3452 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2712 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3453 CHECK_VFP_ENABLED; 2713 CHECK_VFP_ENABLED;
3454 2714
3455 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2715 vmovbrrss_inst *inst_cream = (vmovbrrss_inst *)inst_base->component;
3456 2716
3457 VFP_DEBUG_UNIMPLEMENTED(VMOVBRRSS); 2717 VFP_DEBUG_UNIMPLEMENTED(VMOVBRRSS);
3458 } 2718 }
3459 cpu->Reg[15] += GET_INST_SIZE(cpu); 2719 cpu->Reg[15] += GET_INST_SIZE(cpu);
3460 INC_PC(sizeof(vfpinstr_inst)); 2720 INC_PC(sizeof(vmovbrrss_inst));
3461 FETCH_INST; 2721 FETCH_INST;
3462 GOTO_NEXT_INST; 2722 GOTO_NEXT_INST;
3463} 2723}
3464#endif 2724#endif
3465#ifdef VFP_MCRR_TRANS
3466if (CoProc == 10 && (OPC_1 & 0xD) == 1)
3467{
3468 VFP_DEBUG_UNIMPLEMENTED(VMOVBRRSS);
3469 return ARMul_DONE;
3470}
3471#endif
3472#ifdef VFP_MRRC_TRANS
3473if (CoProc == 10 && (OPC_1 & 0xD) == 1)
3474{
3475 VFP_DEBUG_UNIMPLEMENTED(VMOVBRRSS);
3476 return ARMul_DONE;
3477}
3478#endif
3479#ifdef VFP_DYNCOM_TABLE 2725#ifdef VFP_DYNCOM_TABLE
3480DYNCOM_FILL_ACTION(vfpinstr), 2726DYNCOM_FILL_ACTION(vmovbrrss),
3481#endif 2727#endif
3482#ifdef VFP_DYNCOM_TAG 2728#ifdef VFP_DYNCOM_TAG
3483int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 2729int DYNCOM_TAG(vmovbrrss)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3484{ 2730{
3485 int instr_size = INSTR_SIZE; 2731 int instr_size = INSTR_SIZE;
3486 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2732 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -3489,50 +2735,32 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
3489} 2735}
3490#endif 2736#endif
3491#ifdef VFP_DYNCOM_TRANS 2737#ifdef VFP_DYNCOM_TRANS
3492int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2738int DYNCOM_TRANS(vmovbrrss)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3493 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2739 DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3494 arch_arm_undef(cpu, bb, instr); 2740 arch_arm_undef(cpu, bb, instr);
3495 return No_exp; 2741 return No_exp;
3496} 2742}
3497#endif 2743#endif
3498#undef vfpinstr
3499#undef vfpinstr_inst
3500#undef VFPLABEL_INST
3501 2744
3502/* ----------------------------------------------------------------------- */ 2745/* ----------------------------------------------------------------------- */
3503/* VMOVBRRD between 2 registers and 1 double */ 2746/* VMOVBRRD between 2 registers and 1 double */
3504/* cond 1100 010X Rt2- Rt-- 1011 00X1 Vm-- */ 2747/* cond 1100 010X Rt2- Rt-- 1011 00X1 Vm-- */
3505/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */ 2748/* cond 1100 0101 Rt2- Rt-- copr opc1 CRm- MRRC */
3506#define vfpinstr vmovbrrd
3507#define vfpinstr_inst vmovbrrd_inst
3508#define VFPLABEL_INST VMOVBRRD_INST
3509#ifdef VFP_DECODE
3510{"vmovbrrd", 3, ARMVFP2, 21, 27, 0x62, 6, 11, 0x2c, 4, 4, 1},
3511#endif
3512#ifdef VFP_DECODE_EXCLUSION
3513{"vmovbrrd", 0, ARMVFP2, 0},
3514#endif
3515#ifdef VFP_INTERPRETER_TABLE
3516INTERPRETER_TRANSLATE(vfpinstr),
3517#endif
3518#ifdef VFP_INTERPRETER_LABEL
3519&&VFPLABEL_INST,
3520#endif
3521#ifdef VFP_INTERPRETER_STRUCT 2749#ifdef VFP_INTERPRETER_STRUCT
3522typedef struct _vmovbrrd_inst { 2750typedef struct _vmovbrrd_inst {
3523 unsigned int to_arm; 2751 unsigned int to_arm;
3524 unsigned int t; 2752 unsigned int t;
3525 unsigned int t2; 2753 unsigned int t2;
3526 unsigned int m; 2754 unsigned int m;
3527} vfpinstr_inst; 2755} vmovbrrd_inst;
3528#endif 2756#endif
3529#ifdef VFP_INTERPRETER_TRANS 2757#ifdef VFP_INTERPRETER_TRANS
3530ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2758ARM_INST_PTR INTERPRETER_TRANSLATE(vmovbrrd)(unsigned int inst, int index)
3531{ 2759{
3532 VFP_DEBUG_TRANSLATE; 2760 VFP_DEBUG_TRANSLATE;
3533 2761
3534 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2762 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vmovbrrd_inst));
3535 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2763 vmovbrrd_inst *inst_cream = (vmovbrrd_inst *)inst_base->component;
3536 2764
3537 inst_base->cond = BITS(inst, 28, 31); 2765 inst_base->cond = BITS(inst, 28, 31);
3538 inst_base->idx = index; 2766 inst_base->idx = index;
@@ -3548,63 +2776,28 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3548} 2776}
3549#endif 2777#endif
3550#ifdef VFP_INTERPRETER_IMPL 2778#ifdef VFP_INTERPRETER_IMPL
3551VFPLABEL_INST: 2779VMOVBRRD_INST:
3552{ 2780{
3553 INC_ICOUNTER;
3554 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2781 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3555 CHECK_VFP_ENABLED; 2782 CHECK_VFP_ENABLED;
3556 2783
3557 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2784 vmovbrrd_inst *inst_cream = (vmovbrrd_inst *)inst_base->component;
3558 2785
3559 VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, 2786 VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m,
3560 &(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2])); 2787 &(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2]));
3561 } 2788 }
3562 cpu->Reg[15] += GET_INST_SIZE(cpu); 2789 cpu->Reg[15] += GET_INST_SIZE(cpu);
3563 INC_PC(sizeof(vfpinstr_inst)); 2790 INC_PC(sizeof(vmovbrrd_inst));
3564 FETCH_INST; 2791 FETCH_INST;
3565 GOTO_NEXT_INST; 2792 GOTO_NEXT_INST;
3566} 2793}
3567#endif 2794#endif
3568#ifdef VFP_MCRR_TRANS
3569if (CoProc == 11 && (OPC_1 & 0xD) == 1)
3570{
3571 /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
3572 VMOVBRRD(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, &value1, &value2);
3573 return ARMul_DONE;
3574}
3575#endif
3576#ifdef VFP_MRRC_TRANS
3577if (CoProc == 11 && (OPC_1 & 0xD) == 1)
3578{
3579 /* Transfering Rt and Rt2 is not mandatory, as the value of interest is pointed by value1 and value2 */
3580 VMOVBRRD(state, BIT(20), Rt, Rt2, BIT(5)<<4|CRm, value1, value2);
3581 return ARMul_DONE;
3582}
3583#endif
3584#ifdef VFP_MRRC_IMPL
3585void VMOVBRRD(ARMul_State * state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword *value1, ARMword *value2)
3586{
3587 DBG("VMOV(BRRD) :\n");
3588 if (to_arm)
3589 {
3590 DBG("\tr[%d-%d] <= s[%d-%d]=[%x-%x]\n", t2, t, n*2+1, n*2, state->ExtReg[n*2+1], state->ExtReg[n*2]);
3591 *value2 = state->ExtReg[n*2+1];
3592 *value1 = state->ExtReg[n*2];
3593 }
3594 else
3595 {
3596 DBG("\ts[%d-%d] <= r[%d-%d]=[%x-%x]\n", n*2+1, n*2, t2, t, *value2, *value1);
3597 state->ExtReg[n*2+1] = *value2;
3598 state->ExtReg[n*2] = *value1;
3599 }
3600}
3601 2795
3602#endif
3603#ifdef VFP_DYNCOM_TABLE 2796#ifdef VFP_DYNCOM_TABLE
3604DYNCOM_FILL_ACTION(vfpinstr), 2797DYNCOM_FILL_ACTION(vmovbrrd),
3605#endif 2798#endif
3606#ifdef VFP_DYNCOM_TAG 2799#ifdef VFP_DYNCOM_TAG
3607int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 2800int DYNCOM_TAG(vmovbrrd)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3608{ 2801{
3609 int instr_size = INSTR_SIZE; 2802 int instr_size = INSTR_SIZE;
3610 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2803 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -3615,7 +2808,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
3615} 2808}
3616#endif 2809#endif
3617#ifdef VFP_DYNCOM_TRANS 2810#ifdef VFP_DYNCOM_TRANS
3618int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2811int DYNCOM_TRANS(vmovbrrd)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3619 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 2812 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
3620 //arch_arm_undef(cpu, bb, instr); 2813 //arch_arm_undef(cpu, bb, instr);
3621 int to_arm = BIT(20) == 1; 2814 int to_arm = BIT(20) == 1;
@@ -3633,9 +2826,6 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
3633 return No_exp; 2826 return No_exp;
3634} 2827}
3635#endif 2828#endif
3636#undef vfpinstr
3637#undef vfpinstr_inst
3638#undef VFPLABEL_INST
3639 2829
3640/* ----------------------------------------------------------------------- */ 2830/* ----------------------------------------------------------------------- */
3641/* LDC/STC between 2 registers and 1 double */ 2831/* LDC/STC between 2 registers and 1 double */
@@ -3645,21 +2835,6 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
3645/* ----------------------------------------------------------------------- */ 2835/* ----------------------------------------------------------------------- */
3646/* VSTR */ 2836/* VSTR */
3647/* cond 1101 UD00 Rn-- Vd-- 101X imm8 imm8 */ 2837/* cond 1101 UD00 Rn-- Vd-- 101X imm8 imm8 */
3648#define vfpinstr vstr
3649#define vfpinstr_inst vstr_inst
3650#define VFPLABEL_INST VSTR_INST
3651#ifdef VFP_DECODE
3652{"vstr", 3, ARMVFP2, 24, 27, 0xd, 20, 21, 0, 9, 11, 0x5},
3653#endif
3654#ifdef VFP_DECODE_EXCLUSION
3655{"vstr", 0, ARMVFP2, 0},
3656#endif
3657#ifdef VFP_INTERPRETER_TABLE
3658INTERPRETER_TRANSLATE(vfpinstr),
3659#endif
3660#ifdef VFP_INTERPRETER_LABEL
3661&&VFPLABEL_INST,
3662#endif
3663#ifdef VFP_INTERPRETER_STRUCT 2838#ifdef VFP_INTERPRETER_STRUCT
3664typedef struct _vstr_inst { 2839typedef struct _vstr_inst {
3665 unsigned int single; 2840 unsigned int single;
@@ -3667,15 +2842,15 @@ typedef struct _vstr_inst {
3667 unsigned int d; 2842 unsigned int d;
3668 unsigned int imm32; 2843 unsigned int imm32;
3669 unsigned int add; 2844 unsigned int add;
3670} vfpinstr_inst; 2845} vstr_inst;
3671#endif 2846#endif
3672#ifdef VFP_INTERPRETER_TRANS 2847#ifdef VFP_INTERPRETER_TRANS
3673ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2848ARM_INST_PTR INTERPRETER_TRANSLATE(vstr)(unsigned int inst, int index)
3674{ 2849{
3675 VFP_DEBUG_TRANSLATE; 2850 VFP_DEBUG_TRANSLATE;
3676 2851
3677 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2852 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vstr_inst));
3678 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2853 vstr_inst *inst_cream = (vstr_inst *)inst_base->component;
3679 2854
3680 inst_base->cond = BITS(inst, 28, 31); 2855 inst_base->cond = BITS(inst, 28, 31);
3681 inst_base->idx = index; 2856 inst_base->idx = index;
@@ -3692,13 +2867,12 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3692} 2867}
3693#endif 2868#endif
3694#ifdef VFP_INTERPRETER_IMPL 2869#ifdef VFP_INTERPRETER_IMPL
3695VFPLABEL_INST: 2870VSTR_INST:
3696{ 2871{
3697 INC_ICOUNTER;
3698 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 2872 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3699 CHECK_VFP_ENABLED; 2873 CHECK_VFP_ENABLED;
3700 2874
3701 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2875 vstr_inst *inst_cream = (vstr_inst *)inst_base->component;
3702 2876
3703 unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 : cpu->Reg[inst_cream->n]); 2877 unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 : cpu->Reg[inst_cream->n]);
3704 addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32); 2878 addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32);
@@ -3736,65 +2910,12 @@ VFPLABEL_INST:
3736 GOTO_NEXT_INST; 2910 GOTO_NEXT_INST;
3737} 2911}
3738#endif 2912#endif
3739#ifdef VFP_STC_TRANS
3740if (P == 1 && W == 0)
3741{
3742 return VSTR(state, type, instr, value);
3743}
3744#endif
3745#ifdef VFP_STC_IMPL
3746int VSTR(ARMul_State * state, int type, ARMword instr, ARMword * value)
3747{
3748 static int i = 0;
3749 static int single_reg, add, d, n, imm32, regs;
3750 if (type == ARMul_FIRST)
3751 {
3752 single_reg = BIT(8) == 0; /* Double precision */
3753 add = BIT(23); /* */
3754 imm32 = BITS(0,7)<<2; /* may not be used */
3755 d = single_reg ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
3756 n = BITS(16, 19); /* destination register */
3757
3758 DBG("VSTR :\n");
3759
3760 i = 0;
3761 regs = 1;
3762
3763 return ARMul_DONE;
3764 }
3765 else if (type == ARMul_DATA)
3766 {
3767 if (single_reg)
3768 {
3769 *value = state->ExtReg[d+i];
3770 DBG("\taddr[?] <= s%d=[%x]\n", d+i, state->ExtReg[d+i]);
3771 i++;
3772 if (i < regs)
3773 return ARMul_INC;
3774 else
3775 return ARMul_DONE;
3776 }
3777 else
3778 {
3779 /* FIXME Careful of endianness, may need to rework this */
3780 *value = state->ExtReg[d*2+i];
3781 DBG("\taddr[?] <= s[%d]=[%x]\n", d*2+i, state->ExtReg[d*2+i]);
3782 i++;
3783 if (i < regs*2)
3784 return ARMul_INC;
3785 else
3786 return ARMul_DONE;
3787 }
3788 }
3789 2913
3790 return -1;
3791}
3792#endif
3793#ifdef VFP_DYNCOM_TABLE 2914#ifdef VFP_DYNCOM_TABLE
3794DYNCOM_FILL_ACTION(vfpinstr), 2915DYNCOM_FILL_ACTION(vstr),
3795#endif 2916#endif
3796#ifdef VFP_DYNCOM_TAG 2917#ifdef VFP_DYNCOM_TAG
3797int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 2918int DYNCOM_TAG(vstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
3798{ 2919{
3799 int instr_size = INSTR_SIZE; 2920 int instr_size = INSTR_SIZE;
3800 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc); 2921 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
@@ -3807,7 +2928,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
3807} 2928}
3808#endif 2929#endif
3809#ifdef VFP_DYNCOM_TRANS 2930#ifdef VFP_DYNCOM_TRANS
3810int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 2931int DYNCOM_TRANS(vstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
3811 int single = BIT(8) == 0; 2932 int single = BIT(8) == 0;
3812 int add = BIT(23); 2933 int add = BIT(23);
3813 int imm32 = BITS(0,7) << 2; 2934 int imm32 = BITS(0,7) << 2;
@@ -3853,43 +2974,25 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
3853 return No_exp; 2974 return No_exp;
3854} 2975}
3855#endif 2976#endif
3856#undef vfpinstr
3857#undef vfpinstr_inst
3858#undef VFPLABEL_INST
3859 2977
3860/* ----------------------------------------------------------------------- */ 2978/* ----------------------------------------------------------------------- */
3861/* VPUSH */ 2979/* VPUSH */
3862/* cond 1101 0D10 1101 Vd-- 101X imm8 imm8 */ 2980/* cond 1101 0D10 1101 Vd-- 101X imm8 imm8 */
3863#define vfpinstr vpush
3864#define vfpinstr_inst vpush_inst
3865#define VFPLABEL_INST VPUSH_INST
3866#ifdef VFP_DECODE
3867{"vpush", 3, ARMVFP2, 23, 27, 0x1a, 16, 21, 0x2d, 9, 11, 0x5},
3868#endif
3869#ifdef VFP_DECODE_EXCLUSION
3870{"vpush", 0, ARMVFP2, 0},
3871#endif
3872#ifdef VFP_INTERPRETER_TABLE
3873INTERPRETER_TRANSLATE(vfpinstr),
3874#endif
3875#ifdef VFP_INTERPRETER_LABEL
3876&&VFPLABEL_INST,
3877#endif
3878#ifdef VFP_INTERPRETER_STRUCT 2981#ifdef VFP_INTERPRETER_STRUCT
3879typedef struct _vpush_inst { 2982typedef struct _vpush_inst {
3880 unsigned int single; 2983 unsigned int single;
3881 unsigned int d; 2984 unsigned int d;
3882 unsigned int imm32; 2985 unsigned int imm32;
3883 unsigned int regs; 2986 unsigned int regs;
3884} vfpinstr_inst; 2987} vpush_inst;
3885#endif 2988#endif
3886#ifdef VFP_INTERPRETER_TRANS 2989#ifdef VFP_INTERPRETER_TRANS
3887ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 2990ARM_INST_PTR INTERPRETER_TRANSLATE(vpush)(unsigned int inst, int index)
3888{ 2991{
3889 VFP_DEBUG_TRANSLATE; 2992 VFP_DEBUG_TRANSLATE;
3890 2993
3891 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 2994 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vpush_inst));
3892 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 2995 vpush_inst *inst_cream = (vpush_inst *)inst_base->component;
3893 2996
3894 inst_base->cond = BITS(inst, 28, 31); 2997 inst_base->cond = BITS(inst, 28, 31);
3895 inst_base->idx = index; 2998 inst_base->idx = index;
@@ -3905,15 +3008,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
3905} 3008}
3906#endif 3009#endif
3907#ifdef VFP_INTERPRETER_IMPL 3010#ifdef VFP_INTERPRETER_IMPL
3908VFPLABEL_INST: 3011VPUSH_INST:
3909{ 3012{
3910 INC_ICOUNTER;
3911 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 3013 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
3912 CHECK_VFP_ENABLED; 3014 CHECK_VFP_ENABLED;
3913 3015
3914 int i; 3016 int i;
3915 3017
3916 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3018 vpush_inst *inst_cream = (vpush_inst *)inst_base->component;
3917 3019
3918 DBG("VPUSH :\n"); 3020 DBG("VPUSH :\n");
3919 3021
@@ -3958,66 +3060,11 @@ VFPLABEL_INST:
3958 GOTO_NEXT_INST; 3060 GOTO_NEXT_INST;
3959} 3061}
3960#endif 3062#endif
3961#ifdef VFP_STC_TRANS
3962if (P == 1 && U == 0 && W == 1 && Rn == 0xD)
3963{
3964 return VPUSH(state, type, instr, value);
3965}
3966#endif
3967#ifdef VFP_STC_IMPL
3968int VPUSH(ARMul_State * state, int type, ARMword instr, ARMword * value)
3969{
3970 static int i = 0;
3971 static int single_regs, add, wback, d, n, imm32, regs;
3972 if (type == ARMul_FIRST)
3973 {
3974 single_regs = BIT(8) == 0; /* Single precision */
3975 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
3976 imm32 = BITS(0,7)<<2; /* may not be used */
3977 regs = single_regs ? BITS(0, 7) : BITS(1, 7); /* FSTMX if regs is odd */
3978
3979 DBG("VPUSH :\n");
3980 DBG("\tsp[%x]", state->Reg[R13]);
3981 state->Reg[R13] = state->Reg[R13] - imm32;
3982 DBG("=>[%x]\n", state->Reg[R13]);
3983
3984 i = 0;
3985
3986 return ARMul_DONE;
3987 }
3988 else if (type == ARMul_DATA)
3989 {
3990 if (single_regs)
3991 {
3992 *value = state->ExtReg[d + i];
3993 DBG("\taddr[?] <= s%d=[%x]\n", d+i, state->ExtReg[d + i]);
3994 i++;
3995 if (i < regs)
3996 return ARMul_INC;
3997 else
3998 return ARMul_DONE;
3999 }
4000 else
4001 {
4002 /* FIXME Careful of endianness, may need to rework this */
4003 *value = state->ExtReg[d*2 + i];
4004 DBG("\taddr[?] <= s[%d]=[%x]\n", d*2 + i, state->ExtReg[d*2 + i]);
4005 i++;
4006 if (i < regs*2)
4007 return ARMul_INC;
4008 else
4009 return ARMul_DONE;
4010 }
4011 }
4012
4013 return -1;
4014}
4015#endif
4016#ifdef VFP_DYNCOM_TABLE 3063#ifdef VFP_DYNCOM_TABLE
4017DYNCOM_FILL_ACTION(vfpinstr), 3064DYNCOM_FILL_ACTION(vpush),
4018#endif 3065#endif
4019#ifdef VFP_DYNCOM_TAG 3066#ifdef VFP_DYNCOM_TAG
4020int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 3067int DYNCOM_TAG(vpush)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
4021{ 3068{
4022 int instr_size = INSTR_SIZE; 3069 int instr_size = INSTR_SIZE;
4023 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc); 3070 arm_tag_continue(cpu, pc, instr, tag, new_pc, next_pc);
@@ -4030,7 +3077,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
4030} 3077}
4031#endif 3078#endif
4032#ifdef VFP_DYNCOM_TRANS 3079#ifdef VFP_DYNCOM_TRANS
4033int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 3080int DYNCOM_TRANS(vpush)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
4034 int single = BIT(8) == 0; 3081 int single = BIT(8) == 0;
4035 int d = (single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|(BIT(22)<<4)); 3082 int d = (single ? BITS(12, 15)<<1|BIT(22) : BITS(12, 15)|(BIT(22)<<4));
4036 int imm32 = BITS(0, 7)<<2; 3083 int imm32 = BITS(0, 7)<<2;
@@ -4087,28 +3134,10 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
4087 return No_exp; 3134 return No_exp;
4088} 3135}
4089#endif 3136#endif
4090#undef vfpinstr
4091#undef vfpinstr_inst
4092#undef VFPLABEL_INST
4093 3137
4094/* ----------------------------------------------------------------------- */ 3138/* ----------------------------------------------------------------------- */
4095/* VSTM */ 3139/* VSTM */
4096/* cond 110P UDW0 Rn-- Vd-- 101X imm8 imm8 */ 3140/* cond 110P UDW0 Rn-- Vd-- 101X imm8 imm8 */
4097#define vfpinstr vstm
4098#define vfpinstr_inst vstm_inst
4099#define VFPLABEL_INST VSTM_INST
4100#ifdef VFP_DECODE
4101{"vstm", 3, ARMVFP2, 25, 27, 0x6, 20, 20, 0, 9, 11, 0x5},
4102#endif
4103#ifdef VFP_DECODE_EXCLUSION
4104{"vstm", 0, ARMVFP2, 0},
4105#endif
4106#ifdef VFP_INTERPRETER_TABLE
4107INTERPRETER_TRANSLATE(vfpinstr),
4108#endif
4109#ifdef VFP_INTERPRETER_LABEL
4110&&VFPLABEL_INST,
4111#endif
4112#ifdef VFP_INTERPRETER_STRUCT 3141#ifdef VFP_INTERPRETER_STRUCT
4113typedef struct _vstm_inst { 3142typedef struct _vstm_inst {
4114 unsigned int single; 3143 unsigned int single;
@@ -4118,15 +3147,15 @@ typedef struct _vstm_inst {
4118 unsigned int n; 3147 unsigned int n;
4119 unsigned int imm32; 3148 unsigned int imm32;
4120 unsigned int regs; 3149 unsigned int regs;
4121} vfpinstr_inst; 3150} vstm_inst;
4122#endif 3151#endif
4123#ifdef VFP_INTERPRETER_TRANS 3152#ifdef VFP_INTERPRETER_TRANS
4124ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 3153ARM_INST_PTR INTERPRETER_TRANSLATE(vstm)(unsigned int inst, int index)
4125{ 3154{
4126 VFP_DEBUG_TRANSLATE; 3155 VFP_DEBUG_TRANSLATE;
4127 3156
4128 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 3157 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vstm_inst));
4129 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3158 vstm_inst *inst_cream = (vstm_inst *)inst_base->component;
4130 3159
4131 inst_base->cond = BITS(inst, 28, 31); 3160 inst_base->cond = BITS(inst, 28, 31);
4132 inst_base->idx = index; 3161 inst_base->idx = index;
@@ -4145,15 +3174,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
4145} 3174}
4146#endif 3175#endif
4147#ifdef VFP_INTERPRETER_IMPL 3176#ifdef VFP_INTERPRETER_IMPL
4148VFPLABEL_INST: /* encoding 1 */ 3177VSTM_INST: /* encoding 1 */
4149{ 3178{
4150 INC_ICOUNTER;
4151 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 3179 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4152 CHECK_VFP_ENABLED; 3180 CHECK_VFP_ENABLED;
4153 3181
4154 int i; 3182 int i;
4155 3183
4156 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3184 vstm_inst *inst_cream = (vstm_inst *)inst_base->component;
4157 3185
4158 addr = (inst_cream->add ? cpu->Reg[inst_cream->n] : cpu->Reg[inst_cream->n] - inst_cream->imm32); 3186 addr = (inst_cream->add ? cpu->Reg[inst_cream->n] : cpu->Reg[inst_cream->n] - inst_cream->imm32);
4159 DBG("VSTM : addr[%x]\n", addr); 3187 DBG("VSTM : addr[%x]\n", addr);
@@ -4203,69 +3231,12 @@ VFPLABEL_INST: /* encoding 1 */
4203 GOTO_NEXT_INST; 3231 GOTO_NEXT_INST;
4204} 3232}
4205#endif 3233#endif
4206#ifdef VFP_STC_TRANS
4207/* Should be the last operation of STC */
4208return VSTM(state, type, instr, value);
4209#endif
4210#ifdef VFP_STC_IMPL
4211int VSTM(ARMul_State * state, int type, ARMword instr, ARMword * value)
4212{
4213 static int i = 0;
4214 static int single_regs, add, wback, d, n, imm32, regs;
4215 if (type == ARMul_FIRST)
4216 {
4217 single_regs = BIT(8) == 0; /* Single precision */
4218 add = BIT(23); /* */
4219 wback = BIT(21); /* write-back */
4220 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
4221 n = BITS(16, 19); /* destination register */
4222 imm32 = BITS(0,7) * 4; /* may not be used */
4223 regs = single_regs ? BITS(0, 7) : BITS(0, 7)>>1; /* FSTMX if regs is odd */
4224
4225 DBG("VSTM :\n");
4226
4227 if (wback) {
4228 state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
4229 DBG("\twback r%d[%x]\n", n, state->Reg[n]);
4230 }
4231
4232 i = 0;
4233
4234 return ARMul_DONE;
4235 }
4236 else if (type == ARMul_DATA)
4237 {
4238 if (single_regs)
4239 {
4240 *value = state->ExtReg[d + i];
4241 DBG("\taddr[?] <= s%d=[%x]\n", d+i, state->ExtReg[d + i]);
4242 i++;
4243 if (i < regs)
4244 return ARMul_INC;
4245 else
4246 return ARMul_DONE;
4247 }
4248 else
4249 {
4250 /* FIXME Careful of endianness, may need to rework this */
4251 *value = state->ExtReg[d*2 + i];
4252 DBG("\taddr[?] <= s[%d]=[%x]\n", d*2 + i, state->ExtReg[d*2 + i]);
4253 i++;
4254 if (i < regs*2)
4255 return ARMul_INC;
4256 else
4257 return ARMul_DONE;
4258 }
4259 }
4260 3234
4261 return -1;
4262}
4263#endif
4264#ifdef VFP_DYNCOM_TABLE 3235#ifdef VFP_DYNCOM_TABLE
4265DYNCOM_FILL_ACTION(vfpinstr), 3236DYNCOM_FILL_ACTION(vstm),
4266#endif 3237#endif
4267#ifdef VFP_DYNCOM_TAG 3238#ifdef VFP_DYNCOM_TAG
4268int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 3239int DYNCOM_TAG(vstm)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
4269{ 3240{
4270 int instr_size = INSTR_SIZE; 3241 int instr_size = INSTR_SIZE;
4271 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 3242 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -4280,7 +3251,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
4280} 3251}
4281#endif 3252#endif
4282#ifdef VFP_DYNCOM_TRANS 3253#ifdef VFP_DYNCOM_TRANS
4283int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 3254int DYNCOM_TRANS(vstm)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
4284 //arch_arm_undef(cpu, bb, instr); 3255 //arch_arm_undef(cpu, bb, instr);
4285 int single = BIT(8) == 0; 3256 int single = BIT(8) == 0;
4286 int add = BIT(23); 3257 int add = BIT(23);
@@ -4356,43 +3327,25 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
4356 return No_exp; 3327 return No_exp;
4357} 3328}
4358#endif 3329#endif
4359#undef vfpinstr
4360#undef vfpinstr_inst
4361#undef VFPLABEL_INST
4362 3330
4363/* ----------------------------------------------------------------------- */ 3331/* ----------------------------------------------------------------------- */
4364/* VPOP */ 3332/* VPOP */
4365/* cond 1100 1D11 1101 Vd-- 101X imm8 imm8 */ 3333/* cond 1100 1D11 1101 Vd-- 101X imm8 imm8 */
4366#define vfpinstr vpop
4367#define vfpinstr_inst vpop_inst
4368#define VFPLABEL_INST VPOP_INST
4369#ifdef VFP_DECODE
4370{"vpop", 3, ARMVFP2, 23, 27, 0x19, 16, 21, 0x3d, 9, 11, 0x5},
4371#endif
4372#ifdef VFP_DECODE_EXCLUSION
4373{"vpop", 0, ARMVFP2, 0},
4374#endif
4375#ifdef VFP_INTERPRETER_TABLE
4376INTERPRETER_TRANSLATE(vfpinstr),
4377#endif
4378#ifdef VFP_INTERPRETER_LABEL
4379&&VFPLABEL_INST,
4380#endif
4381#ifdef VFP_INTERPRETER_STRUCT 3334#ifdef VFP_INTERPRETER_STRUCT
4382typedef struct _vpop_inst { 3335typedef struct _vpop_inst {
4383 unsigned int single; 3336 unsigned int single;
4384 unsigned int d; 3337 unsigned int d;
4385 unsigned int imm32; 3338 unsigned int imm32;
4386 unsigned int regs; 3339 unsigned int regs;
4387} vfpinstr_inst; 3340} vpop_inst;
4388#endif 3341#endif
4389#ifdef VFP_INTERPRETER_TRANS 3342#ifdef VFP_INTERPRETER_TRANS
4390ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 3343ARM_INST_PTR INTERPRETER_TRANSLATE(vpop)(unsigned int inst, int index)
4391{ 3344{
4392 VFP_DEBUG_TRANSLATE; 3345 VFP_DEBUG_TRANSLATE;
4393 3346
4394 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 3347 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vpop_inst));
4395 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3348 vpop_inst *inst_cream = (vpop_inst *)inst_base->component;
4396 3349
4397 inst_base->cond = BITS(inst, 28, 31); 3350 inst_base->cond = BITS(inst, 28, 31);
4398 inst_base->idx = index; 3351 inst_base->idx = index;
@@ -4408,16 +3361,15 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
4408} 3361}
4409#endif 3362#endif
4410#ifdef VFP_INTERPRETER_IMPL 3363#ifdef VFP_INTERPRETER_IMPL
4411VFPLABEL_INST: 3364VPOP_INST:
4412{ 3365{
4413 INC_ICOUNTER;
4414 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 3366 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4415 CHECK_VFP_ENABLED; 3367 CHECK_VFP_ENABLED;
4416 3368
4417 int i; 3369 int i;
4418 unsigned int value1, value2; 3370 unsigned int value1, value2;
4419 3371
4420 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3372 vpop_inst *inst_cream = (vpop_inst *)inst_base->component;
4421 3373
4422 DBG("VPOP :\n"); 3374 DBG("VPOP :\n");
4423 3375
@@ -4468,70 +3420,12 @@ VFPLABEL_INST:
4468 GOTO_NEXT_INST; 3420 GOTO_NEXT_INST;
4469} 3421}
4470#endif 3422#endif
4471#ifdef VFP_LDC_TRANS
4472if (P == 0 && U == 1 && W == 1 && Rn == 0xD)
4473{
4474 return VPOP(state, type, instr, value);
4475}
4476#endif
4477#ifdef VFP_LDC_IMPL
4478int VPOP(ARMul_State * state, int type, ARMword instr, ARMword value)
4479{
4480 static int i = 0;
4481 static int single_regs, add, wback, d, n, imm32, regs;
4482 if (type == ARMul_FIRST)
4483 {
4484 single_regs = BIT(8) == 0; /* Single precision */
4485 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
4486 imm32 = BITS(0,7)<<2; /* may not be used */
4487 regs = single_regs ? BITS(0, 7) : BITS(1, 7); /* FLDMX if regs is odd */
4488 3423
4489 DBG("VPOP :\n");
4490 DBG("\tsp[%x]", state->Reg[R13]);
4491 state->Reg[R13] = state->Reg[R13] + imm32;
4492 DBG("=>[%x]\n", state->Reg[R13]);
4493
4494 i = 0;
4495
4496 return ARMul_DONE;
4497 }
4498 else if (type == ARMul_TRANSFER)
4499 {
4500 return ARMul_DONE;
4501 }
4502 else if (type == ARMul_DATA)
4503 {
4504 if (single_regs)
4505 {
4506 state->ExtReg[d + i] = value;
4507 DBG("\ts%d <= [%x]\n", d + i, value);
4508 i++;
4509 if (i < regs)
4510 return ARMul_INC;
4511 else
4512 return ARMul_DONE;
4513 }
4514 else
4515 {
4516 /* FIXME Careful of endianness, may need to rework this */
4517 state->ExtReg[d*2 + i] = value;
4518 DBG("\ts%d <= [%x]\n", d*2 + i, value);
4519 i++;
4520 if (i < regs*2)
4521 return ARMul_INC;
4522 else
4523 return ARMul_DONE;
4524 }
4525 }
4526
4527 return -1;
4528}
4529#endif
4530#ifdef VFP_DYNCOM_TABLE 3424#ifdef VFP_DYNCOM_TABLE
4531DYNCOM_FILL_ACTION(vfpinstr), 3425DYNCOM_FILL_ACTION(vpop),
4532#endif 3426#endif
4533#ifdef VFP_DYNCOM_TAG 3427#ifdef VFP_DYNCOM_TAG
4534int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 3428int DYNCOM_TAG(vpop)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
4535{ 3429{
4536 int instr_size = INSTR_SIZE; 3430 int instr_size = INSTR_SIZE;
4537 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 3431 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -4547,7 +3441,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
4547} 3441}
4548#endif 3442#endif
4549#ifdef VFP_DYNCOM_TRANS 3443#ifdef VFP_DYNCOM_TRANS
4550int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 3444int DYNCOM_TRANS(vpop)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
4551 DBG("\t\tin %s instruction .\n", __FUNCTION__); 3445 DBG("\t\tin %s instruction .\n", __FUNCTION__);
4552 //arch_arm_undef(cpu, bb, instr); 3446 //arch_arm_undef(cpu, bb, instr);
4553 int single = BIT(8) == 0; 3447 int single = BIT(8) == 0;
@@ -4611,28 +3505,10 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
4611 return No_exp; 3505 return No_exp;
4612} 3506}
4613#endif 3507#endif
4614#undef vfpinstr
4615#undef vfpinstr_inst
4616#undef VFPLABEL_INST
4617 3508
4618/* ----------------------------------------------------------------------- */ 3509/* ----------------------------------------------------------------------- */
4619/* VLDR */ 3510/* VLDR */
4620/* cond 1101 UD01 Rn-- Vd-- 101X imm8 imm8 */ 3511/* cond 1101 UD01 Rn-- Vd-- 101X imm8 imm8 */
4621#define vfpinstr vldr
4622#define vfpinstr_inst vldr_inst
4623#define VFPLABEL_INST VLDR_INST
4624#ifdef VFP_DECODE
4625{"vldr", 3, ARMVFP2, 24, 27, 0xd, 20, 21, 0x1, 9, 11, 0x5},
4626#endif
4627#ifdef VFP_DECODE_EXCLUSION
4628{"vldr", 0, ARMVFP2, 0},
4629#endif
4630#ifdef VFP_INTERPRETER_TABLE
4631INTERPRETER_TRANSLATE(vfpinstr),
4632#endif
4633#ifdef VFP_INTERPRETER_LABEL
4634&&VFPLABEL_INST,
4635#endif
4636#ifdef VFP_INTERPRETER_STRUCT 3512#ifdef VFP_INTERPRETER_STRUCT
4637typedef struct _vldr_inst { 3513typedef struct _vldr_inst {
4638 unsigned int single; 3514 unsigned int single;
@@ -4640,15 +3516,15 @@ typedef struct _vldr_inst {
4640 unsigned int d; 3516 unsigned int d;
4641 unsigned int imm32; 3517 unsigned int imm32;
4642 unsigned int add; 3518 unsigned int add;
4643} vfpinstr_inst; 3519} vldr_inst;
4644#endif 3520#endif
4645#ifdef VFP_INTERPRETER_TRANS 3521#ifdef VFP_INTERPRETER_TRANS
4646ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 3522ARM_INST_PTR INTERPRETER_TRANSLATE(vldr)(unsigned int inst, int index)
4647{ 3523{
4648 VFP_DEBUG_TRANSLATE; 3524 VFP_DEBUG_TRANSLATE;
4649 3525
4650 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 3526 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vldr_inst));
4651 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3527 vldr_inst *inst_cream = (vldr_inst *)inst_base->component;
4652 3528
4653 inst_base->cond = BITS(inst, 28, 31); 3529 inst_base->cond = BITS(inst, 28, 31);
4654 inst_base->idx = index; 3530 inst_base->idx = index;
@@ -4665,13 +3541,12 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
4665} 3541}
4666#endif 3542#endif
4667#ifdef VFP_INTERPRETER_IMPL 3543#ifdef VFP_INTERPRETER_IMPL
4668VFPLABEL_INST: 3544VLDR_INST:
4669{ 3545{
4670 INC_ICOUNTER;
4671 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 3546 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4672 CHECK_VFP_ENABLED; 3547 CHECK_VFP_ENABLED;
4673 3548
4674 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3549 vldr_inst *inst_cream = (vldr_inst *)inst_base->component;
4675 3550
4676 unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 : cpu->Reg[inst_cream->n]); 3551 unsigned int base = (inst_cream->n == 15 ? (cpu->Reg[inst_cream->n] & 0xFFFFFFFC) + 8 : cpu->Reg[inst_cream->n]);
4677 addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32); 3552 addr = (inst_cream->add ? base + inst_cream->imm32 : base - inst_cream->imm32);
@@ -4710,69 +3585,12 @@ VFPLABEL_INST:
4710 GOTO_NEXT_INST; 3585 GOTO_NEXT_INST;
4711} 3586}
4712#endif 3587#endif
4713#ifdef VFP_LDC_TRANS
4714if (P == 1 && W == 0)
4715{
4716 return VLDR(state, type, instr, value);
4717}
4718#endif
4719#ifdef VFP_LDC_IMPL
4720int VLDR(ARMul_State * state, int type, ARMword instr, ARMword value)
4721{
4722 static int i = 0;
4723 static int single_reg, add, d, n, imm32, regs;
4724 if (type == ARMul_FIRST)
4725 {
4726 single_reg = BIT(8) == 0; /* Double precision */
4727 add = BIT(23); /* */
4728 imm32 = BITS(0,7)<<2; /* may not be used */
4729 d = single_reg ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
4730 n = BITS(16, 19); /* destination register */
4731
4732 DBG("VLDR :\n");
4733
4734 i = 0;
4735 regs = 1;
4736
4737 return ARMul_DONE;
4738 }
4739 else if (type == ARMul_TRANSFER)
4740 {
4741 return ARMul_DONE;
4742 }
4743 else if (type == ARMul_DATA)
4744 {
4745 if (single_reg)
4746 {
4747 state->ExtReg[d+i] = value;
4748 DBG("\ts%d <= [%x]\n", d+i, value);
4749 i++;
4750 if (i < regs)
4751 return ARMul_INC;
4752 else
4753 return ARMul_DONE;
4754 }
4755 else
4756 {
4757 /* FIXME Careful of endianness, may need to rework this */
4758 state->ExtReg[d*2+i] = value;
4759 DBG("\ts[%d] <= [%x]\n", d*2+i, value);
4760 i++;
4761 if (i < regs*2)
4762 return ARMul_INC;
4763 else
4764 return ARMul_DONE;
4765 }
4766 }
4767 3588
4768 return -1;
4769}
4770#endif
4771#ifdef VFP_DYNCOM_TABLE 3589#ifdef VFP_DYNCOM_TABLE
4772DYNCOM_FILL_ACTION(vfpinstr), 3590DYNCOM_FILL_ACTION(vldr),
4773#endif 3591#endif
4774#ifdef VFP_DYNCOM_TAG 3592#ifdef VFP_DYNCOM_TAG
4775int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 3593int DYNCOM_TAG(vldr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
4776{ 3594{
4777 int instr_size = INSTR_SIZE; 3595 int instr_size = INSTR_SIZE;
4778 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 3596 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -4788,7 +3606,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
4788} 3606}
4789#endif 3607#endif
4790#ifdef VFP_DYNCOM_TRANS 3608#ifdef VFP_DYNCOM_TRANS
4791int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 3609int DYNCOM_TRANS(vldr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
4792 int single = BIT(8) == 0; 3610 int single = BIT(8) == 0;
4793 int add = BIT(23); 3611 int add = BIT(23);
4794 int wback = BIT(21); 3612 int wback = BIT(21);
@@ -4846,28 +3664,10 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
4846 return No_exp; 3664 return No_exp;
4847} 3665}
4848#endif 3666#endif
4849#undef vfpinstr
4850#undef vfpinstr_inst
4851#undef VFPLABEL_INST
4852 3667
4853/* ----------------------------------------------------------------------- */ 3668/* ----------------------------------------------------------------------- */
4854/* VLDM */ 3669/* VLDM */
4855/* cond 110P UDW1 Rn-- Vd-- 101X imm8 imm8 */ 3670/* cond 110P UDW1 Rn-- Vd-- 101X imm8 imm8 */
4856#define vfpinstr vldm
4857#define vfpinstr_inst vldm_inst
4858#define VFPLABEL_INST VLDM_INST
4859#ifdef VFP_DECODE
4860{"vldm", 3, ARMVFP2, 25, 27, 0x6, 20, 20, 1, 9, 11, 0x5},
4861#endif
4862#ifdef VFP_DECODE_EXCLUSION
4863{"vldm", 0, ARMVFP2, 0},
4864#endif
4865#ifdef VFP_INTERPRETER_TABLE
4866INTERPRETER_TRANSLATE(vfpinstr),
4867#endif
4868#ifdef VFP_INTERPRETER_LABEL
4869&&VFPLABEL_INST,
4870#endif
4871#ifdef VFP_INTERPRETER_STRUCT 3671#ifdef VFP_INTERPRETER_STRUCT
4872typedef struct _vldm_inst { 3672typedef struct _vldm_inst {
4873 unsigned int single; 3673 unsigned int single;
@@ -4877,15 +3677,15 @@ typedef struct _vldm_inst {
4877 unsigned int n; 3677 unsigned int n;
4878 unsigned int imm32; 3678 unsigned int imm32;
4879 unsigned int regs; 3679 unsigned int regs;
4880} vfpinstr_inst; 3680} vldm_inst;
4881#endif 3681#endif
4882#ifdef VFP_INTERPRETER_TRANS 3682#ifdef VFP_INTERPRETER_TRANS
4883ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index) 3683ARM_INST_PTR INTERPRETER_TRANSLATE(vldm)(unsigned int inst, int index)
4884{ 3684{
4885 VFP_DEBUG_TRANSLATE; 3685 VFP_DEBUG_TRANSLATE;
4886 3686
4887 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vfpinstr_inst)); 3687 arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(vldm_inst));
4888 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3688 vldm_inst *inst_cream = (vldm_inst *)inst_base->component;
4889 3689
4890 inst_base->cond = BITS(inst, 28, 31); 3690 inst_base->cond = BITS(inst, 28, 31);
4891 inst_base->idx = index; 3691 inst_base->idx = index;
@@ -4904,15 +3704,14 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(vfpinstr)(unsigned int inst, int index)
4904} 3704}
4905#endif 3705#endif
4906#ifdef VFP_INTERPRETER_IMPL 3706#ifdef VFP_INTERPRETER_IMPL
4907VFPLABEL_INST: 3707VLDM_INST:
4908{ 3708{
4909 INC_ICOUNTER;
4910 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 3709 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4911 CHECK_VFP_ENABLED; 3710 CHECK_VFP_ENABLED;
4912 3711
4913 int i; 3712 int i;
4914 3713
4915 vfpinstr_inst *inst_cream = (vfpinstr_inst *)inst_base->component; 3714 vldm_inst *inst_cream = (vldm_inst *)inst_base->component;
4916 3715
4917 addr = (inst_cream->add ? cpu->Reg[inst_cream->n] : cpu->Reg[inst_cream->n] - inst_cream->imm32); 3716 addr = (inst_cream->add ? cpu->Reg[inst_cream->n] : cpu->Reg[inst_cream->n] - inst_cream->imm32);
4918 DBG("VLDM : addr[%x]\n", addr); 3717 DBG("VLDM : addr[%x]\n", addr);
@@ -4952,74 +3751,17 @@ VFPLABEL_INST:
4952 3751
4953 } 3752 }
4954 cpu->Reg[15] += GET_INST_SIZE(cpu); 3753 cpu->Reg[15] += GET_INST_SIZE(cpu);
4955 INC_PC(sizeof(vfpinstr_inst)); 3754 INC_PC(sizeof(vldm_inst));
4956 FETCH_INST; 3755 FETCH_INST;
4957 GOTO_NEXT_INST; 3756 GOTO_NEXT_INST;
4958} 3757}
4959#endif 3758#endif
4960#ifdef VFP_LDC_TRANS
4961/* Should be the last operation of LDC */
4962return VLDM(state, type, instr, value);
4963#endif
4964#ifdef VFP_LDC_IMPL
4965int VLDM(ARMul_State * state, int type, ARMword instr, ARMword value)
4966{
4967 static int i = 0;
4968 static int single_regs, add, wback, d, n, imm32, regs;
4969 if (type == ARMul_FIRST)
4970 {
4971 single_regs = BIT(8) == 0; /* Single precision */
4972 add = BIT(23); /* */
4973 wback = BIT(21); /* write-back */
4974 d = single_regs ? BITS(12, 15)<<1|BIT(22) : BIT(22)<<4|BITS(12, 15); /* Base register */
4975 n = BITS(16, 19); /* destination register */
4976 imm32 = BITS(0,7) * 4; /* may not be used */
4977 regs = single_regs ? BITS(0, 7) : BITS(0, 7)>>1; /* FLDMX if regs is odd */
4978
4979 DBG("VLDM :\n");
4980
4981 if (wback) {
4982 state->Reg[n] = (add ? state->Reg[n] + imm32 : state->Reg[n] - imm32);
4983 DBG("\twback r%d[%x]\n", n, state->Reg[n]);
4984 }
4985
4986 i = 0;
4987
4988 return ARMul_DONE;
4989 }
4990 else if (type == ARMul_DATA)
4991 {
4992 if (single_regs)
4993 {
4994 state->ExtReg[d + i] = value;
4995 DBG("\ts%d <= [%x] addr[?]\n", d+i, state->ExtReg[d + i]);
4996 i++;
4997 if (i < regs)
4998 return ARMul_INC;
4999 else
5000 return ARMul_DONE;
5001 }
5002 else
5003 {
5004 /* FIXME Careful of endianness, may need to rework this */
5005 state->ExtReg[d*2 + i] = value;
5006 DBG("\ts[%d] <= [%x] addr[?]\n", d*2 + i, state->ExtReg[d*2 + i]);
5007 i++;
5008 if (i < regs*2)
5009 return ARMul_INC;
5010 else
5011 return ARMul_DONE;
5012 }
5013 }
5014 3759
5015 return -1;
5016}
5017#endif
5018#ifdef VFP_DYNCOM_TABLE 3760#ifdef VFP_DYNCOM_TABLE
5019DYNCOM_FILL_ACTION(vfpinstr), 3761DYNCOM_FILL_ACTION(vldm),
5020#endif 3762#endif
5021#ifdef VFP_DYNCOM_TAG 3763#ifdef VFP_DYNCOM_TAG
5022int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc) 3764int DYNCOM_TAG(vldm)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr_t *new_pc, addr_t *next_pc)
5023{ 3765{
5024 int instr_size = INSTR_SIZE; 3766 int instr_size = INSTR_SIZE;
5025 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__); 3767 //DBG("\t\tin %s instruction is not implemented.\n", __FUNCTION__);
@@ -5034,7 +3776,7 @@ int DYNCOM_TAG(vfpinstr)(cpu_t *cpu, addr_t pc, uint32_t instr, tag_t *tag, addr
5034} 3776}
5035#endif 3777#endif
5036#ifdef VFP_DYNCOM_TRANS 3778#ifdef VFP_DYNCOM_TRANS
5037int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){ 3779int DYNCOM_TRANS(vldm)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc){
5038 int single = BIT(8) == 0; 3780 int single = BIT(8) == 0;
5039 int add = BIT(23); 3781 int add = BIT(23);
5040 int wback = BIT(21); 3782 int wback = BIT(21);
@@ -5110,14 +3852,3 @@ int DYNCOM_TRANS(vfpinstr)(cpu_t *cpu, uint32_t instr, BasicBlock *bb, addr_t pc
5110 return No_exp; 3852 return No_exp;
5111} 3853}
5112#endif 3854#endif
5113#undef vfpinstr
5114#undef vfpinstr_inst
5115#undef VFPLABEL_INST
5116
5117#define VFP_DEBUG_TRANSLATE DBG("in func %s, %x\n", __FUNCTION__, inst);
5118#define VFP_DEBUG_UNIMPLEMENTED(x) printf("in func %s, " #x " unimplemented\n", __FUNCTION__); exit(-1);
5119#define VFP_DEBUG_UNTESTED(x) printf("in func %s, " #x " untested\n", __FUNCTION__);
5120
5121#define CHECK_VFP_ENABLED
5122
5123#define CHECK_VFP_CDP_RET vfp_raise_exceptions(cpu, ret, inst_cream->instr, cpu->VFP[VFP_OFFSET(VFP_FPSCR)]); //if (ret == -1) {printf("VFP CDP FAILURE %x\n", inst_cream->instr); exit(-1);}
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
index 07d0c1f44..6c33d8b78 100644
--- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
@@ -522,8 +522,7 @@ static s64 vfp_single_to_doubleintern(ARMul_State* state, s32 m, u32 fpscr) //ic
522 if (tm == VFP_QNAN) 522 if (tm == VFP_QNAN)
523 vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN; 523 vdd.significand |= VFP_DOUBLE_SIGNIFICAND_QNAN;
524 goto pack_nan; 524 goto pack_nan;
525 } 525 } else if (tm & VFP_ZERO)
526 else if (tm & VFP_ZERO)
527 vdd.exponent = 0; 526 vdd.exponent = 0;
528 else 527 else
529 vdd.exponent = vsm.exponent + (1023 - 127); 528 vdd.exponent = vsm.exponent + (1023 - 127);
@@ -615,12 +614,12 @@ static u32 vfp_single_ftoui(ARMul_State* state, int sd, int unused, s32 m, u32 f
615 exceptions |= FPSCR_IDC; 614 exceptions |= FPSCR_IDC;
616 615
617 if (tm & VFP_NAN) 616 if (tm & VFP_NAN)
618 vsm.sign = 0; 617 vsm.sign = 1;
619 618
620 if (vsm.exponent >= 127 + 32) { 619 if (vsm.exponent >= 127 + 32) {
621 d = vsm.sign ? 0 : 0xffffffff; 620 d = vsm.sign ? 0 : 0xffffffff;
622 exceptions = FPSCR_IOC; 621 exceptions = FPSCR_IOC;
623 } else if (vsm.exponent >= 127 - 1) { 622 } else if (vsm.exponent >= 127) {
624 int shift = 127 + 31 - vsm.exponent; 623 int shift = 127 + 31 - vsm.exponent;
625 u32 rem, incr = 0; 624 u32 rem, incr = 0;
626 625
@@ -705,7 +704,7 @@ static u32 vfp_single_ftosi(ARMul_State* state, int sd, int unused, s32 m, u32 f
705 if (vsm.sign) 704 if (vsm.sign)
706 d = ~d; 705 d = ~d;
707 exceptions |= FPSCR_IOC; 706 exceptions |= FPSCR_IOC;
708 } else if (vsm.exponent >= 127 - 1) { 707 } else if (vsm.exponent >= 127) {
709 int shift = 127 + 31 - vsm.exponent; 708 int shift = 127 + 31 - vsm.exponent;
710 u32 rem, incr = 0; 709 u32 rem, incr = 0;
711 710
@@ -1149,7 +1148,10 @@ static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1149 /* 1148 /*
1150 * Subtraction is addition with one sign inverted. 1149 * Subtraction is addition with one sign inverted.
1151 */ 1150 */
1152 return vfp_single_fadd(state, sd, sn, vfp_single_packed_negate(m), fpscr); 1151 if (m != 0x7FC00000) // Only negate if m isn't NaN.
1152 m = vfp_single_packed_negate(m);
1153
1154 return vfp_single_fadd(state, sd, sn, m, fpscr);
1153} 1155}
1154 1156
1155/* 1157/*
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 64de0cbba..22213d647 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common_types.h" 5#include "common/common_types.h"
diff --git a/src/core/core.h b/src/core/core.h
index 850bb0ab4..05dbe0ae5 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 1a0b2724a..321648b37 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <vector> 5#include <vector>
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index b197cf40c..496234538 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/file_sys/archive.h b/src/core/file_sys/archive.h
deleted file mode 100644
index 27ed23cd0..000000000
--- a/src/core/file_sys/archive.h
+++ /dev/null
@@ -1,268 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8
9#include "common/common_types.h"
10#include "common/string_util.h"
11#include "common/bit_field.h"
12
13#include "core/file_sys/file.h"
14#include "core/file_sys/directory.h"
15
16#include "core/mem_map.h"
17#include "core/hle/kernel/kernel.h"
18
19////////////////////////////////////////////////////////////////////////////////////////////////////
20// FileSys namespace
21
22namespace FileSys {
23
24// Path string type
25enum LowPathType : u32 {
26 Invalid = 0,
27 Empty = 1,
28 Binary = 2,
29 Char = 3,
30 Wchar = 4
31};
32
33union Mode {
34 u32 hex;
35 BitField<0, 1, u32> read_flag;
36 BitField<1, 1, u32> write_flag;
37 BitField<2, 1, u32> create_flag;
38};
39
40class Path {
41public:
42
43 Path():
44 type(Invalid)
45 {
46 }
47
48 Path(LowPathType type, u32 size, u32 pointer):
49 type(type)
50 {
51 switch (type) {
52 case Binary:
53 {
54 u8* data = Memory::GetPointer(pointer);
55 binary = std::vector<u8>(data, data + size);
56 break;
57 }
58 case Char:
59 {
60 const char* data = reinterpret_cast<const char*>(Memory::GetPointer(pointer));
61 string = std::string(data, size - 1); // Data is always null-terminated.
62 break;
63 }
64 case Wchar:
65 {
66 const char16_t* data = reinterpret_cast<const char16_t*>(Memory::GetPointer(pointer));
67 u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated.
68 break;
69 }
70 default:
71 break;
72 }
73 }
74
75 LowPathType GetType() const {
76 return type;
77 }
78
79 /**
80 * Gets the string representation of the path for debugging
81 * @return String representation of the path for debugging
82 */
83 const std::string DebugStr() const {
84 switch (GetType()) {
85 case Invalid:
86 return "[Invalid]";
87 case Empty:
88 return "[Empty]";
89 case Binary:
90 {
91 std::stringstream res;
92 res << "[Binary: ";
93 for (unsigned byte : binary)
94 res << std::hex << std::setw(2) << std::setfill('0') << byte;
95 res << ']';
96 return res.str();
97 }
98 case Char:
99 return "[Char: " + AsString() + ']';
100 case Wchar:
101 return "[Wchar: " + AsString() + ']';
102 default:
103 // TODO(yuriks): Add assert
104 LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!");
105 return {};
106 }
107 }
108
109 const std::string AsString() const {
110 switch (GetType()) {
111 case Char:
112 return string;
113 case Wchar:
114 return Common::UTF16ToUTF8(u16str);
115 case Empty:
116 return {};
117 default:
118 // TODO(yuriks): Add assert
119 LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!");
120 return {};
121 }
122 }
123
124 const std::u16string AsU16Str() const {
125 switch (GetType()) {
126 case Char:
127 return Common::UTF8ToUTF16(string);
128 case Wchar:
129 return u16str;
130 case Empty:
131 return {};
132 default:
133 // TODO(yuriks): Add assert
134 LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!");
135 return {};
136 }
137 }
138
139 const std::vector<u8> AsBinary() const {
140 switch (GetType()) {
141 case Binary:
142 return binary;
143 case Char:
144 return std::vector<u8>(string.begin(), string.end());
145 case Wchar:
146 return std::vector<u8>(u16str.begin(), u16str.end());
147 case Empty:
148 return {};
149 default:
150 // TODO(yuriks): Add assert
151 LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!");
152 return {};
153 }
154 }
155
156private:
157 LowPathType type;
158 std::vector<u8> binary;
159 std::string string;
160 std::u16string u16str;
161};
162
163class Archive : NonCopyable {
164public:
165 /// Supported archive types
166 enum class IdCode : u32 {
167 RomFS = 0x00000003,
168 SaveData = 0x00000004,
169 ExtSaveData = 0x00000006,
170 SharedExtSaveData = 0x00000007,
171 SystemSaveData = 0x00000008,
172 SDMC = 0x00000009,
173 SDMCWriteOnly = 0x0000000A,
174 };
175
176 Archive() { }
177 virtual ~Archive() { }
178
179 /**
180 * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.)
181 * @return IdCode of the archive
182 */
183 virtual IdCode GetIdCode() const = 0;
184
185 /**
186 * Open a file specified by its path, using the specified mode
187 * @param path Path relative to the archive
188 * @param mode Mode to open the file with
189 * @return Opened file, or nullptr
190 */
191 virtual std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const = 0;
192
193 /**
194 * Delete a file specified by its path
195 * @param path Path relative to the archive
196 * @return Whether the file could be deleted
197 */
198 virtual bool DeleteFile(const FileSys::Path& path) const = 0;
199
200 /**
201 * Rename a File specified by its path
202 * @param src_path Source path relative to the archive
203 * @param dest_path Destination path relative to the archive
204 * @return Whether rename succeeded
205 */
206 virtual bool RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const = 0;
207
208 /**
209 * Delete a directory specified by its path
210 * @param path Path relative to the archive
211 * @return Whether the directory could be deleted
212 */
213 virtual bool DeleteDirectory(const FileSys::Path& path) const = 0;
214
215 /**
216 * Create a directory specified by its path
217 * @param path Path relative to the archive
218 * @return Whether the directory could be created
219 */
220 virtual bool CreateDirectory(const Path& path) const = 0;
221
222 /**
223 * Rename a Directory specified by its path
224 * @param src_path Source path relative to the archive
225 * @param dest_path Destination path relative to the archive
226 * @return Whether rename succeeded
227 */
228 virtual bool RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const = 0;
229
230 /**
231 * Open a directory specified by its path
232 * @param path Path relative to the archive
233 * @return Opened directory, or nullptr
234 */
235 virtual std::unique_ptr<Directory> OpenDirectory(const Path& path) const = 0;
236
237 /**
238 * Read data from the archive
239 * @param offset Offset in bytes to start reading data from
240 * @param length Length in bytes of data to read from archive
241 * @param buffer Buffer to read data into
242 * @return Number of bytes read
243 */
244 virtual size_t Read(const u64 offset, const u32 length, u8* buffer) const = 0;
245
246 /**
247 * Write data to the archive
248 * @param offset Offset in bytes to start writing data to
249 * @param length Length in bytes of data to write to archive
250 * @param buffer Buffer to write data from
251 * @param flush The flush parameters (0 == do not flush)
252 * @return Number of bytes written
253 */
254 virtual size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) = 0;
255
256 /**
257 * Get the size of the archive in bytes
258 * @return Size of the archive in bytes
259 */
260 virtual size_t GetSize() const = 0;
261
262 /**
263 * Set the size of the archive in bytes
264 */
265 virtual void SetSize(const u64 size) = 0;
266};
267
268} // namespace FileSys
diff --git a/src/core/file_sys/archive_backend.h b/src/core/file_sys/archive_backend.h
new file mode 100644
index 000000000..e153917ea
--- /dev/null
+++ b/src/core/file_sys/archive_backend.h
@@ -0,0 +1,243 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8
9#include "common/common_types.h"
10#include "common/string_util.h"
11#include "common/bit_field.h"
12
13#include "core/file_sys/file_backend.h"
14#include "core/file_sys/directory_backend.h"
15
16#include "core/mem_map.h"
17#include "core/hle/kernel/kernel.h"
18
19////////////////////////////////////////////////////////////////////////////////////////////////////
20// FileSys namespace
21
22namespace FileSys {
23
24// Path string type
25enum LowPathType : u32 {
26 Invalid = 0,
27 Empty = 1,
28 Binary = 2,
29 Char = 3,
30 Wchar = 4
31};
32
33union Mode {
34 u32 hex;
35 BitField<0, 1, u32> read_flag;
36 BitField<1, 1, u32> write_flag;
37 BitField<2, 1, u32> create_flag;
38};
39
40class Path {
41public:
42
43 Path() : type(Invalid) {
44 }
45
46 Path(const char* path) : type(Char), string(path) {
47 }
48
49 Path(LowPathType type, u32 size, u32 pointer) : type(type) {
50 switch (type) {
51 case Binary:
52 {
53 u8* data = Memory::GetPointer(pointer);
54 binary = std::vector<u8>(data, data + size);
55 break;
56 }
57
58 case Char:
59 {
60 const char* data = reinterpret_cast<const char*>(Memory::GetPointer(pointer));
61 string = std::string(data, size - 1); // Data is always null-terminated.
62 break;
63 }
64
65 case Wchar:
66 {
67 const char16_t* data = reinterpret_cast<const char16_t*>(Memory::GetPointer(pointer));
68 u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated.
69 break;
70 }
71
72 default:
73 break;
74 }
75 }
76
77 LowPathType GetType() const {
78 return type;
79 }
80
81 /**
82 * Gets the string representation of the path for debugging
83 * @return String representation of the path for debugging
84 */
85 const std::string DebugStr() const {
86 switch (GetType()) {
87 case Invalid:
88 return "[Invalid]";
89 case Empty:
90 return "[Empty]";
91 case Binary:
92 {
93 std::stringstream res;
94 res << "[Binary: ";
95 for (unsigned byte : binary)
96 res << std::hex << std::setw(2) << std::setfill('0') << byte;
97 res << ']';
98 return res.str();
99 }
100 case Char:
101 return "[Char: " + AsString() + ']';
102 case Wchar:
103 return "[Wchar: " + AsString() + ']';
104 }
105 }
106
107 const std::string AsString() const {
108 switch (GetType()) {
109 case Char:
110 return string;
111 case Wchar:
112 return Common::UTF16ToUTF8(u16str);
113 case Empty:
114 return {};
115 case Invalid:
116 case Binary:
117 // TODO(yuriks): Add assert
118 LOG_ERROR(Service_FS, "LowPathType cannot be converted to string!");
119 return {};
120 }
121 }
122
123 const std::u16string AsU16Str() const {
124 switch (GetType()) {
125 case Char:
126 return Common::UTF8ToUTF16(string);
127 case Wchar:
128 return u16str;
129 case Empty:
130 return {};
131 case Invalid:
132 case Binary:
133 // TODO(yuriks): Add assert
134 LOG_ERROR(Service_FS, "LowPathType cannot be converted to u16string!");
135 return {};
136 }
137 }
138
139 const std::vector<u8> AsBinary() const {
140 switch (GetType()) {
141 case Binary:
142 return binary;
143 case Char:
144 return std::vector<u8>(string.begin(), string.end());
145 case Wchar:
146 {
147 // use two u8 for each character of u16str
148 std::vector<u8> to_return(u16str.size() * 2);
149 for (size_t i = 0; i < u16str.size(); ++i) {
150 u16 tmp_char = u16str.at(i);
151 to_return[i*2] = (tmp_char & 0xFF00) >> 8;
152 to_return[i*2 + 1] = (tmp_char & 0x00FF);
153 }
154 return to_return;
155 }
156 case Empty:
157 return {};
158 case Invalid:
159 // TODO(yuriks): Add assert
160 LOG_ERROR(Service_FS, "LowPathType cannot be converted to binary!");
161 return {};
162 }
163 }
164
165private:
166 LowPathType type;
167 std::vector<u8> binary;
168 std::string string;
169 std::u16string u16str;
170};
171
172class ArchiveBackend : NonCopyable {
173public:
174 virtual ~ArchiveBackend() {
175 }
176
177 /**
178 * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.)
179 */
180 virtual std::string GetName() const = 0;
181
182 /**
183 * Open a file specified by its path, using the specified mode
184 * @param path Path relative to the archive
185 * @param mode Mode to open the file with
186 * @return Opened file, or nullptr
187 */
188 virtual std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const = 0;
189
190 /**
191 * Delete a file specified by its path
192 * @param path Path relative to the archive
193 * @return Whether the file could be deleted
194 */
195 virtual bool DeleteFile(const Path& path) const = 0;
196
197 /**
198 * Rename a File specified by its path
199 * @param src_path Source path relative to the archive
200 * @param dest_path Destination path relative to the archive
201 * @return Whether rename succeeded
202 */
203 virtual bool RenameFile(const Path& src_path, const Path& dest_path) const = 0;
204
205 /**
206 * Delete a directory specified by its path
207 * @param path Path relative to the archive
208 * @return Whether the directory could be deleted
209 */
210 virtual bool DeleteDirectory(const Path& path) const = 0;
211
212 /**
213 * Create a file specified by its path
214 * @param path Path relative to the Archive
215 * @param size The size of the new file, filled with zeroes
216 * @return File creation result code
217 */
218 virtual ResultCode CreateFile(const Path& path, u32 size) const = 0;
219
220 /**
221 * Create a directory specified by its path
222 * @param path Path relative to the archive
223 * @return Whether the directory could be created
224 */
225 virtual bool CreateDirectory(const Path& path) const = 0;
226
227 /**
228 * Rename a Directory specified by its path
229 * @param src_path Source path relative to the archive
230 * @param dest_path Destination path relative to the archive
231 * @return Whether rename succeeded
232 */
233 virtual bool RenameDirectory(const Path& src_path, const Path& dest_path) const = 0;
234
235 /**
236 * Open a directory specified by its path
237 * @param path Path relative to the archive
238 * @return Opened directory, or nullptr
239 */
240 virtual std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const = 0;
241};
242
243} // namespace FileSys
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp
index 74974c2df..fdaf73179 100644
--- a/src/core/file_sys/archive_romfs.cpp
+++ b/src/core/file_sys/archive_romfs.cpp
@@ -1,8 +1,11 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory>
6
5#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/make_unique.h"
6 9
7#include "core/file_sys/archive_romfs.h" 10#include "core/file_sys/archive_romfs.h"
8#include "core/file_sys/directory_romfs.h" 11#include "core/file_sys/directory_romfs.h"
@@ -20,107 +23,43 @@ Archive_RomFS::Archive_RomFS(const Loader::AppLoader& app_loader) {
20 } 23 }
21} 24}
22 25
23Archive_RomFS::~Archive_RomFS() { 26std::unique_ptr<FileBackend> Archive_RomFS::OpenFile(const Path& path, const Mode mode) const {
24} 27 return Common::make_unique<File_RomFS>(this);
25
26/**
27 * Open a file specified by its path, using the specified mode
28 * @param path Path relative to the archive
29 * @param mode Mode to open the file with
30 * @return Opened file, or nullptr
31 */
32std::unique_ptr<File> Archive_RomFS::OpenFile(const Path& path, const Mode mode) const {
33 return std::unique_ptr<File>(new File_RomFS);
34} 28}
35 29
36/** 30bool Archive_RomFS::DeleteFile(const Path& path) const {
37 * Delete a file specified by its path
38 * @param path Path relative to the archive
39 * @return Whether the file could be deleted
40 */
41bool Archive_RomFS::DeleteFile(const FileSys::Path& path) const {
42 LOG_WARNING(Service_FS, "Attempted to delete a file from ROMFS."); 31 LOG_WARNING(Service_FS, "Attempted to delete a file from ROMFS.");
43 return false; 32 return false;
44} 33}
45 34
46bool Archive_RomFS::RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const { 35bool Archive_RomFS::RenameFile(const Path& src_path, const Path& dest_path) const {
47 LOG_WARNING(Service_FS, "Attempted to rename a file within ROMFS."); 36 LOG_WARNING(Service_FS, "Attempted to rename a file within ROMFS.");
48 return false; 37 return false;
49} 38}
50 39
51/** 40bool Archive_RomFS::DeleteDirectory(const Path& path) const {
52 * Delete a directory specified by its path
53 * @param path Path relative to the archive
54 * @return Whether the directory could be deleted
55 */
56bool Archive_RomFS::DeleteDirectory(const FileSys::Path& path) const {
57 LOG_WARNING(Service_FS, "Attempted to delete a directory from ROMFS."); 41 LOG_WARNING(Service_FS, "Attempted to delete a directory from ROMFS.");
58 return false; 42 return false;
59} 43}
60 44
61/** 45ResultCode Archive_RomFS::CreateFile(const Path& path, u32 size) const {
62 * Create a directory specified by its path 46 LOG_WARNING(Service_FS, "Attempted to create a file in ROMFS.");
63 * @param path Path relative to the archive 47 // TODO: Verify error code
64 * @return Whether the directory could be created 48 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::FS, ErrorSummary::NotSupported, ErrorLevel::Permanent);
65 */ 49}
50
66bool Archive_RomFS::CreateDirectory(const Path& path) const { 51bool Archive_RomFS::CreateDirectory(const Path& path) const {
67 LOG_WARNING(Service_FS, "Attempted to create a directory in ROMFS."); 52 LOG_WARNING(Service_FS, "Attempted to create a directory in ROMFS.");
68 return false; 53 return false;
69} 54}
70 55
71bool Archive_RomFS::RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const { 56bool Archive_RomFS::RenameDirectory(const Path& src_path, const Path& dest_path) const {
72 LOG_WARNING(Service_FS, "Attempted to rename a file within ROMFS."); 57 LOG_WARNING(Service_FS, "Attempted to rename a file within ROMFS.");
73 return false; 58 return false;
74} 59}
75 60
76/** 61std::unique_ptr<DirectoryBackend> Archive_RomFS::OpenDirectory(const Path& path) const {
77 * Open a directory specified by its path 62 return Common::make_unique<Directory_RomFS>();
78 * @param path Path relative to the archive
79 * @return Opened directory, or nullptr
80 */
81std::unique_ptr<Directory> Archive_RomFS::OpenDirectory(const Path& path) const {
82 return std::unique_ptr<Directory>(new Directory_RomFS);
83}
84
85/**
86 * Read data from the archive
87 * @param offset Offset in bytes to start reading data from
88 * @param length Length in bytes of data to read from archive
89 * @param buffer Buffer to read data into
90 * @return Number of bytes read
91 */
92size_t Archive_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const {
93 LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length);
94 memcpy(buffer, &raw_data[(u32)offset], length);
95 return length;
96}
97
98/**
99 * Write data to the archive
100 * @param offset Offset in bytes to start writing data to
101 * @param length Length in bytes of data to write to archive
102 * @param buffer Buffer to write data from
103 * @param flush The flush parameters (0 == do not flush)
104 * @return Number of bytes written
105 */
106size_t Archive_RomFS::Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) {
107 LOG_WARNING(Service_FS, "Attempted to write to ROMFS.");
108 return 0;
109}
110
111/**
112 * Get the size of the archive in bytes
113 * @return Size of the archive in bytes
114 */
115size_t Archive_RomFS::GetSize() const {
116 return sizeof(u8) * raw_data.size();
117}
118
119/**
120 * Set the size of the archive in bytes
121 */
122void Archive_RomFS::SetSize(const u64 size) {
123 LOG_WARNING(Service_FS, "Attempted to set the size of ROMFS");
124} 63}
125 64
126} // namespace FileSys 65} // namespace FileSys
diff --git a/src/core/file_sys/archive_romfs.h b/src/core/file_sys/archive_romfs.h
index 222bdc356..5e918f92d 100644
--- a/src/core/file_sys/archive_romfs.h
+++ b/src/core/file_sys/archive_romfs.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -8,7 +8,7 @@
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10 10
11#include "core/file_sys/archive.h" 11#include "core/file_sys/archive_backend.h"
12#include "core/loader/loader.h" 12#include "core/loader/loader.h"
13 13
14//////////////////////////////////////////////////////////////////////////////////////////////////// 14////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -17,16 +17,11 @@
17namespace FileSys { 17namespace FileSys {
18 18
19/// File system interface to the RomFS archive 19/// File system interface to the RomFS archive
20class Archive_RomFS final : public Archive { 20class Archive_RomFS final : public ArchiveBackend {
21public: 21public:
22 Archive_RomFS(const Loader::AppLoader& app_loader); 22 Archive_RomFS(const Loader::AppLoader& app_loader);
23 ~Archive_RomFS() override;
24 23
25 /** 24 std::string GetName() const override { return "RomFS"; }
26 * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.)
27 * @return IdCode of the archive
28 */
29 IdCode GetIdCode() const override { return IdCode::RomFS; }
30 25
31 /** 26 /**
32 * Open a file specified by its path, using the specified mode 27 * Open a file specified by its path, using the specified mode
@@ -34,14 +29,14 @@ public:
34 * @param mode Mode to open the file with 29 * @param mode Mode to open the file with
35 * @return Opened file, or nullptr 30 * @return Opened file, or nullptr
36 */ 31 */
37 std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override; 32 std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override;
38 33
39 /** 34 /**
40 * Delete a file specified by its path 35 * Delete a file specified by its path
41 * @param path Path relative to the archive 36 * @param path Path relative to the archive
42 * @return Whether the file could be deleted 37 * @return Whether the file could be deleted
43 */ 38 */
44 bool DeleteFile(const FileSys::Path& path) const override; 39 bool DeleteFile(const Path& path) const override;
45 40
46 /** 41 /**
47 * Rename a File specified by its path 42 * Rename a File specified by its path
@@ -49,14 +44,22 @@ public:
49 * @param dest_path Destination path relative to the archive 44 * @param dest_path Destination path relative to the archive
50 * @return Whether rename succeeded 45 * @return Whether rename succeeded
51 */ 46 */
52 bool RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override; 47 bool RenameFile(const Path& src_path, const Path& dest_path) const override;
53 48
54 /** 49 /**
55 * Delete a directory specified by its path 50 * Delete a directory specified by its path
56 * @param path Path relative to the archive 51 * @param path Path relative to the archive
57 * @return Whether the directory could be deleted 52 * @return Whether the directory could be deleted
58 */ 53 */
59 bool DeleteDirectory(const FileSys::Path& path) const override; 54 bool DeleteDirectory(const Path& path) const override;
55
56 /**
57 * Create a file specified by its path
58 * @param path Path relative to the Archive
59 * @param size The size of the new file, filled with zeroes
60 * @return File creation result code
61 */
62 ResultCode CreateFile(const Path& path, u32 size) const override;
60 63
61 /** 64 /**
62 * Create a directory specified by its path 65 * Create a directory specified by its path
@@ -71,46 +74,18 @@ public:
71 * @param dest_path Destination path relative to the archive 74 * @param dest_path Destination path relative to the archive
72 * @return Whether rename succeeded 75 * @return Whether rename succeeded
73 */ 76 */
74 bool RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override; 77 bool RenameDirectory(const Path& src_path, const Path& dest_path) const override;
75 78
76 /** 79 /**
77 * Open a directory specified by its path 80 * Open a directory specified by its path
78 * @param path Path relative to the archive 81 * @param path Path relative to the archive
79 * @return Opened directory, or nullptr 82 * @return Opened directory, or nullptr
80 */ 83 */
81 std::unique_ptr<Directory> OpenDirectory(const Path& path) const override; 84 std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override;
82
83 /**
84 * Read data from the archive
85 * @param offset Offset in bytes to start reading data from
86 * @param length Length in bytes of data to read from archive
87 * @param buffer Buffer to read data into
88 * @return Number of bytes read
89 */
90 size_t Read(const u64 offset, const u32 length, u8* buffer) const override;
91
92 /**
93 * Write data to the archive
94 * @param offset Offset in bytes to start writing data to
95 * @param length Length in bytes of data to write to archive
96 * @param buffer Buffer to write data from
97 * @param flush The flush parameters (0 == do not flush)
98 * @return Number of bytes written
99 */
100 size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) override;
101
102 /**
103 * Get the size of the archive in bytes
104 * @return Size of the archive in bytes
105 */
106 size_t GetSize() const override;
107
108 /**
109 * Set the size of the archive in bytes
110 */
111 void SetSize(const u64 size) override;
112 85
113private: 86private:
87 friend class File_RomFS;
88
114 std::vector<u8> raw_data; 89 std::vector<u8> raw_data;
115}; 90};
116 91
diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp
new file mode 100644
index 000000000..97853567c
--- /dev/null
+++ b/src/core/file_sys/archive_savedata.cpp
@@ -0,0 +1,33 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <sys/stat.h>
6
7#include "common/common_types.h"
8#include "common/file_util.h"
9
10#include "core/file_sys/archive_savedata.h"
11#include "core/file_sys/disk_archive.h"
12#include "core/settings.h"
13
14////////////////////////////////////////////////////////////////////////////////////////////////////
15// FileSys namespace
16
17namespace FileSys {
18
19Archive_SaveData::Archive_SaveData(const std::string& mount_point, u64 program_id)
20 : DiskArchive(mount_point + Common::StringFromFormat("%016X", program_id) + DIR_SEP) {
21 LOG_INFO(Service_FS, "Directory %s set as SaveData.", this->mount_point.c_str());
22}
23
24bool Archive_SaveData::Initialize() {
25 if (!FileUtil::CreateFullPath(mount_point)) {
26 LOG_ERROR(Service_FS, "Unable to create SaveData path.");
27 return false;
28 }
29
30 return true;
31}
32
33} // namespace FileSys
diff --git a/src/core/file_sys/archive_savedata.h b/src/core/file_sys/archive_savedata.h
new file mode 100644
index 000000000..5b0ce29e6
--- /dev/null
+++ b/src/core/file_sys/archive_savedata.h
@@ -0,0 +1,31 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9#include "core/file_sys/disk_archive.h"
10#include "core/loader/loader.h"
11
12////////////////////////////////////////////////////////////////////////////////////////////////////
13// FileSys namespace
14
15namespace FileSys {
16
17/// File system interface to the SaveData archive
18class Archive_SaveData final : public DiskArchive {
19public:
20 Archive_SaveData(const std::string& mount_point, u64 program_id);
21
22 /**
23 * Initialize the archive.
24 * @return true if it initialized successfully
25 */
26 bool Initialize();
27
28 std::string GetName() const override { return "SaveData"; }
29};
30
31} // namespace FileSys
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp
index 9e524b60e..1c1c170b6 100644
--- a/src/core/file_sys/archive_sdmc.cpp
+++ b/src/core/file_sys/archive_sdmc.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <sys/stat.h> 5#include <sys/stat.h>
@@ -8,8 +8,7 @@
8#include "common/file_util.h" 8#include "common/file_util.h"
9 9
10#include "core/file_sys/archive_sdmc.h" 10#include "core/file_sys/archive_sdmc.h"
11#include "core/file_sys/directory_sdmc.h" 11#include "core/file_sys/disk_archive.h"
12#include "core/file_sys/file_sdmc.h"
13#include "core/settings.h" 12#include "core/settings.h"
14 13
15//////////////////////////////////////////////////////////////////////////////////////////////////// 14////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -17,18 +16,10 @@
17 16
18namespace FileSys { 17namespace FileSys {
19 18
20Archive_SDMC::Archive_SDMC(const std::string& mount_point) { 19Archive_SDMC::Archive_SDMC(const std::string& mount_point) : DiskArchive(mount_point) {
21 this->mount_point = mount_point;
22 LOG_INFO(Service_FS, "Directory %s set as SDMC.", mount_point.c_str()); 20 LOG_INFO(Service_FS, "Directory %s set as SDMC.", mount_point.c_str());
23} 21}
24 22
25Archive_SDMC::~Archive_SDMC() {
26}
27
28/**
29 * Initialize the archive.
30 * @return true if it initialized successfully
31 */
32bool Archive_SDMC::Initialize() { 23bool Archive_SDMC::Initialize() {
33 if (!Settings::values.use_virtual_sd) { 24 if (!Settings::values.use_virtual_sd) {
34 LOG_WARNING(Service_FS, "SDMC disabled by config."); 25 LOG_WARNING(Service_FS, "SDMC disabled by config.");
@@ -43,115 +34,4 @@ bool Archive_SDMC::Initialize() {
43 return true; 34 return true;
44} 35}
45 36
46/**
47 * Open a file specified by its path, using the specified mode
48 * @param path Path relative to the archive
49 * @param mode Mode to open the file with
50 * @return Opened file, or nullptr
51 */
52std::unique_ptr<File> Archive_SDMC::OpenFile(const Path& path, const Mode mode) const {
53 LOG_DEBUG(Service_FS, "called path=%s mode=%u", path.DebugStr().c_str(), mode.hex);
54 File_SDMC* file = new File_SDMC(this, path, mode);
55 if (!file->Open())
56 return nullptr;
57 return std::unique_ptr<File>(file);
58}
59
60/**
61 * Delete a file specified by its path
62 * @param path Path relative to the archive
63 * @return Whether the file could be deleted
64 */
65bool Archive_SDMC::DeleteFile(const FileSys::Path& path) const {
66 return FileUtil::Delete(GetMountPoint() + path.AsString());
67}
68
69bool Archive_SDMC::RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const {
70 return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString());
71}
72
73/**
74 * Delete a directory specified by its path
75 * @param path Path relative to the archive
76 * @return Whether the directory could be deleted
77 */
78bool Archive_SDMC::DeleteDirectory(const FileSys::Path& path) const {
79 return FileUtil::DeleteDir(GetMountPoint() + path.AsString());
80}
81
82/**
83 * Create a directory specified by its path
84 * @param path Path relative to the archive
85 * @return Whether the directory could be created
86 */
87bool Archive_SDMC::CreateDirectory(const Path& path) const {
88 return FileUtil::CreateDir(GetMountPoint() + path.AsString());
89}
90
91bool Archive_SDMC::RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const {
92 return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString());
93}
94
95/**
96 * Open a directory specified by its path
97 * @param path Path relative to the archive
98 * @return Opened directory, or nullptr
99 */
100std::unique_ptr<Directory> Archive_SDMC::OpenDirectory(const Path& path) const {
101 LOG_DEBUG(Service_FS, "called path=%s", path.DebugStr().c_str());
102 Directory_SDMC* directory = new Directory_SDMC(this, path);
103 if (!directory->Open())
104 return nullptr;
105 return std::unique_ptr<Directory>(directory);
106}
107
108/**
109 * Read data from the archive
110 * @param offset Offset in bytes to start reading archive from
111 * @param length Length in bytes to read data from archive
112 * @param buffer Buffer to read data into
113 * @return Number of bytes read
114 */
115size_t Archive_SDMC::Read(const u64 offset, const u32 length, u8* buffer) const {
116 LOG_ERROR(Service_FS, "(UNIMPLEMENTED)");
117 return -1;
118}
119
120/**
121 * Write data to the archive
122 * @param offset Offset in bytes to start writing data to
123 * @param length Length in bytes of data to write to archive
124 * @param buffer Buffer to write data from
125 * @param flush The flush parameters (0 == do not flush)
126 * @return Number of bytes written
127 */
128size_t Archive_SDMC::Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) {
129 LOG_ERROR(Service_FS, "(UNIMPLEMENTED)");
130 return -1;
131}
132
133/**
134 * Get the size of the archive in bytes
135 * @return Size of the archive in bytes
136 */
137size_t Archive_SDMC::GetSize() const {
138 LOG_ERROR(Service_FS, "(UNIMPLEMENTED)");
139 return 0;
140}
141
142/**
143 * Set the size of the archive in bytes
144 */
145void Archive_SDMC::SetSize(const u64 size) {
146 LOG_ERROR(Service_FS, "(UNIMPLEMENTED)");
147}
148
149/**
150 * Getter for the path used for this Archive
151 * @return Mount point of that passthrough archive
152 */
153std::string Archive_SDMC::GetMountPoint() const {
154 return mount_point;
155}
156
157} // namespace FileSys 37} // namespace FileSys
diff --git a/src/core/file_sys/archive_sdmc.h b/src/core/file_sys/archive_sdmc.h
index 19f563a62..1b801f217 100644
--- a/src/core/file_sys/archive_sdmc.h
+++ b/src/core/file_sys/archive_sdmc.h
@@ -1,12 +1,12 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9#include "core/file_sys/archive.h" 9#include "core/file_sys/disk_archive.h"
10#include "core/loader/loader.h" 10#include "core/loader/loader.h"
11 11
12//////////////////////////////////////////////////////////////////////////////////////////////////// 12////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -15,10 +15,9 @@
15namespace FileSys { 15namespace FileSys {
16 16
17/// File system interface to the SDMC archive 17/// File system interface to the SDMC archive
18class Archive_SDMC final : public Archive { 18class Archive_SDMC final : public DiskArchive {
19public: 19public:
20 Archive_SDMC(const std::string& mount_point); 20 Archive_SDMC(const std::string& mount_point);
21 ~Archive_SDMC() override;
22 21
23 /** 22 /**
24 * Initialize the archive. 23 * Initialize the archive.
@@ -26,102 +25,7 @@ public:
26 */ 25 */
27 bool Initialize(); 26 bool Initialize();
28 27
29 /** 28 std::string GetName() const override { return "SDMC"; }
30 * Get the IdCode of the archive (e.g. RomFS, SaveData, etc.)
31 * @return IdCode of the archive
32 */
33 IdCode GetIdCode() const override { return IdCode::SDMC; }
34
35 /**
36 * Open a file specified by its path, using the specified mode
37 * @param path Path relative to the archive
38 * @param mode Mode to open the file with
39 * @return Opened file, or nullptr
40 */
41 std::unique_ptr<File> OpenFile(const Path& path, const Mode mode) const override;
42
43 /**
44 * Delete a file specified by its path
45 * @param path Path relative to the archive
46 * @return Whether the file could be deleted
47 */
48 bool DeleteFile(const FileSys::Path& path) const override;
49
50 /**
51 * Rename a File specified by its path
52 * @param src_path Source path relative to the archive
53 * @param dest_path Destination path relative to the archive
54 * @return Whether rename succeeded
55 */
56 bool RenameFile(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override;
57
58 /**
59 * Delete a directory specified by its path
60 * @param path Path relative to the archive
61 * @return Whether the directory could be deleted
62 */
63 bool DeleteDirectory(const FileSys::Path& path) const override;
64
65 /**
66 * Create a directory specified by its path
67 * @param path Path relative to the archive
68 * @return Whether the directory could be created
69 */
70 bool CreateDirectory(const Path& path) const override;
71
72 /**
73 * Rename a Directory specified by its path
74 * @param src_path Source path relative to the archive
75 * @param dest_path Destination path relative to the archive
76 * @return Whether rename succeeded
77 */
78 bool RenameDirectory(const FileSys::Path& src_path, const FileSys::Path& dest_path) const override;
79
80 /**
81 * Open a directory specified by its path
82 * @param path Path relative to the archive
83 * @return Opened directory, or nullptr
84 */
85 std::unique_ptr<Directory> OpenDirectory(const Path& path) const override;
86
87 /**
88 * Read data from the archive
89 * @param offset Offset in bytes to start reading archive from
90 * @param length Length in bytes to read data from archive
91 * @param buffer Buffer to read data into
92 * @return Number of bytes read
93 */
94 size_t Read(const u64 offset, const u32 length, u8* buffer) const override;
95
96 /**
97 * Write data to the archive
98 * @param offset Offset in bytes to start writing data to
99 * @param length Length in bytes of data to write to archive
100 * @param buffer Buffer to write data from
101 * @param flush The flush parameters (0 == do not flush)
102 * @return Number of bytes written
103 */
104 size_t Write(const u64 offset, const u32 length, const u32 flush, u8* buffer) override;
105
106 /**
107 * Get the size of the archive in bytes
108 * @return Size of the archive in bytes
109 */
110 size_t GetSize() const override;
111
112 /**
113 * Set the size of the archive in bytes
114 */
115 void SetSize(const u64 size) override;
116
117 /**
118 * Getter for the path used for this Archive
119 * @return Mount point of that passthrough archive
120 */
121 std::string GetMountPoint() const;
122
123private:
124 std::string mount_point;
125}; 29};
126 30
127} // namespace FileSys 31} // namespace FileSys
diff --git a/src/core/file_sys/archive_systemsavedata.cpp b/src/core/file_sys/archive_systemsavedata.cpp
new file mode 100644
index 000000000..0da32d510
--- /dev/null
+++ b/src/core/file_sys/archive_systemsavedata.cpp
@@ -0,0 +1,39 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <sys/stat.h>
6
7#include "common/common_types.h"
8#include "common/file_util.h"
9
10#include "core/file_sys/archive_systemsavedata.h"
11#include "core/file_sys/disk_archive.h"
12#include "core/settings.h"
13
14////////////////////////////////////////////////////////////////////////////////////////////////////
15// FileSys namespace
16
17namespace FileSys {
18
19static std::string GetSystemSaveDataPath(const std::string& mount_point, u64 save_id) {
20 u32 save_high = static_cast<u32>((save_id >> 32) & 0xFFFFFFFF);
21 u32 save_low = static_cast<u32>(save_id & 0xFFFFFFFF);
22 return Common::StringFromFormat("%s%08X/%08X/", mount_point.c_str(), save_low, save_high);
23}
24
25Archive_SystemSaveData::Archive_SystemSaveData(const std::string& mount_point, u64 save_id)
26 : DiskArchive(GetSystemSaveDataPath(mount_point, save_id)) {
27 LOG_INFO(Service_FS, "Directory %s set as SystemSaveData.", this->mount_point.c_str());
28}
29
30bool Archive_SystemSaveData::Initialize() {
31 if (!FileUtil::CreateFullPath(mount_point)) {
32 LOG_ERROR(Service_FS, "Unable to create SystemSaveData path.");
33 return false;
34 }
35
36 return true;
37}
38
39} // namespace FileSys
diff --git a/src/core/file_sys/archive_systemsavedata.h b/src/core/file_sys/archive_systemsavedata.h
new file mode 100644
index 000000000..55d85193c
--- /dev/null
+++ b/src/core/file_sys/archive_systemsavedata.h
@@ -0,0 +1,33 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9#include "core/file_sys/disk_archive.h"
10#include "core/loader/loader.h"
11
12////////////////////////////////////////////////////////////////////////////////////////////////////
13// FileSys namespace
14
15namespace FileSys {
16
17/// File system interface to the SystemSaveData archive
18/// TODO(Subv): This archive should point to a location in the NAND,
19/// specifically nand:/data/<ID0>/sysdata/<SaveID-Low>/<SaveID-High>
20class Archive_SystemSaveData final : public DiskArchive {
21public:
22 Archive_SystemSaveData(const std::string& mount_point, u64 save_id);
23
24 /**
25 * Initialize the archive.
26 * @return true if it initialized successfully
27 */
28 bool Initialize();
29
30 std::string GetName() const override { return "SystemSaveData"; }
31};
32
33} // namespace FileSys
diff --git a/src/core/file_sys/directory.h b/src/core/file_sys/directory_backend.h
index 1bb4101d6..7f327dc42 100644
--- a/src/core/file_sys/directory.h
+++ b/src/core/file_sys/directory_backend.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -36,10 +36,10 @@ static_assert(offsetof(Entry, extension) == 0x216, "Wrong offset for extension i
36static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry."); 36static_assert(offsetof(Entry, is_archive) == 0x21E, "Wrong offset for is_archive in Entry.");
37static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry."); 37static_assert(offsetof(Entry, file_size) == 0x220, "Wrong offset for file_size in Entry.");
38 38
39class Directory : NonCopyable { 39class DirectoryBackend : NonCopyable {
40public: 40public:
41 Directory() { } 41 DirectoryBackend() { }
42 virtual ~Directory() { } 42 virtual ~DirectoryBackend() { }
43 43
44 /** 44 /**
45 * Open the directory 45 * Open the directory
diff --git a/src/core/file_sys/directory_romfs.cpp b/src/core/file_sys/directory_romfs.cpp
index e6d571391..e130aca17 100644
--- a/src/core/file_sys/directory_romfs.cpp
+++ b/src/core/file_sys/directory_romfs.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common_types.h" 5#include "common/common_types.h"
@@ -21,20 +21,10 @@ bool Directory_RomFS::Open() {
21 return false; 21 return false;
22} 22}
23 23
24/**
25 * List files contained in the directory
26 * @param count Number of entries to return at once in entries
27 * @param entries Buffer to read data into
28 * @return Number of entries listed
29 */
30u32 Directory_RomFS::Read(const u32 count, Entry* entries) { 24u32 Directory_RomFS::Read(const u32 count, Entry* entries) {
31 return 0; 25 return 0;
32} 26}
33 27
34/**
35 * Close the directory
36 * @return true if the directory closed correctly
37 */
38bool Directory_RomFS::Close() const { 28bool Directory_RomFS::Close() const {
39 return false; 29 return false;
40} 30}
diff --git a/src/core/file_sys/directory_romfs.h b/src/core/file_sys/directory_romfs.h
index e2944099e..2297f1645 100644
--- a/src/core/file_sys/directory_romfs.h
+++ b/src/core/file_sys/directory_romfs.h
@@ -1,12 +1,12 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9#include "core/file_sys/directory.h" 9#include "core/file_sys/directory_backend.h"
10#include "core/loader/loader.h" 10#include "core/loader/loader.h"
11 11
12//////////////////////////////////////////////////////////////////////////////////////////////////// 12////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -14,7 +14,7 @@
14 14
15namespace FileSys { 15namespace FileSys {
16 16
17class Directory_RomFS final : public Directory { 17class Directory_RomFS final : public DirectoryBackend {
18public: 18public:
19 Directory_RomFS(); 19 Directory_RomFS();
20 ~Directory_RomFS() override; 20 ~Directory_RomFS() override;
diff --git a/src/core/file_sys/directory_sdmc.cpp b/src/core/file_sys/directory_sdmc.cpp
deleted file mode 100644
index 519787641..000000000
--- a/src/core/file_sys/directory_sdmc.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include <sys/stat.h>
6
7#include "common/common_types.h"
8#include "common/file_util.h"
9
10#include "core/file_sys/directory_sdmc.h"
11#include "core/file_sys/archive_sdmc.h"
12
13////////////////////////////////////////////////////////////////////////////////////////////////////
14// FileSys namespace
15
16namespace FileSys {
17
18Directory_SDMC::Directory_SDMC(const Archive_SDMC* archive, const Path& path) {
19 // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass
20 // the root directory we set while opening the archive.
21 // For example, opening /../../usr/bin can give the emulated program your installed programs.
22 this->path = archive->GetMountPoint() + path.AsString();
23
24}
25
26Directory_SDMC::~Directory_SDMC() {
27 Close();
28}
29
30bool Directory_SDMC::Open() {
31 if (!FileUtil::IsDirectory(path))
32 return false;
33 FileUtil::ScanDirectoryTree(path, directory);
34 children_iterator = directory.children.begin();
35 return true;
36}
37
38/**
39 * List files contained in the directory
40 * @param count Number of entries to return at once in entries
41 * @param entries Buffer to read data into
42 * @return Number of entries listed
43 */
44u32 Directory_SDMC::Read(const u32 count, Entry* entries) {
45 u32 entries_read = 0;
46
47 while (entries_read < count && children_iterator != directory.children.cend()) {
48 const FileUtil::FSTEntry& file = *children_iterator;
49 const std::string& filename = file.virtualName;
50 Entry& entry = entries[entries_read];
51
52 LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, file.isDirectory);
53
54 // TODO(Link Mauve): use a proper conversion to UTF-16.
55 for (size_t j = 0; j < FILENAME_LENGTH; ++j) {
56 entry.filename[j] = filename[j];
57 if (!filename[j])
58 break;
59 }
60
61 FileUtil::SplitFilename83(filename, entry.short_name, entry.extension);
62
63 entry.is_directory = file.isDirectory;
64 entry.is_hidden = (filename[0] == '.');
65 entry.is_read_only = 0;
66 entry.file_size = file.size;
67
68 // We emulate a SD card where the archive bit has never been cleared, as it would be on
69 // most user SD cards.
70 // Some homebrews (blargSNES for instance) are known to mistakenly use the archive bit as a
71 // file bit.
72 entry.is_archive = !file.isDirectory;
73
74 ++entries_read;
75 ++children_iterator;
76 }
77 return entries_read;
78}
79
80/**
81 * Close the directory
82 * @return true if the directory closed correctly
83 */
84bool Directory_SDMC::Close() const {
85 return true;
86}
87
88} // namespace FileSys
diff --git a/src/core/file_sys/directory_sdmc.h b/src/core/file_sys/directory_sdmc.h
deleted file mode 100644
index 4c08b0d61..000000000
--- a/src/core/file_sys/directory_sdmc.h
+++ /dev/null
@@ -1,55 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8#include "common/file_util.h"
9
10#include "core/file_sys/directory.h"
11#include "core/file_sys/archive_sdmc.h"
12#include "core/loader/loader.h"
13
14////////////////////////////////////////////////////////////////////////////////////////////////////
15// FileSys namespace
16
17namespace FileSys {
18
19class Directory_SDMC final : public Directory {
20public:
21 Directory_SDMC();
22 Directory_SDMC(const Archive_SDMC* archive, const Path& path);
23 ~Directory_SDMC() override;
24
25 /**
26 * Open the directory
27 * @return true if the directory opened correctly
28 */
29 bool Open() override;
30
31 /**
32 * List files contained in the directory
33 * @param count Number of entries to return at once in entries
34 * @param entries Buffer to read data into
35 * @return Number of entries listed
36 */
37 u32 Read(const u32 count, Entry* entries) override;
38
39 /**
40 * Close the directory
41 * @return true if the directory closed correctly
42 */
43 bool Close() const override;
44
45private:
46 std::string path;
47 u32 total_entries_in_directory;
48 FileUtil::FSTEntry directory;
49
50 // We need to remember the last entry we returned, so a subsequent call to Read will continue
51 // from the next one. This iterator will always point to the next unread entry.
52 std::vector<FileUtil::FSTEntry>::iterator children_iterator;
53};
54
55} // namespace FileSys
diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp
new file mode 100644
index 000000000..0197f727d
--- /dev/null
+++ b/src/core/file_sys/disk_archive.cpp
@@ -0,0 +1,188 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <sys/stat.h>
6
7#include "common/common_types.h"
8#include "common/file_util.h"
9
10#include "core/file_sys/disk_archive.h"
11#include "core/settings.h"
12
13////////////////////////////////////////////////////////////////////////////////////////////////////
14// FileSys namespace
15
16namespace FileSys {
17
18std::unique_ptr<FileBackend> DiskArchive::OpenFile(const Path& path, const Mode mode) const {
19 LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex);
20 DiskFile* file = new DiskFile(this, path, mode);
21 if (!file->Open())
22 return nullptr;
23 return std::unique_ptr<FileBackend>(file);
24}
25
26bool DiskArchive::DeleteFile(const Path& path) const {
27 return FileUtil::Delete(GetMountPoint() + path.AsString());
28}
29
30bool DiskArchive::RenameFile(const Path& src_path, const Path& dest_path) const {
31 return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString());
32}
33
34bool DiskArchive::DeleteDirectory(const Path& path) const {
35 return FileUtil::DeleteDir(GetMountPoint() + path.AsString());
36}
37
38ResultCode DiskArchive::CreateFile(const FileSys::Path& path, u32 size) const {
39 std::string full_path = GetMountPoint() + path.AsString();
40
41 if (FileUtil::Exists(full_path))
42 return ResultCode(ErrorDescription::AlreadyExists, ErrorModule::FS, ErrorSummary::NothingHappened, ErrorLevel::Info);
43
44 if (size == 0) {
45 FileUtil::CreateEmptyFile(full_path);
46 return RESULT_SUCCESS;
47 }
48
49 FileUtil::IOFile file(full_path, "wb");
50 // Creates a sparse file (or a normal file on filesystems without the concept of sparse files)
51 // We do this by seeking to the right size, then writing a single null byte.
52 if (file.Seek(size - 1, SEEK_SET) && file.WriteBytes("", 1) == 1)
53 return RESULT_SUCCESS;
54
55 return ResultCode(ErrorDescription::TooLarge, ErrorModule::FS, ErrorSummary::OutOfResource, ErrorLevel::Info);
56}
57
58
59bool DiskArchive::CreateDirectory(const Path& path) const {
60 return FileUtil::CreateDir(GetMountPoint() + path.AsString());
61}
62
63bool DiskArchive::RenameDirectory(const Path& src_path, const Path& dest_path) const {
64 return FileUtil::Rename(GetMountPoint() + src_path.AsString(), GetMountPoint() + dest_path.AsString());
65}
66
67std::unique_ptr<DirectoryBackend> DiskArchive::OpenDirectory(const Path& path) const {
68 LOG_DEBUG(Service_FS, "called path=%s", path.DebugStr().c_str());
69 DiskDirectory* directory = new DiskDirectory(this, path);
70 if (!directory->Open())
71 return nullptr;
72 return std::unique_ptr<DirectoryBackend>(directory);
73}
74
75////////////////////////////////////////////////////////////////////////////////////////////////////
76
77DiskFile::DiskFile(const DiskArchive* archive, const Path& path, const Mode mode) {
78 // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass
79 // the root directory we set while opening the archive.
80 // For example, opening /../../etc/passwd can give the emulated program your users list.
81 this->path = archive->GetMountPoint() + path.AsString();
82 this->mode.hex = mode.hex;
83 this->archive = archive;
84}
85
86bool DiskFile::Open() {
87 if (!mode.create_flag && !FileUtil::Exists(path)) {
88 LOG_ERROR(Service_FS, "Non-existing file %s can't be open without mode create.", path.c_str());
89 return false;
90 }
91
92 std::string mode_string;
93 if (mode.create_flag)
94 mode_string = "w+";
95 else if (mode.write_flag)
96 mode_string = "r+"; // Files opened with Write access can be read from
97 else if (mode.read_flag)
98 mode_string = "r";
99
100 // Open the file in binary mode, to avoid problems with CR/LF on Windows systems
101 mode_string += "b";
102
103 file = new FileUtil::IOFile(path, mode_string.c_str());
104 return true;
105}
106
107size_t DiskFile::Read(const u64 offset, const u32 length, u8* buffer) const {
108 file->Seek(offset, SEEK_SET);
109 return file->ReadBytes(buffer, length);
110}
111
112size_t DiskFile::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const {
113 file->Seek(offset, SEEK_SET);
114 size_t written = file->WriteBytes(buffer, length);
115 if (flush)
116 file->Flush();
117 return written;
118}
119
120size_t DiskFile::GetSize() const {
121 return static_cast<size_t>(file->GetSize());
122}
123
124bool DiskFile::SetSize(const u64 size) const {
125 file->Resize(size);
126 file->Flush();
127 return true;
128}
129
130bool DiskFile::Close() const {
131 return file->Close();
132}
133
134////////////////////////////////////////////////////////////////////////////////////////////////////
135
136DiskDirectory::DiskDirectory(const DiskArchive* archive, const Path& path) {
137 // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass
138 // the root directory we set while opening the archive.
139 // For example, opening /../../usr/bin can give the emulated program your installed programs.
140 this->path = archive->GetMountPoint() + path.AsString();
141 this->archive = archive;
142}
143
144bool DiskDirectory::Open() {
145 if (!FileUtil::IsDirectory(path))
146 return false;
147 FileUtil::ScanDirectoryTree(path, directory);
148 children_iterator = directory.children.begin();
149 return true;
150}
151
152u32 DiskDirectory::Read(const u32 count, Entry* entries) {
153 u32 entries_read = 0;
154
155 while (entries_read < count && children_iterator != directory.children.cend()) {
156 const FileUtil::FSTEntry& file = *children_iterator;
157 const std::string& filename = file.virtualName;
158 Entry& entry = entries[entries_read];
159
160 LOG_TRACE(Service_FS, "File %s: size=%llu dir=%d", filename.c_str(), file.size, file.isDirectory);
161
162 // TODO(Link Mauve): use a proper conversion to UTF-16.
163 for (size_t j = 0; j < FILENAME_LENGTH; ++j) {
164 entry.filename[j] = filename[j];
165 if (!filename[j])
166 break;
167 }
168
169 FileUtil::SplitFilename83(filename, entry.short_name, entry.extension);
170
171 entry.is_directory = file.isDirectory;
172 entry.is_hidden = (filename[0] == '.');
173 entry.is_read_only = 0;
174 entry.file_size = file.size;
175
176 // We emulate a SD card where the archive bit has never been cleared, as it would be on
177 // most user SD cards.
178 // Some homebrews (blargSNES for instance) are known to mistakenly use the archive bit as a
179 // file bit.
180 entry.is_archive = !file.isDirectory;
181
182 ++entries_read;
183 ++children_iterator;
184 }
185 return entries_read;
186}
187
188} // namespace FileSys
diff --git a/src/core/file_sys/disk_archive.h b/src/core/file_sys/disk_archive.h
new file mode 100644
index 000000000..018ebd2ed
--- /dev/null
+++ b/src/core/file_sys/disk_archive.h
@@ -0,0 +1,103 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8#include "common/file_util.h"
9
10#include "core/file_sys/archive_backend.h"
11#include "core/loader/loader.h"
12
13////////////////////////////////////////////////////////////////////////////////////////////////////
14// FileSys namespace
15
16namespace FileSys {
17
18/**
19 * Helper which implements a backend accessing the host machine's filesystem.
20 * This should be subclassed by concrete archive types, which will provide the
21 * base directory on the host filesystem and override any required functionality.
22 */
23class DiskArchive : public ArchiveBackend {
24public:
25 DiskArchive(const std::string& mount_point_) : mount_point(mount_point_) {}
26
27 virtual std::string GetName() const = 0;
28 std::unique_ptr<FileBackend> OpenFile(const Path& path, const Mode mode) const override;
29 bool DeleteFile(const Path& path) const override;
30 bool RenameFile(const Path& src_path, const Path& dest_path) const override;
31 bool DeleteDirectory(const Path& path) const override;
32 ResultCode CreateFile(const Path& path, u32 size) const override;
33 bool CreateDirectory(const Path& path) const override;
34 bool RenameDirectory(const Path& src_path, const Path& dest_path) const override;
35 std::unique_ptr<DirectoryBackend> OpenDirectory(const Path& path) const override;
36
37 /**
38 * Getter for the path used for this Archive
39 * @return Mount point of that passthrough archive
40 */
41 const std::string& GetMountPoint() const {
42 return mount_point;
43 }
44
45protected:
46 std::string mount_point;
47};
48
49class DiskFile : public FileBackend {
50public:
51 DiskFile();
52 DiskFile(const DiskArchive* archive, const Path& path, const Mode mode);
53
54 ~DiskFile() override {
55 Close();
56 }
57
58 bool Open() override;
59 size_t Read(const u64 offset, const u32 length, u8* buffer) const override;
60 size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override;
61 size_t GetSize() const override;
62 bool SetSize(const u64 size) const override;
63 bool Close() const override;
64
65 void Flush() const override {
66 file->Flush();
67 }
68
69protected:
70 const DiskArchive* archive;
71 std::string path;
72 Mode mode;
73 FileUtil::IOFile* file;
74};
75
76class DiskDirectory : public DirectoryBackend {
77public:
78 DiskDirectory();
79 DiskDirectory(const DiskArchive* archive, const Path& path);
80
81 ~DiskDirectory() override {
82 Close();
83 }
84
85 bool Open() override;
86 u32 Read(const u32 count, Entry* entries) override;
87
88 bool Close() const override {
89 return true;
90 }
91
92protected:
93 const DiskArchive* archive;
94 std::string path;
95 u32 total_entries_in_directory;
96 FileUtil::FSTEntry directory;
97
98 // We need to remember the last entry we returned, so a subsequent call to Read will continue
99 // from the next one. This iterator will always point to the next unread entry.
100 std::vector<FileUtil::FSTEntry>::iterator children_iterator;
101};
102
103} // namespace FileSys
diff --git a/src/core/file_sys/file.h b/src/core/file_sys/file_backend.h
index 4013b6c3e..35890af1f 100644
--- a/src/core/file_sys/file.h
+++ b/src/core/file_sys/file_backend.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -13,10 +13,10 @@
13 13
14namespace FileSys { 14namespace FileSys {
15 15
16class File : NonCopyable { 16class FileBackend : NonCopyable {
17public: 17public:
18 File() { } 18 FileBackend() { }
19 virtual ~File() { } 19 virtual ~FileBackend() { }
20 20
21 /** 21 /**
22 * Open the file 22 * Open the file
@@ -61,6 +61,11 @@ public:
61 * @return true if the file closed correctly 61 * @return true if the file closed correctly
62 */ 62 */
63 virtual bool Close() const = 0; 63 virtual bool Close() const = 0;
64
65 /**
66 * Flushes the file
67 */
68 virtual void Flush() const = 0;
64}; 69};
65 70
66} // namespace FileSys 71} // namespace FileSys
diff --git a/src/core/file_sys/file_romfs.cpp b/src/core/file_sys/file_romfs.cpp
index b55708df4..7467d6d31 100644
--- a/src/core/file_sys/file_romfs.cpp
+++ b/src/core/file_sys/file_romfs.cpp
@@ -1,74 +1,41 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common_types.h" 5#include "common/common_types.h"
6 6
7#include "core/file_sys/file_romfs.h" 7#include "core/file_sys/file_romfs.h"
8#include "core/file_sys/archive_romfs.h"
8 9
9//////////////////////////////////////////////////////////////////////////////////////////////////// 10////////////////////////////////////////////////////////////////////////////////////////////////////
10// FileSys namespace 11// FileSys namespace
11 12
12namespace FileSys { 13namespace FileSys {
13 14
14File_RomFS::File_RomFS() {
15}
16
17File_RomFS::~File_RomFS() {
18}
19
20/**
21 * Open the file
22 * @return true if the file opened correctly
23 */
24bool File_RomFS::Open() { 15bool File_RomFS::Open() {
25 return false; 16 return true;
26} 17}
27 18
28/**
29 * Read data from the file
30 * @param offset Offset in bytes to start reading data from
31 * @param length Length in bytes of data to read from file
32 * @param buffer Buffer to read data into
33 * @return Number of bytes read
34 */
35size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const { 19size_t File_RomFS::Read(const u64 offset, const u32 length, u8* buffer) const {
36 return -1; 20 LOG_TRACE(Service_FS, "called offset=%llu, length=%d", offset, length);
21 memcpy(buffer, &archive->raw_data[(u32)offset], length);
22 return length;
37} 23}
38 24
39/**
40 * Write data to the file
41 * @param offset Offset in bytes to start writing data to
42 * @param length Length in bytes of data to write to file
43 * @param flush The flush parameters (0 == do not flush)
44 * @param buffer Buffer to read data from
45 * @return Number of bytes written
46 */
47size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const { 25size_t File_RomFS::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const {
48 return -1; 26 LOG_WARNING(Service_FS, "Attempted to write to ROMFS.");
27 return 0;
49} 28}
50 29
51/**
52 * Get the size of the file in bytes
53 * @return Size of the file in bytes
54 */
55size_t File_RomFS::GetSize() const { 30size_t File_RomFS::GetSize() const {
56 return -1; 31 return sizeof(u8) * archive->raw_data.size();
57} 32}
58 33
59/**
60 * Set the size of the file in bytes
61 * @param size New size of the file
62 * @return true if successful
63 */
64bool File_RomFS::SetSize(const u64 size) const { 34bool File_RomFS::SetSize(const u64 size) const {
35 LOG_WARNING(Service_FS, "Attempted to set the size of ROMFS");
65 return false; 36 return false;
66} 37}
67 38
68/**
69 * Close the file
70 * @return true if the file closed correctly
71 */
72bool File_RomFS::Close() const { 39bool File_RomFS::Close() const {
73 return false; 40 return false;
74} 41}
diff --git a/src/core/file_sys/file_romfs.h b/src/core/file_sys/file_romfs.h
index 5196701d3..04d8a16a2 100644
--- a/src/core/file_sys/file_romfs.h
+++ b/src/core/file_sys/file_romfs.h
@@ -1,12 +1,12 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9#include "core/file_sys/file.h" 9#include "core/file_sys/file_backend.h"
10#include "core/loader/loader.h" 10#include "core/loader/loader.h"
11 11
12//////////////////////////////////////////////////////////////////////////////////////////////////// 12////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -14,10 +14,11 @@
14 14
15namespace FileSys { 15namespace FileSys {
16 16
17class File_RomFS final : public File { 17class Archive_RomFS;
18
19class File_RomFS final : public FileBackend {
18public: 20public:
19 File_RomFS(); 21 File_RomFS(const Archive_RomFS* archive) : archive(archive) {}
20 ~File_RomFS() override;
21 22
22 /** 23 /**
23 * Open the file 24 * Open the file
@@ -62,6 +63,11 @@ public:
62 * @return true if the file closed correctly 63 * @return true if the file closed correctly
63 */ 64 */
64 bool Close() const override; 65 bool Close() const override;
66
67 void Flush() const override { }
68
69private:
70 const Archive_RomFS* archive;
65}; 71};
66 72
67} // namespace FileSys 73} // namespace FileSys
diff --git a/src/core/file_sys/file_sdmc.cpp b/src/core/file_sys/file_sdmc.cpp
deleted file mode 100644
index 46c29900b..000000000
--- a/src/core/file_sys/file_sdmc.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include <sys/stat.h>
6
7#include "common/common_types.h"
8#include "common/file_util.h"
9
10#include "core/file_sys/file_sdmc.h"
11#include "core/file_sys/archive_sdmc.h"
12
13////////////////////////////////////////////////////////////////////////////////////////////////////
14// FileSys namespace
15
16namespace FileSys {
17
18File_SDMC::File_SDMC(const Archive_SDMC* archive, const Path& path, const Mode mode) {
19 // TODO(Link Mauve): normalize path into an absolute path without "..", it can currently bypass
20 // the root directory we set while opening the archive.
21 // For example, opening /../../etc/passwd can give the emulated program your users list.
22 this->path = archive->GetMountPoint() + path.AsString();
23 this->mode.hex = mode.hex;
24}
25
26File_SDMC::~File_SDMC() {
27 Close();
28}
29
30/**
31 * Open the file
32 * @return true if the file opened correctly
33 */
34bool File_SDMC::Open() {
35 if (!mode.create_flag && !FileUtil::Exists(path)) {
36 LOG_ERROR(Service_FS, "Non-existing file %s can’t be open without mode create.", path.c_str());
37 return false;
38 }
39
40 std::string mode_string;
41 if (mode.create_flag)
42 mode_string = "w+";
43 else if (mode.write_flag)
44 mode_string = "r+"; // Files opened with Write access can be read from
45 else if (mode.read_flag)
46 mode_string = "r";
47
48 // Open the file in binary mode, to avoid problems with CR/LF on Windows systems
49 mode_string += "b";
50
51 file = new FileUtil::IOFile(path, mode_string.c_str());
52 return true;
53}
54
55/**
56 * Read data from the file
57 * @param offset Offset in bytes to start reading data from
58 * @param length Length in bytes of data to read from file
59 * @param buffer Buffer to read data into
60 * @return Number of bytes read
61 */
62size_t File_SDMC::Read(const u64 offset, const u32 length, u8* buffer) const {
63 file->Seek(offset, SEEK_SET);
64 return file->ReadBytes(buffer, length);
65}
66
67/**
68 * Write data to the file
69 * @param offset Offset in bytes to start writing data to
70 * @param length Length in bytes of data to write to file
71 * @param flush The flush parameters (0 == do not flush)
72 * @param buffer Buffer to read data from
73 * @return Number of bytes written
74 */
75size_t File_SDMC::Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const {
76 file->Seek(offset, SEEK_SET);
77 size_t written = file->WriteBytes(buffer, length);
78 if (flush)
79 file->Flush();
80 return written;
81}
82
83/**
84 * Get the size of the file in bytes
85 * @return Size of the file in bytes
86 */
87size_t File_SDMC::GetSize() const {
88 return static_cast<size_t>(file->GetSize());
89}
90
91/**
92 * Set the size of the file in bytes
93 * @param size New size of the file
94 * @return true if successful
95 */
96bool File_SDMC::SetSize(const u64 size) const {
97 file->Resize(size);
98 file->Flush();
99 return true;
100}
101
102/**
103 * Close the file
104 * @return true if the file closed correctly
105 */
106bool File_SDMC::Close() const {
107 return file->Close();
108}
109
110} // namespace FileSys
diff --git a/src/core/file_sys/file_sdmc.h b/src/core/file_sys/file_sdmc.h
deleted file mode 100644
index 80b445968..000000000
--- a/src/core/file_sys/file_sdmc.h
+++ /dev/null
@@ -1,75 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8#include "common/file_util.h"
9
10#include "core/file_sys/file.h"
11#include "core/file_sys/archive_sdmc.h"
12#include "core/loader/loader.h"
13
14////////////////////////////////////////////////////////////////////////////////////////////////////
15// FileSys namespace
16
17namespace FileSys {
18
19class File_SDMC final : public File {
20public:
21 File_SDMC();
22 File_SDMC(const Archive_SDMC* archive, const Path& path, const Mode mode);
23 ~File_SDMC() override;
24
25 /**
26 * Open the file
27 * @return true if the file opened correctly
28 */
29 bool Open() override;
30
31 /**
32 * Read data from the file
33 * @param offset Offset in bytes to start reading data from
34 * @param length Length in bytes of data to read from file
35 * @param buffer Buffer to read data into
36 * @return Number of bytes read
37 */
38 size_t Read(const u64 offset, const u32 length, u8* buffer) const override;
39
40 /**
41 * Write data to the file
42 * @param offset Offset in bytes to start writing data to
43 * @param length Length in bytes of data to write to file
44 * @param flush The flush parameters (0 == do not flush)
45 * @param buffer Buffer to read data from
46 * @return Number of bytes written
47 */
48 size_t Write(const u64 offset, const u32 length, const u32 flush, const u8* buffer) const override;
49
50 /**
51 * Get the size of the file in bytes
52 * @return Size of the file in bytes
53 */
54 size_t GetSize() const override;
55
56 /**
57 * Set the size of the file in bytes
58 * @param size New size of the file
59 * @return true if successful
60 */
61 bool SetSize(const u64 size) const override;
62
63 /**
64 * Close the file
65 * @return true if the file closed correctly
66 */
67 bool Close() const override;
68
69private:
70 std::string path;
71 Mode mode;
72 FileUtil::IOFile* file;
73};
74
75} // namespace FileSys
diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp
index d8ba9e6cf..721a600b5 100644
--- a/src/core/hle/config_mem.cpp
+++ b/src/core/hle/config_mem.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common_types.h" 5#include "common/common_types.h"
diff --git a/src/core/hle/config_mem.h b/src/core/hle/config_mem.h
index fa01b5cdb..3975af18f 100644
--- a/src/core/hle/config_mem.h
+++ b/src/core/hle/config_mem.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/hle/coprocessor.cpp b/src/core/hle/coprocessor.cpp
index e34229a57..425959be4 100644
--- a/src/core/hle/coprocessor.cpp
+++ b/src/core/hle/coprocessor.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/coprocessor.h" 5#include "core/hle/coprocessor.h"
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index 3dbe25037..3259ce9eb 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -114,6 +114,20 @@ template<s32 func(u32*, const char*)> void Wrap() {
114 FuncReturn(retval); 114 FuncReturn(retval);
115} 115}
116 116
117template<s32 func(u32*, s32, s32)> void Wrap() {
118 u32 param_1 = 0;
119 u32 retval = func(&param_1, PARAM(1), PARAM(2));
120 Core::g_app_core->SetReg(1, param_1);
121 FuncReturn(retval);
122}
123
124template<s32 func(s32*, u32, s32)> void Wrap() {
125 s32 param_1 = 0;
126 u32 retval = func(&param_1, PARAM(1), PARAM(2));
127 Core::g_app_core->SetReg(1, param_1);
128 FuncReturn(retval);
129}
130
117//////////////////////////////////////////////////////////////////////////////////////////////////// 131////////////////////////////////////////////////////////////////////////////////////////////////////
118// Function wrappers that return type u32 132// Function wrappers that return type u32
119 133
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp
index 3f73b5538..33ac12507 100644
--- a/src/core/hle/hle.cpp
+++ b/src/core/hle/hle.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <vector> 5#include <vector>
@@ -8,6 +8,8 @@
8#include "core/hle/hle.h" 8#include "core/hle/hle.h"
9#include "core/hle/kernel/thread.h" 9#include "core/hle/kernel/thread.h"
10#include "core/hle/service/service.h" 10#include "core/hle/service/service.h"
11#include "core/hle/service/fs/archive.h"
12#include "core/hle/service/cfg/cfg.h"
11 13
12//////////////////////////////////////////////////////////////////////////////////////////////////// 14////////////////////////////////////////////////////////////////////////////////////////////////////
13 15
@@ -41,7 +43,15 @@ void CallSVC(u32 opcode) {
41 43
42void Reschedule(const char *reason) { 44void Reschedule(const char *reason) {
43 _dbg_assert_msg_(Kernel, reason != 0 && strlen(reason) < 256, "Reschedule: Invalid or too long reason."); 45 _dbg_assert_msg_(Kernel, reason != 0 && strlen(reason) < 256, "Reschedule: Invalid or too long reason.");
46
47 // TODO(bunnei): It seems that games depend on some CPU execution time elapsing during HLE
48 // routines. This simulates that time by artificially advancing the number of CPU "ticks".
49 // The value was chosen empirically, it seems to work well enough for everything tested, but
50 // is likely not ideal. We should find a more accurate way to simulate timing with HLE.
51 Core::g_app_core->AddTicks(4000);
52
44 Core::g_app_core->PrepareReschedule(); 53 Core::g_app_core->PrepareReschedule();
54
45 g_reschedule = true; 55 g_reschedule = true;
46} 56}
47 57
@@ -56,6 +66,8 @@ void RegisterAllModules() {
56 66
57void Init() { 67void Init() {
58 Service::Init(); 68 Service::Init();
69 Service::FS::ArchiveInit();
70 Service::CFG::CFGInit();
59 71
60 RegisterAllModules(); 72 RegisterAllModules();
61 73
@@ -63,6 +75,8 @@ void Init() {
63} 75}
64 76
65void Shutdown() { 77void Shutdown() {
78 Service::CFG::CFGShutdown();
79 Service::FS::ArchiveShutdown();
66 Service::Shutdown(); 80 Service::Shutdown();
67 81
68 g_module_db.clear(); 82 g_module_db.clear();
diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h
index 4ab258c69..59b770f02 100644
--- a/src/core/hle/hle.h
+++ b/src/core/hle/hle.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 9a921108d..38705e3cd 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common_types.h" 5#include "common/common_types.h"
@@ -20,8 +20,8 @@ public:
20 std::string GetTypeName() const override { return "Arbiter"; } 20 std::string GetTypeName() const override { return "Arbiter"; }
21 std::string GetName() const override { return name; } 21 std::string GetName() const override { return name; }
22 22
23 static Kernel::HandleType GetStaticHandleType() { return HandleType::AddressArbiter; } 23 static const HandleType HANDLE_TYPE = HandleType::AddressArbiter;
24 Kernel::HandleType GetHandleType() const override { return HandleType::AddressArbiter; } 24 HandleType GetHandleType() const override { return HANDLE_TYPE; }
25 25
26 std::string name; ///< Name of address arbiter object (optional) 26 std::string name; ///< Name of address arbiter object (optional)
27}; 27};
@@ -62,7 +62,8 @@ ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s3
62/// Create an address arbiter 62/// Create an address arbiter
63AddressArbiter* CreateAddressArbiter(Handle& handle, const std::string& name) { 63AddressArbiter* CreateAddressArbiter(Handle& handle, const std::string& name) {
64 AddressArbiter* address_arbiter = new AddressArbiter; 64 AddressArbiter* address_arbiter = new AddressArbiter;
65 handle = Kernel::g_object_pool.Create(address_arbiter); 65 // TOOD(yuriks): Fix error reporting
66 handle = Kernel::g_handle_table.Create(address_arbiter).ValueOr(INVALID_HANDLE);
66 address_arbiter->name = name; 67 address_arbiter->name = name;
67 return address_arbiter; 68 return address_arbiter;
68} 69}
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index 8a5fb10b4..030e7ad7b 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp
deleted file mode 100644
index ddc09e13b..000000000
--- a/src/core/hle/kernel/archive.cpp
+++ /dev/null
@@ -1,435 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common/common_types.h"
6#include "common/file_util.h"
7#include "common/math_util.h"
8
9#include "core/file_sys/archive.h"
10#include "core/file_sys/archive_sdmc.h"
11#include "core/file_sys/directory.h"
12#include "core/hle/kernel/archive.h"
13#include "core/hle/result.h"
14#include "core/hle/service/service.h"
15
16////////////////////////////////////////////////////////////////////////////////////////////////////
17// Kernel namespace
18
19namespace Kernel {
20
21// Command to access archive file
22enum class FileCommand : u32 {
23 Dummy1 = 0x000100C6,
24 Control = 0x040100C4,
25 OpenSubFile = 0x08010100,
26 Read = 0x080200C2,
27 Write = 0x08030102,
28 GetSize = 0x08040000,
29 SetSize = 0x08050080,
30 GetAttributes = 0x08060000,
31 SetAttributes = 0x08070040,
32 Close = 0x08080000,
33 Flush = 0x08090000,
34};
35
36// Command to access directory
37enum class DirectoryCommand : u32 {
38 Dummy1 = 0x000100C6,
39 Control = 0x040100C4,
40 Read = 0x08010042,
41 Close = 0x08020000,
42};
43
44class Archive : public Object {
45public:
46 std::string GetTypeName() const override { return "Archive"; }
47 std::string GetName() const override { return name; }
48
49 static Kernel::HandleType GetStaticHandleType() { return HandleType::Archive; }
50 Kernel::HandleType GetHandleType() const override { return HandleType::Archive; }
51
52 std::string name; ///< Name of archive (optional)
53 FileSys::Archive* backend; ///< Archive backend interface
54
55 ResultVal<bool> SyncRequest() override {
56 u32* cmd_buff = Service::GetCommandBuffer();
57 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
58
59 switch (cmd) {
60 // Read from archive...
61 case FileCommand::Read:
62 {
63 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2] << 32);
64 u32 length = cmd_buff[3];
65 u32 address = cmd_buff[5];
66
67 // Number of bytes read
68 cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address));
69 break;
70 }
71 // Write to archive...
72 case FileCommand::Write:
73 {
74 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2] << 32);
75 u32 length = cmd_buff[3];
76 u32 flush = cmd_buff[4];
77 u32 address = cmd_buff[6];
78
79 // Number of bytes written
80 cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address));
81 break;
82 }
83 case FileCommand::GetSize:
84 {
85 u64 filesize = (u64) backend->GetSize();
86 cmd_buff[2] = (u32) filesize; // Lower word
87 cmd_buff[3] = (u32) (filesize >> 32); // Upper word
88 break;
89 }
90 case FileCommand::SetSize:
91 {
92 backend->SetSize(cmd_buff[1] | ((u64)cmd_buff[2] << 32));
93 break;
94 }
95 case FileCommand::Close:
96 {
97 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
98 CloseArchive(backend->GetIdCode());
99 break;
100 }
101 // Unknown command...
102 default:
103 {
104 LOG_ERROR(Service_FS, "Unknown command=0x%08X", cmd);
105 return UnimplementedFunction(ErrorModule::FS);
106 }
107 }
108 cmd_buff[1] = 0; // No error
109 return MakeResult<bool>(false);
110 }
111};
112
113class File : public Object {
114public:
115 std::string GetTypeName() const override { return "File"; }
116 std::string GetName() const override { return path.DebugStr(); }
117
118 static Kernel::HandleType GetStaticHandleType() { return HandleType::File; }
119 Kernel::HandleType GetHandleType() const override { return HandleType::File; }
120
121 FileSys::Path path; ///< Path of the file
122 std::unique_ptr<FileSys::File> backend; ///< File backend interface
123
124 ResultVal<bool> SyncRequest() override {
125 u32* cmd_buff = Service::GetCommandBuffer();
126 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
127 switch (cmd) {
128
129 // Read from file...
130 case FileCommand::Read:
131 {
132 u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32;
133 u32 length = cmd_buff[3];
134 u32 address = cmd_buff[5];
135 LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x",
136 GetTypeName().c_str(), GetName().c_str(), offset, length, address);
137 cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address));
138 break;
139 }
140
141 // Write to file...
142 case FileCommand::Write:
143 {
144 u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32;
145 u32 length = cmd_buff[3];
146 u32 flush = cmd_buff[4];
147 u32 address = cmd_buff[6];
148 LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x",
149 GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush);
150 cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address));
151 break;
152 }
153
154 case FileCommand::GetSize:
155 {
156 LOG_TRACE(Service_FS, "GetSize %s %s", GetTypeName().c_str(), GetName().c_str());
157 u64 size = backend->GetSize();
158 cmd_buff[2] = (u32)size;
159 cmd_buff[3] = size >> 32;
160 break;
161 }
162
163 case FileCommand::SetSize:
164 {
165 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32);
166 LOG_TRACE(Service_FS, "SetSize %s %s size=%llu",
167 GetTypeName().c_str(), GetName().c_str(), size);
168 backend->SetSize(size);
169 break;
170 }
171
172 case FileCommand::Close:
173 {
174 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
175 Kernel::g_object_pool.Destroy<File>(GetHandle());
176 break;
177 }
178
179 // Unknown command...
180 default:
181 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd);
182 ResultCode error = UnimplementedFunction(ErrorModule::FS);
183 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
184 return error;
185 }
186 cmd_buff[1] = 0; // No error
187 return MakeResult<bool>(false);
188 }
189};
190
191class Directory : public Object {
192public:
193 std::string GetTypeName() const override { return "Directory"; }
194 std::string GetName() const override { return path.DebugStr(); }
195
196 static Kernel::HandleType GetStaticHandleType() { return HandleType::Directory; }
197 Kernel::HandleType GetHandleType() const override { return HandleType::Directory; }
198
199 FileSys::Path path; ///< Path of the directory
200 std::unique_ptr<FileSys::Directory> backend; ///< File backend interface
201
202 ResultVal<bool> SyncRequest() override {
203 u32* cmd_buff = Service::GetCommandBuffer();
204 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]);
205 switch (cmd) {
206
207 // Read from directory...
208 case DirectoryCommand::Read:
209 {
210 u32 count = cmd_buff[1];
211 u32 address = cmd_buff[3];
212 auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address));
213 LOG_TRACE(Service_FS, "Read %s %s: count=%d",
214 GetTypeName().c_str(), GetName().c_str(), count);
215
216 // Number of entries actually read
217 cmd_buff[2] = backend->Read(count, entries);
218 break;
219 }
220
221 case DirectoryCommand::Close:
222 {
223 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
224 Kernel::g_object_pool.Destroy<Directory>(GetHandle());
225 break;
226 }
227
228 // Unknown command...
229 default:
230 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd);
231 ResultCode error = UnimplementedFunction(ErrorModule::FS);
232 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
233 return error;
234 }
235 cmd_buff[1] = 0; // No error
236 return MakeResult<bool>(false);
237 }
238};
239
240////////////////////////////////////////////////////////////////////////////////////////////////////
241
242std::map<FileSys::Archive::IdCode, Handle> g_archive_map; ///< Map of file archives by IdCode
243
244ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code) {
245 auto itr = g_archive_map.find(id_code);
246 if (itr == g_archive_map.end()) {
247 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
248 ErrorSummary::NotFound, ErrorLevel::Permanent);
249 }
250
251 return MakeResult<Handle>(itr->second);
252}
253
254ResultCode CloseArchive(FileSys::Archive::IdCode id_code) {
255 auto itr = g_archive_map.find(id_code);
256 if (itr == g_archive_map.end()) {
257 LOG_ERROR(Service_FS, "Cannot close archive %d, does not exist!", (int)id_code);
258 return InvalidHandle(ErrorModule::FS);
259 }
260
261 LOG_TRACE(Service_FS, "Closed archive %d", (int) id_code);
262 return RESULT_SUCCESS;
263}
264
265/**
266 * Mounts an archive
267 * @param archive Pointer to the archive to mount
268 */
269ResultCode MountArchive(Archive* archive) {
270 FileSys::Archive::IdCode id_code = archive->backend->GetIdCode();
271 ResultVal<Handle> archive_handle = OpenArchive(id_code);
272 if (archive_handle.Succeeded()) {
273 LOG_ERROR(Service_FS, "Cannot mount two archives with the same ID code! (%d)", (int) id_code);
274 return archive_handle.Code();
275 }
276 g_archive_map[id_code] = archive->GetHandle();
277 LOG_TRACE(Service_FS, "Mounted archive %s", archive->GetName().c_str());
278 return RESULT_SUCCESS;
279}
280
281ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name) {
282 Archive* archive = new Archive;
283 Handle handle = Kernel::g_object_pool.Create(archive);
284 archive->name = name;
285 archive->backend = backend;
286
287 ResultCode result = MountArchive(archive);
288 if (result.IsError()) {
289 return result;
290 }
291
292 return RESULT_SUCCESS;
293}
294
295ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) {
296 // TODO(bunnei): Binary type files get a raw file pointer to the archive. Currently, we create
297 // the archive file handles at app loading, and then keep them persistent throughout execution.
298 // Archives file handles are just reused and not actually freed until emulation shut down.
299 // Verify if real hardware works this way, or if new handles are created each time
300 if (path.GetType() == FileSys::Binary)
301 // TODO(bunnei): FixMe - this is a hack to compensate for an incorrect FileSys backend
302 // design. While the functionally of this is OK, our implementation decision to separate
303 // normal files from archive file pointers is very likely wrong.
304 // See https://github.com/citra-emu/citra/issues/205
305 return MakeResult<Handle>(archive_handle);
306
307 File* file = new File;
308 Handle handle = Kernel::g_object_pool.Create(file);
309
310 Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle);
311 if (archive == nullptr) {
312 return InvalidHandle(ErrorModule::FS);
313 }
314 file->path = path;
315 file->backend = archive->backend->OpenFile(path, mode);
316
317 if (!file->backend) {
318 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
319 ErrorSummary::NotFound, ErrorLevel::Permanent);
320 }
321
322 return MakeResult<Handle>(handle);
323}
324
325ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path) {
326 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
327 if (archive == nullptr)
328 return InvalidHandle(ErrorModule::FS);
329 if (archive->backend->DeleteFile(path))
330 return RESULT_SUCCESS;
331 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
332 ErrorSummary::Canceled, ErrorLevel::Status);
333}
334
335ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path,
336 Handle dest_archive_handle, const FileSys::Path& dest_path) {
337 Archive* src_archive = Kernel::g_object_pool.GetFast<Archive>(src_archive_handle);
338 Archive* dest_archive = Kernel::g_object_pool.GetFast<Archive>(dest_archive_handle);
339 if (src_archive == nullptr || dest_archive == nullptr)
340 return InvalidHandle(ErrorModule::FS);
341 if (src_archive == dest_archive) {
342 if (src_archive->backend->RenameFile(src_path, dest_path))
343 return RESULT_SUCCESS;
344 } else {
345 // TODO: Implement renaming across archives
346 return UnimplementedFunction(ErrorModule::FS);
347 }
348 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
349 ErrorSummary::NothingHappened, ErrorLevel::Status);
350}
351
352ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
353 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
354 if (archive == nullptr)
355 return InvalidHandle(ErrorModule::FS);
356 if (archive->backend->DeleteDirectory(path))
357 return RESULT_SUCCESS;
358 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
359 ErrorSummary::Canceled, ErrorLevel::Status);
360}
361
362ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
363 Archive* archive = Kernel::g_object_pool.GetFast<Archive>(archive_handle);
364 if (archive == nullptr)
365 return InvalidHandle(ErrorModule::FS);
366 if (archive->backend->CreateDirectory(path))
367 return RESULT_SUCCESS;
368 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
369 ErrorSummary::Canceled, ErrorLevel::Status);
370}
371
372ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path,
373 Handle dest_archive_handle, const FileSys::Path& dest_path) {
374 Archive* src_archive = Kernel::g_object_pool.GetFast<Archive>(src_archive_handle);
375 Archive* dest_archive = Kernel::g_object_pool.GetFast<Archive>(dest_archive_handle);
376 if (src_archive == nullptr || dest_archive == nullptr)
377 return InvalidHandle(ErrorModule::FS);
378 if (src_archive == dest_archive) {
379 if (src_archive->backend->RenameDirectory(src_path, dest_path))
380 return RESULT_SUCCESS;
381 } else {
382 // TODO: Implement renaming across archives
383 return UnimplementedFunction(ErrorModule::FS);
384 }
385 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
386 ErrorSummary::NothingHappened, ErrorLevel::Status);
387}
388
389/**
390 * Open a Directory from an Archive
391 * @param archive_handle Handle to an open Archive object
392 * @param path Path to the Directory inside of the Archive
393 * @return Opened Directory object
394 */
395ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path) {
396 Directory* directory = new Directory;
397 Handle handle = Kernel::g_object_pool.Create(directory);
398
399 Archive* archive = Kernel::g_object_pool.Get<Archive>(archive_handle);
400 if (archive == nullptr) {
401 return InvalidHandle(ErrorModule::FS);
402 }
403 directory->path = path;
404 directory->backend = archive->backend->OpenDirectory(path);
405
406 if (!directory->backend) {
407 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
408 ErrorSummary::NotFound, ErrorLevel::Permanent);
409 }
410
411 return MakeResult<Handle>(handle);
412}
413
414/// Initialize archives
415void ArchiveInit() {
416 g_archive_map.clear();
417
418 // TODO(Link Mauve): Add the other archive types (see here for the known types:
419 // http://3dbrew.org/wiki/FS:OpenArchive#Archive_idcodes). Currently the only half-finished
420 // archive type is SDMC, so it is the only one getting exposed.
421
422 std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX);
423 auto archive = new FileSys::Archive_SDMC(sdmc_directory);
424 if (archive->Initialize())
425 CreateArchive(archive, "SDMC");
426 else
427 LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str());
428}
429
430/// Shutdown archives
431void ArchiveShutdown() {
432 g_archive_map.clear();
433}
434
435} // namespace Kernel
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 288080209..e43c3ee4e 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <map> 5#include <map>
@@ -19,8 +19,8 @@ public:
19 std::string GetTypeName() const override { return "Event"; } 19 std::string GetTypeName() const override { return "Event"; }
20 std::string GetName() const override { return name; } 20 std::string GetName() const override { return name; }
21 21
22 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } 22 static const HandleType HANDLE_TYPE = HandleType::Event;
23 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Event; } 23 HandleType GetHandleType() const override { return HANDLE_TYPE; }
24 24
25 ResetType intitial_reset_type; ///< ResetType specified at Event initialization 25 ResetType intitial_reset_type; ///< ResetType specified at Event initialization
26 ResetType reset_type; ///< Current ResetType 26 ResetType reset_type; ///< Current ResetType
@@ -53,7 +53,7 @@ public:
53 * @return Result of operation, 0 on success, otherwise error code 53 * @return Result of operation, 0 on success, otherwise error code
54 */ 54 */
55ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) { 55ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) {
56 Event* evt = g_object_pool.Get<Event>(handle); 56 Event* evt = g_handle_table.Get<Event>(handle);
57 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); 57 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
58 58
59 evt->permanent_locked = permanent_locked; 59 evt->permanent_locked = permanent_locked;
@@ -67,7 +67,7 @@ ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) {
67 * @return Result of operation, 0 on success, otherwise error code 67 * @return Result of operation, 0 on success, otherwise error code
68 */ 68 */
69ResultCode SetEventLocked(const Handle handle, const bool locked) { 69ResultCode SetEventLocked(const Handle handle, const bool locked) {
70 Event* evt = g_object_pool.Get<Event>(handle); 70 Event* evt = g_handle_table.Get<Event>(handle);
71 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); 71 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
72 72
73 if (!evt->permanent_locked) { 73 if (!evt->permanent_locked) {
@@ -82,7 +82,7 @@ ResultCode SetEventLocked(const Handle handle, const bool locked) {
82 * @return Result of operation, 0 on success, otherwise error code 82 * @return Result of operation, 0 on success, otherwise error code
83 */ 83 */
84ResultCode SignalEvent(const Handle handle) { 84ResultCode SignalEvent(const Handle handle) {
85 Event* evt = g_object_pool.Get<Event>(handle); 85 Event* evt = g_handle_table.Get<Event>(handle);
86 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); 86 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
87 87
88 // Resume threads waiting for event to signal 88 // Resume threads waiting for event to signal
@@ -110,7 +110,7 @@ ResultCode SignalEvent(const Handle handle) {
110 * @return Result of operation, 0 on success, otherwise error code 110 * @return Result of operation, 0 on success, otherwise error code
111 */ 111 */
112ResultCode ClearEvent(Handle handle) { 112ResultCode ClearEvent(Handle handle) {
113 Event* evt = g_object_pool.Get<Event>(handle); 113 Event* evt = g_handle_table.Get<Event>(handle);
114 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); 114 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
115 115
116 if (!evt->permanent_locked) { 116 if (!evt->permanent_locked) {
@@ -129,7 +129,8 @@ ResultCode ClearEvent(Handle handle) {
129Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) { 129Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) {
130 Event* evt = new Event; 130 Event* evt = new Event;
131 131
132 handle = Kernel::g_object_pool.Create(evt); 132 // TOOD(yuriks): Fix error reporting
133 handle = Kernel::g_handle_table.Create(evt).ValueOr(INVALID_HANDLE);
133 134
134 evt->locked = true; 135 evt->locked = true;
135 evt->permanent_locked = false; 136 evt->permanent_locked = false;
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index 73aec4e79..da793df1a 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index b38be0a49..e59ed1b57 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project / PPSSPP Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
@@ -9,95 +9,109 @@
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/thread.h" 11#include "core/hle/kernel/thread.h"
12#include "core/hle/kernel/archive.h"
13 12
14namespace Kernel { 13namespace Kernel {
15 14
16Handle g_main_thread = 0; 15Handle g_main_thread = 0;
17ObjectPool g_object_pool; 16HandleTable g_handle_table;
17u64 g_program_id = 0;
18 18
19ObjectPool::ObjectPool() { 19HandleTable::HandleTable() {
20 next_id = INITIAL_NEXT_ID; 20 next_generation = 1;
21 Clear();
21} 22}
22 23
23Handle ObjectPool::Create(Object* obj, int range_bottom, int range_top) { 24ResultVal<Handle> HandleTable::Create(Object* obj) {
24 if (range_top > MAX_COUNT) { 25 _dbg_assert_(Kernel, obj != nullptr);
25 range_top = MAX_COUNT; 26
26 } 27 u16 slot = next_free_slot;
27 if (next_id >= range_bottom && next_id < range_top) { 28 if (slot >= generations.size()) {
28 range_bottom = next_id++; 29 LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
29 } 30 return ERR_OUT_OF_HANDLES;
30 for (int i = range_bottom; i < range_top; i++) {
31 if (!occupied[i]) {
32 occupied[i] = true;
33 pool[i] = obj;
34 pool[i]->handle = i + HANDLE_OFFSET;
35 return i + HANDLE_OFFSET;
36 }
37 } 31 }
38 LOG_ERROR(Kernel, "Unable to allocate kernel object, too many objects slots in use."); 32 next_free_slot = generations[slot];
39 return 0;
40}
41 33
42bool ObjectPool::IsValid(Handle handle) const { 34 u16 generation = next_generation++;
43 int index = handle - HANDLE_OFFSET;
44 if (index < 0)
45 return false;
46 if (index >= MAX_COUNT)
47 return false;
48 35
49 return occupied[index]; 36 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
37 // CTR-OS doesn't use generation 0, so skip straight to 1.
38 if (next_generation >= (1 << 15)) next_generation = 1;
39
40 generations[slot] = generation;
41 intrusive_ptr_add_ref(obj);
42 objects[slot] = obj;
43
44 Handle handle = generation | (slot << 15);
45 obj->handle = handle;
46 return MakeResult<Handle>(handle);
50} 47}
51 48
52void ObjectPool::Clear() { 49ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
53 for (int i = 0; i < MAX_COUNT; i++) { 50 Object* object = GetGeneric(handle);
54 //brutally clear everything, no validation 51 if (object == nullptr) {
55 if (occupied[i]) 52 LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle);
56 delete pool[i]; 53 return ERR_INVALID_HANDLE;
57 occupied[i] = false;
58 } 54 }
59 pool.fill(nullptr); 55 return Create(object);
60 next_id = INITIAL_NEXT_ID; 56}
57
58ResultCode HandleTable::Close(Handle handle) {
59 if (!IsValid(handle))
60 return ERR_INVALID_HANDLE;
61
62 size_t slot = GetSlot(handle);
63 u16 generation = GetGeneration(handle);
64
65 intrusive_ptr_release(objects[slot]);
66 objects[slot] = nullptr;
67
68 generations[generation] = next_free_slot;
69 next_free_slot = slot;
70 return RESULT_SUCCESS;
61} 71}
62 72
63Object* &ObjectPool::operator [](Handle handle) 73bool HandleTable::IsValid(Handle handle) const {
64{ 74 size_t slot = GetSlot(handle);
65 _dbg_assert_msg_(Kernel, IsValid(handle), "GRABBING UNALLOCED KERNEL OBJ"); 75 u16 generation = GetGeneration(handle);
66 return pool[handle - HANDLE_OFFSET]; 76
77 return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
67} 78}
68 79
69void ObjectPool::List() { 80Object* HandleTable::GetGeneric(Handle handle) const {
70 for (int i = 0; i < MAX_COUNT; i++) { 81 if (handle == CurrentThread) {
71 if (occupied[i]) { 82 // TODO(yuriks) Directly return the pointer once this is possible.
72 if (pool[i]) { 83 handle = GetCurrentThreadHandle();
73 LOG_DEBUG(Kernel, "KO %i: %s \"%s\"", i + HANDLE_OFFSET, pool[i]->GetTypeName().c_str(), 84 } else if (handle == CurrentProcess) {
74 pool[i]->GetName().c_str()); 85 LOG_ERROR(Kernel, "Current process (%08X) pseudo-handle not supported", CurrentProcess);
75 } 86 return nullptr;
76 }
77 } 87 }
78}
79 88
80int ObjectPool::GetCount() const { 89 if (!IsValid(handle)) {
81 return std::count(occupied.begin(), occupied.end(), true); 90 return nullptr;
91 }
92 return objects[GetSlot(handle)];
82} 93}
83 94
84Object* ObjectPool::CreateByIDType(int type) { 95void HandleTable::Clear() {
85 LOG_ERROR(Kernel, "Unimplemented: %d.", type); 96 for (size_t i = 0; i < MAX_COUNT; ++i) {
86 return nullptr; 97 generations[i] = i + 1;
98 if (objects[i] != nullptr)
99 intrusive_ptr_release(objects[i]);
100 objects[i] = nullptr;
101 }
102 next_free_slot = 0;
87} 103}
88 104
89/// Initialize the kernel 105/// Initialize the kernel
90void Init() { 106void Init() {
91 Kernel::ThreadingInit(); 107 Kernel::ThreadingInit();
92 Kernel::ArchiveInit();
93} 108}
94 109
95/// Shutdown the kernel 110/// Shutdown the kernel
96void Shutdown() { 111void Shutdown() {
97 Kernel::ThreadingShutdown(); 112 Kernel::ThreadingShutdown();
98 Kernel::ArchiveShutdown();
99 113
100 g_object_pool.Clear(); // Free all kernel objects 114 g_handle_table.Clear(); // Free all kernel objects
101} 115}
102 116
103/** 117/**
@@ -106,8 +120,6 @@ void Shutdown() {
106 * @return True on success, otherwise false 120 * @return True on success, otherwise false
107 */ 121 */
108bool LoadExec(u32 entry_point) { 122bool LoadExec(u32 entry_point) {
109 Init();
110
111 Core::g_app_core->SetPC(entry_point); 123 Core::g_app_core->SetPC(entry_point);
112 124
113 // 0x30 is the typical main thread priority I've seen used so far 125 // 0x30 is the typical main thread priority I've seen used so far
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 85e3264b9..7f86fd07d 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project / PPSSPP Project 1// Copyright 2014 Citra Emulator Project / PPSSPP Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -12,9 +12,17 @@
12typedef u32 Handle; 12typedef u32 Handle;
13typedef s32 Result; 13typedef s32 Result;
14 14
15const Handle INVALID_HANDLE = 0;
16
15namespace Kernel { 17namespace Kernel {
16 18
17enum KernelHandle { 19// TODO: Verify code
20const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
21 ErrorSummary::OutOfResource, ErrorLevel::Temporary);
22// TOOD: Verify code
23const ResultCode ERR_INVALID_HANDLE = InvalidHandle(ErrorModule::Kernel);
24
25enum KernelHandle : Handle {
18 CurrentThread = 0xFFFF8000, 26 CurrentThread = 0xFFFF8000,
19 CurrentProcess = 0xFFFF8001, 27 CurrentProcess = 0xFFFF8001,
20}; 28};
@@ -22,7 +30,7 @@ enum KernelHandle {
22enum class HandleType : u32 { 30enum class HandleType : u32 {
23 Unknown = 0, 31 Unknown = 0,
24 Port = 1, 32 Port = 1,
25 Service = 2, 33 Session = 2,
26 Event = 3, 34 Event = 3,
27 Mutex = 4, 35 Mutex = 4,
28 SharedMemory = 5, 36 SharedMemory = 5,
@@ -30,20 +38,17 @@ enum class HandleType : u32 {
30 Thread = 7, 38 Thread = 7,
31 Process = 8, 39 Process = 8,
32 AddressArbiter = 9, 40 AddressArbiter = 9,
33 File = 10, 41 Semaphore = 10,
34 Semaphore = 11,
35 Archive = 12,
36 Directory = 13,
37}; 42};
38 43
39enum { 44enum {
40 DEFAULT_STACK_SIZE = 0x4000, 45 DEFAULT_STACK_SIZE = 0x4000,
41}; 46};
42 47
43class ObjectPool; 48class HandleTable;
44 49
45class Object : NonCopyable { 50class Object : NonCopyable {
46 friend class ObjectPool; 51 friend class HandleTable;
47 u32 handle; 52 u32 handle;
48public: 53public:
49 virtual ~Object() {} 54 virtual ~Object() {}
@@ -53,15 +58,6 @@ public:
53 virtual Kernel::HandleType GetHandleType() const = 0; 58 virtual Kernel::HandleType GetHandleType() const = 0;
54 59
55 /** 60 /**
56 * Synchronize kernel object.
57 * @return True if the current thread should wait as a result of the sync
58 */
59 virtual ResultVal<bool> SyncRequest() {
60 LOG_ERROR(Kernel, "(UNIMPLEMENTED)");
61 return UnimplementedFunction(ErrorModule::Kernel);
62 }
63
64 /**
65 * Wait for kernel object to synchronize. 61 * Wait for kernel object to synchronize.
66 * @return True if the current thread should wait as a result of the wait 62 * @return True if the current thread should wait as a result of the wait
67 */ 63 */
@@ -69,100 +65,138 @@ public:
69 LOG_ERROR(Kernel, "(UNIMPLEMENTED)"); 65 LOG_ERROR(Kernel, "(UNIMPLEMENTED)");
70 return UnimplementedFunction(ErrorModule::Kernel); 66 return UnimplementedFunction(ErrorModule::Kernel);
71 } 67 }
68
69private:
70 friend void intrusive_ptr_add_ref(Object*);
71 friend void intrusive_ptr_release(Object*);
72
73 unsigned int ref_count = 0;
72}; 74};
73 75
74class ObjectPool : NonCopyable { 76// Special functions that will later be used by boost::instrusive_ptr to do automatic ref-counting
77inline void intrusive_ptr_add_ref(Object* object) {
78 ++object->ref_count;
79}
80
81inline void intrusive_ptr_release(Object* object) {
82 if (--object->ref_count == 0) {
83 delete object;
84 }
85}
86
87/**
88 * This class allows the creation of Handles, which are references to objects that can be tested
89 * for validity and looked up. Here they are used to pass references to kernel objects to/from the
90 * emulated process. it has been designed so that it follows the same handle format and has
91 * approximately the same restrictions as the handle manager in the CTR-OS.
92 *
93 * Handles contain two sub-fields: a slot index (bits 31:15) and a generation value (bits 14:0).
94 * The slot index is used to index into the arrays in this class to access the data corresponding
95 * to the Handle.
96 *
97 * To prevent accidental use of a freed Handle whose slot has already been reused, a global counter
98 * is kept and incremented every time a Handle is created. This is the Handle's "generation". The
99 * value of the counter is stored into the Handle as well as in the handle table (in the
100 * "generations" array). When looking up a handle, the Handle's generation must match with the
101 * value stored on the class, otherwise the Handle is considered invalid.
102 *
103 * To find free slots when allocating a Handle without needing to scan the entire object array, the
104 * generations field of unallocated slots is re-purposed as a linked list of indices to free slots.
105 * When a Handle is created, an index is popped off the list and used for the new Handle. When it
106 * is destroyed, it is again pushed onto the list to be re-used by the next allocation. It is
107 * likely that this allocation strategy differs from the one used in CTR-OS, but this hasn't been
108 * verified and isn't likely to cause any problems.
109 */
110class HandleTable final : NonCopyable {
75public: 111public:
76 ObjectPool(); 112 HandleTable();
77 ~ObjectPool() {}
78 113
79 // Allocates a handle within the range and inserts the object into the map. 114 /**
80 Handle Create(Object* obj, int range_bottom=INITIAL_NEXT_ID, int range_top=0x7FFFFFFF); 115 * Allocates a handle for the given object.
116 * @return The created Handle or one of the following errors:
117 * - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded.
118 */
119 ResultVal<Handle> Create(Object* obj);
81 120
82 static Object* CreateByIDType(int type); 121 /**
122 * Returns a new handle that points to the same object as the passed in handle.
123 * @return The duplicated Handle or one of the following errors:
124 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
125 * - Any errors returned by `Create()`.
126 */
127 ResultVal<Handle> Duplicate(Handle handle);
83 128
84 template <class T> 129 /**
85 void Destroy(Handle handle) { 130 * Closes a handle, removing it from the table and decreasing the object's ref-count.
86 if (Get<T>(handle)) { 131 * @return `RESULT_SUCCESS` or one of the following errors:
87 occupied[handle - HANDLE_OFFSET] = false; 132 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
88 delete pool[handle - HANDLE_OFFSET]; 133 */
89 } 134 ResultCode Close(Handle handle);
90 }
91 135
136 /// Checks if a handle is valid and points to an existing object.
92 bool IsValid(Handle handle) const; 137 bool IsValid(Handle handle) const;
93 138
94 template <class T> 139 /**
95 T* Get(Handle handle) { 140 * Looks up a handle.
96 if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) { 141 * @returns Pointer to the looked-up object, or `nullptr` if the handle is not valid.
97 if (handle != 0) { 142 */
98 LOG_ERROR(Kernel, "Bad object handle %08x", handle); 143 Object* GetGeneric(Handle handle) const;
99 }
100 return nullptr;
101 } else {
102 Object* t = pool[handle - HANDLE_OFFSET];
103 if (t->GetHandleType() != T::GetStaticHandleType()) {
104 LOG_ERROR(Kernel, "Wrong object type for %08x", handle);
105 return nullptr;
106 }
107 return static_cast<T*>(t);
108 }
109 }
110 144
111 // ONLY use this when you know the handle is valid. 145 /**
146 * Looks up a handle while verifying its type.
147 * @returns Pointer to the looked-up object, or `nullptr` if the handle is not valid or its
148 * type differs from the handle type `T::HANDLE_TYPE`.
149 */
112 template <class T> 150 template <class T>
113 T *GetFast(Handle handle) { 151 T* Get(Handle handle) const {
114 const Handle realHandle = handle - HANDLE_OFFSET; 152 Object* object = GetGeneric(handle);
115 _dbg_assert_(Kernel, realHandle >= 0 && realHandle < MAX_COUNT && occupied[realHandle]); 153 if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) {
116 return static_cast<T*>(pool[realHandle]); 154 return static_cast<T*>(object);
117 }
118
119 template <class T, typename ArgT>
120 void Iterate(bool func(T*, ArgT), ArgT arg) {
121 int type = T::GetStaticIDType();
122 for (int i = 0; i < MAX_COUNT; i++)
123 {
124 if (!occupied[i])
125 continue;
126 T* t = static_cast<T*>(pool[i]);
127 if (t->GetIDType() == type) {
128 if (!func(t, arg))
129 break;
130 }
131 } 155 }
156 return nullptr;
132 } 157 }
133 158
134 bool GetIDType(Handle handle, HandleType* type) const { 159 /// Closes all handles held in this table.
135 if ((handle < HANDLE_OFFSET) || (handle >= HANDLE_OFFSET + MAX_COUNT) ||
136 !occupied[handle - HANDLE_OFFSET]) {
137 LOG_ERROR(Kernel, "Bad object handle %08X", handle);
138 return false;
139 }
140 Object* t = pool[handle - HANDLE_OFFSET];
141 *type = t->GetHandleType();
142 return true;
143 }
144
145 Object* &operator [](Handle handle);
146 void List();
147 void Clear(); 160 void Clear();
148 int GetCount() const;
149 161
150private: 162private:
163 /**
164 * This is the maximum limit of handles allowed per process in CTR-OS. It can be further
165 * reduced by ExHeader values, but this is not emulated here.
166 */
167 static const size_t MAX_COUNT = 4096;
151 168
152 enum { 169 static size_t GetSlot(Handle handle) { return handle >> 15; }
153 MAX_COUNT = 0x1000, 170 static u16 GetGeneration(Handle handle) { return handle & 0x7FFF; }
154 HANDLE_OFFSET = 0x100,
155 INITIAL_NEXT_ID = 0x10,
156 };
157 171
158 std::array<Object*, MAX_COUNT> pool; 172 /// Stores the Object referenced by the handle or null if the slot is empty.
159 std::array<bool, MAX_COUNT> occupied; 173 std::array<Object*, MAX_COUNT> objects;
160 int next_id; 174
175 /**
176 * The value of `next_generation` when the handle was created, used to check for validity. For
177 * empty slots, contains the index of the next free slot in the list.
178 */
179 std::array<u16, MAX_COUNT> generations;
180
181 /**
182 * Global counter of the number of created handles. Stored in `generations` when a handle is
183 * created, and wraps around to 1 when it hits 0x8000.
184 */
185 u16 next_generation;
186
187 /// Head of the free slots linked list.
188 u16 next_free_slot;
161}; 189};
162 190
163extern ObjectPool g_object_pool; 191extern HandleTable g_handle_table;
164extern Handle g_main_thread; 192extern Handle g_main_thread;
165 193
194/// The ID code of the currently running game
195/// TODO(Subv): This variable should not be here,
196/// we need a way to store information about the currently loaded application
197/// for later query during runtime, maybe using the LDR service?
198extern u64 g_program_id;
199
166/// Initialize the kernel 200/// Initialize the kernel
167void Init(); 201void Init();
168 202
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 5a173e129..558068c79 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <map> 5#include <map>
@@ -18,8 +18,8 @@ public:
18 std::string GetTypeName() const override { return "Mutex"; } 18 std::string GetTypeName() const override { return "Mutex"; }
19 std::string GetName() const override { return name; } 19 std::string GetName() const override { return name; }
20 20
21 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; } 21 static const HandleType HANDLE_TYPE = HandleType::Mutex;
22 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Mutex; } 22 HandleType GetHandleType() const override { return HANDLE_TYPE; }
23 23
24 bool initial_locked; ///< Initial lock state when mutex was created 24 bool initial_locked; ///< Initial lock state when mutex was created
25 bool locked; ///< Current locked state 25 bool locked; ///< Current locked state
@@ -87,7 +87,7 @@ void ReleaseThreadMutexes(Handle thread) {
87 87
88 // Release every mutex that the thread holds, and resume execution on the waiting threads 88 // Release every mutex that the thread holds, and resume execution on the waiting threads
89 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { 89 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) {
90 Mutex* mutex = g_object_pool.GetFast<Mutex>(iter->second); 90 Mutex* mutex = g_handle_table.Get<Mutex>(iter->second);
91 ResumeWaitingThread(mutex); 91 ResumeWaitingThread(mutex);
92 } 92 }
93 93
@@ -115,7 +115,7 @@ bool ReleaseMutex(Mutex* mutex) {
115 * @param handle Handle to mutex to release 115 * @param handle Handle to mutex to release
116 */ 116 */
117ResultCode ReleaseMutex(Handle handle) { 117ResultCode ReleaseMutex(Handle handle) {
118 Mutex* mutex = Kernel::g_object_pool.Get<Mutex>(handle); 118 Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle);
119 if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel); 119 if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel);
120 120
121 if (!ReleaseMutex(mutex)) { 121 if (!ReleaseMutex(mutex)) {
@@ -136,7 +136,8 @@ ResultCode ReleaseMutex(Handle handle) {
136 */ 136 */
137Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) { 137Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) {
138 Mutex* mutex = new Mutex; 138 Mutex* mutex = new Mutex;
139 handle = Kernel::g_object_pool.Create(mutex); 139 // TODO(yuriks): Fix error reporting
140 handle = Kernel::g_handle_table.Create(mutex).ValueOr(INVALID_HANDLE);
140 141
141 mutex->locked = mutex->initial_locked = initial_locked; 142 mutex->locked = mutex->initial_locked = initial_locked;
142 mutex->name = name; 143 mutex->name = name;
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 7f4909a6e..a8ca97014 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
new file mode 100644
index 000000000..6bc8066a6
--- /dev/null
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -0,0 +1,95 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <queue>
6
7#include "common/common.h"
8
9#include "core/hle/kernel/kernel.h"
10#include "core/hle/kernel/semaphore.h"
11#include "core/hle/kernel/thread.h"
12
13namespace Kernel {
14
15class Semaphore : public Object {
16public:
17 std::string GetTypeName() const override { return "Semaphore"; }
18 std::string GetName() const override { return name; }
19
20 static const HandleType HANDLE_TYPE = HandleType::Semaphore;
21 HandleType GetHandleType() const override { return HANDLE_TYPE; }
22
23 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
24 s32 available_count; ///< Number of free slots left in the semaphore
25 std::queue<Handle> waiting_threads; ///< Threads that are waiting for the semaphore
26 std::string name; ///< Name of semaphore (optional)
27
28 /**
29 * Tests whether a semaphore still has free slots
30 * @return Whether the semaphore is available
31 */
32 bool IsAvailable() const {
33 return available_count > 0;
34 }
35
36 ResultVal<bool> WaitSynchronization() override {
37 bool wait = !IsAvailable();
38
39 if (wait) {
40 Kernel::WaitCurrentThread(WAITTYPE_SEMA, GetHandle());
41 waiting_threads.push(GetCurrentThreadHandle());
42 } else {
43 --available_count;
44 }
45
46 return MakeResult<bool>(wait);
47 }
48};
49
50////////////////////////////////////////////////////////////////////////////////////////////////////
51
52ResultCode CreateSemaphore(Handle* handle, s32 initial_count,
53 s32 max_count, const std::string& name) {
54
55 if (initial_count > max_count)
56 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel,
57 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
58
59 Semaphore* semaphore = new Semaphore;
60 // TOOD(yuriks): Fix error reporting
61 *handle = g_handle_table.Create(semaphore).ValueOr(INVALID_HANDLE);
62
63 // When the semaphore is created, some slots are reserved for other threads,
64 // and the rest is reserved for the caller thread
65 semaphore->max_count = max_count;
66 semaphore->available_count = initial_count;
67 semaphore->name = name;
68
69 return RESULT_SUCCESS;
70}
71
72ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
73 Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle);
74 if (semaphore == nullptr)
75 return InvalidHandle(ErrorModule::Kernel);
76
77 if (semaphore->max_count - semaphore->available_count < release_count)
78 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel,
79 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
80
81 *count = semaphore->available_count;
82 semaphore->available_count += release_count;
83
84 // Notify some of the threads that the semaphore has been released
85 // stop once the semaphore is full again or there are no more waiting threads
86 while (!semaphore->waiting_threads.empty() && semaphore->IsAvailable()) {
87 Kernel::ResumeThreadFromWait(semaphore->waiting_threads.front());
88 semaphore->waiting_threads.pop();
89 --semaphore->available_count;
90 }
91
92 return RESULT_SUCCESS;
93}
94
95} // namespace
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
new file mode 100644
index 000000000..8644ecf0c
--- /dev/null
+++ b/src/core/hle/kernel/semaphore.h
@@ -0,0 +1,32 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9#include "core/hle/kernel/kernel.h"
10
11namespace Kernel {
12
13/**
14 * Creates a semaphore.
15 * @param handle Pointer to the handle of the newly created object
16 * @param initial_count Number of slots reserved for other threads
17 * @param max_count Maximum number of slots the semaphore can have
18 * @param name Optional name of semaphore
19 * @return ResultCode of the error
20 */
21ResultCode CreateSemaphore(Handle* handle, s32 initial_count, s32 max_count, const std::string& name = "Unknown");
22
23/**
24 * Releases a certain number of slots from a semaphore.
25 * @param count The number of free slots the semaphore had before this call
26 * @param handle The handle of the semaphore to release
27 * @param release_count The number of slots to release
28 * @return ResultCode of the error
29 */
30ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count);
31
32} // namespace
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
new file mode 100644
index 000000000..91f3ffc2c
--- /dev/null
+++ b/src/core/hle/kernel/session.h
@@ -0,0 +1,58 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/kernel.h"
8
9namespace Kernel {
10
11static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of header
12
13/**
14 * Returns a pointer to the command buffer in kernel memory
15 * @param offset Optional offset into command buffer
16 * @return Pointer to command buffer
17 */
18inline static u32* GetCommandBuffer(const int offset=0) {
19 return (u32*)Memory::GetPointer(Memory::KERNEL_MEMORY_VADDR + kCommandHeaderOffset + offset);
20}
21
22/**
23 * Kernel object representing the client endpoint of an IPC session. Sessions are the basic CTR-OS
24 * primitive for communication between different processes, and are used to implement service calls
25 * to the various system services.
26 *
27 * To make a service call, the client must write the command header and parameters to the buffer
28 * located at offset 0x80 of the TLS (Thread-Local Storage) area, then execute a SendSyncRequest
29 * SVC call with its Session handle. The kernel will read the command header, using it to marshall
30 * the parameters to the process at the server endpoint of the session. After the server replies to
31 * the request, the response is marshalled back to the caller's TLS buffer and control is
32 * transferred back to it.
33 *
34 * In Citra, only the client endpoint is currently implemented and only HLE calls, where the IPC
35 * request is answered by C++ code in the emulator, are supported. When SendSyncRequest is called
36 * with the session handle, this class's SyncRequest method is called, which should read the TLS
37 * buffer and emulate the call accordingly. Since the code can directly read the emulated memory,
38 * no parameter marshalling is done.
39 *
40 * In the long term, this should be turned into the full-fledged IPC mechanism implemented by
41 * CTR-OS so that IPC calls can be optionally handled by the real implementations of processes, as
42 * opposed to HLE simulations.
43 */
44class Session : public Object {
45public:
46 std::string GetTypeName() const override { return "Session"; }
47
48 static const HandleType HANDLE_TYPE = HandleType::Session;
49 HandleType GetHandleType() const override { return HANDLE_TYPE; }
50
51 /**
52 * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls
53 * aren't supported yet.
54 */
55 virtual ResultVal<bool> SyncRequest() = 0;
56};
57
58}
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 3c8c502c6..cea1f6fa1 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common.h" 5#include "common/common.h"
@@ -13,8 +13,8 @@ class SharedMemory : public Object {
13public: 13public:
14 std::string GetTypeName() const override { return "SharedMemory"; } 14 std::string GetTypeName() const override { return "SharedMemory"; }
15 15
16 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::SharedMemory; } 16 static const HandleType HANDLE_TYPE = HandleType::SharedMemory;
17 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::SharedMemory; } 17 HandleType GetHandleType() const override { return HANDLE_TYPE; }
18 18
19 u32 base_address; ///< Address of shared memory block in RAM 19 u32 base_address; ///< Address of shared memory block in RAM
20 MemoryPermission permissions; ///< Permissions of shared memory block (SVC field) 20 MemoryPermission permissions; ///< Permissions of shared memory block (SVC field)
@@ -32,7 +32,8 @@ public:
32 */ 32 */
33SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) { 33SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) {
34 SharedMemory* shared_memory = new SharedMemory; 34 SharedMemory* shared_memory = new SharedMemory;
35 handle = Kernel::g_object_pool.Create(shared_memory); 35 // TOOD(yuriks): Fix error reporting
36 handle = Kernel::g_handle_table.Create(shared_memory).ValueOr(INVALID_HANDLE);
36 shared_memory->name = name; 37 shared_memory->name = name;
37 return shared_memory; 38 return shared_memory;
38} 39}
@@ -60,7 +61,7 @@ ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions
60 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 61 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
61 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 62 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
62 } 63 }
63 SharedMemory* shared_memory = Kernel::g_object_pool.Get<SharedMemory>(handle); 64 SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
64 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); 65 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
65 66
66 shared_memory->base_address = address; 67 shared_memory->base_address = address;
@@ -71,7 +72,7 @@ ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions
71} 72}
72 73
73ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) { 74ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) {
74 SharedMemory* shared_memory = Kernel::g_object_pool.Get<SharedMemory>(handle); 75 SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
75 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); 76 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
76 77
77 if (0 != shared_memory->base_address) 78 if (0 != shared_memory->base_address)
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 304cf5b67..bb65c7ccd 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -12,11 +12,15 @@ namespace Kernel {
12 12
13/// Permissions for mapped shared memory blocks 13/// Permissions for mapped shared memory blocks
14enum class MemoryPermission : u32 { 14enum class MemoryPermission : u32 {
15 None = 0, 15 None = 0,
16 Read = (1u << 0), 16 Read = (1u << 0),
17 Write = (1u << 1), 17 Write = (1u << 1),
18 ReadWrite = (Read | Write), 18 ReadWrite = (Read | Write),
19 DontCare = (1u << 28) 19 Execute = (1u << 2),
20 ReadExecute = (Read | Execute),
21 WriteExecute = (Write | Execute),
22 ReadWriteExecute = (Read | Write | Execute),
23 DontCare = (1u << 28)
20}; 24};
21 25
22/** 26/**
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 1c04701de..872df2d14 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project / PPSSPP Project 1// Copyright 2014 Citra Emulator Project / PPSSPP Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
@@ -26,8 +26,8 @@ public:
26 std::string GetName() const override { return name; } 26 std::string GetName() const override { return name; }
27 std::string GetTypeName() const override { return "Thread"; } 27 std::string GetTypeName() const override { return "Thread"; }
28 28
29 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Thread; } 29 static const HandleType HANDLE_TYPE = HandleType::Thread;
30 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Thread; } 30 HandleType GetHandleType() const override { return HANDLE_TYPE; }
31 31
32 inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; } 32 inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; }
33 inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; } 33 inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; }
@@ -83,8 +83,7 @@ static Thread* current_thread;
83static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup 83static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup
84static u32 next_thread_id; ///< The next available thread id 84static u32 next_thread_id; ///< The next available thread id
85 85
86/// Gets the current thread 86Thread* GetCurrentThread() {
87inline Thread* GetCurrentThread() {
88 return current_thread; 87 return current_thread;
89} 88}
90 89
@@ -148,21 +147,24 @@ void ChangeReadyState(Thread* t, bool ready) {
148 } 147 }
149} 148}
150 149
151/// Verify that a thread has not been released from waiting 150/// Check if a thread is blocking on a specified wait type
152static bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle) { 151static bool CheckWaitType(const Thread* thread, WaitType type) {
153 _dbg_assert_(Kernel, thread != nullptr); 152 return (type == thread->wait_type) && (thread->IsWaiting());
154 return (type == thread->wait_type) && (wait_handle == thread->wait_handle) && (thread->IsWaiting());
155} 153}
156 154
157/// Verify that a thread has not been released from waiting (with wait address) 155/// Check if a thread is blocking on a specified wait type with a specified handle
158static bool VerifyWait(const Thread* thread, WaitType type, Handle wait_handle, VAddr wait_address) { 156static bool CheckWaitType(const Thread* thread, WaitType type, Handle wait_handle) {
159 _dbg_assert_(Kernel, thread != nullptr); 157 return CheckWaitType(thread, type) && (wait_handle == thread->wait_handle);
160 return VerifyWait(thread, type, wait_handle) && (wait_address == thread->wait_address); 158}
159
160/// Check if a thread is blocking on a specified wait type with a specified handle and address
161static bool CheckWaitType(const Thread* thread, WaitType type, Handle wait_handle, VAddr wait_address) {
162 return CheckWaitType(thread, type, wait_handle) && (wait_address == thread->wait_address);
161} 163}
162 164
163/// Stops the current thread 165/// Stops the current thread
164ResultCode StopThread(Handle handle, const char* reason) { 166ResultCode StopThread(Handle handle, const char* reason) {
165 Thread* thread = g_object_pool.Get<Thread>(handle); 167 Thread* thread = g_handle_table.Get<Thread>(handle);
166 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); 168 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel);
167 169
168 // Release all the mutexes that this thread holds 170 // Release all the mutexes that this thread holds
@@ -171,10 +173,10 @@ ResultCode StopThread(Handle handle, const char* reason) {
171 ChangeReadyState(thread, false); 173 ChangeReadyState(thread, false);
172 thread->status = THREADSTATUS_DORMANT; 174 thread->status = THREADSTATUS_DORMANT;
173 for (Handle waiting_handle : thread->waiting_threads) { 175 for (Handle waiting_handle : thread->waiting_threads) {
174 Thread* waiting_thread = g_object_pool.Get<Thread>(waiting_handle); 176 Thread* waiting_thread = g_handle_table.Get<Thread>(waiting_handle);
175 if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, handle)) { 177
178 if (CheckWaitType(waiting_thread, WAITTYPE_THREADEND, handle))
176 ResumeThreadFromWait(waiting_handle); 179 ResumeThreadFromWait(waiting_handle);
177 }
178 } 180 }
179 thread->waiting_threads.clear(); 181 thread->waiting_threads.clear();
180 182
@@ -208,9 +210,9 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) {
208 210
209 // Iterate through threads, find highest priority thread that is waiting to be arbitrated... 211 // Iterate through threads, find highest priority thread that is waiting to be arbitrated...
210 for (Handle handle : thread_queue) { 212 for (Handle handle : thread_queue) {
211 Thread* thread = g_object_pool.Get<Thread>(handle); 213 Thread* thread = g_handle_table.Get<Thread>(handle);
212 214
213 if (!VerifyWait(thread, WAITTYPE_ARB, arbiter, address)) 215 if (!CheckWaitType(thread, WAITTYPE_ARB, arbiter, address))
214 continue; 216 continue;
215 217
216 if (thread == nullptr) 218 if (thread == nullptr)
@@ -233,9 +235,9 @@ void ArbitrateAllThreads(u32 arbiter, u32 address) {
233 235
234 // Iterate through threads, find highest priority thread that is waiting to be arbitrated... 236 // Iterate through threads, find highest priority thread that is waiting to be arbitrated...
235 for (Handle handle : thread_queue) { 237 for (Handle handle : thread_queue) {
236 Thread* thread = g_object_pool.Get<Thread>(handle); 238 Thread* thread = g_handle_table.Get<Thread>(handle);
237 239
238 if (VerifyWait(thread, WAITTYPE_ARB, arbiter, address)) 240 if (CheckWaitType(thread, WAITTYPE_ARB, arbiter, address))
239 ResumeThreadFromWait(handle); 241 ResumeThreadFromWait(handle);
240 } 242 }
241} 243}
@@ -286,7 +288,7 @@ Thread* NextThread() {
286 if (next == 0) { 288 if (next == 0) {
287 return nullptr; 289 return nullptr;
288 } 290 }
289 return Kernel::g_object_pool.Get<Thread>(next); 291 return Kernel::g_handle_table.Get<Thread>(next);
290} 292}
291 293
292void WaitCurrentThread(WaitType wait_type, Handle wait_handle) { 294void WaitCurrentThread(WaitType wait_type, Handle wait_handle) {
@@ -303,9 +305,11 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle, VAddr wait_addres
303 305
304/// Resumes a thread from waiting by marking it as "ready" 306/// Resumes a thread from waiting by marking it as "ready"
305void ResumeThreadFromWait(Handle handle) { 307void ResumeThreadFromWait(Handle handle) {
306 Thread* thread = Kernel::g_object_pool.Get<Thread>(handle); 308 Thread* thread = Kernel::g_handle_table.Get<Thread>(handle);
307 if (thread) { 309 if (thread) {
308 thread->status &= ~THREADSTATUS_WAIT; 310 thread->status &= ~THREADSTATUS_WAIT;
311 thread->wait_handle = 0;
312 thread->wait_type = WAITTYPE_NONE;
309 if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { 313 if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) {
310 ChangeReadyState(thread, true); 314 ChangeReadyState(thread, true);
311 } 315 }
@@ -337,7 +341,8 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio
337 341
338 Thread* thread = new Thread; 342 Thread* thread = new Thread;
339 343
340 handle = Kernel::g_object_pool.Create(thread); 344 // TOOD(yuriks): Fix error reporting
345 handle = Kernel::g_handle_table.Create(thread).ValueOr(INVALID_HANDLE);
341 346
342 thread_queue.push_back(handle); 347 thread_queue.push_back(handle);
343 thread_ready_queue.prepare(priority); 348 thread_ready_queue.prepare(priority);
@@ -394,7 +399,7 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3
394 399
395/// Get the priority of the thread specified by handle 400/// Get the priority of the thread specified by handle
396ResultVal<u32> GetThreadPriority(const Handle handle) { 401ResultVal<u32> GetThreadPriority(const Handle handle) {
397 Thread* thread = g_object_pool.Get<Thread>(handle); 402 Thread* thread = g_handle_table.Get<Thread>(handle);
398 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); 403 if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel);
399 404
400 return MakeResult<u32>(thread->current_priority); 405 return MakeResult<u32>(thread->current_priority);
@@ -406,7 +411,7 @@ ResultCode SetThreadPriority(Handle handle, s32 priority) {
406 if (!handle) { 411 if (!handle) {
407 thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? 412 thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior?
408 } else { 413 } else {
409 thread = g_object_pool.Get<Thread>(handle); 414 thread = g_handle_table.Get<Thread>(handle);
410 if (thread == nullptr) { 415 if (thread == nullptr) {
411 return InvalidHandle(ErrorModule::Kernel); 416 return InvalidHandle(ErrorModule::Kernel);
412 } 417 }
@@ -469,23 +474,31 @@ void Reschedule() {
469 Thread* prev = GetCurrentThread(); 474 Thread* prev = GetCurrentThread();
470 Thread* next = NextThread(); 475 Thread* next = NextThread();
471 HLE::g_reschedule = false; 476 HLE::g_reschedule = false;
472 if (next > 0) {
473 LOG_TRACE(Kernel, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle());
474 477
478 if (next != nullptr) {
479 LOG_TRACE(Kernel, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle());
475 SwitchContext(next); 480 SwitchContext(next);
481 } else {
482 LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle());
476 483
477 // Hack - There is no mechanism yet to waken the primary thread if it has been put to sleep 484 for (Handle handle : thread_queue) {
478 // by a simulated VBLANK thread switch. So, we'll just immediately set it to "ready" again. 485 Thread* thread = g_handle_table.Get<Thread>(handle);
479 // This results in the current thread yielding on a VBLANK once, and then it will be 486 LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X",
480 // immediately placed back in the queue for execution. 487 thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, thread->wait_handle);
481 if (prev->wait_type == WAITTYPE_VBLANK) {
482 ResumeThreadFromWait(prev->GetHandle());
483 } 488 }
484 } 489 }
490
491 // TODO(bunnei): Hack - There is no timing mechanism yet to wake up a thread if it has been put
492 // to sleep. So, we'll just immediately set it to "ready" again after an attempted context
493 // switch has occurred. This results in the current thread yielding on a sleep once, and then it
494 // will immediately be placed back in the queue for execution.
495
496 if (CheckWaitType(prev, WAITTYPE_SLEEP))
497 ResumeThreadFromWait(prev->GetHandle());
485} 498}
486 499
487ResultCode GetThreadId(u32* thread_id, Handle handle) { 500ResultCode GetThreadId(u32* thread_id, Handle handle) {
488 Thread* thread = g_object_pool.Get<Thread>(handle); 501 Thread* thread = g_handle_table.Get<Thread>(handle);
489 if (thread == nullptr) 502 if (thread == nullptr)
490 return ResultCode(ErrorDescription::InvalidHandle, ErrorModule::OS, 503 return ResultCode(ErrorDescription::InvalidHandle, ErrorModule::OS,
491 ErrorSummary::WrongArgument, ErrorLevel::Permanent); 504 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index be7adface..0e1397cd9 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project / PPSSPP Project 1// Copyright 2014 Citra Emulator Project / PPSSPP Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -40,7 +40,6 @@ enum WaitType {
40 WAITTYPE_SEMA, 40 WAITTYPE_SEMA,
41 WAITTYPE_EVENT, 41 WAITTYPE_EVENT,
42 WAITTYPE_THREADEND, 42 WAITTYPE_THREADEND,
43 WAITTYPE_VBLANK,
44 WAITTYPE_MUTEX, 43 WAITTYPE_MUTEX,
45 WAITTYPE_SYNCH, 44 WAITTYPE_SYNCH,
46 WAITTYPE_ARB, 45 WAITTYPE_ARB,
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 15c4a2677..0e9c213e0 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -17,6 +17,8 @@
17/// Detailed description of the error. This listing is likely incomplete. 17/// Detailed description of the error. This listing is likely incomplete.
18enum class ErrorDescription : u32 { 18enum class ErrorDescription : u32 {
19 Success = 0, 19 Success = 0,
20 FS_NotFound = 100,
21 FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive
20 InvalidSection = 1000, 22 InvalidSection = 1000,
21 TooLarge = 1001, 23 TooLarge = 1001,
22 NotAuthorized = 1002, 24 NotAuthorized = 1002,
diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp
index 4130feb9d..20a3fa2e5 100644
--- a/src/core/hle/service/ac_u.cpp
+++ b/src/core/hle/service/ac_u.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -18,7 +18,7 @@ namespace AC_U {
18 * 2 : Output connection type, 0 = none, 1 = Old3DS Internet, 2 = New3DS Internet. 18 * 2 : Output connection type, 0 = none, 1 = Old3DS Internet, 2 = New3DS Internet.
19 */ 19 */
20void GetWifiStatus(Service::Interface* self) { 20void GetWifiStatus(Service::Interface* self) {
21 u32* cmd_buff = Service::GetCommandBuffer(); 21 u32* cmd_buff = Kernel::GetCommandBuffer();
22 22
23 // TODO(purpasmart96): This function is only a stub, 23 // TODO(purpasmart96): This function is only a stub,
24 // it returns a valid result without implementing full functionality. 24 // it returns a valid result without implementing full functionality.
@@ -56,7 +56,4 @@ Interface::Interface() {
56 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 56 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
57} 57}
58 58
59Interface::~Interface() {
60}
61
62} // namespace 59} // namespace
diff --git a/src/core/hle/service/ac_u.h b/src/core/hle/service/ac_u.h
index c91b28353..f1d26ebe8 100644
--- a/src/core/hle/service/ac_u.h
+++ b/src/core/hle/service/ac_u.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -16,11 +16,7 @@ namespace AC_U {
16class Interface : public Service::Interface { 16class Interface : public Service::Interface {
17public: 17public:
18 Interface(); 18 Interface();
19 ~Interface(); 19
20 /**
21 * Gets the string port name used by CTROS for the service
22 * @return Port name of service
23 */
24 std::string GetPortName() const override { 20 std::string GetPortName() const override {
25 return "ac:u"; 21 return "ac:u";
26 } 22 }
diff --git a/src/core/hle/service/act_u.cpp b/src/core/hle/service/act_u.cpp
new file mode 100644
index 000000000..10870f14b
--- /dev/null
+++ b/src/core/hle/service/act_u.cpp
@@ -0,0 +1,24 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/act_u.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace ACT_U
11
12namespace ACT_U {
13
14// Empty arrays are illegal -- commented out until an entry is added.
15//const Interface::FunctionInfo FunctionTable[] = { };
16
17////////////////////////////////////////////////////////////////////////////////////////////////////
18// Interface class
19
20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
22}
23
24} // namespace
diff --git a/src/core/hle/service/act_u.h b/src/core/hle/service/act_u.h
new file mode 100644
index 000000000..be41454a4
--- /dev/null
+++ b/src/core/hle/service/act_u.h
@@ -0,0 +1,23 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace ACT_U
11
12namespace ACT_U {
13
14class Interface : public Service::Interface {
15public:
16 Interface();
17
18 std::string GetPortName() const override {
19 return "act:u";
20 }
21};
22
23} // namespace
diff --git a/src/core/hle/service/am_app.cpp b/src/core/hle/service/am_app.cpp
new file mode 100644
index 000000000..0b396b6d3
--- /dev/null
+++ b/src/core/hle/service/am_app.cpp
@@ -0,0 +1,24 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/am_app.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace AM_APP
11
12namespace AM_APP {
13
14// Empty arrays are illegal -- commented out until an entry is added.
15//const Interface::FunctionInfo FunctionTable[] = { };
16
17////////////////////////////////////////////////////////////////////////////////////////////////////
18// Interface class
19
20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
22}
23
24} // namespace
diff --git a/src/core/hle/service/am_app.h b/src/core/hle/service/am_app.h
new file mode 100644
index 000000000..50dc2f5a2
--- /dev/null
+++ b/src/core/hle/service/am_app.h
@@ -0,0 +1,23 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace AM_APP
11
12namespace AM_APP {
13
14class Interface : public Service::Interface {
15public:
16 Interface();
17
18 std::string GetPortName() const override {
19 return "am:app";
20 }
21};
22
23} // namespace
diff --git a/src/core/hle/service/am_net.cpp b/src/core/hle/service/am_net.cpp
index 403cac353..112844e5b 100644
--- a/src/core/hle/service/am_net.cpp
+++ b/src/core/hle/service/am_net.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -41,7 +41,4 @@ Interface::Interface() {
41 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 41 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
42} 42}
43 43
44Interface::~Interface() {
45}
46
47} // namespace 44} // namespace
diff --git a/src/core/hle/service/am_net.h b/src/core/hle/service/am_net.h
index 4816e1697..616c33ee8 100644
--- a/src/core/hle/service/am_net.h
+++ b/src/core/hle/service/am_net.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -14,11 +14,7 @@ namespace AM_NET {
14class Interface : public Service::Interface { 14class Interface : public Service::Interface {
15public: 15public:
16 Interface(); 16 Interface();
17 ~Interface(); 17
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const override { 18 std::string GetPortName() const override {
23 return "am:net"; 19 return "am:net";
24 } 20 }
diff --git a/src/core/hle/service/apt_a.cpp b/src/core/hle/service/apt_a.cpp
new file mode 100644
index 000000000..dcf5ec4fe
--- /dev/null
+++ b/src/core/hle/service/apt_a.cpp
@@ -0,0 +1,34 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/apt_a.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace APT_A
11
12namespace APT_A {
13
14const Interface::FunctionInfo FunctionTable[] = {
15 {0x00010040, nullptr, "GetLockHandle?"},
16 {0x00020080, nullptr, "Initialize?"},
17 {0x00030040, nullptr, "Enable?"},
18 {0x00040040, nullptr, "Finalize?"},
19 {0x00050040, nullptr, "GetAppletManInfo?"},
20 {0x00060040, nullptr, "GetAppletInfo?"},
21 {0x003B0040, nullptr, "CancelLibraryApplet?"},
22 {0x00430040, nullptr, "NotifyToWait?"},
23 {0x004B00C2, nullptr, "AppletUtility?"},
24 {0x00550040, nullptr, "WriteInputToNsState?"},
25};
26
27////////////////////////////////////////////////////////////////////////////////////////////////////
28// Interface class
29
30Interface::Interface() {
31 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
32}
33
34} // namespace
diff --git a/src/core/hle/service/apt_a.h b/src/core/hle/service/apt_a.h
new file mode 100644
index 000000000..6cbf1288f
--- /dev/null
+++ b/src/core/hle/service/apt_a.h
@@ -0,0 +1,23 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace APT_A
11
12namespace APT_A {
13
14class Interface : public Service::Interface {
15public:
16 Interface();
17
18 std::string GetPortName() const override {
19 return "APT:A";
20 }
21};
22
23} // namespace
diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp
index b6d5d101f..d8b261ba7 100644
--- a/src/core/hle/service/apt_u.cpp
+++ b/src/core/hle/service/apt_u.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5 5
@@ -40,7 +40,7 @@ enum class SignalType : u32 {
40}; 40};
41 41
42void Initialize(Service::Interface* self) { 42void Initialize(Service::Interface* self) {
43 u32* cmd_buff = Service::GetCommandBuffer(); 43 u32* cmd_buff = Kernel::GetCommandBuffer();
44 44
45 cmd_buff[3] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Menu"); // APT menu event handle 45 cmd_buff[3] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Menu"); // APT menu event handle
46 cmd_buff[4] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Pause"); // APT pause event handle 46 cmd_buff[4] = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Pause"); // APT pause event handle
@@ -57,7 +57,7 @@ void Initialize(Service::Interface* self) {
57} 57}
58 58
59void GetLockHandle(Service::Interface* self) { 59void GetLockHandle(Service::Interface* self) {
60 u32* cmd_buff = Service::GetCommandBuffer(); 60 u32* cmd_buff = Kernel::GetCommandBuffer();
61 u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field 61 u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field
62 62
63 if (0 == lock_handle) { 63 if (0 == lock_handle) {
@@ -78,14 +78,14 @@ void GetLockHandle(Service::Interface* self) {
78} 78}
79 79
80void Enable(Service::Interface* self) { 80void Enable(Service::Interface* self) {
81 u32* cmd_buff = Service::GetCommandBuffer(); 81 u32* cmd_buff = Kernel::GetCommandBuffer();
82 u32 unk = cmd_buff[1]; // TODO(bunnei): What is this field used for? 82 u32 unk = cmd_buff[1]; // TODO(bunnei): What is this field used for?
83 cmd_buff[1] = 0; // No error 83 cmd_buff[1] = 0; // No error
84 LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); 84 LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk);
85} 85}
86 86
87void InquireNotification(Service::Interface* self) { 87void InquireNotification(Service::Interface* self) {
88 u32* cmd_buff = Service::GetCommandBuffer(); 88 u32* cmd_buff = Kernel::GetCommandBuffer();
89 u32 app_id = cmd_buff[2]; 89 u32 app_id = cmd_buff[2];
90 cmd_buff[1] = 0; // No error 90 cmd_buff[1] = 0; // No error
91 cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type 91 cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type
@@ -112,7 +112,7 @@ void InquireNotification(Service::Interface* self) {
112 * 8 : Output parameter buffer ptr 112 * 8 : Output parameter buffer ptr
113 */ 113 */
114void ReceiveParameter(Service::Interface* self) { 114void ReceiveParameter(Service::Interface* self) {
115 u32* cmd_buff = Service::GetCommandBuffer(); 115 u32* cmd_buff = Kernel::GetCommandBuffer();
116 u32 app_id = cmd_buff[1]; 116 u32 app_id = cmd_buff[1];
117 u32 buffer_size = cmd_buff[2]; 117 u32 buffer_size = cmd_buff[2];
118 cmd_buff[1] = 0; // No error 118 cmd_buff[1] = 0; // No error
@@ -143,7 +143,7 @@ void ReceiveParameter(Service::Interface* self) {
143 * 8 : Output parameter buffer ptr 143 * 8 : Output parameter buffer ptr
144 */ 144 */
145void GlanceParameter(Service::Interface* self) { 145void GlanceParameter(Service::Interface* self) {
146 u32* cmd_buff = Service::GetCommandBuffer(); 146 u32* cmd_buff = Kernel::GetCommandBuffer();
147 u32 app_id = cmd_buff[1]; 147 u32 app_id = cmd_buff[1];
148 u32 buffer_size = cmd_buff[2]; 148 u32 buffer_size = cmd_buff[2];
149 149
@@ -170,7 +170,7 @@ void GlanceParameter(Service::Interface* self) {
170 * 1 : Result of function, 0 on success, otherwise error code 170 * 1 : Result of function, 0 on success, otherwise error code
171 */ 171 */
172void AppletUtility(Service::Interface* self) { 172void AppletUtility(Service::Interface* self) {
173 u32* cmd_buff = Service::GetCommandBuffer(); 173 u32* cmd_buff = Kernel::GetCommandBuffer();
174 174
175 // These are from 3dbrew - I'm not really sure what they're used for. 175 // These are from 3dbrew - I'm not really sure what they're used for.
176 u32 unk = cmd_buff[1]; 176 u32 unk = cmd_buff[1];
@@ -196,7 +196,7 @@ void AppletUtility(Service::Interface* self) {
196void GetSharedFont(Service::Interface* self) { 196void GetSharedFont(Service::Interface* self) {
197 LOG_TRACE(Kernel_SVC, "called"); 197 LOG_TRACE(Kernel_SVC, "called");
198 198
199 u32* cmd_buff = Service::GetCommandBuffer(); 199 u32* cmd_buff = Kernel::GetCommandBuffer();
200 200
201 if (!shared_font.empty()) { 201 if (!shared_font.empty()) {
202 // TODO(bunnei): This function shouldn't copy the shared font every time it's called. 202 // TODO(bunnei): This function shouldn't copy the shared font every time it's called.
@@ -315,8 +315,8 @@ Interface::Interface() {
315 315
316 if (file.IsOpen()) { 316 if (file.IsOpen()) {
317 // Read shared font data 317 // Read shared font data
318 shared_font.resize(file.GetSize()); 318 shared_font.resize((size_t)file.GetSize());
319 file.ReadBytes(shared_font.data(), file.GetSize()); 319 file.ReadBytes(shared_font.data(), (size_t)file.GetSize());
320 320
321 // Create shared font memory object 321 // Create shared font memory object
322 shared_font_mem = Kernel::CreateSharedMemory("APT_U:shared_font_mem"); 322 shared_font_mem = Kernel::CreateSharedMemory("APT_U:shared_font_mem");
@@ -330,7 +330,4 @@ Interface::Interface() {
330 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 330 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
331} 331}
332 332
333Interface::~Interface() {
334}
335
336} // namespace 333} // namespace
diff --git a/src/core/hle/service/apt_u.h b/src/core/hle/service/apt_u.h
index 306730400..aad918cfc 100644
--- a/src/core/hle/service/apt_u.h
+++ b/src/core/hle/service/apt_u.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -20,15 +20,8 @@ namespace APT_U {
20/// Interface to "APT:U" service 20/// Interface to "APT:U" service
21class Interface : public Service::Interface { 21class Interface : public Service::Interface {
22public: 22public:
23
24 Interface(); 23 Interface();
25 24
26 ~Interface();
27
28 /**
29 * Gets the string port name used by CTROS for the service
30 * @return Port name of service
31 */
32 std::string GetPortName() const override { 25 std::string GetPortName() const override {
33 return "APT:U"; 26 return "APT:U";
34 } 27 }
diff --git a/src/core/hle/service/boss_u.cpp b/src/core/hle/service/boss_u.cpp
index b2ff4a756..1820ea7ad 100644
--- a/src/core/hle/service/boss_u.cpp
+++ b/src/core/hle/service/boss_u.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -11,18 +11,15 @@
11 11
12namespace BOSS_U { 12namespace BOSS_U {
13 13
14 const Interface::FunctionInfo FunctionTable[] = { 14const Interface::FunctionInfo FunctionTable[] = {
15 {0x00020100, nullptr, "GetStorageInfo"}, 15 {0x00020100, nullptr, "GetStorageInfo"},
16 }; 16};
17 17
18 //////////////////////////////////////////////////////////////////////////////////////////////////// 18////////////////////////////////////////////////////////////////////////////////////////////////////
19 // Interface class 19// Interface class
20
21 Interface::Interface() {
22 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
23 }
24 20
25 Interface::~Interface() { 21Interface::Interface() {
26 } 22 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
23}
27 24
28} // namespace 25} // namespace
diff --git a/src/core/hle/service/boss_u.h b/src/core/hle/service/boss_u.h
index af39b8e65..2668f2dfd 100644
--- a/src/core/hle/service/boss_u.h
+++ b/src/core/hle/service/boss_u.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -11,17 +11,13 @@
11 11
12namespace BOSS_U { 12namespace BOSS_U {
13 13
14 class Interface : public Service::Interface { 14class Interface : public Service::Interface {
15 public: 15public:
16 Interface(); 16 Interface();
17 ~Interface(); 17
18 /** 18 std::string GetPortName() const override {
19 * Gets the string port name used by CTROS for the service 19 return "boss:U";
20 * @return Port name of service 20 }
21 */ 21};
22 std::string GetPortName() const {
23 return "boss:U";
24 }
25 };
26 22
27} // namespace 23} // namespace
diff --git a/src/core/hle/service/cecd_u.cpp b/src/core/hle/service/cecd_u.cpp
new file mode 100644
index 000000000..b7655ef0b
--- /dev/null
+++ b/src/core/hle/service/cecd_u.cpp
@@ -0,0 +1,24 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/cecd_u.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace CECD_U
11
12namespace CECD_U {
13
14// Empty arrays are illegal -- commented out until an entry is added.
15//const Interface::FunctionInfo FunctionTable[] = { };
16
17////////////////////////////////////////////////////////////////////////////////////////////////////
18// Interface class
19
20Interface::Interface() {
21 //Register(FunctionTable, ARRAY_SIZE(FunctionTable));
22}
23
24} // namespace
diff --git a/src/core/hle/service/cecd_u.h b/src/core/hle/service/cecd_u.h
new file mode 100644
index 000000000..e67564135
--- /dev/null
+++ b/src/core/hle/service/cecd_u.h
@@ -0,0 +1,23 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace CECD_U
11
12namespace CECD_U {
13
14class Interface : public Service::Interface {
15public:
16 Interface();
17
18 std::string GetPortName() const override {
19 return "cecd:u";
20 }
21};
22
23} // namespace
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp
new file mode 100644
index 000000000..161aa8531
--- /dev/null
+++ b/src/core/hle/service/cfg/cfg.cpp
@@ -0,0 +1,202 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include "common/log.h"
7#include "common/make_unique.h"
8#include "core/file_sys/archive_systemsavedata.h"
9#include "core/hle/service/cfg/cfg.h"
10
11namespace Service {
12namespace CFG {
13
14const u64 CFG_SAVE_ID = 0x00010017;
15const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE;
16const ConsoleModelInfo CONSOLE_MODEL = { NINTENDO_3DS_XL, { 0, 0, 0 } };
17const u8 CONSOLE_LANGUAGE = LANGUAGE_EN;
18const char CONSOLE_USERNAME[0x14] = "CITRA";
19/// This will be initialized in CFGInit, and will be used when creating the block
20UsernameBlock CONSOLE_USERNAME_BLOCK;
21/// TODO(Subv): Find out what this actually is
22const u8 SOUND_OUTPUT_MODE = 2;
23const u8 UNITED_STATES_COUNTRY_ID = 49;
24/// TODO(Subv): Find what the other bytes are
25const ConsoleCountryInfo COUNTRY_INFO = { { 0, 0, 0 }, UNITED_STATES_COUNTRY_ID };
26
27/**
28 * TODO(Subv): Find out what this actually is, these values fix some NaN uniforms in some games,
29 * for example Nintendo Zone
30 * Thanks Normmatt for providing this information
31 */
32const std::array<float, 8> STEREO_CAMERA_SETTINGS = {
33 62.0f, 289.0f, 76.80000305175781f, 46.08000183105469f,
34 10.0f, 5.0f, 55.58000183105469f, 21.56999969482422f
35};
36
37static const u32 CONFIG_SAVEFILE_SIZE = 0x8000;
38static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
39
40static std::unique_ptr<FileSys::Archive_SystemSaveData> cfg_system_save_data;
41
42ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output) {
43 // Read the header
44 SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data());
45
46 auto itr = std::find_if(std::begin(config->block_entries), std::end(config->block_entries),
47 [&](const SaveConfigBlockEntry& entry) {
48 return entry.block_id == block_id && entry.size == size && (entry.flags & flag);
49 });
50
51 if (itr == std::end(config->block_entries)) {
52 LOG_ERROR(Service_CFG, "Config block %u with size %u and flags %u not found", block_id, size, flag);
53 return ResultCode(-1); // TODO(Subv): Find the correct error code
54 }
55
56 // The data is located in the block header itself if the size is less than 4 bytes
57 if (itr->size <= 4)
58 memcpy(output, &itr->offset_or_data, itr->size);
59 else
60 memcpy(output, &cfg_config_file_buffer[itr->offset_or_data], itr->size);
61
62 return RESULT_SUCCESS;
63}
64
65ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const u8* data) {
66 SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data());
67 if (config->total_entries >= CONFIG_FILE_MAX_BLOCK_ENTRIES)
68 return ResultCode(-1); // TODO(Subv): Find the right error code
69
70 // Insert the block header with offset 0 for now
71 config->block_entries[config->total_entries] = { block_id, 0, size, flags };
72 if (size > 4) {
73 u32 offset = config->data_entries_offset;
74 // Perform a search to locate the next offset for the new data
75 // use the offset and size of the previous block to determine the new position
76 for (int i = config->total_entries - 1; i >= 0; --i) {
77 // Ignore the blocks that don't have a separate data offset
78 if (config->block_entries[i].size > 4) {
79 offset = config->block_entries[i].offset_or_data +
80 config->block_entries[i].size;
81 break;
82 }
83 }
84
85 config->block_entries[config->total_entries].offset_or_data = offset;
86
87 // Write the data at the new offset
88 memcpy(&cfg_config_file_buffer[offset], data, size);
89 }
90 else {
91 // The offset_or_data field in the header contains the data itself if it's 4 bytes or less
92 memcpy(&config->block_entries[config->total_entries].offset_or_data, data, size);
93 }
94
95 ++config->total_entries;
96 return RESULT_SUCCESS;
97}
98
99ResultCode DeleteConfigNANDSaveFile() {
100 FileSys::Path path("config");
101 if (cfg_system_save_data->DeleteFile(path))
102 return RESULT_SUCCESS;
103 return ResultCode(-1); // TODO(Subv): Find the right error code
104}
105
106ResultCode UpdateConfigNANDSavegame() {
107 FileSys::Mode mode = {};
108 mode.write_flag = 1;
109 mode.create_flag = 1;
110 FileSys::Path path("config");
111 auto file = cfg_system_save_data->OpenFile(path, mode);
112 _assert_msg_(Service_CFG, file != nullptr, "could not open file");
113 file->Write(0, CONFIG_SAVEFILE_SIZE, 1, cfg_config_file_buffer.data());
114 return RESULT_SUCCESS;
115}
116
117ResultCode FormatConfig() {
118 ResultCode res = DeleteConfigNANDSaveFile();
119 if (!res.IsSuccess())
120 return res;
121 // Delete the old data
122 cfg_config_file_buffer.fill(0);
123 // Create the header
124 SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data());
125 // This value is hardcoded, taken from 3dbrew, verified by hardware, it's always the same value
126 config->data_entries_offset = 0x455C;
127 // Insert the default blocks
128 res = CreateConfigInfoBlk(0x00050005, sizeof(STEREO_CAMERA_SETTINGS), 0xE,
129 reinterpret_cast<const u8*>(STEREO_CAMERA_SETTINGS.data()));
130 if (!res.IsSuccess())
131 return res;
132 res = CreateConfigInfoBlk(0x00090001, sizeof(CONSOLE_UNIQUE_ID), 0xE,
133 reinterpret_cast<const u8*>(&CONSOLE_UNIQUE_ID));
134 if (!res.IsSuccess())
135 return res;
136 res = CreateConfigInfoBlk(0x000F0004, sizeof(CONSOLE_MODEL), 0x8,
137 reinterpret_cast<const u8*>(&CONSOLE_MODEL));
138 if (!res.IsSuccess())
139 return res;
140 res = CreateConfigInfoBlk(0x000A0002, sizeof(CONSOLE_LANGUAGE), 0xA, &CONSOLE_LANGUAGE);
141 if (!res.IsSuccess())
142 return res;
143 res = CreateConfigInfoBlk(0x00070001, sizeof(SOUND_OUTPUT_MODE), 0xE, &SOUND_OUTPUT_MODE);
144 if (!res.IsSuccess())
145 return res;
146 res = CreateConfigInfoBlk(0x000B0000, sizeof(COUNTRY_INFO), 0xE,
147 reinterpret_cast<const u8*>(&COUNTRY_INFO));
148 if (!res.IsSuccess())
149 return res;
150 res = CreateConfigInfoBlk(0x000A0000, sizeof(CONSOLE_USERNAME_BLOCK), 0xE,
151 reinterpret_cast<const u8*>(&CONSOLE_USERNAME_BLOCK));
152 if (!res.IsSuccess())
153 return res;
154 // Save the buffer to the file
155 res = UpdateConfigNANDSavegame();
156 if (!res.IsSuccess())
157 return res;
158 return RESULT_SUCCESS;
159}
160
161void CFGInit() {
162 // TODO(Subv): In the future we should use the FS service to query this archive,
163 // currently it is not possible because you can only have one open archive of the same type at any time
164 std::string syssavedata_directory = FileUtil::GetUserPath(D_SYSSAVEDATA_IDX);
165 cfg_system_save_data = Common::make_unique<FileSys::Archive_SystemSaveData>(
166 syssavedata_directory, CFG_SAVE_ID);
167 if (!cfg_system_save_data->Initialize()) {
168 LOG_CRITICAL(Service_CFG, "Could not initialize SystemSaveData archive for the CFG:U service");
169 return;
170 }
171
172 // TODO(Subv): All this code should be moved to cfg:i,
173 // it's only here because we do not currently emulate the lower level code that uses that service
174 // Try to open the file in read-only mode to check its existence
175 FileSys::Mode mode = {};
176 mode.read_flag = 1;
177 FileSys::Path path("config");
178 auto file = cfg_system_save_data->OpenFile(path, mode);
179
180 // Load the config if it already exists
181 if (file != nullptr) {
182 file->Read(0, CONFIG_SAVEFILE_SIZE, cfg_config_file_buffer.data());
183 return;
184 }
185
186 // Initialize the Username block
187 // TODO(Subv): Initialize this directly in the variable when MSVC supports char16_t string literals
188 CONSOLE_USERNAME_BLOCK.ng_word = 0;
189 CONSOLE_USERNAME_BLOCK.zero = 0;
190 // Copy string to buffer and pad with zeros at the end
191 auto size = Common::UTF8ToUTF16(CONSOLE_USERNAME).copy(CONSOLE_USERNAME_BLOCK.username, 0x14);
192 std::fill(std::begin(CONSOLE_USERNAME_BLOCK.username) + size,
193 std::end(CONSOLE_USERNAME_BLOCK.username), 0);
194 FormatConfig();
195}
196
197void CFGShutdown() {
198
199}
200
201} // namespace CFG
202} // namespace Service
diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h
new file mode 100644
index 000000000..c74527ca4
--- /dev/null
+++ b/src/core/hle/service/cfg/cfg.h
@@ -0,0 +1,144 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include "core/hle/result.h"
9
10namespace Service {
11namespace CFG {
12
13enum SystemModel {
14 NINTENDO_3DS = 0,
15 NINTENDO_3DS_XL = 1,
16 NEW_NINTENDO_3DS = 2,
17 NINTENDO_2DS = 3,
18 NEW_NINTENDO_3DS_XL = 4
19};
20
21enum SystemLanguage {
22 LANGUAGE_JP = 0,
23 LANGUAGE_EN = 1,
24 LANGUAGE_FR = 2,
25 LANGUAGE_DE = 3,
26 LANGUAGE_IT = 4,
27 LANGUAGE_ES = 5,
28 LANGUAGE_ZH = 6,
29 LANGUAGE_KO = 7,
30 LANGUAGE_NL = 8,
31 LANGUAGE_PT = 9,
32 LANGUAGE_RU = 10
33};
34
35/// Block header in the config savedata file
36struct SaveConfigBlockEntry {
37 u32 block_id; ///< The id of the current block
38 u32 offset_or_data; ///< This is the absolute offset to the block data if the size is greater than 4 bytes, otherwise it contains the data itself
39 u16 size; ///< The size of the block
40 u16 flags; ///< The flags of the block, possibly used for access control
41};
42
43/// The maximum number of block entries that can exist in the config file
44static const u32 CONFIG_FILE_MAX_BLOCK_ENTRIES = 1479;
45
46/**
47* The header of the config savedata file,
48* contains information about the blocks in the file
49*/
50struct SaveFileConfig {
51 u16 total_entries; ///< The total number of set entries in the config file
52 u16 data_entries_offset; ///< The offset where the data for the blocks start, this is hardcoded to 0x455C as per hardware
53 SaveConfigBlockEntry block_entries[CONFIG_FILE_MAX_BLOCK_ENTRIES]; ///< The block headers, the maximum possible value is 1479 as per hardware
54 u32 unknown; ///< This field is unknown, possibly padding, 0 has been observed in hardware
55};
56static_assert(sizeof(SaveFileConfig) == 0x455C, "The SaveFileConfig header must be exactly 0x455C bytes");
57
58struct UsernameBlock {
59 char16_t username[10]; ///< Exactly 20 bytes long, padded with zeros at the end if necessary
60 u32 zero;
61 u32 ng_word;
62};
63static_assert(sizeof(UsernameBlock) == 0x1C, "Size of UsernameBlock must be 0x1C");
64
65struct ConsoleModelInfo {
66 u8 model; ///< The console model (3DS, 2DS, etc)
67 u8 unknown[3]; ///< Unknown data
68};
69static_assert(sizeof(ConsoleModelInfo) == 4, "ConsoleModelInfo must be exactly 4 bytes");
70
71struct ConsoleCountryInfo {
72 u8 unknown[3]; ///< Unknown data
73 u8 country_code; ///< The country code of the console
74};
75static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exactly 4 bytes");
76
77extern const u64 CFG_SAVE_ID;
78extern const u64 CONSOLE_UNIQUE_ID;
79extern const ConsoleModelInfo CONSOLE_MODEL;
80extern const u8 CONSOLE_LANGUAGE;
81extern const char CONSOLE_USERNAME[0x14];
82/// This will be initialized in the Interface constructor, and will be used when creating the block
83extern UsernameBlock CONSOLE_USERNAME_BLOCK;
84/// TODO(Subv): Find out what this actually is
85extern const u8 SOUND_OUTPUT_MODE;
86extern const u8 UNITED_STATES_COUNTRY_ID;
87/// TODO(Subv): Find what the other bytes are
88extern const ConsoleCountryInfo COUNTRY_INFO;
89extern const std::array<float, 8> STEREO_CAMERA_SETTINGS;
90
91static_assert(sizeof(STEREO_CAMERA_SETTINGS) == 0x20, "STEREO_CAMERA_SETTINGS must be exactly 0x20 bytes");
92static_assert(sizeof(CONSOLE_UNIQUE_ID) == 8, "CONSOLE_UNIQUE_ID must be exactly 8 bytes");
93static_assert(sizeof(CONSOLE_LANGUAGE) == 1, "CONSOLE_LANGUAGE must be exactly 1 byte");
94static_assert(sizeof(SOUND_OUTPUT_MODE) == 1, "SOUND_OUTPUT_MODE must be exactly 1 byte");
95
96/**
97 * Reads a block with the specified id and flag from the Config savegame buffer
98 * and writes the output to output.
99 * The input size must match exactly the size of the requested block
100 * @param block_id The id of the block we want to read
101 * @param size The size of the block we want to read
102 * @param flag The requested block must have this flag set
103 * @param output A pointer where we will write the read data
104 * @returns ResultCode indicating the result of the operation, 0 on success
105 */
106ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output);
107
108/**
109 * Creates a block with the specified id and writes the input data to the cfg savegame buffer in memory.
110 * The config savegame file in the filesystem is not updated.
111 * @param block_id The id of the block we want to create
112 * @param size The size of the block we want to create
113 * @param flag The flags of the new block
114 * @param data A pointer containing the data we will write to the new block
115 * @returns ResultCode indicating the result of the operation, 0 on success
116 */
117ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const u8* data);
118
119/**
120 * Deletes the config savegame file from the filesystem, the buffer in memory is not affected
121 * @returns ResultCode indicating the result of the operation, 0 on success
122 */
123ResultCode DeleteConfigNANDSaveFile();
124
125/**
126 * Writes the config savegame memory buffer to the config savegame file in the filesystem
127 * @returns ResultCode indicating the result of the operation, 0 on success
128 */
129ResultCode UpdateConfigNANDSavegame();
130
131/**
132 * Re-creates the config savegame file in memory and the filesystem with the default blocks
133 * @returns ResultCode indicating the result of the operation, 0 on success
134 */
135ResultCode FormatConfig();
136
137/// Initialize the config service
138void CFGInit();
139
140/// Shutdown the config service
141void CFGShutdown();
142
143} // namespace CFG
144} // namespace Service
diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp
new file mode 100644
index 000000000..7c1ee8ac3
--- /dev/null
+++ b/src/core/hle/service/cfg/cfg_i.cpp
@@ -0,0 +1,110 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/cfg/cfg.h"
8#include "core/hle/service/cfg/cfg_i.h"
9
10////////////////////////////////////////////////////////////////////////////////////////////////////
11// Namespace CFG_I
12
13namespace CFG_I {
14
15/**
16 * CFG_I::GetConfigInfoBlk8 service function
17 * This function is called by two command headers,
18 * there appears to be no difference between them according to 3dbrew
19 * Inputs:
20 * 0 : 0x04010082 / 0x08010082
21 * 1 : Size
22 * 2 : Block ID
23 * 3 : Descriptor for the output buffer
24 * 4 : Output buffer pointer
25 * Outputs:
26 * 1 : Result of function, 0 on success, otherwise error code
27 */
28static void GetConfigInfoBlk8(Service::Interface* self) {
29 u32* cmd_buffer = Kernel::GetCommandBuffer();
30 u32 size = cmd_buffer[1];
31 u32 block_id = cmd_buffer[2];
32 u8* data_pointer = Memory::GetPointer(cmd_buffer[4]);
33
34 if (data_pointer == nullptr) {
35 cmd_buffer[1] = -1; // TODO(Subv): Find the right error code
36 return;
37 }
38
39 cmd_buffer[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data_pointer).raw;
40}
41
42/**
43 * CFG_I::UpdateConfigNANDSavegame service function
44 * This function is called by two command headers,
45 * there appears to be no difference between them according to 3dbrew
46 * Inputs:
47 * 0 : 0x04030000 / 0x08030000
48 * Outputs:
49 * 1 : Result of function, 0 on success, otherwise error code
50 */
51static void UpdateConfigNANDSavegame(Service::Interface* self) {
52 u32* cmd_buffer = Kernel::GetCommandBuffer();
53 cmd_buffer[1] = Service::CFG::UpdateConfigNANDSavegame().raw;
54}
55
56/**
57 * CFG_I::FormatConfig service function
58 * Inputs:
59 * 0 : 0x08060000
60 * Outputs:
61 * 1 : Result of function, 0 on success, otherwise error code
62 */
63static void FormatConfig(Service::Interface* self) {
64 u32* cmd_buffer = Kernel::GetCommandBuffer();
65 cmd_buffer[1] = Service::CFG::FormatConfig().raw;
66}
67
68const Interface::FunctionInfo FunctionTable[] = {
69 {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
70 {0x04020082, nullptr, "SetConfigInfoBlk4"},
71 {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
72 {0x04040042, nullptr, "GetLocalFriendCodeSeedData"},
73 {0x04050000, nullptr, "GetLocalFriendCodeSeed"},
74 {0x04060000, nullptr, "SecureInfoGetRegion"},
75 {0x04070000, nullptr, "SecureInfoGetByte101"},
76 {0x04080042, nullptr, "SecureInfoGetSerialNo"},
77 {0x04090000, nullptr, "UpdateConfigBlk00040003"},
78 {0x08010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
79 {0x08020082, nullptr, "SetConfigInfoBlk4"},
80 {0x08030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
81 {0x080400C2, nullptr, "CreateConfigInfoBlk"},
82 {0x08050000, nullptr, "DeleteConfigNANDSavefile"},
83 {0x08060000, FormatConfig, "FormatConfig"},
84 {0x08080000, nullptr, "UpdateConfigBlk1"},
85 {0x08090000, nullptr, "UpdateConfigBlk2"},
86 {0x080A0000, nullptr, "UpdateConfigBlk3"},
87 {0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"},
88 {0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"},
89 {0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"},
90 {0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"},
91 {0x080F0042, nullptr, "GetLocalFriendCodeSeedData"},
92 {0x08100000, nullptr, "GetLocalFriendCodeSeed"},
93 {0x08110084, nullptr, "SetSecureInfo"},
94 {0x08120000, nullptr, "DeleteCreateNANDSecureInfo"},
95 {0x08130000, nullptr, "VerifySigSecureInfo"},
96 {0x08140042, nullptr, "SecureInfoGetData"},
97 {0x08150042, nullptr, "SecureInfoGetSignature"},
98 {0x08160000, nullptr, "SecureInfoGetRegion"},
99 {0x08170000, nullptr, "SecureInfoGetByte101"},
100 {0x08180042, nullptr, "SecureInfoGetSerialNo"},
101};
102
103////////////////////////////////////////////////////////////////////////////////////////////////////
104// Interface class
105
106Interface::Interface() {
107 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
108}
109
110} // namespace
diff --git a/src/core/hle/service/cfg_i.h b/src/core/hle/service/cfg/cfg_i.h
index fe343c968..a498dd589 100644
--- a/src/core/hle/service/cfg_i.h
+++ b/src/core/hle/service/cfg/cfg_i.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -14,11 +14,7 @@ namespace CFG_I {
14class Interface : public Service::Interface { 14class Interface : public Service::Interface {
15public: 15public:
16 Interface(); 16 Interface();
17 ~Interface(); 17
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const override { 18 std::string GetPortName() const override {
23 return "cfg:i"; 19 return "cfg:i";
24 } 20 }
diff --git a/src/core/hle/service/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp
index 972cc0534..03c01cf90 100644
--- a/src/core/hle/service/cfg_u.cpp
+++ b/src/core/hle/service/cfg/cfg_u.cpp
@@ -1,10 +1,14 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/file_util.h"
5#include "common/log.h" 6#include "common/log.h"
7#include "common/string_util.h"
8#include "core/file_sys/archive_systemsavedata.h"
6#include "core/hle/hle.h" 9#include "core/hle/hle.h"
7#include "core/hle/service/cfg_u.h" 10#include "core/hle/service/cfg/cfg.h"
11#include "core/hle/service/cfg/cfg_u.h"
8 12
9//////////////////////////////////////////////////////////////////////////////////////////////////// 13////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace CFG_U 14// Namespace CFG_U
@@ -52,7 +56,7 @@ static const std::array<u16, 187> country_codes = {
52 * 2 : Country's 2-char string 56 * 2 : Country's 2-char string
53 */ 57 */
54static void GetCountryCodeString(Service::Interface* self) { 58static void GetCountryCodeString(Service::Interface* self) {
55 u32* cmd_buffer = Service::GetCommandBuffer(); 59 u32* cmd_buffer = Kernel::GetCommandBuffer();
56 u32 country_code_id = cmd_buffer[1]; 60 u32 country_code_id = cmd_buffer[1];
57 61
58 if (country_code_id >= country_codes.size() || 0 == country_codes[country_code_id]) { 62 if (country_code_id >= country_codes.size() || 0 == country_codes[country_code_id]) {
@@ -74,7 +78,7 @@ static void GetCountryCodeString(Service::Interface* self) {
74 * 2 : Country Code ID 78 * 2 : Country Code ID
75 */ 79 */
76static void GetCountryCodeID(Service::Interface* self) { 80static void GetCountryCodeID(Service::Interface* self) {
77 u32* cmd_buffer = Service::GetCommandBuffer(); 81 u32* cmd_buffer = Kernel::GetCommandBuffer();
78 u16 country_code = cmd_buffer[1]; 82 u16 country_code = cmd_buffer[1];
79 u16 country_code_id = 0; 83 u16 country_code_id = 0;
80 84
@@ -99,18 +103,85 @@ static void GetCountryCodeID(Service::Interface* self) {
99 cmd_buffer[2] = country_code_id; 103 cmd_buffer[2] = country_code_id;
100} 104}
101 105
106/**
107 * CFG_User::GetConfigInfoBlk2 service function
108 * Inputs:
109 * 0 : 0x00010082
110 * 1 : Size
111 * 2 : Block ID
112 * 3 : Descriptor for the output buffer
113 * 4 : Output buffer pointer
114 * Outputs:
115 * 1 : Result of function, 0 on success, otherwise error code
116 */
117static void GetConfigInfoBlk2(Service::Interface* self) {
118 u32* cmd_buffer = Kernel::GetCommandBuffer();
119 u32 size = cmd_buffer[1];
120 u32 block_id = cmd_buffer[2];
121 u8* data_pointer = Memory::GetPointer(cmd_buffer[4]);
122
123 if (data_pointer == nullptr) {
124 cmd_buffer[1] = -1; // TODO(Subv): Find the right error code
125 return;
126 }
127
128 cmd_buffer[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data_pointer).raw;
129}
130
131/**
132 * CFG_User::GetSystemModel service function
133 * Inputs:
134 * 0 : 0x00050000
135 * Outputs:
136 * 1 : Result of function, 0 on success, otherwise error code
137 * 2 : Model of the console
138 */
139static void GetSystemModel(Service::Interface* self) {
140 u32* cmd_buffer = Kernel::GetCommandBuffer();
141 u32 data;
142
143 // TODO(Subv): Find out the correct error codes
144 cmd_buffer[1] = Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8,
145 reinterpret_cast<u8*>(&data)).raw;
146 cmd_buffer[2] = data & 0xFF;
147}
148
149/**
150 * CFG_User::GetModelNintendo2DS service function
151 * Inputs:
152 * 0 : 0x00060000
153 * Outputs:
154 * 1 : Result of function, 0 on success, otherwise error code
155 * 2 : 0 if the system is a Nintendo 2DS, 1 otherwise
156 */
157static void GetModelNintendo2DS(Service::Interface* self) {
158 u32* cmd_buffer = Kernel::GetCommandBuffer();
159 u32 data;
160
161 // TODO(Subv): Find out the correct error codes
162 cmd_buffer[1] = Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8,
163 reinterpret_cast<u8*>(&data)).raw;
164
165 u8 model = data & 0xFF;
166 if (model == Service::CFG::NINTENDO_2DS)
167 cmd_buffer[2] = 0;
168 else
169 cmd_buffer[2] = 1;
170}
171
102const Interface::FunctionInfo FunctionTable[] = { 172const Interface::FunctionInfo FunctionTable[] = {
103 {0x00010082, nullptr, "GetConfigInfoBlk2"}, 173 {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
104 {0x00020000, nullptr, "SecureInfoGetRegion"}, 174 {0x00020000, nullptr, "SecureInfoGetRegion"},
105 {0x00030000, nullptr, "GenHashConsoleUnique"}, 175 {0x00030000, nullptr, "GenHashConsoleUnique"},
106 {0x00040000, nullptr, "GetRegionCanadaUSA"}, 176 {0x00040000, nullptr, "GetRegionCanadaUSA"},
107 {0x00050000, nullptr, "GetSystemModel"}, 177 {0x00050000, GetSystemModel, "GetSystemModel"},
108 {0x00060000, nullptr, "GetModelNintendo2DS"}, 178 {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"},
109 {0x00070040, nullptr, "unknown"}, 179 {0x00070040, nullptr, "unknown"},
110 {0x00080080, nullptr, "unknown"}, 180 {0x00080080, nullptr, "unknown"},
111 {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, 181 {0x00090040, GetCountryCodeString, "GetCountryCodeString"},
112 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, 182 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
113}; 183};
184
114//////////////////////////////////////////////////////////////////////////////////////////////////// 185////////////////////////////////////////////////////////////////////////////////////////////////////
115// Interface class 186// Interface class
116 187
@@ -118,7 +189,4 @@ Interface::Interface() {
118 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 189 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
119} 190}
120 191
121Interface::~Interface() {
122}
123
124} // namespace 192} // namespace
diff --git a/src/core/hle/service/cfg_u.h b/src/core/hle/service/cfg/cfg_u.h
index 8075d19a8..9ad73f355 100644
--- a/src/core/hle/service/cfg_u.h
+++ b/src/core/hle/service/cfg/cfg_u.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -14,11 +14,7 @@ namespace CFG_U {
14class Interface : public Service::Interface { 14class Interface : public Service::Interface {
15public: 15public:
16 Interface(); 16 Interface();
17 ~Interface(); 17
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const override { 18 std::string GetPortName() const override {
23 return "cfg:u"; 19 return "cfg:u";
24 } 20 }
diff --git a/src/core/hle/service/cfg_i.cpp b/src/core/hle/service/cfg_i.cpp
deleted file mode 100644
index 88d13d459..000000000
--- a/src/core/hle/service/cfg_i.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/cfg_i.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace CFG_I
11
12namespace CFG_I {
13
14const Interface::FunctionInfo FunctionTable[] = {
15 {0x04010082, nullptr, "GetConfigInfoBlk8"},
16 {0x04020082, nullptr, "GetConfigInfoBlk4"},
17 {0x04030000, nullptr, "UpdateConfigNANDSavegame"},
18 {0x04040042, nullptr, "GetLocalFriendCodeSeedData"},
19 {0x04050000, nullptr, "GetLocalFriendCodeSeed"},
20 {0x04060000, nullptr, "SecureInfoGetRegion"},
21 {0x04070000, nullptr, "SecureInfoGetByte101"},
22 {0x04080042, nullptr, "SecureInfoGetSerialNo"},
23 {0x04090000, nullptr, "UpdateConfigBlk00040003"},
24 {0x08010082, nullptr, "GetConfigInfoBlk8"},
25 {0x08020082, nullptr, "GetConfigInfoBlk4"},
26 {0x08030000, nullptr, "UpdateConfigNANDSavegame"},
27 {0x080400C2, nullptr, "CreateConfigInfoBlk"},
28 {0x08050000, nullptr, "DeleteConfigNANDSavefile"},
29 {0x08060000, nullptr, "FormatConfig"},
30 {0x08070000, nullptr, "Unknown"},
31 {0x08080000, nullptr, "UpdateConfigBlk1"},
32 {0x08090000, nullptr, "UpdateConfigBlk2"},
33 {0x080A0000, nullptr, "UpdateConfigBlk3"},
34 {0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"},
35 {0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"},
36 {0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"},
37 {0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"},
38 {0x080F0042, nullptr, "GetLocalFriendCodeSeedData"},
39 {0x08100000, nullptr, "GetLocalFriendCodeSeed"},
40 {0x08110084, nullptr, "SetSecureInfo"},
41 {0x08120000, nullptr, "DeleteCreateNANDSecureInfo"},
42 {0x08130000, nullptr, "VerifySigSecureInfo"},
43 {0x08140042, nullptr, "SecureInfoGetData"},
44 {0x08150042, nullptr, "SecureInfoGetSignature"},
45 {0x08160000, nullptr, "SecureInfoGetRegion"},
46 {0x08170000, nullptr, "SecureInfoGetByte101"},
47 {0x08180042, nullptr, "SecureInfoGetSerialNo"},
48};
49////////////////////////////////////////////////////////////////////////////////////////////////////
50// Interface class
51
52Interface::Interface() {
53 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
54}
55
56Interface::~Interface() {
57}
58
59} // namespace
diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp
index 6e59a9bf3..aef8cfbca 100644
--- a/src/core/hle/service/csnd_snd.cpp
+++ b/src/core/hle/service/csnd_snd.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -33,7 +33,4 @@ Interface::Interface() {
33 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 33 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
34} 34}
35 35
36Interface::~Interface() {
37}
38
39} // namespace 36} // namespace
diff --git a/src/core/hle/service/csnd_snd.h b/src/core/hle/service/csnd_snd.h
index 31cc85b07..a84752473 100644
--- a/src/core/hle/service/csnd_snd.h
+++ b/src/core/hle/service/csnd_snd.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -14,11 +14,7 @@ namespace CSND_SND {
14class Interface : public Service::Interface { 14class Interface : public Service::Interface {
15public: 15public:
16 Interface(); 16 Interface();
17 ~Interface(); 17
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const override { 18 std::string GetPortName() const override {
23 return "csnd:SND"; 19 return "csnd:SND";
24 } 20 }
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index ce1c9938d..2cf4d118f 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -25,7 +25,7 @@ static Handle interrupt_event;
25 * 2 : (inaddr << 1) + 0x1FF40000 (where 0x1FF00000 is the DSP RAM address) 25 * 2 : (inaddr << 1) + 0x1FF40000 (where 0x1FF00000 is the DSP RAM address)
26 */ 26 */
27void ConvertProcessAddressFromDspDram(Service::Interface* self) { 27void ConvertProcessAddressFromDspDram(Service::Interface* self) {
28 u32* cmd_buff = Service::GetCommandBuffer(); 28 u32* cmd_buff = Kernel::GetCommandBuffer();
29 29
30 u32 addr = cmd_buff[1]; 30 u32 addr = cmd_buff[1];
31 31
@@ -48,7 +48,7 @@ void ConvertProcessAddressFromDspDram(Service::Interface* self) {
48 * 2 : Component loaded, 0 on not loaded, 1 on loaded 48 * 2 : Component loaded, 0 on not loaded, 1 on loaded
49 */ 49 */
50void LoadComponent(Service::Interface* self) { 50void LoadComponent(Service::Interface* self) {
51 u32* cmd_buff = Service::GetCommandBuffer(); 51 u32* cmd_buff = Kernel::GetCommandBuffer();
52 52
53 cmd_buff[1] = 0; // No error 53 cmd_buff[1] = 0; // No error
54 cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware 54 cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware
@@ -65,7 +65,7 @@ void LoadComponent(Service::Interface* self) {
65 * 3 : Semaphore event handle 65 * 3 : Semaphore event handle
66 */ 66 */
67void GetSemaphoreEventHandle(Service::Interface* self) { 67void GetSemaphoreEventHandle(Service::Interface* self) {
68 u32* cmd_buff = Service::GetCommandBuffer(); 68 u32* cmd_buff = Kernel::GetCommandBuffer();
69 69
70 cmd_buff[1] = 0; // No error 70 cmd_buff[1] = 0; // No error
71 cmd_buff[3] = semaphore_event; // Event handle 71 cmd_buff[3] = semaphore_event; // Event handle
@@ -83,7 +83,7 @@ void GetSemaphoreEventHandle(Service::Interface* self) {
83 * 1 : Result of function, 0 on success, otherwise error code 83 * 1 : Result of function, 0 on success, otherwise error code
84 */ 84 */
85void RegisterInterruptEvents(Service::Interface* self) { 85void RegisterInterruptEvents(Service::Interface* self) {
86 u32* cmd_buff = Service::GetCommandBuffer(); 86 u32* cmd_buff = Kernel::GetCommandBuffer();
87 87
88 interrupt_event = static_cast<Handle>(cmd_buff[4]); 88 interrupt_event = static_cast<Handle>(cmd_buff[4]);
89 89
@@ -100,7 +100,7 @@ void RegisterInterruptEvents(Service::Interface* self) {
100 * 1 : Result of function, 0 on success, otherwise error code 100 * 1 : Result of function, 0 on success, otherwise error code
101 */ 101 */
102void WriteReg0x10(Service::Interface* self) { 102void WriteReg0x10(Service::Interface* self) {
103 u32* cmd_buff = Service::GetCommandBuffer(); 103 u32* cmd_buff = Kernel::GetCommandBuffer();
104 104
105 Kernel::SignalEvent(interrupt_event); 105 Kernel::SignalEvent(interrupt_event);
106 106
@@ -121,7 +121,7 @@ void WriteReg0x10(Service::Interface* self) {
121 * 2 : Number of bytes read from pipe 121 * 2 : Number of bytes read from pipe
122 */ 122 */
123void ReadPipeIfPossible(Service::Interface* self) { 123void ReadPipeIfPossible(Service::Interface* self) {
124 u32* cmd_buff = Service::GetCommandBuffer(); 124 u32* cmd_buff = Kernel::GetCommandBuffer();
125 125
126 u32 size = cmd_buff[3] & 0xFFFF;// Lower 16 bits are size 126 u32 size = cmd_buff[3] & 0xFFFF;// Lower 16 bits are size
127 VAddr addr = cmd_buff[0x41]; 127 VAddr addr = cmd_buff[0x41];
@@ -190,7 +190,4 @@ Interface::Interface() {
190 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 190 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
191} 191}
192 192
193Interface::~Interface() {
194}
195
196} // namespace 193} // namespace
diff --git a/src/core/hle/service/dsp_dsp.h b/src/core/hle/service/dsp_dsp.h
index 9431b62f6..0b8b64600 100644
--- a/src/core/hle/service/dsp_dsp.h
+++ b/src/core/hle/service/dsp_dsp.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -14,11 +14,7 @@ namespace DSP_DSP {
14class Interface : public Service::Interface { 14class Interface : public Service::Interface {
15public: 15public:
16 Interface(); 16 Interface();
17 ~Interface(); 17
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const override { 18 std::string GetPortName() const override {
23 return "dsp::DSP"; 19 return "dsp::DSP";
24 } 20 }
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index 785c351e9..8c900eabc 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -11,17 +11,15 @@
11 11
12namespace ERR_F { 12namespace ERR_F {
13 13
14 const Interface::FunctionInfo FunctionTable[] = { 14const Interface::FunctionInfo FunctionTable[] = {
15 {0x00010800, nullptr, "ThrowFatalError"} 15 {0x00010800, nullptr, "ThrowFatalError"}
16 }; 16};
17 ////////////////////////////////////////////////////////////////////////////////////////////////////
18 // Interface class
19 17
20 Interface::Interface() { 18////////////////////////////////////////////////////////////////////////////////////////////////////
21 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 19// Interface class
22 }
23 20
24 Interface::~Interface() { 21Interface::Interface() {
25 } 22 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
23}
26 24
27} // namespace 25} // namespace
diff --git a/src/core/hle/service/err_f.h b/src/core/hle/service/err_f.h
index 6d7141c1b..892d8af9b 100644
--- a/src/core/hle/service/err_f.h
+++ b/src/core/hle/service/err_f.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -11,17 +11,13 @@
11 11
12namespace ERR_F { 12namespace ERR_F {
13 13
14 class Interface : public Service::Interface { 14class Interface : public Service::Interface {
15 public: 15public:
16 Interface(); 16 Interface();
17 ~Interface(); 17
18 /** 18 std::string GetPortName() const override {
19 * Gets the string port name used by CTROS for the service 19 return "err:f";
20 * @return Port name of service 20 }
21 */ 21};
22 std::string GetPortName() const override {
23 return "err:f";
24 }
25 };
26 22
27} // namespace 23} // namespace
diff --git a/src/core/hle/service/frd_u.cpp b/src/core/hle/service/frd_u.cpp
index 58023e536..021186e57 100644
--- a/src/core/hle/service/frd_u.cpp
+++ b/src/core/hle/service/frd_u.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -11,25 +11,23 @@
11 11
12namespace FRD_U { 12namespace FRD_U {
13 13
14 const Interface::FunctionInfo FunctionTable[] = { 14const Interface::FunctionInfo FunctionTable[] = {
15 {0x00050000, nullptr, "GetFriendKey"}, 15 {0x00050000, nullptr, "GetFriendKey"},
16 {0x00080000, nullptr, "GetMyPresence"}, 16 {0x00080000, nullptr, "GetMyPresence"},
17 {0x00100040, nullptr, "GetPassword"}, 17 {0x00100040, nullptr, "GetPassword"},
18 {0x00190042, nullptr, "GetFriendFavoriteGame"}, 18 {0x00190042, nullptr, "GetFriendFavoriteGame"},
19 {0x001A00C4, nullptr, "GetFriendInfo"}, 19 {0x001A00C4, nullptr, "GetFriendInfo"},
20 {0x001B0080, nullptr, "IsOnFriendList"}, 20 {0x001B0080, nullptr, "IsOnFriendList"},
21 {0x001C0042, nullptr, "DecodeLocalFriendCode"}, 21 {0x001C0042, nullptr, "DecodeLocalFriendCode"},
22 {0x001D0002, nullptr, "SetCurrentlyPlayingText"}, 22 {0x001D0002, nullptr, "SetCurrentlyPlayingText"},
23 {0x00320042, nullptr, "SetClientSdkVersion"} 23 {0x00320042, nullptr, "SetClientSdkVersion"}
24 }; 24};
25 ////////////////////////////////////////////////////////////////////////////////////////////////////
26 // Interface class
27 25
28 Interface::Interface() { 26////////////////////////////////////////////////////////////////////////////////////////////////////
29 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 27// Interface class
30 }
31 28
32 Interface::~Interface() { 29Interface::Interface() {
33 } 30 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
31}
34 32
35} // namespace 33} // namespace
diff --git a/src/core/hle/service/frd_u.h b/src/core/hle/service/frd_u.h
index 4020c6664..ab8897d5b 100644
--- a/src/core/hle/service/frd_u.h
+++ b/src/core/hle/service/frd_u.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -11,17 +11,13 @@
11 11
12namespace FRD_U { 12namespace FRD_U {
13 13
14 class Interface : public Service::Interface { 14class Interface : public Service::Interface {
15 public: 15public:
16 Interface(); 16 Interface();
17 ~Interface(); 17
18 /** 18 std::string GetPortName() const override {
19 * Gets the string port name used by CTROS for the service 19 return "frd:u";
20 * @return Port name of service 20 }
21 */ 21};
22 std::string GetPortName() const override {
23 return "frd:u";
24 }
25 };
26 22
27} // namespace 23} // namespace
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
new file mode 100644
index 000000000..487bf3aa7
--- /dev/null
+++ b/src/core/hle/service/fs/archive.cpp
@@ -0,0 +1,442 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <memory>
6#include <unordered_map>
7
8#include "common/common_types.h"
9#include "common/file_util.h"
10#include "common/make_unique.h"
11#include "common/math_util.h"
12
13#include "core/file_sys/archive_savedata.h"
14#include "core/file_sys/archive_backend.h"
15#include "core/file_sys/archive_sdmc.h"
16#include "core/file_sys/directory_backend.h"
17#include "core/hle/service/fs/archive.h"
18#include "core/hle/kernel/session.h"
19#include "core/hle/result.h"
20
21// Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map.
22// Workaroung for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970
23namespace std {
24 template <>
25 struct hash<Service::FS::ArchiveIdCode> {
26 typedef Service::FS::ArchiveIdCode argument_type;
27 typedef std::size_t result_type;
28
29 result_type operator()(const argument_type& id_code) const {
30 typedef std::underlying_type<argument_type>::type Type;
31 return std::hash<Type>()(static_cast<Type>(id_code));
32 }
33 };
34}
35
36namespace Service {
37namespace FS {
38
39// Command to access archive file
40enum class FileCommand : u32 {
41 Dummy1 = 0x000100C6,
42 Control = 0x040100C4,
43 OpenSubFile = 0x08010100,
44 Read = 0x080200C2,
45 Write = 0x08030102,
46 GetSize = 0x08040000,
47 SetSize = 0x08050080,
48 GetAttributes = 0x08060000,
49 SetAttributes = 0x08070040,
50 Close = 0x08080000,
51 Flush = 0x08090000,
52};
53
54// Command to access directory
55enum class DirectoryCommand : u32 {
56 Dummy1 = 0x000100C6,
57 Control = 0x040100C4,
58 Read = 0x08010042,
59 Close = 0x08020000,
60};
61
62class Archive {
63public:
64 Archive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code)
65 : backend(std::move(backend)), id_code(id_code) {
66 }
67
68 std::string GetName() const { return "Archive: " + backend->GetName(); }
69
70 ArchiveIdCode id_code; ///< Id code of the archive
71 std::unique_ptr<FileSys::ArchiveBackend> backend; ///< Archive backend interface
72};
73
74class File : public Kernel::Session {
75public:
76 File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path)
77 : backend(std::move(backend)), path(path) {
78 }
79
80 std::string GetName() const override { return "Path: " + path.DebugStr(); }
81
82 FileSys::Path path; ///< Path of the file
83 std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface
84
85 ResultVal<bool> SyncRequest() override {
86 u32* cmd_buff = Kernel::GetCommandBuffer();
87 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
88 switch (cmd) {
89
90 // Read from file...
91 case FileCommand::Read:
92 {
93 u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32;
94 u32 length = cmd_buff[3];
95 u32 address = cmd_buff[5];
96 LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x",
97 GetTypeName().c_str(), GetName().c_str(), offset, length, address);
98 cmd_buff[2] = backend->Read(offset, length, Memory::GetPointer(address));
99 break;
100 }
101
102 // Write to file...
103 case FileCommand::Write:
104 {
105 u64 offset = cmd_buff[1] | ((u64) cmd_buff[2]) << 32;
106 u32 length = cmd_buff[3];
107 u32 flush = cmd_buff[4];
108 u32 address = cmd_buff[6];
109 LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x",
110 GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush);
111 cmd_buff[2] = backend->Write(offset, length, flush, Memory::GetPointer(address));
112 break;
113 }
114
115 case FileCommand::GetSize:
116 {
117 LOG_TRACE(Service_FS, "GetSize %s %s", GetTypeName().c_str(), GetName().c_str());
118 u64 size = backend->GetSize();
119 cmd_buff[2] = (u32)size;
120 cmd_buff[3] = size >> 32;
121 break;
122 }
123
124 case FileCommand::SetSize:
125 {
126 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32);
127 LOG_TRACE(Service_FS, "SetSize %s %s size=%llu",
128 GetTypeName().c_str(), GetName().c_str(), size);
129 backend->SetSize(size);
130 break;
131 }
132
133 case FileCommand::Close:
134 {
135 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
136 backend->Close();
137 break;
138 }
139
140 case FileCommand::Flush:
141 {
142 LOG_TRACE(Service_FS, "Flush");
143 backend->Flush();
144 break;
145 }
146
147 // Unknown command...
148 default:
149 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd);
150 ResultCode error = UnimplementedFunction(ErrorModule::FS);
151 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
152 return error;
153 }
154 cmd_buff[1] = 0; // No error
155 return MakeResult<bool>(false);
156 }
157};
158
159class Directory : public Kernel::Session {
160public:
161 Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path)
162 : backend(std::move(backend)), path(path) {
163 }
164
165 std::string GetName() const override { return "Directory: " + path.DebugStr(); }
166
167 FileSys::Path path; ///< Path of the directory
168 std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface
169
170 ResultVal<bool> SyncRequest() override {
171 u32* cmd_buff = Kernel::GetCommandBuffer();
172 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]);
173 switch (cmd) {
174
175 // Read from directory...
176 case DirectoryCommand::Read:
177 {
178 u32 count = cmd_buff[1];
179 u32 address = cmd_buff[3];
180 auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address));
181 LOG_TRACE(Service_FS, "Read %s %s: count=%d",
182 GetTypeName().c_str(), GetName().c_str(), count);
183
184 // Number of entries actually read
185 cmd_buff[2] = backend->Read(count, entries);
186 break;
187 }
188
189 case DirectoryCommand::Close:
190 {
191 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
192 backend->Close();
193 break;
194 }
195
196 // Unknown command...
197 default:
198 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd);
199 ResultCode error = UnimplementedFunction(ErrorModule::FS);
200 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
201 return MakeResult<bool>(false);
202 }
203 cmd_buff[1] = 0; // No error
204 return MakeResult<bool>(false);
205 }
206};
207
208////////////////////////////////////////////////////////////////////////////////////////////////////
209
210/**
211 * Map of registered archives, identified by id code. Once an archive is registered here, it is
212 * never removed until the FS service is shut down.
213 */
214static std::unordered_map<ArchiveIdCode, std::unique_ptr<Archive>> id_code_map;
215
216/**
217 * Map of active archive handles. Values are pointers to the archives in `idcode_map`.
218 */
219static std::unordered_map<ArchiveHandle, Archive*> handle_map;
220static ArchiveHandle next_handle;
221
222static Archive* GetArchive(ArchiveHandle handle) {
223 auto itr = handle_map.find(handle);
224 return (itr == handle_map.end()) ? nullptr : itr->second;
225}
226
227ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code) {
228 LOG_TRACE(Service_FS, "Opening archive with id code 0x%08X", id_code);
229
230 auto itr = id_code_map.find(id_code);
231 if (itr == id_code_map.end()) {
232 if (id_code == ArchiveIdCode::SaveData) {
233 // When a SaveData archive is created for the first time, it is not yet formatted
234 // and the save file/directory structure expected by the game has not yet been initialized.
235 // Returning the NotFormatted error code will signal the game to provision the SaveData archive
236 // with the files and folders that it expects.
237 // The FormatSaveData service call will create the SaveData archive when it is called.
238 return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
239 ErrorSummary::InvalidState, ErrorLevel::Status);
240 }
241 // TODO: Verify error against hardware
242 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
243 ErrorSummary::NotFound, ErrorLevel::Permanent);
244 }
245
246 // This should never even happen in the first place with 64-bit handles,
247 while (handle_map.count(next_handle) != 0) {
248 ++next_handle;
249 }
250 handle_map.emplace(next_handle, itr->second.get());
251 return MakeResult<ArchiveHandle>(next_handle++);
252}
253
254ResultCode CloseArchive(ArchiveHandle handle) {
255 if (handle_map.erase(handle) == 0)
256 return InvalidHandle(ErrorModule::FS);
257 else
258 return RESULT_SUCCESS;
259}
260
261// TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in
262// http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22
263ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code) {
264 auto result = id_code_map.emplace(id_code, Common::make_unique<Archive>(std::move(backend), id_code));
265
266 bool inserted = result.second;
267 _dbg_assert_msg_(Service_FS, inserted, "Tried to register more than one archive with same id code");
268
269 auto& archive = result.first->second;
270 LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code);
271 return RESULT_SUCCESS;
272}
273
274ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) {
275 Archive* archive = GetArchive(archive_handle);
276 if (archive == nullptr)
277 return InvalidHandle(ErrorModule::FS);
278
279 std::unique_ptr<FileSys::FileBackend> backend = archive->backend->OpenFile(path, mode);
280 if (backend == nullptr) {
281 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS,
282 ErrorSummary::NotFound, ErrorLevel::Status);
283 }
284
285 auto file = Common::make_unique<File>(std::move(backend), path);
286 // TOOD(yuriks): Fix error reporting
287 Handle handle = Kernel::g_handle_table.Create(file.release()).ValueOr(INVALID_HANDLE);
288 return MakeResult<Handle>(handle);
289}
290
291ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
292 Archive* archive = GetArchive(archive_handle);
293 if (archive == nullptr)
294 return InvalidHandle(ErrorModule::FS);
295
296 if (archive->backend->DeleteFile(path))
297 return RESULT_SUCCESS;
298 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
299 ErrorSummary::Canceled, ErrorLevel::Status);
300}
301
302ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path,
303 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) {
304 Archive* src_archive = GetArchive(src_archive_handle);
305 Archive* dest_archive = GetArchive(dest_archive_handle);
306 if (src_archive == nullptr || dest_archive == nullptr)
307 return InvalidHandle(ErrorModule::FS);
308
309 if (src_archive == dest_archive) {
310 if (src_archive->backend->RenameFile(src_path, dest_path))
311 return RESULT_SUCCESS;
312 } else {
313 // TODO: Implement renaming across archives
314 return UnimplementedFunction(ErrorModule::FS);
315 }
316
317 // TODO(yuriks): This code probably isn't right, it'll return a Status even if the file didn't
318 // exist or similar. Verify.
319 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
320 ErrorSummary::NothingHappened, ErrorLevel::Status);
321}
322
323ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
324 Archive* archive = GetArchive(archive_handle);
325 if (archive == nullptr)
326 return InvalidHandle(ErrorModule::FS);
327
328 if (archive->backend->DeleteDirectory(path))
329 return RESULT_SUCCESS;
330 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
331 ErrorSummary::Canceled, ErrorLevel::Status);
332}
333
334ResultCode CreateFileInArchive(Handle archive_handle, const FileSys::Path& path, u32 file_size) {
335 Archive* archive = GetArchive(archive_handle);
336 if (archive == nullptr)
337 return InvalidHandle(ErrorModule::FS);
338
339 return archive->backend->CreateFile(path, file_size);
340}
341
342ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
343 Archive* archive = GetArchive(archive_handle);
344 if (archive == nullptr)
345 return InvalidHandle(ErrorModule::FS);
346
347 if (archive->backend->CreateDirectory(path))
348 return RESULT_SUCCESS;
349 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
350 ErrorSummary::Canceled, ErrorLevel::Status);
351}
352
353ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path,
354 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) {
355 Archive* src_archive = GetArchive(src_archive_handle);
356 Archive* dest_archive = GetArchive(dest_archive_handle);
357 if (src_archive == nullptr || dest_archive == nullptr)
358 return InvalidHandle(ErrorModule::FS);
359
360 if (src_archive == dest_archive) {
361 if (src_archive->backend->RenameDirectory(src_path, dest_path))
362 return RESULT_SUCCESS;
363 } else {
364 // TODO: Implement renaming across archives
365 return UnimplementedFunction(ErrorModule::FS);
366 }
367
368 // TODO(yuriks): This code probably isn't right, it'll return a Status even if the file didn't
369 // exist or similar. Verify.
370 return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
371 ErrorSummary::NothingHappened, ErrorLevel::Status);
372}
373
374/**
375 * Open a Directory from an Archive
376 * @param archive_handle Handle to an open Archive object
377 * @param path Path to the Directory inside of the Archive
378 * @return Opened Directory object
379 */
380ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
381 Archive* archive = GetArchive(archive_handle);
382 if (archive == nullptr)
383 return InvalidHandle(ErrorModule::FS);
384
385 std::unique_ptr<FileSys::DirectoryBackend> backend = archive->backend->OpenDirectory(path);
386 if (backend == nullptr) {
387 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS,
388 ErrorSummary::NotFound, ErrorLevel::Permanent);
389 }
390
391 auto directory = Common::make_unique<Directory>(std::move(backend), path);
392 // TOOD(yuriks): Fix error reporting
393 Handle handle = Kernel::g_handle_table.Create(directory.release()).ValueOr(INVALID_HANDLE);
394 return MakeResult<Handle>(handle);
395}
396
397ResultCode FormatSaveData() {
398 // TODO(Subv): Actually wipe the savedata folder after creating or opening it
399
400 // Do not create the archive again if it already exists
401 if (id_code_map.find(ArchiveIdCode::SaveData) != id_code_map.end())
402 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the correct error code
403
404 // Create the SaveData archive
405 std::string savedata_directory = FileUtil::GetUserPath(D_SAVEDATA_IDX);
406 auto savedata_archive = Common::make_unique<FileSys::Archive_SaveData>(savedata_directory,
407 Kernel::g_program_id);
408
409 if (savedata_archive->Initialize()) {
410 CreateArchive(std::move(savedata_archive), ArchiveIdCode::SaveData);
411 return RESULT_SUCCESS;
412 } else {
413 LOG_ERROR(Service_FS, "Can't instantiate SaveData archive with path %s",
414 savedata_archive->GetMountPoint().c_str());
415 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the proper error code
416 }
417}
418
419/// Initialize archives
420void ArchiveInit() {
421 next_handle = 1;
422
423 // TODO(Link Mauve): Add the other archive types (see here for the known types:
424 // http://3dbrew.org/wiki/FS:OpenArchive#Archive_idcodes). Currently the only half-finished
425 // archive type is SDMC, so it is the only one getting exposed.
426
427 std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX);
428 auto sdmc_archive = Common::make_unique<FileSys::Archive_SDMC>(sdmc_directory);
429 if (sdmc_archive->Initialize())
430 CreateArchive(std::move(sdmc_archive), ArchiveIdCode::SDMC);
431 else
432 LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str());
433}
434
435/// Shutdown archives
436void ArchiveShutdown() {
437 handle_map.clear();
438 id_code_map.clear();
439}
440
441} // namespace FS
442} // namespace Service
diff --git a/src/core/hle/kernel/archive.h b/src/core/hle/service/fs/archive.h
index b50833a2b..b39bc41b6 100644
--- a/src/core/hle/kernel/archive.h
+++ b/src/core/hle/service/fs/archive.h
@@ -1,39 +1,50 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9#include "core/file_sys/archive.h" 9#include "core/file_sys/archive_backend.h"
10#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
11#include "core/hle/result.h" 11#include "core/hle/result.h"
12 12
13//////////////////////////////////////////////////////////////////////////////////////////////////// 13namespace Service {
14// Kernel namespace 14namespace FS {
15 15
16namespace Kernel { 16/// Supported archive types
17enum class ArchiveIdCode : u32 {
18 RomFS = 0x00000003,
19 SaveData = 0x00000004,
20 ExtSaveData = 0x00000006,
21 SharedExtSaveData = 0x00000007,
22 SystemSaveData = 0x00000008,
23 SDMC = 0x00000009,
24 SDMCWriteOnly = 0x0000000A,
25};
26
27typedef u64 ArchiveHandle;
17 28
18/** 29/**
19 * Opens an archive 30 * Opens an archive
20 * @param id_code IdCode of the archive to open 31 * @param id_code IdCode of the archive to open
21 * @return Handle to the opened archive 32 * @return Handle to the opened archive
22 */ 33 */
23ResultVal<Handle> OpenArchive(FileSys::Archive::IdCode id_code); 34ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code);
24 35
25/** 36/**
26 * Closes an archive 37 * Closes an archive
27 * @param id_code IdCode of the archive to open 38 * @param id_code IdCode of the archive to open
28 */ 39 */
29ResultCode CloseArchive(FileSys::Archive::IdCode id_code); 40ResultCode CloseArchive(ArchiveHandle handle);
30 41
31/** 42/**
32 * Creates an Archive 43 * Creates an Archive
33 * @param backend File system backend interface to the archive 44 * @param backend File system backend interface to the archive
34 * @param name Name of Archive 45 * @param id_code Id code used to access this type of archive
35 */ 46 */
36ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name); 47ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, ArchiveIdCode id_code);
37 48
38/** 49/**
39 * Open a File from an Archive 50 * Open a File from an Archive
@@ -42,7 +53,7 @@ ResultCode CreateArchive(FileSys::Archive* backend, const std::string& name);
42 * @param mode Mode under which to open the File 53 * @param mode Mode under which to open the File
43 * @return Handle to the opened File object 54 * @return Handle to the opened File object
44 */ 55 */
45ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path& path, const FileSys::Mode mode); 56ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode);
46 57
47/** 58/**
48 * Delete a File from an Archive 59 * Delete a File from an Archive
@@ -50,7 +61,7 @@ ResultVal<Handle> OpenFileFromArchive(Handle archive_handle, const FileSys::Path
50 * @param path Path to the File inside of the Archive 61 * @param path Path to the File inside of the Archive
51 * @return Whether deletion succeeded 62 * @return Whether deletion succeeded
52 */ 63 */
53ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& path); 64ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path);
54 65
55/** 66/**
56 * Rename a File between two Archives 67 * Rename a File between two Archives
@@ -60,8 +71,8 @@ ResultCode DeleteFileFromArchive(Handle archive_handle, const FileSys::Path& pat
60 * @param dest_path Path to the File inside of the destination Archive 71 * @param dest_path Path to the File inside of the destination Archive
61 * @return Whether rename succeeded 72 * @return Whether rename succeeded
62 */ 73 */
63ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, 74ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path,
64 Handle dest_archive_handle, const FileSys::Path& dest_path); 75 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path);
65 76
66/** 77/**
67 * Delete a Directory from an Archive 78 * Delete a Directory from an Archive
@@ -69,7 +80,16 @@ ResultCode RenameFileBetweenArchives(Handle src_archive_handle, const FileSys::P
69 * @param path Path to the Directory inside of the Archive 80 * @param path Path to the Directory inside of the Archive
70 * @return Whether deletion succeeded 81 * @return Whether deletion succeeded
71 */ 82 */
72ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); 83ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path);
84
85/**
86 * Create a File in an Archive
87 * @param archive_handle Handle to an open Archive object
88 * @param path Path to the File inside of the Archive
89 * @param file_size The size of the new file, filled with zeroes
90 * @return File creation result code
91 */
92ResultCode CreateFileInArchive(Handle archive_handle, const FileSys::Path& path, u32 file_size);
73 93
74/** 94/**
75 * Create a Directory from an Archive 95 * Create a Directory from an Archive
@@ -77,7 +97,7 @@ ResultCode DeleteDirectoryFromArchive(Handle archive_handle, const FileSys::Path
77 * @param path Path to the Directory inside of the Archive 97 * @param path Path to the Directory inside of the Archive
78 * @return Whether creation of directory succeeded 98 * @return Whether creation of directory succeeded
79 */ 99 */
80ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); 100ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path);
81 101
82/** 102/**
83 * Rename a Directory between two Archives 103 * Rename a Directory between two Archives
@@ -87,8 +107,8 @@ ResultCode CreateDirectoryFromArchive(Handle archive_handle, const FileSys::Path
87 * @param dest_path Path to the Directory inside of the destination Archive 107 * @param dest_path Path to the Directory inside of the destination Archive
88 * @return Whether rename succeeded 108 * @return Whether rename succeeded
89 */ 109 */
90ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileSys::Path& src_path, 110ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path,
91 Handle dest_archive_handle, const FileSys::Path& dest_path); 111 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path);
92 112
93/** 113/**
94 * Open a Directory from an Archive 114 * Open a Directory from an Archive
@@ -96,7 +116,13 @@ ResultCode RenameDirectoryBetweenArchives(Handle src_archive_handle, const FileS
96 * @param path Path to the Directory inside of the Archive 116 * @param path Path to the Directory inside of the Archive
97 * @return Handle to the opened File object 117 * @return Handle to the opened File object
98 */ 118 */
99ResultVal<Handle> OpenDirectoryFromArchive(Handle archive_handle, const FileSys::Path& path); 119ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path);
120
121/**
122 * Creates a blank SaveData archive.
123 * @return ResultCode 0 on success or the corresponding code on error
124 */
125ResultCode FormatSaveData();
100 126
101/// Initialize archives 127/// Initialize archives
102void ArchiveInit(); 128void ArchiveInit();
@@ -104,4 +130,5 @@ void ArchiveInit();
104/// Shutdown archives 130/// Shutdown archives
105void ArchiveShutdown(); 131void ArchiveShutdown();
106 132
107} // namespace FileSys 133} // namespace FS
134} // namespace Service
diff --git a/src/core/hle/service/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index 9bda4fe8a..b1a465274 100644
--- a/src/core/hle/service/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -1,23 +1,28 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common.h" 5#include "common/common.h"
6 6#include "common/file_util.h"
7#include "common/scope_exit.h"
7#include "common/string_util.h" 8#include "common/string_util.h"
8#include "core/hle/kernel/archive.h"
9#include "core/hle/kernel/archive.h"
10#include "core/hle/result.h" 9#include "core/hle/result.h"
11#include "core/hle/service/fs_user.h" 10#include "core/hle/service/fs/archive.h"
11#include "core/hle/service/fs/fs_user.h"
12#include "core/settings.h" 12#include "core/settings.h"
13 13
14//////////////////////////////////////////////////////////////////////////////////////////////////// 14////////////////////////////////////////////////////////////////////////////////////////////////////
15// Namespace FS_User 15// Namespace FS_User
16 16
17namespace FS_User { 17namespace Service {
18namespace FS {
19
20static ArchiveHandle MakeArchiveHandle(u32 low_word, u32 high_word) {
21 return (u64)low_word | ((u64)high_word << 32);
22}
18 23
19static void Initialize(Service::Interface* self) { 24static void Initialize(Service::Interface* self) {
20 u32* cmd_buff = Service::GetCommandBuffer(); 25 u32* cmd_buff = Kernel::GetCommandBuffer();
21 26
22 // TODO(Link Mauve): check the behavior when cmd_buff[1] isn't 32, as per 27 // TODO(Link Mauve): check the behavior when cmd_buff[1] isn't 32, as per
23 // http://3dbrew.org/wiki/FS:Initialize#Request 28 // http://3dbrew.org/wiki/FS:Initialize#Request
@@ -43,11 +48,9 @@ static void Initialize(Service::Interface* self) {
43 * 3 : File handle 48 * 3 : File handle
44 */ 49 */
45static void OpenFile(Service::Interface* self) { 50static void OpenFile(Service::Interface* self) {
46 u32* cmd_buff = Service::GetCommandBuffer(); 51 u32* cmd_buff = Kernel::GetCommandBuffer();
47 52
48 // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to 53 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
49 // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
50 Handle archive_handle = static_cast<Handle>(cmd_buff[3]);
51 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 54 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
52 u32 filename_size = cmd_buff[5]; 55 u32 filename_size = cmd_buff[5];
53 FileSys::Mode mode; mode.hex = cmd_buff[6]; 56 FileSys::Mode mode; mode.hex = cmd_buff[6];
@@ -57,11 +60,12 @@ static void OpenFile(Service::Interface* self) {
57 60
58 LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); 61 LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes);
59 62
60 ResultVal<Handle> handle = Kernel::OpenFileFromArchive(archive_handle, file_path, mode); 63 ResultVal<Handle> handle = OpenFileFromArchive(archive_handle, file_path, mode);
61 cmd_buff[1] = handle.Code().raw; 64 cmd_buff[1] = handle.Code().raw;
62 if (handle.Succeeded()) { 65 if (handle.Succeeded()) {
63 cmd_buff[3] = *handle; 66 cmd_buff[3] = *handle;
64 } else { 67 } else {
68 cmd_buff[3] = 0;
65 LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); 69 LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str());
66 } 70 }
67} 71}
@@ -86,9 +90,9 @@ static void OpenFile(Service::Interface* self) {
86 * 3 : File handle 90 * 3 : File handle
87 */ 91 */
88static void OpenFileDirectly(Service::Interface* self) { 92static void OpenFileDirectly(Service::Interface* self) {
89 u32* cmd_buff = Service::GetCommandBuffer(); 93 u32* cmd_buff = Kernel::GetCommandBuffer();
90 94
91 auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[2]); 95 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[2]);
92 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); 96 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]);
93 u32 archivename_size = cmd_buff[4]; 97 u32 archivename_size = cmd_buff[4];
94 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]); 98 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]);
@@ -106,25 +110,25 @@ static void OpenFileDirectly(Service::Interface* self) {
106 if (archive_path.GetType() != FileSys::Empty) { 110 if (archive_path.GetType() != FileSys::Empty) {
107 LOG_ERROR(Service_FS, "archive LowPath type other than empty is currently unsupported"); 111 LOG_ERROR(Service_FS, "archive LowPath type other than empty is currently unsupported");
108 cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw; 112 cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw;
113 cmd_buff[3] = 0;
109 return; 114 return;
110 } 115 }
111 116
112 // TODO(Link Mauve): Check if we should even get a handle for the archive, and don't leak it 117 ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id);
113 // TODO(yuriks): Why is there all this duplicate (and seemingly useless) code up here?
114 ResultVal<Handle> archive_handle = Kernel::OpenArchive(archive_id);
115 cmd_buff[1] = archive_handle.Code().raw;
116 if (archive_handle.Failed()) { 118 if (archive_handle.Failed()) {
117 LOG_ERROR(Service_FS, "failed to get a handle for archive"); 119 LOG_ERROR(Service_FS, "failed to get a handle for archive");
120 cmd_buff[1] = archive_handle.Code().raw;
121 cmd_buff[3] = 0;
118 return; 122 return;
119 } 123 }
120 // cmd_buff[2] isn't used according to 3dmoo's implementation. 124 SCOPE_EXIT({ CloseArchive(*archive_handle); });
121 cmd_buff[3] = *archive_handle;
122 125
123 ResultVal<Handle> handle = Kernel::OpenFileFromArchive(*archive_handle, file_path, mode); 126 ResultVal<Handle> handle = OpenFileFromArchive(*archive_handle, file_path, mode);
124 cmd_buff[1] = handle.Code().raw; 127 cmd_buff[1] = handle.Code().raw;
125 if (handle.Succeeded()) { 128 if (handle.Succeeded()) {
126 cmd_buff[3] = *handle; 129 cmd_buff[3] = *handle;
127 } else { 130 } else {
131 cmd_buff[3] = 0;
128 LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str()); 132 LOG_ERROR(Service_FS, "failed to get a handle for file %s", file_path.DebugStr().c_str());
129 } 133 }
130} 134}
@@ -140,12 +144,10 @@ static void OpenFileDirectly(Service::Interface* self) {
140 * Outputs: 144 * Outputs:
141 * 1 : Result of function, 0 on success, otherwise error code 145 * 1 : Result of function, 0 on success, otherwise error code
142 */ 146 */
143void DeleteFile(Service::Interface* self) { 147static void DeleteFile(Service::Interface* self) {
144 u32* cmd_buff = Service::GetCommandBuffer(); 148 u32* cmd_buff = Kernel::GetCommandBuffer();
145 149
146 // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to 150 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
147 // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
148 Handle archive_handle = static_cast<Handle>(cmd_buff[3]);
149 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 151 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
150 u32 filename_size = cmd_buff[5]; 152 u32 filename_size = cmd_buff[5];
151 u32 filename_ptr = cmd_buff[7]; 153 u32 filename_ptr = cmd_buff[7];
@@ -155,7 +157,7 @@ void DeleteFile(Service::Interface* self) {
155 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", 157 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s",
156 filename_type, filename_size, file_path.DebugStr().c_str()); 158 filename_type, filename_size, file_path.DebugStr().c_str());
157 159
158 cmd_buff[1] = Kernel::DeleteFileFromArchive(archive_handle, file_path).raw; 160 cmd_buff[1] = DeleteFileFromArchive(archive_handle, file_path).raw;
159} 161}
160 162
161/* 163/*
@@ -174,15 +176,13 @@ void DeleteFile(Service::Interface* self) {
174 * Outputs: 176 * Outputs:
175 * 1 : Result of function, 0 on success, otherwise error code 177 * 1 : Result of function, 0 on success, otherwise error code
176 */ 178 */
177void RenameFile(Service::Interface* self) { 179static void RenameFile(Service::Interface* self) {
178 u32* cmd_buff = Service::GetCommandBuffer(); 180 u32* cmd_buff = Kernel::GetCommandBuffer();
179 181
180 // TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to 182 ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
181 // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
182 Handle src_archive_handle = static_cast<Handle>(cmd_buff[3]);
183 auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 183 auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
184 u32 src_filename_size = cmd_buff[5]; 184 u32 src_filename_size = cmd_buff[5];
185 Handle dest_archive_handle = static_cast<Handle>(cmd_buff[7]); 185 ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);;
186 auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); 186 auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
187 u32 dest_filename_size = cmd_buff[9]; 187 u32 dest_filename_size = cmd_buff[9];
188 u32 src_filename_ptr = cmd_buff[11]; 188 u32 src_filename_ptr = cmd_buff[11];
@@ -195,7 +195,7 @@ void RenameFile(Service::Interface* self) {
195 src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(), 195 src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(),
196 dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str()); 196 dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str());
197 197
198 cmd_buff[1] = Kernel::RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw; 198 cmd_buff[1] = RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw;
199} 199}
200 200
201/* 201/*
@@ -209,12 +209,10 @@ void RenameFile(Service::Interface* self) {
209 * Outputs: 209 * Outputs:
210 * 1 : Result of function, 0 on success, otherwise error code 210 * 1 : Result of function, 0 on success, otherwise error code
211 */ 211 */
212void DeleteDirectory(Service::Interface* self) { 212static void DeleteDirectory(Service::Interface* self) {
213 u32* cmd_buff = Service::GetCommandBuffer(); 213 u32* cmd_buff = Kernel::GetCommandBuffer();
214 214
215 // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to 215 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
216 // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
217 Handle archive_handle = static_cast<Handle>(cmd_buff[3]);
218 auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 216 auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
219 u32 dirname_size = cmd_buff[5]; 217 u32 dirname_size = cmd_buff[5];
220 u32 dirname_ptr = cmd_buff[7]; 218 u32 dirname_ptr = cmd_buff[7];
@@ -224,7 +222,36 @@ void DeleteDirectory(Service::Interface* self) {
224 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", 222 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s",
225 dirname_type, dirname_size, dir_path.DebugStr().c_str()); 223 dirname_type, dirname_size, dir_path.DebugStr().c_str());
226 224
227 cmd_buff[1] = Kernel::DeleteDirectoryFromArchive(archive_handle, dir_path).raw; 225 cmd_buff[1] = DeleteDirectoryFromArchive(archive_handle, dir_path).raw;
226}
227
228/*
229 * FS_User::CreateFile service function
230 * Inputs:
231 * 0 : Command header 0x08080202
232 * 2 : Archive handle lower word
233 * 3 : Archive handle upper word
234 * 4 : File path string type
235 * 5 : File path string size
236 * 7 : File size (filled with zeroes)
237 * 10: File path string data
238 * Outputs:
239 * 1 : Result of function, 0 on success, otherwise error code
240 */
241static void CreateFile(Service::Interface* self) {
242 u32* cmd_buff = Kernel::GetCommandBuffer();
243
244 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
245 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
246 u32 filename_size = cmd_buff[5];
247 u32 file_size = cmd_buff[7];
248 u32 filename_ptr = cmd_buff[10];
249
250 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
251
252 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", filename_type, filename_size, file_path.DebugStr().c_str());
253
254 cmd_buff[1] = CreateFileInArchive(archive_handle, file_path, file_size).raw;
228} 255}
229 256
230/* 257/*
@@ -239,11 +266,9 @@ void DeleteDirectory(Service::Interface* self) {
239 * 1 : Result of function, 0 on success, otherwise error code 266 * 1 : Result of function, 0 on success, otherwise error code
240 */ 267 */
241static void CreateDirectory(Service::Interface* self) { 268static void CreateDirectory(Service::Interface* self) {
242 u32* cmd_buff = Service::GetCommandBuffer(); 269 u32* cmd_buff = Kernel::GetCommandBuffer();
243 270
244 // TODO: cmd_buff[2], aka archive handle lower word, isn't used according to 271 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
245 // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
246 Handle archive_handle = static_cast<Handle>(cmd_buff[3]);
247 auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 272 auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
248 u32 dirname_size = cmd_buff[5]; 273 u32 dirname_size = cmd_buff[5];
249 u32 dirname_ptr = cmd_buff[8]; 274 u32 dirname_ptr = cmd_buff[8];
@@ -252,7 +277,7 @@ static void CreateDirectory(Service::Interface* self) {
252 277
253 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); 278 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str());
254 279
255 cmd_buff[1] = Kernel::CreateDirectoryFromArchive(archive_handle, dir_path).raw; 280 cmd_buff[1] = CreateDirectoryFromArchive(archive_handle, dir_path).raw;
256} 281}
257 282
258/* 283/*
@@ -271,15 +296,13 @@ static void CreateDirectory(Service::Interface* self) {
271 * Outputs: 296 * Outputs:
272 * 1 : Result of function, 0 on success, otherwise error code 297 * 1 : Result of function, 0 on success, otherwise error code
273 */ 298 */
274void RenameDirectory(Service::Interface* self) { 299static void RenameDirectory(Service::Interface* self) {
275 u32* cmd_buff = Service::GetCommandBuffer(); 300 u32* cmd_buff = Kernel::GetCommandBuffer();
276 301
277 // TODO(Link Mauve): cmd_buff[2] and cmd_buff[6], aka archive handle lower word, aren't used according to 302 ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
278 // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
279 Handle src_archive_handle = static_cast<Handle>(cmd_buff[3]);
280 auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 303 auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
281 u32 src_dirname_size = cmd_buff[5]; 304 u32 src_dirname_size = cmd_buff[5];
282 Handle dest_archive_handle = static_cast<Handle>(cmd_buff[7]); 305 ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);
283 auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); 306 auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
284 u32 dest_dirname_size = cmd_buff[9]; 307 u32 dest_dirname_size = cmd_buff[9];
285 u32 src_dirname_ptr = cmd_buff[11]; 308 u32 src_dirname_ptr = cmd_buff[11];
@@ -292,15 +315,26 @@ void RenameDirectory(Service::Interface* self) {
292 src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(), 315 src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(),
293 dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str()); 316 dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str());
294 317
295 cmd_buff[1] = Kernel::RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw; 318 cmd_buff[1] = RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw;
296} 319}
297 320
321/**
322 * FS_User::OpenDirectory service function
323 * Inputs:
324 * 1 : Archive handle low word
325 * 2 : Archive handle high word
326 * 3 : Low path type
327 * 4 : Low path size
328 * 7 : (LowPathSize << 14) | 2
329 * 8 : Low path data pointer
330 * Outputs:
331 * 1 : Result of function, 0 on success, otherwise error code
332 * 3 : Directory handle
333 */
298static void OpenDirectory(Service::Interface* self) { 334static void OpenDirectory(Service::Interface* self) {
299 u32* cmd_buff = Service::GetCommandBuffer(); 335 u32* cmd_buff = Kernel::GetCommandBuffer();
300 336
301 // TODO(Link Mauve): cmd_buff[2], aka archive handle lower word, isn't used according to 337 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[1], cmd_buff[2]);
302 // 3dmoo's or ctrulib's implementations. Triple check if it's really the case.
303 Handle archive_handle = static_cast<Handle>(cmd_buff[2]);
304 auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); 338 auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[3]);
305 u32 dirname_size = cmd_buff[4]; 339 u32 dirname_size = cmd_buff[4];
306 u32 dirname_ptr = cmd_buff[6]; 340 u32 dirname_ptr = cmd_buff[6];
@@ -309,7 +343,7 @@ static void OpenDirectory(Service::Interface* self) {
309 343
310 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); 344 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str());
311 345
312 ResultVal<Handle> handle = Kernel::OpenDirectoryFromArchive(archive_handle, dir_path); 346 ResultVal<Handle> handle = OpenDirectoryFromArchive(archive_handle, dir_path);
313 cmd_buff[1] = handle.Code().raw; 347 cmd_buff[1] = handle.Code().raw;
314 if (handle.Succeeded()) { 348 if (handle.Succeeded()) {
315 cmd_buff[3] = *handle; 349 cmd_buff[3] = *handle;
@@ -332,9 +366,9 @@ static void OpenDirectory(Service::Interface* self) {
332 * 3 : Archive handle upper word (same as file handle) 366 * 3 : Archive handle upper word (same as file handle)
333 */ 367 */
334static void OpenArchive(Service::Interface* self) { 368static void OpenArchive(Service::Interface* self) {
335 u32* cmd_buff = Service::GetCommandBuffer(); 369 u32* cmd_buff = Kernel::GetCommandBuffer();
336 370
337 auto archive_id = static_cast<FileSys::Archive::IdCode>(cmd_buff[1]); 371 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]);
338 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); 372 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]);
339 u32 archivename_size = cmd_buff[3]; 373 u32 archivename_size = cmd_buff[3];
340 u32 archivename_ptr = cmd_buff[5]; 374 u32 archivename_ptr = cmd_buff[5];
@@ -348,16 +382,34 @@ static void OpenArchive(Service::Interface* self) {
348 return; 382 return;
349 } 383 }
350 384
351 ResultVal<Handle> handle = Kernel::OpenArchive(archive_id); 385 ResultVal<ArchiveHandle> handle = OpenArchive(archive_id);
352 cmd_buff[1] = handle.Code().raw; 386 cmd_buff[1] = handle.Code().raw;
353 if (handle.Succeeded()) { 387 if (handle.Succeeded()) {
354 // cmd_buff[2] isn't used according to 3dmoo's implementation. 388 cmd_buff[2] = *handle & 0xFFFFFFFF;
355 cmd_buff[3] = *handle; 389 cmd_buff[3] = (*handle >> 32) & 0xFFFFFFFF;
356 } else { 390 } else {
391 cmd_buff[2] = cmd_buff[3] = 0;
357 LOG_ERROR(Service_FS, "failed to get a handle for archive"); 392 LOG_ERROR(Service_FS, "failed to get a handle for archive");
358 } 393 }
359} 394}
360 395
396/**
397 * FS_User::CloseArchive service function
398 * Inputs:
399 * 0 : 0x080E0080
400 * 1 : Archive handle low word
401 * 2 : Archive handle high word
402 * Outputs:
403 * 0 : ??? TODO(yuriks): Verify return header
404 * 1 : Result of function, 0 on success, otherwise error code
405 */
406static void CloseArchive(Service::Interface* self) {
407 u32* cmd_buff = Kernel::GetCommandBuffer();
408
409 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[1], cmd_buff[2]);
410 cmd_buff[1] = CloseArchive(archive_handle).raw;
411}
412
361/* 413/*
362* FS_User::IsSdmcDetected service function 414* FS_User::IsSdmcDetected service function
363* Outputs: 415* Outputs:
@@ -365,7 +417,7 @@ static void OpenArchive(Service::Interface* self) {
365* 2 : Whether the Sdmc could be detected 417* 2 : Whether the Sdmc could be detected
366*/ 418*/
367static void IsSdmcDetected(Service::Interface* self) { 419static void IsSdmcDetected(Service::Interface* self) {
368 u32* cmd_buff = Service::GetCommandBuffer(); 420 u32* cmd_buff = Kernel::GetCommandBuffer();
369 421
370 cmd_buff[1] = 0; 422 cmd_buff[1] = 0;
371 cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0; 423 cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0;
@@ -373,7 +425,83 @@ static void IsSdmcDetected(Service::Interface* self) {
373 LOG_DEBUG(Service_FS, "called"); 425 LOG_DEBUG(Service_FS, "called");
374} 426}
375 427
376const Interface::FunctionInfo FunctionTable[] = { 428/**
429 * FS_User::IsSdmcWriteable service function
430 * Outputs:
431 * 0 : Command header 0x08180000
432 * 1 : Result of function, 0 on success, otherwise error code
433 * 2 : Whether the Sdmc is currently writeable
434 */
435static void IsSdmcWriteable(Service::Interface* self) {
436 u32* cmd_buff = Kernel::GetCommandBuffer();
437
438 cmd_buff[1] = RESULT_SUCCESS.raw;
439 // If the SD isn't enabled, it can't be writeable...else, stubbed true
440 cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0;
441
442 LOG_DEBUG(Service_FS, " (STUBBED)");
443}
444
445/**
446 * FS_User::FormatSaveData service function,
447 * formats the SaveData specified by the input path.
448 * Inputs:
449 * 0 : 0x084C0242
450 * 1 : Archive ID
451 * 2 : Archive low path type
452 * 3 : Archive low path size
453 * 10 : (LowPathSize << 14) | 2
454 * 11 : Archive low path
455 * Outputs:
456 * 1 : Result of function, 0 on success, otherwise error code
457 */
458static void FormatSaveData(Service::Interface* self) {
459 // TODO(Subv): Find out what the other inputs and outputs of this function are
460 u32* cmd_buff = Kernel::GetCommandBuffer();
461 LOG_DEBUG(Service_FS, "(STUBBED)");
462
463 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]);
464 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]);
465 u32 archivename_size = cmd_buff[3];
466 u32 archivename_ptr = cmd_buff[11];
467 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
468
469 LOG_DEBUG(Service_FS, "archive_path=%s", archive_path.DebugStr().c_str());
470
471 if (archive_id != FS::ArchiveIdCode::SaveData) {
472 // TODO(Subv): What should happen if somebody attempts to format a different archive?
473 LOG_ERROR(Service_FS, "tried to format an archive different than SaveData, %u", cmd_buff[1]);
474 cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw;
475 return;
476 }
477
478 if (archive_path.GetType() != FileSys::LowPathType::Empty) {
479 // TODO(Subv): Implement formatting the SaveData of other games
480 LOG_ERROR(Service_FS, "archive LowPath type other than empty is currently unsupported");
481 cmd_buff[1] = UnimplementedFunction(ErrorModule::FS).raw;
482 return;
483 }
484
485 cmd_buff[1] = FormatSaveData().raw;
486}
487
488/**
489 * FS_User::FormatThisUserSaveData service function
490 * Inputs:
491 * 0: 0x080F0180
492 * Outputs:
493 * 1 : Result of function, 0 on success, otherwise error code
494 */
495static void FormatThisUserSaveData(Service::Interface* self) {
496 u32* cmd_buff = Kernel::GetCommandBuffer();
497 LOG_DEBUG(Service_FS, "(STUBBED)");
498
499 // TODO(Subv): Find out what the inputs and outputs of this function are
500
501 cmd_buff[1] = FormatSaveData().raw;
502}
503
504const FSUserInterface::FunctionInfo FunctionTable[] = {
377 {0x000100C6, nullptr, "Dummy1"}, 505 {0x000100C6, nullptr, "Dummy1"},
378 {0x040100C4, nullptr, "Control"}, 506 {0x040100C4, nullptr, "Control"},
379 {0x08010002, Initialize, "Initialize"}, 507 {0x08010002, Initialize, "Initialize"},
@@ -383,14 +511,14 @@ const Interface::FunctionInfo FunctionTable[] = {
383 {0x08050244, RenameFile, "RenameFile"}, 511 {0x08050244, RenameFile, "RenameFile"},
384 {0x08060142, DeleteDirectory, "DeleteDirectory"}, 512 {0x08060142, DeleteDirectory, "DeleteDirectory"},
385 {0x08070142, nullptr, "DeleteDirectoryRecursively"}, 513 {0x08070142, nullptr, "DeleteDirectoryRecursively"},
386 {0x08080202, nullptr, "CreateFile"}, 514 {0x08080202, CreateFile, "CreateFile"},
387 {0x08090182, CreateDirectory, "CreateDirectory"}, 515 {0x08090182, CreateDirectory, "CreateDirectory"},
388 {0x080A0244, RenameDirectory, "RenameDirectory"}, 516 {0x080A0244, RenameDirectory, "RenameDirectory"},
389 {0x080B0102, OpenDirectory, "OpenDirectory"}, 517 {0x080B0102, OpenDirectory, "OpenDirectory"},
390 {0x080C00C2, OpenArchive, "OpenArchive"}, 518 {0x080C00C2, OpenArchive, "OpenArchive"},
391 {0x080D0144, nullptr, "ControlArchive"}, 519 {0x080D0144, nullptr, "ControlArchive"},
392 {0x080E0080, nullptr, "CloseArchive"}, 520 {0x080E0080, CloseArchive, "CloseArchive"},
393 {0x080F0180, nullptr, "FormatThisUserSaveData"}, 521 {0x080F0180, FormatThisUserSaveData,"FormatThisUserSaveData"},
394 {0x08100200, nullptr, "CreateSystemSaveData"}, 522 {0x08100200, nullptr, "CreateSystemSaveData"},
395 {0x08110040, nullptr, "DeleteSystemSaveData"}, 523 {0x08110040, nullptr, "DeleteSystemSaveData"},
396 {0x08120080, nullptr, "GetFreeBytes"}, 524 {0x08120080, nullptr, "GetFreeBytes"},
@@ -399,7 +527,7 @@ const Interface::FunctionInfo FunctionTable[] = {
399 {0x08150000, nullptr, "GetNandArchiveResource"}, 527 {0x08150000, nullptr, "GetNandArchiveResource"},
400 {0x08160000, nullptr, "GetSdmcFatfsErro"}, 528 {0x08160000, nullptr, "GetSdmcFatfsErro"},
401 {0x08170000, IsSdmcDetected, "IsSdmcDetected"}, 529 {0x08170000, IsSdmcDetected, "IsSdmcDetected"},
402 {0x08180000, nullptr, "IsSdmcWritable"}, 530 {0x08180000, IsSdmcWriteable, "IsSdmcWritable"},
403 {0x08190042, nullptr, "GetSdmcCid"}, 531 {0x08190042, nullptr, "GetSdmcCid"},
404 {0x081A0042, nullptr, "GetNandCid"}, 532 {0x081A0042, nullptr, "GetNandCid"},
405 {0x081B0000, nullptr, "GetSdmcSpeedInfo"}, 533 {0x081B0000, nullptr, "GetSdmcSpeedInfo"},
@@ -451,7 +579,7 @@ const Interface::FunctionInfo FunctionTable[] = {
451 {0x08490040, nullptr, "GetArchiveResource"}, 579 {0x08490040, nullptr, "GetArchiveResource"},
452 {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"}, 580 {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"},
453 {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"}, 581 {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"},
454 {0x084C0242, nullptr, "FormatSaveData"}, 582 {0x084C0242, FormatSaveData, "FormatSaveData"},
455 {0x084D0102, nullptr, "GetLegacySubBannerData"}, 583 {0x084D0102, nullptr, "GetLegacySubBannerData"},
456 {0x084E0342, nullptr, "UpdateSha256Context"}, 584 {0x084E0342, nullptr, "UpdateSha256Context"},
457 {0x084F0102, nullptr, "ReadSpecialFile"}, 585 {0x084F0102, nullptr, "ReadSpecialFile"},
@@ -465,11 +593,9 @@ const Interface::FunctionInfo FunctionTable[] = {
465//////////////////////////////////////////////////////////////////////////////////////////////////// 593////////////////////////////////////////////////////////////////////////////////////////////////////
466// Interface class 594// Interface class
467 595
468Interface::Interface() { 596FSUserInterface::FSUserInterface() {
469 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 597 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
470} 598}
471 599
472Interface::~Interface() { 600} // namespace FS
473} 601} // namespace Service
474
475} // namespace
diff --git a/src/core/hle/service/fs_user.h b/src/core/hle/service/fs/fs_user.h
index 005382540..2d896dd5f 100644
--- a/src/core/hle/service/fs_user.h
+++ b/src/core/hle/service/fs/fs_user.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -9,23 +9,18 @@
9//////////////////////////////////////////////////////////////////////////////////////////////////// 9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace FS_User 10// Namespace FS_User
11 11
12namespace FS_User { 12namespace Service {
13namespace FS {
13 14
14/// Interface to "fs:USER" service 15/// Interface to "fs:USER" service
15class Interface : public Service::Interface { 16class FSUserInterface : public Service::Interface {
16public: 17public:
18 FSUserInterface();
17 19
18 Interface();
19
20 ~Interface();
21
22 /**
23 * Gets the string port name used by CTROS for the service
24 * @return Port name of service
25 */
26 std::string GetPortName() const override { 20 std::string GetPortName() const override {
27 return "fs:USER"; 21 return "fs:USER";
28 } 22 }
29}; 23};
30 24
31} // namespace 25} // namespace FS
26} // namespace Service
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 223800560..0127d4ee5 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5 5
@@ -72,7 +72,7 @@ static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) {
72 72
73/// Write a GSP GPU hardware register 73/// Write a GSP GPU hardware register
74static void WriteHWRegs(Service::Interface* self) { 74static void WriteHWRegs(Service::Interface* self) {
75 u32* cmd_buff = Service::GetCommandBuffer(); 75 u32* cmd_buff = Kernel::GetCommandBuffer();
76 u32 reg_addr = cmd_buff[1]; 76 u32 reg_addr = cmd_buff[1];
77 u32 size = cmd_buff[2]; 77 u32 size = cmd_buff[2];
78 78
@@ -83,7 +83,7 @@ static void WriteHWRegs(Service::Interface* self) {
83 83
84/// Read a GSP GPU hardware register 84/// Read a GSP GPU hardware register
85static void ReadHWRegs(Service::Interface* self) { 85static void ReadHWRegs(Service::Interface* self) {
86 u32* cmd_buff = Service::GetCommandBuffer(); 86 u32* cmd_buff = Kernel::GetCommandBuffer();
87 u32 reg_addr = cmd_buff[1]; 87 u32 reg_addr = cmd_buff[1];
88 u32 size = cmd_buff[2]; 88 u32 size = cmd_buff[2];
89 89
@@ -136,7 +136,7 @@ static void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
136 * 1: Result code 136 * 1: Result code
137 */ 137 */
138static void SetBufferSwap(Service::Interface* self) { 138static void SetBufferSwap(Service::Interface* self) {
139 u32* cmd_buff = Service::GetCommandBuffer(); 139 u32* cmd_buff = Kernel::GetCommandBuffer();
140 u32 screen_id = cmd_buff[1]; 140 u32 screen_id = cmd_buff[1];
141 FrameBufferInfo* fb_info = (FrameBufferInfo*)&cmd_buff[2]; 141 FrameBufferInfo* fb_info = (FrameBufferInfo*)&cmd_buff[2];
142 SetBufferSwap(screen_id, *fb_info); 142 SetBufferSwap(screen_id, *fb_info);
@@ -145,6 +145,30 @@ static void SetBufferSwap(Service::Interface* self) {
145} 145}
146 146
147/** 147/**
148 * GSP_GPU::FlushDataCache service function
149 *
150 * This Function is a no-op, We aren't emulating the CPU cache any time soon.
151 *
152 * Inputs:
153 * 1 : Address
154 * 2 : Size
155 * 3 : Value 0, some descriptor for the KProcess Handle
156 * 4 : KProcess handle
157 * Outputs:
158 * 1 : Result of function, 0 on success, otherwise error code
159 */
160static void FlushDataCache(Service::Interface* self) {
161 u32* cmd_buff = Kernel::GetCommandBuffer();
162 u32 address = cmd_buff[1];
163 u32 size = cmd_buff[2];
164 u32 process = cmd_buff[4];
165
166 // TODO(purpasmart96): Verify return header on HW
167
168 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
169}
170
171/**
148 * GSP_GPU::RegisterInterruptRelayQueue service function 172 * GSP_GPU::RegisterInterruptRelayQueue service function
149 * Inputs: 173 * Inputs:
150 * 1 : "Flags" field, purpose is unknown 174 * 1 : "Flags" field, purpose is unknown
@@ -155,7 +179,7 @@ static void SetBufferSwap(Service::Interface* self) {
155 * 4 : Handle to GSP shared memory 179 * 4 : Handle to GSP shared memory
156 */ 180 */
157static void RegisterInterruptRelayQueue(Service::Interface* self) { 181static void RegisterInterruptRelayQueue(Service::Interface* self) {
158 u32* cmd_buff = Service::GetCommandBuffer(); 182 u32* cmd_buff = Kernel::GetCommandBuffer();
159 u32 flags = cmd_buff[1]; 183 u32 flags = cmd_buff[1];
160 g_interrupt_event = cmd_buff[3]; 184 g_interrupt_event = cmd_buff[3];
161 g_shared_memory = Kernel::CreateSharedMemory("GSPSharedMem"); 185 g_shared_memory = Kernel::CreateSharedMemory("GSPSharedMem");
@@ -323,7 +347,7 @@ static void TriggerCmdReqQueue(Service::Interface* self) {
323 } 347 }
324 } 348 }
325 349
326 u32* cmd_buff = Service::GetCommandBuffer(); 350 u32* cmd_buff = Kernel::GetCommandBuffer();
327 cmd_buff[1] = 0; // No error 351 cmd_buff[1] = 0; // No error
328} 352}
329 353
@@ -335,7 +359,7 @@ const Interface::FunctionInfo FunctionTable[] = {
335 {0x00050200, SetBufferSwap, "SetBufferSwap"}, 359 {0x00050200, SetBufferSwap, "SetBufferSwap"},
336 {0x00060082, nullptr, "SetCommandList"}, 360 {0x00060082, nullptr, "SetCommandList"},
337 {0x000700C2, nullptr, "RequestDma"}, 361 {0x000700C2, nullptr, "RequestDma"},
338 {0x00080082, nullptr, "FlushDataCache"}, 362 {0x00080082, FlushDataCache, "FlushDataCache"},
339 {0x00090082, nullptr, "InvalidateDataCache"}, 363 {0x00090082, nullptr, "InvalidateDataCache"},
340 {0x000A0044, nullptr, "RegisterInterruptEvents"}, 364 {0x000A0044, nullptr, "RegisterInterruptEvents"},
341 {0x000B0040, nullptr, "SetLcdForceBlack"}, 365 {0x000B0040, nullptr, "SetLcdForceBlack"},
@@ -372,7 +396,4 @@ Interface::Interface() {
372 g_thread_id = 1; 396 g_thread_id = 1;
373} 397}
374 398
375Interface::~Interface() {
376}
377
378} // namespace 399} // namespace
diff --git a/src/core/hle/service/gsp_gpu.h b/src/core/hle/service/gsp_gpu.h
index 177ce8da6..932b6170f 100644
--- a/src/core/hle/service/gsp_gpu.h
+++ b/src/core/hle/service/gsp_gpu.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -158,19 +158,11 @@ static_assert(sizeof(CommandBuffer) == 0x200, "CommandBuffer struct has incorrec
158/// Interface to "srv:" service 158/// Interface to "srv:" service
159class Interface : public Service::Interface { 159class Interface : public Service::Interface {
160public: 160public:
161
162 Interface(); 161 Interface();
163 162
164 ~Interface();
165
166 /**
167 * Gets the string port name used by CTROS for the service
168 * @return Port name of service
169 */
170 std::string GetPortName() const override { 163 std::string GetPortName() const override {
171 return "gsp::Gpu"; 164 return "gsp::Gpu";
172 } 165 }
173
174}; 166};
175 167
176/** 168/**
diff --git a/src/core/hle/service/hid_user.cpp b/src/core/hle/service/hid_user.cpp
index 5772199d4..99b0ea5a0 100644
--- a/src/core/hle/service/hid_user.cpp
+++ b/src/core/hle/service/hid_user.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -153,7 +153,7 @@ void PadUpdateComplete() {
153 * 8 : Event signaled by HID_User 153 * 8 : Event signaled by HID_User
154 */ 154 */
155static void GetIPCHandles(Service::Interface* self) { 155static void GetIPCHandles(Service::Interface* self) {
156 u32* cmd_buff = Service::GetCommandBuffer(); 156 u32* cmd_buff = Kernel::GetCommandBuffer();
157 157
158 cmd_buff[1] = 0; // No error 158 cmd_buff[1] = 0; // No error
159 cmd_buff[3] = shared_mem; 159 cmd_buff[3] = shared_mem;
@@ -179,7 +179,6 @@ const Interface::FunctionInfo FunctionTable[] = {
179 {0x00170000, nullptr, "GetSoundVolume"}, 179 {0x00170000, nullptr, "GetSoundVolume"},
180}; 180};
181 181
182
183//////////////////////////////////////////////////////////////////////////////////////////////////// 182////////////////////////////////////////////////////////////////////////////////////////////////////
184// Interface class 183// Interface class
185 184
@@ -196,7 +195,4 @@ Interface::Interface() {
196 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 195 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
197} 196}
198 197
199Interface::~Interface() {
200}
201
202} // namespace 198} // namespace
diff --git a/src/core/hle/service/hid_user.h b/src/core/hle/service/hid_user.h
index 8f53befdb..5b96dda60 100644
--- a/src/core/hle/service/hid_user.h
+++ b/src/core/hle/service/hid_user.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -102,19 +102,11 @@ void PadUpdateComplete();
102 */ 102 */
103class Interface : public Service::Interface { 103class Interface : public Service::Interface {
104public: 104public:
105
106 Interface(); 105 Interface();
107 106
108 ~Interface();
109
110 /**
111 * Gets the string port name used by CTROS for the service
112 * @return Port name of service
113 */
114 std::string GetPortName() const override { 107 std::string GetPortName() const override {
115 return "hid:USER"; 108 return "hid:USER";
116 } 109 }
117
118}; 110};
119 111
120} // namespace 112} // namespace
diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp
new file mode 100644
index 000000000..d0bff552f
--- /dev/null
+++ b/src/core/hle/service/http_c.cpp
@@ -0,0 +1,64 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/http_c.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace HTTP_C
11
12namespace HTTP_C {
13
14const Interface::FunctionInfo FunctionTable[] = {
15 {0x00010044, nullptr, "Initialize"},
16 {0x00020082, nullptr, "CreateContext"},
17 {0x00030040, nullptr, "CloseContext"},
18 {0x00040040, nullptr, "CancelConnection"},
19 {0x00050040, nullptr, "GetRequestState"},
20 {0x00060040, nullptr, "GetDownloadSizeState"},
21 {0x00070040, nullptr, "GetRequestError"},
22 {0x00080042, nullptr, "InitializeConnectionSession"},
23 {0x00090040, nullptr, "BeginRequest"},
24 {0x000A0040, nullptr, "BeginRequestAsync"},
25 {0x000B0082, nullptr, "ReceiveData"},
26 {0x000C0102, nullptr, "ReceiveDataTimeout"},
27 {0x000D0146, nullptr, "SetProxy"},
28 {0x000E0040, nullptr, "SetProxyDefault"},
29 {0x000F00C4, nullptr, "SetBasicAuthorization"},
30 {0x00100080, nullptr, "SetSocketBufferSize"},
31 {0x001100C4, nullptr, "AddRequestHeader"},
32 {0x001200C4, nullptr, "AddPostDataAscii"},
33 {0x001300C4, nullptr, "AddPostDataBinary"},
34 {0x00140082, nullptr, "AddPostDataRaw"},
35 {0x00150080, nullptr, "SetPostDataType"},
36 {0x001600C4, nullptr, "SendPostDataAscii"},
37 {0x00170144, nullptr, "SendPostDataAsciiTimeout"},
38 {0x001800C4, nullptr, "SendPostDataBinary"},
39 {0x00190144, nullptr, "SendPostDataBinaryTimeout"},
40 {0x001A0082, nullptr, "SendPostDataRaw"},
41 {0x001B0102, nullptr, "SendPOSTDataRawTimeout"},
42 {0x001C0080, nullptr, "SetPostDataEncoding"},
43 {0x001D0040, nullptr, "NotifyFinishSendPostData"},
44 {0x001E00C4, nullptr, "GetResponseHeader"},
45 {0x001F0144, nullptr, "GetResponseHeaderTimeout"},
46 {0x00200082, nullptr, "GetResponseData"},
47 {0x00210102, nullptr, "GetResponseDataTimeout"},
48 {0x00220040, nullptr, "GetResponseStatusCode"},
49 {0x002300C0, nullptr, "GetResponseStatusCodeTimeout"},
50 {0x00240082, nullptr, "AddTrustedRootCA"},
51 {0x00350186, nullptr, "SetDefaultProxy"},
52 {0x00360000, nullptr, "ClearDNSCache"},
53 {0x00370080, nullptr, "SetKeepAlive"},
54 {0x003800C0, nullptr, "Finalize"},
55};
56
57////////////////////////////////////////////////////////////////////////////////////////////////////
58// Interface class
59
60Interface::Interface() {
61 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
62}
63
64} // namespace
diff --git a/src/core/hle/service/http_c.h b/src/core/hle/service/http_c.h
new file mode 100644
index 000000000..5ea3d1df3
--- /dev/null
+++ b/src/core/hle/service/http_c.h
@@ -0,0 +1,23 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace HTTP_C
11
12namespace HTTP_C {
13
14class Interface : public Service::Interface {
15public:
16 Interface();
17
18 std::string GetPortName() const override {
19 return "http:C";
20 }
21};
22
23} // namespace
diff --git a/src/core/hle/service/ir_rst.cpp b/src/core/hle/service/ir_rst.cpp
index be15db231..b388afb15 100644
--- a/src/core/hle/service/ir_rst.cpp
+++ b/src/core/hle/service/ir_rst.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -30,7 +30,4 @@ Interface::Interface() {
30 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 30 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
31} 31}
32 32
33Interface::~Interface() {
34}
35
36} // namespace 33} // namespace
diff --git a/src/core/hle/service/ir_rst.h b/src/core/hle/service/ir_rst.h
index 73effd7e3..deef701c5 100644
--- a/src/core/hle/service/ir_rst.h
+++ b/src/core/hle/service/ir_rst.h
@@ -1,6 +1,6 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included..
4 4
5#pragma once 5#pragma once
6 6
@@ -14,11 +14,7 @@ namespace IR_RST {
14class Interface : public Service::Interface { 14class Interface : public Service::Interface {
15public: 15public:
16 Interface(); 16 Interface();
17 ~Interface(); 17
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const override { 18 std::string GetPortName() const override {
23 return "ir:rst"; 19 return "ir:rst";
24 } 20 }
diff --git a/src/core/hle/service/ir_u.cpp b/src/core/hle/service/ir_u.cpp
index aa9db6f6d..da6f38e41 100644
--- a/src/core/hle/service/ir_u.cpp
+++ b/src/core/hle/service/ir_u.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -39,7 +39,4 @@ Interface::Interface() {
39 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 39 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
40} 40}
41 41
42Interface::~Interface() {
43}
44
45} // namespace 42} // namespace
diff --git a/src/core/hle/service/ir_u.h b/src/core/hle/service/ir_u.h
index 86d98d079..ec47a1524 100644
--- a/src/core/hle/service/ir_u.h
+++ b/src/core/hle/service/ir_u.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -14,11 +14,7 @@ namespace IR_U {
14class Interface : public Service::Interface { 14class Interface : public Service::Interface {
15public: 15public:
16 Interface(); 16 Interface();
17 ~Interface(); 17
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const override { 18 std::string GetPortName() const override {
23 return "ir:u"; 19 return "ir:u";
24 } 20 }
diff --git a/src/core/hle/service/ldr_ro.cpp b/src/core/hle/service/ldr_ro.cpp
new file mode 100644
index 000000000..9c9e90a40
--- /dev/null
+++ b/src/core/hle/service/ldr_ro.cpp
@@ -0,0 +1,29 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/ldr_ro.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace LDR_RO
11
12namespace LDR_RO {
13
14const Interface::FunctionInfo FunctionTable[] = {
15 {0x000100C2, nullptr, "Initialize"},
16 {0x00020082, nullptr, "CRR_Load"},
17 {0x00030042, nullptr, "CRR_Unload"},
18 {0x000402C2, nullptr, "CRO_LoadAndFix"},
19 {0x000500C2, nullptr, "CRO_ApplyRelocationPatchesAndLink"}
20};
21
22////////////////////////////////////////////////////////////////////////////////////////////////////
23// Interface class
24
25Interface::Interface() {
26 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
27}
28
29} // namespace
diff --git a/src/core/hle/service/ldr_ro.h b/src/core/hle/service/ldr_ro.h
new file mode 100644
index 000000000..331637cde
--- /dev/null
+++ b/src/core/hle/service/ldr_ro.h
@@ -0,0 +1,23 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace LDR_RO
11
12namespace LDR_RO {
13
14class Interface : public Service::Interface {
15public:
16 Interface();
17
18 std::string GetPortName() const override {
19 return "ldr:ro";
20 }
21};
22
23} // namespace
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp
index d6f30e9ae..82bce9180 100644
--- a/src/core/hle/service/mic_u.cpp
+++ b/src/core/hle/service/mic_u.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -37,7 +37,4 @@ Interface::Interface() {
37 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 37 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
38} 38}
39 39
40Interface::~Interface() {
41}
42
43} // namespace 40} // namespace
diff --git a/src/core/hle/service/mic_u.h b/src/core/hle/service/mic_u.h
index 2a495f3a9..dc795d14c 100644
--- a/src/core/hle/service/mic_u.h
+++ b/src/core/hle/service/mic_u.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -16,11 +16,7 @@ namespace MIC_U {
16class Interface : public Service::Interface { 16class Interface : public Service::Interface {
17public: 17public:
18 Interface(); 18 Interface();
19 ~Interface(); 19
20 /**
21 * Gets the string port name used by CTROS for the service
22 * @return Port name of service
23 */
24 std::string GetPortName() const override { 20 std::string GetPortName() const override {
25 return "mic:u"; 21 return "mic:u";
26 } 22 }
diff --git a/src/core/hle/service/ndm_u.cpp b/src/core/hle/service/ndm_u.cpp
index 37c0661bf..233b14f6d 100644
--- a/src/core/hle/service/ndm_u.cpp
+++ b/src/core/hle/service/ndm_u.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/hle.h" 5#include "core/hle/hle.h"
@@ -24,7 +24,4 @@ Interface::Interface() {
24 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 24 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
25} 25}
26 26
27Interface::~Interface() {
28}
29
30} // namespace 27} // namespace
diff --git a/src/core/hle/service/ndm_u.h b/src/core/hle/service/ndm_u.h
index 2ca9fcf22..51c4b3902 100644
--- a/src/core/hle/service/ndm_u.h
+++ b/src/core/hle/service/ndm_u.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -15,19 +15,11 @@ namespace NDM_U {
15 15
16class Interface : public Service::Interface { 16class Interface : public Service::Interface {
17public: 17public:
18
19 Interface(); 18 Interface();
20 19
21 ~Interface();
22
23 /**
24 * Gets the string port name used by CTROS for the service
25 * @return Port name of service
26 */
27 std::string GetPortName() const override { 20 std::string GetPortName() const override {
28 return "ndm:u"; 21 return "ndm:u";
29 } 22 }
30
31}; 23};
32 24
33} // namespace 25} // namespace
diff --git a/src/core/hle/service/news_u.cpp b/src/core/hle/service/news_u.cpp
new file mode 100644
index 000000000..b5adad4c6
--- /dev/null
+++ b/src/core/hle/service/news_u.cpp
@@ -0,0 +1,25 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/news_u.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace NEWS_U
11
12namespace NEWS_U {
13
14const Interface::FunctionInfo FunctionTable[] = {
15 {0x000100C8, nullptr, "AddNotification"},
16};
17
18////////////////////////////////////////////////////////////////////////////////////////////////////
19// Interface class
20
21Interface::Interface() {
22 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
23}
24
25} // namespace
diff --git a/src/core/hle/service/news_u.h b/src/core/hle/service/news_u.h
new file mode 100644
index 000000000..0473cd19c
--- /dev/null
+++ b/src/core/hle/service/news_u.h
@@ -0,0 +1,23 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace NEWS_U
11
12namespace NEWS_U {
13
14class Interface : public Service::Interface {
15public:
16 Interface();
17
18 std::string GetPortName() const override {
19 return "news:u";
20 }
21};
22
23} // namespace
diff --git a/src/core/hle/service/nim_aoc.cpp b/src/core/hle/service/nim_aoc.cpp
new file mode 100644
index 000000000..17d1c4ff5
--- /dev/null
+++ b/src/core/hle/service/nim_aoc.cpp
@@ -0,0 +1,31 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/log.h"
6#include "core/hle/hle.h"
7#include "core/hle/service/nim_aoc.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace NIM_AOC
11
12namespace NIM_AOC {
13
14const Interface::FunctionInfo FunctionTable[] = {
15 {0x00030042, nullptr, "SetApplicationId"},
16 {0x00040042, nullptr, "SetTin"},
17 {0x000902D0, nullptr, "ListContentSetsEx"},
18 {0x00180000, nullptr, "GetBalance"},
19 {0x001D0000, nullptr, "GetCustomerSupportCode"},
20 {0x00210000, nullptr, "Initialize"},
21 {0x00240282, nullptr, "CalculateContentsRequiredSize"},
22 {0x00250000, nullptr, "RefreshServerTime"},
23};
24////////////////////////////////////////////////////////////////////////////////////////////////////
25// Interface class
26
27Interface::Interface() {
28 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
29}
30
31} // namespace
diff --git a/src/core/hle/service/nim_aoc.h b/src/core/hle/service/nim_aoc.h
new file mode 100644
index 000000000..aeb71eed2
--- /dev/null
+++ b/src/core/hle/service/nim_aoc.h
@@ -0,0 +1,23 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/service/service.h"
8
9////////////////////////////////////////////////////////////////////////////////////////////////////
10// Namespace NIM_AOC
11
12namespace NIM_AOC {
13
14class Interface : public Service::Interface {
15public:
16 Interface();
17
18 std::string GetPortName() const override {
19 return "nim:aoc";
20 }
21};
22
23} // namespace
diff --git a/src/core/hle/service/nwm_uds.cpp b/src/core/hle/service/nwm_uds.cpp
index 14df86d85..ce456a966 100644
--- a/src/core/hle/service/nwm_uds.cpp
+++ b/src/core/hle/service/nwm_uds.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -29,7 +29,4 @@ Interface::Interface() {
29 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 29 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
30} 30}
31 31
32Interface::~Interface() {
33}
34
35} // namespace 32} // namespace
diff --git a/src/core/hle/service/nwm_uds.h b/src/core/hle/service/nwm_uds.h
index 69d2c2002..9043f5aa7 100644
--- a/src/core/hle/service/nwm_uds.h
+++ b/src/core/hle/service/nwm_uds.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -16,11 +16,7 @@ namespace NWM_UDS {
16class Interface : public Service::Interface { 16class Interface : public Service::Interface {
17public: 17public:
18 Interface(); 18 Interface();
19 ~Interface(); 19
20 /**
21 * Gets the string port name used by CTROS for the service
22 * @return Port name of service
23 */
24 std::string GetPortName() const override { 20 std::string GetPortName() const override {
25 return "nwm:UDS"; 21 return "nwm:UDS";
26 } 22 }
diff --git a/src/core/hle/service/pm_app.cpp b/src/core/hle/service/pm_app.cpp
index 90e9b1bfa..529dccafb 100644
--- a/src/core/hle/service/pm_app.cpp
+++ b/src/core/hle/service/pm_app.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -29,7 +29,4 @@ Interface::Interface() {
29 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 29 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
30} 30}
31 31
32Interface::~Interface() {
33}
34
35} // namespace 32} // namespace
diff --git a/src/core/hle/service/pm_app.h b/src/core/hle/service/pm_app.h
index 28c38f582..c1fb1f9da 100644
--- a/src/core/hle/service/pm_app.h
+++ b/src/core/hle/service/pm_app.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -14,11 +14,7 @@ namespace PM_APP {
14class Interface : public Service::Interface { 14class Interface : public Service::Interface {
15public: 15public:
16 Interface(); 16 Interface();
17 ~Interface(); 17
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const override { 18 std::string GetPortName() const override {
23 return "pm:app"; 19 return "pm:app";
24 } 20 }
diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp
index 559f148dd..d1498f05c 100644
--- a/src/core/hle/service/ptm_u.cpp
+++ b/src/core/hle/service/ptm_u.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -34,7 +34,7 @@ static bool battery_is_charging = true;
34 * 2 : Output of function, 0 = not charging, 1 = charging. 34 * 2 : Output of function, 0 = not charging, 1 = charging.
35 */ 35 */
36static void GetAdapterState(Service::Interface* self) { 36static void GetAdapterState(Service::Interface* self) {
37 u32* cmd_buff = Service::GetCommandBuffer(); 37 u32* cmd_buff = Kernel::GetCommandBuffer();
38 38
39 // TODO(purpasmart96): This function is only a stub, 39 // TODO(purpasmart96): This function is only a stub,
40 // it returns a valid result without implementing full functionality. 40 // it returns a valid result without implementing full functionality.
@@ -52,7 +52,7 @@ static void GetAdapterState(Service::Interface* self) {
52 * 2 : Whether the 3DS's physical shell casing is open (1) or closed (0) 52 * 2 : Whether the 3DS's physical shell casing is open (1) or closed (0)
53 */ 53 */
54static void GetShellState(Service::Interface* self) { 54static void GetShellState(Service::Interface* self) {
55 u32* cmd_buff = Service::GetCommandBuffer(); 55 u32* cmd_buff = Kernel::GetCommandBuffer();
56 56
57 cmd_buff[1] = 0; 57 cmd_buff[1] = 0;
58 cmd_buff[2] = shell_open ? 1 : 0; 58 cmd_buff[2] = shell_open ? 1 : 0;
@@ -68,7 +68,7 @@ static void GetShellState(Service::Interface* self) {
68 * 3 = half full battery, 2 = low battery, 1 = critical battery. 68 * 3 = half full battery, 2 = low battery, 1 = critical battery.
69 */ 69 */
70static void GetBatteryLevel(Service::Interface* self) { 70static void GetBatteryLevel(Service::Interface* self) {
71 u32* cmd_buff = Service::GetCommandBuffer(); 71 u32* cmd_buff = Kernel::GetCommandBuffer();
72 72
73 // TODO(purpasmart96): This function is only a stub, 73 // TODO(purpasmart96): This function is only a stub,
74 // it returns a valid result without implementing full functionality. 74 // it returns a valid result without implementing full functionality.
@@ -86,7 +86,7 @@ static void GetBatteryLevel(Service::Interface* self) {
86 * 2 : Output of function, 0 = not charging, 1 = charging. 86 * 2 : Output of function, 0 = not charging, 1 = charging.
87 */ 87 */
88static void GetBatteryChargeState(Service::Interface* self) { 88static void GetBatteryChargeState(Service::Interface* self) {
89 u32* cmd_buff = Service::GetCommandBuffer(); 89 u32* cmd_buff = Kernel::GetCommandBuffer();
90 90
91 // TODO(purpasmart96): This function is only a stub, 91 // TODO(purpasmart96): This function is only a stub,
92 // it returns a valid result without implementing full functionality. 92 // it returns a valid result without implementing full functionality.
@@ -122,7 +122,4 @@ Interface::Interface() {
122 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 122 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
123} 123}
124 124
125Interface::~Interface() {
126}
127
128} // namespace 125} // namespace
diff --git a/src/core/hle/service/ptm_u.h b/src/core/hle/service/ptm_u.h
index f8d9f57be..a44624fd5 100644
--- a/src/core/hle/service/ptm_u.h
+++ b/src/core/hle/service/ptm_u.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -16,11 +16,7 @@ namespace PTM_U {
16class Interface : public Service::Interface { 16class Interface : public Service::Interface {
17public: 17public:
18 Interface(); 18 Interface();
19 ~Interface(); 19
20 /**
21 * Gets the string port name used by CTROS for the service
22 * @return Port name of service
23 */
24 std::string GetPortName() const override { 20 std::string GetPortName() const override {
25 return "ptm:u"; 21 return "ptm:u";
26 } 22 }
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index e6973572b..0f3cc2aa8 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common.h" 5#include "common/common.h"
@@ -7,22 +7,30 @@
7 7
8#include "core/hle/service/service.h" 8#include "core/hle/service/service.h"
9#include "core/hle/service/ac_u.h" 9#include "core/hle/service/ac_u.h"
10#include "core/hle/service/act_u.h"
11#include "core/hle/service/am_app.h"
10#include "core/hle/service/am_net.h" 12#include "core/hle/service/am_net.h"
13#include "core/hle/service/apt_a.h"
11#include "core/hle/service/apt_u.h" 14#include "core/hle/service/apt_u.h"
12#include "core/hle/service/boss_u.h" 15#include "core/hle/service/boss_u.h"
13#include "core/hle/service/cfg_i.h" 16#include "core/hle/service/cecd_u.h"
14#include "core/hle/service/cfg_u.h" 17#include "core/hle/service/cfg/cfg_i.h"
18#include "core/hle/service/cfg/cfg_u.h"
15#include "core/hle/service/csnd_snd.h" 19#include "core/hle/service/csnd_snd.h"
16#include "core/hle/service/dsp_dsp.h" 20#include "core/hle/service/dsp_dsp.h"
17#include "core/hle/service/err_f.h" 21#include "core/hle/service/err_f.h"
18#include "core/hle/service/fs_user.h" 22#include "core/hle/service/fs/fs_user.h"
19#include "core/hle/service/frd_u.h" 23#include "core/hle/service/frd_u.h"
20#include "core/hle/service/gsp_gpu.h" 24#include "core/hle/service/gsp_gpu.h"
21#include "core/hle/service/hid_user.h" 25#include "core/hle/service/hid_user.h"
26#include "core/hle/service/http_c.h"
22#include "core/hle/service/ir_rst.h" 27#include "core/hle/service/ir_rst.h"
23#include "core/hle/service/ir_u.h" 28#include "core/hle/service/ir_u.h"
29#include "core/hle/service/ldr_ro.h"
24#include "core/hle/service/mic_u.h" 30#include "core/hle/service/mic_u.h"
25#include "core/hle/service/ndm_u.h" 31#include "core/hle/service/ndm_u.h"
32#include "core/hle/service/news_u.h"
33#include "core/hle/service/nim_aoc.h"
26#include "core/hle/service/nwm_uds.h" 34#include "core/hle/service/nwm_uds.h"
27#include "core/hle/service/pm_app.h" 35#include "core/hle/service/pm_app.h"
28#include "core/hle/service/ptm_u.h" 36#include "core/hle/service/ptm_u.h"
@@ -48,7 +56,8 @@ Manager::~Manager() {
48 56
49/// Add a service to the manager (does not create it though) 57/// Add a service to the manager (does not create it though)
50void Manager::AddService(Interface* service) { 58void Manager::AddService(Interface* service) {
51 m_port_map[service->GetPortName()] = Kernel::g_object_pool.Create(service); 59 // TOOD(yuriks): Fix error reporting
60 m_port_map[service->GetPortName()] = Kernel::g_handle_table.Create(service).ValueOr(INVALID_HANDLE);
52 m_services.push_back(service); 61 m_services.push_back(service);
53} 62}
54 63
@@ -62,7 +71,7 @@ void Manager::DeleteService(const std::string& port_name) {
62 71
63/// Get a Service Interface from its Handle 72/// Get a Service Interface from its Handle
64Interface* Manager::FetchFromHandle(Handle handle) { 73Interface* Manager::FetchFromHandle(Handle handle) {
65 return Kernel::g_object_pool.Get<Interface>(handle); 74 return Kernel::g_handle_table.Get<Interface>(handle);
66} 75}
67 76
68/// Get a Service Interface from its port 77/// Get a Service Interface from its port
@@ -84,22 +93,30 @@ void Init() {
84 93
85 g_manager->AddService(new SRV::Interface); 94 g_manager->AddService(new SRV::Interface);
86 g_manager->AddService(new AC_U::Interface); 95 g_manager->AddService(new AC_U::Interface);
96 g_manager->AddService(new ACT_U::Interface);
97 g_manager->AddService(new AM_APP::Interface);
87 g_manager->AddService(new AM_NET::Interface); 98 g_manager->AddService(new AM_NET::Interface);
99 g_manager->AddService(new APT_A::Interface);
88 g_manager->AddService(new APT_U::Interface); 100 g_manager->AddService(new APT_U::Interface);
89 g_manager->AddService(new BOSS_U::Interface); 101 g_manager->AddService(new BOSS_U::Interface);
102 g_manager->AddService(new CECD_U::Interface);
90 g_manager->AddService(new CFG_I::Interface); 103 g_manager->AddService(new CFG_I::Interface);
91 g_manager->AddService(new CFG_U::Interface); 104 g_manager->AddService(new CFG_U::Interface);
92 g_manager->AddService(new CSND_SND::Interface); 105 g_manager->AddService(new CSND_SND::Interface);
93 g_manager->AddService(new DSP_DSP::Interface); 106 g_manager->AddService(new DSP_DSP::Interface);
94 g_manager->AddService(new ERR_F::Interface); 107 g_manager->AddService(new ERR_F::Interface);
95 g_manager->AddService(new FRD_U::Interface); 108 g_manager->AddService(new FRD_U::Interface);
96 g_manager->AddService(new FS_User::Interface); 109 g_manager->AddService(new FS::FSUserInterface);
97 g_manager->AddService(new GSP_GPU::Interface); 110 g_manager->AddService(new GSP_GPU::Interface);
98 g_manager->AddService(new HID_User::Interface); 111 g_manager->AddService(new HID_User::Interface);
112 g_manager->AddService(new HTTP_C::Interface);
99 g_manager->AddService(new IR_RST::Interface); 113 g_manager->AddService(new IR_RST::Interface);
100 g_manager->AddService(new IR_U::Interface); 114 g_manager->AddService(new IR_U::Interface);
115 g_manager->AddService(new LDR_RO::Interface);
101 g_manager->AddService(new MIC_U::Interface); 116 g_manager->AddService(new MIC_U::Interface);
102 g_manager->AddService(new NDM_U::Interface); 117 g_manager->AddService(new NDM_U::Interface);
118 g_manager->AddService(new NEWS_U::Interface);
119 g_manager->AddService(new NIM_AOC::Interface);
103 g_manager->AddService(new NWM_UDS::Interface); 120 g_manager->AddService(new NWM_UDS::Interface);
104 g_manager->AddService(new PM_APP::Interface); 121 g_manager->AddService(new PM_APP::Interface);
105 g_manager->AddService(new PTM_U::Interface); 122 g_manager->AddService(new PTM_U::Interface);
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index baae910a1..28b4ccd17 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -14,6 +14,7 @@
14#include "core/mem_map.h" 14#include "core/mem_map.h"
15 15
16#include "core/hle/kernel/kernel.h" 16#include "core/hle/kernel/kernel.h"
17#include "core/hle/kernel/session.h"
17#include "core/hle/svc.h" 18#include "core/hle/svc.h"
18 19
19//////////////////////////////////////////////////////////////////////////////////////////////////// 20////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -21,30 +22,19 @@
21 22
22namespace Service { 23namespace Service {
23 24
24static const int kMaxPortSize = 0x08; ///< Maximum size of a port name (8 characters) 25static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters)
25static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of header
26
27/**
28 * Returns a pointer to the command buffer in kernel memory
29 * @param offset Optional offset into command buffer
30 * @return Pointer to command buffer
31 */
32inline static u32* GetCommandBuffer(const int offset=0) {
33 return (u32*)Memory::GetPointer(Memory::KERNEL_MEMORY_VADDR + kCommandHeaderOffset + offset);
34}
35 26
36class Manager; 27class Manager;
37 28
38/// Interface to a CTROS service 29/// Interface to a CTROS service
39class Interface : public Kernel::Object { 30class Interface : public Kernel::Session {
31 // TODO(yuriks): An "Interface" being a Kernel::Object is mostly non-sense. Interface should be
32 // just something that encapsulates a session and acts as a helper to implement service
33 // processes.
34
40 friend class Manager; 35 friend class Manager;
41public: 36public:
42
43 std::string GetName() const override { return GetPortName(); } 37 std::string GetName() const override { return GetPortName(); }
44 std::string GetTypeName() const override { return GetPortName(); }
45
46 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Service; }
47 Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Service; }
48 38
49 typedef void (*Function)(Interface*); 39 typedef void (*Function)(Interface*);
50 40
@@ -64,7 +54,8 @@ public:
64 54
65 /// Allocates a new handle for the service 55 /// Allocates a new handle for the service
66 Handle CreateHandle(Kernel::Object *obj) { 56 Handle CreateHandle(Kernel::Object *obj) {
67 Handle handle = Kernel::g_object_pool.Create(obj); 57 // TODO(yuriks): Fix error reporting
58 Handle handle = Kernel::g_handle_table.Create(obj).ValueOr(INVALID_HANDLE);
68 m_handles.push_back(handle); 59 m_handles.push_back(handle);
69 return handle; 60 return handle;
70 } 61 }
@@ -72,12 +63,12 @@ public:
72 /// Frees a handle from the service 63 /// Frees a handle from the service
73 template <class T> 64 template <class T>
74 void DeleteHandle(const Handle handle) { 65 void DeleteHandle(const Handle handle) {
75 Kernel::g_object_pool.Destroy<T>(handle); 66 Kernel::g_handle_table.Close(handle);
76 m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end()); 67 m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end());
77 } 68 }
78 69
79 ResultVal<bool> SyncRequest() override { 70 ResultVal<bool> SyncRequest() override {
80 u32* cmd_buff = GetCommandBuffer(); 71 u32* cmd_buff = Kernel::GetCommandBuffer();
81 auto itr = m_functions.find(cmd_buff[0]); 72 auto itr = m_functions.find(cmd_buff[0]);
82 73
83 if (itr == m_functions.end() || itr->second.func == nullptr) { 74 if (itr == m_functions.end() || itr->second.func == nullptr) {
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp
index 2f8910468..ef4f9829d 100644
--- a/src/core/hle/service/soc_u.cpp
+++ b/src/core/hle/service/soc_u.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -52,7 +52,4 @@ Interface::Interface() {
52 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 52 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
53} 53}
54 54
55Interface::~Interface() {
56}
57
58} // namespace 55} // namespace
diff --git a/src/core/hle/service/soc_u.h b/src/core/hle/service/soc_u.h
index d5590a683..2edf3b482 100644
--- a/src/core/hle/service/soc_u.h
+++ b/src/core/hle/service/soc_u.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -14,11 +14,7 @@ namespace SOC_U {
14class Interface : public Service::Interface { 14class Interface : public Service::Interface {
15public: 15public:
16 Interface(); 16 Interface();
17 ~Interface(); 17
18 /**
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const override { 18 std::string GetPortName() const override {
23 return "soc:U"; 19 return "soc:U";
24 } 20 }
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index 24a846533..25fab1a4f 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/hle.h" 5#include "core/hle/hle.h"
@@ -16,7 +16,7 @@ static Handle g_event_handle = 0;
16static void Initialize(Service::Interface* self) { 16static void Initialize(Service::Interface* self) {
17 LOG_DEBUG(Service_SRV, "called"); 17 LOG_DEBUG(Service_SRV, "called");
18 18
19 u32* cmd_buff = Service::GetCommandBuffer(); 19 u32* cmd_buff = Kernel::GetCommandBuffer();
20 20
21 cmd_buff[1] = 0; // No error 21 cmd_buff[1] = 0; // No error
22} 22}
@@ -24,7 +24,7 @@ static void Initialize(Service::Interface* self) {
24static void GetProcSemaphore(Service::Interface* self) { 24static void GetProcSemaphore(Service::Interface* self) {
25 LOG_TRACE(Service_SRV, "called"); 25 LOG_TRACE(Service_SRV, "called");
26 26
27 u32* cmd_buff = Service::GetCommandBuffer(); 27 u32* cmd_buff = Kernel::GetCommandBuffer();
28 28
29 // TODO(bunnei): Change to a semaphore once these have been implemented 29 // TODO(bunnei): Change to a semaphore once these have been implemented
30 g_event_handle = Kernel::CreateEvent(RESETTYPE_ONESHOT, "SRV:Event"); 30 g_event_handle = Kernel::CreateEvent(RESETTYPE_ONESHOT, "SRV:Event");
@@ -36,7 +36,7 @@ static void GetProcSemaphore(Service::Interface* self) {
36 36
37static void GetServiceHandle(Service::Interface* self) { 37static void GetServiceHandle(Service::Interface* self) {
38 ResultCode res = RESULT_SUCCESS; 38 ResultCode res = RESULT_SUCCESS;
39 u32* cmd_buff = Service::GetCommandBuffer(); 39 u32* cmd_buff = Kernel::GetCommandBuffer();
40 40
41 std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize); 41 std::string port_name = std::string((const char*)&cmd_buff[1], 0, Service::kMaxPortSize);
42 Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); 42 Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);
@@ -68,7 +68,4 @@ Interface::Interface() {
68 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 68 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
69} 69}
70 70
71Interface::~Interface() {
72}
73
74} // namespace 71} // namespace
diff --git a/src/core/hle/service/srv.h b/src/core/hle/service/srv.h
index 6d5fe5048..653aba5cb 100644
--- a/src/core/hle/service/srv.h
+++ b/src/core/hle/service/srv.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/service/service.h" 5#include "core/hle/service/service.h"
@@ -11,21 +11,12 @@ namespace SRV {
11 11
12/// Interface to "srv:" service 12/// Interface to "srv:" service
13class Interface : public Service::Interface { 13class Interface : public Service::Interface {
14
15public: 14public:
16
17 Interface(); 15 Interface();
18 16
19 ~Interface();
20
21 /**
22 * Gets the string name used by CTROS for the service
23 * @return Port name of service
24 */
25 std::string GetPortName() const override { 17 std::string GetPortName() const override {
26 return "srv:"; 18 return "srv:";
27 } 19 }
28
29}; 20};
30 21
31} // namespace 22} // namespace
diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp
index 4aa660ecc..360516cdf 100644
--- a/src/core/hle/service/ssl_c.cpp
+++ b/src/core/hle/service/ssl_c.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/log.h" 5#include "common/log.h"
@@ -25,7 +25,4 @@ Interface::Interface() {
25 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 25 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
26} 26}
27 27
28Interface::~Interface() {
29}
30
31} // namespace 28} // namespace
diff --git a/src/core/hle/service/ssl_c.h b/src/core/hle/service/ssl_c.h
index 7b4e7fd8a..58e87c1cb 100644
--- a/src/core/hle/service/ssl_c.h
+++ b/src/core/hle/service/ssl_c.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -14,12 +14,8 @@ namespace SSL_C {
14class Interface : public Service::Interface { 14class Interface : public Service::Interface {
15public: 15public:
16 Interface(); 16 Interface();
17 ~Interface(); 17
18 /** 18 std::string GetPortName() const override {
19 * Gets the string port name used by CTROS for the service
20 * @return Port name of service
21 */
22 std::string GetPortName() const {
23 return "ssl:C"; 19 return "ssl:C";
24 } 20 }
25}; 21};
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index db0c42e74..25944fc68 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <map> 5#include <map>
@@ -12,6 +12,7 @@
12#include "core/hle/kernel/address_arbiter.h" 12#include "core/hle/kernel/address_arbiter.h"
13#include "core/hle/kernel/event.h" 13#include "core/hle/kernel/event.h"
14#include "core/hle/kernel/mutex.h" 14#include "core/hle/kernel/mutex.h"
15#include "core/hle/kernel/semaphore.h"
15#include "core/hle/kernel/shared_memory.h" 16#include "core/hle/kernel/shared_memory.h"
16#include "core/hle/kernel/thread.h" 17#include "core/hle/kernel/thread.h"
17 18
@@ -63,6 +64,10 @@ static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other
63 case Kernel::MemoryPermission::Read: 64 case Kernel::MemoryPermission::Read:
64 case Kernel::MemoryPermission::Write: 65 case Kernel::MemoryPermission::Write:
65 case Kernel::MemoryPermission::ReadWrite: 66 case Kernel::MemoryPermission::ReadWrite:
67 case Kernel::MemoryPermission::Execute:
68 case Kernel::MemoryPermission::ReadExecute:
69 case Kernel::MemoryPermission::WriteExecute:
70 case Kernel::MemoryPermission::ReadWriteExecute:
66 case Kernel::MemoryPermission::DontCare: 71 case Kernel::MemoryPermission::DontCare:
67 Kernel::MapSharedMemory(handle, addr, permissions_type, 72 Kernel::MapSharedMemory(handle, addr, permissions_type,
68 static_cast<Kernel::MemoryPermission>(other_permissions)); 73 static_cast<Kernel::MemoryPermission>(other_permissions));
@@ -87,17 +92,14 @@ static Result ConnectToPort(Handle* out, const char* port_name) {
87 92
88/// Synchronize to an OS service 93/// Synchronize to an OS service
89static Result SendSyncRequest(Handle handle) { 94static Result SendSyncRequest(Handle handle) {
90 // TODO(yuriks): ObjectPool::Get tries to check the Object type, which fails since this is a generic base Object, 95 Kernel::Session* session = Kernel::g_handle_table.Get<Kernel::Session>(handle);
91 // so we are forced to use GetFast and manually verify the handle. 96 if (session == nullptr) {
92 if (!Kernel::g_object_pool.IsValid(handle)) {
93 return InvalidHandle(ErrorModule::Kernel).raw; 97 return InvalidHandle(ErrorModule::Kernel).raw;
94 } 98 }
95 Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle);
96 99
97 _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); 100 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str());
98 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName().c_str());
99 101
100 ResultVal<bool> wait = object->SyncRequest(); 102 ResultVal<bool> wait = session->SyncRequest();
101 if (wait.Succeeded() && *wait) { 103 if (wait.Succeeded() && *wait) {
102 Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? 104 Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct?
103 } 105 }
@@ -117,11 +119,9 @@ static Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
117 // TODO(bunnei): Do something with nano_seconds, currently ignoring this 119 // TODO(bunnei): Do something with nano_seconds, currently ignoring this
118 bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated 120 bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated
119 121
120 if (!Kernel::g_object_pool.IsValid(handle)) { 122 Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handle);
123 if (object == nullptr)
121 return InvalidHandle(ErrorModule::Kernel).raw; 124 return InvalidHandle(ErrorModule::Kernel).raw;
122 }
123 Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle);
124 _dbg_assert_(Kernel, object != nullptr);
125 125
126 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), 126 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(),
127 object->GetName().c_str(), nano_seconds); 127 object->GetName().c_str(), nano_seconds);
@@ -148,10 +148,9 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
148 148
149 // Iterate through each handle, synchronize kernel object 149 // Iterate through each handle, synchronize kernel object
150 for (s32 i = 0; i < handle_count; i++) { 150 for (s32 i = 0; i < handle_count; i++) {
151 if (!Kernel::g_object_pool.IsValid(handles[i])) { 151 Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handles[i]);
152 if (object == nullptr)
152 return InvalidHandle(ErrorModule::Kernel).raw; 153 return InvalidHandle(ErrorModule::Kernel).raw;
153 }
154 Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handles[i]);
155 154
156 LOG_TRACE(Kernel_SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(), 155 LOG_TRACE(Kernel_SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(),
157 object->GetName().c_str()); 156 object->GetName().c_str());
@@ -288,6 +287,21 @@ static Result GetThreadId(u32* thread_id, Handle handle) {
288 return result.raw; 287 return result.raw;
289} 288}
290 289
290/// Creates a semaphore
291static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) {
292 ResultCode res = Kernel::CreateSemaphore(semaphore, initial_count, max_count);
293 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X",
294 initial_count, max_count, *semaphore);
295 return res.raw;
296}
297
298/// Releases a certain number of slots in a semaphore
299static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) {
300 LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore);
301 ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count);
302 return res.raw;
303}
304
291/// Query memory 305/// Query memory
292static Result QueryMemory(void* info, void* out, u32 addr) { 306static Result QueryMemory(void* info, void* out, u32 addr) {
293 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); 307 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr);
@@ -304,19 +318,12 @@ static Result CreateEvent(Handle* evt, u32 reset_type) {
304 318
305/// Duplicates a kernel handle 319/// Duplicates a kernel handle
306static Result DuplicateHandle(Handle* out, Handle handle) { 320static Result DuplicateHandle(Handle* out, Handle handle) {
307 LOG_WARNING(Kernel_SVC, "(STUBBED) called handle=0x%08X", handle); 321 ResultVal<Handle> out_h = Kernel::g_handle_table.Duplicate(handle);
308 322 if (out_h.Succeeded()) {
309 // Translate kernel handles -> real handles 323 *out = *out_h;
310 if (handle == Kernel::CurrentThread) { 324 LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out);
311 handle = Kernel::GetCurrentThreadHandle();
312 } 325 }
313 _assert_msg_(KERNEL, (handle != Kernel::CurrentProcess), 326 return out_h.Code().raw;
314 "(UNIMPLEMENTED) process handle duplication!");
315
316 // TODO(bunnei): FixMe - This is a hack to return the handle that we were asked to duplicate.
317 *out = handle;
318
319 return 0;
320} 327}
321 328
322/// Signals an event 329/// Signals an event
@@ -335,7 +342,8 @@ static Result ClearEvent(Handle evt) {
335static void SleepThread(s64 nanoseconds) { 342static void SleepThread(s64 nanoseconds) {
336 LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds); 343 LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds);
337 344
338 // Check for next thread to schedule 345 // Sleep current thread and check for next thread to schedule
346 Kernel::WaitCurrentThread(WAITTYPE_SLEEP);
339 HLE::Reschedule(__func__); 347 HLE::Reschedule(__func__);
340} 348}
341 349
@@ -366,8 +374,8 @@ const HLE::FunctionDef SVC_Table[] = {
366 {0x12, nullptr, "Run"}, 374 {0x12, nullptr, "Run"},
367 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"}, 375 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"},
368 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"}, 376 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"},
369 {0x15, nullptr, "CreateSemaphore"}, 377 {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"},
370 {0x16, nullptr, "ReleaseSemaphore"}, 378 {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"},
371 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"}, 379 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"},
372 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"}, 380 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"},
373 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"}, 381 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"},
diff --git a/src/core/hle/svc.h b/src/core/hle/svc.h
index 6be393d0b..ad780818e 100644
--- a/src/core/hle/svc.h
+++ b/src/core/hle/svc.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index da78b85e5..dd619cb16 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common_types.h" 5#include "common/common_types.h"
@@ -21,12 +21,14 @@ namespace GPU {
21 21
22Regs g_regs; 22Regs g_regs;
23 23
24u32 g_cur_line = 0; ///< Current vertical screen line 24bool g_skip_frame = false; ///< True if the current frame was skipped
25u64 g_last_line_ticks = 0; ///< CPU tick count from last vertical screen line
26u64 g_last_frame_ticks = 0; ///< CPU tick count from last frame
27 25
28static u32 kFrameCycles = 0; ///< 268MHz / 60 frames per second 26static u64 frame_ticks = 0; ///< 268MHz / gpu_refresh_rate frames per second
29static u32 kFrameTicks = 0; ///< Approximate number of instructions/frame 27static u64 line_ticks = 0; ///< Number of ticks for a screen line
28static u32 cur_line = 0; ///< Current screen line
29static u64 last_update_tick = 0; ///< CPU ticl count from last GPU update
30static u64 frame_count = 0; ///< Number of frames drawn
31static bool last_skip_frame = false; ///< True if the last frame was skipped
30 32
31template <typename T> 33template <typename T>
32inline void Read(T &var, const u32 raw_addr) { 34inline void Read(T &var, const u32 raw_addr) {
@@ -34,7 +36,7 @@ inline void Read(T &var, const u32 raw_addr) {
34 u32 index = addr / 4; 36 u32 index = addr / 4;
35 37
36 // Reads other than u32 are untested, so I'd rather have them abort than silently fail 38 // Reads other than u32 are untested, so I'd rather have them abort than silently fail
37 if (index >= Regs::NumIds() || !std::is_same<T,u32>::value) { 39 if (index >= Regs::NumIds() || !std::is_same<T, u32>::value) {
38 LOG_ERROR(HW_GPU, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr); 40 LOG_ERROR(HW_GPU, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr);
39 return; 41 return;
40 } 42 }
@@ -48,7 +50,7 @@ inline void Write(u32 addr, const T data) {
48 u32 index = addr / 4; 50 u32 index = addr / 4;
49 51
50 // Writes other than u32 are untested, so I'd rather have them abort than silently fail 52 // Writes other than u32 are untested, so I'd rather have them abort than silently fail
51 if (index >= Regs::NumIds() || !std::is_same<T,u32>::value) { 53 if (index >= Regs::NumIds() || !std::is_same<T, u32>::value) {
52 LOG_ERROR(HW_GPU, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr); 54 LOG_ERROR(HW_GPU, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr);
53 return; 55 return;
54 } 56 }
@@ -179,37 +181,41 @@ template void Write<u8>(u32 addr, const u8 data);
179/// Update hardware 181/// Update hardware
180void Update() { 182void Update() {
181 auto& framebuffer_top = g_regs.framebuffer_config[0]; 183 auto& framebuffer_top = g_regs.framebuffer_config[0];
182 u64 current_ticks = Core::g_app_core->GetTicks();
183
184 // Update the frame after a certain number of CPU ticks have elapsed. This assumes that the
185 // active frame in memory is always complete to render. There also may be issues with this
186 // becoming out-of-synch with GSP synchrinization code (as follows). At this time, this seems to
187 // be the most effective solution for both homebrew and retail applications. With retail, this
188 // could be moved below (and probably would guarantee more accurate synchronization). However,
189 // primitive homebrew relies on a vertical blank interrupt to happen inevitably (regardless of a
190 // threading reschedule).
191
192 if ((current_ticks - g_last_frame_ticks) > GPU::kFrameTicks) {
193 VideoCore::g_renderer->SwapBuffers();
194 g_last_frame_ticks = current_ticks;
195 }
196 184
197 // Synchronize GPU on a thread reschedule: Because we cannot accurately predict a vertical 185 // Synchronize GPU on a thread reschedule: Because we cannot accurately predict a vertical
198 // blank, we need to simulate it. Based on testing, it seems that retail applications work more 186 // blank, we need to simulate it. Based on testing, it seems that retail applications work more
199 // accurately when this is signalled between thread switches. 187 // accurately when this is signalled between thread switches.
200 188
201 if (HLE::g_reschedule) { 189 if (HLE::g_reschedule) {
190 u64 current_ticks = Core::g_app_core->GetTicks();
191 u32 num_lines = static_cast<u32>((current_ticks - last_update_tick) / line_ticks);
202 192
203 // Synchronize line... 193 // Synchronize line...
204 if ((current_ticks - g_last_line_ticks) >= GPU::kFrameTicks / framebuffer_top.height) { 194 if (num_lines > 0) {
205 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0); 195 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0);
206 g_cur_line++; 196 cur_line += num_lines;
207 g_last_line_ticks = current_ticks; 197 last_update_tick += (num_lines * line_ticks);
208 } 198 }
209 199
210 // Synchronize frame... 200 // Synchronize frame...
211 if (g_cur_line >= framebuffer_top.height) { 201 if (cur_line >= framebuffer_top.height) {
212 g_cur_line = 0; 202 cur_line = 0;
203 frame_count++;
204 last_skip_frame = g_skip_frame;
205 g_skip_frame = (frame_count & Settings::values.frame_skip) != 0;
206
207 // Swap buffers based on the frameskip mode, which is a little bit tricky. When
208 // a frame is being skipped, nothing is being rendered to the internal framebuffer(s).
209 // So, we should only swap frames if the last frame was rendered. The rules are:
210 // - If frameskip == 0 (disabled), always swap buffers
211 // - If frameskip == 1, swap buffers every other frame (starting from the first frame)
212 // - If frameskip > 1, swap buffers every frameskip^n frames (starting from the second frame)
213
214 if ((((Settings::values.frame_skip != 1) ^ last_skip_frame) && last_skip_frame != g_skip_frame) ||
215 Settings::values.frame_skip == 0) {
216 VideoCore::g_renderer->SwapBuffers();
217 }
218
213 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1); 219 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1);
214 } 220 }
215 } 221 }
@@ -217,12 +223,6 @@ void Update() {
217 223
218/// Initialize hardware 224/// Initialize hardware
219void Init() { 225void Init() {
220 kFrameCycles = 268123480 / Settings::values.gpu_refresh_rate;
221 kFrameTicks = kFrameCycles / 3;
222
223 g_cur_line = 0;
224 g_last_frame_ticks = g_last_line_ticks = Core::g_app_core->GetTicks();
225
226 auto& framebuffer_top = g_regs.framebuffer_config[0]; 226 auto& framebuffer_top = g_regs.framebuffer_config[0];
227 auto& framebuffer_sub = g_regs.framebuffer_config[1]; 227 auto& framebuffer_sub = g_regs.framebuffer_config[1];
228 228
@@ -251,6 +251,13 @@ void Init() {
251 framebuffer_sub.color_format = Regs::PixelFormat::RGB8; 251 framebuffer_sub.color_format = Regs::PixelFormat::RGB8;
252 framebuffer_sub.active_fb = 0; 252 framebuffer_sub.active_fb = 0;
253 253
254 frame_ticks = 268123480 / Settings::values.gpu_refresh_rate;
255 line_ticks = (GPU::frame_ticks / framebuffer_top.height);
256 cur_line = 0;
257 last_update_tick = Core::g_app_core->GetTicks();
258 last_skip_frame = false;
259 g_skip_frame = false;
260
254 LOG_DEBUG(HW_GPU, "initialized OK"); 261 LOG_DEBUG(HW_GPU, "initialized OK");
255} 262}
256 263
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h
index 86cd5e680..292f496c1 100644
--- a/src/core/hw/gpu.h
+++ b/src/core/hw/gpu.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -241,6 +241,7 @@ ASSERT_REG_POSITION(command_processor_config, 0x00638);
241static_assert(sizeof(Regs) == 0x1000 * sizeof(u32), "Invalid total size of register set"); 241static_assert(sizeof(Regs) == 0x1000 * sizeof(u32), "Invalid total size of register set");
242 242
243extern Regs g_regs; 243extern Regs g_regs;
244extern bool g_skip_frame;
244 245
245template <typename T> 246template <typename T>
246void Read(T &var, const u32 addr); 247void Read(T &var, const u32 addr);
diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp
index af42b41fb..848ab5348 100644
--- a/src/core/hw/hw.cpp
+++ b/src/core/hw/hw.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common_types.h" 5#include "common/common_types.h"
diff --git a/src/core/hw/hw.h b/src/core/hw/hw.h
index 1055ed94f..991c0a07d 100644
--- a/src/core/hw/hw.h
+++ b/src/core/hw/hw.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
index f48d13530..4d072871a 100644
--- a/src/core/loader/3dsx.cpp
+++ b/src/core/loader/3dsx.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2+ 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
@@ -8,7 +8,7 @@
8#include "core/file_sys/archive_romfs.h" 8#include "core/file_sys/archive_romfs.h"
9#include "core/loader/elf.h" 9#include "core/loader/elf.h"
10#include "core/loader/ncch.h" 10#include "core/loader/ncch.h"
11#include "core/hle/kernel/archive.h" 11#include "core/hle/service/fs/archive.h"
12#include "core/mem_map.h" 12#include "core/mem_map.h"
13 13
14#include "3dsx.h" 14#include "3dsx.h"
@@ -223,9 +223,7 @@ int THREEDSXReader::Load3DSXFile(const std::string& filename, u32 base_addr)
223 LOG_INFO(Loader, "Loading 3DSX file %s...", filename.c_str()); 223 LOG_INFO(Loader, "Loading 3DSX file %s...", filename.c_str());
224 FileUtil::IOFile file(filename, "rb"); 224 FileUtil::IOFile file(filename, "rb");
225 if (file.IsOpen()) { 225 if (file.IsOpen()) {
226 226 THREEDSXReader::Load3DSXFile(filename, 0x00100000);
227 THREEDSXReader reader;
228 reader.Load3DSXFile(filename, 0x00100000);
229 Kernel::LoadExec(0x00100000); 227 Kernel::LoadExec(0x00100000);
230 } else { 228 } else {
231 return ResultStatus::Error; 229 return ResultStatus::Error;
diff --git a/src/core/loader/3dsx.h b/src/core/loader/3dsx.h
index 848d3ef8a..da8836662 100644
--- a/src/core/loader/3dsx.h
+++ b/src/core/loader/3dsx.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Dolphin Emulator Project / Citra Emulator Project 1// Copyright 2014 Dolphin Emulator Project / Citra Emulator Project
2// Licensed under GPLv2+ 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index c95882f4a..354335014 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <string> 5#include <string>
diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h
index 5ae88439a..c221cce6d 100644
--- a/src/core/loader/elf.h
+++ b/src/core/loader/elf.h
@@ -1,5 +1,5 @@
1// Copyright 2013 Dolphin Emulator Project / Citra Emulator Project 1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 3883e1307..87580cb2a 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -1,14 +1,16 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory> 5#include <string>
6
7#include "common/make_unique.h"
6 8
7#include "core/file_sys/archive_romfs.h" 9#include "core/file_sys/archive_romfs.h"
8#include "core/loader/3dsx.h" 10#include "core/loader/3dsx.h"
9#include "core/loader/elf.h" 11#include "core/loader/elf.h"
10#include "core/loader/ncch.h" 12#include "core/loader/ncch.h"
11#include "core/hle/kernel/archive.h" 13#include "core/hle/service/fs/archive.h"
12#include "core/mem_map.h" 14#include "core/mem_map.h"
13 15
14//////////////////////////////////////////////////////////////////////////////////////////////////// 16////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -74,7 +76,8 @@ ResultStatus LoadFile(const std::string& filename) {
74 76
75 // Load application and RomFS 77 // Load application and RomFS
76 if (ResultStatus::Success == app_loader.Load()) { 78 if (ResultStatus::Success == app_loader.Load()) {
77 Kernel::CreateArchive(new FileSys::Archive_RomFS(app_loader), "RomFS"); 79 Kernel::g_program_id = app_loader.GetProgramId();
80 Service::FS::CreateArchive(Common::make_unique<FileSys::Archive_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS);
78 return ResultStatus::Success; 81 return ResultStatus::Success;
79 } 82 }
80 break; 83 break;
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index 0f836d285..ec5534d41 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index ba9ba00c0..0dc21699e 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory> 5#include <memory>
@@ -315,4 +315,8 @@ ResultStatus AppLoader_NCCH::ReadRomFS(std::vector<u8>& buffer) const {
315 return ResultStatus::Error; 315 return ResultStatus::Error;
316} 316}
317 317
318u64 AppLoader_NCCH::GetProgramId() const {
319 return *reinterpret_cast<u64 const*>(&ncch_header.program_id[0]);
320}
321
318} // namespace Loader 322} // namespace Loader
diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h
index 03116add8..fd9258970 100644
--- a/src/core/loader/ncch.h
+++ b/src/core/loader/ncch.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -191,6 +191,12 @@ public:
191 */ 191 */
192 ResultStatus ReadRomFS(std::vector<u8>& buffer) const override; 192 ResultStatus ReadRomFS(std::vector<u8>& buffer) const override;
193 193
194 /*
195 * Gets the program id from the NCCH header
196 * @return u64 Program id
197 */
198 u64 GetProgramId() const;
199
194private: 200private:
195 201
196 /** 202 /**
diff --git a/src/core/mem_map.cpp b/src/core/mem_map.cpp
index d1c44ed24..eea6c5bf1 100644
--- a/src/core/mem_map.cpp
+++ b/src/core/mem_map.cpp
@@ -1,5 +1,5 @@
1 // Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common.h" 5#include "common/common.h"
diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index 4d47fc171..a2ef9d3af 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index d8720990e..fdf382ed6 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <map> 5#include <map>
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index c486f6274..8a14f75aa 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "settings.h" 5#include "settings.h"
diff --git a/src/core/settings.h b/src/core/settings.h
index 138ffc615..4b8928847 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -31,6 +31,7 @@ struct Values {
31 // Core 31 // Core
32 int cpu_core; 32 int cpu_core;
33 int gpu_refresh_rate; 33 int gpu_refresh_rate;
34 int frame_skip;
34 35
35 // Data Storage 36 // Data Storage
36 bool use_virtual_sd; 37 bool use_virtual_sd;
diff --git a/src/core/system.cpp b/src/core/system.cpp
index 43d0eef2c..d6188f055 100644
--- a/src/core/system.cpp
+++ b/src/core/system.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/core.h" 5#include "core/core.h"
@@ -23,10 +23,10 @@ void Init(EmuWindow* emu_window) {
23 Core::Init(); 23 Core::Init();
24 Memory::Init(); 24 Memory::Init();
25 HW::Init(); 25 HW::Init();
26 Kernel::Init();
26 HLE::Init(); 27 HLE::Init();
27 CoreTiming::Init(); 28 CoreTiming::Init();
28 VideoCore::Init(emu_window); 29 VideoCore::Init(emu_window);
29 Kernel::Init();
30} 30}
31 31
32void RunLoopFor(int cycles) { 32void RunLoopFor(int cycles) {
@@ -37,13 +37,13 @@ void RunLoopUntil(u64 global_cycles) {
37} 37}
38 38
39void Shutdown() { 39void Shutdown() {
40 Core::Shutdown();
41 Memory::Shutdown();
42 HW::Shutdown();
43 HLE::Shutdown();
44 CoreTiming::Shutdown();
45 VideoCore::Shutdown(); 40 VideoCore::Shutdown();
41 CoreTiming::Shutdown();
42 HLE::Shutdown();
46 Kernel::Shutdown(); 43 Kernel::Shutdown();
44 HW::Shutdown();
45 Memory::Shutdown();
46 Core::Shutdown();
47} 47}
48 48
49} // namespace 49} // namespace
diff --git a/src/core/system.h b/src/core/system.h
index 2bc2edc75..05d836530 100644
--- a/src/core/system.h
+++ b/src/core/system.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/video_core/clipper.cpp b/src/video_core/clipper.cpp
index 632fb959a..1744066ba 100644
--- a/src/video_core/clipper.cpp
+++ b/src/video_core/clipper.cpp
@@ -1,8 +1,8 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <vector> 5#include <boost/container/static_vector.hpp>
6 6
7#include "clipper.h" 7#include "clipper.h"
8#include "pica.h" 8#include "pica.h"
@@ -91,25 +91,31 @@ static void InitScreenCoordinates(OutputVertex& vtx)
91 viewport.zscale = float24::FromRawFloat24(registers.viewport_depth_range); 91 viewport.zscale = float24::FromRawFloat24(registers.viewport_depth_range);
92 viewport.offset_z = float24::FromRawFloat24(registers.viewport_depth_far_plane); 92 viewport.offset_z = float24::FromRawFloat24(registers.viewport_depth_far_plane);
93 93
94 float24 inv_w = float24::FromFloat32(1.f) / vtx.pos.w;
95 vtx.color *= inv_w;
96 vtx.tc0 *= inv_w;
97 vtx.tc1 *= inv_w;
98 vtx.tc2 *= inv_w;
99 vtx.pos.w = inv_w;
100
94 // TODO: Not sure why the viewport width needs to be divided by 2 but the viewport height does not 101 // TODO: Not sure why the viewport width needs to be divided by 2 but the viewport height does not
95 vtx.screenpos[0] = (vtx.pos.x / vtx.pos.w + float24::FromFloat32(1.0)) * viewport.halfsize_x + viewport.offset_x; 102 vtx.screenpos[0] = (vtx.pos.x * inv_w + float24::FromFloat32(1.0)) * viewport.halfsize_x + viewport.offset_x;
96 vtx.screenpos[1] = (vtx.pos.y / vtx.pos.w + float24::FromFloat32(1.0)) * viewport.halfsize_y + viewport.offset_y; 103 vtx.screenpos[1] = (vtx.pos.y * inv_w + float24::FromFloat32(1.0)) * viewport.halfsize_y + viewport.offset_y;
97 vtx.screenpos[2] = viewport.offset_z - vtx.pos.z / vtx.pos.w * viewport.zscale; 104 vtx.screenpos[2] = viewport.offset_z - vtx.pos.z * inv_w * viewport.zscale;
98} 105}
99 106
100void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) { 107void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) {
101 108 using boost::container::static_vector;
102 // TODO (neobrain): 109
103 // The list of output vertices has some fixed maximum size, 110 // Clipping a planar n-gon against a plane will remove at least 1 vertex and introduces 2 at
104 // however I haven't taken the time to figure out what it is exactly. 111 // the new edge (or less in degenerate cases). As such, we can say that each clipping plane
105 // For now, we hence just assume a maximal size of 1000 vertices. 112 // introduces at most 1 new vertex to the polygon. Since we start with a triangle and have a
106 const size_t max_vertices = 1000; 113 // fixed 6 clipping planes, the maximum number of vertices of the clipped polygon is 3 + 6 = 9.
107 std::vector<OutputVertex> buffer_vertices; 114 static const size_t MAX_VERTICES = 9;
108 std::vector<OutputVertex*> output_list{ &v0, &v1, &v2 }; 115 static_vector<OutputVertex, MAX_VERTICES> buffer_a = { v0, v1, v2 };
109 116 static_vector<OutputVertex, MAX_VERTICES> buffer_b;
110 // Make sure to reserve space for all vertices. 117 auto* output_list = &buffer_a;
111 // Without this, buffer reallocation would invalidate references. 118 auto* input_list = &buffer_b;
112 buffer_vertices.reserve(max_vertices);
113 119
114 // Simple implementation of the Sutherland-Hodgman clipping algorithm. 120 // Simple implementation of the Sutherland-Hodgman clipping algorithm.
115 // TODO: Make this less inefficient (currently lots of useless buffering overhead happens here) 121 // TODO: Make this less inefficient (currently lots of useless buffering overhead happens here)
@@ -120,48 +126,45 @@ void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) {
120 ClippingEdge(ClippingEdge::POS_Z, float24::FromFloat32(+1.0)), 126 ClippingEdge(ClippingEdge::POS_Z, float24::FromFloat32(+1.0)),
121 ClippingEdge(ClippingEdge::NEG_Z, float24::FromFloat32(-1.0)) }) { 127 ClippingEdge(ClippingEdge::NEG_Z, float24::FromFloat32(-1.0)) }) {
122 128
123 const std::vector<OutputVertex*> input_list = output_list; 129 std::swap(input_list, output_list);
124 output_list.clear(); 130 output_list->clear();
125 131
126 const OutputVertex* reference_vertex = input_list.back(); 132 const OutputVertex* reference_vertex = &input_list->back();
127 133
128 for (const auto& vertex : input_list) { 134 for (const auto& vertex : *input_list) {
129 // NOTE: This algorithm changes vertex order in some cases! 135 // NOTE: This algorithm changes vertex order in some cases!
130 if (edge.IsInside(*vertex)) { 136 if (edge.IsInside(vertex)) {
131 if (edge.IsOutSide(*reference_vertex)) { 137 if (edge.IsOutSide(*reference_vertex)) {
132 buffer_vertices.push_back(edge.GetIntersection(*vertex, *reference_vertex)); 138 output_list->push_back(edge.GetIntersection(vertex, *reference_vertex));
133 output_list.push_back(&(buffer_vertices.back()));
134 } 139 }
135 140
136 output_list.push_back(vertex); 141 output_list->push_back(vertex);
137 } else if (edge.IsInside(*reference_vertex)) { 142 } else if (edge.IsInside(*reference_vertex)) {
138 buffer_vertices.push_back(edge.GetIntersection(*vertex, *reference_vertex)); 143 output_list->push_back(edge.GetIntersection(vertex, *reference_vertex));
139 output_list.push_back(&(buffer_vertices.back()));
140 } 144 }
141 145 reference_vertex = &vertex;
142 reference_vertex = vertex;
143 } 146 }
144 147
145 // Need to have at least a full triangle to continue... 148 // Need to have at least a full triangle to continue...
146 if (output_list.size() < 3) 149 if (output_list->size() < 3)
147 return; 150 return;
148 } 151 }
149 152
150 InitScreenCoordinates(*(output_list[0])); 153 InitScreenCoordinates((*output_list)[0]);
151 InitScreenCoordinates(*(output_list[1])); 154 InitScreenCoordinates((*output_list)[1]);
152 155
153 for (size_t i = 0; i < output_list.size() - 2; i ++) { 156 for (size_t i = 0; i < output_list->size() - 2; i ++) {
154 OutputVertex& vtx0 = *(output_list[0]); 157 OutputVertex& vtx0 = (*output_list)[0];
155 OutputVertex& vtx1 = *(output_list[i+1]); 158 OutputVertex& vtx1 = (*output_list)[i+1];
156 OutputVertex& vtx2 = *(output_list[i+2]); 159 OutputVertex& vtx2 = (*output_list)[i+2];
157 160
158 InitScreenCoordinates(vtx2); 161 InitScreenCoordinates(vtx2);
159 162
160 LOG_TRACE(Render_Software, 163 LOG_TRACE(Render_Software,
161 "Triangle %lu/%lu (%lu buffer vertices) at position (%.3f, %.3f, %.3f, %.3f), " 164 "Triangle %lu/%lu at position (%.3f, %.3f, %.3f, %.3f), "
162 "(%.3f, %.3f, %.3f, %.3f), (%.3f, %.3f, %.3f, %.3f) and " 165 "(%.3f, %.3f, %.3f, %.3f), (%.3f, %.3f, %.3f, %.3f) and "
163 "screen position (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f)", 166 "screen position (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f)",
164 i,output_list.size(), buffer_vertices.size(), 167 i, output_list->size(),
165 vtx0.pos.x.ToFloat32(), vtx0.pos.y.ToFloat32(), vtx0.pos.z.ToFloat32(), vtx0.pos.w.ToFloat32(), 168 vtx0.pos.x.ToFloat32(), vtx0.pos.y.ToFloat32(), vtx0.pos.z.ToFloat32(), vtx0.pos.w.ToFloat32(),
166 vtx1.pos.x.ToFloat32(), vtx1.pos.y.ToFloat32(), vtx1.pos.z.ToFloat32(), vtx1.pos.w.ToFloat32(), 169 vtx1.pos.x.ToFloat32(), vtx1.pos.y.ToFloat32(), vtx1.pos.z.ToFloat32(), vtx1.pos.w.ToFloat32(),
167 vtx2.pos.x.ToFloat32(), vtx2.pos.y.ToFloat32(), vtx2.pos.z.ToFloat32(), vtx2.pos.w.ToFloat32(), 170 vtx2.pos.x.ToFloat32(), vtx2.pos.y.ToFloat32(), vtx2.pos.z.ToFloat32(), vtx2.pos.w.ToFloat32(),
diff --git a/src/video_core/clipper.h b/src/video_core/clipper.h
index 14d31ca1e..19ce8e140 100644
--- a/src/video_core/clipper.h
+++ b/src/video_core/clipper.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index b74cd3261..9602779f4 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "clipper.h" 5#include "clipper.h"
@@ -9,6 +9,7 @@
9#include "primitive_assembly.h" 9#include "primitive_assembly.h"
10#include "vertex_shader.h" 10#include "vertex_shader.h"
11#include "core/hle/service/gsp_gpu.h" 11#include "core/hle/service/gsp_gpu.h"
12#include "core/hw/gpu.h"
12 13
13#include "debug_utils/debug_utils.h" 14#include "debug_utils/debug_utils.h"
14 15
@@ -31,6 +32,10 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
31 if (id >= registers.NumIds()) 32 if (id >= registers.NumIds())
32 return; 33 return;
33 34
35 // If we're skipping this frame, only allow trigger IRQ
36 if (GPU::g_skip_frame && id != PICA_REG_INDEX(trigger_irq))
37 return;
38
34 // TODO: Figure out how register masking acts on e.g. vs_uniform_setup.set_value 39 // TODO: Figure out how register masking acts on e.g. vs_uniform_setup.set_value
35 u32 old_value = registers[id]; 40 u32 old_value = registers[id];
36 registers[id] = (old_value & ~mask) | (value & mask); 41 registers[id] = (old_value & ~mask) | (value & mask);
@@ -56,10 +61,11 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
56 g_debug_context->OnEvent(DebugContext::Event::IncomingPrimitiveBatch, nullptr); 61 g_debug_context->OnEvent(DebugContext::Event::IncomingPrimitiveBatch, nullptr);
57 62
58 const auto& attribute_config = registers.vertex_attributes; 63 const auto& attribute_config = registers.vertex_attributes;
59 const u8* const base_address = Memory::GetPointer(attribute_config.GetBaseAddress()); 64 const u32 base_address = attribute_config.GetPhysicalBaseAddress();
60 65
61 // Information about internal vertex attributes 66 // Information about internal vertex attributes
62 const u8* vertex_attribute_sources[16]; 67 u32 vertex_attribute_sources[16];
68 std::fill(vertex_attribute_sources, &vertex_attribute_sources[16], 0xdeadbeef);
63 u32 vertex_attribute_strides[16]; 69 u32 vertex_attribute_strides[16];
64 u32 vertex_attribute_formats[16]; 70 u32 vertex_attribute_formats[16];
65 u32 vertex_attribute_elements[16]; 71 u32 vertex_attribute_elements[16];
@@ -69,7 +75,7 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
69 for (int loader = 0; loader < 12; ++loader) { 75 for (int loader = 0; loader < 12; ++loader) {
70 const auto& loader_config = attribute_config.attribute_loaders[loader]; 76 const auto& loader_config = attribute_config.attribute_loaders[loader];
71 77
72 const u8* load_address = base_address + loader_config.data_offset; 78 u32 load_address = base_address + loader_config.data_offset;
73 79
74 // TODO: What happens if a loader overwrites a previous one's data? 80 // TODO: What happens if a loader overwrites a previous one's data?
75 for (unsigned component = 0; component < loader_config.component_count; ++component) { 81 for (unsigned component = 0; component < loader_config.component_count; ++component) {
@@ -87,9 +93,9 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
87 bool is_indexed = (id == PICA_REG_INDEX(trigger_draw_indexed)); 93 bool is_indexed = (id == PICA_REG_INDEX(trigger_draw_indexed));
88 94
89 const auto& index_info = registers.index_array; 95 const auto& index_info = registers.index_array;
90 const u8* index_address_8 = (u8*)base_address + index_info.offset; 96 const u8* index_address_8 = Memory::GetPointer(PAddrToVAddr(base_address + index_info.offset));
91 const u16* index_address_16 = (u16*)index_address_8; 97 const u16* index_address_16 = (u16*)index_address_8;
92 bool index_u16 = (bool)index_info.format; 98 bool index_u16 = index_info.format != 0;
93 99
94 DebugUtils::GeometryDumper geometry_dumper; 100 DebugUtils::GeometryDumper geometry_dumper;
95 PrimitiveAssembler<VertexShader::OutputVertex> clipper_primitive_assembler(registers.triangle_topology.Value()); 101 PrimitiveAssembler<VertexShader::OutputVertex> clipper_primitive_assembler(registers.triangle_topology.Value());
@@ -108,7 +114,14 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
108 114
109 for (int i = 0; i < attribute_config.GetNumTotalAttributes(); ++i) { 115 for (int i = 0; i < attribute_config.GetNumTotalAttributes(); ++i) {
110 for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) { 116 for (unsigned int comp = 0; comp < vertex_attribute_elements[i]; ++comp) {
111 const u8* srcdata = vertex_attribute_sources[i] + vertex_attribute_strides[i] * vertex + comp * vertex_attribute_element_size[i]; 117 const u8* srcdata = Memory::GetPointer(PAddrToVAddr(vertex_attribute_sources[i] + vertex_attribute_strides[i] * vertex + comp * vertex_attribute_element_size[i]));
118
119 // TODO(neobrain): Ocarina of Time 3D has GetNumTotalAttributes return 8,
120 // yet only provides 2 valid source data addresses. Need to figure out
121 // what's wrong there, until then we just continue when address lookup fails
122 if (srcdata == nullptr)
123 continue;
124
112 const float srcval = (vertex_attribute_formats[i] == 0) ? *(s8*)srcdata : 125 const float srcval = (vertex_attribute_formats[i] == 0) ? *(s8*)srcdata :
113 (vertex_attribute_formats[i] == 1) ? *(u8*)srcdata : 126 (vertex_attribute_formats[i] == 1) ? *(u8*)srcdata :
114 (vertex_attribute_formats[i] == 2) ? *(s16*)srcdata : 127 (vertex_attribute_formats[i] == 2) ? *(s16*)srcdata :
@@ -116,13 +129,16 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
116 input.attr[i][comp] = float24::FromFloat32(srcval); 129 input.attr[i][comp] = float24::FromFloat32(srcval);
117 LOG_TRACE(HW_GPU, "Loaded component %x of attribute %x for vertex %x (index %x) from 0x%08x + 0x%08lx + 0x%04lx: %f", 130 LOG_TRACE(HW_GPU, "Loaded component %x of attribute %x for vertex %x (index %x) from 0x%08x + 0x%08lx + 0x%04lx: %f",
118 comp, i, vertex, index, 131 comp, i, vertex, index,
119 attribute_config.GetBaseAddress(), 132 attribute_config.GetPhysicalBaseAddress(),
120 vertex_attribute_sources[i] - base_address, 133 vertex_attribute_sources[i] - base_address,
121 srcdata - vertex_attribute_sources[i], 134 vertex_attribute_strides[i] * vertex + comp * vertex_attribute_element_size[i],
122 input.attr[i][comp].ToFloat32()); 135 input.attr[i][comp].ToFloat32());
123 } 136 }
124 } 137 }
125 138
139 if (g_debug_context)
140 g_debug_context->OnEvent(DebugContext::Event::VertexLoaded, (void*)&input);
141
126 // NOTE: When dumping geometry, we simply assume that the first input attribute 142 // NOTE: When dumping geometry, we simply assume that the first input attribute
127 // corresponds to the position for now. 143 // corresponds to the position for now.
128 DebugUtils::GeometryDumper::Vertex dumped_vertex = { 144 DebugUtils::GeometryDumper::Vertex dumped_vertex = {
@@ -151,6 +167,12 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
151 break; 167 break;
152 } 168 }
153 169
170 case PICA_REG_INDEX(vs_bool_uniforms):
171 for (unsigned i = 0; i < 16; ++i)
172 VertexShader::GetBoolUniform(i) = (registers.vs_bool_uniforms.Value() & (1 << i)) != 0;
173
174 break;
175
154 case PICA_REG_INDEX_WORKAROUND(vs_uniform_setup.set_value[0], 0x2c1): 176 case PICA_REG_INDEX_WORKAROUND(vs_uniform_setup.set_value[0], 0x2c1):
155 case PICA_REG_INDEX_WORKAROUND(vs_uniform_setup.set_value[1], 0x2c2): 177 case PICA_REG_INDEX_WORKAROUND(vs_uniform_setup.set_value[1], 0x2c2):
156 case PICA_REG_INDEX_WORKAROUND(vs_uniform_setup.set_value[2], 0x2c3): 178 case PICA_REG_INDEX_WORKAROUND(vs_uniform_setup.set_value[2], 0x2c3):
diff --git a/src/video_core/command_processor.h b/src/video_core/command_processor.h
index 955f9daec..bb3d4150f 100644
--- a/src/video_core/command_processor.h
+++ b/src/video_core/command_processor.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index 1a20f19ec..5921185a6 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -14,6 +14,8 @@
14#include <png.h> 14#include <png.h>
15#endif 15#endif
16 16
17#include <nihstro/shader_binary.h>
18
17#include "common/log.h" 19#include "common/log.h"
18#include "common/file_util.h" 20#include "common/file_util.h"
19 21
@@ -22,6 +24,10 @@
22 24
23#include "debug_utils.h" 25#include "debug_utils.h"
24 26
27using nihstro::DVLBHeader;
28using nihstro::DVLEHeader;
29using nihstro::DVLPHeader;
30
25namespace Pica { 31namespace Pica {
26 32
27void DebugContext::OnEvent(Event event, void* data) { 33void DebugContext::OnEvent(Event event, void* data) {
@@ -98,65 +104,6 @@ void GeometryDumper::Dump() {
98 } 104 }
99} 105}
100 106
101#pragma pack(1)
102struct DVLBHeader {
103 enum : u32 {
104 MAGIC_WORD = 0x424C5644, // "DVLB"
105 };
106
107 u32 magic_word;
108 u32 num_programs;
109// u32 dvle_offset_table[];
110};
111static_assert(sizeof(DVLBHeader) == 0x8, "Incorrect structure size");
112
113struct DVLPHeader {
114 enum : u32 {
115 MAGIC_WORD = 0x504C5644, // "DVLP"
116 };
117
118 u32 magic_word;
119 u32 version;
120 u32 binary_offset; // relative to DVLP start
121 u32 binary_size_words;
122 u32 swizzle_patterns_offset;
123 u32 swizzle_patterns_num_entries;
124 u32 unk2;
125};
126static_assert(sizeof(DVLPHeader) == 0x1C, "Incorrect structure size");
127
128struct DVLEHeader {
129 enum : u32 {
130 MAGIC_WORD = 0x454c5644, // "DVLE"
131 };
132
133 enum class ShaderType : u8 {
134 VERTEX = 0,
135 GEOMETRY = 1,
136 };
137
138 u32 magic_word;
139 u16 pad1;
140 ShaderType type;
141 u8 pad2;
142 u32 main_offset_words; // offset within binary blob
143 u32 endmain_offset_words;
144 u32 pad3;
145 u32 pad4;
146 u32 constant_table_offset;
147 u32 constant_table_size; // number of entries
148 u32 label_table_offset;
149 u32 label_table_size;
150 u32 output_register_table_offset;
151 u32 output_register_table_size;
152 u32 uniform_table_offset;
153 u32 uniform_table_size;
154 u32 symbol_table_offset;
155 u32 symbol_table_size;
156
157};
158static_assert(sizeof(DVLEHeader) == 0x40, "Incorrect structure size");
159#pragma pack()
160 107
161void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data, u32 swizzle_size, 108void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data, u32 swizzle_size,
162 u32 main_offset, const Regs::VSOutputAttributes* output_attributes) 109 u32 main_offset, const Regs::VSOutputAttributes* output_attributes)
@@ -276,8 +223,8 @@ void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data
276 dvlp.binary_size_words = binary_size; 223 dvlp.binary_size_words = binary_size;
277 QueueForWriting((u8*)binary_data, binary_size * sizeof(u32)); 224 QueueForWriting((u8*)binary_data, binary_size * sizeof(u32));
278 225
279 dvlp.swizzle_patterns_offset = write_offset - dvlp_offset; 226 dvlp.swizzle_info_offset = write_offset - dvlp_offset;
280 dvlp.swizzle_patterns_num_entries = swizzle_size; 227 dvlp.swizzle_info_num_entries = swizzle_size;
281 u32 dummy = 0; 228 u32 dummy = 0;
282 for (unsigned int i = 0; i < swizzle_size; ++i) { 229 for (unsigned int i = 0; i < swizzle_size; ++i) {
283 QueueForWriting((u8*)&swizzle_data[i], sizeof(swizzle_data[i])); 230 QueueForWriting((u8*)&swizzle_data[i], sizeof(swizzle_data[i]));
@@ -356,39 +303,170 @@ std::unique_ptr<PicaTrace> FinishPicaTracing()
356 return std::move(ret); 303 return std::move(ret);
357} 304}
358 305
359const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info) { 306const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info, bool disable_alpha) {
360 _dbg_assert_(Debug_GPU, info.format == Pica::Regs::TextureFormat::RGB8); 307 // Images are split into 8x8 tiles. Each tile is composed of four 4x4 subtiles each
308 // of which is composed of four 2x2 subtiles each of which is composed of four texels.
309 // Each structure is embedded into the next-bigger one in a diagonal pattern, e.g.
310 // texels are laid out in a 2x2 subtile like this:
311 // 2 3
312 // 0 1
313 //
314 // The full 8x8 tile has the texels arranged like this:
315 //
316 // 42 43 46 47 58 59 62 63
317 // 40 41 44 45 56 57 60 61
318 // 34 35 38 39 50 51 54 55
319 // 32 33 36 37 48 49 52 53
320 // 10 11 14 15 26 27 30 31
321 // 08 09 12 13 24 25 28 29
322 // 02 03 06 07 18 19 22 23
323 // 00 01 04 05 16 17 20 21
324
325 const unsigned int block_width = 8;
326 const unsigned int block_height = 8;
327
328 const unsigned int coarse_x = x & ~7;
329 const unsigned int coarse_y = y & ~7;
330
331 // Interleave the lower 3 bits of each coordinate to get the intra-block offsets, which are
332 // arranged in a Z-order curve. More details on the bit manipulation at:
333 // https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
334 unsigned int i = (x | (y << 8)) & 0x0707; // ---- -210
335 i = (i ^ (i << 2)) & 0x1313; // ---2 --10
336 i = (i ^ (i << 1)) & 0x1515; // ---2 -1-0
337 i = (i | (i >> 7)) & 0x3F;
338
339 source += coarse_y * info.stride;
340 const unsigned int offset = coarse_x * block_height + i;
341
342 switch (info.format) {
343 case Regs::TextureFormat::RGBA8:
344 {
345 const u8* source_ptr = source + offset * 4;
346 return { source_ptr[3], source_ptr[2], source_ptr[1], disable_alpha ? (u8)255 : source_ptr[0] };
347 }
348
349 case Regs::TextureFormat::RGB8:
350 {
351 const u8* source_ptr = source + offset * 3;
352 return { source_ptr[2], source_ptr[1], source_ptr[0], 255 };
353 }
354
355 case Regs::TextureFormat::RGBA5551:
356 {
357 const u16 source_ptr = *(const u16*)(source + offset * 2);
358 u8 r = (source_ptr >> 11) & 0x1F;
359 u8 g = ((source_ptr) >> 6) & 0x1F;
360 u8 b = (source_ptr >> 1) & 0x1F;
361 u8 a = source_ptr & 1;
362 return Math::MakeVec<u8>((r << 3) | (r >> 2), (g << 3) | (g >> 2), (b << 3) | (b >> 2), disable_alpha ? 255 : (a * 255));
363 }
364
365 case Regs::TextureFormat::RGB565:
366 {
367 const u16 source_ptr = *(const u16*)(source + offset * 2);
368 u8 r = (source_ptr >> 11) & 0x1F;
369 u8 g = ((source_ptr) >> 5) & 0x3F;
370 u8 b = (source_ptr) & 0x1F;
371 return Math::MakeVec<u8>((r << 3) | (r >> 2), (g << 2) | (g >> 4), (b << 3) | (b >> 2), 255);
372 }
373
374 case Regs::TextureFormat::RGBA4:
375 {
376 const u8* source_ptr = source + offset * 2;
377 u8 r = source_ptr[1] >> 4;
378 u8 g = source_ptr[1] & 0xFF;
379 u8 b = source_ptr[0] >> 4;
380 u8 a = source_ptr[0] & 0xFF;
381 r = (r << 4) | r;
382 g = (g << 4) | g;
383 b = (b << 4) | b;
384 a = (a << 4) | a;
385 return { r, g, b, disable_alpha ? (u8)255 : a };
386 }
387
388 case Regs::TextureFormat::IA8:
389 {
390 const u8* source_ptr = source + offset * 2;
361 391
362 // Cf. rasterizer code for an explanation of this algorithm. 392 // TODO: component order not verified
363 int texel_index_within_tile = 0;
364 for (int block_size_index = 0; block_size_index < 3; ++block_size_index) {
365 int sub_tile_width = 1 << block_size_index;
366 int sub_tile_height = 1 << block_size_index;
367 393
368 int sub_tile_index = (x & sub_tile_width) << block_size_index; 394 if (disable_alpha) {
369 sub_tile_index += 2 * ((y & sub_tile_height) << block_size_index); 395 // Show intensity as red, alpha as green
370 texel_index_within_tile += sub_tile_index; 396 return { source_ptr[0], source_ptr[1], 0, 255 };
397 } else {
398 return { source_ptr[0], source_ptr[0], source_ptr[0], source_ptr[1]};
399 }
371 } 400 }
372 401
373 const int block_width = 8; 402 case Regs::TextureFormat::I8:
374 const int block_height = 8; 403 {
404 const u8* source_ptr = source + offset;
405 return { *source_ptr, *source_ptr, *source_ptr, 255 };
406 }
407
408 case Regs::TextureFormat::A8:
409 {
410 const u8* source_ptr = source + offset;
411
412 if (disable_alpha) {
413 return { *source_ptr, *source_ptr, *source_ptr, 255 };
414 } else {
415 return { 0, 0, 0, *source_ptr };
416 }
417 }
418
419 case Regs::TextureFormat::IA4:
420 {
421 const u8* source_ptr = source + offset / 2;
422
423 // TODO: component order not verified
375 424
376 int coarse_x = (x / block_width) * block_width; 425 u8 i = (*source_ptr) & 0xF;
377 int coarse_y = (y / block_height) * block_height; 426 u8 a = ((*source_ptr) & 0xF0) >> 4;
427 a |= a << 4;
428 i |= i << 4;
378 429
379 const u8* source_ptr = source + coarse_x * block_height * 3 + coarse_y * info.stride + texel_index_within_tile * 3; 430 if (disable_alpha) {
380 return { source_ptr[2], source_ptr[1], source_ptr[0], 255 }; 431 // Show intensity as red, alpha as green
432 return { i, a, 0, 255 };
433 } else {
434 return { i, i, i, a };
435 }
436 }
437
438 case Regs::TextureFormat::A4:
439 {
440 const u8* source_ptr = source + offset / 2;
441
442 // TODO: component order not verified
443
444 u8 a = (coarse_x % 2) ? ((*source_ptr)&0xF) : (((*source_ptr) & 0xF0) >> 4);
445 a |= a << 4;
446
447 if (disable_alpha) {
448 return { *source_ptr, *source_ptr, *source_ptr, 255 };
449 } else {
450 return { 0, 0, 0, *source_ptr };
451 }
452 }
453
454 default:
455 LOG_ERROR(HW_GPU, "Unknown texture format: %x", (u32)info.format);
456 _dbg_assert_(HW_GPU, 0);
457 return {};
458 }
381} 459}
382 460
383TextureInfo TextureInfo::FromPicaRegister(const Regs::TextureConfig& config, 461TextureInfo TextureInfo::FromPicaRegister(const Regs::TextureConfig& config,
384 const Regs::TextureFormat& format) 462 const Regs::TextureFormat& format)
385{ 463{
386 TextureInfo info; 464 TextureInfo info;
387 info.address = config.GetPhysicalAddress(); 465 info.physical_address = config.GetPhysicalAddress();
388 info.width = config.width; 466 info.width = config.width;
389 info.height = config.height; 467 info.height = config.height;
390 info.format = format; 468 info.format = format;
391 info.stride = Pica::Regs::BytesPerPixel(info.format) * info.width; 469 info.stride = Pica::Regs::NibblesPerPixel(info.format) * info.width / 2;
392 return info; 470 return info;
393} 471}
394 472
@@ -499,26 +577,32 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
499 for (size_t index = 0; index < stages.size(); ++index) { 577 for (size_t index = 0; index < stages.size(); ++index) {
500 const auto& tev_stage = stages[index]; 578 const auto& tev_stage = stages[index];
501 579
502 const std::map<Source, std::string> source_map = { 580 static const std::map<Source, std::string> source_map = {
503 { Source::PrimaryColor, "PrimaryColor" }, 581 { Source::PrimaryColor, "PrimaryColor" },
504 { Source::Texture0, "Texture0" }, 582 { Source::Texture0, "Texture0" },
583 { Source::Texture1, "Texture1" },
584 { Source::Texture2, "Texture2" },
505 { Source::Constant, "Constant" }, 585 { Source::Constant, "Constant" },
506 { Source::Previous, "Previous" }, 586 { Source::Previous, "Previous" },
507 }; 587 };
508 588
509 const std::map<ColorModifier, std::string> color_modifier_map = { 589 static const std::map<ColorModifier, std::string> color_modifier_map = {
510 { ColorModifier::SourceColor, { "%source.rgb" } } 590 { ColorModifier::SourceColor, { "%source.rgb" } },
591 { ColorModifier::SourceAlpha, { "%source.aaa" } },
511 }; 592 };
512 const std::map<AlphaModifier, std::string> alpha_modifier_map = { 593 static const std::map<AlphaModifier, std::string> alpha_modifier_map = {
513 { AlphaModifier::SourceAlpha, "%source.a" } 594 { AlphaModifier::SourceAlpha, "%source.a" },
595 { AlphaModifier::OneMinusSourceAlpha, "(255 - %source.a)" },
514 }; 596 };
515 597
516 std::map<Operation, std::string> combiner_map = { 598 static const std::map<Operation, std::string> combiner_map = {
517 { Operation::Replace, "%source1" }, 599 { Operation::Replace, "%source1" },
518 { Operation::Modulate, "(%source1 * %source2) / 255" }, 600 { Operation::Modulate, "(%source1 * %source2) / 255" },
601 { Operation::Add, "(%source1 + %source2)" },
602 { Operation::Lerp, "lerp(%source1, %source2, %source3)" },
519 }; 603 };
520 604
521 auto ReplacePattern = 605 static auto ReplacePattern =
522 [](const std::string& input, const std::string& pattern, const std::string& replacement) -> std::string { 606 [](const std::string& input, const std::string& pattern, const std::string& replacement) -> std::string {
523 size_t start = input.find(pattern); 607 size_t start = input.find(pattern);
524 if (start == std::string::npos) 608 if (start == std::string::npos)
@@ -528,8 +612,8 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
528 ret.replace(start, pattern.length(), replacement); 612 ret.replace(start, pattern.length(), replacement);
529 return ret; 613 return ret;
530 }; 614 };
531 auto GetColorSourceStr = 615 static auto GetColorSourceStr =
532 [&source_map,&color_modifier_map,&ReplacePattern](const Source& src, const ColorModifier& modifier) { 616 [](const Source& src, const ColorModifier& modifier) {
533 auto src_it = source_map.find(src); 617 auto src_it = source_map.find(src);
534 std::string src_str = "Unknown"; 618 std::string src_str = "Unknown";
535 if (src_it != source_map.end()) 619 if (src_it != source_map.end())
@@ -542,8 +626,8 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
542 626
543 return ReplacePattern(modifier_str, "%source", src_str); 627 return ReplacePattern(modifier_str, "%source", src_str);
544 }; 628 };
545 auto GetColorCombinerStr = 629 static auto GetColorCombinerStr =
546 [&](const Regs::TevStageConfig& tev_stage) { 630 [](const Regs::TevStageConfig& tev_stage) {
547 auto op_it = combiner_map.find(tev_stage.color_op); 631 auto op_it = combiner_map.find(tev_stage.color_op);
548 std::string op_str = "Unknown op (%source1, %source2, %source3)"; 632 std::string op_str = "Unknown op (%source1, %source2, %source3)";
549 if (op_it != combiner_map.end()) 633 if (op_it != combiner_map.end())
@@ -553,8 +637,8 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
553 op_str = ReplacePattern(op_str, "%source2", GetColorSourceStr(tev_stage.color_source2, tev_stage.color_modifier2)); 637 op_str = ReplacePattern(op_str, "%source2", GetColorSourceStr(tev_stage.color_source2, tev_stage.color_modifier2));
554 return ReplacePattern(op_str, "%source3", GetColorSourceStr(tev_stage.color_source3, tev_stage.color_modifier3)); 638 return ReplacePattern(op_str, "%source3", GetColorSourceStr(tev_stage.color_source3, tev_stage.color_modifier3));
555 }; 639 };
556 auto GetAlphaSourceStr = 640 static auto GetAlphaSourceStr =
557 [&source_map,&alpha_modifier_map,&ReplacePattern](const Source& src, const AlphaModifier& modifier) { 641 [](const Source& src, const AlphaModifier& modifier) {
558 auto src_it = source_map.find(src); 642 auto src_it = source_map.find(src);
559 std::string src_str = "Unknown"; 643 std::string src_str = "Unknown";
560 if (src_it != source_map.end()) 644 if (src_it != source_map.end())
@@ -567,8 +651,8 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
567 651
568 return ReplacePattern(modifier_str, "%source", src_str); 652 return ReplacePattern(modifier_str, "%source", src_str);
569 }; 653 };
570 auto GetAlphaCombinerStr = 654 static auto GetAlphaCombinerStr =
571 [&](const Regs::TevStageConfig& tev_stage) { 655 [](const Regs::TevStageConfig& tev_stage) {
572 auto op_it = combiner_map.find(tev_stage.alpha_op); 656 auto op_it = combiner_map.find(tev_stage.alpha_op);
573 std::string op_str = "Unknown op (%source1, %source2, %source3)"; 657 std::string op_str = "Unknown op (%source1, %source2, %source3)";
574 if (op_it != combiner_map.end()) 658 if (op_it != combiner_map.end())
diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h
index 51f14f12f..f361a5385 100644
--- a/src/video_core/debug_utils/debug_utils.h
+++ b/src/video_core/debug_utils/debug_utils.h
@@ -26,6 +26,7 @@ public:
26 CommandProcessed, 26 CommandProcessed,
27 IncomingPrimitiveBatch, 27 IncomingPrimitiveBatch,
28 FinishedPrimitiveBatch, 28 FinishedPrimitiveBatch,
29 VertexLoaded,
29 30
30 NumEvents 31 NumEvents
31 }; 32 };
@@ -192,7 +193,7 @@ void OnPicaRegWrite(u32 id, u32 value);
192std::unique_ptr<PicaTrace> FinishPicaTracing(); 193std::unique_ptr<PicaTrace> FinishPicaTracing();
193 194
194struct TextureInfo { 195struct TextureInfo {
195 unsigned int address; 196 PAddr physical_address;
196 int width; 197 int width;
197 int height; 198 int height;
198 int stride; 199 int stride;
@@ -202,7 +203,17 @@ struct TextureInfo {
202 const Pica::Regs::TextureFormat& format); 203 const Pica::Regs::TextureFormat& format);
203}; 204};
204 205
205const Math::Vec4<u8> LookupTexture(const u8* source, int x, int y, const TextureInfo& info); 206/**
207 * Lookup texel located at the given coordinates and return an RGBA vector of its color.
208 * @param source Source pointer to read data from
209 * @param s,t Texture coordinates to read from
210 * @param info TextureInfo object describing the texture setup
211 * @param disable_alpha This is used for debug widgets which use this method to display textures without providing a good way to visualize alpha by themselves. If true, this will return 255 for the alpha component, and either drop the information entirely or store it in an "unused" color channel.
212 * @todo Eventually we should get rid of the disable_alpha parameter.
213 */
214const Math::Vec4<u8> LookupTexture(const u8* source, int s, int t, const TextureInfo& info,
215 bool disable_alpha = false);
216
206void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data); 217void DumpTexture(const Pica::Regs::TextureConfig& texture_config, u8* data);
207 218
208void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages); 219void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages);
diff --git a/src/video_core/gpu_debugger.h b/src/video_core/gpu_debugger.h
index 16b1656bb..a51d49c92 100644
--- a/src/video_core/gpu_debugger.h
+++ b/src/video_core/gpu_debugger.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -85,7 +85,7 @@ public:
85 85
86 void UnregisterObserver(DebuggerObserver* observer) 86 void UnregisterObserver(DebuggerObserver* observer)
87 { 87 {
88 std::remove(observers.begin(), observers.end(), observer); 88 observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
89 observer->observed = nullptr; 89 observer->observed = nullptr;
90 } 90 }
91 91
diff --git a/src/video_core/math.h b/src/video_core/math.h
index 83ba81235..9622e7614 100644
--- a/src/video_core/math.h
+++ b/src/video_core/math.h
@@ -1,4 +1,4 @@
1// Licensed under GPLv2 1// Licensed under GPLv2 or any later version
2// Refer to the license.txt file included. 2// Refer to the license.txt file included.
3 3
4 4
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index 4c3791ad9..38bac748c 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -8,6 +8,7 @@
8#include <cstddef> 8#include <cstddef>
9#include <initializer_list> 9#include <initializer_list>
10#include <map> 10#include <map>
11#include <vector>
11 12
12#include "common/bit_field.h" 13#include "common/bit_field.h"
13#include "common/common_types.h" 14#include "common/common_types.h"
@@ -104,6 +105,11 @@ struct Regs {
104 INSERT_PADDING_WORDS(0x17); 105 INSERT_PADDING_WORDS(0x17);
105 106
106 struct TextureConfig { 107 struct TextureConfig {
108 enum WrapMode : u32 {
109 ClampToEdge = 0,
110 Repeat = 2,
111 };
112
107 INSERT_PADDING_WORDS(0x1); 113 INSERT_PADDING_WORDS(0x1);
108 114
109 union { 115 union {
@@ -111,12 +117,17 @@ struct Regs {
111 BitField<16, 16, u32> width; 117 BitField<16, 16, u32> width;
112 }; 118 };
113 119
114 INSERT_PADDING_WORDS(0x2); 120 union {
121 BitField< 8, 2, WrapMode> wrap_s;
122 BitField<11, 2, WrapMode> wrap_t;
123 };
124
125 INSERT_PADDING_WORDS(0x1);
115 126
116 u32 address; 127 u32 address;
117 128
118 u32 GetPhysicalAddress() const { 129 u32 GetPhysicalAddress() const {
119 return DecodeAddressRegister(address) - Memory::FCRAM_PADDR + Memory::HEAP_LINEAR_VADDR; 130 return DecodeAddressRegister(address);
120 } 131 }
121 132
122 // texture1 and texture2 store the texture format directly after the address 133 // texture1 and texture2 store the texture format directly after the address
@@ -131,36 +142,70 @@ struct Regs {
131 RGBA5551 = 2, 142 RGBA5551 = 2,
132 RGB565 = 3, 143 RGB565 = 3,
133 RGBA4 = 4, 144 RGBA4 = 4,
145 IA8 = 5,
146
147 I8 = 7,
148 A8 = 8,
149 IA4 = 9,
134 150
151 A4 = 11,
135 // TODO: Support for the other formats is not implemented, yet. 152 // TODO: Support for the other formats is not implemented, yet.
136 // Seems like they are luminance formats and compressed textures. 153 // Seems like they are luminance formats and compressed textures.
137 }; 154 };
138 155
139 static unsigned BytesPerPixel(TextureFormat format) { 156 static unsigned NibblesPerPixel(TextureFormat format) {
140 switch (format) { 157 switch (format) {
141 case TextureFormat::RGBA8: 158 case TextureFormat::RGBA8:
142 return 4; 159 return 8;
143 160
144 case TextureFormat::RGB8: 161 case TextureFormat::RGB8:
145 return 3; 162 return 6;
146 163
147 case TextureFormat::RGBA5551: 164 case TextureFormat::RGBA5551:
148 case TextureFormat::RGB565: 165 case TextureFormat::RGB565:
149 case TextureFormat::RGBA4: 166 case TextureFormat::RGBA4:
150 return 2; 167 case TextureFormat::IA8:
168 return 4;
151 169
152 default: 170 case TextureFormat::A4:
153 // placeholder for yet unknown formats
154 return 1; 171 return 1;
172
173 case TextureFormat::I8:
174 case TextureFormat::A8:
175 case TextureFormat::IA4:
176 default: // placeholder for yet unknown formats
177 return 2;
155 } 178 }
156 } 179 }
157 180
158 BitField< 0, 1, u32> texturing_enable; 181 union {
182 BitField< 0, 1, u32> texture0_enable;
183 BitField< 1, 1, u32> texture1_enable;
184 BitField< 2, 1, u32> texture2_enable;
185 };
159 TextureConfig texture0; 186 TextureConfig texture0;
160 INSERT_PADDING_WORDS(0x8); 187 INSERT_PADDING_WORDS(0x8);
161 BitField<0, 4, TextureFormat> texture0_format; 188 BitField<0, 4, TextureFormat> texture0_format;
162 189 INSERT_PADDING_WORDS(0x2);
163 INSERT_PADDING_WORDS(0x31); 190 TextureConfig texture1;
191 BitField<0, 4, TextureFormat> texture1_format;
192 INSERT_PADDING_WORDS(0x2);
193 TextureConfig texture2;
194 BitField<0, 4, TextureFormat> texture2_format;
195 INSERT_PADDING_WORDS(0x21);
196
197 struct FullTextureConfig {
198 const bool enabled;
199 const TextureConfig config;
200 const TextureFormat format;
201 };
202 const std::array<FullTextureConfig, 3> GetTextures() const {
203 return {{
204 { texture0_enable.ToBool(), texture0, texture0_format },
205 { texture1_enable.ToBool(), texture1, texture1_format },
206 { texture2_enable.ToBool(), texture2, texture2_format }
207 }};
208 }
164 209
165 // 0xc0-0xff: Texture Combiner (akin to glTexEnv) 210 // 0xc0-0xff: Texture Combiner (akin to glTexEnv)
166 struct TevStageConfig { 211 struct TevStageConfig {
@@ -282,11 +327,11 @@ struct Regs {
282 327
283 INSERT_PADDING_WORDS(0x1); 328 INSERT_PADDING_WORDS(0x1);
284 329
285 inline u32 GetColorBufferAddress() const { 330 inline u32 GetColorBufferPhysicalAddress() const {
286 return Memory::PhysicalToVirtualAddress(DecodeAddressRegister(color_buffer_address)); 331 return DecodeAddressRegister(color_buffer_address);
287 } 332 }
288 inline u32 GetDepthBufferAddress() const { 333 inline u32 GetDepthBufferPhysicalAddress() const {
289 return Memory::PhysicalToVirtualAddress(DecodeAddressRegister(depth_buffer_address)); 334 return DecodeAddressRegister(depth_buffer_address);
290 } 335 }
291 336
292 inline u32 GetWidth() const { 337 inline u32 GetWidth() const {
@@ -310,9 +355,8 @@ struct Regs {
310 355
311 BitField<0, 29, u32> base_address; 356 BitField<0, 29, u32> base_address;
312 357
313 inline u32 GetBaseAddress() const { 358 u32 GetPhysicalBaseAddress() const {
314 // TODO: Ugly, should fix PhysicalToVirtualAddress instead 359 return DecodeAddressRegister(base_address);
315 return DecodeAddressRegister(base_address) - Memory::FCRAM_PADDR + Memory::HEAP_LINEAR_VADDR;
316 } 360 }
317 361
318 // Descriptor for internal vertex attributes 362 // Descriptor for internal vertex attributes
@@ -448,7 +492,11 @@ struct Regs {
448 492
449 BitField<8, 2, TriangleTopology> triangle_topology; 493 BitField<8, 2, TriangleTopology> triangle_topology;
450 494
451 INSERT_PADDING_WORDS(0x5b); 495 INSERT_PADDING_WORDS(0x51);
496
497 BitField<0, 16, u32> vs_bool_uniforms;
498
499 INSERT_PADDING_WORDS(0x9);
452 500
453 // Offset to shader program entry point (in words) 501 // Offset to shader program entry point (in words)
454 BitField<0, 16, u32> vs_main_offset; 502 BitField<0, 16, u32> vs_main_offset;
@@ -542,11 +590,11 @@ struct Regs {
542 static std::string GetCommandName(int index) { 590 static std::string GetCommandName(int index) {
543 std::map<u32, std::string> map; 591 std::map<u32, std::string> map;
544 592
545 Regs regs;
546 #define ADD_FIELD(name) \ 593 #define ADD_FIELD(name) \
547 do { \ 594 do { \
548 map.insert({PICA_REG_INDEX(name), #name}); \ 595 map.insert({PICA_REG_INDEX(name), #name}); \
549 for (u32 i = PICA_REG_INDEX(name) + 1; i < PICA_REG_INDEX(name) + sizeof(regs.name) / 4; ++i) \ 596 /* TODO: change to Regs::name when VS2015 and other compilers support it */ \
597 for (u32 i = PICA_REG_INDEX(name) + 1; i < PICA_REG_INDEX(name) + sizeof(Regs().name) / 4; ++i) \
550 map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))}); \ 598 map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))}); \
551 } while(false) 599 } while(false)
552 600
@@ -556,9 +604,13 @@ struct Regs {
556 ADD_FIELD(viewport_depth_range); 604 ADD_FIELD(viewport_depth_range);
557 ADD_FIELD(viewport_depth_far_plane); 605 ADD_FIELD(viewport_depth_far_plane);
558 ADD_FIELD(viewport_corner); 606 ADD_FIELD(viewport_corner);
559 ADD_FIELD(texturing_enable); 607 ADD_FIELD(texture0_enable);
560 ADD_FIELD(texture0); 608 ADD_FIELD(texture0);
561 ADD_FIELD(texture0_format); 609 ADD_FIELD(texture0_format);
610 ADD_FIELD(texture1);
611 ADD_FIELD(texture1_format);
612 ADD_FIELD(texture2);
613 ADD_FIELD(texture2_format);
562 ADD_FIELD(tev_stage0); 614 ADD_FIELD(tev_stage0);
563 ADD_FIELD(tev_stage1); 615 ADD_FIELD(tev_stage1);
564 ADD_FIELD(tev_stage2); 616 ADD_FIELD(tev_stage2);
@@ -572,6 +624,7 @@ struct Regs {
572 ADD_FIELD(trigger_draw); 624 ADD_FIELD(trigger_draw);
573 ADD_FIELD(trigger_draw_indexed); 625 ADD_FIELD(trigger_draw_indexed);
574 ADD_FIELD(triangle_topology); 626 ADD_FIELD(triangle_topology);
627 ADD_FIELD(vs_bool_uniforms);
575 ADD_FIELD(vs_main_offset); 628 ADD_FIELD(vs_main_offset);
576 ADD_FIELD(vs_input_register_map); 629 ADD_FIELD(vs_input_register_map);
577 ADD_FIELD(vs_uniform_setup); 630 ADD_FIELD(vs_uniform_setup);
@@ -622,9 +675,13 @@ ASSERT_REG_POSITION(viewport_depth_far_plane, 0x4e);
622ASSERT_REG_POSITION(vs_output_attributes[0], 0x50); 675ASSERT_REG_POSITION(vs_output_attributes[0], 0x50);
623ASSERT_REG_POSITION(vs_output_attributes[1], 0x51); 676ASSERT_REG_POSITION(vs_output_attributes[1], 0x51);
624ASSERT_REG_POSITION(viewport_corner, 0x68); 677ASSERT_REG_POSITION(viewport_corner, 0x68);
625ASSERT_REG_POSITION(texturing_enable, 0x80); 678ASSERT_REG_POSITION(texture0_enable, 0x80);
626ASSERT_REG_POSITION(texture0, 0x81); 679ASSERT_REG_POSITION(texture0, 0x81);
627ASSERT_REG_POSITION(texture0_format, 0x8e); 680ASSERT_REG_POSITION(texture0_format, 0x8e);
681ASSERT_REG_POSITION(texture1, 0x91);
682ASSERT_REG_POSITION(texture1_format, 0x96);
683ASSERT_REG_POSITION(texture2, 0x99);
684ASSERT_REG_POSITION(texture2_format, 0x9e);
628ASSERT_REG_POSITION(tev_stage0, 0xc0); 685ASSERT_REG_POSITION(tev_stage0, 0xc0);
629ASSERT_REG_POSITION(tev_stage1, 0xc8); 686ASSERT_REG_POSITION(tev_stage1, 0xc8);
630ASSERT_REG_POSITION(tev_stage2, 0xd0); 687ASSERT_REG_POSITION(tev_stage2, 0xd0);
@@ -638,6 +695,7 @@ ASSERT_REG_POSITION(num_vertices, 0x228);
638ASSERT_REG_POSITION(trigger_draw, 0x22e); 695ASSERT_REG_POSITION(trigger_draw, 0x22e);
639ASSERT_REG_POSITION(trigger_draw_indexed, 0x22f); 696ASSERT_REG_POSITION(trigger_draw_indexed, 0x22f);
640ASSERT_REG_POSITION(triangle_topology, 0x25e); 697ASSERT_REG_POSITION(triangle_topology, 0x25e);
698ASSERT_REG_POSITION(vs_bool_uniforms, 0x2b0);
641ASSERT_REG_POSITION(vs_main_offset, 0x2ba); 699ASSERT_REG_POSITION(vs_main_offset, 0x2ba);
642ASSERT_REG_POSITION(vs_input_register_map, 0x2bb); 700ASSERT_REG_POSITION(vs_input_register_map, 0x2bb);
643ASSERT_REG_POSITION(vs_uniform_setup, 0x2c0); 701ASSERT_REG_POSITION(vs_uniform_setup, 0x2c0);
@@ -699,6 +757,26 @@ struct float24 {
699 return float24::FromFloat32(ToFloat32() - flt.ToFloat32()); 757 return float24::FromFloat32(ToFloat32() - flt.ToFloat32());
700 } 758 }
701 759
760 float24& operator *= (const float24& flt) {
761 value *= flt.ToFloat32();
762 return *this;
763 }
764
765 float24& operator /= (const float24& flt) {
766 value /= flt.ToFloat32();
767 return *this;
768 }
769
770 float24& operator += (const float24& flt) {
771 value += flt.ToFloat32();
772 return *this;
773 }
774
775 float24& operator -= (const float24& flt) {
776 value -= flt.ToFloat32();
777 return *this;
778 }
779
702 float24 operator - () const { 780 float24 operator - () const {
703 return float24::FromFloat32(-ToFloat32()); 781 return float24::FromFloat32(-ToFloat32());
704 } 782 }
@@ -719,6 +797,14 @@ struct float24 {
719 return ToFloat32() <= flt.ToFloat32(); 797 return ToFloat32() <= flt.ToFloat32();
720 } 798 }
721 799
800 bool operator == (const float24& flt) const {
801 return ToFloat32() == flt.ToFloat32();
802 }
803
804 bool operator != (const float24& flt) const {
805 return ToFloat32() != flt.ToFloat32();
806 }
807
722private: 808private:
723 // Stored as a regular float, merely for convenience 809 // Stored as a regular float, merely for convenience
724 // TODO: Perform proper arithmetic on this! 810 // TODO: Perform proper arithmetic on this!
@@ -736,5 +822,15 @@ union CommandHeader {
736 BitField<31, 1, u32> group_commands; 822 BitField<31, 1, u32> group_commands;
737}; 823};
738 824
825// TODO: Ugly, should fix PhysicalToVirtualAddress instead
826inline static u32 PAddrToVAddr(u32 addr) {
827 if (addr >= Memory::VRAM_PADDR && addr < Memory::VRAM_PADDR + Memory::VRAM_SIZE) {
828 return addr - Memory::VRAM_PADDR + Memory::VRAM_VADDR;
829 } else if (addr >= Memory::FCRAM_PADDR && addr < Memory::FCRAM_PADDR + Memory::FCRAM_SIZE) {
830 return addr - Memory::FCRAM_PADDR + Memory::HEAP_LINEAR_VADDR;
831 } else {
832 return 0;
833 }
834}
739 835
740} // namespace 836} // namespace
diff --git a/src/video_core/primitive_assembly.cpp b/src/video_core/primitive_assembly.cpp
index 102693ed9..242a07e26 100644
--- a/src/video_core/primitive_assembly.cpp
+++ b/src/video_core/primitive_assembly.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "pica.h" 5#include "pica.h"
@@ -30,20 +30,27 @@ void PrimitiveAssembler<VertexType>::SubmitVertex(VertexType& vtx, TriangleHandl
30 } 30 }
31 break; 31 break;
32 32
33 case Regs::TriangleTopology::Strip:
33 case Regs::TriangleTopology::Fan: 34 case Regs::TriangleTopology::Fan:
34 if (buffer_index == 2) { 35 if (strip_ready) {
35 buffer_index = 0; 36 // TODO: Should be "buffer[0], buffer[1], vtx" instead!
36 37 // Not quite sure why we need this order for things to show up properly.
37 triangle_handler(buffer[0], buffer[1], vtx); 38 // Maybe a bug in the rasterizer?
39 triangle_handler(buffer[1], buffer[0], vtx);
40 }
41 buffer[buffer_index] = vtx;
38 42
39 buffer[1] = vtx; 43 if (topology == Regs::TriangleTopology::Strip) {
40 } else { 44 strip_ready |= (buffer_index == 1);
41 buffer[buffer_index++] = vtx; 45 buffer_index = !buffer_index;
46 } else if (topology == Regs::TriangleTopology::Fan) {
47 buffer_index = 1;
48 strip_ready = true;
42 } 49 }
43 break; 50 break;
44 51
45 default: 52 default:
46 LOG_ERROR(Render_Software, "Unknown triangle topology %x:", (int)topology); 53 LOG_ERROR(HW_GPU, "Unknown triangle topology %x:", (int)topology);
47 break; 54 break;
48 } 55 }
49} 56}
diff --git a/src/video_core/primitive_assembly.h b/src/video_core/primitive_assembly.h
index ea2e2f61e..52ff4cd89 100644
--- a/src/video_core/primitive_assembly.h
+++ b/src/video_core/primitive_assembly.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -37,6 +37,7 @@ private:
37 37
38 int buffer_index; 38 int buffer_index;
39 VertexType buffer[2]; 39 VertexType buffer[2];
40 bool strip_ready = false;
40}; 41};
41 42
42 43
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index b7e04a560..a80148872 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
@@ -18,7 +18,7 @@ namespace Pica {
18namespace Rasterizer { 18namespace Rasterizer {
19 19
20static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) { 20static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) {
21 u32* color_buffer = (u32*)Memory::GetPointer(registers.framebuffer.GetColorBufferAddress()); 21 u32* color_buffer = reinterpret_cast<u32*>(Memory::GetPointer(PAddrToVAddr(registers.framebuffer.GetColorBufferPhysicalAddress())));
22 u32 value = (color.a() << 24) | (color.r() << 16) | (color.g() << 8) | color.b(); 22 u32 value = (color.a() << 24) | (color.r() << 16) | (color.g() << 8) | color.b();
23 23
24 // Assuming RGBA8 format until actual framebuffer format handling is implemented 24 // Assuming RGBA8 format until actual framebuffer format handling is implemented
@@ -26,14 +26,14 @@ static void DrawPixel(int x, int y, const Math::Vec4<u8>& color) {
26} 26}
27 27
28static u32 GetDepth(int x, int y) { 28static u32 GetDepth(int x, int y) {
29 u16* depth_buffer = (u16*)Memory::GetPointer(registers.framebuffer.GetDepthBufferAddress()); 29 u16* depth_buffer = reinterpret_cast<u16*>(Memory::GetPointer(PAddrToVAddr(registers.framebuffer.GetDepthBufferPhysicalAddress())));
30 30
31 // Assuming 16-bit depth buffer format until actual format handling is implemented 31 // Assuming 16-bit depth buffer format until actual format handling is implemented
32 return *(depth_buffer + x + y * registers.framebuffer.GetWidth()); 32 return *(depth_buffer + x + y * registers.framebuffer.GetWidth());
33} 33}
34 34
35static void SetDepth(int x, int y, u16 value) { 35static void SetDepth(int x, int y, u16 value) {
36 u16* depth_buffer = (u16*)Memory::GetPointer(registers.framebuffer.GetDepthBufferAddress()); 36 u16* depth_buffer = reinterpret_cast<u16*>(Memory::GetPointer(PAddrToVAddr(registers.framebuffer.GetDepthBufferPhysicalAddress())));
37 37
38 // Assuming 16-bit depth buffer format until actual format handling is implemented 38 // Assuming 16-bit depth buffer format until actual format handling is implemented
39 *(depth_buffer + x + y * registers.framebuffer.GetWidth()) = value; 39 *(depth_buffer + x + y * registers.framebuffer.GetWidth()) = value;
@@ -106,6 +106,11 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
106 int bias1 = IsRightSideOrFlatBottomEdge(vtxpos[1].xy(), vtxpos[2].xy(), vtxpos[0].xy()) ? -1 : 0; 106 int bias1 = IsRightSideOrFlatBottomEdge(vtxpos[1].xy(), vtxpos[2].xy(), vtxpos[0].xy()) ? -1 : 0;
107 int bias2 = IsRightSideOrFlatBottomEdge(vtxpos[2].xy(), vtxpos[0].xy(), vtxpos[1].xy()) ? -1 : 0; 107 int bias2 = IsRightSideOrFlatBottomEdge(vtxpos[2].xy(), vtxpos[0].xy(), vtxpos[1].xy()) ? -1 : 0;
108 108
109 auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w);
110
111 auto textures = registers.GetTextures();
112 auto tev_stages = registers.GetTevStages();
113
109 // TODO: Not sure if looping through x first might be faster 114 // TODO: Not sure if looping through x first might be faster
110 for (u16 y = min_y; y < max_y; y += 0x10) { 115 for (u16 y = min_y; y < max_y; y += 0x10) {
111 for (u16 x = min_x; x < max_x; x += 0x10) { 116 for (u16 x = min_x; x < max_x; x += 0x10) {
@@ -129,6 +134,11 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
129 if (w0 < 0 || w1 < 0 || w2 < 0) 134 if (w0 < 0 || w1 < 0 || w2 < 0)
130 continue; 135 continue;
131 136
137 auto baricentric_coordinates = Math::MakeVec(float24::FromFloat32(static_cast<float>(w0)),
138 float24::FromFloat32(static_cast<float>(w1)),
139 float24::FromFloat32(static_cast<float>(w2)));
140 float24 interpolated_w_inverse = float24::FromFloat32(1.0f) / Math::Dot(w_inverse, baricentric_coordinates);
141
132 // Perspective correct attribute interpolation: 142 // Perspective correct attribute interpolation:
133 // Attribute values cannot be calculated by simple linear interpolation since 143 // Attribute values cannot be calculated by simple linear interpolation since
134 // they are not linear in screen space. For example, when interpolating a 144 // they are not linear in screen space. For example, when interpolating a
@@ -145,19 +155,9 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
145 // 155 //
146 // The generalization to three vertices is straightforward in baricentric coordinates. 156 // The generalization to three vertices is straightforward in baricentric coordinates.
147 auto GetInterpolatedAttribute = [&](float24 attr0, float24 attr1, float24 attr2) { 157 auto GetInterpolatedAttribute = [&](float24 attr0, float24 attr1, float24 attr2) {
148 auto attr_over_w = Math::MakeVec(attr0 / v0.pos.w, 158 auto attr_over_w = Math::MakeVec(attr0, attr1, attr2);
149 attr1 / v1.pos.w,
150 attr2 / v2.pos.w);
151 auto w_inverse = Math::MakeVec(float24::FromFloat32(1.f) / v0.pos.w,
152 float24::FromFloat32(1.f) / v1.pos.w,
153 float24::FromFloat32(1.f) / v2.pos.w);
154 auto baricentric_coordinates = Math::MakeVec(float24::FromFloat32(static_cast<float>(w0)),
155 float24::FromFloat32(static_cast<float>(w1)),
156 float24::FromFloat32(static_cast<float>(w2)));
157
158 float24 interpolated_attr_over_w = Math::Dot(attr_over_w, baricentric_coordinates); 159 float24 interpolated_attr_over_w = Math::Dot(attr_over_w, baricentric_coordinates);
159 float24 interpolated_w_inverse = Math::Dot(w_inverse, baricentric_coordinates); 160 return interpolated_attr_over_w * interpolated_w_inverse;
160 return interpolated_attr_over_w / interpolated_w_inverse;
161 }; 161 };
162 162
163 Math::Vec4<u8> primary_color{ 163 Math::Vec4<u8> primary_color{
@@ -167,60 +167,48 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
167 (u8)(GetInterpolatedAttribute(v0.color.a(), v1.color.a(), v2.color.a()).ToFloat32() * 255) 167 (u8)(GetInterpolatedAttribute(v0.color.a(), v1.color.a(), v2.color.a()).ToFloat32() * 255)
168 }; 168 };
169 169
170 Math::Vec4<u8> texture_color{}; 170 Math::Vec2<float24> uv[3];
171 float24 u = GetInterpolatedAttribute(v0.tc0.u(), v1.tc0.u(), v2.tc0.u()); 171 uv[0].u() = GetInterpolatedAttribute(v0.tc0.u(), v1.tc0.u(), v2.tc0.u());
172 float24 v = GetInterpolatedAttribute(v0.tc0.v(), v1.tc0.v(), v2.tc0.v()); 172 uv[0].v() = GetInterpolatedAttribute(v0.tc0.v(), v1.tc0.v(), v2.tc0.v());
173 if (registers.texturing_enable) { 173 uv[1].u() = GetInterpolatedAttribute(v0.tc1.u(), v1.tc1.u(), v2.tc1.u());
174 // Images are split into 8x8 tiles. Each tile is composed of four 4x4 subtiles each 174 uv[1].v() = GetInterpolatedAttribute(v0.tc1.v(), v1.tc1.v(), v2.tc1.v());
175 // of which is composed of four 2x2 subtiles each of which is composed of four texels. 175 uv[2].u() = GetInterpolatedAttribute(v0.tc2.u(), v1.tc2.u(), v2.tc2.u());
176 // Each structure is embedded into the next-bigger one in a diagonal pattern, e.g. 176 uv[2].v() = GetInterpolatedAttribute(v0.tc2.v(), v1.tc2.v(), v2.tc2.v());
177 // texels are laid out in a 2x2 subtile like this: 177
178 // 2 3 178 Math::Vec4<u8> texture_color[3]{};
179 // 0 1 179 for (int i = 0; i < 3; ++i) {
180 // 180 const auto& texture = textures[i];
181 // The full 8x8 tile has the texels arranged like this: 181 if (!texture.enabled)
182 // 182 continue;
183 // 42 43 46 47 58 59 62 63 183
184 // 40 41 44 45 56 57 60 61 184 _dbg_assert_(HW_GPU, 0 != texture.config.address);
185 // 34 35 38 39 50 51 54 55 185
186 // 32 33 36 37 48 49 52 53 186 int s = (int)(uv[i].u() * float24::FromFloat32(static_cast<float>(texture.config.width))).ToFloat32();
187 // 10 11 14 15 26 27 30 31 187 int t = (int)(uv[i].v() * float24::FromFloat32(static_cast<float>(texture.config.height))).ToFloat32();
188 // 08 09 12 13 24 25 28 29 188 auto GetWrappedTexCoord = [](Regs::TextureConfig::WrapMode mode, int val, unsigned size) {
189 // 02 03 06 07 18 19 22 23 189 switch (mode) {
190 // 00 01 04 05 16 17 20 21 190 case Regs::TextureConfig::ClampToEdge:
191 191 val = std::max(val, 0);
192 // TODO: This is currently hardcoded for RGB8 192 val = std::min(val, (int)size - 1);
193 u32* texture_data = (u32*)Memory::GetPointer(registers.texture0.GetPhysicalAddress()); 193 return val;
194 194
195 // TODO(neobrain): Not sure if this swizzling pattern is used for all textures. 195 case Regs::TextureConfig::Repeat:
196 // To be flexible in case different but similar patterns are used, we keep this 196 return (int)(((unsigned)val) % size);
197 // somewhat inefficient code around for now. 197
198 int s = (int)(u * float24::FromFloat32(static_cast<float>(registers.texture0.width))).ToFloat32(); 198 default:
199 int t = (int)(v * float24::FromFloat32(static_cast<float>(registers.texture0.height))).ToFloat32(); 199 LOG_ERROR(HW_GPU, "Unknown texture coordinate wrapping mode %x\n", (int)mode);
200 int texel_index_within_tile = 0; 200 _dbg_assert_(HW_GPU, 0);
201 for (int block_size_index = 0; block_size_index < 3; ++block_size_index) { 201 return 0;
202 int sub_tile_width = 1 << block_size_index; 202 }
203 int sub_tile_height = 1 << block_size_index; 203 };
204 204 s = GetWrappedTexCoord(registers.texture0.wrap_s, s, registers.texture0.width);
205 int sub_tile_index = (s & sub_tile_width) << block_size_index; 205 t = GetWrappedTexCoord(registers.texture0.wrap_t, t, registers.texture0.height);
206 sub_tile_index += 2 * ((t & sub_tile_height) << block_size_index); 206
207 texel_index_within_tile += sub_tile_index; 207 u8* texture_data = Memory::GetPointer(PAddrToVAddr(texture.config.GetPhysicalAddress()));
208 } 208 auto info = DebugUtils::TextureInfo::FromPicaRegister(texture.config, texture.format);
209 209
210 const int block_width = 8; 210 texture_color[i] = DebugUtils::LookupTexture(texture_data, s, t, info);
211 const int block_height = 8; 211 DebugUtils::DumpTexture(texture.config, texture_data);
212
213 int coarse_s = (s / block_width) * block_width;
214 int coarse_t = (t / block_height) * block_height;
215
216 const int row_stride = registers.texture0.width * 3;
217 u8* source_ptr = (u8*)texture_data + coarse_s * block_height * 3 + coarse_t * row_stride + texel_index_within_tile * 3;
218 texture_color.r() = source_ptr[2];
219 texture_color.g() = source_ptr[1];
220 texture_color.b() = source_ptr[0];
221 texture_color.a() = 0xFF;
222
223 DebugUtils::DumpTexture(registers.texture0, (u8*)texture_data);
224 } 212 }
225 213
226 // Texture environment - consists of 6 stages of color and alpha combining. 214 // Texture environment - consists of 6 stages of color and alpha combining.
@@ -231,28 +219,35 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
231 // with some basic arithmetic. Alpha combiners can be configured separately but work 219 // with some basic arithmetic. Alpha combiners can be configured separately but work
232 // analogously. 220 // analogously.
233 Math::Vec4<u8> combiner_output; 221 Math::Vec4<u8> combiner_output;
234 for (auto tev_stage : registers.GetTevStages()) { 222 for (const auto& tev_stage : tev_stages) {
235 using Source = Regs::TevStageConfig::Source; 223 using Source = Regs::TevStageConfig::Source;
236 using ColorModifier = Regs::TevStageConfig::ColorModifier; 224 using ColorModifier = Regs::TevStageConfig::ColorModifier;
237 using AlphaModifier = Regs::TevStageConfig::AlphaModifier; 225 using AlphaModifier = Regs::TevStageConfig::AlphaModifier;
238 using Operation = Regs::TevStageConfig::Operation; 226 using Operation = Regs::TevStageConfig::Operation;
239 227
240 auto GetColorSource = [&](Source source) -> Math::Vec3<u8> { 228 auto GetColorSource = [&](Source source) -> Math::Vec4<u8> {
241 switch (source) { 229 switch (source) {
242 case Source::PrimaryColor: 230 case Source::PrimaryColor:
243 return primary_color.rgb(); 231 return primary_color;
244 232
245 case Source::Texture0: 233 case Source::Texture0:
246 return texture_color.rgb(); 234 return texture_color[0];
235
236 case Source::Texture1:
237 return texture_color[1];
238
239 case Source::Texture2:
240 return texture_color[2];
247 241
248 case Source::Constant: 242 case Source::Constant:
249 return {tev_stage.const_r, tev_stage.const_g, tev_stage.const_b}; 243 return {tev_stage.const_r, tev_stage.const_g, tev_stage.const_b, tev_stage.const_a};
250 244
251 case Source::Previous: 245 case Source::Previous:
252 return combiner_output.rgb(); 246 return combiner_output;
253 247
254 default: 248 default:
255 LOG_ERROR(HW_GPU, "Unknown color combiner source %d\n", (int)source); 249 LOG_ERROR(HW_GPU, "Unknown color combiner source %d\n", (int)source);
250 _dbg_assert_(HW_GPU, 0);
256 return {}; 251 return {};
257 } 252 }
258 }; 253 };
@@ -263,7 +258,13 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
263 return primary_color.a(); 258 return primary_color.a();
264 259
265 case Source::Texture0: 260 case Source::Texture0:
266 return texture_color.a(); 261 return texture_color[0].a();
262
263 case Source::Texture1:
264 return texture_color[1].a();
265
266 case Source::Texture2:
267 return texture_color[2].a();
267 268
268 case Source::Constant: 269 case Source::Constant:
269 return tev_stage.const_a; 270 return tev_stage.const_a;
@@ -273,17 +274,23 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
273 274
274 default: 275 default:
275 LOG_ERROR(HW_GPU, "Unknown alpha combiner source %d\n", (int)source); 276 LOG_ERROR(HW_GPU, "Unknown alpha combiner source %d\n", (int)source);
277 _dbg_assert_(HW_GPU, 0);
276 return 0; 278 return 0;
277 } 279 }
278 }; 280 };
279 281
280 auto GetColorModifier = [](ColorModifier factor, const Math::Vec3<u8>& values) -> Math::Vec3<u8> { 282 auto GetColorModifier = [](ColorModifier factor, const Math::Vec4<u8>& values) -> Math::Vec3<u8> {
281 switch (factor) 283 switch (factor)
282 { 284 {
283 case ColorModifier::SourceColor: 285 case ColorModifier::SourceColor:
284 return values; 286 return values.rgb();
287
288 case ColorModifier::SourceAlpha:
289 return { values.a(), values.a(), values.a() };
290
285 default: 291 default:
286 LOG_ERROR(HW_GPU, "Unknown color factor %d\n", (int)factor); 292 LOG_ERROR(HW_GPU, "Unknown color factor %d\n", (int)factor);
293 _dbg_assert_(HW_GPU, 0);
287 return {}; 294 return {};
288 } 295 }
289 }; 296 };
@@ -292,8 +299,13 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
292 switch (factor) { 299 switch (factor) {
293 case AlphaModifier::SourceAlpha: 300 case AlphaModifier::SourceAlpha:
294 return value; 301 return value;
302
303 case AlphaModifier::OneMinusSourceAlpha:
304 return 255 - value;
305
295 default: 306 default:
296 LOG_ERROR(HW_GPU, "Unknown color factor %d\n", (int)factor); 307 LOG_ERROR(HW_GPU, "Unknown alpha factor %d\n", (int)factor);
308 _dbg_assert_(HW_GPU, 0);
297 return 0; 309 return 0;
298 } 310 }
299 }; 311 };
@@ -306,8 +318,21 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
306 case Operation::Modulate: 318 case Operation::Modulate:
307 return ((input[0] * input[1]) / 255).Cast<u8>(); 319 return ((input[0] * input[1]) / 255).Cast<u8>();
308 320
321 case Operation::Add:
322 {
323 auto result = input[0] + input[1];
324 result.r() = std::min(255, result.r());
325 result.g() = std::min(255, result.g());
326 result.b() = std::min(255, result.b());
327 return result.Cast<u8>();
328 }
329
330 case Operation::Lerp:
331 return ((input[0] * input[2] + input[1] * (Math::MakeVec<u8>(255, 255, 255) - input[2]).Cast<u8>()) / 255).Cast<u8>();
332
309 default: 333 default:
310 LOG_ERROR(HW_GPU, "Unknown color combiner operation %d\n", (int)op); 334 LOG_ERROR(HW_GPU, "Unknown color combiner operation %d\n", (int)op);
335 _dbg_assert_(HW_GPU, 0);
311 return {}; 336 return {};
312 } 337 }
313 }; 338 };
@@ -320,8 +345,15 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
320 case Operation::Modulate: 345 case Operation::Modulate:
321 return input[0] * input[1] / 255; 346 return input[0] * input[1] / 255;
322 347
348 case Operation::Add:
349 return std::min(255, input[0] + input[1]);
350
351 case Operation::Lerp:
352 return (input[0] * input[2] + input[1] * (255 - input[2])) / 255;
353
323 default: 354 default:
324 LOG_ERROR(HW_GPU, "Unknown alpha combiner operation %d\n", (int)op); 355 LOG_ERROR(HW_GPU, "Unknown alpha combiner operation %d\n", (int)op);
356 _dbg_assert_(HW_GPU, 0);
325 return 0; 357 return 0;
326 } 358 }
327 }; 359 };
diff --git a/src/video_core/rasterizer.h b/src/video_core/rasterizer.h
index 500be9462..42148f8b1 100644
--- a/src/video_core/rasterizer.h
+++ b/src/video_core/rasterizer.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index bce402b88..b77f29c11 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp
index d0f82e6cd..e982e3746 100644
--- a/src/video_core/renderer_opengl/gl_shader_util.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_util.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "gl_shader_util.h" 5#include "gl_shader_util.h"
diff --git a/src/video_core/renderer_opengl/gl_shader_util.h b/src/video_core/renderer_opengl/gl_shader_util.h
index 986cbabc0..9b93a8a0c 100644
--- a/src/video_core/renderer_opengl/gl_shader_util.h
+++ b/src/video_core/renderer_opengl/gl_shader_util.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/video_core/renderer_opengl/gl_shaders.h b/src/video_core/renderer_opengl/gl_shaders.h
index 0f88ab802..746a37afe 100644
--- a/src/video_core/renderer_opengl/gl_shaders.h
+++ b/src/video_core/renderer_opengl/gl_shaders.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index e2caeeb8f..4df3a5e25 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hw/gpu.h" 5#include "core/hw/gpu.h"
@@ -240,14 +240,14 @@ MathUtil::Rectangle<unsigned> RendererOpenGL::GetViewportExtent() {
240 MathUtil::Rectangle<unsigned> viewport_extent; 240 MathUtil::Rectangle<unsigned> viewport_extent;
241 if (window_aspect_ratio > emulation_aspect_ratio) { 241 if (window_aspect_ratio > emulation_aspect_ratio) {
242 // Window is narrower than the emulation content => apply borders to the top and bottom 242 // Window is narrower than the emulation content => apply borders to the top and bottom
243 unsigned viewport_height = std::round(emulation_aspect_ratio * framebuffer_width); 243 unsigned viewport_height = static_cast<unsigned>(std::round(emulation_aspect_ratio * framebuffer_width));
244 viewport_extent.left = 0; 244 viewport_extent.left = 0;
245 viewport_extent.top = (framebuffer_height - viewport_height) / 2; 245 viewport_extent.top = (framebuffer_height - viewport_height) / 2;
246 viewport_extent.right = viewport_extent.left + framebuffer_width; 246 viewport_extent.right = viewport_extent.left + framebuffer_width;
247 viewport_extent.bottom = viewport_extent.top + viewport_height; 247 viewport_extent.bottom = viewport_extent.top + viewport_height;
248 } else { 248 } else {
249 // Otherwise, apply borders to the left and right sides of the window. 249 // Otherwise, apply borders to the left and right sides of the window.
250 unsigned viewport_width = std::round(framebuffer_height / emulation_aspect_ratio); 250 unsigned viewport_width = static_cast<unsigned>(std::round(framebuffer_height / emulation_aspect_ratio));
251 viewport_extent.left = (framebuffer_width - viewport_width) / 2; 251 viewport_extent.left = (framebuffer_width - viewport_width) / 2;
252 viewport_extent.top = 0; 252 viewport_extent.top = 0;
253 viewport_extent.right = viewport_extent.left + viewport_width; 253 viewport_extent.right = viewport_extent.left + viewport_width;
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index 7fdcec731..cf78c1e77 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/video_core/utils.cpp b/src/video_core/utils.cpp
index f1156a493..c7cc93cea 100644
--- a/src/video_core/utils.cpp
+++ b/src/video_core/utils.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <stdio.h> 5#include <stdio.h>
diff --git a/src/video_core/utils.h b/src/video_core/utils.h
index 21380a908..63ebccbde 100644
--- a/src/video_core/utils.h
+++ b/src/video_core/utils.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
diff --git a/src/video_core/vertex_shader.cpp b/src/video_core/vertex_shader.cpp
index 477e78cfe..bed5081a0 100644
--- a/src/video_core/vertex_shader.cpp
+++ b/src/video_core/vertex_shader.cpp
@@ -1,17 +1,26 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <stack>
6
5#include <boost/range/algorithm.hpp> 7#include <boost/range/algorithm.hpp>
6 8
7#include <common/file_util.h> 9#include <common/file_util.h>
8 10
9#include <core/mem_map.h> 11#include <core/mem_map.h>
10 12
11#include "debug_utils/debug_utils.h" 13#include <nihstro/shader_bytecode.h>
14
12 15
13#include "pica.h" 16#include "pica.h"
14#include "vertex_shader.h" 17#include "vertex_shader.h"
18#include "debug_utils/debug_utils.h"
19
20using nihstro::Instruction;
21using nihstro::RegisterType;
22using nihstro::SourceRegister;
23using nihstro::SwizzlePattern;
15 24
16namespace Pica { 25namespace Pica {
17 26
@@ -19,13 +28,14 @@ namespace VertexShader {
19 28
20static struct { 29static struct {
21 Math::Vec4<float24> f[96]; 30 Math::Vec4<float24> f[96];
22} shader_uniforms;
23 31
32 std::array<bool,16> b;
33} shader_uniforms;
24 34
25// TODO: Not sure where the shader binary and swizzle patterns are supposed to be loaded to! 35// TODO: Not sure where the shader binary and swizzle patterns are supposed to be loaded to!
26// For now, we just keep these local arrays around. 36// For now, we just keep these local arrays around.
27static u32 shader_memory[1024]; 37static std::array<u32, 1024> shader_memory;
28static u32 swizzle_data[1024]; 38static std::array<u32, 1024> swizzle_data;
29 39
30void SubmitShaderMemoryChange(u32 addr, u32 value) 40void SubmitShaderMemoryChange(u32 addr, u32 value)
31{ 41{
@@ -42,6 +52,21 @@ Math::Vec4<float24>& GetFloatUniform(u32 index)
42 return shader_uniforms.f[index]; 52 return shader_uniforms.f[index];
43} 53}
44 54
55bool& GetBoolUniform(u32 index)
56{
57 return shader_uniforms.b[index];
58}
59
60const std::array<u32, 1024>& GetShaderBinary()
61{
62 return shader_memory;
63}
64
65const std::array<u32, 1024>& GetSwizzlePatterns()
66{
67 return swizzle_data;
68}
69
45struct VertexShaderState { 70struct VertexShaderState {
46 u32* program_counter; 71 u32* program_counter;
47 72
@@ -49,13 +74,23 @@ struct VertexShaderState {
49 float24* output_register_table[7*4]; 74 float24* output_register_table[7*4];
50 75
51 Math::Vec4<float24> temporary_registers[16]; 76 Math::Vec4<float24> temporary_registers[16];
52 bool status_registers[2]; 77 bool conditional_code[2];
78
79 // Two Address registers and one loop counter
80 // TODO: How many bits do these actually have?
81 s32 address_registers[3];
53 82
54 enum { 83 enum {
55 INVALID_ADDRESS = 0xFFFFFFFF 84 INVALID_ADDRESS = 0xFFFFFFFF
56 }; 85 };
57 u32 call_stack[8]; // TODO: What is the maximal call stack depth? 86
58 u32* call_stack_pointer; 87 struct CallStackElement {
88 u32 final_address;
89 u32 return_address;
90 };
91
92 // TODO: Is there a maximal size for this?
93 std::stack<CallStackElement> call_stack;
59 94
60 struct { 95 struct {
61 u32 max_offset; // maximum program counter ever reached 96 u32 max_offset; // maximum program counter ever reached
@@ -64,49 +99,105 @@ struct VertexShaderState {
64}; 99};
65 100
66static void ProcessShaderCode(VertexShaderState& state) { 101static void ProcessShaderCode(VertexShaderState& state) {
102
103 // Placeholder for invalid inputs
104 static float24 dummy_vec4_float24[4];
105
67 while (true) { 106 while (true) {
68 bool increment_pc = true; 107 if (!state.call_stack.empty()) {
108 if (state.program_counter - shader_memory.data() == state.call_stack.top().final_address) {
109 state.program_counter = &shader_memory[state.call_stack.top().return_address];
110 state.call_stack.pop();
111
112 // TODO: Is "trying again" accurate to hardware?
113 continue;
114 }
115 }
116
69 bool exit_loop = false; 117 bool exit_loop = false;
70 const Instruction& instr = *(const Instruction*)state.program_counter; 118 const Instruction& instr = *(const Instruction*)state.program_counter;
71 state.debug.max_offset = std::max<u32>(state.debug.max_offset, 1 + (state.program_counter - shader_memory));
72
73 const float24* src1_ = (instr.common.src1 < 0x10) ? state.input_register_table[instr.common.src1.GetIndex()]
74 : (instr.common.src1 < 0x20) ? &state.temporary_registers[instr.common.src1.GetIndex()].x
75 : (instr.common.src1 < 0x80) ? &shader_uniforms.f[instr.common.src1.GetIndex()].x
76 : nullptr;
77 const float24* src2_ = (instr.common.src2 < 0x10) ? state.input_register_table[instr.common.src2.GetIndex()]
78 : &state.temporary_registers[instr.common.src2.GetIndex()].x;
79 float24* dest = (instr.common.dest < 0x08) ? state.output_register_table[4*instr.common.dest.GetIndex()]
80 : (instr.common.dest < 0x10) ? nullptr
81 : (instr.common.dest < 0x20) ? &state.temporary_registers[instr.common.dest.GetIndex()][0]
82 : nullptr;
83
84 const SwizzlePattern& swizzle = *(SwizzlePattern*)&swizzle_data[instr.common.operand_desc_id]; 119 const SwizzlePattern& swizzle = *(SwizzlePattern*)&swizzle_data[instr.common.operand_desc_id];
85 const bool negate_src1 = (swizzle.negate != 0);
86 120
87 float24 src1[4] = { 121 auto call = [&](VertexShaderState& state, u32 offset, u32 num_instructions, u32 return_offset) {
88 src1_[(int)swizzle.GetSelectorSrc1(0)], 122 state.program_counter = &shader_memory[offset] - 1; // -1 to make sure when incrementing the PC we end up at the correct offset
89 src1_[(int)swizzle.GetSelectorSrc1(1)], 123 state.call_stack.push({ offset + num_instructions, return_offset });
90 src1_[(int)swizzle.GetSelectorSrc1(2)],
91 src1_[(int)swizzle.GetSelectorSrc1(3)],
92 }; 124 };
93 if (negate_src1) { 125 u32 binary_offset = state.program_counter - shader_memory.data();
94 src1[0] = src1[0] * float24::FromFloat32(-1); 126
95 src1[1] = src1[1] * float24::FromFloat32(-1); 127 state.debug.max_offset = std::max<u32>(state.debug.max_offset, 1 + binary_offset);
96 src1[2] = src1[2] * float24::FromFloat32(-1); 128
97 src1[3] = src1[3] * float24::FromFloat32(-1); 129 auto LookupSourceRegister = [&](const SourceRegister& source_reg) -> const float24* {
98 } 130 switch (source_reg.GetRegisterType()) {
99 const float24 src2[4] = { 131 case RegisterType::Input:
100 src2_[(int)swizzle.GetSelectorSrc2(0)], 132 return state.input_register_table[source_reg.GetIndex()];
101 src2_[(int)swizzle.GetSelectorSrc2(1)], 133
102 src2_[(int)swizzle.GetSelectorSrc2(2)], 134 case RegisterType::Temporary:
103 src2_[(int)swizzle.GetSelectorSrc2(3)], 135 return &state.temporary_registers[source_reg.GetIndex()].x;
136
137 case RegisterType::FloatUniform:
138 return &shader_uniforms.f[source_reg.GetIndex()].x;
139
140 default:
141 return dummy_vec4_float24;
142 }
104 }; 143 };
105 144
106 switch (instr.opcode) { 145 switch (instr.opcode.GetInfo().type) {
146 case Instruction::OpCodeType::Arithmetic:
147 {
148 bool is_inverted = 0 != (instr.opcode.GetInfo().subtype & Instruction::OpCodeInfo::SrcInversed);
149 if (is_inverted) {
150 // TODO: We don't really support this properly: For instance, the address register
151 // offset needs to be applied to SRC2 instead, etc.
152 // For now, we just abort in this situation.
153 LOG_CRITICAL(HW_GPU, "Bad condition...");
154 exit(0);
155 }
156
157 const int address_offset = (instr.common.address_register_index == 0)
158 ? 0 : state.address_registers[instr.common.address_register_index - 1];
159
160 const float24* src1_ = LookupSourceRegister(instr.common.GetSrc1(is_inverted) + address_offset);
161 const float24* src2_ = LookupSourceRegister(instr.common.GetSrc2(is_inverted));
162
163 const bool negate_src1 = ((bool)swizzle.negate_src1 != false);
164 const bool negate_src2 = ((bool)swizzle.negate_src2 != false);
165
166 float24 src1[4] = {
167 src1_[(int)swizzle.GetSelectorSrc1(0)],
168 src1_[(int)swizzle.GetSelectorSrc1(1)],
169 src1_[(int)swizzle.GetSelectorSrc1(2)],
170 src1_[(int)swizzle.GetSelectorSrc1(3)],
171 };
172 if (negate_src1) {
173 src1[0] = src1[0] * float24::FromFloat32(-1);
174 src1[1] = src1[1] * float24::FromFloat32(-1);
175 src1[2] = src1[2] * float24::FromFloat32(-1);
176 src1[3] = src1[3] * float24::FromFloat32(-1);
177 }
178 float24 src2[4] = {
179 src2_[(int)swizzle.GetSelectorSrc2(0)],
180 src2_[(int)swizzle.GetSelectorSrc2(1)],
181 src2_[(int)swizzle.GetSelectorSrc2(2)],
182 src2_[(int)swizzle.GetSelectorSrc2(3)],
183 };
184 if (negate_src2) {
185 src2[0] = src2[0] * float24::FromFloat32(-1);
186 src2[1] = src2[1] * float24::FromFloat32(-1);
187 src2[2] = src2[2] * float24::FromFloat32(-1);
188 src2[3] = src2[3] * float24::FromFloat32(-1);
189 }
190
191 float24* dest = (instr.common.dest < 0x08) ? state.output_register_table[4*instr.common.dest.GetIndex()]
192 : (instr.common.dest < 0x10) ? dummy_vec4_float24
193 : (instr.common.dest < 0x20) ? &state.temporary_registers[instr.common.dest.GetIndex()][0]
194 : dummy_vec4_float24;
195
196 state.debug.max_opdesc_id = std::max<u32>(state.debug.max_opdesc_id, 1+instr.common.operand_desc_id);
197
198 switch (instr.opcode.EffectiveOpCode()) {
107 case Instruction::OpCode::ADD: 199 case Instruction::OpCode::ADD:
108 { 200 {
109 state.debug.max_opdesc_id = std::max<u32>(state.debug.max_opdesc_id, 1+instr.common.operand_desc_id);
110 for (int i = 0; i < 4; ++i) { 201 for (int i = 0; i < 4; ++i) {
111 if (!swizzle.DestComponentEnabled(i)) 202 if (!swizzle.DestComponentEnabled(i))
112 continue; 203 continue;
@@ -119,7 +210,6 @@ static void ProcessShaderCode(VertexShaderState& state) {
119 210
120 case Instruction::OpCode::MUL: 211 case Instruction::OpCode::MUL:
121 { 212 {
122 state.debug.max_opdesc_id = std::max<u32>(state.debug.max_opdesc_id, 1+instr.common.operand_desc_id);
123 for (int i = 0; i < 4; ++i) { 213 for (int i = 0; i < 4; ++i) {
124 if (!swizzle.DestComponentEnabled(i)) 214 if (!swizzle.DestComponentEnabled(i))
125 continue; 215 continue;
@@ -130,10 +220,18 @@ static void ProcessShaderCode(VertexShaderState& state) {
130 break; 220 break;
131 } 221 }
132 222
223 case Instruction::OpCode::MAX:
224 for (int i = 0; i < 4; ++i) {
225 if (!swizzle.DestComponentEnabled(i))
226 continue;
227
228 dest[i] = std::max(src1[i], src2[i]);
229 }
230 break;
231
133 case Instruction::OpCode::DP3: 232 case Instruction::OpCode::DP3:
134 case Instruction::OpCode::DP4: 233 case Instruction::OpCode::DP4:
135 { 234 {
136 state.debug.max_opdesc_id = std::max<u32>(state.debug.max_opdesc_id, 1+instr.common.operand_desc_id);
137 float24 dot = float24::FromFloat32(0.f); 235 float24 dot = float24::FromFloat32(0.f);
138 int num_components = (instr.opcode == Instruction::OpCode::DP3) ? 3 : 4; 236 int num_components = (instr.opcode == Instruction::OpCode::DP3) ? 3 : 4;
139 for (int i = 0; i < num_components; ++i) 237 for (int i = 0; i < num_components; ++i)
@@ -151,7 +249,6 @@ static void ProcessShaderCode(VertexShaderState& state) {
151 // Reciprocal 249 // Reciprocal
152 case Instruction::OpCode::RCP: 250 case Instruction::OpCode::RCP:
153 { 251 {
154 state.debug.max_opdesc_id = std::max<u32>(state.debug.max_opdesc_id, 1+instr.common.operand_desc_id);
155 for (int i = 0; i < 4; ++i) { 252 for (int i = 0; i < 4; ++i) {
156 if (!swizzle.DestComponentEnabled(i)) 253 if (!swizzle.DestComponentEnabled(i))
157 continue; 254 continue;
@@ -167,7 +264,6 @@ static void ProcessShaderCode(VertexShaderState& state) {
167 // Reciprocal Square Root 264 // Reciprocal Square Root
168 case Instruction::OpCode::RSQ: 265 case Instruction::OpCode::RSQ:
169 { 266 {
170 state.debug.max_opdesc_id = std::max<u32>(state.debug.max_opdesc_id, 1+instr.common.operand_desc_id);
171 for (int i = 0; i < 4; ++i) { 267 for (int i = 0; i < 4; ++i) {
172 if (!swizzle.DestComponentEnabled(i)) 268 if (!swizzle.DestComponentEnabled(i))
173 continue; 269 continue;
@@ -180,9 +276,21 @@ static void ProcessShaderCode(VertexShaderState& state) {
180 break; 276 break;
181 } 277 }
182 278
279 case Instruction::OpCode::MOVA:
280 {
281 for (int i = 0; i < 2; ++i) {
282 if (!swizzle.DestComponentEnabled(i))
283 continue;
284
285 // TODO: Figure out how the rounding is done on hardware
286 state.address_registers[i] = static_cast<s32>(src1[i].ToFloat32());
287 }
288
289 break;
290 }
291
183 case Instruction::OpCode::MOV: 292 case Instruction::OpCode::MOV:
184 { 293 {
185 state.debug.max_opdesc_id = std::max<u32>(state.debug.max_opdesc_id, 1+instr.common.operand_desc_id);
186 for (int i = 0; i < 4; ++i) { 294 for (int i = 0; i < 4; ++i) {
187 if (!swizzle.DestComponentEnabled(i)) 295 if (!swizzle.DestComponentEnabled(i))
188 continue; 296 continue;
@@ -192,39 +300,137 @@ static void ProcessShaderCode(VertexShaderState& state) {
192 break; 300 break;
193 } 301 }
194 302
195 case Instruction::OpCode::RET: 303 case Instruction::OpCode::CMP:
196 if (*state.call_stack_pointer == VertexShaderState::INVALID_ADDRESS) { 304 for (int i = 0; i < 2; ++i) {
197 exit_loop = true; 305 // TODO: Can you restrict to one compare via dest masking?
198 } else { 306
199 // Jump back to call stack position, invalidate call stack entry, move up call stack pointer 307 auto compare_op = instr.common.compare_op;
200 state.program_counter = &shader_memory[*state.call_stack_pointer]; 308 auto op = (i == 0) ? compare_op.x.Value() : compare_op.y.Value();
201 *state.call_stack_pointer-- = VertexShaderState::INVALID_ADDRESS; 309
310 switch (op) {
311 case compare_op.Equal:
312 state.conditional_code[i] = (src1[i] == src2[i]);
313 break;
314
315 case compare_op.NotEqual:
316 state.conditional_code[i] = (src1[i] != src2[i]);
317 break;
318
319 case compare_op.LessThan:
320 state.conditional_code[i] = (src1[i] < src2[i]);
321 break;
322
323 case compare_op.LessEqual:
324 state.conditional_code[i] = (src1[i] <= src2[i]);
325 break;
326
327 case compare_op.GreaterThan:
328 state.conditional_code[i] = (src1[i] > src2[i]);
329 break;
330
331 case compare_op.GreaterEqual:
332 state.conditional_code[i] = (src1[i] >= src2[i]);
333 break;
334
335 default:
336 LOG_ERROR(HW_GPU, "Unknown compare mode %x", static_cast<int>(op));
337 break;
338 }
202 } 339 }
340 break;
203 341
342 default:
343 LOG_ERROR(HW_GPU, "Unhandled arithmetic instruction: 0x%02x (%s): 0x%08x",
344 (int)instr.opcode.Value(), instr.opcode.GetInfo().name, instr.hex);
345 _dbg_assert_(HW_GPU, 0);
346 break;
347 }
348
349 break;
350 }
351 default:
352 // Handle each instruction on its own
353 switch (instr.opcode) {
354 case Instruction::OpCode::END:
355 exit_loop = true;
204 break; 356 break;
205 357
206 case Instruction::OpCode::CALL: 358 case Instruction::OpCode::CALL:
207 increment_pc = false; 359 call(state,
360 instr.flow_control.dest_offset,
361 instr.flow_control.num_instructions,
362 binary_offset + 1);
363 break;
208 364
209 _dbg_assert_(HW_GPU, state.call_stack_pointer - state.call_stack < sizeof(state.call_stack)); 365 case Instruction::OpCode::NOP:
366 break;
367
368 case Instruction::OpCode::IFU:
369 if (shader_uniforms.b[instr.flow_control.bool_uniform_id]) {
370 call(state,
371 binary_offset + 1,
372 instr.flow_control.dest_offset - binary_offset - 1,
373 instr.flow_control.dest_offset + instr.flow_control.num_instructions);
374 } else {
375 call(state,
376 instr.flow_control.dest_offset,
377 instr.flow_control.num_instructions,
378 instr.flow_control.dest_offset + instr.flow_control.num_instructions);
379 }
210 380
211 *++state.call_stack_pointer = state.program_counter - shader_memory;
212 // TODO: Does this offset refer to the beginning of shader memory?
213 state.program_counter = &shader_memory[instr.flow_control.offset_words];
214 break; 381 break;
215 382
216 case Instruction::OpCode::FLS: 383 case Instruction::OpCode::IFC:
217 // TODO: Do whatever needs to be done here? 384 {
385 // TODO: Do we need to consider swizzlers here?
386
387 auto flow_control = instr.flow_control;
388 bool results[3] = { (bool)flow_control.refx == state.conditional_code[0],
389 (bool)flow_control.refy == state.conditional_code[1] };
390
391 switch (flow_control.op) {
392 case flow_control.Or:
393 results[2] = results[0] || results[1];
394 break;
395
396 case flow_control.And:
397 results[2] = results[0] && results[1];
398 break;
399
400 case flow_control.JustX:
401 results[2] = results[0];
402 break;
403
404 case flow_control.JustY:
405 results[2] = results[1];
406 break;
407 }
408
409 if (results[2]) {
410 call(state,
411 binary_offset + 1,
412 instr.flow_control.dest_offset - binary_offset - 1,
413 instr.flow_control.dest_offset + instr.flow_control.num_instructions);
414 } else {
415 call(state,
416 instr.flow_control.dest_offset,
417 instr.flow_control.num_instructions,
418 instr.flow_control.dest_offset + instr.flow_control.num_instructions);
419 }
420
218 break; 421 break;
422 }
219 423
220 default: 424 default:
221 LOG_ERROR(HW_GPU, "Unhandled instruction: 0x%02x (%s): 0x%08x", 425 LOG_ERROR(HW_GPU, "Unhandled instruction: 0x%02x (%s): 0x%08x",
222 (int)instr.opcode.Value(), instr.GetOpCodeName().c_str(), instr.hex); 426 (int)instr.opcode.Value(), instr.opcode.GetInfo().name, instr.hex);
223 break; 427 break;
428 }
429
430 break;
224 } 431 }
225 432
226 if (increment_pc) 433 ++state.program_counter;
227 ++state.program_counter;
228 434
229 if (exit_loop) 435 if (exit_loop)
230 break; 436 break;
@@ -263,6 +469,10 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes)
263 469
264 // Setup output register table 470 // Setup output register table
265 OutputVertex ret; 471 OutputVertex ret;
472 // Zero output so that attributes which aren't output won't have denormals in them, which will
473 // slow us down later.
474 memset(&ret, 0, sizeof(ret));
475
266 for (int i = 0; i < 7; ++i) { 476 for (int i = 0; i < 7; ++i) {
267 const auto& output_register_map = registers.vs_output_attributes[i]; 477 const auto& output_register_map = registers.vs_output_attributes[i];
268 478
@@ -275,13 +485,11 @@ OutputVertex RunShader(const InputVertex& input, int num_attributes)
275 state.output_register_table[4*i+comp] = ((float24*)&ret) + semantics[comp]; 485 state.output_register_table[4*i+comp] = ((float24*)&ret) + semantics[comp];
276 } 486 }
277 487
278 state.status_registers[0] = false; 488 state.conditional_code[0] = false;
279 state.status_registers[1] = false; 489 state.conditional_code[1] = false;
280 boost::fill(state.call_stack, VertexShaderState::INVALID_ADDRESS);
281 state.call_stack_pointer = &state.call_stack[0];
282 490
283 ProcessShaderCode(state); 491 ProcessShaderCode(state);
284 DebugUtils::DumpShader(shader_memory, state.debug.max_offset, swizzle_data, 492 DebugUtils::DumpShader(shader_memory.data(), state.debug.max_offset, swizzle_data.data(),
285 state.debug.max_opdesc_id, registers.vs_main_offset, 493 state.debug.max_opdesc_id, registers.vs_main_offset,
286 registers.vs_output_attributes); 494 registers.vs_output_attributes);
287 495
diff --git a/src/video_core/vertex_shader.h b/src/video_core/vertex_shader.h
index bfb6fb6e3..af3fb2a2f 100644
--- a/src/video_core/vertex_shader.h
+++ b/src/video_core/vertex_shader.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
@@ -27,15 +27,18 @@ struct OutputVertex {
27 Math::Vec4<float24> dummy; // quaternions (not implemented, yet) 27 Math::Vec4<float24> dummy; // quaternions (not implemented, yet)
28 Math::Vec4<float24> color; 28 Math::Vec4<float24> color;
29 Math::Vec2<float24> tc0; 29 Math::Vec2<float24> tc0;
30 Math::Vec2<float24> tc1;
31 float24 pad[6];
32 Math::Vec2<float24> tc2;
30 33
31 // Padding for optimal alignment 34 // Padding for optimal alignment
32 float24 pad[14]; 35 float24 pad2[4];
33 36
34 // Attributes used to store intermediate results 37 // Attributes used to store intermediate results
35 38
36 // position after perspective divide 39 // position after perspective divide
37 Math::Vec3<float24> screenpos; 40 Math::Vec3<float24> screenpos;
38 float24 pad2; 41 float24 pad3;
39 42
40 // Linear interpolation 43 // Linear interpolation
41 // factor: 0=this, 1=vtx 44 // factor: 0=this, 1=vtx
@@ -44,6 +47,8 @@ struct OutputVertex {
44 47
45 // TODO: Should perform perspective correct interpolation here... 48 // TODO: Should perform perspective correct interpolation here...
46 tc0 = tc0 * factor + vtx.tc0 * (float24::FromFloat32(1) - factor); 49 tc0 = tc0 * factor + vtx.tc0 * (float24::FromFloat32(1) - factor);
50 tc1 = tc1 * factor + vtx.tc1 * (float24::FromFloat32(1) - factor);
51 tc2 = tc2 * factor + vtx.tc2 * (float24::FromFloat32(1) - factor);
47 52
48 screenpos = screenpos * factor + vtx.screenpos * (float24::FromFloat32(1) - factor); 53 screenpos = screenpos * factor + vtx.screenpos * (float24::FromFloat32(1) - factor);
49 54
@@ -61,222 +66,16 @@ struct OutputVertex {
61static_assert(std::is_pod<OutputVertex>::value, "Structure is not POD"); 66static_assert(std::is_pod<OutputVertex>::value, "Structure is not POD");
62static_assert(sizeof(OutputVertex) == 32 * sizeof(float), "OutputVertex has invalid size"); 67static_assert(sizeof(OutputVertex) == 32 * sizeof(float), "OutputVertex has invalid size");
63 68
64union Instruction {
65 enum class OpCode : u32 {
66 ADD = 0x0,
67 DP3 = 0x1,
68 DP4 = 0x2,
69
70 MUL = 0x8,
71
72 MAX = 0xC,
73 MIN = 0xD,
74 RCP = 0xE,
75 RSQ = 0xF,
76
77 MOV = 0x13,
78
79 RET = 0x21,
80 FLS = 0x22, // Flush
81 CALL = 0x24,
82 };
83
84 std::string GetOpCodeName() const {
85 std::map<OpCode, std::string> map = {
86 { OpCode::ADD, "ADD" },
87 { OpCode::DP3, "DP3" },
88 { OpCode::DP4, "DP4" },
89 { OpCode::MUL, "MUL" },
90 { OpCode::MAX, "MAX" },
91 { OpCode::MIN, "MIN" },
92 { OpCode::RCP, "RCP" },
93 { OpCode::RSQ, "RSQ" },
94 { OpCode::MOV, "MOV" },
95 { OpCode::RET, "RET" },
96 { OpCode::FLS, "FLS" },
97 };
98 auto it = map.find(opcode);
99 if (it == map.end())
100 return "UNK";
101 else
102 return it->second;
103 }
104
105 u32 hex;
106
107 BitField<0x1a, 0x6, OpCode> opcode;
108
109 // General notes:
110 //
111 // When two input registers are used, one of them uses a 5-bit index while the other
112 // one uses a 7-bit index. This is because at most one floating point uniform may be used
113 // as an input.
114
115
116 // Format used e.g. by arithmetic instructions and comparisons
117 // "src1" and "src2" specify register indices (i.e. indices referring to groups of 4 floats),
118 // while "dest" addresses individual floats.
119 union {
120 BitField<0x00, 0x5, u32> operand_desc_id;
121
122 template<class BitFieldType>
123 struct SourceRegister : BitFieldType {
124 enum RegisterType {
125 Input,
126 Temporary,
127 FloatUniform
128 };
129
130 RegisterType GetRegisterType() const {
131 if (BitFieldType::Value() < 0x10)
132 return Input;
133 else if (BitFieldType::Value() < 0x20)
134 return Temporary;
135 else
136 return FloatUniform;
137 }
138
139 int GetIndex() const {
140 if (GetRegisterType() == Input)
141 return BitFieldType::Value();
142 else if (GetRegisterType() == Temporary)
143 return BitFieldType::Value() - 0x10;
144 else // if (GetRegisterType() == FloatUniform)
145 return BitFieldType::Value() - 0x20;
146 }
147
148 std::string GetRegisterName() const {
149 std::map<RegisterType, std::string> type = {
150 { Input, "i" },
151 { Temporary, "t" },
152 { FloatUniform, "f" },
153 };
154 return type[GetRegisterType()] + std::to_string(GetIndex());
155 }
156 };
157
158 SourceRegister<BitField<0x07, 0x5, u32>> src2;
159 SourceRegister<BitField<0x0c, 0x7, u32>> src1;
160
161 struct : BitField<0x15, 0x5, u32>
162 {
163 enum RegisterType {
164 Output,
165 Temporary,
166 Unknown
167 };
168 RegisterType GetRegisterType() const {
169 if (Value() < 0x8)
170 return Output;
171 else if (Value() < 0x10)
172 return Unknown;
173 else
174 return Temporary;
175 }
176 int GetIndex() const {
177 if (GetRegisterType() == Output)
178 return Value();
179 else if (GetRegisterType() == Temporary)
180 return Value() - 0x10;
181 else
182 return Value();
183 }
184 std::string GetRegisterName() const {
185 std::map<RegisterType, std::string> type = {
186 { Output, "o" },
187 { Temporary, "t" },
188 { Unknown, "u" }
189 };
190 return type[GetRegisterType()] + std::to_string(GetIndex());
191 }
192 } dest;
193 } common;
194
195 // Format used for flow control instructions ("if")
196 union {
197 BitField<0x00, 0x8, u32> num_instructions;
198 BitField<0x0a, 0xc, u32> offset_words;
199 } flow_control;
200};
201static_assert(std::is_standard_layout<Instruction>::value, "Structure is not using standard layout!");
202
203union SwizzlePattern {
204 u32 hex;
205
206 enum class Selector : u32 {
207 x = 0,
208 y = 1,
209 z = 2,
210 w = 3
211 };
212
213 Selector GetSelectorSrc1(int comp) const {
214 Selector selectors[] = {
215 src1_selector_0, src1_selector_1, src1_selector_2, src1_selector_3
216 };
217 return selectors[comp];
218 }
219
220 Selector GetSelectorSrc2(int comp) const {
221 Selector selectors[] = {
222 src2_selector_0, src2_selector_1, src2_selector_2, src2_selector_3
223 };
224 return selectors[comp];
225 }
226
227 bool DestComponentEnabled(int i) const {
228 return (dest_mask & (0x8 >> i)) != 0;
229 }
230
231 std::string SelectorToString(bool src2) const {
232 std::map<Selector, std::string> map = {
233 { Selector::x, "x" },
234 { Selector::y, "y" },
235 { Selector::z, "z" },
236 { Selector::w, "w" }
237 };
238 std::string ret;
239 for (int i = 0; i < 4; ++i) {
240 ret += map.at(src2 ? GetSelectorSrc2(i) : GetSelectorSrc1(i));
241 }
242 return ret;
243 }
244
245 std::string DestMaskToString() const {
246 std::string ret;
247 for (int i = 0; i < 4; ++i) {
248 if (!DestComponentEnabled(i))
249 ret += "_";
250 else
251 ret += "xyzw"[i];
252 }
253 return ret;
254 }
255
256 // Components of "dest" that should be written to: LSB=dest.w, MSB=dest.x
257 BitField< 0, 4, u32> dest_mask;
258
259 BitField< 4, 1, u32> negate; // negates src1
260
261 BitField< 5, 2, Selector> src1_selector_3;
262 BitField< 7, 2, Selector> src1_selector_2;
263 BitField< 9, 2, Selector> src1_selector_1;
264 BitField<11, 2, Selector> src1_selector_0;
265
266 BitField<14, 2, Selector> src2_selector_3;
267 BitField<16, 2, Selector> src2_selector_2;
268 BitField<18, 2, Selector> src2_selector_1;
269 BitField<20, 2, Selector> src2_selector_0;
270
271 BitField<31, 1, u32> flag; // not sure what this means, maybe it's the sign?
272};
273
274void SubmitShaderMemoryChange(u32 addr, u32 value); 69void SubmitShaderMemoryChange(u32 addr, u32 value);
275void SubmitSwizzleDataChange(u32 addr, u32 value); 70void SubmitSwizzleDataChange(u32 addr, u32 value);
276 71
277OutputVertex RunShader(const InputVertex& input, int num_attributes); 72OutputVertex RunShader(const InputVertex& input, int num_attributes);
278 73
279Math::Vec4<float24>& GetFloatUniform(u32 index); 74Math::Vec4<float24>& GetFloatUniform(u32 index);
75bool& GetBoolUniform(u32 index);
76
77const std::array<u32, 1024>& GetShaderBinary();
78const std::array<u32, 1024>& GetSwizzlePatterns();
280 79
281} // namespace 80} // namespace
282 81
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index 6791e4007..c9707e5f1 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/common.h" 5#include "common/common.h"
diff --git a/src/video_core/video_core.h b/src/video_core/video_core.h
index 609aac513..b782f17bd 100644
--- a/src/video_core/video_core.h
+++ b/src/video_core/video_core.h
@@ -1,5 +1,5 @@
1// Copyright 2014 Citra Emulator Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once